diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9157e7e9d2442..145b983f2c623 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7309,6 +7309,8 @@ let CategoryName = "Lambda Issue" in { "here">; def note_var_explicitly_captured_here : Note<"variable %0 is" "%select{| explicitly}1 captured here">; + def err_implicit_this_capture : Error< + "implicit capture of 'this' is not allowed for kernel functions">; // C++14 lambda init-captures. def warn_cxx11_compat_init_capture : Warning< diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index c176f6e639f51..ef836df159d61 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -1943,6 +1943,11 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, constructKernelName(*this, KernelCallerFunc, MC); StringRef KernelName(getLangOpts().SYCLUnnamedLambda ? StableName : CalculatedName); + if (KernelObj->isLambda()) { + for (const LambdaCapture &LC : KernelObj->captures()) + if (LC.capturesThis() && LC.isImplicit()) + Diag(LC.getLocation(), diag::err_implicit_this_capture); + } SyclKernelFieldChecker checker(*this); SyclKernelDeclCreator kernel_decl( *this, checker, KernelName, KernelObj->getLocation(), diff --git a/clang/test/SemaSYCL/lambda_implicit_capture_this.cpp b/clang/test/SemaSYCL/lambda_implicit_capture_this.cpp new file mode 100644 index 0000000000000..331eb1b64ae3e --- /dev/null +++ b/clang/test/SemaSYCL/lambda_implicit_capture_this.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -fsyntax-only -verify %s + +template +__attribute__((sycl_kernel)) void kernel(Func kernelFunc) { + kernelFunc(); +} + +class Class { +public: + Class() : member(1) {} + void function(); + int member; +}; + +void Class::function() { + kernel( + [=]() { + int acc[1] = {5}; + acc[0] *= member; // expected-error{{implicit capture of 'this' is not allowed for kernel functions}} + }); +} + +int main(int argc, char *argv[]) { + Class c; + c.function(); +} diff --git a/sycl/include/CL/sycl/handler.hpp b/sycl/include/CL/sycl/handler.hpp index 0a40efb33bd2e..5554d6dc8713b 100644 --- a/sycl/include/CL/sycl/handler.hpp +++ b/sycl/include/CL/sycl/handler.hpp @@ -504,8 +504,8 @@ class __SYCL_EXPORT handler { template - detail::enable_if_t - readFromFirstAccElement(accessor Src) const { + static detail::enable_if_t + readFromFirstAccElement(accessor Src) { #ifdef __ENABLE_USM_ADDR_SPACE__ atomic AtomicSrc = Src; #else @@ -516,23 +516,23 @@ class __SYCL_EXPORT handler { template - detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, T> - readFromFirstAccElement(accessor Src) const { + static detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, T> + readFromFirstAccElement(accessor Src) { id Id = getDelinearizedIndex(Src.get_range(), 0); return Src[Id].load(); } template - detail::enable_if_t - readFromFirstAccElement(accessor Src) const { + static detail::enable_if_t + readFromFirstAccElement(accessor Src) { return *(Src.get_pointer()); } template - detail::enable_if_t - writeToFirstAccElement(accessor Dst, T V) const { + static detail::enable_if_t + writeToFirstAccElement(accessor Dst, T V) { #ifdef __ENABLE_USM_ADDR_SPACE__ atomic AtomicDst = Dst; #else @@ -543,16 +543,16 @@ class __SYCL_EXPORT handler { template - detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, void> - writeToFirstAccElement(accessor Dst, T V) const { + static detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, void> + writeToFirstAccElement(accessor Dst, T V) { id Id = getDelinearizedIndex(Dst.get_range(), 0); Dst[Id].store(V); } template - detail::enable_if_t - writeToFirstAccElement(accessor Dst, T V) const { + static detail::enable_if_t + writeToFirstAccElement(accessor Dst, T V) { *(Dst.get_pointer()) = V; }