Skip to content

[SYCL] Allow __failed_assertion to support libstdc++-11 #3774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ static constexpr llvm::StringLiteral InitESIMDMethodName = "__init_esimd";
static constexpr llvm::StringLiteral InitSpecConstantsBuffer =
"__init_specialization_constants_buffer";
static constexpr llvm::StringLiteral FinalizeMethodName = "__finalize";
static constexpr llvm::StringLiteral LibstdcxxFailedAssertion =
"__failed_assertion";
constexpr unsigned MaxKernelArgsSize = 2048;

namespace {
Expand Down Expand Up @@ -320,6 +322,21 @@ static bool isSYCLKernelBodyFunction(FunctionDecl *FD) {
return FD->getOverloadedOperator() == OO_Call;
}

static bool isSYCLUndefinedAllowed(const FunctionDecl *Callee,
const SourceManager &SrcMgr) {
if (!Callee)
return false;

// libstdc++-11 introduced an undefined function "void __failed_assertion()"
// which may lead to SemaSYCL check failure. However, this undefined function
// is used to trigger some compilation error when the check fails at compile
// time and will be ignored when the check succeeds. We allow calls to this
// function to support some important std functions in SYCL device.
return (Callee->getName() == LibstdcxxFailedAssertion) &&
Callee->getNumParams() == 0 && Callee->getReturnType()->isVoidType() &&
SrcMgr.isInSystemHeader(Callee->getLocation());
}

// Helper function to report conflicting function attributes.
// F - the function, A1 - function attribute, A2 - the attribute it conflicts
// with.
Expand Down Expand Up @@ -4122,7 +4139,10 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller,
return;

// Diagnose if this is an undefined function and it is not a builtin.
if (!Callee->isDefined() && !Callee->getBuiltinID()) {
// Currently, there is an exception of "__failed_assertion" in libstdc++-11,
// this undefined function is used to trigger a compiling error.
if (!Callee->isDefined() && !Callee->getBuiltinID() &&
!isSYCLUndefinedAllowed(Callee, getSourceManager())) {
Diag(Loc, diag::err_sycl_restrict) << Sema::KernelCallUndefinedFunction;
Diag(Callee->getLocation(), diag::note_previous_decl) << Callee;
Diag(Caller->getLocation(), diag::note_called_by) << Caller;
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaSYCL/Inputs/dummy_failed_assert
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
void __failed_assertion();
29 changes: 29 additions & 0 deletions clang/test/SemaSYCL/__failed_assertion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -sycl-std=2020 -verify -DUSR -fsyntax-only %s
// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -sycl-std=2020 -verify -fsyntax-only %s
// UNSUPPORTED: system-windows
// This test checks that an undefined "__failed_assertion" without SYCL_EXTERNAL will lead to SYCL sema check
// failure if it is not declared in a system header otherwise no SYCL sema check failure will be triggered.

#include "sycl.hpp"
#ifdef USR
void __failed_assertion();
// expected-note@-1 {{'__failed_assertion' declared here}}
#else
#include <dummy_failed_assert>
#endif

#ifdef USR
SYCL_EXTERNAL
void call_failed_assertion() {
// expected-note@-1 {{called by 'call_failed_assertion'}}
__failed_assertion();
// expected-error@-1 {{SYCL kernel cannot call an undefined function without SYCL_EXTERNAL attribute}}
}
#else
// expected-no-diagnostics
SYCL_EXTERNAL
void call_failed_assertion() {
__failed_assertion();
}
#endif