Skip to content

Commit e84c952

Browse files
authored
[SYCL] Allow calls through constant expr function pointers (#5390)
The current SYCL spec doesn't allow any indirect calls, but it may make sense to allow calls to constant expression function pointers because they are lowered to direct calls by front-end.
1 parent 426664a commit e84c952

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,9 +636,16 @@ class DiagDeviceFunction : public RecursiveASTVisitor<DiagDeviceFunction> {
636636
}
637637
} else if (!SemaRef.getLangOpts().SYCLAllowFuncPtr &&
638638
!e->isTypeDependent() &&
639-
!isa<CXXPseudoDestructorExpr>(e->getCallee()))
640-
SemaRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
641-
<< Sema::KernelCallFunctionPointer;
639+
!isa<CXXPseudoDestructorExpr>(e->getCallee())) {
640+
bool MaybeConstantExpr = false;
641+
Expr *NonDirectCallee = e->getCallee();
642+
if (!NonDirectCallee->isValueDependent())
643+
MaybeConstantExpr =
644+
NonDirectCallee->isCXX11ConstantExpr(SemaRef.getASTContext());
645+
if (!MaybeConstantExpr)
646+
SemaRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
647+
<< Sema::KernelCallFunctionPointer;
648+
}
642649
return true;
643650
}
644651

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify -sycl-std=2020 -std=c++17 %s
2+
3+
// This test checks that the compiler doesn't emit an error when indirect call
4+
// was made through a function pointer that is constant expression, and makes
5+
// sure that the error is emitted when a function pointer is not a constant
6+
// expression.
7+
8+
void t() {}
9+
10+
constexpr auto F = t;
11+
const auto F1 = t;
12+
13+
typedef void (*SomeFunc)();
14+
15+
constexpr SomeFunc foo() { return t; }
16+
17+
const SomeFunc foo1() { return t; }
18+
19+
void bar1(const SomeFunc fptr) {
20+
fptr();
21+
}
22+
23+
template <auto f> void fooNTTP() { f(); }
24+
25+
__attribute__((sycl_device)) void bar() {
26+
// OK
27+
constexpr auto f = t;
28+
f();
29+
const auto f1 = t;
30+
// expected-error@+1 {{SYCL kernel cannot call through a function pointer}}
31+
f1();
32+
auto f2 = t;
33+
// expected-error@+1 {{SYCL kernel cannot call through a function pointer}}
34+
f2();
35+
36+
// OK
37+
F();
38+
// expected-error@+1 {{SYCL kernel cannot call through a function pointer}}
39+
F1();
40+
41+
constexpr auto ff = foo();
42+
ff();
43+
const auto ff1 = foo();
44+
// expected-error@+1 {{SYCL kernel cannot call through a function pointer}}
45+
ff1();
46+
const auto fff = foo1();
47+
// expected-error@+1 {{SYCL kernel cannot call through a function pointer}}
48+
fff();
49+
50+
fooNTTP<t>();
51+
}

0 commit comments

Comments
 (0)