Anastasia created this revision.
Anastasia added a reviewer: rjmccall.
Herald added subscribers: ebevhan, yaxunl.

A regression was introduced in D64400 <https://reviews.llvm.org/D64400> because 
auto is using the same logic as templates. However, deduction of addr spaces 
wasn't working correctly even before.

Here are the rules that are implemented in this patch:

- For non-reference and non-pointer types deduction can be done early because 
addr space is not going to be taken from init expr
- For ref or ptr auto types we should prevent deducing addr space before the 
deduction of the whole type (incl its pointee addr spaces) from init expr


https://reviews.llvm.org/D65744

Files:
  include/clang/AST/Type.h
  lib/Sema/SemaType.cpp
  lib/Sema/TreeTransform.h
  test/SemaOpenCLCXX/addrspace-auto.cl

Index: test/SemaOpenCLCXX/addrspace-auto.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCLCXX/addrspace-auto.cl
@@ -0,0 +1,31 @@
+//RUN: %clang_cc1 %s -cl-std=clc++ -pedantic -ast-dump -verify | FileCheck %s
+
+kernel void test(){
+  int i;
+//CHECK: VarDecl {{.*}} ai 'int':'int'
+  auto ai = i;
+
+  constexpr int c = 1;
+//CHECK: VarDecl {{.*}} used cai '__constant int':'__constant int'
+  __constant auto cai = c;
+//CHECK: VarDecl {{.*}} aii 'int':'int'
+  auto aii = cai;
+
+//CHECK: VarDecl {{.*}} ref 'int &'
+  auto& ref = i;
+//CHECK: VarDecl {{.*}} ptr 'int *'
+  auto* ptr = &i;
+//CHECK: VarDecl {{.*}} ref_c '__constant int &'
+  auto& ref_c = cai;
+
+//CHECK: VarDecl {{.*}} ptrptr 'int **'
+  auto ** ptrptr = &ptr;
+//CHECK: VarDecl {{.*}} refptr 'int *&'
+  auto *& refptr = ptr;
+
+//CHECK: VarDecl {{.*}} invalid gref '__global auto &'
+  __global auto& gref = i; //expected-error{{variable 'gref' with type '__global auto &' has incompatible initializer of type 'int'}}
+  __local int* ptr_l;
+//CHECK: VarDecl {{.*}} invalid gptr '__global auto *'
+  __global auto* gptr = ptr_l; //expected-error{{variable 'gptr' with type '__global auto *' has incompatible initializer of type '__local int *'}}
+}
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -4538,8 +4538,17 @@
 
 /// Helper to deduce addr space of a pointee type in OpenCL mode.
 /// If the type is updated it will be overwritten in PointeeType param.
-static void deduceOpenCLPointeeAddrSpace(Sema &SemaRef, QualType &PointeeType) {
-  if (PointeeType.getAddressSpace() == LangAS::Default)
+static void deduceOpenCLPointeeAddrSpace(Sema &SemaRef, QualType &PointeeType,
+                                         QualType TLT) {
+  // Prevent deducing addr space for auto because it will be taken from
+  // the initializing expression.
+  bool IsAuto = false;
+  auto Pointee = TLT->getPointeeType();
+  do {
+    IsAuto = Pointee->isAutoType();
+    Pointee = Pointee->getPointeeType();
+  }  while (!Pointee.isNull());
+  if (!IsAuto && PointeeType.getAddressSpace() == LangAS::Default)
     PointeeType = SemaRef.Context.getAddrSpaceQualType(PointeeType,
                                                        LangAS::opencl_generic);
 }
@@ -4553,7 +4562,7 @@
     return QualType();
 
   if (SemaRef.getLangOpts().OpenCL)
-    deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType);
+    deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType, TL.getType());
 
   QualType Result = TL.getType();
   if (PointeeType->getAs<ObjCObjectType>()) {
@@ -4594,7 +4603,7 @@
     return QualType();
 
   if (SemaRef.getLangOpts().OpenCL)
-    deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType);
+    deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType, TL.getType());
 
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||
@@ -4626,7 +4635,7 @@
     return QualType();
 
   if (SemaRef.getLangOpts().OpenCL)
-    deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType);
+    deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType, TL.getType());
 
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -7398,6 +7398,17 @@
   bool IsFuncType =
       ChunkIndex < D.getNumTypeObjects() &&
       D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function;
+  bool IsAutoPointee = false;
+  if (State.getSema().getLangOpts().OpenCLCPlusPlus){
+    // Detect if pointer or reference are part of auto type.
+    if (T->isPointerType() || T->isReferenceType()) {
+      auto Pointee = T->getPointeeType();
+      do {
+        IsAutoPointee = Pointee->isAutoType();
+        Pointee = Pointee->getPointeeType();
+      } while (!Pointee.isNull());
+    }
+  }
   if ( // Do not deduce addr space for function return type and function type,
        // otherwise it will fail some sema check.
       IsFuncReturnType || IsFuncType ||
@@ -7425,6 +7436,9 @@
       // Do not deduce addr space of decltype because it will be taken from
       // its argument.
       T->isDecltypeType() ||
+      // Do not deduce addr space for auto pointee type because it is taken from
+      // the initializing expression type during the type deduction.
+      (T->isAutoType() && IsPointee) || (IsAutoPointee) ||
       // OpenCL spec v2.0 s6.9.b:
       // The sampler type cannot be used with the __local and __global address
       // space qualifiers.
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -2056,6 +2056,8 @@
   bool isAlignValT() const;                     // C++17 std::align_val_t
   bool isStdByteType() const;                   // C++17 std::byte
   bool isAtomicType() const;                    // C11 _Atomic()
+  bool isAutoType() const;                      // C++11 auto or
+                                                // C++14 decltype(auto)
 
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
   bool is##Id##Type() const;
@@ -6502,6 +6504,10 @@
   return isa<AtomicType>(CanonicalType);
 }
 
+inline bool Type::isAutoType() const {
+  return isa<AutoType>(CanonicalType);
+}
+
 inline bool Type::isObjCQualifiedIdType() const {
   if (const auto *OPT = getAs<ObjCObjectPointerType>())
     return OPT->isObjCQualifiedIdType();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to