Skip to content

Commit 4de5690

Browse files
author
Erich Keane
committed
[SYCL] Move variadic call diagnostics to delayed diagnostics, fixes.
One of our downstreams requires using the variadic call diagnostics from SYCL, however the SemaSYCL AST walker ends up being messy. This patch initially removes the check from the AST walker and instead implements its in normal SEMA via the delayed diagnostics mechanism. However, while evaluating this, we discovered that there are quite a few issues with how the diagnostics are emitted, so this patch includes quite a few cleanups to make sure the diagnostics are emitted properly. This results in some additional notes in some of the test. Additionally, the asm checks were previously implemented in BOTH delayed diagnostics as well as the AST walker, since the bugs in each aligned to have full coverage. This patch ends up removing it from the AST walking code since the other bugs were fixed. Signed-off-by: Erich Keane <[email protected]>
1 parent dd8070e commit 4de5690

File tree

9 files changed

+79
-29
lines changed

9 files changed

+79
-29
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12015,6 +12015,11 @@ class Sema final {
1201512015
// is associated with.
1201612016
std::unique_ptr<SYCLIntegrationHeader> SyclIntHeader;
1201712017

12018+
// Used to suppress diagnostics during kernel construction, since these were
12019+
// already emitted earlier. Diagnosing during Kernel emissions also skips the
12020+
// useful notes that shows where the kernel was called.
12021+
bool ConstructingOpenCLKernel = false;
12022+
1201812023
public:
1201912024
void addSyclDeviceDecl(Decl *d) { SyclDeviceDecls.push_back(d); }
1202012025
SmallVectorImpl<Decl *> &syclDeviceDecls() { return SyclDeviceDecls; }
@@ -12041,6 +12046,7 @@ class Sema final {
1204112046
KernelCallVariadicFunction
1204212047
};
1204312048
DeviceDiagBuilder SYCLDiagIfDeviceCode(SourceLocation Loc, unsigned DiagID);
12049+
bool isKnownGoodSYCLDecl(const Decl *D);
1204412050
void ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, MangleContext &MC);
1204512051
void MarkDevice(void);
1204612052
bool CheckSYCLCall(SourceLocation Loc, FunctionDecl *Callee);

clang/lib/Sema/SemaExpr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5380,6 +5380,12 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
53805380

53815381
// Otherwise do argument promotion, (C99 6.5.2.2p7).
53825382
} else {
5383+
// Diagnose variadic calls in SYCL.
5384+
if (getLangOpts().SYCLIsDevice && !isUnevaluatedContext() &&
5385+
!isKnownGoodSYCLDecl(FDecl))
5386+
SYCLDiagIfDeviceCode(CallLoc, diag::err_sycl_restrict)
5387+
<< Sema::KernelCallVariadicFunction;
5388+
53835389
for (Expr *A : Args.slice(ArgIx)) {
53845390
ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl);
53855391
Invalid |= Arg.isInvalid();

clang/lib/Sema/SemaOverload.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14027,6 +14027,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1402714027

1402814028
// If this is a variadic call, handle args passed through "...".
1402914029
if (Proto->isVariadic()) {
14030+
// Diagnose variadic calls in SYCL.
14031+
if (getLangOpts().SYCLIsDevice && !isUnevaluatedContext())
14032+
SYCLDiagIfDeviceCode(LParenLoc, diag::err_sycl_restrict)
14033+
<< Sema::KernelCallVariadicFunction;
14034+
1403014035
// Promote the arguments (C99 6.5.2.2p7).
1403114036
for (unsigned i = NumParams, e = Args.size(); i < e; i++) {
1403214037
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ static bool IsSyclMathFunc(unsigned BuiltinID) {
184184
return true;
185185
}
186186

187-
static bool isKnownGoodDecl(const Decl *D) {
187+
bool Sema::isKnownGoodSYCLDecl(const Decl *D) {
188188
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
189189
const IdentifierInfo *II = FD->getIdentifier();
190190
const DeclContext *DC = FD->getDeclContext();
@@ -326,7 +326,7 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
326326

327327
bool VisitDeclRefExpr(DeclRefExpr *E) {
328328
Decl* D = E->getDecl();
329-
if (isKnownGoodDecl(D))
329+
if (SemaRef.isKnownGoodSYCLDecl(D))
330330
return true;
331331

332332
CheckSYCLType(E->getType(), E->getSourceRange());
@@ -372,18 +372,6 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
372372
return true;
373373
}
374374

375-
bool VisitGCCAsmStmt(GCCAsmStmt *S) {
376-
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict)
377-
<< Sema::KernelUseAssembly;
378-
return true;
379-
}
380-
381-
bool VisitMSAsmStmt(MSAsmStmt *S) {
382-
SemaRef.Diag(S->getBeginLoc(), diag::err_sycl_restrict)
383-
<< Sema::KernelUseAssembly;
384-
return true;
385-
}
386-
387375
// The call graph for this translation unit.
388376
CallGraph SYCLCG;
389377
// The set of functions called by a kernel function.
@@ -549,9 +537,6 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
549537
}
550538
}
551539
} else if (const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) {
552-
if (FPTy->isVariadic() && SemaRef.getLangOpts().SYCLIsDevice)
553-
SemaRef.SYCLDiagIfDeviceCode(Loc.getBegin(), diag::err_sycl_restrict)
554-
<< Sema::KernelCallVariadicFunction;
555540
for (const auto &ParamTy : FPTy->param_types())
556541
if (!CheckSYCLType(ParamTy, Loc, Visited))
557542
return false;
@@ -1308,8 +1293,10 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc,
13081293
// in different translation units.
13091294
OpenCLKernel->setImplicitlyInline(KernelCallerFunc->isInlined());
13101295

1296+
ConstructingOpenCLKernel = true;
13111297
CompoundStmt *OpenCLKernelBody =
13121298
CreateOpenCLKernelBody(*this, KernelCallerFunc, OpenCLKernel);
1299+
ConstructingOpenCLKernel = false;
13131300
OpenCLKernel->setBody(OpenCLKernelBody);
13141301
addSyclDeviceDecl(OpenCLKernel);
13151302
}
@@ -1404,13 +1391,13 @@ static bool isKnownEmitted(Sema &S, FunctionDecl *FD) {
14041391
if (!FD)
14051392
return true; // Seen in LIT testing
14061393

1407-
if (FD->hasAttr<SYCLDeviceAttr>() || FD->hasAttr<SYCLKernelAttr>())
1408-
return true;
1409-
14101394
// Templates are emitted when they're instantiated.
14111395
if (FD->isDependentContext())
14121396
return false;
14131397

1398+
if (FD->hasAttr<SYCLDeviceAttr>() || FD->hasAttr<SYCLKernelAttr>())
1399+
return true;
1400+
14141401
// Otherwise, the function is known-emitted if it's in our set of
14151402
// known-emitted functions.
14161403
return S.DeviceKnownEmittedFns.count(FD) > 0;
@@ -1420,18 +1407,20 @@ Sema::DeviceDiagBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
14201407
unsigned DiagID) {
14211408
assert(getLangOpts().SYCLIsDevice &&
14221409
"Should only be called during SYCL compilation");
1423-
DeviceDiagBuilder::Kind DiagKind = [this] {
1424-
if (isKnownEmitted(*this, dyn_cast<FunctionDecl>(CurContext)))
1410+
FunctionDecl *FD = dyn_cast<FunctionDecl>(CurContext);
1411+
DeviceDiagBuilder::Kind DiagKind = [this, FD] {
1412+
if (ConstructingOpenCLKernel || (FD && FD->isDependentContext()))
1413+
return DeviceDiagBuilder::K_Nop;
1414+
else if (isKnownEmitted(*this, FD))
14251415
return DeviceDiagBuilder::K_ImmediateWithCallStack;
14261416
return DeviceDiagBuilder::K_Deferred;
14271417
}();
1428-
return DeviceDiagBuilder(DiagKind, Loc, DiagID,
1429-
dyn_cast<FunctionDecl>(CurContext), *this);
1418+
return DeviceDiagBuilder(DiagKind, Loc, DiagID, FD, *this);
14301419
}
14311420

14321421
bool Sema::CheckSYCLCall(SourceLocation Loc, FunctionDecl *Callee) {
14331422
assert(Callee && "Callee may not be null.");
1434-
FunctionDecl *Caller = getCurFunctionDecl();
1423+
FunctionDecl *Caller = dyn_cast<FunctionDecl>(getCurLexicalContext());
14351424

14361425
// If the caller is known-emitted, mark the callee as known-emitted.
14371426
// Otherwise, mark the call in our call graph so we can traverse it later.

clang/test/SemaSYCL/inline-asm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ void bar() {
2121

2222
template <typename name, typename Func>
2323
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
24+
// expected-note@+1 {{called by 'kernel_single_task<fake_kernel, (lambda}}
2425
kernelFunc();
2526
}
2627

2728
int main() {
2829
foo();
30+
// expected-note@+1 {{called by 'operator()'}}
2931
kernel_single_task<class fake_kernel>([]() { bar(); });
3032
return 0;
3133
}

clang/test/SemaSYCL/sycl-cconv.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ __inline __cdecl __attribute__((sycl_device)) int foo() { return 0; }
88
__inline __cdecl int moo() { return 0; }
99

1010
void bar() {
11-
printf("hello\n"); // expected-no-error
11+
//printf("hello\n"); // expected-no-error
1212
}
1313

1414
template <typename name, typename Func>
@@ -18,10 +18,12 @@ __cdecl __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
1818
printf("cannot call from here\n");
1919
// expected-no-error@+1
2020
moo();
21+
// expected-note@+1{{called by}}
2122
kernelFunc();
2223
}
2324

2425
int main() {
26+
//expected-note@+2 {{in instantiation of}}
2527
//expected-error@+1 {{SYCL kernel cannot call a variadic function}}
2628
kernel_single_task<class fake_kernel>([]() { printf("world\n"); });
2729
bar();

clang/test/SemaSYCL/sycl-restrict.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ void eh_not_ok(void)
124124

125125
void usage(myFuncDef functionPtr) {
126126

127+
// expected-note@+1 {{called by 'usage'}}
127128
eh_not_ok();
128129

129130
#if ALLOW_FP
@@ -169,7 +170,6 @@ int use2 ( a_type ab, a_type *abp ) {
169170
return ns::glob +
170171
// expected-error@+1 {{SYCL kernel cannot use a global variable}}
171172
AnotherNS::moar_globals;
172-
// expected-note@+1 {{called by 'use2'}}
173173
eh_not_ok();
174174
Check_RTTI_Restriction:: A *a;
175175
Check_RTTI_Restriction:: isa_B(a);
@@ -180,15 +180,16 @@ int use2 ( a_type ab, a_type *abp ) {
180180

181181
template <typename name, typename Func>
182182
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
183+
// expected-note@+1 {{called by 'kernel_single_task}}
183184
kernelFunc();
184185
a_type ab;
185186
a_type *p;
186-
// expected-note@+1 {{called by 'kernel_single_task'}}
187187
use2(ab, p);
188188
}
189189

190190
int main() {
191191
a_type ab;
192+
// expected-note@+1 {{called by 'operator()'}}
192193
kernel_single_task<class fake_kernel>([]() { usage( &addInt ); });
193194
return 0;
194195
}

clang/test/SemaSYCL/sycl-varargs-cconv.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ void bar() {
3939

4040
template <typename name, typename Func>
4141
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
42-
kernelFunc();
42+
kernelFunc(); //expected-note 2+ {{called by 'kernel_single_task}}
4343
}
4444

4545
int main() {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -triple spir64-unknown-unknown -fsycl-is-device -fsyntax-only -verify %s
2+
3+
void variadic(int, ...);
4+
namespace NS {
5+
void variadic(int, ...);
6+
}
7+
8+
struct S {
9+
S(int, ...);
10+
void operator()(int, ...);
11+
};
12+
13+
void foo() {
14+
auto x = [](int, ...) {};
15+
x(5, 10); //expected-error{{SYCL kernel cannot call a variadic function}}
16+
}
17+
18+
void overloaded(int, int);
19+
void overloaded(int, ...);
20+
template <typename, typename Func>
21+
__attribute__((sycl_kernel)) void task(Func KF) {
22+
KF(); // expected-note 2 {{called by 'task}}
23+
}
24+
25+
int main() {
26+
task<class FK>([]() {
27+
variadic(5); //expected-error{{SYCL kernel cannot call a variadic function}}
28+
variadic(5, 2); //expected-error{{SYCL kernel cannot call a variadic function}}
29+
NS::variadic(5, 3); //expected-error{{SYCL kernel cannot call a variadic function}}
30+
S s(5, 4); //expected-error{{SYCL kernel cannot call a variadic function}}
31+
S s2(5); //expected-error{{SYCL kernel cannot call a variadic function}}
32+
s(5, 5); //expected-error{{SYCL kernel cannot call a variadic function}}
33+
s2(5); //expected-error{{SYCL kernel cannot call a variadic function}}
34+
foo(); //expected-note{{called by 'operator()'}}
35+
overloaded(5, 6); //expected-no-error
36+
overloaded(5, s); //expected-error{{SYCL kernel cannot call a variadic function}}
37+
overloaded(5); //expected-error{{SYCL kernel cannot call a variadic function}}
38+
});
39+
}

0 commit comments

Comments
 (0)