Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2634,6 +2634,8 @@ "field may not be qualified with an address space">; def err_compound_literal_with_address_space : Error< "compound literal in function scope may not be qualified with an address space">; +def err_address_space_mismatch_templ_inst : Error< + "conflicting address space qualifiers are provided between types %0 and %1">; def err_attr_objc_ownership_redundant : Error< "the type %0 is already explicitly ownership-qualified">; def err_invalid_nsnumber_type : Error< Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -7201,7 +7201,10 @@ !IsPointee) || // Do not deduce addr space of the void type, e.g. in f(void), otherwise // it will fail some sema check. - (T->isVoidType() && !IsPointee)) + (T->isVoidType() && !IsPointee) || + // Do not deduce address spaces for dependent types because they might end + // up instantiating to a type with an explicit address space qualifier. + T->isDependentType()) return; LangAS ImpAddr = LangAS::Default; @@ -7226,9 +7229,8 @@ if (IsPointee) { ImpAddr = LangAS::opencl_generic; } else { - if (D.getContext() == DeclaratorContext::TemplateArgContext || - T->isDependentType()) { - // Do not deduce address space for non-pointee type in templates. + if (D.getContext() == DeclaratorContext::TemplateArgContext) { + // Do not deduce address space for non-pointee type in template arg. } else if (D.getContext() == DeclaratorContext::FileContext) { ImpAddr = LangAS::opencl_global; } else { Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -684,15 +684,13 @@ OMPClause *Transform ## Class(Class *S); #include "clang/Basic/OpenMPKinds.def" - /// Build a new qualified type given its unqualified type and type - /// qualifiers. + /// Build a new qualified type given its unqualified type and type location. /// /// By default, this routine adds type qualifiers only to types that can /// have qualifiers, and silently suppresses those qualifiers that are not /// permitted. Subclasses may override this routine to provide different /// behavior. - QualType RebuildQualifiedType(QualType T, SourceLocation Loc, - Qualifiers Quals); + QualType RebuildQualifiedType(QualType T, QualifiedTypeLoc TL); /// Build a new pointer type given its pointee type. /// @@ -4228,8 +4226,9 @@ return nullptr; if (QTL) { - Result = getDerived().RebuildQualifiedType( - Result, QTL.getBeginLoc(), QTL.getType().getLocalQualifiers()); + Result = getDerived().RebuildQualifiedType(Result, QTL); + if (Result.isNull()) + return nullptr; TLB.TypeWasModifiedSafely(Result); } @@ -4240,13 +4239,14 @@ QualType TreeTransform::TransformQualifiedType(TypeLocBuilder &TLB, QualifiedTypeLoc T) { - Qualifiers Quals = T.getType().getLocalQualifiers(); - QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc()); if (Result.isNull()) return QualType(); - Result = getDerived().RebuildQualifiedType(Result, T.getBeginLoc(), Quals); + Result = getDerived().RebuildQualifiedType(Result, T); + + if (Result.isNull()) + return QualType(); // RebuildQualifiedType might have updated the type, but not in a way // that invalidates the TypeLoc. (There's no location information for @@ -4256,10 +4256,21 @@ return Result; } -template +template QualType TreeTransform::RebuildQualifiedType(QualType T, - SourceLocation Loc, - Qualifiers Quals) { + QualifiedTypeLoc TL) { + + SourceLocation Loc = TL.getBeginLoc(); + Qualifiers Quals = TL.getType().getLocalQualifiers(); + + if (((T.getAddressSpace() != LangAS::Default && + Quals.getAddressSpace() != LangAS::Default)) && + T.getAddressSpace() != Quals.getAddressSpace()) { + SemaRef.Diag(Loc, diag::err_address_space_mismatch_templ_inst) + << TL.getType() << T; + return QualType(); + } + // C++ [dcl.fct]p7: // [When] adding cv-qualifications on top of the function type [...] the // cv-qualifiers are ignored. Index: test/SemaOpenCLCXX/address-space-templates.cl =================================================================== --- test/SemaOpenCLCXX/address-space-templates.cl +++ test/SemaOpenCLCXX/address-space-templates.cl @@ -7,6 +7,25 @@ void f2(T); // expected-error{{parameter may not be qualified with an address space}} }; +template +T foo1(__global T *i) { // expected-note{{candidate template ignored: substitution failure [with T = __local int]: conflicting address space qualifiers are provided between types '__global T' and '__local int'}} + return *i; +} + +template +T *foo2(T *i) { + return i; +} + +template +void foo3() { + __private T ii; // expected-error{{conflicting address space qualifiers are provided between types 'T' and '__global int'}} +} + void bar() { S sintgl; // expected-note{{in instantiation of template class 'S' 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}} }