Skip to content

Commit f537293

Browse files
Erich Keanebader
authored andcommitted
[SYCL] Move variadic call diagnostics to delayed diagnostics, fixes. (#998)
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. Remove FIXME comment that this invalidates. Signed-off-by: Erich Keane <[email protected]>
1 parent 3a0b62e commit f537293

File tree

10 files changed

+78
-29
lines changed

10 files changed

+78
-29
lines changed

clang/include/clang/Sema/Sema.h

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

12052+
// Used to suppress diagnostics during kernel construction, since these were
12053+
// already emitted earlier. Diagnosing during Kernel emissions also skips the
12054+
// useful notes that shows where the kernel was called.
12055+
bool ConstructingOpenCLKernel = false;
12056+
1205212057
public:
1205312058
void addSyclDeviceDecl(Decl *d) { SyclDeviceDecls.push_back(d); }
1205412059
SmallVectorImpl<Decl *> &syclDeviceDecls() { return SyclDeviceDecls; }
@@ -12075,6 +12080,7 @@ class Sema final {
1207512080
KernelCallVariadicFunction
1207612081
};
1207712082
DeviceDiagBuilder SYCLDiagIfDeviceCode(SourceLocation Loc, unsigned DiagID);
12083+
bool isKnownGoodSYCLDecl(const Decl *D);
1207812084
void ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, MangleContext &MC);
1207912085
void MarkDevice(void);
1208012086
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
@@ -5404,6 +5404,12 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
54045404

54055405
// Otherwise do argument promotion, (C99 6.5.2.2p7).
54065406
} else {
5407+
// Diagnose variadic calls in SYCL.
5408+
if (getLangOpts().SYCLIsDevice && !isUnevaluatedContext() &&
5409+
!isKnownGoodSYCLDecl(FDecl))
5410+
SYCLDiagIfDeviceCode(CallLoc, diag::err_sycl_restrict)
5411+
<< Sema::KernelCallVariadicFunction;
5412+
54075413
for (Expr *A : Args.slice(ArgIx)) {
54085414
ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl);
54095415
Invalid |= Arg.isInvalid();

clang/lib/Sema/SemaOverload.cpp

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

1423114231
// If this is a variadic call, handle args passed through "...".
1423214232
if (Proto->isVariadic()) {
14233+
// Diagnose variadic calls in SYCL.
14234+
if (getLangOpts().SYCLIsDevice && !isUnevaluatedContext())
14235+
SYCLDiagIfDeviceCode(LParenLoc, diag::err_sycl_restrict)
14236+
<< Sema::KernelCallVariadicFunction;
14237+
1423314238
// Promote the arguments (C99 6.5.2.2p7).
1423414239
for (unsigned i = NumParams, e = Args.size(); i < e; i++) {
1423514240
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>(getCurLexicalContext());
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/lib/Sema/SemaType.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4685,7 +4685,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
46854685
// OpenCL doesn't support variadic functions and blocks
46864686
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
46874687
// We also allow here any toolchain reserved identifiers.
4688-
// FIXME: Use deferred diagnostics engine to skip host side issues.
46894688
if (FTI.isVariadic &&
46904689
!LangOpts.SYCLIsDevice &&
46914690
!(D.getIdentifier() &&

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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)