[clang] b102e68 - [OpenCL] Fix overloading resolution of addrspace constructors

Ole Strohm via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 11 03:13:54 PDT 2021


Author: Ole Strohm
Date: 2021-06-11T11:12:33+01:00
New Revision: b102e6880ab06654f945284a520f68c099732f44

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

LOG: [OpenCL] Fix overloading resolution of addrspace constructors

This fixes the prioritization of address spaces when choosing a
constructor, stopping them from being considered equally good,
which made the construction of types that could be constructed
by more than one of the constructors.

It does this by preferring the most specific address space,
which is decided by seeing if one of the address spaces is
a superset of the other, and preferring the other.

Fixes: PR50329

Reviewed By: Anastasia

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4b6c3f3658a7f..2801c3cff8afc 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,23 @@ bool clang::isBetterOverloadCandidate(
            S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  // General member function overloading is handled above, so this only handles
+  // constructors with address spaces.
+  // This only handles address spaces since C++ has no other
+  // qualifier that can be used with constructors.
+  const auto *CD1 = dyn_cast_or_null<CXXConstructorDecl>(Cand1.Function);
+  const auto *CD2 = dyn_cast_or_null<CXXConstructorDecl>(Cand2.Function);
+  if (CD1 && CD2) {
+    LangAS AS1 = CD1->getMethodQualifiers().getAddressSpace();
+    LangAS AS2 = CD2->getMethodQualifiers().getAddressSpace();
+    if (AS1 != AS2) {
+      if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+        return true;
+      if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+        return false;
+    }
+  }
+
   return false;
 }
 

diff  --git a/clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp b/clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
index a5e41950649df..c0913f484f5e3 100644
--- a/clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ b/clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@ struct X {
   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 @@ __global X gx;
 // 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;

diff  --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
index 9154d579a9b4a..0605a48d0fe91 100644
--- a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,24 @@
-// 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
+//CHECK-NOT:  used
+//CHECK-SAME: X 'void (){{.*}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __private'
+  X() __private : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //expected-note at +2{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const __generic Y' for 1st argument}}
 //expected-note at +1{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to '__generic Y' for 1st argument}}
 struct Y {
@@ -20,6 +30,7 @@ kernel void k() {
   __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}}


        


More information about the cfe-commits mailing list