From 9b4c6b8c7b182c0686454064519119d8b98f5b95 Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Thu, 4 Apr 2019 11:08:51 +0000 Subject: [PATCH] [PR41157][OpenCL] Prevent implicit init of local addr space var in C++ mode. Prevent adding initializers implicitly to variables declared in local address space. This happens when they get converted into global variables and therefore theoretically have to be default initialized in C++. Differential Revision: https://reviews.llvm.org/D59646 llvm-svn: 357684 --- clang/lib/Sema/SemaDecl.cpp | 6 +++++- .../CodeGenOpenCLCXX/addrspace-of-this.cl | 6 ++---- .../CodeGenOpenCLCXX/local_addrspace_init.cl | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d22b9f695e9a0..fa29e8c904fc7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11682,7 +11682,11 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { setFunctionHasBranchProtectedScope(); } } - + // In OpenCL, we can't initialize objects in the __local address space, + // even implicitly, so don't synthesize an implicit initializer. + if (getLangOpts().OpenCL && + Var->getType().getAddressSpace() == LangAS::opencl_local) + return; // C++03 [dcl.init]p9: // If no initializer is specified for an object, and the // object is of (possibly cv-qualified) non-POD class type (or diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl index 0e76523f38a63..490b027200e38 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl @@ -150,15 +150,13 @@ __kernel void test__global() { TEST(__local) // COMMON-LABEL: _Z11test__localv -// EXPL: @__cxa_guard_acquire -// Test the address space of 'this' when invoking a constructor for an object in non-default address space -// EXPL: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*)) +// Test that we don't initialize an object in local address space. +// EXPL-NOT: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*)) // Test the address space of 'this' when invoking a method. // COMMON: %call = call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*)) - // Test the address space of 'this' when invoking copy-constructor. // COMMON: [[C1GEN:%[0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* // EXPL: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(3)* @_ZZ11test__localvE1c to %class.C addrspace(4)*)) diff --git a/clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl b/clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl new file mode 100644 index 0000000000000..8f78a35343ec8 --- /dev/null +++ b/clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s + +// Test that we don't initialize local address space objects. +//CHECK: @_ZZ4testvE1i = internal addrspace(3) global i32 undef +//CHECK: @_ZZ4testvE2ii = internal addrspace(3) global %class.C undef +class C { + int i; +}; + +kernel void test() { + __local int i; + __local C ii; + // FIXME: In OpenCL C we don't accept initializers for local + // address space variables. User defined initialization could + // make sense, but would it mean that all work items need to + // execute it? Potentially disallowing any initialization would + // make things easier and assingments can be used to set specific + // values. This rules should make it consistent with OpenCL C. + //__local C c(); +}