From 12e3a8af81da5f55381a47fada6f76a63ca735ce Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Wed, 5 Dec 2018 17:02:22 +0000 Subject: [PATCH] [OpenCL] Diagnose conflicting address spaces in templates. Added new diagnostic when templates are instantiated with different address space from the one provided in its definition. This also prevents deducing generic address space in pointer type of templates to allow giving them concrete address space during instantiation. Differential Revision: https://reviews.llvm.org/D55127 llvm-svn: 348382 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaType.cpp | 10 ++++--- clang/lib/Sema/TreeTransform.h | 35 ++++++++++++++-------- .../test/SemaOpenCLCXX/address-space-templates.cl | 19 ++++++++++++ 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a6d0d0..eaaecb4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2634,6 +2634,8 @@ def err_field_with_address_space : Error< "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< diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 011d0a5..3d0e70a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -7201,7 +7201,10 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, !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 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, 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 { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 58f73ef..bbc5fab 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -684,15 +684,13 @@ public: 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 @@ TreeTransform::TransformTypeWithDeducedTST(TypeSourceInfo *DI) { 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 @@ template 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 @@ TreeTransform::TransformQualifiedType(TypeLocBuilder &TLB, 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. diff --git a/clang/test/SemaOpenCLCXX/address-space-templates.cl b/clang/test/SemaOpenCLCXX/address-space-templates.cl index 780175b..48fbdc7 100644 --- a/clang/test/SemaOpenCLCXX/address-space-templates.cl +++ b/clang/test/SemaOpenCLCXX/address-space-templates.cl @@ -7,6 +7,25 @@ struct S { 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}} } -- 2.7.4