Skip to content

Commit 226679a

Browse files
authored
[SYCL] Error out instead of crash when templated global var used (#5195)
SYCL deferred diagnostics couldn't catch the case like: ``` template <typename T> class randomType { public: randomType() {} T val; }; template <typename T> const randomType<T> Var; SYCL_EXTERNAL void foo() { (void)Var<int>; } ``` And CodeGen was crashing due to attempt to emit invalid cast. That happened because use of `Var` should be diagnosed. The diagnostic wasn't emitted because at the places where deferred diagnostic is issued for this case, templated variable doesn't yet has initializer, or it has it but current lexical context is out of device code (in this particular case it will be a translation unit). This patch follows the logic invented by `finalizeOpenMPDelayedAnalysis` and `finalizeSYCLDelayedAnalysis` routines, i.e. emit immediate diagnostic when post-parsing of AST for deferred diagnostics happens.
1 parent ae711ab commit 226679a

File tree

7 files changed

+28
-24
lines changed

7 files changed

+28
-24
lines changed

clang/lib/Sema/Sema.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,6 +1679,15 @@ class DeferredDiagnosticsEmitter
16791679
}
16801680

16811681
void visitUsedDecl(SourceLocation Loc, Decl *D) {
1682+
if (S.LangOpts.SYCLIsDevice && ShouldEmitRootNode) {
1683+
if (auto *VD = dyn_cast<VarDecl>(D)) {
1684+
if (!S.checkAllowedSYCLInitializer(VD)) {
1685+
S.Diag(Loc, diag::err_sycl_restrict)
1686+
<< Sema::KernelConstStaticVariable;
1687+
return;
1688+
}
1689+
}
1690+
}
16821691
if (isa<VarDecl>(D))
16831692
return;
16841693
if (auto *FD = dyn_cast<FunctionDecl>(D)) {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18729,16 +18729,14 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD,
1872918729
bool Final) {
1873018730
assert(FD && "Expected non-null FunctionDecl");
1873118731

18732-
// SYCL functions can be template, so we check if they have appropriate
18733-
// attribute prior to checking if it is a template.
18734-
if (LangOpts.SYCLIsDevice &&
18735-
(FD->hasAttr<SYCLDeviceAttr>() || FD->hasAttr<SYCLKernelAttr>()))
18736-
return FunctionEmissionStatus::Emitted;
18737-
1873818732
// Templates are emitted when they're instantiated.
1873918733
if (FD->isDependentContext())
1874018734
return FunctionEmissionStatus::TemplateDiscarded;
1874118735

18736+
if (LangOpts.SYCLIsDevice &&
18737+
(FD->hasAttr<SYCLDeviceAttr>() || FD->hasAttr<SYCLKernelAttr>()))
18738+
return FunctionEmissionStatus::Emitted;
18739+
1874218740
// Check whether this function is an externally visible definition.
1874318741
auto IsEmittedForExternalSymbol = [this, FD]() {
1874418742
// We have to check the GVA linkage of the function's *definition* -- if we

clang/lib/Sema/SemaExpr.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
246246
SYCLDiagIfDeviceCode(*Locs.begin(),
247247
diag::err_esimd_global_in_sycl_context,
248248
Sema::DeviceDiagnosticReason::Sycl);
249-
// Disallow const statics and globals that are not zero-initialized
250-
// or constant-initialized.
251-
else if (IsRuntimeEvaluated && IsConst && VD->hasGlobalStorage() &&
252-
!VD->isConstexpr() && !checkAllowedSYCLInitializer(VD))
253-
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
254-
<< Sema::KernelConstStaticVariable;
255249
} else if (auto *FDecl = dyn_cast<FunctionDecl>(D)) {
256250
// SYCL device function cannot be called from an ESIMD context. However,
257251
// funcitons that start with '__spirv_' or '__sycl_' are exceptions to

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4050,11 +4050,6 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller,
40504050
const FunctionDecl *Callee,
40514051
SourceLocation Loc,
40524052
DeviceDiagnosticReason Reason) {
4053-
// Somehow an unspecialized template appears to be in callgraph or list of
4054-
// device functions. We don't want to emit diagnostic here.
4055-
if (Callee->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
4056-
return;
4057-
40584053
Callee = Callee->getMostRecentDecl();
40594054

40604055
// If the reason for the emission of this diagnostic is not SYCL-specific,

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5717,10 +5717,6 @@ void Sema::InstantiateVariableInitializer(
57175717

57185718
if (getLangOpts().CUDA)
57195719
checkAllowedCUDAInitializer(Var);
5720-
5721-
if (getLangOpts().SYCLIsDevice && !checkAllowedSYCLInitializer(Var))
5722-
SYCLDiagIfDeviceCode(Var->getLocation(), diag::err_sycl_restrict)
5723-
<< Sema::KernelConstStaticVariable;
57245720
}
57255721

57265722
/// Instantiate the definition of the given variable from its

clang/test/SemaSYCL/inline-asm.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ static __inline unsigned int
2222
asm_func_2(unsigned int __leaf, unsigned long __d[]) {
2323
unsigned int __result;
2424
#ifdef SPIR_CHECK
25-
//expected-error@+2 2{{invalid output constraint '=a' in asm}}
25+
// expected-error@+2 {{invalid output constraint '=a' in asm}}
2626
__asm__("enclu"
2727
: "=a"(__result), "=b"(__d[0]), "=c"(__d[1]), "=d"(__d[2])
2828
: "a"(__leaf), "b"(__d[0]), "c"(__d[1]), "d"(__d[2])
@@ -58,7 +58,7 @@ __attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) {
5858
#ifdef SPIR_CHECK
5959
unsigned int i = 3;
6060
unsigned long d[4];
61-
//expected-note@+1 2{{called by 'kernel_single_task}}
61+
// expected-note@+1 {{called by 'kernel_single_task}}
6262
asm_func_2(i, d);
6363
#endif // SPIR_CHECK
6464
#else

clang/test/SemaSYCL/sycl-device-const-static.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ template struct U<Base>;
2222

2323
const S s5;
2424

25+
template <typename T>
26+
class randomType {
27+
public:
28+
randomType() {}
29+
T val;
30+
};
31+
32+
template <typename T>
33+
const randomType<T> Var;
34+
2535
void usage() {
2636
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
2737
static int s1;
@@ -34,11 +44,13 @@ void usage() {
3444
(void)s5;
3545
// expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}}
3646
(void)s6;
47+
48+
// expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}}
49+
(void)Var<int>;
3750
}
3851

3952
template <typename Name, typename Func>
4053
__attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) {
41-
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
4254
static int z;
4355
// expected-note-re@+3{{called by 'kernel_single_task<fake_kernel, (lambda at {{.*}})>}}
4456
// expected-note-re@+2{{called by 'kernel_single_task<fake_kernel, (lambda at {{.*}})>}}

0 commit comments

Comments
 (0)