Skip to content

Commit

Permalink
[SYCL] Error for implicit capture of this pointer inside a sycl kernel (
Browse files Browse the repository at this point in the history
#2029)

Signed-off-by: Arvind Sudarsanam <[email protected]>
  • Loading branch information
asudarsa authored Jul 22, 2020
1 parent 400e1e6 commit 1b9f026
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 12 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
26 changes: 26 additions & 0 deletions clang/test/SemaSYCL/lambda_implicit_capture_this.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -fsyntax-only -verify %s

template <typename name, typename Func>
__attribute__((sycl_kernel)) void kernel(Func kernelFunc) {
kernelFunc();
}

class Class {
public:
Class() : member(1) {}
void function();
int member;
};

void Class::function() {
kernel<class kernel_wrapper>(
[=]() {
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();
}
24 changes: 12 additions & 12 deletions sycl/include/CL/sycl/handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,8 @@ class __SYCL_EXPORT handler {

template <typename T, int Dim, access::mode Mode, access::target Target,
access::placeholder IsPH>
detail::enable_if_t<Dim == 0 && Mode == access::mode::atomic, T>
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) const {
static detail::enable_if_t<Dim == 0 && Mode == access::mode::atomic, T>
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) {
#ifdef __ENABLE_USM_ADDR_SPACE__
atomic<T, access::address_space::global_device_space> AtomicSrc = Src;
#else
Expand All @@ -521,23 +521,23 @@ class __SYCL_EXPORT handler {

template <typename T, int Dim, access::mode Mode, access::target Target,
access::placeholder IsPH>
detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, T>
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) const {
static detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, T>
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) {
id<Dim> Id = getDelinearizedIndex(Src.get_range(), 0);
return Src[Id].load();
}

template <typename T, int Dim, access::mode Mode, access::target Target,
access::placeholder IsPH>
detail::enable_if_t<Mode != access::mode::atomic, T>
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) const {
static detail::enable_if_t<Mode != access::mode::atomic, T>
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) {
return *(Src.get_pointer());
}

template <typename T, int Dim, access::mode Mode, access::target Target,
access::placeholder IsPH>
detail::enable_if_t<Dim == 0 && Mode == access::mode::atomic, void>
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const {
static detail::enable_if_t<Dim == 0 && Mode == access::mode::atomic, void>
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) {
#ifdef __ENABLE_USM_ADDR_SPACE__
atomic<T, access::address_space::global_device_space> AtomicDst = Dst;
#else
Expand All @@ -548,16 +548,16 @@ class __SYCL_EXPORT handler {

template <typename T, int Dim, access::mode Mode, access::target Target,
access::placeholder IsPH>
detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, void>
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const {
static detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, void>
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) {
id<Dim> Id = getDelinearizedIndex(Dst.get_range(), 0);
Dst[Id].store(V);
}

template <typename T, int Dim, access::mode Mode, access::target Target,
access::placeholder IsPH>
detail::enable_if_t<Mode != access::mode::atomic, void>
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const {
static detail::enable_if_t<Mode != access::mode::atomic, void>
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) {
*(Dst.get_pointer()) = V;
}

Expand Down

0 comments on commit 1b9f026

Please sign in to comment.