[clang] cbba960 - Revert "[clang] Improved canonicalization for template specialization types" (#135354)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 11 06:55:15 PDT 2025
Author: Dmitry Vasilyev
Date: 2025-04-11T17:55:11+04:00
New Revision: cbba9600ae4faeb06619ed8b52c22d8a38708230
URL: https://github.com/llvm/llvm-project/commit/cbba9600ae4faeb06619ed8b52c22d8a38708230
DIFF: https://github.com/llvm/llvm-project/commit/cbba9600ae4faeb06619ed8b52c22d8a38708230.diff
LOG: Revert "[clang] Improved canonicalization for template specialization types" (#135354)
Reverts llvm/llvm-project#135119 because of the assert in ASTContext.cpp, line 5619.
See #135352 for details.
Added:
Modified:
clang-tools-extra/clangd/AST.cpp
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/PropertiesBase.td
clang/include/clang/AST/TemplateBase.h
clang/include/clang/AST/Type.h
clang/include/clang/AST/TypeProperties.td
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTDiagnostic.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/DeclTemplate.cpp
clang/lib/AST/QualTypeNames.cpp
clang/lib/AST/TemplateBase.cpp
clang/lib/AST/Type.cpp
clang/lib/Sema/SemaCXXScopeSpec.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Sema/SemaTemplateVariadic.cpp
clang/lib/Sema/TreeTransform.h
clang/test/CXX/class.derived/class.derived.general/p2.cpp
clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
clang/test/SemaCXX/undefined-partial-specialization.cpp
clang/test/SemaTemplate/make_integer_seq.cpp
clang/test/SemaTemplate/type_pack_element.cpp
clang/unittests/AST/TypePrinterTest.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index 3b991e5e9013f..66b587f00ff4a 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -439,8 +439,7 @@ QualType declaredType(const TypeDecl *D) {
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
if (const auto *Args = CTSD->getTemplateArgsAsWritten())
return Context.getTemplateSpecializationType(
- TemplateName(CTSD->getSpecializedTemplate()), Args->arguments(),
- /*CanonicalArgs=*/std::nullopt);
+ TemplateName(CTSD->getSpecializedTemplate()), Args->arguments());
return Context.getTypeDeclType(D);
}
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 69c7369755c67..db8dad268a8a7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -301,8 +301,6 @@ Improvements to Clang's diagnostics
- Clang now better preserves the sugared types of pointers to member.
- Clang now better preserves the presence of the template keyword with dependent
prefixes.
-- Clang now in more cases avoids printing 'type-parameter-X-X' instead of the name of
- the template parameter.
- Clang now respects the current language mode when printing expressions in
diagnostics. This fixes a bunch of `bool` being printed as `_Bool`, and also
a bunch of HLSL types being printed as their C++ equivalents.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index b8ea2af9215d2..b1e6344576eb5 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -367,6 +367,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
const ASTContext&>
CanonTemplateTemplateParms;
+ TemplateTemplateParmDecl *
+ getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
+
/// The typedef for the __int128_t type.
mutable TypedefDecl *Int128Decl = nullptr;
@@ -1808,26 +1811,22 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool ParameterPack,
TemplateTypeParmDecl *ParmDecl = nullptr) const;
- QualType getCanonicalTemplateSpecializationType(
- TemplateName T, ArrayRef<TemplateArgument> CanonicalArgs) const;
+ QualType getTemplateSpecializationType(TemplateName T,
+ ArrayRef<TemplateArgument> Args,
+ QualType Canon = QualType()) const;
QualType
- getTemplateSpecializationType(TemplateName T,
- ArrayRef<TemplateArgument> SpecifiedArgs,
- ArrayRef<TemplateArgument> CanonicalArgs,
- QualType Underlying = QualType()) const;
+ getCanonicalTemplateSpecializationType(TemplateName T,
+ ArrayRef<TemplateArgument> Args) const;
- QualType
- getTemplateSpecializationType(TemplateName T,
- ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
- ArrayRef<TemplateArgument> CanonicalArgs,
- QualType Canon = QualType()) const;
+ QualType getTemplateSpecializationType(TemplateName T,
+ ArrayRef<TemplateArgumentLoc> Args,
+ QualType Canon = QualType()) const;
- TypeSourceInfo *getTemplateSpecializationTypeInfo(
- TemplateName T, SourceLocation TLoc,
- const TemplateArgumentListInfo &SpecifiedArgs,
- ArrayRef<TemplateArgument> CanonicalArgs,
- QualType Canon = QualType()) const;
+ TypeSourceInfo *
+ getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
+ const TemplateArgumentListInfo &Args,
+ QualType Canon = QualType()) const;
QualType getParenType(QualType NamedType) const;
@@ -2943,21 +2942,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
const;
- /// Canonicalize the given template argument list.
- ///
- /// Returns true if any arguments were non-canonical, false otherwise.
- bool
- canonicalizeTemplateArguments(MutableArrayRef<TemplateArgument> Args) const;
-
- /// Canonicalize the given TemplateTemplateParmDecl.
- TemplateTemplateParmDecl *
- getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
-
- TemplateTemplateParmDecl *findCanonicalTemplateTemplateParmDeclInternal(
- TemplateTemplateParmDecl *TTP) const;
- TemplateTemplateParmDecl *insertCanonicalTemplateTemplateParmDeclInternal(
- TemplateTemplateParmDecl *CanonTTP) const;
-
/// Type Query functions. If the type is an instance of the specified class,
/// return the Type pointer for the underlying maximally pretty type. This
/// is a member of ASTContext because this may need to do some amount of
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 33336d57b6298..90537d47dd9c9 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -877,14 +877,11 @@ let Class = PropertyTypeCase<TemplateArgument, "Expression"> in {
def : Property<"expression", ExprRef> {
let Read = [{ node.getAsExpr() }];
}
- def : Property<"IsCanonical", Bool> {
- let Read = [{ node.isCanonicalExpr() }];
- }
def : Property<"isDefaulted", Bool> {
let Read = [{ node.getIsDefaulted() }];
}
def : Creator<[{
- return TemplateArgument(expression, IsCanonical, isDefaulted);
+ return TemplateArgument(expression, isDefaulted);
}]>;
}
let Class = PropertyTypeCase<TemplateArgument, "Pack"> in {
diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index 279feb858e665..bea624eb04942 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -167,8 +167,6 @@ class TemplateArgument {
unsigned Kind : 31;
LLVM_PREFERRED_TYPE(bool)
unsigned IsDefaulted : 1;
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsCanonicalExpr : 1;
uintptr_t V;
};
union {
@@ -189,8 +187,7 @@ class TemplateArgument {
public:
/// Construct an empty, invalid template argument.
- constexpr TemplateArgument()
- : TypeOrValue{Null, /*IsDefaulted=*/0, /*IsCanonicalExpr=*/0, /*V=*/0} {}
+ constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {}
/// Construct a template type argument.
TemplateArgument(QualType T, bool isNullPtr = false,
@@ -265,10 +262,9 @@ class TemplateArgument {
/// This form of template argument only occurs in template argument
/// lists used for dependent types and for expression; it will not
/// occur in a non-dependent, canonical template argument list.
- TemplateArgument(Expr *E, bool IsCanonical, bool IsDefaulted = false) {
+ explicit TemplateArgument(Expr *E, bool IsDefaulted = false) {
TypeOrValue.Kind = Expression;
TypeOrValue.IsDefaulted = IsDefaulted;
- TypeOrValue.IsCanonicalExpr = IsCanonical;
TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
}
@@ -411,11 +407,6 @@ class TemplateArgument {
return reinterpret_cast<Expr *>(TypeOrValue.V);
}
- bool isCanonicalExpr() const {
- assert(getKind() == Expression && "Unexpected kind");
- return TypeOrValue.IsCanonicalExpr;
- }
-
/// Iterator that traverses the elements of a template argument pack.
using pack_iterator = const TemplateArgument *;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index dc57170bf9160..9f6189440fabf 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -6676,9 +6676,10 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
/// replacement must, recursively, be one of these).
TemplateName Template;
- TemplateSpecializationType(TemplateName T, bool IsAlias,
+ TemplateSpecializationType(TemplateName T,
ArrayRef<TemplateArgument> Args,
- QualType Underlying);
+ QualType Canon,
+ QualType Aliased);
public:
/// Determine whether any of the given template arguments are dependent.
@@ -6746,7 +6747,7 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
- ArrayRef<TemplateArgument> Args, QualType Underlying,
+ ArrayRef<TemplateArgument> Args,
const ASTContext &Context);
static bool classof(const Type *T) {
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 3bf9239e9cbf5..66d490850678a 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -737,19 +737,39 @@ let Class = DependentAddressSpaceType in {
}
let Class = TemplateSpecializationType in {
+ def : Property<"dependent", Bool> {
+ let Read = [{ node->isDependentType() }];
+ }
def : Property<"templateName", TemplateName> {
let Read = [{ node->getTemplateName() }];
}
- def : Property<"args", Array<TemplateArgument>> {
+ def : Property<"templateArguments", Array<TemplateArgument>> {
let Read = [{ node->template_arguments() }];
}
- def : Property<"UnderlyingType", QualType> {
- let Read = [{ node->isCanonicalUnqualified() ? QualType() :
- node->desugar() }];
+ def : Property<"underlyingType", Optional<QualType>> {
+ let Read = [{
+ node->isTypeAlias()
+ ? std::optional<QualType>(node->getAliasedType())
+ : node->isCanonicalUnqualified()
+ ? std::nullopt
+ : std::optional<QualType>(node->getCanonicalTypeInternal())
+ }];
}
def : Creator<[{
- return ctx.getTemplateSpecializationType(templateName, args, std::nullopt, UnderlyingType);
+ QualType result;
+ if (!underlyingType) {
+ result = ctx.getCanonicalTemplateSpecializationType(templateName,
+ templateArguments);
+ } else {
+ result = ctx.getTemplateSpecializationType(templateName,
+ templateArguments,
+ *underlyingType);
+ }
+ if (dependent)
+ const_cast<Type *>(result.getTypePtr())
+ ->addDependence(TypeDependence::DependentInstantiation);
+ return result;
}]>;
}
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b8e6245230475..00e2fa267a460 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -844,31 +844,6 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
return CanonTTP;
}
-TemplateTemplateParmDecl *
-ASTContext::findCanonicalTemplateTemplateParmDeclInternal(
- TemplateTemplateParmDecl *TTP) const {
- llvm::FoldingSetNodeID ID;
- CanonicalTemplateTemplateParm::Profile(ID, *this, TTP);
- void *InsertPos = nullptr;
- CanonicalTemplateTemplateParm *Canonical =
- CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
- return Canonical ? Canonical->getParam() : nullptr;
-}
-
-TemplateTemplateParmDecl *
-ASTContext::insertCanonicalTemplateTemplateParmDeclInternal(
- TemplateTemplateParmDecl *CanonTTP) const {
- llvm::FoldingSetNodeID ID;
- CanonicalTemplateTemplateParm::Profile(ID, *this, CanonTTP);
- void *InsertPos = nullptr;
- if (auto *Existing =
- CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos))
- return Existing->getParam();
- CanonTemplateTemplateParms.InsertNode(
- new (*this) CanonicalTemplateTemplateParm(CanonTTP), InsertPos);
- return CanonTTP;
-}
-
/// Check if a type can have its sanitizer instrumentation elided based on its
/// presence within an ignorelist.
bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
@@ -3108,19 +3083,12 @@ static auto getCanonicalTemplateArguments(const ASTContext &C,
ArrayRef<TemplateArgument> Args,
bool &AnyNonCanonArgs) {
SmallVector<TemplateArgument, 16> CanonArgs(Args);
- AnyNonCanonArgs |= C.canonicalizeTemplateArguments(CanonArgs);
- return CanonArgs;
-}
-
-bool ASTContext::canonicalizeTemplateArguments(
- MutableArrayRef<TemplateArgument> Args) const {
- bool AnyNonCanonArgs = false;
- for (auto &Arg : Args) {
+ for (auto &Arg : CanonArgs) {
TemplateArgument OrigArg = Arg;
- Arg = getCanonicalTemplateArgument(Arg);
+ Arg = C.getCanonicalTemplateArgument(Arg);
AnyNonCanonArgs |= !Arg.structurallyEquals(OrigArg);
}
- return AnyNonCanonArgs;
+ return CanonArgs;
}
//===----------------------------------------------------------------------===//
@@ -5570,121 +5538,132 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
return QualType(TypeParm, 0);
}
-TypeSourceInfo *ASTContext::getTemplateSpecializationTypeInfo(
- TemplateName Name, SourceLocation NameLoc,
- const TemplateArgumentListInfo &SpecifiedArgs,
- ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
- QualType TST = getTemplateSpecializationType(Name, SpecifiedArgs.arguments(),
- CanonicalArgs, Underlying);
+TypeSourceInfo *
+ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo &Args,
+ QualType Underlying) const {
+ assert(!Name.getAsDependentTemplateName() &&
+ "No dependent template names here!");
+ QualType TST =
+ getTemplateSpecializationType(Name, Args.arguments(), Underlying);
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
TemplateSpecializationTypeLoc TL =
DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>();
TL.setTemplateKeywordLoc(SourceLocation());
TL.setTemplateNameLoc(NameLoc);
- TL.setLAngleLoc(SpecifiedArgs.getLAngleLoc());
- TL.setRAngleLoc(SpecifiedArgs.getRAngleLoc());
+ TL.setLAngleLoc(Args.getLAngleLoc());
+ TL.setRAngleLoc(Args.getRAngleLoc());
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- TL.setArgLocInfo(i, SpecifiedArgs[i].getLocInfo());
+ TL.setArgLocInfo(i, Args[i].getLocInfo());
return DI;
}
-QualType ASTContext::getTemplateSpecializationType(
- TemplateName Template, ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
- ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
- SmallVector<TemplateArgument, 4> SpecifiedArgVec;
- SpecifiedArgVec.reserve(SpecifiedArgs.size());
- for (const TemplateArgumentLoc &Arg : SpecifiedArgs)
- SpecifiedArgVec.push_back(Arg.getArgument());
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+ ArrayRef<TemplateArgumentLoc> Args,
+ QualType Underlying) const {
+ assert(!Template.getAsDependentTemplateName() &&
+ "No dependent template names here!");
- return getTemplateSpecializationType(Template, SpecifiedArgVec, CanonicalArgs,
- Underlying);
+ SmallVector<TemplateArgument, 4> ArgVec;
+ ArgVec.reserve(Args.size());
+ for (const TemplateArgumentLoc &Arg : Args)
+ ArgVec.push_back(Arg.getArgument());
+
+ return getTemplateSpecializationType(Template, ArgVec, Underlying);
}
-[[maybe_unused]] static bool
-hasAnyPackExpansions(ArrayRef<TemplateArgument> Args) {
+#ifndef NDEBUG
+static bool hasAnyPackExpansions(ArrayRef<TemplateArgument> Args) {
for (const TemplateArgument &Arg : Args)
if (Arg.isPackExpansion())
return true;
- return false;
-}
-QualType ASTContext::getCanonicalTemplateSpecializationType(
- TemplateName Template, ArrayRef<TemplateArgument> Args) const {
- assert(Template ==
- getCanonicalTemplateName(Template, /*IgnoreDeduced=*/true));
- assert(!Args.empty());
-#ifndef NDEBUG
- for (const auto &Arg : Args)
- assert(Arg.structurallyEquals(getCanonicalTemplateArgument(Arg)));
-#endif
-
- llvm::FoldingSetNodeID ID;
- TemplateSpecializationType::Profile(ID, Template, Args, QualType(), *this);
- void *InsertPos = nullptr;
- if (auto *T = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(T, 0);
-
- void *Mem = Allocate(sizeof(TemplateSpecializationType) +
- sizeof(TemplateArgument) * Args.size(),
- alignof(TemplateSpecializationType));
- auto *Spec = new (Mem)
- TemplateSpecializationType(Template, /*IsAlias=*/false, Args, QualType());
- assert(Spec->isDependentType() &&
- "canonical template specialization must be dependent");
- Types.push_back(Spec);
- TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
- return QualType(Spec, 0);
+ return true;
}
+#endif
-QualType ASTContext::getTemplateSpecializationType(
- TemplateName Template, ArrayRef<TemplateArgument> SpecifiedArgs,
- ArrayRef<TemplateArgument> CanonicalArgs, QualType Underlying) const {
- assert(!Template.getUnderlying().getAsDependentTemplateName() &&
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+ ArrayRef<TemplateArgument> Args,
+ QualType Underlying) const {
+ assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
const auto *TD = Template.getAsTemplateDecl(/*IgnoreDeduced=*/true);
bool IsTypeAlias = TD && TD->isTypeAlias();
- if (Underlying.isNull()) {
- TemplateName CanonTemplate =
- getCanonicalTemplateName(Template, /*IgnoreDeduced=*/true);
- bool NonCanonical = Template != CanonTemplate;
- SmallVector<TemplateArgument, 4> CanonArgsVec;
- if (CanonicalArgs.empty()) {
- CanonArgsVec = SmallVector<TemplateArgument, 4>(SpecifiedArgs);
- NonCanonical |= canonicalizeTemplateArguments(CanonArgsVec);
- CanonicalArgs = CanonArgsVec;
- } else {
- NonCanonical |= !llvm::equal(
- SpecifiedArgs, CanonicalArgs,
- [](const TemplateArgument &A, const TemplateArgument &B) {
- return A.structurallyEquals(B);
- });
- }
-
- // We can get here with an alias template when the specialization
- // contains a pack expansion that does not match up with a parameter
- // pack, or a builtin template which cannot be resolved due to dependency.
- assert((!isa_and_nonnull<TypeAliasTemplateDecl>(TD) ||
- hasAnyPackExpansions(CanonicalArgs)) &&
+ QualType CanonType;
+ if (!Underlying.isNull())
+ CanonType = getCanonicalType(Underlying);
+ else {
+ // We can get here with an alias template when the specialization contains
+ // a pack expansion that does not match up with a parameter pack.
+ assert((!IsTypeAlias || hasAnyPackExpansions(Args)) &&
"Caller must compute aliased type");
IsTypeAlias = false;
-
- Underlying =
- getCanonicalTemplateSpecializationType(CanonTemplate, CanonicalArgs);
- if (!NonCanonical)
- return Underlying;
+ CanonType = getCanonicalTemplateSpecializationType(Template, Args);
}
+
+ // Allocate the (non-canonical) template specialization type, but don't
+ // try to unique it: these types typically have location information that
+ // we don't unique and don't want to lose.
void *Mem = Allocate(sizeof(TemplateSpecializationType) +
- sizeof(TemplateArgument) * SpecifiedArgs.size() +
+ sizeof(TemplateArgument) * Args.size() +
(IsTypeAlias ? sizeof(QualType) : 0),
alignof(TemplateSpecializationType));
- auto *Spec = new (Mem) TemplateSpecializationType(Template, IsTypeAlias,
- SpecifiedArgs, Underlying);
+ auto *Spec
+ = new (Mem) TemplateSpecializationType(Template, Args, CanonType,
+ IsTypeAlias ? Underlying : QualType());
+
Types.push_back(Spec);
return QualType(Spec, 0);
}
+QualType ASTContext::getCanonicalTemplateSpecializationType(
+ TemplateName Template, ArrayRef<TemplateArgument> Args) const {
+ assert(!Template.getAsDependentTemplateName() &&
+ "No dependent template names here!");
+
+ // Build the canonical template specialization type.
+ // Any DeducedTemplateNames are ignored, because the effective name of a TST
+ // accounts for the TST arguments laid over any default arguments contained in
+ // its name.
+ TemplateName CanonTemplate =
+ getCanonicalTemplateName(Template, /*IgnoreDeduced=*/true);
+
+ bool AnyNonCanonArgs = false;
+ auto CanonArgs =
+ ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
+
+ // Determine whether this canonical template specialization type already
+ // exists.
+ llvm::FoldingSetNodeID ID;
+ TemplateSpecializationType::Profile(ID, CanonTemplate,
+ CanonArgs, *this);
+
+ void *InsertPos = nullptr;
+ TemplateSpecializationType *Spec
+ = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!Spec) {
+ // Allocate a new canonical template specialization type.
+ void *Mem = Allocate((sizeof(TemplateSpecializationType) +
+ sizeof(TemplateArgument) * CanonArgs.size()),
+ alignof(TemplateSpecializationType));
+ Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
+ CanonArgs,
+ QualType(), QualType());
+ Types.push_back(Spec);
+ TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+ }
+
+ assert(Spec->isDependentType() &&
+ "Non-dependent template-id type must have a canonical type");
+ return QualType(Spec, 0);
+}
+
QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
QualType NamedType,
@@ -5874,7 +5853,7 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) const {
if (NTTP->isParameterPack())
E = new (*this) PackExpansionExpr(E, NTTP->getLocation(), std::nullopt);
- Arg = TemplateArgument(E, /*IsCanonical=*/false);
+ Arg = TemplateArgument(E);
} else {
auto *TTP = cast<TemplateTemplateParmDecl>(Param);
TemplateName Name = getQualifiedTemplateName(
@@ -6482,9 +6461,9 @@ QualType ASTContext::getAutoTypeInternal(
auto CanonicalConceptArgs = ::getCanonicalTemplateArguments(
*this, TypeConstraintArgs, AnyNonCanonArgs);
if (CanonicalConcept != TypeConstraintConcept || AnyNonCanonArgs) {
- Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
- CanonicalConcept, CanonicalConceptArgs,
- /*IsCanon=*/true);
+ Canon =
+ getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack,
+ CanonicalConcept, CanonicalConceptArgs, true);
}
}
}
@@ -7564,8 +7543,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
return Arg;
case TemplateArgument::Expression:
- return TemplateArgument(Arg.getAsExpr(), /*IsCanonical=*/true,
- Arg.getIsDefaulted());
+ return Arg;
case TemplateArgument::Declaration: {
auto *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
@@ -8221,7 +8199,8 @@ QualType ASTContext::getObjCSuperType() const {
void ASTContext::setCFConstantStringType(QualType T) {
const auto *TD = T->castAs<TypedefType>();
CFConstantStringTypeDecl = cast<TypedefDecl>(TD->getDecl());
- const auto *TagType = TD->castAs<RecordType>();
+ const auto *TagType =
+ CFConstantStringTypeDecl->getUnderlyingType()->castAs<RecordType>();
CFConstantStringTagDecl = TagType->getDecl();
}
@@ -14033,7 +14012,7 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
::getCommonTemplateNameChecked(Ctx, TX->getTemplateName(),
TY->getTemplateName(),
/*IgnoreDeduced=*/true),
- As, /*CanonicalArgs=*/std::nullopt, X->getCanonicalTypeInternal());
+ As, X->getCanonicalTypeInternal());
}
case Type::Decltype: {
const auto *DX = cast<DecltypeType>(X);
@@ -14273,12 +14252,11 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
TY->getTemplateName(), /*IgnoreDeduced=*/true);
if (!CTN.getAsVoidPointer())
return QualType();
- SmallVector<TemplateArgument, 8> As;
- if (getCommonTemplateArguments(Ctx, As, TX->template_arguments(),
+ SmallVector<TemplateArgument, 8> Args;
+ if (getCommonTemplateArguments(Ctx, Args, TX->template_arguments(),
TY->template_arguments()))
return QualType();
- return Ctx.getTemplateSpecializationType(CTN, As,
- /*CanonicalArgs=*/std::nullopt,
+ return Ctx.getTemplateSpecializationType(CTN, Args,
Ctx.getQualifiedType(Underlying));
}
case Type::Typedef: {
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 5baff6c1e13e9..ccfef9c7ae361 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -128,7 +128,7 @@ QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
if (DesugarArgument) {
ShouldAKA = true;
QT = Context.getTemplateSpecializationType(
- TST->getTemplateName(), Args, /*CanonicalArgs=*/std::nullopt, QT);
+ TST->getTemplateName(), Args, QT);
}
break;
}
@@ -1142,9 +1142,9 @@ class TemplateDiff {
return nullptr;
Ty = Context.getTemplateSpecializationType(
- TemplateName(CTSD->getSpecializedTemplate()),
- CTSD->getTemplateArgs().asArray(), /*CanonicalArgs=*/std::nullopt,
- Ty.getLocalUnqualifiedType().getCanonicalType());
+ TemplateName(CTSD->getSpecializedTemplate()),
+ CTSD->getTemplateArgs().asArray(),
+ Ty.getLocalUnqualifiedType().getCanonicalType());
return Ty->getAs<TemplateSpecializationType>();
}
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 742ff18031337..f7cd54e447bbf 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -893,8 +893,7 @@ ASTNodeImporter::import(const TemplateArgument &From) {
case TemplateArgument::Expression:
if (ExpectedExpr ToExpr = import(From.getAsExpr()))
- return TemplateArgument(*ToExpr, From.isCanonicalExpr(),
- From.getIsDefaulted());
+ return TemplateArgument(*ToExpr, From.getIsDefaulted());
else
return ToExpr.takeError();
@@ -1661,15 +1660,18 @@ ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
ImportTemplateArguments(T->template_arguments(), ToTemplateArgs))
return std::move(Err);
- if (T->isCanonicalUnqualified())
- return Importer.getToContext().getCanonicalTemplateSpecializationType(
- *ToTemplateOrErr, ToTemplateArgs);
-
- ExpectedType ToUnderlyingOrErr = import(T->desugar());
- if (!ToUnderlyingOrErr)
- return ToUnderlyingOrErr.takeError();
- return Importer.getToContext().getTemplateSpecializationType(
- *ToTemplateOrErr, ToTemplateArgs, std::nullopt, *ToUnderlyingOrErr);
+ QualType ToCanonType;
+ if (!T->isCanonicalUnqualified()) {
+ QualType FromCanonType
+ = Importer.getFromContext().getCanonicalType(QualType(T, 0));
+ if (ExpectedType TyOrErr = import(FromCanonType))
+ ToCanonType = *TyOrErr;
+ else
+ return TyOrErr.takeError();
+ }
+ return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr,
+ ToTemplateArgs,
+ ToCanonType);
}
ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
@@ -6016,12 +6018,6 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
ExpectedDecl
ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
- bool IsCanonical = false;
- if (auto *CanonD = Importer.getFromContext()
- .findCanonicalTemplateTemplateParmDeclInternal(D);
- CanonD == D)
- IsCanonical = true;
-
// Import the name of this declaration.
auto NameOrErr = import(D->getDeclName());
if (!NameOrErr)
@@ -6049,10 +6045,6 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
if (Error Err = importTemplateParameterDefaultArgument(D, ToD))
return Err;
- if (IsCanonical)
- return Importer.getToContext()
- .insertCanonicalTemplateTemplateParmDeclInternal(ToD);
-
return ToD;
}
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 79a36109276f0..e8e2cad721981 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -671,11 +671,8 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
ASTContext &Context = getASTContext();
TemplateName Name = Context.getQualifiedTemplateName(
/*NNS=*/nullptr, /*TemplateKeyword=*/false, TemplateName(this));
- auto TemplateArgs = getTemplateParameters()->getInjectedTemplateArgs(Context);
- CommonPtr->InjectedClassNameType =
- Context.getTemplateSpecializationType(Name,
- /*SpecifiedArgs=*/TemplateArgs,
- /*CanonicalArgs=*/std::nullopt);
+ CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(
+ Name, getTemplateParameters()->getInjectedTemplateArgs(Context));
return CommonPtr->InjectedClassNameType;
}
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 4d11a3b623314..5c151254c36e7 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -140,7 +140,7 @@ static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
if (MightHaveChanged) {
QualType QT = Ctx.getTemplateSpecializationType(
TST->getTemplateName(), FQArgs,
- /*CanonicalArgs=*/std::nullopt, TST->desugar());
+ TST->getCanonicalTypeInternal());
// getTemplateSpecializationType returns a fully qualified
// version of the specialization itself, so no need to qualify
// it.
@@ -172,7 +172,6 @@ static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
TemplateName TN(TSTDecl->getSpecializedTemplate());
QualType QT = Ctx.getTemplateSpecializationType(
TN, FQArgs,
- /*CanonicalArgs=*/std::nullopt,
TSTRecord->getCanonicalTypeInternal());
// getTemplateSpecializationType returns a fully qualified
// version of the specialization itself, so no need to qualify
diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index ad4f919b7483e..42da4e6ca9964 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -414,16 +414,9 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
getAsStructuralValue().Profile(ID);
break;
- case Expression: {
- const Expr *E = getAsExpr();
- bool IsCanonical = isCanonicalExpr();
- ID.AddBoolean(IsCanonical);
- if (IsCanonical)
- E->Profile(ID, Context, true);
- else
- ID.AddPointer(E);
+ case Expression:
+ getAsExpr()->Profile(ID, Context, true);
break;
- }
case Pack:
ID.AddInteger(Args.NumArgs);
@@ -438,11 +431,9 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
switch (getKind()) {
case Null:
case Type:
+ case Expression:
case NullPtr:
return TypeOrValue.V == Other.TypeOrValue.V;
- case Expression:
- return TypeOrValue.V == Other.TypeOrValue.V &&
- TypeOrValue.IsCanonicalExpr == Other.TypeOrValue.IsCanonicalExpr;
case Template:
case TemplateExpansion:
@@ -487,8 +478,7 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
return getAsType()->castAs<PackExpansionType>()->getPattern();
case Expression:
- return TemplateArgument(cast<PackExpansionExpr>(getAsExpr())->getPattern(),
- isCanonicalExpr());
+ return TemplateArgument(cast<PackExpansionExpr>(getAsExpr())->getPattern());
case TemplateExpansion:
return TemplateArgument(getAsTemplateOrTemplatePattern());
@@ -665,7 +655,6 @@ static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
case TemplateArgument::Expression:
- // FIXME: Support printing expressions as canonical
return DB << Arg.getAsExpr();
case TemplateArgument::Pack: {
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index a62f287512156..f6dffeb0a1a8f 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -4388,19 +4388,17 @@ bool TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
}
TemplateSpecializationType::TemplateSpecializationType(
- TemplateName T, bool IsAlias, ArrayRef<TemplateArgument> Args,
- QualType Underlying)
- : Type(TemplateSpecialization,
- Underlying.isNull() ? QualType(this, 0)
- : Underlying.getCanonicalType(),
- (Underlying.isNull()
+ TemplateName T, ArrayRef<TemplateArgument> Args, QualType Canon,
+ QualType AliasedType)
+ : Type(TemplateSpecialization, Canon.isNull() ? QualType(this, 0) : Canon,
+ (Canon.isNull()
? TypeDependence::DependentInstantiation
- : toSemanticDependence(Underlying->getDependence())) |
+ : toSemanticDependence(Canon->getDependence())) |
(toTypeDependence(T.getDependence()) &
TypeDependence::UnexpandedPack)),
Template(T) {
TemplateSpecializationTypeBits.NumArgs = Args.size();
- TemplateSpecializationTypeBits.TypeAlias = IsAlias;
+ TemplateSpecializationTypeBits.TypeAlias = !AliasedType.isNull();
assert(!T.getAsDependentTemplateName() &&
"Use DependentTemplateSpecializationType for dependent template-name");
@@ -4412,8 +4410,7 @@ TemplateSpecializationType::TemplateSpecializationType(
T.getKind() == TemplateName::DeducedTemplate) &&
"Unexpected template name for TemplateSpecializationType");
- auto *TemplateArgs =
- const_cast<TemplateArgument *>(template_arguments().data());
+ auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1);
for (const TemplateArgument &Arg : Args) {
// Update instantiation-dependent, variably-modified, and error bits.
// If the canonical type exists and is non-dependent, the template
@@ -4431,10 +4428,11 @@ TemplateSpecializationType::TemplateSpecializationType(
new (TemplateArgs++) TemplateArgument(Arg);
}
- // Store the aliased type after the template arguments, if this is a type
- // alias template specialization.
- if (IsAlias)
- *reinterpret_cast<QualType *>(TemplateArgs) = Underlying;
+ // Store the aliased type if this is a type alias template specialization.
+ if (isTypeAlias()) {
+ auto *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
+ *reinterpret_cast<QualType *>(Begin + Args.size()) = AliasedType;
+ }
}
QualType TemplateSpecializationType::getAliasedType() const {
@@ -4444,19 +4442,17 @@ QualType TemplateSpecializationType::getAliasedType() const {
void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) {
- Profile(ID, Template, template_arguments(),
- isSugared() ? desugar() : QualType(), Ctx);
+ Profile(ID, Template, template_arguments(), Ctx);
+ if (isTypeAlias())
+ getAliasedType().Profile(ID);
}
-void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
- TemplateName T,
- ArrayRef<TemplateArgument> Args,
- QualType Underlying,
- const ASTContext &Context) {
+void
+TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
+ TemplateName T,
+ ArrayRef<TemplateArgument> Args,
+ const ASTContext &Context) {
T.Profile(ID);
- Underlying.Profile(ID);
-
- ID.AddInteger(Args.size());
for (const TemplateArgument &Arg : Args)
Arg.Profile(ID, Context);
}
@@ -5268,9 +5264,9 @@ AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
}
void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
- QualType Deduced, AutoTypeKeyword Keyword,
- bool IsDependent, ConceptDecl *CD,
- ArrayRef<TemplateArgument> Arguments) {
+ QualType Deduced, AutoTypeKeyword Keyword,
+ bool IsDependent, ConceptDecl *CD,
+ ArrayRef<TemplateArgument> Arguments) {
ID.AddPointer(Deduced.getAsOpaquePtr());
ID.AddInteger((unsigned)Keyword);
ID.AddBoolean(IsDependent);
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index f497106223df4..68ee006c6cf00 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -69,14 +69,17 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
// Look through type alias templates, per C++0x [temp.dep.type]p1.
NNSType = Context.getCanonicalType(NNSType);
- if (const auto *SpecType =
- dyn_cast<TemplateSpecializationType>(NNSType)) {
+ if (const TemplateSpecializationType *SpecType
+ = NNSType->getAs<TemplateSpecializationType>()) {
// We are entering the context of the nested name specifier, so try to
// match the nested name specifier to either a primary class template
// or a class template partial specialization.
- if (ClassTemplateDecl *ClassTemplate =
- dyn_cast_or_null<ClassTemplateDecl>(
- SpecType->getTemplateName().getAsTemplateDecl())) {
+ if (ClassTemplateDecl *ClassTemplate
+ = dyn_cast_or_null<ClassTemplateDecl>(
+ SpecType->getTemplateName().getAsTemplateDecl())) {
+ QualType ContextType =
+ Context.getCanonicalType(QualType(SpecType, 0));
+
// FIXME: The fallback on the search of partial
// specialization using ContextType should be eventually removed since
// it doesn't handle the case of constrained template parameters
@@ -97,8 +100,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
SpecType->template_arguments(), *L, Pos);
}
} else {
- PartialSpec =
- ClassTemplate->findPartialSpecialization(QualType(SpecType, 0));
+ PartialSpec = ClassTemplate->findPartialSpecialization(ContextType);
}
if (PartialSpec) {
@@ -120,7 +122,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
// into that class template definition.
QualType Injected =
ClassTemplate->getInjectedClassNameSpecialization();
- if (Context.hasSameType(Injected, QualType(SpecType, 0)))
+ if (Context.hasSameType(Injected, ContextType))
return ClassTemplate->getTemplatedDecl();
}
} else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c25daaa022f49..25b7bd0e16942 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2183,7 +2183,7 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
case LOLR_Template: {
TemplateArgumentListInfo ExplicitArgs;
- TemplateArgument Arg(Lit, /*IsCanonical=*/false);
+ TemplateArgument Arg(Lit);
TemplateArgumentLocInfo ArgInfo(Lit);
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
return BuildLiteralOperatorCall(R, OpNameInfo, {}, StringTokLocs.back(),
@@ -21108,22 +21108,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
Diag(Temp->getLocation(), diag::note_referenced_type_template)
<< IsTypeAliasTemplateDecl;
- TemplateArgumentListInfo TAL(ULE->getLAngleLoc(), ULE->getRAngleLoc());
- bool HasAnyDependentTA = false;
- for (const TemplateArgumentLoc &Arg : ULE->template_arguments()) {
- HasAnyDependentTA |= Arg.getArgument().isDependent();
- TAL.addArgument(Arg);
- }
-
- QualType TST;
- {
- SFINAETrap Trap(*this);
- TST = CheckTemplateIdType(TN, NameInfo.getBeginLoc(), TAL);
- }
- if (TST.isNull())
- TST = Context.getTemplateSpecializationType(
- TN, ULE->template_arguments(), /*CanonicalArgs=*/std::nullopt,
- HasAnyDependentTA ? Context.DependentTy : Context.IntTy);
+ QualType TST =
+ Context.getTemplateSpecializationType(TN, ULE->template_arguments());
QualType ET =
Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS, TST);
return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {},
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 58134603424a6..a77ca779a9ee3 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3713,8 +3713,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (StringLit) {
SFINAETrap Trap(*this);
CheckTemplateArgumentInfo CTAI;
- TemplateArgumentLoc Arg(
- TemplateArgument(StringLit, /*IsCanonical=*/false), StringLit);
+ TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit);
if (CheckTemplateArgument(
Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(),
/*ArgumentPackIndex=*/0, CTAI, CTAK_Specified) ||
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 40e29bb18807a..3d7fa38272e6a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -909,7 +909,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
case ParsedTemplateArgument::NonType: {
Expr *E = static_cast<Expr *>(Arg.getAsExpr());
- return TemplateArgumentLoc(TemplateArgument(E, /*IsCanonical=*/false), E);
+ return TemplateArgumentLoc(TemplateArgument(E), E);
}
case ParsedTemplateArgument::Template: {
@@ -1576,9 +1576,8 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
return Param;
Param->setDefaultArgument(
- Context, getTrivialTemplateArgumentLoc(
- TemplateArgument(Default, /*IsCanonical=*/false),
- QualType(), SourceLocation()));
+ Context, getTrivialTemplateArgumentLoc(TemplateArgument(Default),
+ QualType(), SourceLocation()));
}
return Param;
@@ -3251,7 +3250,8 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
TemplateArgument NumArgsArg = Converted[2];
if (NumArgsArg.isDependent())
- return QualType();
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
+ Converted);
TemplateArgumentListInfo SyntheticTemplateArgs;
// The type argument, wrapped in substitution sugar, gets reused as the
@@ -3288,11 +3288,12 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
// __type_pack_element<Index, T_1, ..., T_N>
// are treated like T_Index.
assert(Converted.size() == 2 &&
- "__type_pack_element should be given an index and a parameter pack");
+ "__type_pack_element should be given an index and a parameter pack");
TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
if (IndexArg.isDependent() || Ts.isDependent())
- return QualType();
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
+ Converted);
llvm::APSInt Index = IndexArg.getAsIntegral();
assert(Index >= 0 && "the index used with __type_pack_element should be of "
@@ -3312,9 +3313,12 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
case BTK__builtin_common_type: {
assert(Converted.size() == 4);
if (llvm::any_of(Converted, [](auto &C) { return C.isDependent(); }))
- return QualType();
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
+ Converted);
TemplateName BaseTemplate = Converted[0].getAsTemplate();
+ TemplateName HasTypeMember = Converted[1].getAsTemplate();
+ QualType HasNoTypeMember = Converted[2].getAsType();
ArrayRef<TemplateArgument> Ts = Converted[3].getPackAsArray();
if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts);
!CT.isNull()) {
@@ -3322,10 +3326,9 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
TAs.addArgument(TemplateArgumentLoc(
TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo(
CT, TemplateArgs[1].getLocation())));
- TemplateName HasTypeMember = Converted[1].getAsTemplate();
+
return SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs);
}
- QualType HasNoTypeMember = Converted[2].getAsType();
return HasNoTypeMember;
}
}
@@ -3489,19 +3492,20 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
resolveAssumedTemplateNameAsType(/*Scope=*/nullptr, Name, TemplateLoc))
return QualType();
- TemplateDecl *Template;
- DefaultArguments DefaultArgs;
- if (const SubstTemplateTemplateParmPackStorage *S =
- Name.getAsSubstTemplateTemplateParmPack()) {
- Template = S->getParameterPack();
- } else {
- std::tie(Template, DefaultArgs) = Name.getTemplateDeclAndDefaultArgs();
- if (!Template || isa<FunctionTemplateDecl>(Template) ||
- isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) {
- Diag(TemplateLoc, diag::err_template_id_not_a_type) << Name;
- NoteAllFoundTemplates(Name);
- return QualType();
- }
+ auto [Template, DefaultArgs] = Name.getTemplateDeclAndDefaultArgs();
+
+ if (!Template || isa<FunctionTemplateDecl>(Template) ||
+ isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) {
+ // We might have a substituted template template parameter pack. If so,
+ // build a template specialization type for it.
+ if (Name.getAsSubstTemplateTemplateParmPack())
+ return Context.getTemplateSpecializationType(Name,
+ TemplateArgs.arguments());
+
+ Diag(TemplateLoc, diag::err_template_id_not_a_type)
+ << Name;
+ NoteAllFoundTemplates(Name);
+ return QualType();
}
// Check that the template argument list is well-formed for this
@@ -3515,11 +3519,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
QualType CanonType;
- if (isa<TemplateTemplateParmDecl>(Template)) {
- // We might have a substituted template template parameter pack. If so,
- // build a template specialization type for it.
- } else if (TypeAliasTemplateDecl *AliasTemplate =
- dyn_cast<TypeAliasTemplateDecl>(Template)) {
+ if (TypeAliasTemplateDecl *AliasTemplate =
+ dyn_cast<TypeAliasTemplateDecl>(Template)) {
// Find the canonical type for this type alias template specialization.
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
@@ -3601,9 +3602,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
//
// template<typename T, typename U = T> struct A;
CanonType = Context.getCanonicalTemplateSpecializationType(
- Context.getCanonicalTemplateName(Name, /*IgnoreDeduced=*/true),
- CTAI.CanonicalConverted);
- assert(CanonType->isCanonicalUnqualified());
+ Name, CTAI.CanonicalConverted);
// This might work out to be a current instantiation, in which
// case the canonical type needs to be the InjectedClassNameType.
@@ -3689,8 +3688,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Build the fully-sugared type for this class template
// specialization, which refers back to the class template
// specialization we created or found.
- return Context.getTemplateSpecializationType(
- Name, TemplateArgs.arguments(), CTAI.CanonicalConverted, CanonType);
+ return Context.getTemplateSpecializationType(Name, TemplateArgs.arguments(),
+ CanonType);
}
void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName,
@@ -5287,7 +5286,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
// If the resulting expression is new, then use it in place of the
// old expression in the template argument.
if (R != E) {
- TemplateArgument TA(R, /*IsCanonical=*/false);
+ TemplateArgument TA(R);
ArgLoc = TemplateArgumentLoc(TA, R);
}
break;
@@ -6477,7 +6476,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction(
// Stop checking the precise nature of the argument if it is value dependent,
// it should be checked when instantiated.
if (Arg->isValueDependent()) {
- SugaredConverted = TemplateArgument(ArgIn, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(ArgIn);
CanonicalConverted =
S.Context.getCanonicalTemplateArgument(SugaredConverted);
return false;
@@ -6668,7 +6667,7 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param,
if (VD->getType()->isMemberPointerType()) {
if (isa<NonTypeTemplateParmDecl>(VD)) {
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
S.Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
@@ -6734,7 +6733,7 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param,
// Okay: this is the address of a non-static member, and therefore
// a member pointer constant.
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
S.Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
@@ -6785,7 +6784,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (DeductionArg->isTypeDependent()) {
auto *AT = dyn_cast<AutoType>(DeducedT);
if (AT && AT->isDecltypeAuto()) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted = TemplateArgument(
Context.getCanonicalTemplateArgument(SugaredConverted));
return Arg;
@@ -6859,7 +6858,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (E.isInvalid())
return ExprError();
setDeductionArg(E.get());
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted = TemplateArgument(
Context.getCanonicalTemplateArgument(SugaredConverted));
return Arg;
@@ -6890,7 +6889,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// normal template rules apply: we accept the template if it would be valid
// for any number of expansions (i.e. none).
if (ArgPE && !StrictCheck) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted = TemplateArgument(
Context.getCanonicalTemplateArgument(SugaredConverted));
return Arg;
@@ -6916,7 +6915,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return Arg;
}
if (isa<NonTypeTemplateParmDecl>(ND)) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
@@ -6973,7 +6972,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// permitted (and expected) to be unable to determine a value.
if (ArgResult.get()->isValueDependent()) {
setDeductionArg(ArgResult.get());
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
@@ -7011,7 +7010,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
!Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {
if (ArgPE) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
@@ -7042,7 +7041,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_
diff );
if (ArgPE) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
@@ -7087,7 +7086,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// We can't check arbitrary value-dependent arguments.
if (DeductionArg->isValueDependent()) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
@@ -7104,7 +7103,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
: Context.getTypeSize(IntegerType));
if (ArgPE) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
@@ -7188,7 +7187,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (DeductionArg->isValueDependent()) {
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
@@ -7244,7 +7243,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
if (ArgPE) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
@@ -7367,7 +7366,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// Deal with parameters of type std::nullptr_t.
if (ParamType->isNullPtrType()) {
if (DeductionArg->isTypeDependent() || DeductionArg->isValueDependent()) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
return Arg;
@@ -7387,7 +7386,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
case NPV_NullPointer:
Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
if (ArgPE) {
- SugaredConverted = TemplateArgument(Arg, /*IsCanonical=*/false);
+ SugaredConverted = TemplateArgument(Arg);
CanonicalConverted =
Context.getCanonicalTemplateArgument(SugaredConverted);
} else {
@@ -8524,34 +8523,17 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
isPartialSpecialization))
return true;
+ // The canonical type
QualType CanonType;
- if (!isPartialSpecialization) {
- // Create a new class template specialization declaration node for
- // this explicit specialization or friend declaration.
- Specialization = ClassTemplateSpecializationDecl::Create(
- Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
- ClassTemplate, CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
- Specialization->setTemplateArgsAsWritten(TemplateArgs);
- SetNestedNameSpecifier(*this, Specialization, SS);
- if (TemplateParameterLists.size() > 0) {
- Specialization->setTemplateParameterListsInfo(Context,
- TemplateParameterLists);
- }
-
- if (!PrevDecl)
- ClassTemplate->AddSpecialization(Specialization, InsertPos);
-
- if (!CurContext->isDependentContext())
- CanonType = Context.getTypeDeclType(Specialization);
- }
-
- TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
- Name, TemplateNameLoc, TemplateArgs, CTAI.CanonicalConverted, CanonType);
-
if (isPartialSpecialization) {
- if (Context.hasSameType(
- WrittenTy->getType(),
- ClassTemplate->getInjectedClassNameSpecialization()) &&
+ // Build the canonical type that describes the converted template
+ // arguments of the class template partial specialization.
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ CanonType = Context.getTemplateSpecializationType(CanonTemplate,
+ CTAI.CanonicalConverted);
+
+ if (Context.hasSameType(CanonType,
+ ClassTemplate->getInjectedClassNameSpecialization()) &&
(!Context.getLangOpts().CPlusPlus20 ||
!TemplateParams->hasAssociatedConstraints())) {
// C++ [temp.class.spec]p9b3:
@@ -8578,8 +8560,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplatePartialSpecializationDecl *Partial =
ClassTemplatePartialSpecializationDecl::Create(
Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams,
- ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(),
- PrevPartial);
+ ClassTemplate, CTAI.CanonicalConverted, CanonType, PrevPartial);
Partial->setTemplateArgsAsWritten(TemplateArgs);
SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
@@ -8597,6 +8578,29 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
PrevPartial->setMemberSpecialization();
CheckTemplatePartialSpecialization(Partial);
+ } else {
+ // Create a new class template specialization declaration node for
+ // this explicit specialization or friend declaration.
+ Specialization = ClassTemplateSpecializationDecl::Create(
+ Context, Kind, DC, KWLoc, TemplateNameLoc, ClassTemplate,
+ CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
+ Specialization->setTemplateArgsAsWritten(TemplateArgs);
+ SetNestedNameSpecifier(*this, Specialization, SS);
+ if (TemplateParameterLists.size() > 0) {
+ Specialization->setTemplateParameterListsInfo(Context,
+ TemplateParameterLists);
+ }
+
+ if (!PrevDecl)
+ ClassTemplate->AddSpecialization(Specialization, InsertPos);
+
+ if (CurContext->isDependentContext()) {
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ CanonType = Context.getTemplateSpecializationType(
+ CanonTemplate, CTAI.CanonicalConverted);
+ } else {
+ CanonType = Context.getTypeDeclType(Specialization);
+ }
}
// C++ [temp.expl.spec]p6:
@@ -8686,6 +8690,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// actually wrote the specialization, rather than formatting the
// name based on the "canonical" representation used to store the
// template arguments in the specialization.
+ TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(
+ Name, TemplateNameLoc, TemplateArgs, CanonType);
FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
TemplateNameLoc,
WrittenTy,
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 772962ac653f7..5dc69a5413db0 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -493,8 +493,8 @@ DeduceNullPtrTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
: CK_NullToPointer)
.get();
return DeduceNonTypeTemplateArgument(
- S, TemplateParams, NTTP, TemplateArgument(Value, /*IsCanonical=*/false),
- Value->getType(), Info, PartialOrdering, Deduced, HasDeducedAnyParam);
+ S, TemplateParams, NTTP, TemplateArgument(Value), Value->getType(), Info,
+ PartialOrdering, Deduced, HasDeducedAnyParam);
}
/// Deduce the value of the given non-type template parameter
@@ -508,8 +508,8 @@ DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool *HasDeducedAnyParam) {
return DeduceNonTypeTemplateArgument(
- S, TemplateParams, NTTP, TemplateArgument(Value, /*IsCanonical=*/false),
- Value->getType(), Info, PartialOrdering, Deduced, HasDeducedAnyParam);
+ S, TemplateParams, NTTP, TemplateArgument(Value), Value->getType(), Info,
+ PartialOrdering, Deduced, HasDeducedAnyParam);
}
/// Deduce the value of the given non-type template parameter
@@ -615,15 +615,12 @@ static TemplateDeductionResult DeduceTemplateArguments(
/// but it may still fail, later, for other reasons.
static const TemplateSpecializationType *getLastTemplateSpecType(QualType QT) {
- const TemplateSpecializationType *LastTST = nullptr;
for (const Type *T = QT.getTypePtr(); /**/; /**/) {
const TemplateSpecializationType *TST =
T->getAs<TemplateSpecializationType>();
- if (!TST)
- return LastTST;
+ assert(TST && "Expected a TemplateSpecializationType");
if (!TST->isSugared())
return TST;
- LastTST = TST;
T = TST->desugar().getTypePtr();
}
}
@@ -2902,7 +2899,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
Expr *E = BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc,
TemplateParam)
.getAs<Expr>();
- return TemplateArgumentLoc(TemplateArgument(E, /*IsCanonical=*/false), E);
+ return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::NullPtr: {
@@ -2917,7 +2914,7 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
case TemplateArgument::Integral:
case TemplateArgument::StructuralValue: {
Expr *E = BuildExpressionFromNonTypeTemplateArgument(Arg, Loc).get();
- return TemplateArgumentLoc(TemplateArgument(E, /*IsCanonical=*/false), E);
+ return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::Template:
@@ -6418,8 +6415,8 @@ Sema::getMoreSpecializedPartialSpecialization(
ClassTemplatePartialSpecializationDecl *PS1,
ClassTemplatePartialSpecializationDecl *PS2,
SourceLocation Loc) {
- QualType PT1 = PS1->getInjectedSpecializationType().getCanonicalType();
- QualType PT2 = PS2->getInjectedSpecializationType().getCanonicalType();
+ QualType PT1 = PS1->getInjectedSpecializationType();
+ QualType PT2 = PS2->getInjectedSpecializationType();
TemplateDeductionInfo Info(Loc);
return getMoreSpecialized(*this, PT1, PT2, PS1, PS2, Info);
@@ -6428,9 +6425,8 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Sema::isMoreSpecializedThanPrimary(
ClassTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
ClassTemplateDecl *Primary = Spec->getSpecializedTemplate();
- QualType PrimaryT =
- Primary->getInjectedClassNameSpecialization().getCanonicalType();
- QualType PartialT = Spec->getInjectedSpecializationType().getCanonicalType();
+ QualType PrimaryT = Primary->getInjectedClassNameSpecialization();
+ QualType PartialT = Spec->getInjectedSpecializationType();
ClassTemplatePartialSpecializationDecl *MaybeSpec =
getMoreSpecialized(*this, PartialT, PrimaryT, Spec, Primary, Info);
@@ -6448,10 +6444,10 @@ Sema::getMoreSpecializedPartialSpecialization(
assert(PS1->getSpecializedTemplate() == PS2->getSpecializedTemplate() &&
"the partial specializations being compared should specialize"
" the same template.");
- TemplateName Name(PS1->getSpecializedTemplate()->getCanonicalDecl());
- QualType PT1 = Context.getCanonicalTemplateSpecializationType(
+ TemplateName Name(PS1->getSpecializedTemplate());
+ QualType PT1 = Context.getTemplateSpecializationType(
Name, PS1->getTemplateArgs().asArray());
- QualType PT2 = Context.getCanonicalTemplateSpecializationType(
+ QualType PT2 = Context.getTemplateSpecializationType(
Name, PS2->getTemplateArgs().asArray());
TemplateDeductionInfo Info(Loc);
@@ -6461,15 +6457,10 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Sema::isMoreSpecializedThanPrimary(
VarTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
VarTemplateDecl *Primary = Spec->getSpecializedTemplate();
- TemplateName Name(Primary->getCanonicalDecl());
-
- SmallVector<TemplateArgument, 8> PrimaryCanonArgs(
- Primary->getInjectedTemplateArgs(Context));
- Context.canonicalizeTemplateArguments(PrimaryCanonArgs);
-
- QualType PrimaryT =
- Context.getCanonicalTemplateSpecializationType(Name, PrimaryCanonArgs);
- QualType PartialT = Context.getCanonicalTemplateSpecializationType(
+ TemplateName Name(Primary);
+ QualType PrimaryT = Context.getTemplateSpecializationType(
+ Name, Primary->getInjectedTemplateArgs(Context));
+ QualType PartialT = Context.getTemplateSpecializationType(
Name, Spec->getTemplateArgs().asArray());
VarTemplatePartialSpecializationDecl *MaybeSpec =
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 108d7e1dbaebc..eb8632d9eb255 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4791,18 +4791,17 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
ClassTemplate->findPartialSpecialization(CTAI.CanonicalConverted,
InstParams, InsertPos);
- // Build the type that describes the converted template arguments of the class
- // template partial specialization.
- TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
- TemplateName(ClassTemplate), TemplArgInfo->getLAngleLoc(),
- InstTemplateArgs, CTAI.CanonicalConverted);
+ // Build the canonical type that describes the converted template
+ // arguments of the class template partial specialization.
+ QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
+ TemplateName(ClassTemplate), CTAI.CanonicalConverted);
// Create the class template partial specialization declaration.
ClassTemplatePartialSpecializationDecl *InstPartialSpec =
ClassTemplatePartialSpecializationDecl::Create(
SemaRef.Context, PartialSpec->getTagKind(), Owner,
PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
- ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(),
+ ClassTemplate, CTAI.CanonicalConverted, CanonType,
/*PrevDecl=*/nullptr);
InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs);
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index dc7e3a0bf8875..3040a30454b0c 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -1286,8 +1286,7 @@ TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern(
Expr *Pattern = Expansion->getPattern();
Ellipsis = Expansion->getEllipsisLoc();
NumExpansions = Expansion->getNumExpansions();
- return TemplateArgumentLoc(
- TemplateArgument(Pattern, Argument.isCanonicalExpr()), Pattern);
+ return TemplateArgumentLoc(TemplateArgument(Pattern), Pattern);
}
case TemplateArgument::TemplateExpansion:
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 21e250e172d5e..13762dc485c32 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3981,9 +3981,7 @@ class TreeTransform {
if (Result.isInvalid())
return TemplateArgumentLoc();
- return TemplateArgumentLoc(TemplateArgument(Result.get(),
- /*IsCanonical=*/false),
- Result.get());
+ return TemplateArgumentLoc(TemplateArgument(Result.get()), Result.get());
}
case TemplateArgument::Template:
@@ -4943,8 +4941,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
E = SemaRef.ActOnConstantExpression(E);
if (E.isInvalid())
return true;
- Output = TemplateArgumentLoc(
- TemplateArgument(E.get(), /*IsCanonical=*/false), E.get());
+ Output = TemplateArgumentLoc(TemplateArgument(E.get()), E.get());
return false;
}
}
@@ -16134,10 +16131,8 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
E->getPackLoc());
if (DRE.isInvalid())
return ExprError();
- ArgStorage = TemplateArgument(
- new (getSema().Context)
- PackExpansionExpr(DRE.get(), E->getPackLoc(), std::nullopt),
- /*IsCanonical=*/false);
+ ArgStorage = TemplateArgument(new (getSema().Context) PackExpansionExpr(
+ DRE.get(), E->getPackLoc(), std::nullopt));
}
PackArgs = ArgStorage;
}
diff --git a/clang/test/CXX/class.derived/class.derived.general/p2.cpp b/clang/test/CXX/class.derived/class.derived.general/p2.cpp
index 1423eeabebf59..888d9cd7a939d 100644
--- a/clang/test/CXX/class.derived/class.derived.general/p2.cpp
+++ b/clang/test/CXX/class.derived/class.derived.general/p2.cpp
@@ -63,7 +63,7 @@ namespace CurrentInstantiation {
struct A0<T>::B5<U>::C3 : A0, B5 { };
template<typename T>
- struct A0<T*> { // expected-note 2{{definition of 'A0<T *>' is not complete until the closing '}'}}
+ struct A0<T*> { // expected-note 2{{definition of 'A0<type-parameter-0-0 *>' is not complete until the closing '}'}}
struct B0 : A0 { }; // expected-error {{base class has incomplete type}}
template<typename U>
diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
index 2da0382accff3..0f7653c96dcc5 100644
--- a/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
@@ -38,7 +38,7 @@ A<short>::C::B<int*> absip;
template<typename T, typename U>
struct Outer {
template<typename X, typename Y> struct Inner;
- template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous declaration of class template partial specialization 'Inner<int, Y>' is here}}
+ template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous declaration of class template partial specialization 'Inner<int, type-parameter-0-0>' is here}}
template<typename Y> struct Inner<U, Y> {}; // expected-error{{cannot be redeclared}}
};
@@ -80,7 +80,7 @@ namespace print_dependent_TemplateSpecializationType {
template <class T, class U> struct Foo {
template <unsigned long, class X, class Y> struct Bar;
template <class Y> struct Bar<0, T, Y> {};
- // expected-note-re at -1 {{previous declaration {{.*}} 'Bar<0, int, Y>' is here}}
+ // expected-note-re at -1 {{previous declaration {{.*}} 'Bar<0, int, type-parameter-0-0>' is here}}
template <class Y> struct Bar<0, U, Y> {};
// expected-error at -1 {{partial specialization 'Bar<0, int, Y>' cannot be redeclared}}
};
diff --git a/clang/test/SemaCXX/undefined-partial-specialization.cpp b/clang/test/SemaCXX/undefined-partial-specialization.cpp
index 0f776a6145fef..b07a513270fd6 100644
--- a/clang/test/SemaCXX/undefined-partial-specialization.cpp
+++ b/clang/test/SemaCXX/undefined-partial-specialization.cpp
@@ -10,6 +10,6 @@ template <typename T>
class boo<T, true>;
template<typename T>
-void boo<T, true>::foo(){} // expected-error{{out-of-line definition of 'foo' from class 'boo<T, true>' without definition}}
+void boo<T, true>::foo(){} // expected-error{{out-of-line definition of 'foo' from class 'boo<type-parameter-0-0, true>' without definition}}
}
diff --git a/clang/test/SemaTemplate/make_integer_seq.cpp b/clang/test/SemaTemplate/make_integer_seq.cpp
index cd36d1e2c8e09..7ca7b55b49964 100644
--- a/clang/test/SemaTemplate/make_integer_seq.cpp
+++ b/clang/test/SemaTemplate/make_integer_seq.cpp
@@ -73,47 +73,76 @@ using test2 = B<int, 1>;
template <template <class T, T...> class S, class T, int N> struct C {
using test3 = __make_integer_seq<S, T, N>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<template-parameter-0-0, type-parameter-0-1, N>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' dependent
-// CHECK-NEXT: |-name: '__make_integer_seq'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent alias
+// CHECK-NEXT: |-name: '__make_integer_seq' qualified
// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template 'S'
// CHECK-NEXT: | | `-TemplateTemplateParmDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:11, col:42> col:42 depth 0 index 0 S
// CHECK-NEXT: |-TemplateArgument type 'T'
// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1
// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T'
-// CHECK-NEXT: `-TemplateArgument expr 'N'
-// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:42> 'T' <Dependent>
-// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: |-TemplateArgument expr 'N'
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:42> 'T' <Dependent>
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<template-parameter-0-0, type-parameter-0-1, N>' dependent
+// CHECK-NEXT: |-name: '__make_integer_seq'
+// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __make_integer_seq
+// CHECK-NEXT: |-TemplateArgument template 'template-parameter-0-0'
+// CHECK-NEXT: | `-TemplateTemplateParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> depth 0 index 0
+// CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-1'
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1
+// CHECK-NEXT: `-TemplateArgument expr 'N'
+// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'T' <Dependent>
+// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
using test4 = __make_integer_seq<A, T, 1>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, type-parameter-0-1, 1>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' dependent
-// CHECK-NEXT: |-name: '__make_integer_seq'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent alias
+// CHECK-NEXT: |-name: '__make_integer_seq' qualified
// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template 'A'
// CHECK-NEXT: | `-ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:1, col:41> col:38 A
// CHECK-NEXT: |-TemplateArgument type 'T'
// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1
// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T'
-// CHECK-NEXT: `-TemplateArgument expr '1'
-// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:42> 'T' <Dependent>
-// CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
+// CHECK-NEXT: |-TemplateArgument expr '1'
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:42> 'T' <Dependent>
+// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, type-parameter-0-1, 1>' dependent
+// CHECK-NEXT: |-name: '__make_integer_seq'
+// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __make_integer_seq
+// CHECK-NEXT: |-TemplateArgument template 'A'
+// CHECK-NEXT: | `-ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:1, col:41> col:38 A
+// CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-1'
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1
+// CHECK-NEXT: `-TemplateArgument expr '1'
+// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:42> 'T' <Dependent>
+// CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
using test5 = __make_integer_seq<A, int, N>;
// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent
-// CHECK-NEXT: |-name: '__make_integer_seq'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent alias
+// CHECK-NEXT: |-name: '__make_integer_seq' qualified
// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template 'A'
// CHECK-NEXT: | `-ClassTemplateDecl 0x{{.+}} <line:{{.+}}:1, col:41> col:38 A
// CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
-// CHECK-NEXT: `-TemplateArgument expr 'N'
-// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: |-TemplateArgument expr 'N'
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent
+// CHECK-NEXT: |-name: '__make_integer_seq'
+// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __make_integer_seq
+// CHECK-NEXT: |-TemplateArgument template 'A'
+// CHECK-NEXT: | `-ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:1, col:41> col:38 A
+// CHECK-NEXT: |-TemplateArgument type 'int'
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: `-TemplateArgument expr 'N'
+// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
};
// expected-no-diagnostics
diff --git a/clang/test/SemaTemplate/type_pack_element.cpp b/clang/test/SemaTemplate/type_pack_element.cpp
index 264b4dcdc044d..e08a4a6ee6c5a 100644
--- a/clang/test/SemaTemplate/type_pack_element.cpp
+++ b/clang/test/SemaTemplate/type_pack_element.cpp
@@ -17,23 +17,33 @@ using test1 = __type_pack_element<0, int>;
template<int N, class ...Ts> struct A {
using test2 = __type_pack_element<N, Ts...>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, type-parameter-0-1...>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' dependent
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent alias
// CHECK-NEXT: |-name: '__type_pack_element' qualified
// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr 'N'
// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT: `-TemplateArgument type 'Ts...'
-// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
-// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
-// CHECK-NEXT: `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: |-TemplateArgument type 'Ts...'
+// CHECK-NEXT: | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, type-parameter-0-1...>' dependent
+// CHECK-NEXT: |-name: '__type_pack_element'
+// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element
+// CHECK-NEXT: |-TemplateArgument expr 'N'
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateArgument pack '<type-parameter-0-1...>'
+// CHECK-NEXT: `-TemplateArgument type 'type-parameter-0-1...'
+// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent
+// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
using test3 = __type_pack_element<0, Ts...>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, type-parameter-0-1...>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' dependent
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent alias
// CHECK-NEXT: |-name: '__type_pack_element' qualified
// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr '0'
@@ -41,22 +51,39 @@ template<int N, class ...Ts> struct A {
// CHECK-NEXT: | |-value: Int 0
// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:37> 'int' 0
-// CHECK-NEXT: `-TemplateArgument type 'Ts...'
-// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
-// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
-// CHECK-NEXT: `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: |-TemplateArgument type 'Ts...'
+// CHECK-NEXT: | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, type-parameter-0-1...>' dependent
+// CHECK-NEXT: |-name: '__type_pack_element'
+// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element
+// CHECK-NEXT: |-TemplateArgument integral '0UL'
+// CHECK-NEXT: `-TemplateArgument pack '<type-parameter-0-1...>'
+// CHECK-NEXT: `-TemplateArgument type 'type-parameter-0-1...'
+// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent
+// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
using test4 = __type_pack_element<N, int>;
// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:3, col:43> col:9 test4 '__type_pack_element<N, int>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent alias
// CHECK-NEXT: |-name: '__type_pack_element' qualified
// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr 'N'
// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT: `-TemplateArgument type 'int'
-// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: |-TemplateArgument type 'int'
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent
+// CHECK-NEXT: |-name: '__type_pack_element'
+// CHECK-NEXT: | `-BuiltinTemplateDecl {{.+}} __type_pack_element
+// CHECK-NEXT: |-TemplateArgument expr 'N'
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateArgument pack '<int>'
+// CHECK-NEXT: `-TemplateArgument type 'int'
+// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
};
// expected-no-diagnostics
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index dd6df43864481..494085a2ebca6 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -257,7 +257,7 @@ TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
const int Result = 42;
auto *ConstExpr = createBinOpExpr(LHS, RHS, Result);
// Arg is instantiated with '40 + 2'
- TemplateArgument Arg(ConstExpr, /*IsCanonical=*/false);
+ TemplateArgument Arg(ConstExpr);
// Param has default expr of '42'
auto const *Param = Params->getParam(1);
@@ -273,7 +273,7 @@ TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
auto *ConstExpr = createBinOpExpr(LHS, RHS, Result);
// Arg is instantiated with '40 + 1'
- TemplateArgument Arg(ConstExpr, /*IsCanonical=*/false);
+ TemplateArgument Arg(ConstExpr);
// Param has default expr of '42'
auto const *Param = Params->getParam(1);
@@ -289,7 +289,7 @@ TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
auto *ConstExpr = createBinOpExpr(LHS, RHS, Result);
// Arg is instantiated with '4 + 0'
- TemplateArgument Arg(ConstExpr, /*IsCanonical=*/false);
+ TemplateArgument Arg(ConstExpr);
// Param has is value-dependent expression (i.e., sizeof(T))
auto const *Param = Params->getParam(3);
More information about the cfe-commits
mailing list