Index: clang/include/clang/AST/Type.h =================================================================== --- clang/include/clang/AST/Type.h +++ clang/include/clang/AST/Type.h @@ -2044,6 +2044,8 @@ bool isAlignValT() const; // C++17 std::align_val_t bool isStdByteType() const; // C++17 std::byte bool isAtomicType() const; // C11 _Atomic() + bool isUndeducedAutoType() const; // C++11 auto or + // C++14 decltype(auto) #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ bool is##Id##Type() const; @@ -6475,6 +6477,10 @@ return isa(CanonicalType); } +inline bool Type::isUndeducedAutoType() const { + return isa(CanonicalType); +} + inline bool Type::isObjCQualifiedIdType() const { if (const auto *OPT = getAs()) return OPT->isObjCQualifiedIdType(); Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -1805,7 +1805,7 @@ auto Ty = getType(); auto SETy = getSubExpr()->getType(); assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy)); - if (/*isRValue()*/ !Ty->getPointeeType().isNull()) { + if (isRValue()) { Ty = Ty->getPointeeType(); SETy = SETy->getPointeeType(); } Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -1962,6 +1962,18 @@ return true; } +// Helper to deduce addr space of a pointee type in OpenCL mode. +static QualType deduceOpenCLPointeeAddrSpace(Sema &S, QualType PointeeType) { + if (!PointeeType->isUndeducedAutoType() && !PointeeType->isDependentType() && + !PointeeType.getQualifiers().hasAddressSpace()) + PointeeType = S.getASTContext().getAddrSpaceQualType( + PointeeType, + S.getLangOpts().OpenCLCPlusPlus || S.getLangOpts().OpenCLVersion == 200 + ? LangAS::opencl_generic + : LangAS::opencl_private); + return PointeeType; +} + /// Build a pointer type. /// /// \param T The type to which we'll be building a pointer. @@ -1998,6 +2010,9 @@ if (getLangOpts().ObjCAutoRefCount) T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false); + if (getLangOpts().OpenCL) + T = deduceOpenCLPointeeAddrSpace(*this, T); + // Build the pointer type. return Context.getPointerType(T); } @@ -2058,6 +2073,9 @@ if (getLangOpts().ObjCAutoRefCount) T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true); + if (getLangOpts().OpenCL) + T = deduceOpenCLPointeeAddrSpace(*this, T); + // Handle restrict on references. if (LValueRef) return Context.getLValueReferenceType(T, SpelledAsLValue); @@ -2626,6 +2644,9 @@ if (checkQualifiedFunction(*this, T, Loc, QFK_BlockPointer)) return QualType(); + if (getLangOpts().OpenCL) + T = deduceOpenCLPointeeAddrSpace(*this, T); + return Context.getBlockPointerType(T); } @@ -7434,6 +7455,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->isUndeducedAutoType() && IsPointee) || // OpenCL spec v2.0 s6.9.b: // The sampler type cannot be used with the __local and __global address // space qualifiers. Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -4535,14 +4535,6 @@ return Result; } -/// 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) - PointeeType = SemaRef.Context.getAddrSpaceQualType(PointeeType, - LangAS::opencl_generic); -} - template QualType TreeTransform::TransformPointerType(TypeLocBuilder &TLB, PointerTypeLoc TL) { @@ -4551,9 +4543,6 @@ if (PointeeType.isNull()) return QualType(); - if (SemaRef.getLangOpts().OpenCL) - deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); - QualType Result = TL.getType(); if (PointeeType->getAs()) { // A dependent pointer type 'T *' has is being transformed such @@ -4592,9 +4581,6 @@ if (PointeeType.isNull()) return QualType(); - if (SemaRef.getLangOpts().OpenCL) - deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); - QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != TL.getPointeeLoc().getType()) { @@ -4624,9 +4610,6 @@ if (PointeeType.isNull()) return QualType(); - if (SemaRef.getLangOpts().OpenCL) - deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); - QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeTypeAsWritten()) { Index: clang/test/SemaOpenCLCXX/addrspace-auto.cl =================================================================== --- /dev/null +++ clang/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 *__generic *' + auto ** ptrptr = &ptr; +//CHECK: VarDecl {{.*}} refptr 'int *__generic &' + 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 *'}} +}