diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index f3eee1c6335f9..66b587f00ff4a 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -119,8 +119,7 @@ getQualification(ASTContext &Context, const DeclContext *DestContext, // There can't be any more tag parents after hitting a namespace. assert(!ReachedNS); (void)ReachedNS; - NNS = NestedNameSpecifier::Create(Context, nullptr, false, - TD->getTypeForDecl()); + NNS = NestedNameSpecifier::Create(Context, nullptr, TD->getTypeForDecl()); } else if (auto *NSD = llvm::dyn_cast(CurContext)) { ReachedNS = true; NNS = NestedNameSpecifier::Create(Context, nullptr, NSD); diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 008cc96c91996..0eb196fbad46a 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1467,7 +1467,6 @@ bool allowIndex(CodeCompletionContext &CC) { return true; case NestedNameSpecifier::Super: case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: // Unresolved inside a template. case NestedNameSpecifier::Identifier: return false; diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index e605f82e91fe4..584bb1f088380 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -157,7 +157,6 @@ class DumpVisitor : public RecursiveASTVisitor { NNS_KIND(Identifier); NNS_KIND(Namespace); NNS_KIND(TypeSpec); - NNS_KIND(TypeSpecWithTemplate); NNS_KIND(Global); NNS_KIND(Super); NNS_KIND(NamespaceAlias); diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index bb4c91b831354..62f220b32bd10 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -500,7 +500,6 @@ struct TargetFinder { } return; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: add(QualType(NNS->getAsType(), 0), Flags); return; case NestedNameSpecifier::Global: diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index 7a140c991925c..dff0c711f04c5 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -144,7 +144,6 @@ class ASTWalker : public RecursiveASTVisitor { case NestedNameSpecifier::Global: return true; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::Super: case NestedNameSpecifier::Identifier: return false; diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 75a173a48e67e..c3b64d84a1b1c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -275,6 +275,10 @@ Improvements to Clang's diagnostics - Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with ``-Wno-error=parentheses``. - Clang now better preserves the sugared types of pointers to member. +- Clang now better preserves the presence of the template keyword with dependent + prefixes. +- When printing types for diagnostics, clang now doesn't suppress the scopes of + template arguments contained within nested names. - The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334) - Fixed diagnostics adding a trailing ``::`` when printing some source code constructs, like base classes. diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index af8c49e99a7ce..f386282890b5a 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1837,15 +1837,14 @@ class ASTContext : public RefCountedBase { TagDecl *OwnedTagDecl = nullptr) const; QualType getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - QualType Canon = QualType()) const; + const IdentifierInfo *Name) const; QualType getDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const IdentifierInfo *Name, ArrayRef Args) const; + ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name, + ArrayRef Args) const; QualType getDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const IdentifierInfo *Name, ArrayRef Args) const; + ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name, + ArrayRef Args, bool IsCanonical = false) const; TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const; @@ -2393,11 +2392,9 @@ class ASTContext : public RefCountedBase { TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateName Template) const; + TemplateName + getDependentTemplateName(const DependentTemplateStorage &Name) const; - TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, - const IdentifierInfo *Name) const; - TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, - OverloadedOperatorKind Operator) const; TemplateName getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl, unsigned Index, diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index 8c3fa842ab8b9..a2550716e3c7f 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -446,6 +446,14 @@ class TypeSourceInfo; /// returns nullptr only if the FromId was nullptr. IdentifierInfo *Import(const IdentifierInfo *FromId); + /// Import the given identifier or overloaded operator from the "from" + /// context into the "to" context. + /// + /// \returns The equivalent identifier or overloaded operator in the "to" + /// context. + IdentifierOrOverloadedOperator + Import(IdentifierOrOverloadedOperator FromIO); + /// Import the given Objective-C selector from the "from" /// context into the "to" context. /// diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 83a6b77704f34..f086d8134a64b 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -396,8 +396,7 @@ class ASTNodeTraverser // FIXME: Provide a NestedNameSpecifier visitor. NestedNameSpecifier *Qualifier = T->getQualifier(); if (NestedNameSpecifier::SpecifierKind K = Qualifier->getKind(); - K == NestedNameSpecifier::TypeSpec || - K == NestedNameSpecifier::TypeSpecWithTemplate) + K == NestedNameSpecifier::TypeSpec) Visit(Qualifier->getAsType()); if (T->isSugared()) Visit(T->getMostRecentCXXRecordDecl()->getTypeForDecl()); diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h index 4b627c65e276b..5ab438715ecf7 100644 --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -279,10 +279,8 @@ class DataStreamBasicReader : public BasicReaderBase { continue; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: cur = NestedNameSpecifier::Create(ctx, cur, - kind == NestedNameSpecifier::TypeSpecWithTemplate, - asImpl().readQualType().getTypePtr()); + asImpl().readQualType().getTypePtr()); continue; case NestedNameSpecifier::Global: diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h index b941add8bde88..f65d94abc2ff1 100644 --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -260,7 +260,6 @@ class DataStreamBasicWriter : public BasicWriterBase { continue; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: asImpl().writeQualType(QualType(NNS->getAsType(), 0)); continue; diff --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h index 273e73e7c1e95..d7da3272d0943 100644 --- a/clang/include/clang/AST/NestedNameSpecifier.h +++ b/clang/include/clang/AST/NestedNameSpecifier.h @@ -52,8 +52,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { enum StoredSpecifierKind { StoredIdentifier = 0, StoredDecl = 1, - StoredTypeSpec = 2, - StoredTypeSpecWithTemplate = 3 + StoredTypeSpec = 2 }; /// The nested name specifier that precedes this nested name @@ -89,10 +88,6 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { /// A type, stored as a Type*. TypeSpec, - /// A type that was preceded by the 'template' keyword, - /// stored as a Type*. - TypeSpecWithTemplate, - /// The global specifier '::'. There is no stored value. Global, @@ -137,9 +132,8 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { const NamespaceAliasDecl *Alias); /// Builds a nested name specifier that names a type. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - bool Template, const Type *T); + static NestedNameSpecifier * + Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const Type *T); /// Builds a specifier that consists of just an identifier. /// @@ -194,8 +188,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { /// Retrieve the type stored in this nested name specifier. const Type *getAsType() const { - if (Prefix.getInt() == StoredTypeSpec || - Prefix.getInt() == StoredTypeSpecWithTemplate) + if (Prefix.getInt() == StoredTypeSpec) return (const Type *)Specifier; return nullptr; @@ -401,13 +394,10 @@ class NestedNameSpecifierLocBuilder { /// \param Context The AST context in which this nested-name-specifier /// resides. /// - /// \param TemplateKWLoc The location of the 'template' keyword, if present. - /// /// \param TL The TypeLoc that describes the type preceding the '::'. /// /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, - SourceLocation ColonColonLoc); + void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc); /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'identifier::'. diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index a1caa6d39a87c..a923901b32dc0 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -94,6 +94,7 @@ class ODRHash { void AddStmt(const Stmt *S); void AddIdentifierInfo(const IdentifierInfo *II); void AddNestedNameSpecifier(const NestedNameSpecifier *NNS); + void AddDependentTemplateName(const DependentTemplateStorage &Name); void AddTemplateName(TemplateName Name); void AddDeclarationName(DeclarationName Name, bool TreatAsDecl = false); void AddTemplateArgument(TemplateArgument TA); diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 42883b6419261..178308a24e1a0 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -692,25 +692,26 @@ let Class = PropertyTypeCase in { let Class = PropertyTypeCase in { def : ReadHelper<[{ auto dtn = node.getAsDependentTemplateName(); + auto name = dtn->getName(); }]>; def : Property<"qualifier", NestedNameSpecifier> { let Read = [{ dtn->getQualifier() }]; } def : Property<"identifier", Optional> { - let Read = [{ makeOptionalFromPointer( - dtn->isIdentifier() - ? dtn->getIdentifier() - : nullptr) }]; + let Read = [{ makeOptionalFromPointer(name.getIdentifier()) }]; } def : Property<"operatorKind", OverloadedOperatorKind> { let Conditional = [{ !identifier }]; - let Read = [{ dtn->getOperator() }]; + let Read = [{ name.getOperator() }]; + } + def : Property<"HasTemplateKeyword", Bool> { + let Read = [{ dtn->hasTemplateKeyword() }]; } def : Creator<[{ if (identifier) { - return ctx.getDependentTemplateName(qualifier, *identifier); + return ctx.getDependentTemplateName({qualifier, *identifier, HasTemplateKeyword}); } else { - return ctx.getDependentTemplateName(qualifier, *operatorKind); + return ctx.getDependentTemplateName({qualifier, *operatorKind, HasTemplateKeyword}); } }]>; } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 0d5d515c0e6f7..0530996ed20d3 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -795,7 +795,6 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifier( return true; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); } @@ -820,7 +819,6 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifierLoc( return true; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); break; } @@ -1172,7 +1170,8 @@ DEF_TRAVERSE_TYPE(DependentNameType, { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + const DependentTemplateStorage &S = T->getDependentTemplateName(); + TRY_TO(TraverseNestedNameSpecifier(S.getQualifier())); TRY_TO(TraverseTemplateArguments(T->template_arguments())); }) diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h index ce97f834bfc1d..1a56133b72d6e 100644 --- a/clang/include/clang/AST/TemplateName.h +++ b/clang/include/clang/AST/TemplateName.h @@ -16,6 +16,7 @@ #include "clang/AST/DependenceFlags.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" @@ -537,6 +538,35 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { } }; +struct IdentifierOrOverloadedOperator { + IdentifierOrOverloadedOperator() = default; + IdentifierOrOverloadedOperator(const IdentifierInfo *II); + IdentifierOrOverloadedOperator(OverloadedOperatorKind OOK); + + /// Returns the identifier to which this template name refers. + const IdentifierInfo *getIdentifier() const { + if (getOperator() != OO_None) + return nullptr; + return reinterpret_cast(PtrOrOp); + } + + /// Return the overloaded operator to which this template name refers. + OverloadedOperatorKind getOperator() const { + uintptr_t OOK = -PtrOrOp; + return OOK < NUM_OVERLOADED_OPERATORS ? OverloadedOperatorKind(OOK) + : OO_None; + } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + bool operator==(const IdentifierOrOverloadedOperator &Other) const { + return PtrOrOp == Other.PtrOrOp; + }; + +private: + uintptr_t PtrOrOp = 0; +}; + /// Represents a dependent template name that cannot be /// resolved prior to template instantiation. /// @@ -545,104 +575,53 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// DependentTemplateName can refer to "MetaFun::template apply", /// where "MetaFun::" is the nested name specifier and "apply" is the /// template name referenced. The "template" keyword is implied. -class DependentTemplateName : public llvm::FoldingSetNode { - friend class ASTContext; - +class DependentTemplateStorage { /// The nested name specifier that qualifies the template /// name. /// /// The bit stored in this qualifier describes whether the \c Name field - /// is interpreted as an IdentifierInfo pointer (when clear) or as an - /// overloaded operator kind (when set). + /// was preceeded by a template keyword. llvm::PointerIntPair Qualifier; /// The dependent template name. - union { - /// The identifier template name. - /// - /// Only valid when the bit on \c Qualifier is clear. - const IdentifierInfo *Identifier; - - /// The overloaded operator name. - /// - /// Only valid when the bit on \c Qualifier is set. - OverloadedOperatorKind Operator; - }; - - /// The canonical template name to which this dependent - /// template name refers. - /// - /// The canonical template name for a dependent template name is - /// another dependent template name whose nested name specifier is - /// canonical. - TemplateName CanonicalTemplateName; - - DependentTemplateName(NestedNameSpecifier *Qualifier, - const IdentifierInfo *Identifier) - : Qualifier(Qualifier, false), Identifier(Identifier), - CanonicalTemplateName(this) {} - - DependentTemplateName(NestedNameSpecifier *Qualifier, - const IdentifierInfo *Identifier, - TemplateName Canon) - : Qualifier(Qualifier, false), Identifier(Identifier), - CanonicalTemplateName(Canon) {} - - DependentTemplateName(NestedNameSpecifier *Qualifier, - OverloadedOperatorKind Operator) - : Qualifier(Qualifier, true), Operator(Operator), - CanonicalTemplateName(this) {} - - DependentTemplateName(NestedNameSpecifier *Qualifier, - OverloadedOperatorKind Operator, - TemplateName Canon) - : Qualifier(Qualifier, true), Operator(Operator), - CanonicalTemplateName(Canon) {} + IdentifierOrOverloadedOperator Name; public: + DependentTemplateStorage(NestedNameSpecifier *Qualifier, + IdentifierOrOverloadedOperator Name, + bool HasTemplateKeyword); + /// Return the nested name specifier that qualifies this name. NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } - /// Determine whether this template name refers to an identifier. - bool isIdentifier() const { return !Qualifier.getInt(); } + IdentifierOrOverloadedOperator getName() const { return Name; } - /// Returns the identifier to which this template name refers. - const IdentifierInfo *getIdentifier() const { - assert(isIdentifier() && "Template name isn't an identifier?"); - return Identifier; - } - - /// Determine whether this template name refers to an overloaded - /// operator. - bool isOverloadedOperator() const { return Qualifier.getInt(); } + /// Was this template name was preceeded by the template keyword? + bool hasTemplateKeyword() const { return Qualifier.getInt(); } - /// Return the overloaded operator to which this template name refers. - OverloadedOperatorKind getOperator() const { - assert(isOverloadedOperator() && - "Template name isn't an overloaded operator?"); - return Operator; - } + TemplateNameDependence getDependence() const; - void Profile(llvm::FoldingSetNodeID &ID) { - if (isIdentifier()) - Profile(ID, getQualifier(), getIdentifier()); - else - Profile(ID, getQualifier(), getOperator()); + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, getQualifier(), getName(), hasTemplateKeyword()); } static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - const IdentifierInfo *Identifier) { + IdentifierOrOverloadedOperator Name, + bool HasTemplateKeyword) { ID.AddPointer(NNS); - ID.AddBoolean(false); - ID.AddPointer(Identifier); + ID.AddBoolean(HasTemplateKeyword); + Name.Profile(ID); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - OverloadedOperatorKind Operator) { - ID.AddPointer(NNS); - ID.AddBoolean(true); - ID.AddInteger(Operator); - } + void print(raw_ostream &OS, const PrintingPolicy &Policy) const; +}; + +class DependentTemplateName : public DependentTemplateStorage, + public llvm::FoldingSetNode { + friend class ASTContext; + using DependentTemplateStorage::DependentTemplateStorage; + DependentTemplateName(const DependentTemplateStorage &S) + : DependentTemplateStorage(S) {} }; } // namespace clang. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index a809102c069a8..988362787a452 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -7098,21 +7098,17 @@ class DependentTemplateSpecializationType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - /// The nested name specifier containing the qualifier. - NestedNameSpecifier *NNS; - - /// The identifier of the template. - const IdentifierInfo *Name; + DependentTemplateStorage Name; DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, + const DependentTemplateStorage &Name, ArrayRef Args, QualType Canon); public: - NestedNameSpecifier *getQualifier() const { return NNS; } - const IdentifierInfo *getIdentifier() const { return Name; } + const DependentTemplateStorage &getDependentTemplateName() const { + return Name; + } ArrayRef template_arguments() const { return {reinterpret_cast(this + 1), @@ -7123,14 +7119,12 @@ class DependentTemplateSpecializationType : public TypeWithKeyword, QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { - Profile(ID, Context, getKeyword(), NNS, Name, template_arguments()); + Profile(ID, Context, getKeyword(), Name, template_arguments()); } - static void Profile(llvm::FoldingSetNodeID &ID, - const ASTContext &Context, + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *Qualifier, - const IdentifierInfo *Name, + const DependentTemplateStorage &Name, ArrayRef Args); static bool classof(const Type *T) { diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 17ce09fa5da4f..92661b8b13fe0 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -2502,8 +2502,9 @@ class DependentTemplateSpecializationTypeLoc : if (!getLocalData()->QualifierData) return NestedNameSpecifierLoc(); - return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), - getLocalData()->QualifierData); + return NestedNameSpecifierLoc( + getTypePtr()->getDependentTemplateName().getQualifier(), + getLocalData()->QualifierData); } void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { @@ -2516,8 +2517,8 @@ class DependentTemplateSpecializationTypeLoc : return; } - assert(QualifierLoc.getNestedNameSpecifier() - == getTypePtr()->getQualifier() && + assert(QualifierLoc.getNestedNameSpecifier() == + getTypePtr()->getDependentTemplateName().getQualifier() && "Inconsistent nested-name-specifier pointer"); getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index 27f71bf5cc62f..10eb40dc90ad4 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -774,22 +774,37 @@ let Class = TemplateSpecializationType in { } let Class = DependentTemplateSpecializationType in { - def : Property<"keyword", ElaboratedTypeKeyword> { - let Read = [{ node->getKeyword() }]; - } + def : ReadHelper<[{ + const auto &dtn = node->getDependentTemplateName(); + auto name = dtn.getName(); + }]>; + def : Property<"qualifier", NestedNameSpecifier> { - let Read = [{ node->getQualifier() }]; + let Read = [{ dtn.getQualifier() }]; + } + def : Property<"identifier", Optional> { + let Read = [{ makeOptionalFromPointer(name.getIdentifier()) }]; } - def : Property<"name", Identifier> { - let Read = [{ node->getIdentifier() }]; + def : Property<"operatorKind", OverloadedOperatorKind> { + let Conditional = [{ !identifier }]; + let Read = [{ name.getOperator() }]; + } + def : Property<"HasTemplateKeyword", Bool> { + let Read = [{ dtn.hasTemplateKeyword() }]; + } + + def : Property<"keyword", ElaboratedTypeKeyword> { + let Read = [{ node->getKeyword() }]; } def : Property<"templateArguments", Array> { let Read = [{ node->template_arguments() }]; } def : Creator<[{ - return ctx.getDependentTemplateSpecializationType(keyword, qualifier, - name, templateArguments); + DependentTemplateStorage S(qualifier, identifier ? IdentifierOrOverloadedOperator(*identifier) : + IdentifierOrOverloadedOperator(*operatorKind), + HasTemplateKeyword); + return ctx.getDependentTemplateSpecializationType(keyword, S, templateArguments); }]>; } @@ -926,22 +941,10 @@ let Class = DependentNameType in { def : Property<"qualifier", NestedNameSpecifier> { let Read = [{ node->getQualifier() }]; } - def : Property<"name", Identifier> { - let Read = [{ node->getIdentifier() }]; - } - def : Property<"underlyingType", Optional> { - let Read = [{ - node->isCanonicalUnqualified() - ? std::nullopt - : std::optional(node->getCanonicalTypeInternal()) - }]; - } + def : Property<"name", Identifier> { let Read = [{ node->getIdentifier() }]; } def : Creator<[{ - QualType canon = (underlyingType - ? ctx.getCanonicalType(*underlyingType) - : QualType()); - return ctx.getDependentNameType(keyword, qualifier, name, canon); + return ctx.getDependentNameType(keyword, qualifier, name); }]>; } diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 5f5df3a45d41d..6c4a32c4ac2f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -107,8 +107,7 @@ class CXXScopeSpec { /// \param TL The TypeLoc that describes the type preceding the '::'. /// /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, - SourceLocation ColonColonLoc); + void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc); /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'identifier::'. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2d9480ebcf00c..089d01839e1cf 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4033,7 +4033,6 @@ QualType ASTContext::getMemberPointerType(QualType T, if (!Qualifier) { assert(Cls && "At least one of Qualifier or Cls must be provided"); Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr, - /*Template=*/false, getTypeDeclType(Cls).getTypePtr()); } else if (!Cls) { Cls = Qualifier->getAsRecordDecl(); @@ -4052,8 +4051,7 @@ QualType ASTContext::getMemberPointerType(QualType T, if (!Cls) return getCanonicalNestedNameSpecifier(Qualifier); NestedNameSpecifier *R = NestedNameSpecifier::Create( - *this, /*Prefix=*/nullptr, /*Template=*/false, - Cls->getCanonicalDecl()->getTypeForDecl()); + *this, /*Prefix=*/nullptr, Cls->getCanonicalDecl()->getTypeForDecl()); assert(R == getCanonicalNestedNameSpecifier(R)); return R; }(); @@ -5739,24 +5737,26 @@ ASTContext::getMacroQualifiedType(QualType UnderlyingTy, QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - QualType Canon) const { - if (Canon.isNull()) { - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - if (CanonNNS != NNS) - Canon = getDependentNameType(Keyword, CanonNNS, Name); - } - + const IdentifierInfo *Name) const { llvm::FoldingSetNodeID ID; DependentNameType::Profile(ID, Keyword, NNS, Name); void *InsertPos = nullptr; - DependentNameType *T - = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); - if (T) + if (DependentNameType *T = + DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(T, 0); - T = new (*this, alignof(DependentNameType)) + QualType Canon; + if (NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + CanonNNS != NNS) { + Canon = getDependentNameType(Keyword, CanonNNS, Name); + [[maybe_unused]] DependentNameType *T = + DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!T && "broken canonicalization"); + assert(Canon.isCanonical()); + } + + DependentNameType *T = new (*this, alignof(DependentNameType)) DependentNameType(Keyword, NNS, Name, Canon); Types.push_back(T); DependentNameTypes.InsertNode(T, InsertPos); @@ -5764,61 +5764,63 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, } QualType ASTContext::getDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const IdentifierInfo *Name, ArrayRef Args) const { + ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name, + ArrayRef Args) const { // TODO: avoid this copy SmallVector ArgCopy; for (unsigned I = 0, E = Args.size(); I != E; ++I) ArgCopy.push_back(Args[I].getArgument()); - return getDependentTemplateSpecializationType(Keyword, NNS, Name, ArgCopy); + return getDependentTemplateSpecializationType(Keyword, Name, ArgCopy); } -QualType -ASTContext::getDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - ArrayRef Args) const { - assert((!NNS || NNS->isDependent()) && - "nested-name-specifier must be dependent"); - +QualType ASTContext::getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name, + ArrayRef Args, bool IsCanonical) const { llvm::FoldingSetNodeID ID; - DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, - Name, Args); + DependentTemplateSpecializationType::Profile(ID, *this, Keyword, Name, Args); void *InsertPos = nullptr; - DependentTemplateSpecializationType *T - = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); - if (T) + if (auto *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos( + ID, InsertPos)) return QualType(T, 0); - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - - ElaboratedTypeKeyword CanonKeyword = Keyword; - if (Keyword == ElaboratedTypeKeyword::None) - CanonKeyword = ElaboratedTypeKeyword::Typename; - - bool AnyNonCanonArgs = false; - auto CanonArgs = - ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs); + NestedNameSpecifier *NNS = Name.getQualifier(); QualType Canon; - if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) { - Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS, - Name, - CanonArgs); - - // Find the insert position again. - [[maybe_unused]] auto *Nothing = - DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!Nothing && "canonical type broken"); + if (!IsCanonical) { + ElaboratedTypeKeyword CanonKeyword = Keyword != ElaboratedTypeKeyword::None + ? Keyword + : ElaboratedTypeKeyword::Typename; + NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + bool AnyNonCanonArgs = false; + auto CanonArgs = + ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs); + + if (AnyNonCanonArgs || CanonNNS != NNS || !Name.hasTemplateKeyword() || + CanonKeyword != Keyword) { + Canon = getDependentTemplateSpecializationType( + CanonKeyword, {CanonNNS, Name.getName(), /*HasTemplateKeyword=*/true}, + CanonArgs, /*IsCanonical=*/true); + // Find the insert position again. + [[maybe_unused]] auto *Nothing = + DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, + InsertPos); + assert(!Nothing && "canonical type broken"); + } + } else { + assert(Keyword != ElaboratedTypeKeyword::None); + assert(Name.hasTemplateKeyword()); + assert(NNS == getCanonicalNestedNameSpecifier(NNS)); +#ifndef NDEBUG + for (const auto &Arg : Args) + assert(Arg.structurallyEquals(getCanonicalTemplateArgument(Arg))); +#endif } - void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) + sizeof(TemplateArgument) * Args.size()), alignof(DependentTemplateSpecializationType)); - T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS, - Name, Args, Canon); + auto *T = + new (Mem) DependentTemplateSpecializationType(Keyword, Name, Args, Canon); Types.push_back(T); DependentTemplateSpecializationTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -6916,12 +6918,13 @@ ASTContext::getNameForTemplate(TemplateName Name, case TemplateName::DependentTemplate: { DependentTemplateName *DTN = Name.getAsDependentTemplateName(); + IdentifierOrOverloadedOperator TN = DTN->getName(); DeclarationName DName; - if (DTN->isIdentifier()) { - DName = DeclarationNames.getIdentifier(DTN->getIdentifier()); + if (const IdentifierInfo *II = TN.getIdentifier()) { + DName = DeclarationNames.getIdentifier(II); return DeclarationNameInfo(DName, NameLoc); } else { - DName = DeclarationNames.getCXXOperatorName(DTN->getOperator()); + DName = DeclarationNames.getCXXOperatorName(TN.getOperator()); // DNInfo work in progress: FIXME: source locations? DeclarationNameLoc DNLoc = DeclarationNameLoc::makeCXXOperatorNameLoc(SourceRange()); @@ -6996,7 +6999,13 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name, case TemplateName::DependentTemplate: { DependentTemplateName *DTN = Name.getAsDependentTemplateName(); assert(DTN && "Non-dependent template names must refer to template decls."); - return DTN->CanonicalTemplateName; + NestedNameSpecifier *Qualifier = DTN->getQualifier(); + NestedNameSpecifier *CanonQualifier = + getCanonicalNestedNameSpecifier(Qualifier); + if (Qualifier != CanonQualifier || !DTN->hasTemplateKeyword()) + return getDependentTemplateName({CanonQualifier, DTN->getName(), + /*HasTemplateKeyword=*/true}); + return Name; } case TemplateName::SubstTemplateTemplateParmPack: { @@ -7229,7 +7238,6 @@ static bool isSameQualifier(const NestedNameSpecifier *X, // We've already checked that we named the same namespace. break; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: if (X->getAsType()->getCanonicalTypeInternal() != Y->getAsType()->getCanonicalTypeInternal()) return false; @@ -7608,8 +7616,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { // The difference between TypeSpec and TypeSpecWithTemplate is that the // latter will have the 'template' keyword when printed. - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { + case NestedNameSpecifier::TypeSpec: { const Type *T = getCanonicalType(NNS->getAsType()); // If we have some kind of dependent-named type (e.g., "typename T::type"), @@ -7622,11 +7629,19 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { if (const auto *DNT = T->getAs()) return NestedNameSpecifier::Create(*this, DNT->getQualifier(), DNT->getIdentifier()); - if (const auto *DTST = T->getAs()) - return NestedNameSpecifier::Create(*this, DTST->getQualifier(), true, T); - - // TODO: Set 'Template' parameter to true for other template types. - return NestedNameSpecifier::Create(*this, nullptr, false, T); + if (const auto *DTST = T->getAs()) { + const DependentTemplateStorage &DTN = DTST->getDependentTemplateName(); + QualType NewT = getDependentTemplateSpecializationType( + ElaboratedTypeKeyword::Typename, + {/*NNS=*/nullptr, DTN.getName(), /*HasTemplateKeyword=*/true}, + DTST->template_arguments(), /*IsCanonical=*/true); + assert(NewT.isCanonical()); + NestedNameSpecifier *Prefix = DTN.getQualifier(); + if (!Prefix) + Prefix = getCanonicalNestedNameSpecifier(NNS->getPrefix()); + return NestedNameSpecifier::Create(*this, Prefix, NewT.getTypePtr()); + } + return NestedNameSpecifier::Create(*this, nullptr, T); } case NestedNameSpecifier::Global: @@ -10056,75 +10071,20 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, return TemplateName(QTN); } -/// Retrieve the template name that represents a dependent -/// template name such as \c MetaFun::template apply. -TemplateName -ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, - const IdentifierInfo *Name) const { - assert((!NNS || NNS->isDependent()) && - "Nested name specifier must be dependent"); - - llvm::FoldingSetNodeID ID; - DependentTemplateName::Profile(ID, NNS, Name); - - void *InsertPos = nullptr; - DependentTemplateName *QTN = - DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); - - if (QTN) - return TemplateName(QTN); - - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - if (CanonNNS == NNS) { - QTN = new (*this, alignof(DependentTemplateName)) - DependentTemplateName(NNS, Name); - } else { - TemplateName Canon = getDependentTemplateName(CanonNNS, Name); - QTN = new (*this, alignof(DependentTemplateName)) - DependentTemplateName(NNS, Name, Canon); - DependentTemplateName *CheckQTN = - DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); - assert(!CheckQTN && "Dependent type name canonicalization broken"); - (void)CheckQTN; - } - - DependentTemplateNames.InsertNode(QTN, InsertPos); - return TemplateName(QTN); -} - /// Retrieve the template name that represents a dependent /// template name such as \c MetaFun::template operator+. TemplateName -ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, - OverloadedOperatorKind Operator) const { - assert((!NNS || NNS->isDependent()) && - "Nested name specifier must be dependent"); - +ASTContext::getDependentTemplateName(const DependentTemplateStorage &S) const { llvm::FoldingSetNodeID ID; - DependentTemplateName::Profile(ID, NNS, Operator); + S.Profile(ID); void *InsertPos = nullptr; - DependentTemplateName *QTN - = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); - - if (QTN) + if (DependentTemplateName *QTN = + DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos)) return TemplateName(QTN); - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - if (CanonNNS == NNS) { - QTN = new (*this, alignof(DependentTemplateName)) - DependentTemplateName(NNS, Operator); - } else { - TemplateName Canon = getDependentTemplateName(CanonNNS, Operator); - QTN = new (*this, alignof(DependentTemplateName)) - DependentTemplateName(NNS, Operator, Canon); - - DependentTemplateName *CheckQTN - = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); - assert(!CheckQTN && "Dependent template name canonicalization broken"); - (void)CheckQTN; - } - + DependentTemplateName *QTN = + new (*this, alignof(DependentTemplateName)) DependentTemplateName(S); DependentTemplateNames.InsertNode(QTN, InsertPos); return TemplateName(QTN); } @@ -13543,19 +13503,12 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx, R = NestedNameSpecifier::Create(Ctx, P, ::getCommonDeclChecked(N1, N2)); break; } - case NestedNameSpecifier::SpecifierKind::TypeSpec: - case NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate: { + case NestedNameSpecifier::SpecifierKind::TypeSpec: { // FIXME: See comment below, on Super case. if (K2 == NestedNameSpecifier::SpecifierKind::Super) return Ctx.getCanonicalNestedNameSpecifier(NNS1); - assert(K2 == NestedNameSpecifier::SpecifierKind::TypeSpec || - K2 == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate); - - // Only keep the template keyword if both sides have it. - bool Template = - K1 == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate && - K2 == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate; + assert(K2 == NestedNameSpecifier::SpecifierKind::TypeSpec); const Type *T1 = NNS1->getAsType(), *T2 = NNS2->getAsType(); if (T1 == T2) { @@ -13569,13 +13522,12 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx, bool IsSame = isa(T1); NestedNameSpecifier *P = ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(), IsSame); - R = NestedNameSpecifier::Create(Ctx, P, Template, T1); + R = NestedNameSpecifier::Create(Ctx, P, T1); break; } // TODO: Try to salvage the original prefix. // If getCommonSugaredType removed any top level sugar, the original prefix // is not applicable anymore. - NestedNameSpecifier *P = nullptr; const Type *T = Ctx.getCommonSugaredType(QualType(T1, 0), QualType(T2, 0), /*Unqualified=*/true) .getTypePtr(); @@ -13585,7 +13537,7 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx, case Type::Elaborated: { // An ElaboratedType is stripped off, it's Qualifier becomes the prefix. auto *ET = cast(T); - R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(), Template, + R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(), ET->getNamedType().getTypePtr()); break; } @@ -13600,16 +13552,17 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx, // A DependentTemplateSpecializationType loses it's Qualifier, which // is turned into the prefix. auto *DTST = cast(T); - T = Ctx.getDependentTemplateSpecializationType( - DTST->getKeyword(), /*NNS=*/nullptr, DTST->getIdentifier(), - DTST->template_arguments()) + const DependentTemplateStorage &DTN = DTST->getDependentTemplateName(); + DependentTemplateStorage NewDTN(/*Qualifier=*/nullptr, DTN.getName(), + DTN.hasTemplateKeyword()); + T = Ctx.getDependentTemplateSpecializationType(DTST->getKeyword(), NewDTN, + DTST->template_arguments()) .getTypePtr(); - P = DTST->getQualifier(); - R = NestedNameSpecifier::Create(Ctx, DTST->getQualifier(), Template, T); + R = NestedNameSpecifier::Create(Ctx, DTN.getQualifier(), T); break; } default: - R = NestedNameSpecifier::Create(Ctx, P, Template, T); + R = NestedNameSpecifier::Create(Ctx, /*Prefix=*/nullptr, T); break; } break; @@ -14052,19 +14005,22 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, assert(NX->getIdentifier() == NY->getIdentifier()); return Ctx.getDependentNameType( getCommonTypeKeyword(NX, NY), - getCommonQualifier(Ctx, NX, NY, /*IsSame=*/true), NX->getIdentifier(), - NX->getCanonicalTypeInternal()); + getCommonQualifier(Ctx, NX, NY, /*IsSame=*/true), NX->getIdentifier()); } case Type::DependentTemplateSpecialization: { const auto *TX = cast(X), *TY = cast(Y); - assert(TX->getIdentifier() == TY->getIdentifier()); auto As = getCommonTemplateArguments(Ctx, TX->template_arguments(), TY->template_arguments()); + const DependentTemplateStorage &SX = TX->getDependentTemplateName(), + &SY = TY->getDependentTemplateName(); + assert(SX.getName() == SY.getName()); + DependentTemplateStorage Name( + getCommonNNS(Ctx, SX.getQualifier(), SY.getQualifier(), + /*IsSame=*/true), + SX.getName(), SX.hasTemplateKeyword() || SY.hasTemplateKeyword()); return Ctx.getDependentTemplateSpecializationType( - getCommonTypeKeyword(TX, TY), - getCommonQualifier(Ctx, TX, TY, /*IsSame=*/true), TX->getIdentifier(), - As); + getCommonTypeKeyword(TX, TY), Name, As); } case Type::UnaryTransform: { const auto *TX = cast(X), diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 1db30b3f3f76f..9a84e402e3d69 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1707,11 +1707,10 @@ ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) { ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType *T) { - auto ToQualifierOrErr = import(T->getQualifier()); - if (!ToQualifierOrErr) - return ToQualifierOrErr.takeError(); - - IdentifierInfo *ToName = Importer.Import(T->getIdentifier()); + const DependentTemplateStorage &DTN = T->getDependentTemplateName(); + auto QualifierOrErr = import(DTN.getQualifier()); + if (!QualifierOrErr) + return QualifierOrErr.takeError(); SmallVector ToPack; ToPack.reserve(T->template_arguments().size()); @@ -1719,7 +1718,10 @@ ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType( return std::move(Err); return Importer.getToContext().getDependentTemplateSpecializationType( - T->getKeyword(), *ToQualifierOrErr, ToName, ToPack); + T->getKeyword(), + {*QualifierOrErr, Importer.Import(DTN.getName()), + DTN.hasTemplateKeyword()}, + ToPack); } ExpectedType @@ -1729,18 +1731,8 @@ ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) { return ToQualifierOrErr.takeError(); IdentifierInfo *Name = Importer.Import(T->getIdentifier()); - - QualType Canon; - if (T != T->getCanonicalTypeInternal().getTypePtr()) { - if (ExpectedType TyOrErr = import(T->getCanonicalTypeInternal())) - Canon = (*TyOrErr).getCanonicalType(); - else - return TyOrErr.takeError(); - } - return Importer.getToContext().getDependentNameType(T->getKeyword(), - *ToQualifierOrErr, - Name, Canon); + *ToQualifierOrErr, Name); } ExpectedType @@ -9788,12 +9780,8 @@ ASTImporter::Import(NestedNameSpecifier *FromNNS) { return RDOrErr.takeError(); case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: if (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) { - bool TSTemplate = - FromNNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate; - return NestedNameSpecifier::Create(ToContext, Prefix, TSTemplate, - *TyOrErr); + return NestedNameSpecifier::Create(ToContext, Prefix, *TyOrErr); } else { return TyOrErr.takeError(); } @@ -9851,21 +9839,13 @@ ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { ToLocalBeginLoc, ToLocalEndLoc); break; - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { + case NestedNameSpecifier::TypeSpec: { SourceLocation ToTLoc; if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc())) return std::move(Err); TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo( - QualType(Spec->getAsType(), 0), ToTLoc); - if (Kind == NestedNameSpecifier::TypeSpecWithTemplate) - // ToLocalBeginLoc is here the location of the 'template' keyword. - Builder.Extend(getToContext(), ToLocalBeginLoc, TSI->getTypeLoc(), - ToLocalEndLoc); - else - // No location for 'template' keyword here. - Builder.Extend(getToContext(), SourceLocation{}, TSI->getTypeLoc(), - ToLocalEndLoc); + QualType(Spec->getAsType(), 0), ToTLoc); + Builder.Extend(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc); break; } @@ -9934,14 +9914,8 @@ Expected ASTImporter::Import(TemplateName From) { auto QualifierOrErr = Import(DTN->getQualifier()); if (!QualifierOrErr) return QualifierOrErr.takeError(); - - if (DTN->isIdentifier()) { - return ToContext.getDependentTemplateName(*QualifierOrErr, - Import(DTN->getIdentifier())); - } - - return ToContext.getDependentTemplateName(*QualifierOrErr, - DTN->getOperator()); + return ToContext.getDependentTemplateName( + {*QualifierOrErr, Import(DTN->getName()), DTN->hasTemplateKeyword()}); } case TemplateName::SubstTemplateTemplateParm: { @@ -10312,6 +10286,13 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { return ToId; } +IdentifierOrOverloadedOperator +ASTImporter::Import(IdentifierOrOverloadedOperator FromIO) { + if (const IdentifierInfo *FromII = FromIO.getIdentifier()) + return Import(FromII); + return FromIO.getOperator(); +} + Expected ASTImporter::Import(Selector FromSel) { if (FromSel.isNull()) return Selector{}; diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index a4349bdaaf682..c769722521d9c 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -566,7 +566,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(), NNS2->getAsNamespaceAlias()); case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0), QualType(NNS2->getAsType(), 0)); case NestedNameSpecifier::Global: @@ -578,6 +577,19 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + const DependentTemplateStorage &S1, + const DependentTemplateStorage &S2) { + if (!IsStructurallyEquivalent(Context, S1.getQualifier(), S2.getQualifier())) + return false; + + IdentifierOrOverloadedOperator IO1 = S1.getName(), IO2 = S2.getName(); + const IdentifierInfo *II1 = IO1.getIdentifier(), *II2 = IO2.getIdentifier(); + if (!II1 || !II2) + return IO1.getOperator() == IO2.getOperator(); + return IsStructurallyEquivalent(II1, II2); +} + static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, const TemplateName &N1, const TemplateName &N2) { @@ -614,19 +626,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return TN1->getDeclName() == TN2->getDeclName(); } - case TemplateName::DependentTemplate: { - DependentTemplateName *DN1 = N1.getAsDependentTemplateName(), - *DN2 = N2.getAsDependentTemplateName(); - if (!IsStructurallyEquivalent(Context, DN1->getQualifier(), - DN2->getQualifier())) - return false; - if (DN1->isIdentifier() && DN2->isIdentifier()) - return IsStructurallyEquivalent(DN1->getIdentifier(), - DN2->getIdentifier()); - else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator()) - return DN1->getOperator() == DN2->getOperator(); - return false; - } + case TemplateName::DependentTemplate: + return IsStructurallyEquivalent(Context, *N1.getAsDependentTemplateName(), + *N2.getAsDependentTemplateName()); case TemplateName::SubstTemplateTemplateParmPack: { SubstTemplateTemplateParmPackStorage @@ -1315,11 +1317,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::DependentTemplateSpecialization: { const auto *Spec1 = cast(T1); const auto *Spec2 = cast(T2); - if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(), - Spec2->getQualifier())) + if (Spec1->getKeyword() != Spec2->getKeyword()) return false; - if (!IsStructurallyEquivalent(Spec1->getIdentifier(), - Spec2->getIdentifier())) + if (!IsStructurallyEquivalent(Context, Spec1->getDependentTemplateName(), + Spec2->getDependentTemplateName())) return false; if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(), Spec2->template_arguments())) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 49a04861ae25d..b81981606866a 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1327,7 +1327,7 @@ void CXXNameMangler::manglePrefix(QualType type) { type->getAs()) { if (!mangleSubstitution(QualType(DTST, 0))) { TemplateName Template = getASTContext().getDependentTemplateName( - DTST->getQualifier(), DTST->getIdentifier()); + DTST->getDependentTemplateName()); mangleTemplatePrefix(Template); // FIXME: GCC does not appear to mangle the template arguments when @@ -1395,8 +1395,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, mangleSourceNameWithAbiTags(qualifier->getAsNamespaceAlias()); break; - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { + case NestedNameSpecifier::TypeSpec: { const Type *type = qualifier->getAsType(); // We only want to use an unresolved-type encoding if this is one of: @@ -2181,7 +2180,17 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { return; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: + if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) { + const auto *DTST = + cast(qualifier->getAsType()); + QualType NewT = getASTContext().getDependentTemplateSpecializationType( + DTST->getKeyword(), + {Prefix, DTST->getDependentTemplateName().getName(), + /*HasTemplateKeyword=*/true}, + DTST->template_arguments(), /*IsCanonical=*/true); + manglePrefix(NewT); + return; + } manglePrefix(QualType(qualifier->getAsType(), 0)); return; @@ -2265,10 +2274,11 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { if (Clang11Compat && mangleSubstitution(Template)) return; - if (const IdentifierInfo *Id = Dependent->getIdentifier()) + if (IdentifierOrOverloadedOperator Name = Dependent->getName(); + const IdentifierInfo *Id = Name.getIdentifier()) mangleSourceName(Id); else - mangleOperatorName(Dependent->getOperator(), UnknownArity); + mangleOperatorName(Name.getOperator(), UnknownArity); addSubstitution(Template); } @@ -2376,12 +2386,13 @@ void CXXNameMangler::mangleType(TemplateName TN) { case TemplateName::DependentTemplate: { const DependentTemplateName *Dependent = TN.getAsDependentTemplateName(); - assert(Dependent->isIdentifier()); + const IdentifierInfo *II = Dependent->getName().getIdentifier(); + assert(II); // ::= // ::= mangleUnresolvedPrefix(Dependent->getQualifier()); - mangleSourceName(Dependent->getIdentifier()); + mangleSourceName(II); break; } @@ -2572,8 +2583,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, const DependentTemplateSpecializationType *DTST = cast(Ty); TemplateName Template = getASTContext().getDependentTemplateName( - DTST->getQualifier(), DTST->getIdentifier()); - mangleSourceName(DTST->getIdentifier()); + DTST->getDependentTemplateName()); + mangleTemplatePrefix(Template); mangleTemplateArgs(Template, DTST->template_arguments()); break; } @@ -4481,10 +4492,8 @@ void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) { // Dependently-scoped template types are nested if they have a prefix. Out << 'N'; - // TODO: avoid making this TemplateName. TemplateName Prefix = - getASTContext().getDependentTemplateName(T->getQualifier(), - T->getIdentifier()); + getASTContext().getDependentTemplateName(T->getDependentTemplateName()); mangleTemplatePrefix(Prefix); // FIXME: GCC does not appear to mangle the template arguments when diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index d3195e6487f0b..51aa2d69d0f0d 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -98,14 +98,13 @@ NestedNameSpecifier::Create(const ASTContext &Context, return FindOrInsert(Context, Mockup); } -NestedNameSpecifier * -NestedNameSpecifier::Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - bool Template, const Type *T) { +NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context, + NestedNameSpecifier *Prefix, + const Type *T) { assert(T && "Type cannot be NULL"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); + Mockup.Prefix.setInt(StoredTypeSpec); Mockup.Specifier = const_cast(T); return FindOrInsert(Context, Mockup); } @@ -155,9 +154,6 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { case StoredTypeSpec: return TypeSpec; - - case StoredTypeSpecWithTemplate: - return TypeSpecWithTemplate; } llvm_unreachable("Invalid NNS Kind!"); @@ -189,7 +185,6 @@ CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { return dyn_cast(static_cast(Specifier)); case StoredTypeSpec: - case StoredTypeSpecWithTemplate: return getAsType()->getAsCXXRecordDecl(); } @@ -222,9 +217,13 @@ NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const { return NestedNameSpecifierDependence::None; } - case TypeSpec: - case TypeSpecWithTemplate: - return toNestedNameSpecifierDependendence(getAsType()->getDependence()); + case TypeSpec: { + NestedNameSpecifierDependence Dep = + toNestedNameSpecifierDependendence(getAsType()->getDependence()); + if (NestedNameSpecifier *Prefix = getPrefix()) + Dep |= Prefix->getDependence(); + return Dep; + } } llvm_unreachable("Invalid NNS Kind!"); } @@ -254,17 +253,17 @@ NestedNameSpecifier::translateToType(const ASTContext &Context) const { .getDependentNameType(ElaboratedTypeKeyword::None, Prefix, getAsIdentifier()) .getTypePtr(); - case SpecifierKind::TypeSpec: - case SpecifierKind::TypeSpecWithTemplate: { + case SpecifierKind::TypeSpec: { const Type *T = getAsType(); switch (T->getTypeClass()) { case Type::DependentTemplateSpecialization: { const auto *DT = cast(T); - // FIXME: The type node can't represent the template keyword. + const DependentTemplateStorage &DTN = DT->getDependentTemplateName(); return Context - .getDependentTemplateSpecializationType(ElaboratedTypeKeyword::None, - Prefix, DT->getIdentifier(), - DT->template_arguments()) + .getDependentTemplateSpecializationType( + ElaboratedTypeKeyword::None, + {Prefix, DTN.getName(), DTN.hasTemplateKeyword()}, + DT->template_arguments()) .getTypePtr(); } case Type::Record: @@ -324,59 +323,11 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, OS << "__super"; break; - case TypeSpecWithTemplate: - OS << "template "; - // Fall through to print the type. - [[fallthrough]]; - case TypeSpec: { - const auto *Record = - dyn_cast_or_null(getAsRecordDecl()); - if (ResolveTemplateArguments && Record) { - // Print the type trait with resolved template parameters. - Record->printName(OS, Policy); - printTemplateArgumentList( - OS, Record->getTemplateArgs().asArray(), Policy, - Record->getSpecializedTemplate()->getTemplateParameters()); - break; - } - const Type *T = getAsType(); - PrintingPolicy InnerPolicy(Policy); InnerPolicy.SuppressScope = true; InnerPolicy.SuppressTagKeyword = true; - - // Nested-name-specifiers are intended to contain minimally-qualified - // types. An actual ElaboratedType will not occur, since we'll store - // just the type that is referred to in the nested-name-specifier (e.g., - // a TypedefType, TagType, etc.). However, when we are dealing with - // dependent template-id types (e.g., Outer::template Inner), - // the type requires its own nested-name-specifier for uniqueness, so we - // suppress that nested-name-specifier during printing. - assert(!isa(T) && - "Elaborated type in nested-name-specifier"); - if (const TemplateSpecializationType *SpecType - = dyn_cast(T)) { - // Print the template name without its corresponding - // nested-name-specifier. - SpecType->getTemplateName().print(OS, InnerPolicy, - TemplateName::Qualified::None); - - // Print the template argument list. - printTemplateArgumentList(OS, SpecType->template_arguments(), - InnerPolicy); - } else if (const auto *DepSpecType = - dyn_cast(T)) { - // Print the template name without its corresponding - // nested-name-specifier. - OS << DepSpecType->getIdentifier()->getName(); - // Print the template argument list. - printTemplateArgumentList(OS, DepSpecType->template_arguments(), - InnerPolicy); - } else { - // Print the type normally - QualType(T, 0).print(OS, InnerPolicy); - } + QualType(getAsType(), 0).print(OS, InnerPolicy); break; } } @@ -421,7 +372,6 @@ NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { Length += sizeof(SourceLocation::UIntTy); break; - case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: // The "void*" that points at the TypeLoc data. // Note: the 'template' keyword is part of the TypeLoc. @@ -485,7 +435,6 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { LoadSourceLocation(Data, Offset), LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy))); - case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: { // The "void*" that points at the TypeLoc data. // Note: the 'template' keyword is part of the TypeLoc. @@ -500,8 +449,7 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { } TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { - if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec && - Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate) + if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec) return TypeLoc(); // The "void*" that points at the TypeLoc data. @@ -609,13 +557,10 @@ operator=(const NestedNameSpecifierLocBuilder &Other) { return *this; } -void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, - SourceLocation TemplateKWLoc, - TypeLoc TL, +void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc) { - Representation = NestedNameSpecifier::Create(Context, Representation, - TemplateKWLoc.isValid(), - TL.getTypePtr()); + Representation = + NestedNameSpecifier::Create(Context, Representation, TL.getTypePtr()); // Push source-location info into the buffer. SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); @@ -697,8 +642,7 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); break; - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { + case NestedNameSpecifier::TypeSpec: { TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), R.getBegin()); diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 4c428cce32475..f8446dfbc6859 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -128,7 +128,6 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { AddDecl(NNS->getAsNamespaceAlias()); break; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: AddType(NNS->getAsType()); break; case NestedNameSpecifier::Global: @@ -137,6 +136,16 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { } } +void ODRHash::AddDependentTemplateName(const DependentTemplateStorage &Name) { + if (NestedNameSpecifier *NNS = Name.getQualifier()) + AddNestedNameSpecifier(NNS); + if (IdentifierOrOverloadedOperator IO = Name.getName(); + const IdentifierInfo *II = IO.getIdentifier()) + AddIdentifierInfo(II); + else + ID.AddInteger(IO.getOperator()); +} + void ODRHash::AddTemplateName(TemplateName Name) { auto Kind = Name.getKind(); ID.AddInteger(Kind); @@ -153,10 +162,13 @@ void ODRHash::AddTemplateName(TemplateName Name) { AddTemplateName(QTN->getUnderlyingTemplate()); break; } + case TemplateName::DependentTemplate: { + AddDependentTemplateName(*Name.getAsDependentTemplateName()); + break; + } // TODO: Support these cases. case TemplateName::OverloadedTemplate: case TemplateName::AssumedTemplate: - case TemplateName::DependentTemplate: case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: case TemplateName::UsingTemplate: @@ -1221,8 +1233,7 @@ class ODRTypeVisitor : public TypeVisitor { void VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType *T) { - AddIdentifierInfo(T->getIdentifier()); - AddNestedNameSpecifier(T->getQualifier()); + Hash.AddDependentTemplateName(T->getDependentTemplateName()); ID.AddInteger(T->template_arguments().size()); for (const auto &TA : T->template_arguments()) { Hash.AddTemplateArgument(TA); diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 3c814b777f8ab..d8ab1092d3ea4 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -212,6 +212,7 @@ static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( bool WithGlobalNsPrefix) { switch (Scope->getKind()) { case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: // Already fully qualified return Scope; case NestedNameSpecifier::Namespace: @@ -232,9 +233,7 @@ static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( // but use the name of it's prefix. return getFullyQualifiedNestedNameSpecifier( Ctx, Scope->getPrefix(), WithGlobalNsPrefix); - case NestedNameSpecifier::Super: - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { + case NestedNameSpecifier::TypeSpec: { const Type *Type = Scope->getAsType(); // Find decl context. const TagDecl *TD = nullptr; @@ -366,8 +365,7 @@ NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, } return NestedNameSpecifier::Create( - Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), - false /*No TemplateKeyword*/, TypePtr); + Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), TypePtr); } /// Return the fully qualified type, including fully-qualified diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index 9e0a7dc2b8cdc..031b58123fc99 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -122,6 +122,31 @@ void SubstTemplateTemplateParmPackStorage::Profile( ID.AddBoolean(Final); } +IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator( + const IdentifierInfo *II) + : PtrOrOp(reinterpret_cast(II)) { + static_assert(NUM_OVERLOADED_OPERATORS <= 4096, + "NUM_OVERLOADED_OPERATORS is too large"); + assert(II); + assert(getIdentifier() == II); +} +IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator( + OverloadedOperatorKind OOK) + : PtrOrOp(-uintptr_t(OOK)) { + assert(OOK != OO_None); + assert(getOperator() == OOK); +} + +void IdentifierOrOverloadedOperator::Profile(llvm::FoldingSetNodeID &ID) const { + if (auto *Identifier = getIdentifier()) { + ID.AddBoolean(false); + ID.AddPointer(Identifier); + } else { + ID.AddBoolean(true); + ID.AddInteger(getOperator()); + } +} + TemplateName::TemplateName(void *Ptr) { Storage = StorageType::getFromOpaqueValue(Ptr); } @@ -275,6 +300,36 @@ UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { return nullptr; } +DependentTemplateStorage::DependentTemplateStorage( + NestedNameSpecifier *Qualifier, IdentifierOrOverloadedOperator Name, + bool HasTemplateKeyword) + : Qualifier(Qualifier, HasTemplateKeyword), Name(Name) { + assert((!Qualifier || Qualifier->isDependent()) && + "Qualifier must be dependent"); +} + +TemplateNameDependence DependentTemplateStorage::getDependence() const { + auto D = TemplateNameDependence::DependentInstantiation; + if (NestedNameSpecifier *Qualifier = getQualifier()) + D |= toTemplateNameDependence(Qualifier->getDependence()); + return D; +} + +void DependentTemplateStorage::print(raw_ostream &OS, + const PrintingPolicy &Policy) const { + if (NestedNameSpecifier *NNS = getQualifier()) + NNS->print(OS, Policy); + + if (hasTemplateKeyword()) + OS << "template "; + + IdentifierOrOverloadedOperator Name = getName(); + if (const IdentifierInfo *II = Name.getIdentifier()) + OS << II->getName(); + else + OS << "operator " << getOperatorSpelling(Name.getOperator()); +} + DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const { if (UncommonTemplateNameStorage *Uncommon = dyn_cast_if_present(Storage)) @@ -313,7 +368,8 @@ TemplateNameDependence TemplateName::getDependence() const { case NameKind::DependentTemplate: { DependentTemplateName *S = getAsDependentTemplateName(); auto D = TemplateNameDependence::DependentInstantiation; - D |= toTemplateNameDependence(S->getQualifier()->getDependence()); + if (NestedNameSpecifier *Qualifier = S->getQualifier()) + D |= toTemplateNameDependence(Qualifier->getDependence()); return D; } case NameKind::SubstTemplateTemplateParm: { @@ -401,14 +457,7 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, else OS << *UTD; } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { - if (NestedNameSpecifier *NNS = DTN->getQualifier()) - NNS->print(OS, Policy); - OS << "template "; - - if (DTN->isIdentifier()) - OS << DTN->getIdentifier()->getName(); - else - OS << "operator " << getOperatorSpelling(DTN->getOperator()); + DTN->print(OS, Policy); } else if (SubstTemplateTemplateParmStorage *subst = getAsSubstTemplateTemplateParm()) { subst->getReplacement().print(OS, Policy, Qual); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index f18cf703bdaa6..1fe6f2c722acf 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1027,10 +1027,6 @@ void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *N OS << " TypeSpec"; dumpType(QualType(NNS->getAsType(), 0)); break; - case NestedNameSpecifier::TypeSpecWithTemplate: - OS << " TypeSpecWithTemplate"; - dumpType(QualType(NNS->getAsType(), 0)); - break; case NestedNameSpecifier::Global: OS << " Global"; break; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 08798219c0b83..9fda02b430e48 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3270,16 +3270,13 @@ StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { } DependentTemplateSpecializationType::DependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const IdentifierInfo *Name, ArrayRef Args, QualType Canon) + ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name, + ArrayRef Args, QualType Canon) : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, - TypeDependence::DependentInstantiation | - (NNS ? toTypeDependence(NNS->getDependence()) - : TypeDependence::None)), - NNS(NNS), Name(Name) { + + toTypeDependence(Name.getDependence())), + Name(Name) { DependentTemplateSpecializationTypeBits.NumArgs = Args.size(); - assert((!NNS || NNS->isDependent()) && - "DependentTemplateSpecializatonType requires dependent qualifier"); auto *ArgBuffer = const_cast(template_arguments().data()); for (const TemplateArgument &Arg : Args) { addDependence(toTypeDependence(Arg.getDependence() & @@ -3289,16 +3286,12 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType( } } -void -DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, - const ASTContext &Context, - ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *Qualifier, - const IdentifierInfo *Name, - ArrayRef Args) { +void DependentTemplateSpecializationType::Profile( + llvm::FoldingSetNodeID &ID, const ASTContext &Context, + ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name, + ArrayRef Args) { ID.AddInteger(llvm::to_underlying(Keyword)); - ID.AddPointer(Qualifier); - ID.AddPointer(Name); + Name.Profile(ID); for (const TemplateArgument &Arg : Args) Arg.Profile(ID, Context); } diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index fbb7fc5cd7690..24726901b8f55 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -569,9 +569,10 @@ void DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setElaboratedKeywordLoc(Loc); - if (getTypePtr()->getQualifier()) { + if (NestedNameSpecifier *Qualifier = + getTypePtr()->getDependentTemplateName().getQualifier()) { NestedNameSpecifierLocBuilder Builder; - Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); + Builder.MakeTrivial(Context, Qualifier, Loc); setQualifierLoc(Builder.getWithLocInContext(Context)); } else { setQualifierLoc(NestedNameSpecifierLoc()); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 3982ca3b50604..4ec252e3f89b5 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1793,9 +1793,7 @@ void TypePrinter::printDependentTemplateSpecializationBefore( if (T->getKeyword() != ElaboratedTypeKeyword::None) OS << " "; - if (T->getQualifier()) - T->getQualifier()->print(OS, Policy); - OS << "template " << T->getIdentifier()->getName(); + T->getDependentTemplateName().print(OS, Policy); printTemplateArgumentList(OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); } @@ -2498,14 +2496,18 @@ void clang::printTemplateArgumentList(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL) { - printTo(OS, Args, Policy, TPL, /*isPack*/ false, /*parmIndex*/ 0); + PrintingPolicy InnerPolicy = Policy; + InnerPolicy.SuppressScope = false; + printTo(OS, Args, InnerPolicy, TPL, /*isPack*/ false, /*parmIndex*/ 0); } void clang::printTemplateArgumentList(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL) { - printTo(OS, Args, Policy, TPL, /*isPack*/ false, /*parmIndex*/ 0); + PrintingPolicy InnerPolicy = Policy; + InnerPolicy.SuppressScope = false; + printTo(OS, Args, InnerPolicy, TPL, /*isPack*/ false, /*parmIndex*/ 0); } std::string Qualifiers::getAsString() const { diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 480e33f607bb0..d7eebcbc3c2f9 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -249,13 +249,6 @@ DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); break; - case NestedNameSpecifier::TypeSpecWithTemplate: - // A type prefixed by the `template` keyword. - Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); - Fragments.appendSpace(); - // Fallthrough after adding the keyword to handle the actual type. - [[fallthrough]]; - case NestedNameSpecifier::TypeSpec: { const Type *T = NNS->getAsType(); // FIXME: Handle C++ template specialization type diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp index d5d0a3c422871..98b5513128fbe 100644 --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -277,7 +277,6 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, break; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: indexTypeLoc(NNS.getTypeLoc(), Parent, DC); break; } diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 26be78ee8ca15..941e681247de1 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -587,12 +587,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier( << II.getName() << FixItHint::CreateInsertion(Tok.getLocation(), "template "); } - - SourceLocation TemplateNameLoc = ConsumeToken(); + ConsumeToken(); TemplateNameKind TNK = Actions.ActOnTemplateName( - getCurScope(), SS, TemplateNameLoc, TemplateName, ObjectType, - EnteringContext, Template, /*AllowInjectedClassName*/ true); + getCurScope(), SS, /*TemplateKWLoc=*/SourceLocation(), TemplateName, + ObjectType, EnteringContext, Template, + /*AllowInjectedClassName=*/true); if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), TemplateName, false)) return true; diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 95e14ca0fa3b7..ee5a862c32509 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -48,9 +48,9 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { EndLocation = TemplateId->RAngleLoc; } -void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, - TypeLoc TL, SourceLocation ColonColonLoc) { - Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc); +void CXXScopeSpec::Extend(ASTContext &Context, TypeLoc TL, + SourceLocation ColonColonLoc) { + Builder.Extend(Context, TL, ColonColonLoc); if (Range.getBegin().isInvalid()) Range.setBegin(TL.getBeginLoc()); Range.setEnd(ColonColonLoc); diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp index 4544d75ea73c4..f6ee000a58f4b 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -365,9 +365,10 @@ HeuristicResolverImpl::resolveDependentNameType(const DependentNameType *DNT) { std::vector HeuristicResolverImpl::resolveTemplateSpecializationType( const DependentTemplateSpecializationType *DTST) { + const DependentTemplateStorage &DTN = DTST->getDependentTemplateName(); return resolveDependentMember( - resolveNestedNameSpecifierToType(DTST->getQualifier()), - DTST->getIdentifier(), TemplateFilter); + resolveNestedNameSpecifierToType(DTN.getQualifier()), + DTN.getName().getIdentifier(), TemplateFilter); } std::vector @@ -409,7 +410,6 @@ QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType( // the TypeSpec cases too. switch (NNS->getKind()) { case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: return QualType(NNS->getAsType(), 0); case NestedNameSpecifier::Identifier: { return resolveDeclsToType( diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index f04f7f9929442..545da5c295832 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -145,8 +145,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, case NestedNameSpecifier::NamespaceAlias: return NNS->getAsNamespaceAlias()->getNamespace(); - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { + case NestedNameSpecifier::TypeSpec: { const TagType *Tag = NNS->getAsType()->getAs(); assert(Tag && "Non-tag type in nested-name-specifier"); return Tag->getDecl(); @@ -687,8 +686,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); } - SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), - IdInfo.CCLoc); + SS.Extend(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc); return false; } @@ -735,8 +733,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, QualType T = Context.getTypeDeclType(ContainingClass); TypeLocBuilder TLB; TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); - SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), - TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); + SS.Extend(Context, TLB.getTypeLocInContext(Context, T), + IdInfo.IdentifierLoc); // Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); @@ -804,8 +802,7 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, DecltypeTypeLoc DecltypeTL = TLB.push(T); DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd()); - SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), - ColonColonLoc); + SS.Extend(Context, TLB.getTypeLocInContext(Context, T), ColonColonLoc); return false; } @@ -827,8 +824,7 @@ bool Sema::ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS, DS.getBeginLoc()); PackIndexingTypeLoc PIT = TLB.push(Type); PIT.setEllipsisLoc(DS.getEllipsisLoc()); - SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, Type), - ColonColonLoc); + SS.Extend(Context, TLB.getTypeLocInContext(Context, Type), ColonColonLoc); return false; } @@ -862,12 +858,14 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, translateTemplateArguments(TemplateArgsIn, TemplateArgs); DependentTemplateName *DTN = Template.getAsDependentTemplateName(); - if (DTN && DTN->isIdentifier()) { + if (DTN && DTN->getName().getIdentifier()) { // Handle a dependent template specialization for which we cannot resolve // the template name. assert(DTN->getQualifier() == SS.getScopeRep()); QualType T = Context.getDependentTemplateSpecializationType( - ElaboratedTypeKeyword::None, DTN->getQualifier(), DTN->getIdentifier(), + ElaboratedTypeKeyword::None, + {/*Qualifier=*/nullptr, DTN->getName().getIdentifier(), + TemplateKWLoc.isValid()}, TemplateArgs.arguments()); // Create source-location information for this type. @@ -875,7 +873,6 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, DependentTemplateSpecializationTypeLoc SpecTL = Builder.push(T); SpecTL.setElaboratedKeywordLoc(SourceLocation()); - SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); SpecTL.setTemplateKeywordLoc(TemplateKWLoc); SpecTL.setTemplateNameLoc(TemplateNameLoc); SpecTL.setLAngleLoc(LAngleLoc); @@ -883,8 +880,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T), - CCLoc); + SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc); return false; } @@ -932,9 +928,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - - SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T), - CCLoc); + SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc); return false; } @@ -1007,7 +1001,6 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::Super: // These are never namespace scopes. return true; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 2003701b65654..54cafc2010f09 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -755,7 +755,7 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, Result = NestedNameSpecifier::Create(Context, Result, Namespace); } else if (const auto *TD = dyn_cast(Parent)) Result = NestedNameSpecifier::Create( - Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); + Context, Result, Context.getTypeDeclType(TD).getTypePtr()); } return Result; } @@ -1216,7 +1216,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); else if (const TagDecl *Tag = dyn_cast(Ctx)) R.Qualifier = NestedNameSpecifier::Create( - SemaRef.Context, nullptr, false, + SemaRef.Context, nullptr, SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else R.QualifierIsInformative = false; @@ -1405,7 +1405,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); else if (const auto *Tag = dyn_cast(Ctx)) R.Qualifier = NestedNameSpecifier::Create( - SemaRef.Context, nullptr, false, + SemaRef.Context, nullptr, SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else R.QualifierIsInformative = false; diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 53536b0d14037..6f873cafa98fd 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -116,8 +116,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, auto buildElaboratedType = [&]() { auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace()); - NNS = NestedNameSpecifier::Create(S.Context, NNS, false, - CoroTrait.getTypePtr()); + NNS = NestedNameSpecifier::Create(S.Context, NNS, CoroTrait.getTypePtr()); return S.Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS, PromiseType); }; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5527ed5419fc8..2246f0f1b3121 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -252,8 +252,8 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II; ASTContext &Context = S.Context; - auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false, - cast(Context.getRecordType(RD))); + auto *NNS = NestedNameSpecifier::Create( + Context, nullptr, cast(Context.getRecordType(RD))); QualType T = Context.getDependentNameType(ElaboratedTypeKeyword::Typename, NNS, &II); @@ -580,10 +580,10 @@ synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) { auto *ND = dyn_cast(DC); if (ND && !ND->isInline() && !ND->isAnonymousNamespace()) return NestedNameSpecifier::Create(Context, nullptr, ND); - else if (auto *RD = dyn_cast(DC)) - return NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(), + if (auto *RD = dyn_cast(DC)) + return NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl()); - else if (isa(DC)) + if (isa(DC)) return NestedNameSpecifier::GlobalSpecifier(Context); } llvm_unreachable("something isn't in TU scope?"); @@ -624,8 +624,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II, findRecordWithDependentBasesOfEnclosingMethod(CurContext)) { // Build a DependentNameType that will perform lookup into RD at // instantiation time. - NNS = NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(), - RD->getTypeForDecl()); + NNS = NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl()); // Diagnose that this identifier was undeclared, and retry the lookup during // template instantiation. @@ -6243,11 +6242,12 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data()); do { - if (SpecLoc.getNestedNameSpecifier()->getKind() == - NestedNameSpecifier::TypeSpecWithTemplate) - Diag(Loc, diag::ext_template_after_declarative_nns) - << FixItHint::CreateRemoval( - SpecLoc.getTypeLoc().getTemplateKeywordLoc()); + if (TypeLoc TL = SpecLoc.getTypeLoc()) { + if (SourceLocation TemplateKeywordLoc = TL.getTemplateKeywordLoc(); + TemplateKeywordLoc.isValid()) + Diag(Loc, diag::ext_template_after_declarative_nns) + << FixItHint::CreateRemoval(TemplateKeywordLoc); + } if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) { if (const auto *TST = T->getAsAdjusted()) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d724e183b69bd..43bf9b7cd0f95 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -14799,8 +14799,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, CXXScopeSpec SS; const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); SS.MakeTrivial(S.Context, - NestedNameSpecifier::Create(S.Context, nullptr, false, - CanonicalT), + NestedNameSpecifier::Create(S.Context, nullptr, CanonicalT), Loc); // Create the reference to operator=. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1c0ef39878d7f..7cc8374e69d73 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2684,7 +2684,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context, // perform name lookup during template instantiation. CXXScopeSpec SS; auto *NNS = - NestedNameSpecifier::Create(Context, nullptr, true, RD->getTypeForDecl()); + NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl()); SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc)); return DependentScopeDeclRefExpr::Create( Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 46895db4a0756..19fd51134d160 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -508,7 +508,6 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, switch (SS.getScopeRep()->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: // Per C++11 [over.literal]p2, literal operators can only be declared at // namespace scope. Therefore, this unqualified-id cannot name anything. // Reject it early, because we have no AST representation for this in the diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 876340010cf5f..a77ca779a9ee3 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -4530,7 +4530,6 @@ static void getNestedNameSpecifierIdentifiers( II = NNS->getAsNamespaceAlias()->getIdentifier(); break; - case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier(); break; @@ -4895,8 +4894,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier( NNS = NestedNameSpecifier::Create(Context, NNS, ND); ++NumSpecifiers; } else if (auto *RD = dyn_cast_or_null(C)) { - NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(), - RD->getTypeForDecl()); + NNS = NestedNameSpecifier::Create(Context, NNS, RD->getTypeForDecl()); ++NumSpecifiers; } } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index be81b6a46b2c0..de2b1fdbc44e2 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -364,8 +364,8 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, // The code is missing a 'template' keyword prior to the dependent template // name. NestedNameSpecifier *Qualifier = (NestedNameSpecifier *)SS->getScopeRep(); - SuggestedTemplate - = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II)); + SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName( + {Qualifier, &II, /*HasTemplateKeyword=*/false})); Diag(IILoc, diag::err_template_kw_missing) << SuggestedTemplate.get() << FixItHint::CreateInsertion(IILoc, "template "); @@ -2777,7 +2777,8 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( // Look one step prior in a dependent template specialization type. if (const DependentTemplateSpecializationType *DependentTST = T->getAs()) { - if (NestedNameSpecifier *NNS = DependentTST->getQualifier()) + if (NestedNameSpecifier *NNS = + DependentTST->getDependentTemplateName().getQualifier()) T = QualType(NNS->getAsType(), 0); else T = QualType(); @@ -3480,16 +3481,17 @@ Sema::findFailedBooleanCondition(Expr *Cond) { QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { - DependentTemplateName *DTN = - Name.getUnderlying().getAsDependentTemplateName(); - if (DTN && DTN->isIdentifier()) + // FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias + // template substitutions. + if (DependentTemplateName *DTN = + Name.getUnderlying().getAsDependentTemplateName(); + DTN && DTN->getName().getIdentifier()) // When building a template-id where the template-name is dependent, // assume the template is a type template. Either our assumption is // correct, or the code is ill-formed and will be diagnosed when the // dependent name is substituted. return Context.getDependentTemplateSpecializationType( - ElaboratedTypeKeyword::None, DTN->getQualifier(), DTN->getIdentifier(), - TemplateArgs.arguments()); + ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments()); if (Name.getAsAssumedTemplateName() && resolveAssumedTemplateNameAsType(/*Scope=*/nullptr, Name, TemplateLoc)) @@ -3824,8 +3826,7 @@ TypeResult Sema::ActOnTemplateIdType( if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { assert(SS.getScopeRep() == DTN->getQualifier()); QualType T = Context.getDependentTemplateSpecializationType( - ElaboratedTypeKeyword::None, DTN->getQualifier(), DTN->getIdentifier(), - TemplateArgs.arguments()); + ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments()); // Build type-source information. TypeLocBuilder TLB; DependentTemplateSpecializationTypeLoc SpecTL @@ -3894,8 +3895,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { assert(SS.getScopeRep() == DTN->getQualifier()); QualType T = Context.getDependentTemplateSpecializationType( - Keyword, DTN->getQualifier(), DTN->getIdentifier(), - TemplateArgs.arguments()); + Keyword, *DTN, TemplateArgs.arguments()); // Build type-source information. TypeLocBuilder TLB; @@ -4812,13 +4812,14 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S, switch (Name.getKind()) { case UnqualifiedIdKind::IK_Identifier: - Result = TemplateTy::make( - Context.getDependentTemplateName(Qualifier, Name.Identifier)); + Result = TemplateTy::make(Context.getDependentTemplateName( + {Qualifier, Name.Identifier, TemplateKWLoc.isValid()})); return TNK_Dependent_template_name; case UnqualifiedIdKind::IK_OperatorFunctionId: Result = TemplateTy::make(Context.getDependentTemplateName( - Qualifier, Name.OperatorFunctionId.Operator)); + {Qualifier, Name.OperatorFunctionId.Operator, + TemplateKWLoc.isValid()})); return TNK_Function_template; case UnqualifiedIdKind::IK_LiteralOperatorId: @@ -5332,7 +5333,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, // know that we need a non-type template argument, convert this // template name into an expression. - DeclarationNameInfo NameInfo(DTN->getIdentifier(), + DeclarationNameInfo NameInfo(DTN->getName().getIdentifier(), ArgLoc.getTemplateNameLoc()); CXXScopeSpec SS; @@ -6071,8 +6072,9 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentNameType( bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType* T) { - if (auto *Q = T->getQualifier()) + if (auto *Q = T->getDependentTemplateName().getQualifier()) return VisitNestedNameSpecifier(Q); + return false; } @@ -6154,7 +6156,6 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( return false; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: return Visit(QualType(NNS->getAsType(), 0)); } llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); @@ -7526,9 +7527,8 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument( isa(VD))); QualType ClassType = Context.getTypeDeclType(cast(VD->getDeclContext())); - NestedNameSpecifier *Qualifier - = NestedNameSpecifier::Create(Context, nullptr, false, - ClassType.getTypePtr()); + NestedNameSpecifier *Qualifier = + NestedNameSpecifier::Create(Context, nullptr, ClassType.getTypePtr()); SS.MakeTrivial(Context, Qualifier, Loc); } @@ -10694,15 +10694,14 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, assert(DTN && "dependent template has non-dependent name?"); assert(DTN->getQualifier() == SS.getScopeRep()); - if (!DTN->isIdentifier()) { + if (!DTN->getName().getIdentifier()) { Diag(TemplateIILoc, diag::err_template_id_not_a_type) << Template; NoteAllFoundTemplates(Template); return true; } QualType T = Context.getDependentTemplateSpecializationType( - ElaboratedTypeKeyword::Typename, DTN->getQualifier(), - DTN->getIdentifier(), TemplateArgs.arguments()); + ElaboratedTypeKeyword::Typename, *DTN, TemplateArgs.arguments()); // Create source-location information for this type. TypeLocBuilder Builder; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 740a7a1513975..b39eb8fd5512e 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -7031,7 +7031,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, const DependentTemplateSpecializationType *Spec = cast(T); - MarkUsedTemplateParameters(Ctx, Spec->getQualifier(), + MarkUsedTemplateParameters(Ctx, + Spec->getDependentTemplateName().getQualifier(), OnlyDeduced, Depth, Used); for (const auto &Arg : Spec->template_arguments()) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8fdb2cf6dce6c..e455b225d7f49 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -705,7 +705,7 @@ class TreeTransform { QualType TransformDependentTemplateSpecializationType( TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL, - NestedNameSpecifierLoc QualifierLoc); + CXXScopeSpec &SS); /// Transforms the parameters of a function type into the /// given vectors. @@ -1132,38 +1132,21 @@ class TreeTransform { /// nested-name-specifier and the given type. Subclasses may override /// this routine to provide different behavior. QualType RebuildDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const IdentifierInfo *Name, - SourceLocation NameLoc, - TemplateArgumentListInfo &Args, - bool AllowInjectedClassName) { - // Rebuild the template name. - // TODO: avoid TemplateName abstraction - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - TemplateName InstName = getDerived().RebuildTemplateName( - SS, TemplateKWLoc, *Name, NameLoc, QualType(), nullptr, - AllowInjectedClassName); - - if (InstName.isNull()) - return QualType(); - + ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + SourceLocation TemplateKWLoc, TemplateName Name, SourceLocation NameLoc, + TemplateArgumentListInfo &Args, bool AllowInjectedClassName) { // If it's still dependent, make a dependent specialization. - if (InstName.getAsDependentTemplateName()) + if (const DependentTemplateStorage *S = Name.getAsDependentTemplateName()) return SemaRef.Context.getDependentTemplateSpecializationType( - Keyword, QualifierLoc.getNestedNameSpecifier(), Name, - Args.arguments()); + Keyword, *S, Args.arguments()); // Otherwise, make an elaborated type wrapping a non-dependent // specialization. QualType T = - getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + getDerived().RebuildTemplateSpecializationType(Name, NameLoc, Args); if (T.isNull()) return QualType(); - return SemaRef.Context.getElaboratedType( - Keyword, QualifierLoc.getNestedNameSpecifier(), T); + return SemaRef.Context.getElaboratedType(Keyword, NNS, T); } /// Build a new typename type that refers to an identifier. @@ -1332,6 +1315,13 @@ class TreeTransform { SourceLocation NameLoc, QualType ObjectType, bool AllowInjectedClassName); + TemplateName RebuildTemplateName(CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + IdentifierOrOverloadedOperator IO, + SourceLocation NameLoc, QualType ObjectType, + NamedDecl *FirstQualifierInScope, + bool AllowInjectedClassName); + /// Build a new template name given a template template parameter pack /// and the /// @@ -4634,7 +4624,6 @@ NestedNameSpecifierLoc TreeTransform::TransformNestedNameSpecifierLoc( break; } - case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: { TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType, FirstQualifierInScope, SS); @@ -4654,8 +4643,7 @@ NestedNameSpecifierLoc TreeTransform::TransformNestedNameSpecifierLoc( TL = ETL.getNamedTypeLoc(); } - SS.Extend(SemaRef.Context, TL.getTemplateKeywordLoc(), TL, - Q.getLocalEndLoc()); + SS.Extend(SemaRef.Context, TL, Q.getLocalEndLoc()); break; } // If the nested-name-specifier is an invalid type def, don't emit an @@ -4753,6 +4741,22 @@ ::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) { llvm_unreachable("Unknown name kind."); } +template +TemplateName TreeTransform::RebuildTemplateName( + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + IdentifierOrOverloadedOperator IO, SourceLocation NameLoc, + QualType ObjectType, NamedDecl *FirstQualifierInScope, + bool AllowInjectedClassName) { + if (const IdentifierInfo *II = IO.getIdentifier()) { + return getDerived().RebuildTemplateName(SS, TemplateKWLoc, *II, NameLoc, + ObjectType, FirstQualifierInScope, + AllowInjectedClassName); + } + return getDerived().RebuildTemplateName(SS, TemplateKWLoc, IO.getOperator(), + NameLoc, ObjectType, + AllowInjectedClassName); +} + template TemplateName TreeTransform::TransformTemplateName(CXXScopeSpec &SS, @@ -4794,20 +4798,9 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, // FIXME: Preserve the location of the "template" keyword. SourceLocation TemplateKWLoc = NameLoc; - - if (DTN->isIdentifier()) { - return getDerived().RebuildTemplateName(SS, - TemplateKWLoc, - *DTN->getIdentifier(), - NameLoc, - ObjectType, - FirstQualifierInScope, - AllowInjectedClassName); - } - - return getDerived().RebuildTemplateName(SS, TemplateKWLoc, - DTN->getOperator(), NameLoc, - ObjectType, AllowInjectedClassName); + return getDerived().RebuildTemplateName( + SS, TemplateKWLoc, DTN->getName(), NameLoc, ObjectType, + FirstQualifierInScope, AllowInjectedClassName); } // FIXME: Try to preserve more of the TemplateName. @@ -5401,13 +5394,14 @@ TypeSourceInfo *TreeTransform::TransformTSIInObjectScope( DependentTemplateSpecializationTypeLoc SpecTL = TL.castAs(); - TemplateName Template - = getDerived().RebuildTemplateName(SS, - SpecTL.getTemplateKeywordLoc(), - *SpecTL.getTypePtr()->getIdentifier(), - SpecTL.getTemplateNameLoc(), - ObjectType, UnqualLookup, - /*AllowInjectedClassName*/true); + const IdentifierInfo *II = SpecTL.getTypePtr() + ->getDependentTemplateName() + .getName() + .getIdentifier(); + TemplateName Template = getDerived().RebuildTemplateName( + SS, SpecTL.getTemplateKeywordLoc(), *II, SpecTL.getTemplateNameLoc(), + ObjectType, UnqualLookup, + /*AllowInjectedClassName*/ true); if (Template.isNull()) return nullptr; @@ -7430,9 +7424,9 @@ QualType TreeTransform::TransformDependentTemplateSpecializationType( // FIXME: maybe don't rebuild if all the template arguments are the same. if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + assert(DTN->getQualifier() == SS.getScopeRep()); QualType Result = getSema().Context.getDependentTemplateSpecializationType( - TL.getTypePtr()->getKeyword(), DTN->getQualifier(), - DTN->getIdentifier(), NewTemplateArgs.arguments()); + TL.getTypePtr()->getKeyword(), *DTN, NewTemplateArgs.arguments()); DependentTemplateSpecializationTypeLoc NewTL = TLB.push(Result); @@ -7755,15 +7749,15 @@ QualType TreeTransform:: return QualType(); } - return getDerived() - .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc); + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + return getDerived().TransformDependentTemplateSpecializationType(TLB, TL, SS); } -template -QualType TreeTransform:: -TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, - DependentTemplateSpecializationTypeLoc TL, - NestedNameSpecifierLoc QualifierLoc) { +template +QualType TreeTransform::TransformDependentTemplateSpecializationType( + TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL, + CXXScopeSpec &SS) { const DependentTemplateSpecializationType *T = TL.getTypePtr(); TemplateArgumentListInfo NewTemplateArgs; @@ -7777,13 +7771,25 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, NewTemplateArgs)) return QualType(); - QualType Result = getDerived().RebuildDependentTemplateSpecializationType( - T->getKeyword(), QualifierLoc, TL.getTemplateKeywordLoc(), - T->getIdentifier(), TL.getTemplateNameLoc(), NewTemplateArgs, - /*AllowInjectedClassName*/ false); - if (Result.isNull()) - return QualType(); + const DependentTemplateStorage &DTN = T->getDependentTemplateName(); + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || SS.getScopeRep() != DTN.getQualifier()) { + TemplateName Name = getDerived().RebuildTemplateName( + SS, TL.getTemplateKeywordLoc(), DTN.getName(), TL.getTemplateNameLoc(), + /*ObjectType=*/QualType(), /*FirstQualifierInScope=*/nullptr, + /*AllowInjectedClassName=*/false); + if (Name.isNull()) + return QualType(); + Result = getDerived().RebuildDependentTemplateSpecializationType( + T->getKeyword(), SS.getScopeRep(), TL.getTemplateKeywordLoc(), Name, + TL.getTemplateNameLoc(), NewTemplateArgs, + /*AllowInjectedClassName=*/false); + if (Result.isNull()) + return QualType(); + } + + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(SemaRef.Context); if (const ElaboratedType *ElabT = dyn_cast(Result)) { QualType NamedT = ElabT->getNamedType(); @@ -7801,7 +7807,8 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, ElaboratedTypeLoc NewTL = TLB.push(Result); NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setQualifierLoc(QualifierLoc); - } else if (isa(Result)) { + } else { + assert(isa(Result)); DependentTemplateSpecializationTypeLoc SpecTL = TLB.push(Result); SpecTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); @@ -7812,15 +7819,6 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, SpecTL.setRAngleLoc(TL.getRAngleLoc()); for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); - } else { - TemplateSpecializationTypeLoc SpecTL - = TLB.push(Result); - SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); - SpecTL.setTemplateNameLoc(TL.getTemplateNameLoc()); - SpecTL.setLAngleLoc(TL.getLAngleLoc()); - SpecTL.setRAngleLoc(TL.getRAngleLoc()); - for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) - SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); } return Result; } @@ -17532,8 +17530,7 @@ TreeTransform::RebuildCXXPseudoDestructorExpr(Expr *Base, << ScopeType->getType() << getSema().getLangOpts().CPlusPlus; return ExprError(); } - SS.Extend(SemaRef.Context, SourceLocation(), ScopeType->getTypeLoc(), - CCLoc); + SS.Extend(SemaRef.Context, ScopeType->getTypeLoc(), CCLoc); } SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 0cd2cedb48dd9..58a57d6c54523 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9914,18 +9914,12 @@ ASTRecordReader::readNestedNameSpecifierLoc() { break; } - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - bool Template = readBool(); + case NestedNameSpecifier::TypeSpec: { TypeSourceInfo *T = readTypeSourceInfo(); if (!T) return NestedNameSpecifierLoc(); SourceLocation ColonColonLoc = readSourceLocation(); - - // FIXME: 'template' keyword location not saved anywhere, so we fake it. - Builder.Extend(Context, - Template? T->getTypeLoc().getBeginLoc() : SourceLocation(), - T->getTypeLoc(), ColonColonLoc); + Builder.Extend(Context, T->getTypeLoc(), ColonColonLoc); break; } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 99ac26cb43cac..84f7f2bc5fce4 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7022,8 +7022,6 @@ void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { break; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); AddTypeRef(NNS.getTypeLoc().getType()); AddTypeLoc(NNS.getTypeLoc()); AddSourceLocation(NNS.getLocalSourceRange().getEnd()); diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 3e50d67f4d6ef..8b746c02dbfc9 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -959,8 +959,6 @@ class BuildTreeVisitor : public RecursiveASTVisitor { case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Identifier: return syntax::NodeKind::IdentifierNameSpecifier; - case NestedNameSpecifier::TypeSpecWithTemplate: - return syntax::NodeKind::SimpleTemplateNameSpecifier; case NestedNameSpecifier::TypeSpec: { const auto *NNSType = NNS.getAsType(); assert(NNSType); diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp index d79051fb6efaa..08d8fba795daa 100644 --- a/clang/test/AST/ast-dump-decl.cpp +++ b/clang/test/AST/ast-dump-decl.cpp @@ -351,8 +351,8 @@ namespace testClassTemplateDecl { // CHECK-NEXT: | |-CXXDestructorDecl 0x{{.+}} col:5 used ~TestClassTemplate 'void () noexcept' implicit_instantiation instantiated_from 0x[[#TEMPLATE_DESTRUCTOR_DECL]]{{$}} // CHECK-NEXT: | |-CXXMethodDecl 0x{{.+}} col:9 j 'int ()' implicit_instantiation instantiated_from 0x[[#TEMPLATE_METHOD_DECL]]{{$}} // CHECK-NEXT: | |-FieldDecl 0x{{.+}} col:9 i 'int'{{$}} -// CHECK-NEXT: | `-CXXConstructorDecl 0x{{.+}} col:30 implicit constexpr TestClassTemplate 'void (const TestClassTemplate &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} -// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} col:30 'const TestClassTemplate &'{{$}} +// CHECK-NEXT: | `-CXXConstructorDecl 0x{{.+}} col:30 implicit constexpr TestClassTemplate 'void (const TestClassTemplate &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} +// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} col:30 'const TestClassTemplate &'{{$}} // CHECK-NEXT: |-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}} // CHECK-NEXT: |-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}} // CHECK-NEXT: `-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}} @@ -654,10 +654,10 @@ namespace testCanonicalTemplate { // CHECK-NEXT: | `-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}} // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} col:31 implicit used constexpr TestClassTemplate 'void () noexcept' inline default trivial{{$}} // CHECK-NEXT: | `-CompoundStmt 0x{{.+}} {{$}} - // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate 'void (const TestClassTemplate &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} - // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} col:31 'const TestClassTemplate &'{{$}} - // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate 'void (TestClassTemplate &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} - // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} col:31 'TestClassTemplate &&'{{$}} + // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate 'void (const TestClassTemplate &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} + // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} col:31 'const TestClassTemplate &'{{$}} + // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate 'void (TestClassTemplate &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} + // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} col:31 'TestClassTemplate &&'{{$}} template class TestClassTemplate2; @@ -682,10 +682,10 @@ namespace testCanonicalTemplate { // CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} col:31 implicit class TestClassTemplate2{{$}} // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} col:31 implicit used constexpr TestClassTemplate2 'void () noexcept' inline default trivial{{$}} // CHECK-NEXT: | `-CompoundStmt 0x{{.+}} {{$}} - // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate2 'void (const TestClassTemplate2 &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} - // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} col:31 'const TestClassTemplate2 &'{{$}} - // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate2 'void (TestClassTemplate2 &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} - // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} col:31 'TestClassTemplate2 &&'{{$}} + // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate2 'void (const TestClassTemplate2 &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} + // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} col:31 'const TestClassTemplate2 &'{{$}} + // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} col:31 implicit constexpr TestClassTemplate2 'void (TestClassTemplate2 &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}} + // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} col:31 'TestClassTemplate2 &&'{{$}} // CHECK: ClassTemplateDecl 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-26]]:3, col:31> col:31 TestClassTemplate2{{$}} // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} col:21 typename depth 0 index 0 T1{{$}} diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 5da025c229ea3..2efd0b5e8ac21 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -229,11 +229,10 @@ void PostfixExpressions(S a, S *p, U *r) { // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *' - // FIXME: there is no mention that this used the template keyword. r->template U::~U(); // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} 'void' // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} '' ->~U 0x{{[^ ]*}} - // CHECK-NEXT: NestedNameSpecifier TypeSpecWithTemplate 'template U':'U' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'template U':'U' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'U *' lvalue ParmVar 0x{{[^ ]*}} 'r' 'U *' diff --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp index fb0132bf7dbc2..d6982a0927e8c 100644 --- a/clang/test/AST/ast-dump-templates.cpp +++ b/clang/test/AST/ast-dump-templates.cpp @@ -174,7 +174,7 @@ namespace TestDependentMemberPointer { // DUMP-NEXT: | `-BuiltinType {{.+}} 'int' // DUMP-NEXT: `-TypeAliasDecl {{.+}} Z 'int U::template V::*'{{$}} // DUMP-NEXT: `-MemberPointerType {{.+}} 'int U::template V::*' dependent -// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'U::template V' dependent +// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'template V' dependent // DUMP-NEXT: `-BuiltinType {{.+}} 'int' } // namespace TestDependentMemberPointer @@ -6588,7 +6588,7 @@ namespace TestDependentMemberPointer { // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6359, +// JSON-NEXT: "offset": 6356, // JSON-NEXT: "line": 179, // JSON-NEXT: "col": 1, // JSON-NEXT: "tokLen": 1 @@ -6896,7 +6896,7 @@ namespace TestDependentMemberPointer { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "DependentTemplateSpecializationType", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "U::template V" +// JSON-NEXT: "qualType": "template V" // JSON-NEXT: }, // JSON-NEXT: "isDependent": true, // JSON-NEXT: "isInstantiationDependent": true diff --git a/clang/test/CXX/class.access/p6.cpp b/clang/test/CXX/class.access/p6.cpp index 6f266728faa6b..15f2644f6ac1d 100644 --- a/clang/test/CXX/class.access/p6.cpp +++ b/clang/test/CXX/class.access/p6.cpp @@ -92,7 +92,7 @@ namespace test3 { template class Outer::A { public: - static void foo(); // expected-note {{'Outer::A::foo' declared here}} + static void foo(); // expected-note {{'Outer::A::foo' declared here}} }; class B { @@ -102,7 +102,7 @@ namespace test3 { void test() { Outer::A::foo(); - Outer::A::foo(); // expected-error {{no member named 'foo' in 'test3::Outer::A'; did you mean 'Outer::A::foo'?}} + Outer::A::foo(); // expected-error {{no member named 'foo' in 'test3::Outer::A'; did you mean 'Outer::A::foo'?}} } } diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp index b621318a9ce41..b2ae8f88ead74 100644 --- a/clang/test/CXX/drs/cwg2xx.cpp +++ b/clang/test/CXX/drs/cwg2xx.cpp @@ -98,8 +98,8 @@ template class Templ { // #cwg203-ex3-Templ void foo() { Templ x(&Derived::func); } // expected-error@-1 {{no matching constructor for initialization of 'Templ'}} -// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'const Templ' for 1st argument}} -// since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'Templ' for 1st argument}} +// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'const Templ' for 1st argument}} +// since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'Templ' for 1st argument}} // expected-note@#cwg203-ex3-Templ-ctor {{candidate template ignored: could not match 'cwg203::ex3::Derived' against 'cwg203::ex3::Base'}} } // namespace ex3 diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp index 763d983d20f61..651cca927d513 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp @@ -150,7 +150,7 @@ void func() { // expected-note@#bar {{while substituting template arguments into constraint expression here}} // expected-note@#bar {{while checking the satisfaction of nested requirement requested here}} // expected-note@#bar {{candidate template ignored: constraints not satisfied [with T = False]}} - // expected-note@#bar {{because 'X::value' evaluated to false}} + // expected-note@#bar {{because 'X::value' evaluated to false}} bar(); // expected-note@-1 {{while checking constraint satisfaction for template 'bar' required here}} \ diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp index 0d384b6b499f7..bf6a2eeb432a3 100644 --- a/clang/test/SemaCXX/static-assert.cpp +++ b/clang/test/SemaCXX/static-assert.cpp @@ -196,8 +196,10 @@ struct NestedTemplates1 { template void foo2() { + // FIXME: Here the template keyword is dropped because the failed condition + // for a static assert is always printed with canonical types. static_assert(::ns::NestedTemplates1::NestedTemplates2::template NestedTemplates3::value, "message"); - // expected-error@-1{{static assertion failed due to requirement '::ns::NestedTemplates1::NestedTemplates2::template NestedTemplates3::value': message}} + // expected-error@-1{{static assertion failed due to requirement '::ns::NestedTemplates1::NestedTemplates2::NestedTemplates3::value': message}} } template void foo2(); // expected-note@-1{{in instantiation of function template specialization 'foo2' requested here}} diff --git a/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp b/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp index 0854ac9178b4f..2ecd2694ce09d 100644 --- a/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp +++ b/clang/test/SemaTemplate/aggregate-deduction-candidate.cpp @@ -331,7 +331,7 @@ namespace DeduceArity { // CHECK: | |-ParmVarDecl {{.*}} 'Types' // CHECK: | `-ParmVarDecl {{.*}} 'T...' pack // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit used - // CHECK-SAME: 'auto (Types, DeduceArity::X, DeduceArity::Y, DeduceArity::Z) -> + // CHECK-SAME: 'auto (Types, DeduceArity::X, DeduceArity::Y, DeduceArity::Z) -> // CHECK-SAME: DeduceArity::F' // CHECK: | |-TemplateArgument pack // CHECK: | | |-TemplateArgument type 'DeduceArity::X' @@ -343,16 +343,16 @@ namespace DeduceArity { // CHECK: | | `-TemplateArgument type 'DeduceArity::Z' // CHECK: | | `-RecordType {{.*}} 'DeduceArity::Z' // CHECK: | | `-CXXRecord {{.*}} 'Z' - // CHECK: | |-ParmVarDecl {{.*}} 'Types':'DeduceArity::Types' + // CHECK: | |-ParmVarDecl {{.*}} 'Types':'DeduceArity::Types' // CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::X' // CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::Y' // CHECK: | `-ParmVarDecl {{.*}} 'DeduceArity::Z' - // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit 'auto (Types, DeduceArity::X) -> DeduceArity::F' + // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit 'auto (Types, DeduceArity::X) -> DeduceArity::F' // CHECK: |-TemplateArgument pack // CHECK: | `-TemplateArgument type 'DeduceArity::X' // CHECK: | `-RecordType {{.*}} 'DeduceArity::X' // CHECK: | `-CXXRecord {{.*}} 'X' - // CHECK: |-ParmVarDecl {{.*}} 'Types':'DeduceArity::Types' + // CHECK: |-ParmVarDecl {{.*}} 'Types':'DeduceArity::Types' // CHECK: `-ParmVarDecl {{.*}} 'DeduceArity::X' // CHECK: FunctionProtoType {{.*}} 'auto (Types, T...) -> F' dependent trailing_return cdecl // CHECK: |-InjectedClassNameType {{.*}} 'F' dependent diff --git a/clang/test/SemaTemplate/dependent-template-recover.cpp b/clang/test/SemaTemplate/dependent-template-recover.cpp index c7e27e8da25f1..251a8f9816417 100644 --- a/clang/test/SemaTemplate/dependent-template-recover.cpp +++ b/clang/test/SemaTemplate/dependent-template-recover.cpp @@ -134,3 +134,21 @@ namespace PR9401 { const D::template B::template E > > A::B::a = typename C::template B::template E >(g); } + +namespace templ_spec { + template using A = void; // expected-note 2{{template parameter is declared here}} + template struct B { + A> t1; + // expected-error@-1 {{'A>' (aka 'void')}} + + A> t2; // expected-error {{use 'template' keyword}} + // expected-error@-1 {{'A>' (aka 'void')}} + + // FIXME: Why error recovery for the non-typename case is so bad? + A> t3; // expected-error {{did you forget 'typename'}} + // expected-error@-1 {{'A' (aka 'void')}} + + A> t4; // expected-error {{use 'template' keyword}} expected-error {{did you forget 'typename'}} + // expected-error@-1 {{'A' (aka 'void')}} + }; +} // namespace templ_spec diff --git a/clang/test/SemaTemplate/instantiate-requires-expr.cpp b/clang/test/SemaTemplate/instantiate-requires-expr.cpp index a1f5456156a06..ab5fac1f9e63e 100644 --- a/clang/test/SemaTemplate/instantiate-requires-expr.cpp +++ b/clang/test/SemaTemplate/instantiate-requires-expr.cpp @@ -72,8 +72,8 @@ namespace type_requirement { template requires false_v; }> - // expected-note@-1 {{because 'false_v::template temp >; }>' evaluated to false}} - // expected-note@-2 {{because 'false_v::template temp >; }>' evaluated to false}} + // expected-note@-1 {{because 'false_v::template temp >; }>' evaluated to false}} + // expected-note@-2 {{because 'false_v::template temp >; }>' evaluated to false}} struct r2 {}; using r2i1 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template]}} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index e498a875bbbe8..197ba2cd6856e 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1457,7 +1457,6 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, break; } - case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::Global: case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Super: @@ -1492,7 +1491,6 @@ bool CursorVisitor::VisitNestedNameSpecifierLoc( break; case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: if (Visit(Q.getTypeLoc())) return true; diff --git a/libcxx/test/std/containers/sequences/array/array.overview/nttp.verify.cpp b/libcxx/test/std/containers/sequences/array/array.overview/nttp.verify.cpp index 3eb8e2596f85b..f50febf5f2485 100644 --- a/libcxx/test/std/containers/sequences/array/array.overview/nttp.verify.cpp +++ b/libcxx/test/std/containers/sequences/array/array.overview/nttp.verify.cpp @@ -61,7 +61,7 @@ using E = test{}>; // expected-error@-1 {{non-type template parameter has non-literal type 'std::array'}} using F = test{}>; -// expected-error@-1 {{type 'std::array' (aka 'std::array') of non-type template parameter is not a structural type}} +// expected-error-re@-1 {{type 'std::array<{{(std::)?}}string, 2>'{{( \(aka 'std::array'\))?}} of non-type template parameter is not a structural type}} } // namespace test_ctad namespace test_auto { diff --git a/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp index d6d70782c5eb5..fba0f61b76060 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp @@ -26,7 +26,7 @@ int main(int, char**) { // expected-error-re@*:* {{static assertion failed due to requirement {{.*}}std::shared_ptr<> is not supported}} std::ignore = std::inout_ptr(sPtr); - // expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr' to 'std::inout_ptr_t, _Ptr>' (aka 'inout_ptr_t, int *>'}} + // expected-error-re@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr' to 'std::inout_ptr_t<{{(std::)?}}shared_ptr, _Ptr>'{{( \(aka 'inout_ptr_t, int *>')?}}}} std::ignore = std::inout_ptr(sPtr); } diff --git a/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp index 1fe78ecb22789..da3ffbba94a8f 100644 --- a/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp +++ b/libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp @@ -26,7 +26,7 @@ int main(int, char**) { // expected-error-re@*:* {{static assertion failed due to requirement {{.*}}Using std::shared_ptr<> without a deleter in std::out_ptr is not supported.}} std::ignore = std::out_ptr(sPtr); - // expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr' to 'std::out_ptr_t, _Ptr>' (aka 'out_ptr_t, int *>')}} + // expected-error-re@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr' to 'std::out_ptr_t<{{(std::)?}}shared_ptr, _Ptr>'{{( \(aka 'out_ptr_t, int *>'\))?}}}} std::ignore = std::out_ptr(sPtr); } diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/nttp.verify.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/nttp.verify.cpp index b9b5432a30b21..9a39c18f138fb 100644 --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/nttp.verify.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/nttp.verify.cpp @@ -74,7 +74,7 @@ using H = test{}>; // expected-error@-1 {{non-type template parameter has non-literal type 'std::pair'}} using I = test{}>; -// expected-error@-1 {{type 'std::pair' (aka 'std::pair') of non-type template parameter is not a structural type}} +// expected-error-re@-1 {{type 'std::pair<{{(std::)?}}string, {{(std::)?}}string>'{{( \(aka 'std::pair'\))?}} of non-type template parameter is not a structural type}} } // namespace test_ctad namespace test_auto {