From 1b9f026424a61e6c806587e2f35559078b9baf3a Mon Sep 17 00:00:00 2001 From: asudarsa <52976623+asudarsa@users.noreply.github.com> Date: Wed, 22 Jul 2020 03:58:46 -0400 Subject: [PATCH] [SYCL] Error for implicit capture of this pointer inside a sycl kernel (#2029) Signed-off-by: Arvind Sudarsanam --- .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaSYCL.cpp | 5 ++++ .../SemaSYCL/lambda_implicit_capture_this.cpp | 26 +++++++++++++++++++ sycl/include/CL/sycl/handler.hpp | 24 ++++++++--------- 4 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 clang/test/SemaSYCL/lambda_implicit_capture_this.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9c4fc3ab93b59..705337d3b8fc4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7326,6 +7326,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 0690f7ff406cb..9920dce40bb49 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -1944,6 +1944,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 2ab34ec6b488a..da60f8258a0bb 100644 --- a/sycl/include/CL/sycl/handler.hpp +++ b/sycl/include/CL/sycl/handler.hpp @@ -509,8 +509,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 @@ -521,23 +521,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 @@ -548,16 +548,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; }