Skip to content

Commit d0efca5

Browse files
authored
[SYCL] Report deferred diagnostics in function templates (#5114)
Under some circumstances, deferred diagnostics were not emitted for usages within a template function. This was because the FunctionDecl associated with the diagnostic was that of the template declaration, but at the point of emitting the diagnostic, the FunctionDecl in the call chain was that of the template instantiation. Signed-off-by: Premanand M Rao <[email protected]>
1 parent 5373362 commit d0efca5

File tree

5 files changed

+58
-20
lines changed

5 files changed

+58
-20
lines changed

clang/lib/Sema/Sema.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1770,8 +1770,15 @@ class DeferredDiagnosticsEmitter
17701770
// Emit any deferred diagnostics for FD
17711771
void emitDeferredDiags(FunctionDecl *FD, bool ShowCallStack) {
17721772
auto It = S.DeviceDeferredDiags.find(FD);
1773-
if (It == S.DeviceDeferredDiags.end())
1773+
if (It == S.DeviceDeferredDiags.end()) {
1774+
// If this is a template instantiation, check if its declaration
1775+
// is on the deferred diagnostics stack.
1776+
if (FD->isTemplateInstantiation()) {
1777+
FD = FD->getTemplateInstantiationPattern();
1778+
emitDeferredDiags(FD, ShowCallStack);
1779+
}
17741780
return;
1781+
}
17751782
bool HasWarningOrError = false;
17761783
bool FirstDiag = true;
17771784
for (Sema::DeviceDeferredDiagnostic &D : It->second) {

clang/test/CodeGenSYCL/static-var-address-space.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,12 @@
11
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
22
#include "Inputs/sycl.hpp"
3-
struct C {
4-
static int c;
5-
};
6-
7-
template <typename T>
8-
struct D {
9-
static T d;
10-
};
113

124
template <typename T>
135
void test() {
146
// CHECK: @_ZZ4testIiEvvE1a = linkonce_odr addrspace(1) constant i32 0, comdat, align 4
157
static const int a = 0;
168
// CHECK: @_ZZ4testIiEvvE1b = linkonce_odr addrspace(1) constant i32 0, comdat, align 4
179
static const T b = T(0);
18-
// CHECK: @_ZN1C1cE = external addrspace(1) global i32, align 4
19-
C::c = 10;
20-
const C struct_c;
21-
// CHECK: @_ZN1DIiE1dE = external addrspace(1) global i32, align 4
22-
D<int>::d = 11;
23-
const D<int> struct_d;
2410
}
2511

2612
int main() {

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,34 @@ void usage() {
5151

5252
template <typename Name, typename Func>
5353
__attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) {
54+
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
5455
static int z;
5556
// expected-note-re@+3{{called by 'kernel_single_task<fake_kernel, (lambda at {{.*}})>}}
5657
// expected-note-re@+2{{called by 'kernel_single_task<fake_kernel, (lambda at {{.*}})>}}
5758
// expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}}
5859
kernelFunc(U<Base>::s2);
5960
}
6061

62+
struct C {
63+
static int c;
64+
};
65+
66+
template <typename T>
67+
struct D {
68+
static T d;
69+
};
70+
71+
template <typename T>
72+
T D<T>::d = T();
73+
74+
template <typename T>
75+
void test() {
76+
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
77+
C::c = 10;
78+
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
79+
D<int>::d = 11;
80+
}
81+
6182
int main() {
6283
static int s2;
6384
kernel_single_task<class fake_kernel>([](S s4) {
@@ -66,6 +87,7 @@ int main() {
6687
s4.foo();
6788
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
6889
static int s3;
90+
test<int>();
6991
});
7092

7193
return 0;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -verify -Wno-sycl-2017-compat -fsyntax-only %s -internal-isystem %S/Inputs
2+
3+
// This test verifies that we generate deferred diagnostics when
4+
// such diagnostics are in a function template.
5+
6+
#include "sycl.hpp"
7+
8+
using namespace cl::sycl;
9+
queue q;
10+
11+
int global_value = -1;
12+
13+
template <typename T>
14+
void kernel_wrapper() {
15+
q.submit([&](handler &h) {
16+
h.single_task([=] {
17+
// expected-error@+1{{SYCL kernel cannot use a non-const global variable}}
18+
(void)global_value;
19+
});
20+
});
21+
}
22+
23+
int main() {
24+
kernel_wrapper<int>();
25+
}

clang/test/SemaSYCL/wrong-address-taking.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,12 @@ void basicUsage() {
4545

4646
template <typename T> void templatedContext() {
4747

48-
// FIXME: this is likely not diagnosed because of a common problem among
49-
// deferred diagnostics. They don't work from templated context if the
50-
// problematic code doesn't depend on a template parameter. See
51-
// https://github.com/intel/llvm/pull/5114 for an explanation of the problem
52-
// and possible solution.
48+
// expected-error@+1 {{taking address of a function not marked with 'intel::device_indirectly_callable' attribute is not allowed in SYCL device code}}
5349
int (*p)(int) = &badFoo;
50+
// expected-error@+1 {{taking address of a function not marked with 'intel::device_indirectly_callable' attribute is not allowed in SYCL device code}}
5451
auto p1 = &ForMembers::badMember;
5552

53+
// expected-error@+2 {{taking address of a function not marked with 'intel::device_indirectly_callable' attribute is not allowed in SYCL device code}}
5654
// expected-note@+1 {{called by 'templatedContext<int>'}}
5755
templateCaller1<badFoo>(1);
5856
}

0 commit comments

Comments
 (0)