Skip to content

[SYCL] Allow __glibcxx_assert_fail in SemaSYCL #18856

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 2 commits into from
Jun 11, 2025
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
27 changes: 24 additions & 3 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ static constexpr llvm::StringLiteral InitSpecConstantsBuffer =
static constexpr llvm::StringLiteral FinalizeMethodName = "__finalize";
static constexpr llvm::StringLiteral LibstdcxxFailedAssertion =
"__failed_assertion";
static constexpr llvm::StringLiteral GlibcxxAssertFail =
"__glibcxx_assert_fail";
constexpr unsigned MaxKernelArgsSize = 2048;

bool SemaSYCL::isSyclType(QualType Ty, SYCLTypeAttr::SYCLType TypeName) {
Expand Down Expand Up @@ -599,14 +601,33 @@ static bool isSYCLUndefinedAllowed(const FunctionDecl *Callee,
if (!Callee->getIdentifier())
return false;

bool IsAllowed = 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());
IsAllowed = (Callee->getName() == LibstdcxxFailedAssertion) &&
Callee->getNumParams() == 0 &&
Callee->getReturnType()->isVoidType() &&
SrcMgr.isInSystemHeader(Callee->getLocation());

if (IsAllowed)
return true;

// GCC-15 introduced "std::__glibcxx_assert_fail" declared c++config.h and
// extensively used in STL to do runtime check in debug mode. The behavior
// is similar to "assert", we have supported it in libdevice in the same way
// as "assert". However, Sema check will report "undefined function without
// SYCL_EXTERNAL attribute" error in some cases. We have to allow it just as
// what we did to "__failed_assertion". The prototype is following:
// void __glibcxx_assert_fail(const char *, int, const char *, const char*);
IsAllowed = (Callee->getName() == GlibcxxAssertFail) &&
Callee->getNumParams() == 4 &&
Comment on lines +615 to +626
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (IsAllowed)
return true;
// GCC-15 introduced "std::__glibcxx_assert_fail" declared c++config.h and
// extensively used in STL to do runtime check in debug mode. The behavior
// is similar to "assert", we have supported it in libdevice in the same way
// as "assert". However, Sema check will report "undefined function without
// SYCL_EXTERNAL attribute" error in some cases. We have to allow it just as
// what we did to "__failed_assertion". The prototype is following:
// void __glibcxx_assert_fail(const char *, int, const char *, const char*);
IsAllowed = (Callee->getName() == GlibcxxAssertFail) &&
Callee->getNumParams() == 4 &&
// GCC-15 introduced "std::__glibcxx_assert_fail" declared c++config.h and
// extensively used in STL to do runtime check in debug mode. The behavior
// is similar to "assert", we have supported it in libdevice in the same way
// as "assert". However, Sema check will report "undefined function without
// SYCL_EXTERNAL attribute" error in some cases. We have to allow it just as
// what we did to "__failed_assertion". The prototype is following:
// void __glibcxx_assert_fail(const char *, int, const char *, const char*);
IsAllowed = IsAllowed || (Callee->getName() == GlibcxxAssertFail) &&
Callee->getNumParams() == 4 &&

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit.

Callee->getReturnType()->isVoidType() &&
SrcMgr.isInSystemHeader(Callee->getLocation());

return IsAllowed;
}

// Helper function to report conflicting function attributes.
Expand Down
3 changes: 3 additions & 0 deletions clang/test/SemaSYCL/Inputs/dummy_failed_assert
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
void __failed_assertion();
namespace std {
void __glibcxx_assert_fail(const char*, int, const char*, const char*) noexcept;
}
31 changes: 31 additions & 0 deletions clang/test/SemaSYCL/__glibcxx_assert_fail.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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 "__glibcxx_assert_fail" 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
namespace std {
void __glibcxx_assert_fail(const char*, int, const char*, const char*) noexcept;
// expected-note@-1 {{'__glibcxx_assert_fail' declared here}}
}
#else
#include <dummy_failed_assert>
#endif

#ifdef USR
SYCL_EXTERNAL
void call_glibcxx_assert_fail() {
// expected-note@-1 {{called by 'call_glibcxx_assert_fail'}}
std::__glibcxx_assert_fail("file1", 10, "func1", "dummy test");
// expected-error@-1 {{SYCL kernel cannot call an undefined function without SYCL_EXTERNAL attribute}}
}
#else
// expected-no-diagnostics
SYCL_EXTERNAL
void call_glibcxx_assert_fail() {
std::__glibcxx_assert_fail("file1", 10, "func1", "dummy test");
}
#endif