olestrohm updated this revision to Diff 347872.
olestrohm added a comment.

Made the check more general, it's no longer OpenCL specific and no longer 
restricted to just constructors, since the check only requires them to be 
methods.

Also added more Sema tests, including using FileCheck to check that the 
constructors that should be used are actually used.


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

https://reviews.llvm.org/D102850

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
  clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===================================================================
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must 
be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK: -CXXConstructorDecl {{.*}} X 'void (){{( __attribute__.*)?}} 
__generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} 
__private'
+  X() __private : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} 
__global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //expected-note@+2{{candidate constructor (the implicit copy constructor) not 
viable: no known conversion from 'int' to 'const __generic Y' for 1st argument}}
 //expected-note@+1{{candidate constructor (the implicit move constructor) not 
viable: no known conversion from 'int' to '__generic Y' for 1st argument}}
 struct Y {
@@ -20,6 +28,7 @@
   __constant X cx1;
   __constant X cx2(1);
   __local X lx;
+  __private X x;
 
   __private Y py;
   __constant Y cy1; // expected-error{{variable in constant address space must 
be initialized}}
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===================================================================
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ : x(0) {}
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor.
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,19 @@
            S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  if (const auto *MD1 = dyn_cast_or_null<CXXMethodDecl>(Cand1.Function)) {
+    if (const auto *MD2 = dyn_cast_or_null<CXXMethodDecl>(Cand2.Function)) {
+      LangAS AS1 = MD1->getMethodQualifiers().getAddressSpace();
+      LangAS AS2 = MD2->getMethodQualifiers().getAddressSpace();
+      if (AS1 != AS2) {
+        if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+          return true;
+        if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2))
+          return false;
+      }
+    }
+  }
+
   return false;
 }
 


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===================================================================
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK: -CXXConstructorDecl {{.*}} X 'void (){{( __attribute__.*)?}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} __private'
+  X() __private : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //expected-note@+2{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const __generic Y' for 1st argument}}
 //expected-note@+1{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to '__generic Y' for 1st argument}}
 struct Y {
@@ -20,6 +28,7 @@
   __constant X cx1;
   __constant X cx2(1);
   __local X lx;
+  __private X x;
 
   __private Y py;
   __constant Y cy1; // expected-error{{variable in constant address space must be initialized}}
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===================================================================
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ : x(0) {}
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor.
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,19 @@
            S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  if (const auto *MD1 = dyn_cast_or_null<CXXMethodDecl>(Cand1.Function)) {
+    if (const auto *MD2 = dyn_cast_or_null<CXXMethodDecl>(Cand2.Function)) {
+      LangAS AS1 = MD1->getMethodQualifiers().getAddressSpace();
+      LangAS AS2 = MD2->getMethodQualifiers().getAddressSpace();
+      if (AS1 != AS2) {
+        if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+          return true;
+        if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2))
+          return false;
+      }
+    }
+  }
+
   return false;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to