Anastasia updated this revision to Diff 320447.
Anastasia added a comment.

Added address space compatibility check and improved testing.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95608/new/

https://reviews.llvm.org/D95608

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

Index: clang/test/SemaOpenCLCXX/address-space-references.cl
===================================================================
--- clang/test/SemaOpenCLCXX/address-space-references.cl
+++ clang/test/SemaOpenCLCXX/address-space-references.cl
@@ -10,8 +10,20 @@
 // 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
Index: clang/test/CodeGenOpenCLCXX/addrspace-references.cl
===================================================================
--- clang/test/CodeGenOpenCLCXX/addrspace-references.cl
+++ 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 @@
   // 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});
+}
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -4289,17 +4289,36 @@
     if (Sequence.step_begin() != Sequence.step_end())
       Sequence.RewrapReferenceInitList(cv1T1, InitList);
   }
-
+  // Perform address space compatibility check.
+  QualType cv1T1IgnoreAS = cv1T1;
+  if (T1Quals.hasAddressSpace()) {
+    Qualifiers T2Quals;
+    static_cast<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, VK_XValue);
+    } else
       Sequence.SetFailed(
           InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to