diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 114 |
5 files changed, 129 insertions, 31 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ce843a587b7..60daae056b3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -60,11 +60,6 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); } -static bool isTypeTemplate(NamedDecl *ND) { - return isa<ClassTemplateDecl>(ND) || isa<TypeAliasTemplateDecl>(ND) || - isa<TemplateTemplateParmDecl>(ND); -} - namespace { class TypeNameValidatorCCC : public CorrectionCandidateCallback { @@ -81,7 +76,7 @@ class TypeNameValidatorCCC : public CorrectionCandidateCallback { bool ValidateCandidate(const TypoCorrection &candidate) override { if (NamedDecl *ND = candidate.getCorrectionDecl()) { bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); - bool AllowedTemplate = AllowTemplates && isTypeTemplate(ND); + bool AllowedTemplate = AllowTemplates && getAsTypeTemplateDecl(ND); return (IsType || AllowedTemplate) && (AllowInvalidDecl || !ND->isInvalidDecl()); } @@ -405,7 +400,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); Res != ResEnd; ++Res) { if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) || - (AllowDeducedTemplate && isTypeTemplate(*Res))) { + (AllowDeducedTemplate && getAsTypeTemplateDecl(*Res))) { if (!IIDecl || (*Res)->getLocation().getRawEncoding() < IIDecl->getLocation().getRawEncoding()) @@ -458,9 +453,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) T = Context.getObjCInterfaceType(IDecl); - } else if (AllowDeducedTemplate && isTypeTemplate(IIDecl)) { - T = Context.getDeducedTemplateSpecializationType( - TemplateName(cast<TemplateDecl>(IIDecl)), QualType(), false); + } else if (AllowDeducedTemplate) { + if (auto *TD = getAsTypeTemplateDecl(IIDecl)) + T = Context.getDeducedTemplateSpecializationType(TemplateName(TD), + QualType(), false); } if (T.isNull()) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8f46ad056b7..d3b47f13410 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8792,8 +8792,18 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, Context.getTypeDeclType(Type)); } - // FIXME: Form a deduced template specialization type if we get a template - // declaration here. + // C++ [dcl.type.simple]p2: + // A type-specifier of the form + // typename[opt] nested-name-specifier[opt] template-name + // is a placeholder for a deduced class type [...]. + if (getLangOpts().CPlusPlus1z) { + if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) { + return Context.getElaboratedType( + Keyword, QualifierLoc.getNestedNameSpecifier(), + Context.getDeducedTemplateSpecializationType(TemplateName(TD), + QualType(), false)); + } + } DiagID = diag::err_typename_nested_not_type; Referenced = Result.getFoundDecl(); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index aff19ec597e..723a6c0e4de 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1490,12 +1490,16 @@ TemplateInstantiator::TransformSubstTemplateTypeParmPackType( /// a cast expression) or that the entity has no name (e.g., an /// unnamed function parameter). /// +/// \param AllowDeducedTST Whether a DeducedTemplateSpecializationType is +/// acceptable as the top level type of the result. +/// /// \returns If the instantiation succeeds, the instantiated /// type. Otherwise, produces diagnostics and returns a NULL type. TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &Args, SourceLocation Loc, - DeclarationName Entity) { + DeclarationName Entity, + bool AllowDeducedTST) { assert(!ActiveTemplateInstantiations.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -1505,7 +1509,8 @@ TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, return T; TemplateInstantiator Instantiator(*this, Args, Loc, Entity); - return Instantiator.TransformType(T); + return AllowDeducedTST ? Instantiator.TransformTypeWithDeducedTST(T) + : Instantiator.TransformType(T); } TypeSourceInfo *Sema::SubstType(TypeLoc TL, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 2310e99ab9d..46de4a1565a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -657,10 +657,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, ArrayRef<BindingDecl*> *Bindings) { // Do substitution on the type of the declaration - TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), - TemplateArgs, - D->getTypeSpecStartLoc(), - D->getDeclName()); + TypeSourceInfo *DI = SemaRef.SubstType( + D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(), + D->getDeclName(), /*AllowDeducedTST*/true); if (!DI) return nullptr; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index d27cd770400..7198fce7529 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -307,6 +307,17 @@ public: /// QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL); + /// \brief Transform a type that is permitted to produce a + /// DeducedTemplateSpecializationType. + /// + /// This is used in the (relatively rare) contexts where it is acceptable + /// for transformation to produce a class template type with deduced + /// template arguments. + /// @{ + QualType TransformTypeWithDeducedTST(QualType T); + TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI); + /// @} + /// \brief Transform the given statement. /// /// By default, this routine transforms a statement by delegating to the @@ -898,7 +909,7 @@ public: /// By default, builds a new ParenType type from the inner type. /// Subclasses may override this routine to provide different behavior. QualType RebuildParenType(QualType InnerType) { - return SemaRef.Context.getParenType(InnerType); + return SemaRef.BuildParenType(InnerType); } /// \brief Build a new qualified name type. @@ -968,7 +979,8 @@ public: SourceLocation KeywordLoc, NestedNameSpecifierLoc QualifierLoc, const IdentifierInfo *Id, - SourceLocation IdLoc) { + SourceLocation IdLoc, + bool DeducedTSTContext) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); @@ -980,9 +992,25 @@ public: Id); } - if (Keyword == ETK_None || Keyword == ETK_Typename) - return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, - *Id, IdLoc); + if (Keyword == ETK_None || Keyword == ETK_Typename) { + QualType T = SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, + *Id, IdLoc); + // If a dependent name resolves to a deduced template specialization type, + // check that we're in one of the syntactic contexts permitting it. + if (!DeducedTSTContext) { + if (auto *Deduced = dyn_cast_or_null<DeducedTemplateSpecializationType>( + T.isNull() ? nullptr : T->getContainedDeducedType())) { + SemaRef.Diag(IdLoc, diag::err_dependent_deduced_tst) + << (int)SemaRef.getTemplateNameKindForDiagnostics( + Deduced->getTemplateName()) + << QualType(QualifierLoc.getNestedNameSpecifier()->getAsType(), 0); + if (auto *TD = Deduced->getTemplateName().getAsTemplateDecl()) + SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here); + return QualType(); + } + } + return T; + } TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); @@ -3157,6 +3185,10 @@ private: TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType, NamedDecl *FirstQualifierInScope, CXXScopeSpec &SS); + + QualType TransformDependentNameType(TypeLocBuilder &TLB, + DependentNameTypeLoc TL, + bool DeducibleTSTContext); }; template<typename Derived> @@ -4048,6 +4080,52 @@ TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) { llvm_unreachable("unhandled type loc!"); } +template<typename Derived> +QualType TreeTransform<Derived>::TransformTypeWithDeducedTST(QualType T) { + if (!isa<DependentNameType>(T)) + return TransformType(T); + + if (getDerived().AlreadyTransformed(T)) + return T; + TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo(T, + getDerived().getBaseLocation()); + TypeSourceInfo *NewDI = getDerived().TransformTypeWithDeducedTST(DI); + return NewDI ? NewDI->getType() : QualType(); +} + +template<typename Derived> +TypeSourceInfo * +TreeTransform<Derived>::TransformTypeWithDeducedTST(TypeSourceInfo *DI) { + if (!isa<DependentNameType>(DI->getType())) + return TransformType(DI); + + // Refine the base location to the type's location. + TemporaryBase Rebase(*this, DI->getTypeLoc().getBeginLoc(), + getDerived().getBaseEntity()); + if (getDerived().AlreadyTransformed(DI->getType())) + return DI; + + TypeLocBuilder TLB; + + TypeLoc TL = DI->getTypeLoc(); + TLB.reserve(TL.getFullDataSize()); + + Qualifiers Quals; + if (auto QTL = TL.getAs<QualifiedTypeLoc>()) { + Quals = QTL.getType().getLocalQualifiers(); + TL = QTL.getUnqualifiedLoc(); + } + + auto DNTL = TL.castAs<DependentNameTypeLoc>(); + + QualType Result = getDerived().TransformDependentNameType( + TLB, DNTL, /*DeducedTSTContext*/true); + if (Result.isNull()) + return nullptr; + + return TLB.getTypeSourceInfo(SemaRef.Context, Result); +} + /// FIXME: By default, this routine adds type qualifiers only to types /// that can have qualifiers, and silently suppresses those qualifiers /// that are not permitted (e.g., qualifiers on reference or function @@ -5854,8 +5932,14 @@ TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB, } template<typename Derived> -QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL) { +QualType TreeTransform<Derived>::TransformDependentNameType( + TypeLocBuilder &TLB, DependentNameTypeLoc TL) { + return TransformDependentNameType(TLB, TL, false); +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformDependentNameType( + TypeLocBuilder &TLB, DependentNameTypeLoc TL, bool DeducedTSTContext) { const DependentNameType *T = TL.getTypePtr(); NestedNameSpecifierLoc QualifierLoc @@ -5868,7 +5952,8 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, TL.getElaboratedKeywordLoc(), QualifierLoc, T->getIdentifier(), - TL.getNameLoc()); + TL.getNameLoc(), + DeducedTSTContext); if (Result.isNull()) return QualType(); @@ -9474,7 +9559,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXFunctionalCastExpr( CXXFunctionalCastExpr *E) { - TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten()); + TypeSourceInfo *Type = + getDerived().TransformTypeWithDeducedTST(E->getTypeInfoAsWritten()); if (!Type) return ExprError(); @@ -9663,8 +9749,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { // Transform the type that we're allocating - TypeSourceInfo *AllocTypeInfo - = getDerived().TransformType(E->getAllocatedTypeSourceInfo()); + TypeSourceInfo *AllocTypeInfo = + getDerived().TransformTypeWithDeducedTST(E->getAllocatedTypeSourceInfo()); if (!AllocTypeInfo) return ExprError(); @@ -10375,7 +10461,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( CXXTemporaryObjectExpr *E) { - TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); + TypeSourceInfo *T = + getDerived().TransformTypeWithDeducedTST(E->getTypeSourceInfo()); if (!T) return ExprError(); @@ -10672,7 +10759,8 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { - TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); + TypeSourceInfo *T = + getDerived().TransformTypeWithDeducedTST(E->getTypeSourceInfo()); if (!T) return ExprError(); |