[clang-tools-extra] dc17429 - [clang] improved preservation of template keyword (#133610)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 1 13:15:22 PDT 2025
Author: Matheus Izvekov
Date: 2025-04-01T17:15:18-03:00
New Revision: dc17429ae6961a6783371dcf6749eea657b5446a
URL: https://github.com/llvm/llvm-project/commit/dc17429ae6961a6783371dcf6749eea657b5446a
DIFF: https://github.com/llvm/llvm-project/commit/dc17429ae6961a6783371dcf6749eea657b5446a.diff
LOG: [clang] improved preservation of template keyword (#133610)
Added:
Modified:
clang-tools-extra/clangd/AST.cpp
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/DumpAST.cpp
clang-tools-extra/clangd/FindTarget.cpp
clang-tools-extra/include-cleaner/lib/WalkAST.cpp
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/ASTImporter.h
clang/include/clang/AST/ASTNodeTraverser.h
clang/include/clang/AST/AbstractBasicReader.h
clang/include/clang/AST/AbstractBasicWriter.h
clang/include/clang/AST/NestedNameSpecifier.h
clang/include/clang/AST/ODRHash.h
clang/include/clang/AST/PropertiesBase.td
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/TemplateName.h
clang/include/clang/AST/Type.h
clang/include/clang/AST/TypeLoc.h
clang/include/clang/AST/TypeProperties.td
clang/include/clang/Sema/DeclSpec.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/ASTStructuralEquivalence.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/NestedNameSpecifier.cpp
clang/lib/AST/ODRHash.cpp
clang/lib/AST/QualTypeNames.cpp
clang/lib/AST/TemplateName.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/AST/Type.cpp
clang/lib/AST/TypeLoc.cpp
clang/lib/AST/TypePrinter.cpp
clang/lib/ExtractAPI/DeclarationFragments.cpp
clang/lib/Index/IndexTypeSourceInfo.cpp
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Sema/DeclSpec.cpp
clang/lib/Sema/HeuristicResolver.cpp
clang/lib/Sema/SemaCXXScopeSpec.cpp
clang/lib/Sema/SemaCodeComplete.cpp
clang/lib/Sema/SemaCoroutine.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/test/AST/ast-dump-decl.cpp
clang/test/AST/ast-dump-expr.cpp
clang/test/AST/ast-dump-templates.cpp
clang/test/CXX/class.access/p6.cpp
clang/test/CXX/drs/cwg2xx.cpp
clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
clang/test/SemaCXX/static-assert.cpp
clang/test/SemaTemplate/aggregate-deduction-candidate.cpp
clang/test/SemaTemplate/dependent-template-recover.cpp
clang/test/SemaTemplate/instantiate-requires-expr.cpp
clang/tools/libclang/CIndex.cpp
libcxx/test/std/containers/sequences/array/array.overview/nttp.verify.cpp
libcxx/test/std/utilities/smartptr/adapt/inout_ptr/inout_ptr.verify.cpp
libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.verify.cpp
libcxx/test/std/utilities/utility/pairs/pairs.pair/nttp.verify.cpp
Removed:
################################################################################
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<NamespaceDecl>(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<DumpVisitor> {
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<ASTWalker> {
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<ASTContext> {
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<TemplateArgumentLoc> Args) const;
+ ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
+ ArrayRef<TemplateArgumentLoc> Args) const;
QualType getDependentTemplateSpecializationType(
- ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
- const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
+ ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
+ ArrayRef<TemplateArgument> Args, bool IsCanonical = false) const;
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const;
@@ -2393,11 +2392,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
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<Impl> {
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<Impl> {
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<TemplateName, "QualifiedTemplate"> in {
let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
def : ReadHelper<[{
auto dtn = node.getAsDependentTemplateName();
+ auto name = dtn->getName();
}]>;
def : Property<"qualifier", NestedNameSpecifier> {
let Read = [{ dtn->getQualifier() }];
}
def : Property<"identifier", Optional<Identifier>> {
- 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<Derived>::TraverseNestedNameSpecifier(
return true;
case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
}
@@ -820,7 +819,6 @@ bool RecursiveASTVisitor<Derived>::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<const IdentifierInfo *>(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<NestedNameSpecifier *, 1, bool> 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<TemplateArgument> Args,
QualType Canon);
public:
- NestedNameSpecifier *getQualifier() const { return NNS; }
- const IdentifierInfo *getIdentifier() const { return Name; }
+ const DependentTemplateStorage &getDependentTemplateName() const {
+ return Name;
+ }
ArrayRef<TemplateArgument> template_arguments() const {
return {reinterpret_cast<const TemplateArgument *>(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<TemplateArgument> 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<Identifier>> {
+ 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<TemplateArgument>> {
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<QualType>> {
- let Read = [{
- node->isCanonicalUnqualified()
- ? std::nullopt
- : std::optional<QualType>(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<TemplateArgumentLoc> Args) const {
+ ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
+ ArrayRef<TemplateArgumentLoc> Args) const {
// TODO: avoid this copy
SmallVector<TemplateArgument, 16> 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<TemplateArgument> Args) const {
- assert((!NNS || NNS->isDependent()) &&
- "nested-name-specifier must be dependent");
-
+QualType ASTContext::getDependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
+ ArrayRef<TemplateArgument> 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
diff erence 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<DependentNameType>())
return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
DNT->getIdentifier());
- if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>())
- 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<DependentTemplateSpecializationType>()) {
+ 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<DependentTemplateSpecializationType>(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<ElaboratedType>(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<DependentTemplateSpecializationType>(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<DependentTemplateSpecializationType>(X),
*TY = cast<DependentTemplateSpecializationType>(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<UnaryTransformType>(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<TemplateArgument, 2> 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<TemplateName> 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<Selector> 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<DependentTemplateSpecializationType>(T1);
const auto *Spec2 = cast<DependentTemplateSpecializationType>(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<DependentTemplateSpecializationType>()) {
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<DependentTemplateSpecializationType>(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);
// <class-enum-type> ::= <name>
// <name> ::= <nested-name>
mangleUnresolvedPrefix(Dependent->getQualifier());
- mangleSourceName(Dependent->getIdentifier());
+ mangleSourceName(II);
break;
}
@@ -2572,8 +2583,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
const DependentTemplateSpecializationType *DTST =
cast<DependentTemplateSpecializationType>(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<Type*>(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<CXXRecordDecl>(static_cast<NamedDecl *>(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<DependentTemplateSpecializationType>(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<ClassTemplateSpecializationDecl>(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<T>::template Inner<U>),
- // the type requires its own nested-name-specifier for uniqueness, so we
- // suppress that nested-name-specifier during printing.
- assert(!isa<ElaboratedType>(T) &&
- "Elaborated type in nested-name-specifier");
- if (const TemplateSpecializationType *SpecType
- = dyn_cast<TemplateSpecializationType>(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<DependentTemplateSpecializationType>(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<ODRTypeVisitor> {
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<uintptr_t>(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<UncommonTemplateNameStorage *>(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<TemplateArgument> Args, QualType Canon)
+ ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
+ ArrayRef<TemplateArgument> 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<TemplateArgument *>(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<TemplateArgument> Args) {
+void DependentTemplateSpecializationType::Profile(
+ llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
+ ArrayRef<TemplateArgument> 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<TemplateArgument> 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<TemplateArgumentLoc> 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<const NamedDecl *>
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<const NamedDecl *>
@@ -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<TagType>();
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<DecltypeTypeLoc>(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<PackIndexingTypeLoc>(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<DependentTemplateSpecializationTypeLoc>(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<TagDecl>(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<TagDecl>(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<TagDecl>(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<Type>(Context.getRecordType(RD)));
+ auto *NNS = NestedNameSpecifier::Create(
+ Context, nullptr, cast<Type>(Context.getRecordType(RD)));
QualType T =
Context.getDependentNameType(ElaboratedTypeKeyword::Typename, NNS, &II);
@@ -580,10 +580,10 @@ synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) {
auto *ND = dyn_cast<NamespaceDecl>(DC);
if (ND && !ND->isInline() && !ND->isAnonymousNamespace())
return NestedNameSpecifier::Create(Context, nullptr, ND);
- else if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
- return NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(),
+ if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
+ return NestedNameSpecifier::Create(Context, nullptr,
RD->getTypeForDecl());
- else if (isa<TranslationUnitDecl>(DC))
+ if (isa<TranslationUnitDecl>(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<TemplateSpecializationType>()) {
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<RecordDecl>(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<DependentTemplateSpecializationType>()) {
- 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<IndirectFieldDecl>(VD)));
QualType ClassType
= Context.getTypeDeclType(cast<RecordDecl>(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<DependentTemplateSpecializationType>(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
diff erent 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<Derived>::TransformNestedNameSpecifierLoc(
break;
}
- case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
FirstQualifierInScope, SS);
@@ -4654,8 +4643,7 @@ NestedNameSpecifierLoc TreeTransform<Derived>::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 <typename Derived>
+TemplateName TreeTransform<Derived>::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<typename Derived>
TemplateName
TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
@@ -4794,20 +4798,9 @@ TreeTransform<Derived>::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<Derived>::TransformTSIInObjectScope(
DependentTemplateSpecializationTypeLoc SpecTL =
TL.castAs<DependentTemplateSpecializationTypeLoc>();
- 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<Derived>::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<DependentTemplateSpecializationTypeLoc>(Result);
@@ -7755,15 +7749,15 @@ QualType TreeTransform<Derived>::
return QualType();
}
- return getDerived()
- .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc);
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
+ return getDerived().TransformDependentTemplateSpecializationType(TLB, TL, SS);
}
-template<typename Derived>
-QualType TreeTransform<Derived>::
-TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
- DependentTemplateSpecializationTypeLoc TL,
- NestedNameSpecifierLoc QualifierLoc) {
+template <typename Derived>
+QualType TreeTransform<Derived>::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<ElaboratedType>(Result)) {
QualType NamedT = ElabT->getNamedType();
@@ -7801,7 +7807,8 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
NewTL.setQualifierLoc(QualifierLoc);
- } else if (isa<DependentTemplateSpecializationType>(Result)) {
+ } else {
+ assert(isa<DependentTemplateSpecializationType>(Result));
DependentTemplateSpecializationTypeLoc SpecTL
= TLB.push<DependentTemplateSpecializationTypeLoc>(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<TemplateSpecializationTypeLoc>(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<Derived>::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<BuildTreeVisitor> {
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{{.+}} <line:[[@LINE-67]]:5, col:24> col:5 used ~TestClassTemplate 'void () noexcept' implicit_instantiation instantiated_from 0x[[#TEMPLATE_DESTRUCTOR_DECL]]{{$}}
// CHECK-NEXT: | |-CXXMethodDecl 0x{{.+}} <line:[[@LINE-67]]:5, col:11> col:9 j 'int ()' implicit_instantiation instantiated_from 0x[[#TEMPLATE_METHOD_DECL]]{{$}}
// CHECK-NEXT: | |-FieldDecl 0x{{.+}} <line:[[@LINE-67]]:5, col:9> col:9 i 'int'{{$}}
-// CHECK-NEXT: | `-CXXConstructorDecl 0x{{.+}} <line:[[@LINE-73]]:30> col:30 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
-// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:30> col:30 'const TestClassTemplate<A> &'{{$}}
+// CHECK-NEXT: | `-CXXConstructorDecl 0x{{.+}} <line:[[@LINE-73]]:30> col:30 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<testClassTemplateDecl::A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
+// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:30> col:30 'const TestClassTemplate<testClassTemplateDecl::A> &'{{$}}
// 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{{.+}} <line:[[@LINE-36]]:31> col:31 implicit used constexpr TestClassTemplate 'void () noexcept' inline default trivial{{$}}
// CHECK-NEXT: | `-CompoundStmt 0x{{.+}} <col:31>{{$}}
- // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
- // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate<A> &'{{$}}
- // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (TestClassTemplate<A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
- // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate<A> &&'{{$}}
+ // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<testCanonicalTemplate::A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
+ // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate<testCanonicalTemplate::A> &'{{$}}
+ // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (TestClassTemplate<testCanonicalTemplate::A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
+ // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate<testCanonicalTemplate::A> &&'{{$}}
template<typename T1> class TestClassTemplate2;
@@ -682,10 +682,10 @@ namespace testCanonicalTemplate {
// CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} <col:25, col:31> col:31 implicit class TestClassTemplate2{{$}}
// CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit used constexpr TestClassTemplate2 'void () noexcept' inline default trivial{{$}}
// CHECK-NEXT: | `-CompoundStmt 0x{{.+}} <col:31>{{$}}
- // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (const TestClassTemplate2<A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
- // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate2<A> &'{{$}}
- // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (TestClassTemplate2<A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
- // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate2<A> &&'{{$}}
+ // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (const TestClassTemplate2<testCanonicalTemplate::A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
+ // CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate2<testCanonicalTemplate::A> &'{{$}}
+ // CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (TestClassTemplate2<testCanonicalTemplate::A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
+ // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate2<testCanonicalTemplate::A> &&'{{$}}
// CHECK: ClassTemplateDecl 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-26]]:3, col:31> col:31 TestClassTemplate2{{$}}
// CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:12, col:21> 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<int> *r) {
// CHECK-NEXT: ImplicitCastExpr
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *'
- // FIXME: there is no mention that this used the template keyword.
r->template U<int>::~U();
// CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:26> 'void'
// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:24> '<bound member function type>' ->~U 0x{{[^ ]*}}
- // CHECK-NEXT: NestedNameSpecifier TypeSpecWithTemplate 'template U<int>':'U<int>'
+ // CHECK-NEXT: NestedNameSpecifier TypeSpec 'template U<int>':'U<int>'
// CHECK-NEXT: ImplicitCastExpr
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'U<int> *' lvalue ParmVar 0x{{[^ ]*}} 'r' 'U<int> *'
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<int>::*'{{$}}
// DUMP-NEXT: `-MemberPointerType {{.+}} 'int U::template V<int>::*' dependent
-// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'U::template V<int>' dependent
+// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'template V<int>' 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<int>"
+// JSON-NEXT: "qualType": "template V<int>"
// 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 T> class Outer::A<T, typename T::nature> {
public:
- static void foo(); // expected-note {{'Outer::A<B, Green>::foo' declared here}}
+ static void foo(); // expected-note {{'Outer::A<test3::B, test3::Green>::foo' declared here}}
};
class B {
@@ -102,7 +102,7 @@ namespace test3 {
void test() {
Outer::A<B, Green>::foo();
- Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo' in 'test3::Outer::A<test3::B, test3::Blue>'; did you mean 'Outer::A<B, Green>::foo'?}}
+ Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo' in 'test3::Outer::A<test3::B, test3::Blue>'; did you mean 'Outer::A<test3::B, test3::Green>::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 T> class Templ { // #cwg203-ex3-Templ
void foo() { Templ<Derived> x(&Derived::func); }
// expected-error at -1 {{no matching constructor for initialization of 'Templ<Derived>'}}
-// 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<Derived>' 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<Derived>' 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<cwg203::ex3::Derived>' 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<cwg203::ex3::Derived>' 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<False>::value' evaluated to false}}
+ // expected-note@#bar {{because 'X<SubstitutionFailureNestedRequires::ErrorExpressions_NotSF::False>::value' evaluated to false}}
bar<int>();
// expected-note at -1 {{while checking constraint satisfaction for template 'bar<int>' 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 <typename T, typename U, int a>
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<T, a>::NestedTemplates2::template NestedTemplates3<U>::value, "message");
- // expected-error at -1{{static assertion failed due to requirement '::ns::NestedTemplates1<int, 3>::NestedTemplates2::template NestedTemplates3<float>::value': message}}
+ // expected-error at -1{{static assertion failed due to requirement '::ns::NestedTemplates1<int, 3>::NestedTemplates2::NestedTemplates3<float>::value': message}}
}
template void foo2<int, float, 3>();
// expected-note at -1{{in instantiation of function template specialization 'foo2<int, float, 3>' 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<T...>'
// CHECK: | `-ParmVarDecl {{.*}} 'T...' pack
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for F>
- // CHECK-SAME: 'auto (Types<X, Y, Z>, DeduceArity::X, DeduceArity::Y, DeduceArity::Z) ->
+ // CHECK-SAME: 'auto (Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>, DeduceArity::X, DeduceArity::Y, DeduceArity::Z) ->
// CHECK-SAME: DeduceArity::F<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
// 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<X, Y, Z>':'DeduceArity::Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
+ // CHECK: | |-ParmVarDecl {{.*}} 'Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>':'DeduceArity::Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
// CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::X'
// CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::Y'
// CHECK: | `-ParmVarDecl {{.*}} 'DeduceArity::Z'
- // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (Types<X>, DeduceArity::X) -> DeduceArity::F<DeduceArity::X>'
+ // CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (Types<DeduceArity::X>, DeduceArity::X) -> DeduceArity::F<DeduceArity::X>'
// CHECK: |-TemplateArgument pack
// CHECK: | `-TemplateArgument type 'DeduceArity::X'
// CHECK: | `-RecordType {{.*}} 'DeduceArity::X'
// CHECK: | `-CXXRecord {{.*}} 'X'
- // CHECK: |-ParmVarDecl {{.*}} 'Types<X>':'DeduceArity::Types<DeduceArity::X>'
+ // CHECK: |-ParmVarDecl {{.*}} 'Types<DeduceArity::X>':'DeduceArity::Types<DeduceArity::X>'
// CHECK: `-ParmVarDecl {{.*}} 'DeduceArity::X'
// CHECK: FunctionProtoType {{.*}} 'auto (Types<T...>, T...) -> F<T...>' dependent trailing_return cdecl
// CHECK: |-InjectedClassNameType {{.*}} 'F<T...>' 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<typename C<S, T>::template B<U>::template E<D<F> > >
A<S, T>::B<U>::a = typename C<S, T>::template B<U>::template E<D<F> >(g);
}
+
+namespace templ_spec {
+ template <class U> using A = void; // expected-note 2{{template parameter is declared here}}
+ template <class T> struct B {
+ A<typename T::template X<int>> t1;
+ // expected-error at -1 {{'A<typename T::template X<int>>' (aka 'void')}}
+
+ A<typename T::X<int>> t2; // expected-error {{use 'template' keyword}}
+ // expected-error at -1 {{'A<typename T::X<int>>' (aka 'void')}}
+
+ // FIXME: Why error recovery for the non-typename case is so bad?
+ A<T::template X<int>> t3; // expected-error {{did you forget 'typename'}}
+ // expected-error at -1 {{'A<typename T::X>' (aka 'void')}}
+
+ A<T::X<int>> t4; // expected-error {{use 'template' keyword}} expected-error {{did you forget 'typename'}}
+ // expected-error at -1 {{'A<typename T::X>' (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<typename T> requires
false_v<requires { typename T::template temp<T>; }>
- // expected-note at -1 {{because 'false_v<requires { typename contains_template<int>::template temp<contains_template<int> >; }>' evaluated to false}}
- // expected-note at -2 {{because 'false_v<requires { typename contains_template<short>::template temp<contains_template<short> >; }>' evaluated to false}}
+ // expected-note at -1 {{because 'false_v<requires { typename contains_template<int>::template temp<type_requirement::contains_template<int> >; }>' evaluated to false}}
+ // expected-note at -2 {{because 'false_v<requires { typename contains_template<short>::template temp<type_requirement::contains_template<short> >; }>' evaluated to false}}
struct r2 {};
using r2i1 = r2<contains_template<int>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<int>]}}
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<std::array<NotALiteral, 1>{}>;
// expected-error at -1 {{non-type template parameter has non-literal type 'std::array<NotALiteral, 1>'}}
using F = test<std::array<std::string, 2>{}>;
-// expected-error at -1 {{type 'std::array<string, 2>' (aka 'std::array<std::string, 2>') of non-type template parameter is not a structural type}}
+// expected-error-re at -1 {{type 'std::array<{{(std::)?}}string, 2>'{{( \(aka 'std::array<std::string, 2>'\))?}} 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<int>' to 'std::inout_ptr_t<shared_ptr<int>, _Ptr>' (aka 'inout_ptr_t<std::shared_ptr<int>, int *>'}}
+ // expected-error-re@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::inout_ptr_t<{{(std::)?}}shared_ptr<int>, _Ptr>'{{( \(aka 'inout_ptr_t<std::shared_ptr<int>, int *>')?}}}}
std::ignore = std::inout_ptr<int*>(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<int>' to 'std::out_ptr_t<shared_ptr<int>, _Ptr>' (aka 'out_ptr_t<std::shared_ptr<int>, int *>')}}
+ // expected-error-re@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::out_ptr_t<{{(std::)?}}shared_ptr<int>, _Ptr>'{{( \(aka 'out_ptr_t<std::shared_ptr<int>, int *>'\))?}}}}
std::ignore = std::out_ptr<int*>(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<std::pair<NotALiteral, NotALiteral>{}>;
// expected-error at -1 {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}}
using I = test<std::pair<std::string, std::string>{}>;
-// expected-error at -1 {{type 'std::pair<string, string>' (aka 'std::pair<std::string, std::string>') of non-type template parameter is not a structural type}}
+// expected-error-re at -1 {{type 'std::pair<{{(std::)?}}string, {{(std::)?}}string>'{{( \(aka 'std::pair<std::string, std::string>'\))?}} of non-type template parameter is not a structural type}}
} // namespace test_ctad
namespace test_auto {
More information about the cfe-commits
mailing list