Skip to content

[SYCL] Move function pointer diagnostics to BuildResolvedCallExpr #16987

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 10 commits into from
Mar 19, 2025
12 changes: 12 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7124,6 +7124,18 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
return ExprError();
}

// Diagnose function pointers in SYCL.
if (!FDecl && !getLangOpts().SYCLAllowFuncPtr && getLangOpts().SYCLIsDevice &&
!isUnevaluatedContext()) {
bool MaybeConstantExpr = false;
Expr *NonDirectCallee = TheCall->getCallee();
if (!NonDirectCallee->isValueDependent())
MaybeConstantExpr = NonDirectCallee->isCXX11ConstantExpr(getASTContext());
if (!MaybeConstantExpr)
SYCL().DiagIfDeviceCode(TheCall->getExprLoc(), diag::err_sycl_restrict)
<< SemaSYCL::KernelCallFunctionPointer;
}

return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), FDecl);
}

Expand Down
11 changes: 0 additions & 11 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,17 +687,6 @@ class DiagDeviceFunction : public RecursiveASTVisitor<DiagDeviceFunction> {
SemaSYCLRef.Diag(e->getExprLoc(), diag::err_builtin_target_unsupported)
<< Name << "SYCL device";
}
} else if (!SemaSYCLRef.getLangOpts().SYCLAllowFuncPtr &&
!e->isTypeDependent() &&
!isa<CXXPseudoDestructorExpr>(e->getCallee())) {
bool MaybeConstantExpr = false;
Expr *NonDirectCallee = e->getCallee();
if (!NonDirectCallee->isValueDependent())
MaybeConstantExpr =
NonDirectCallee->isCXX11ConstantExpr(SemaSYCLRef.getASTContext());
if (!MaybeConstantExpr)
SemaSYCLRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
<< SemaSYCL::KernelCallFunctionPointer;
}
return true;
}
Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaSYCL/constexpr-function-pointer.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify -sycl-std=2020 -std=c++17 %s
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify=host -sycl-std=2020 -std=c++17 %s

// This test checks that the compiler doesn't emit an error when indirect call
// was made through a function pointer that is constant expression, and makes
// sure that the error is emitted when a function pointer is not a constant
// expression.

// host-no-diagnostics

void t() {}

constexpr auto F = t;
Expand All @@ -22,6 +25,8 @@ void bar1(const SomeFunc fptr) {

template <auto f> void fooNTTP() { f(); }

template <typename FTy> void templated(FTy f) { f(); } // #call-templated

__attribute__((sycl_device)) void bar() {
// OK
constexpr auto f = t;
Expand All @@ -48,4 +53,19 @@ __attribute__((sycl_device)) void bar() {
fff();

fooNTTP<t>();

templated(t);
// expected-error@#call-templated {{SYCL kernel cannot call through a function pointer}}
// expected-note@-2 {{called by 'bar'}}
}

void from_host() {
const auto f1 = t;
f1();
auto f2 = t;
f2();

fooNTTP<t>();

templated(t);
}
Loading