Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -4526,6 +4526,14 @@ 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) { @@ -4534,6 +4542,9 @@ 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 @@ -4572,6 +4583,9 @@ if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != TL.getPointeeLoc().getType()) { @@ -4601,6 +4615,9 @@ if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeTypeAsWritten()) { Index: test/SemaOpenCLCXX/address-space-deduction.cl =================================================================== --- test/SemaOpenCLCXX/address-space-deduction.cl +++ test/SemaOpenCLCXX/address-space-deduction.cl @@ -38,3 +38,43 @@ int foo[10]; xxx(&foo[0]); } + +// Deducing addr spaces for template specialization is fine +// addr space of template arg can't affecting the addr space +// of specialization + +template +struct x1 { +//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &) __generic' +//CHECK: -CXXMethodDecl {{.*}} operator= '__generic x1 &(const __generic x1 &) __generic' + x1& operator=(const x1& xx) { + y = xx.y; + return *this; + } + int y; +}; + +template +struct x2 { +//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *) __generic' +//CHECK: -CXXMethodDecl {{.*}} foo 'void (__generic x1 *) __generic' + void foo(x1* xx) { + m[0] = *xx; + } +//CHECK: -FieldDecl {{.*}} m 'x1 [2]' + x1 m[2]; +}; + +void bar(__global x1 *xx, __global x2 *bar) { + bar->foo(xx); +} + +template +class x3 : public T { +public: + //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &) __generic' + x3(const x3 &t); +}; +//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &) __generic' +template +x3::x3(const x3 &t) {}