Skip to content

Commit eb373c4

Browse files
author
Erich Keane
authored
[SYCL] Implement thread-local storage restriction (#1281)
The SYCL spec was recently clarified to prohibit thread local storage, so this commit ensures an error is always emitted in these cases. Additionally, the DeclRefExpr to a VarDecl were switched to delayed diagnostics. Signed-off-by: Erich Keane <[email protected]>
1 parent ea21fdc commit eb373c4

File tree

5 files changed

+67
-14
lines changed

5 files changed

+67
-14
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7060,10 +7060,13 @@ NamedDecl *Sema::ActOnVariableDeclarator(
70607060

70617061
// Static variables declared inside SYCL device code must be const or
70627062
// constexpr
7063-
if (getLangOpts().SYCLIsDevice && SCSpec == DeclSpec::SCS_static &&
7064-
!R.isConstant(Context))
7065-
SYCLDiagIfDeviceCode(D.getIdentifierLoc(), diag::err_sycl_restrict)
7066-
<< Sema::KernelNonConstStaticDataVariable;
7063+
if (getLangOpts().SYCLIsDevice) {
7064+
if (SCSpec == DeclSpec::SCS_static && !R.isConstant(Context))
7065+
SYCLDiagIfDeviceCode(D.getIdentifierLoc(), diag::err_sycl_restrict)
7066+
<< Sema::KernelNonConstStaticDataVariable;
7067+
else if (NewVD->getTSCSpec() == DeclSpec::TSCS_thread_local)
7068+
SYCLDiagIfDeviceCode(D.getIdentifierLoc(), diag::err_thread_unsupported);
7069+
}
70677070

70687071
switch (D.getDeclSpec().getConstexprSpecifier()) {
70697072
case CSK_unspecified:

clang/lib/Sema/SemaExpr.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,16 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
212212
ObjCInterfaceDecl *ClassReceiver) {
213213
if (getLangOpts().SYCLIsDevice) {
214214
if (auto VD = dyn_cast<VarDecl>(D)) {
215-
if (VD->getStorageClass() == SC_Static &&
216-
!VD->getType().isConstant(Context))
215+
bool IsConst = VD->getType().isConstant(Context);
216+
if (VD->getTLSKind() != VarDecl::TLS_None)
217+
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_thread_unsupported);
218+
219+
if (!IsConst && VD->getStorageClass() == SC_Static)
217220
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
218221
<< Sema::KernelNonConstStaticDataVariable;
222+
else if (!IsConst && VD->hasGlobalStorage() && !isa<ParmVarDecl>(VD))
223+
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
224+
<< Sema::KernelGlobalVariable;
219225
}
220226
}
221227

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,6 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
322322

323323
CheckSYCLType(E->getType(), E->getSourceRange());
324324
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
325-
bool IsConst = VD->getType().getNonReferenceType().isConstQualified();
326-
if (!IsConst && VD->hasGlobalStorage() && !VD->isStaticLocal() &&
327-
!VD->isStaticDataMember() && !isa<ParmVarDecl>(VD)) {
328-
if (VD->getTLSKind() != VarDecl::TLS_None)
329-
SemaRef.Diag(E->getLocation(), diag::err_thread_unsupported);
330-
SemaRef.Diag(E->getLocation(), diag::err_sycl_restrict)
331-
<< Sema::KernelGlobalVariable;
332-
}
333325
if (!VD->isLocalVarDeclOrParm() && VD->hasGlobalStorage()) {
334326
VD->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context));
335327
SemaRef.addSyclDeviceDecl(VD);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -verify -fsyntax-only %s
2+
3+
thread_local const int prohobit_ns_scope = 0;
4+
thread_local int prohobit_ns_scope2 = 0;
5+
thread_local const int allow_ns_scope = 0;
6+
7+
struct S {
8+
static const thread_local int prohibit_static_member;
9+
static thread_local int prohibit_static_member2;
10+
};
11+
12+
struct T {
13+
static const thread_local int allow_static_member;
14+
};
15+
16+
void foo() {
17+
// expected-error@+1{{thread-local storage is not supported for the current target}}
18+
thread_local const int prohibit_local = 0;
19+
// expected-error@+1{{thread-local storage is not supported for the current target}}
20+
thread_local int prohibit_local2;
21+
}
22+
23+
void bar() { thread_local int allow_local; }
24+
25+
void usage() {
26+
// expected-note@+1 {{called by}}
27+
foo();
28+
// expected-error@+1 {{thread-local storage is not supported for the current target}}
29+
(void)prohobit_ns_scope;
30+
// expected-error@+2 {{SYCL kernel cannot use a non-const global variable}}
31+
// expected-error@+1 {{thread-local storage is not supported for the current target}}
32+
(void)prohobit_ns_scope2;
33+
// expected-error@+1 {{thread-local storage is not supported for the current target}}
34+
(void)S::prohibit_static_member;
35+
// expected-error@+2 {{SYCL kernel cannot use a non-const static data variable}}
36+
// expected-error@+1 {{thread-local storage is not supported for the current target}}
37+
(void)S::prohibit_static_member2;
38+
}
39+
40+
template <typename name, typename Func>
41+
__attribute__((sycl_kernel))
42+
// expected-note@+2 2{{called by}}
43+
void
44+
kernel_single_task(Func kernelFunc) { kernelFunc(); }
45+
46+
int main() {
47+
// expected-note@+1 2{{called by}}
48+
kernel_single_task<class fake_kernel>([]() { usage(); });
49+
return 0;
50+
}

clang/test/SemaSYCL/tls_error.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ void usage() {
1515

1616
template <typename name, typename Func>
1717
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
18+
//expected-note@+1{{called by}}
1819
kernelFunc();
1920
}
2021

2122
int main() {
23+
//expected-note@+1{{called by}}
2224
kernel_single_task<class fake_kernel>([]() { usage(); });
2325
return 0;
2426
}

0 commit comments

Comments
 (0)