[clang] e635feb - [OpenCL] Fix address space in binding of initializer lists to referencs

Anastasia Stulova via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 3 04:50:15 PST 2021


Author: Anastasia Stulova
Date: 2021-02-03T12:48:21Z
New Revision: e635feb15a91e6eeb77876031be2811e63d542f3

URL: https://github.com/llvm/llvm-project/commit/e635feb15a91e6eeb77876031be2811e63d542f3
DIFF: https://github.com/llvm/llvm-project/commit/e635feb15a91e6eeb77876031be2811e63d542f3.diff

LOG: [OpenCL] Fix address space in binding of initializer lists to referencs

Prevent materializing temporaries in the address space of the references
they are bind to. The temporaries should always be in the same address
space - private for OpenCL.

Tags: #clang

Differential Revision: https://reviews.llvm.org/D95608

Added: 
    

Modified: 
    clang/lib/Sema/SemaInit.cpp
    clang/test/CodeGenOpenCLCXX/addrspace-references.cl
    clang/test/SemaOpenCLCXX/address-space-references.cl

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index f4493d84238d..4e3547c5121f 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4289,17 +4289,36 @@ static void TryReferenceListInitialization(Sema &S,
     if (Sequence.step_begin() != Sequence.step_end())
       Sequence.RewrapReferenceInitList(cv1T1, InitList);
   }
-
+  // Perform address space compatibility check.
+  QualType cv1T1IgnoreAS = cv1T1;
+  if (T1Quals.hasAddressSpace()) {
+    Qualifiers T2Quals;
+    (void)S.Context.getUnqualifiedArrayType(InitList->getType(), T2Quals);
+    if (!T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+      Sequence.SetFailed(
+          InitializationSequence::FK_ReferenceInitDropsQualifiers);
+      return;
+    }
+    // Ignore address space of reference type at this point and perform address
+    // space conversion after the reference binding step.
+    cv1T1IgnoreAS =
+        S.Context.getQualifiedType(T1, T1Quals.withoutAddressSpace());
+  }
   // Not reference-related. Create a temporary and bind to that.
-  InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+  InitializedEntity TempEntity =
+      InitializedEntity::InitializeTemporary(cv1T1IgnoreAS);
 
   TryListInitialization(S, TempEntity, Kind, InitList, Sequence,
                         TreatUnavailableAsInvalid);
   if (Sequence) {
     if (DestType->isRValueReferenceType() ||
-        (T1Quals.hasConst() && !T1Quals.hasVolatile()))
-      Sequence.AddReferenceBindingStep(cv1T1, /*BindingTemporary=*/true);
-    else
+        (T1Quals.hasConst() && !T1Quals.hasVolatile())) {
+      Sequence.AddReferenceBindingStep(cv1T1IgnoreAS,
+                                       /*BindingTemporary=*/true);
+      if (T1Quals.hasAddressSpace())
+        Sequence.AddQualificationConversionStep(
+            cv1T1, DestType->isRValueReferenceType() ? VK_XValue : VK_LValue);
+    } else
       Sequence.SetFailed(
           InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
   }

diff  --git a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl
index 056168684d2d..6d4bece1a624 100644
--- a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl
+++ b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl
@@ -1,8 +1,16 @@
-//RUN: %clang_cc1 %s -cl-std=clc++ -triple spir -emit-llvm -o - | FileCheck %s
+//RUN: %clang_cc1 %s -cl-std=clc++ -triple spir -emit-llvm -o - -O0 | FileCheck %s
+
+typedef short short2 __attribute__((ext_vector_type(2)));
 
 int bar(const unsigned int &i);
-// CHECK-LABEL: define{{.*}} spir_func void @_Z3foov() 
-void foo() {
+
+class C {
+public:
+  void bar(const short2 &);
+};
+
+// CHECK-LABEL: define{{.*}} spir_func void @_Z6scalarv()
+void scalar() {
   // The generic addr space reference parameter object will be bound
   // to a temporary value allocated in private addr space. We need an
   // addrspacecast before passing the value to the function.
@@ -12,3 +20,14 @@ void foo() {
   // CHECK: call spir_func i32 @_Z3barRU3AS4Kj(i32 addrspace(4)* align 4 dereferenceable(4) [[REG]])
   bar(1);
 }
+
+// Test list initialization
+// CHECK-LABEL: define{{.*}} spir_func void @_Z4listv()
+void list() {
+  C c1;
+// CHECK: [[REF:%.*]] = alloca <2 x i16>
+// CHECK: store <2 x i16> <i16 1, i16 2>, <2 x i16>* [[REF]]
+// CHECK: [[REG:%[.a-z0-9]+]] = addrspacecast <2 x i16>* [[REF]] to <2 x i16> addrspace(4)*
+// CHECK: call {{.*}}void @_ZNU3AS41C3barERU3AS4KDv2_s(%class.C addrspace(4)* {{.*}}, <2 x i16> addrspace(4)*{{.*}} [[REG]])
+  c1.bar({1, 2});
+}

diff  --git a/clang/test/SemaOpenCLCXX/address-space-references.cl b/clang/test/SemaOpenCLCXX/address-space-references.cl
index 66cd1c02e32f..05e789a7d4fd 100644
--- a/clang/test/SemaOpenCLCXX/address-space-references.cl
+++ b/clang/test/SemaOpenCLCXX/address-space-references.cl
@@ -10,8 +10,20 @@ int bar(const __global unsigned int &i); // expected-note{{passing argument to p
 // can't detect this case and therefore fails.
 int bar(const unsigned int &i);
 
+typedef short short2 __attribute__((ext_vector_type(2)));
+class C {
+public:
+  void gen(const short2 &);
+  void glob(__global const short2 &); //expected-note{{passing argument to parameter here}}
+  void nested_list(const short2 (&)[2]);
+};
+
 void foo() {
   bar(1); // expected-error{{binding reference of type 'const __global unsigned int' to value of type 'int' changes address space}}
+  C c;
+  c.gen({1, 2});
+  c.glob({1, 2}); //expected-error{{binding reference of type 'const __global short2' (vector of 2 'short' values) to value of type 'void' changes address space}}
+  c.nested_list({{1, 2}, {3, 4}});
 }
 
 // Test addr space conversion with nested pointers


        


More information about the cfe-commits mailing list