diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 139641c1d0171..a6e6335079caa 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1770,8 +1770,15 @@ class DeferredDiagnosticsEmitter // Emit any deferred diagnostics for FD void emitDeferredDiags(FunctionDecl *FD, bool ShowCallStack) { auto It = S.DeviceDeferredDiags.find(FD); - if (It == S.DeviceDeferredDiags.end()) + if (It == S.DeviceDeferredDiags.end()) { + // If this is a template instantiation, check if its declaration + // is on the deferred diagnostics stack. + if (FD->isTemplateInstantiation()) { + FD = FD->getTemplateInstantiationPattern(); + emitDeferredDiags(FD, ShowCallStack); + } return; + } bool HasWarningOrError = false; bool FirstDiag = true; for (Sema::DeviceDeferredDiagnostic &D : It->second) { diff --git a/clang/test/CodeGenSYCL/static-var-address-space.cpp b/clang/test/CodeGenSYCL/static-var-address-space.cpp index 5e1066ba92657..3dd135ae64469 100644 --- a/clang/test/CodeGenSYCL/static-var-address-space.cpp +++ b/clang/test/CodeGenSYCL/static-var-address-space.cpp @@ -1,13 +1,5 @@ // RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s #include "Inputs/sycl.hpp" -struct C { - static int c; -}; - -template -struct D { - static T d; -}; template void test() { @@ -15,12 +7,6 @@ void test() { static const int a = 0; // CHECK: @_ZZ4testIiEvvE1b = linkonce_odr addrspace(1) constant i32 0, comdat, align 4 static const T b = T(0); - // CHECK: @_ZN1C1cE = external addrspace(1) global i32, align 4 - C::c = 10; - const C struct_c; - // CHECK: @_ZN1DIiE1dE = external addrspace(1) global i32, align 4 - D::d = 11; - const D struct_d; } int main() { diff --git a/clang/test/SemaSYCL/sycl-device-const-static.cpp b/clang/test/SemaSYCL/sycl-device-const-static.cpp index 7cf081a193c2a..6a785f17725cb 100644 --- a/clang/test/SemaSYCL/sycl-device-const-static.cpp +++ b/clang/test/SemaSYCL/sycl-device-const-static.cpp @@ -51,6 +51,7 @@ void usage() { template __attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) { + // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} static int z; // expected-note-re@+3{{called by 'kernel_single_task}} // expected-note-re@+2{{called by 'kernel_single_task}} @@ -58,6 +59,26 @@ __attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) { kernelFunc(U::s2); } +struct C { + static int c; +}; + +template +struct D { + static T d; +}; + +template +T D::d = T(); + +template +void test() { + // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} + C::c = 10; + // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} + D::d = 11; +} + int main() { static int s2; kernel_single_task([](S s4) { @@ -66,6 +87,7 @@ int main() { s4.foo(); // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} static int s3; + test(); }); return 0; diff --git a/clang/test/SemaSYCL/sycl-device-template-diag.cpp b/clang/test/SemaSYCL/sycl-device-template-diag.cpp new file mode 100644 index 0000000000000..01d02b288f875 --- /dev/null +++ b/clang/test/SemaSYCL/sycl-device-template-diag.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsycl-is-device -verify -Wno-sycl-2017-compat -fsyntax-only %s -internal-isystem %S/Inputs + +// This test verifies that we generate deferred diagnostics when +// such diagnostics are in a function template. + +#include "sycl.hpp" + +using namespace cl::sycl; +queue q; + +int global_value = -1; + +template +void kernel_wrapper() { + q.submit([&](handler &h) { + h.single_task([=] { + // expected-error@+1{{SYCL kernel cannot use a non-const global variable}} + (void)global_value; + }); + }); +} + +int main() { + kernel_wrapper(); +} diff --git a/clang/test/SemaSYCL/wrong-address-taking.cpp b/clang/test/SemaSYCL/wrong-address-taking.cpp index 3cbb2ca681770..90bcbd9291126 100644 --- a/clang/test/SemaSYCL/wrong-address-taking.cpp +++ b/clang/test/SemaSYCL/wrong-address-taking.cpp @@ -45,14 +45,12 @@ void basicUsage() { template void templatedContext() { - // FIXME: this is likely not diagnosed because of a common problem among - // deferred diagnostics. They don't work from templated context if the - // problematic code doesn't depend on a template parameter. See - // https://github.com/intel/llvm/pull/5114 for an explanation of the problem - // and possible solution. + // expected-error@+1 {{taking address of a function not marked with 'intel::device_indirectly_callable' attribute is not allowed in SYCL device code}} int (*p)(int) = &badFoo; + // expected-error@+1 {{taking address of a function not marked with 'intel::device_indirectly_callable' attribute is not allowed in SYCL device code}} auto p1 = &ForMembers::badMember; + // expected-error@+2 {{taking address of a function not marked with 'intel::device_indirectly_callable' attribute is not allowed in SYCL device code}} // expected-note@+1 {{called by 'templatedContext'}} templateCaller1(1); }