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@-1 {{previous declaration {{.*}} 'Bar<0, int, Y>' is here}} + // expected-note-re@-1 {{previous declaration {{.*}} 'Bar<0, int, type-parameter-0-0>' is here}} template <class Y> struct Bar<0, U, Y> {}; // expected-error@-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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits