olestrohm created this revision.
olestrohm added reviewers: Anastasia, rjmccall.
olestrohm added a project: clang.
Herald added subscribers: cfe-commits, yaxunl.

When you have a templated constructor with an R-value reference the compiler 
implicitly creates a copy and move constructor through the template 
constructor, and the copy constructor created this way was missing an address 
space in the reference parameter. I've come up with this fix that deduces the 
address space for the reference parameter right before it's created, and a 
corresponding test.

The test is quite big, but rep_outer is necessary to force the compiler to 
create the copy constructor, and the two template structs are partly for 
readability.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83665

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaOpenCLCXX/address-space-templates.cl

Index: clang/test/SemaOpenCLCXX/address-space-templates.cl
===================================================================
--- clang/test/SemaOpenCLCXX/address-space-templates.cl
+++ clang/test/SemaOpenCLCXX/address-space-templates.cl
@@ -22,10 +22,28 @@
   __private T ii; // expected-error{{conflicting address space qualifiers are provided between types '__private T' and '__global int'}}
 }
 
+template <class _Tp> struct remove_reference         { typedef _Tp type; };
+template <class _Tp> struct remove_reference<_Tp &>  { typedef _Tp type; };
+template <class _Tp> struct as_pointer {
+    typedef typename remove_reference<_Tp>::type* type;
+};
+
+struct rep {
+	// CHECK |-CXXConstructorDecl {{.*}} rep 'void (const __generic rep &__private) __generic'
+	template<class U, class = typename as_pointer<U>::type>
+	rep(U&& v) {}
+};
+
+struct rep_outer : private rep {
+	rep_outer()
+		: rep(0) {}
+};
+
 void bar() {
   S<const __global int> sintgl; // expected-note{{in instantiation of template class 'S<const __global int>' requested here}}
 
   foo1<__local int>(1); // expected-error{{no matching function for call to 'foo1'}}
   foo2<__global int>(0);
   foo3<__global int>(); // expected-note{{in instantiation of function template specialization 'foo3<__global int>' requested here}}
+  rep_outer r;
 }
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -2036,13 +2036,13 @@
 }
 
 // Helper to deduce addr space of a pointee type in OpenCL mode.
-static QualType deduceOpenCLPointeeAddrSpace(Sema &S, QualType PointeeType) {
+QualType Sema::deduceOpenCLPointeeAddrSpace(QualType PointeeType) {
   if (!PointeeType->isUndeducedAutoType() && !PointeeType->isDependentType() &&
       !PointeeType->isSamplerT() &&
       !PointeeType.hasAddressSpace())
-    PointeeType = S.getASTContext().getAddrSpaceQualType(
+    PointeeType = getASTContext().getAddrSpaceQualType(
         PointeeType,
-        S.getLangOpts().OpenCLCPlusPlus || S.getLangOpts().OpenCLVersion == 200
+        getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion == 200
             ? LangAS::opencl_generic
             : LangAS::opencl_private);
   return PointeeType;
@@ -2085,7 +2085,7 @@
     T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);
 
   if (getLangOpts().OpenCL)
-    T = deduceOpenCLPointeeAddrSpace(*this, T);
+    T = deduceOpenCLPointeeAddrSpace(T);
 
   // Build the pointer type.
   return Context.getPointerType(T);
@@ -2148,7 +2148,7 @@
     T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
 
   if (getLangOpts().OpenCL)
-    T = deduceOpenCLPointeeAddrSpace(*this, T);
+    T = deduceOpenCLPointeeAddrSpace(T);
 
   // Handle restrict on references.
   if (LValueRef)
@@ -2862,7 +2862,7 @@
     return QualType();
 
   if (getLangOpts().OpenCL)
-    T = deduceOpenCLPointeeAddrSpace(*this, T);
+    T = deduceOpenCLPointeeAddrSpace(T);
 
   return Context.getBlockPointerType(T);
 }
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3806,8 +3806,11 @@
     //   If P is a forwarding reference and the argument is an lvalue, the type
     //   "lvalue reference to A" is used in place of A for type deduction.
     if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) &&
-        Arg->isLValue())
+        Arg->isLValue()) {
+      if(S.getLangOpts().OpenCL)
+        ArgType = S.deduceOpenCLPointeeAddrSpace(ArgType);
       ArgType = S.Context.getLValueReferenceType(ArgType);
+    }
   } else {
     // C++ [temp.deduct.call]p2:
     //   If P is not a reference type:
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -9364,6 +9364,7 @@
   bool inferObjCARCLifetime(ValueDecl *decl);
 
   void deduceOpenCLAddressSpace(ValueDecl *decl);
+  QualType deduceOpenCLPointeeAddrSpace(QualType PointeeType);
 
   ExprResult
   HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to