Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SYCL] Error for implicit capture of this pointer inside a sycl kernel #2029

Merged
merged 9 commits into from
Jul 22, 2020
Merged
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
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 @@ -1943,6 +1943,11 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc,
constructKernelName(*this, KernelCallerFunc, MC);
StringRef KernelName(getLangOpts().SYCLUnnamedLambda ? StableName
: CalculatedName);
if (KernelObj->isLambda()) {
bader marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -504,8 +504,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>
bader marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -516,23 +516,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 @@ -543,16 +543,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