https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/155120
>From f31c4e385a66cf3e6c7aab499bcba7bd271902fb Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Sat, 9 Aug 2025 18:14:46 -0300 Subject: [PATCH] [clang] remove isDefaulted bit from TemplateArgument The IsDefaulted bit being part of a canonical TemplateArgument doesn't make sense, as that information is not information a canonical type should have. In C++, all template specialization types for ther same template are the same if the full list of template arguments is the same, an argument being defaulted or not doesn't matter. Moreover, this information is already available in the sugared template specialization type, in the sense that, taking the as-written list and matching it up to the template parameters, any parameters which are left without a corresponding template argument must have been defaulted. This patch besides removing that bit, changes the current DebugInfo users to derive that information from the as-written argument list. And it goes a little beyond that by wiring up the actual sugared TemplateArguments, so the Debug Info produced is also richer. This patch is a performance improvement, as the TemplateArgument is one of the hottest data structures for C++ compilation: The small regression on `-O0 -g` test is explained by the increased amount of debug info generated. --- clang/include/clang/AST/PropertiesBase.td | 52 ++---- clang/include/clang/AST/TemplateBase.h | 75 +++----- clang/lib/AST/ASTContext.cpp | 18 +- clang/lib/AST/ASTImporter.cpp | 16 +- clang/lib/AST/TemplateBase.cpp | 38 +--- clang/lib/AST/TypePrinter.cpp | 7 +- clang/lib/CodeGen/CGDebugInfo.cpp | 162 ++++++++++++------ clang/lib/CodeGen/CGDebugInfo.h | 41 +++-- clang/lib/Sema/HLSLExternalSemaSource.cpp | 3 +- clang/lib/Sema/SemaTemplate.cpp | 11 -- clang/lib/Serialization/ASTWriterDecl.cpp | 1 - .../test/DebugInfo/CXX/template-parameter.cpp | 9 +- clang/test/DebugInfo/CXX/template.cpp | 11 +- .../Generic/preferred_name-chain.cpp | 4 +- .../test/DebugInfo/Generic/preferred_name.cpp | 6 +- .../gmodules-preferred-name-typedef.cpp | 2 +- clang/test/SemaCXX/cxx14-compat.cpp | 2 +- clang/unittests/AST/ASTImporterTest.cpp | 20 --- clang/unittests/AST/DeclTest.cpp | 31 ---- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 16 +- .../DWARF/DWARFASTParserClangTests.cpp | 8 +- 21 files changed, 221 insertions(+), 312 deletions(-) diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 5b10127526e4e..f5cc1bac61671 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -785,14 +785,9 @@ let Class = PropertyTypeCase<TemplateArgument, "Null"> in { }]>; } let Class = PropertyTypeCase<TemplateArgument, "Type"> in { - def : Property<"type", QualType> { - let Read = [{ node.getAsType() }]; - } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } + def : Property<"type", QualType> { let Read = [{ node.getAsType() }]; } def : Creator<[{ - return TemplateArgument(type, /* isNullPtr */ false, isDefaulted); + return TemplateArgument(type, /* isNullPtr=*/false); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in { @@ -802,36 +797,23 @@ let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in { def : Property<"parameterType", QualType> { let Read = [{ node.getParamTypeForDecl() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(declaration, parameterType, isDefaulted); + return TemplateArgument(declaration, parameterType); }]>; } let Class = PropertyTypeCase<TemplateArgument, "NullPtr"> in { - def : Property<"type", QualType> { - let Read = [{ node.getNullPtrType() }]; - } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } + def : Property<"type", QualType> { let Read = [{ node.getNullPtrType() }]; } def : Creator<[{ - return TemplateArgument(type, /*nullptr*/ true, isDefaulted); + return TemplateArgument(type, /*IsNullPtr=*/true); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Integral"> in { def : Property<"value", APSInt> { let Read = [{ node.getAsIntegral() }]; } - def : Property<"type", QualType> { - let Read = [{ node.getIntegralType() }]; - } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } + def : Property<"type", QualType> { let Read = [{ node.getIntegralType() }]; } def : Creator<[{ - return TemplateArgument(ctx, value, type, isDefaulted); + return TemplateArgument(ctx, value, type); }]>; } let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in { @@ -841,22 +823,16 @@ let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in { def : Property<"type", QualType> { let Read = [{ node.getStructuralValueType() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(ctx, type, value, isDefaulted); + return TemplateArgument(ctx, type, value); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Template"> in { def : Property<"name", TemplateName> { let Read = [{ node.getAsTemplateOrTemplatePattern() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(name, isDefaulted); + return TemplateArgument(name); }]>; } let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in { @@ -868,11 +844,8 @@ let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in { node.getNumTemplateExpansions() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(name, numExpansions, isDefaulted); + return TemplateArgument(name, numExpansions); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Expression"> in { @@ -882,11 +855,8 @@ let Class = PropertyTypeCase<TemplateArgument, "Expression"> in { 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, IsCanonical); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Pack"> in { diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index 69481e85d87fa..46e843799e5dc 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -113,8 +113,6 @@ class TemplateArgument { struct DA { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; void *QT; ValueDecl *D; }; @@ -122,13 +120,11 @@ class TemplateArgument { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; + unsigned IsUnsigned : 1; // We store a decomposed APSInt with the data allocated by ASTContext if // BitWidth > 64. The memory may be shared between multiple // TemplateArgument instances. unsigned BitWidth : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsUnsigned : 1; union { /// Used to store the <= 64 bits integer value. uint64_t VAL; @@ -141,24 +137,18 @@ class TemplateArgument { struct V { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; APValue *Value; void *Type; }; struct A { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; unsigned NumArgs; const TemplateArgument *Args; }; struct TA { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; UnsignedOrNone NumExpansions; void *Name; }; @@ -166,8 +156,6 @@ class TemplateArgument { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; - LLVM_PREFERRED_TYPE(bool) unsigned IsCanonicalExpr : 1; uintptr_t V; }; @@ -180,38 +168,46 @@ class TemplateArgument { struct TV TypeOrValue; }; - void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted); - void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted); + void initFromType(QualType T, bool IsNullPtr) { + TypeOrValue.Kind = IsNullPtr ? NullPtr : Type; + TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + } + + void initFromDeclaration(ValueDecl *D, QualType QT) { + assert(D && "Expected decl"); + DeclArg.Kind = Declaration; + DeclArg.QT = QT.getAsOpaquePtr(); + DeclArg.D = D; + } + void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type, bool IsDefaulted); + QualType Type); void initFromStructural(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted); + const APValue &V); public: /// Construct an empty, invalid template argument. constexpr TemplateArgument() - : TypeOrValue{Null, /*IsDefaulted=*/0, /*IsCanonicalExpr=*/0, /*V=*/0} {} + : TypeOrValue{Null, /*IsCanonicalExpr=*/false, /*V=*/0} {} /// Construct a template type argument. - TemplateArgument(QualType T, bool isNullPtr = false, - bool IsDefaulted = false) { - initFromType(T, isNullPtr, IsDefaulted); + TemplateArgument(QualType T, bool isNullPtr = false) { + initFromType(T, isNullPtr); } /// Construct a template argument that refers to a (non-dependent) /// declaration. - TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) { - initFromDeclaration(D, QT, IsDefaulted); - } + TemplateArgument(ValueDecl *D, QualType QT) { initFromDeclaration(D, QT); } /// Construct an integral constant template argument. The memory to /// store the value is allocated with Ctx. TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type, bool IsDefaulted = false); + QualType Type) { + initFromIntegral(Ctx, Value, Type); + } /// Construct a template argument from an arbitrary constant value. - TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value, - bool IsDefaulted = false); + TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value); /// Construct an integral constant template argument with the same /// value as Other but a different type. @@ -228,12 +224,8 @@ class TemplateArgument { /// is taken. /// /// \param Name The template name. - /// - /// \param IsDefaulted If 'true', implies that this TemplateArgument - /// corresponds to a default template parameter - TemplateArgument(TemplateName Name, bool IsDefaulted = false) { + TemplateArgument(TemplateName Name) { TemplateArg.Kind = Template; - TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = std::nullopt; } @@ -249,13 +241,8 @@ class TemplateArgument { /// /// \param NumExpansions The number of expansions that will be generated by /// instantiating - /// - /// \param IsDefaulted If 'true', implies that this TemplateArgument - /// corresponds to a default template parameter - TemplateArgument(TemplateName Name, UnsignedOrNone NumExpansions, - bool IsDefaulted = false) { + TemplateArgument(TemplateName Name, UnsignedOrNone NumExpansions) { TemplateArg.Kind = TemplateExpansion; - TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = NumExpansions; } @@ -265,9 +252,8 @@ 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) { + TemplateArgument(Expr *E, bool IsCanonical) { TypeOrValue.Kind = Expression; - TypeOrValue.IsDefaulted = IsDefaulted; TypeOrValue.IsCanonicalExpr = IsCanonical; TypeOrValue.V = reinterpret_cast<uintptr_t>(E); } @@ -278,7 +264,6 @@ class TemplateArgument { /// outlives the TemplateArgument itself. explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { this->Args.Kind = Pack; - this->Args.IsDefaulted = false; this->Args.Args = Args.data(); this->Args.NumArgs = Args.size(); } @@ -387,14 +372,6 @@ class TemplateArgument { Integer.Type = T.getAsOpaquePtr(); } - /// Set to 'true' if this TemplateArgument corresponds to a - /// default template parameter. - void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; } - - /// If returns 'true', this TemplateArgument corresponds to a - /// default template parameter. - bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } - /// Get the value of a StructuralValue. const APValue &getAsStructuralValue() const { return *Value.Value; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index bbb957067c4c8..2f33ea8ecc114 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7945,27 +7945,24 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { return Arg; case TemplateArgument::Expression: - return TemplateArgument(Arg.getAsExpr(), /*IsCanonical=*/true, - Arg.getIsDefaulted()); + return TemplateArgument(Arg.getAsExpr(), /*IsCanonical=*/true); case TemplateArgument::Declaration: { auto *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl()); - return TemplateArgument(D, getCanonicalType(Arg.getParamTypeForDecl()), - Arg.getIsDefaulted()); + return TemplateArgument(D, getCanonicalType(Arg.getParamTypeForDecl())); } case TemplateArgument::NullPtr: return TemplateArgument(getCanonicalType(Arg.getNullPtrType()), - /*isNullPtr*/ true, Arg.getIsDefaulted()); + /*isNullPtr=*/true); case TemplateArgument::Template: - return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()), - Arg.getIsDefaulted()); + return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); case TemplateArgument::TemplateExpansion: return TemplateArgument( getCanonicalTemplateName(Arg.getAsTemplateOrTemplatePattern()), - Arg.getNumTemplateExpansions(), Arg.getIsDefaulted()); + Arg.getNumTemplateExpansions()); case TemplateArgument::Integral: return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType())); @@ -7973,11 +7970,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::StructuralValue: return TemplateArgument(*this, getCanonicalType(Arg.getStructuralValueType()), - Arg.getAsStructuralValue(), Arg.getIsDefaulted()); + Arg.getAsStructuralValue()); case TemplateArgument::Type: return TemplateArgument(getCanonicalType(Arg.getAsType()), - /*isNullPtr*/ false, Arg.getIsDefaulted()); + /*isNullPtr=*/false); case TemplateArgument::Pack: { bool AnyNonCanonArgs = false; @@ -7987,7 +7984,6 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { return Arg; auto NewArg = TemplateArgument::CreatePackCopy( const_cast<ASTContext &>(*this), CanonArgs); - NewArg.setIsDefaulted(Arg.getIsDefaulted()); return NewArg; } } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 6299efaf6bbfc..617aff459daeb 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -848,8 +848,7 @@ ASTNodeImporter::import(const TemplateArgument &From) { ExpectedType ToTypeOrErr = import(From.getAsType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ false, - From.getIsDefaulted()); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr=*/false); } case TemplateArgument::Integral: { @@ -867,15 +866,14 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTypeOrErr) return ToTypeOrErr.takeError(); return TemplateArgument(dyn_cast<ValueDecl>((*ToOrErr)->getCanonicalDecl()), - *ToTypeOrErr, From.getIsDefaulted()); + *ToTypeOrErr); } case TemplateArgument::NullPtr: { ExpectedType ToTypeOrErr = import(From.getNullPtrType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ true, - From.getIsDefaulted()); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr=*/true); } case TemplateArgument::StructuralValue: { @@ -894,7 +892,7 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument(*ToTemplateOrErr, From.getIsDefaulted()); + return TemplateArgument(*ToTemplateOrErr); } case TemplateArgument::TemplateExpansion: { @@ -903,14 +901,12 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions(), - From.getIsDefaulted()); + return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions()); } case TemplateArgument::Expression: if (ExpectedExpr ToExpr = import(From.getAsExpr())) - return TemplateArgument(*ToExpr, From.isCanonicalExpr(), - From.getIsDefaulted()); + return TemplateArgument(*ToExpr, From.isCanonicalExpr()); else return ToExpr.takeError(); diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 76050ceeb35a7..6ab364aa008db 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -157,27 +157,10 @@ static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) { // TemplateArgument Implementation //===----------------------------------------------------------------------===// -void TemplateArgument::initFromType(QualType T, bool IsNullPtr, - bool IsDefaulted) { - TypeOrValue.Kind = IsNullPtr ? NullPtr : Type; - TypeOrValue.IsDefaulted = IsDefaulted; - TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); -} - -void TemplateArgument::initFromDeclaration(ValueDecl *D, QualType QT, - bool IsDefaulted) { - assert(D && "Expected decl"); - DeclArg.Kind = Declaration; - DeclArg.IsDefaulted = IsDefaulted; - DeclArg.QT = QT.getAsOpaquePtr(); - DeclArg.D = D; -} - void TemplateArgument::initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type, bool IsDefaulted) { + QualType Type) { Integer.Kind = Integral; - Integer.IsDefaulted = IsDefaulted; // Copy the APSInt value into our decomposed form. Integer.BitWidth = Value.getBitWidth(); Integer.IsUnsigned = Value.isUnsigned(); @@ -195,20 +178,13 @@ void TemplateArgument::initFromIntegral(const ASTContext &Ctx, } void TemplateArgument::initFromStructural(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted) { + const APValue &V) { Value.Kind = StructuralValue; - Value.IsDefaulted = IsDefaulted; Value.Value = new (Ctx) APValue(V); Ctx.addDestruction(Value.Value); Value.Type = Type.getAsOpaquePtr(); } -TemplateArgument::TemplateArgument(const ASTContext &Ctx, - const llvm::APSInt &Value, QualType Type, - bool IsDefaulted) { - initFromIntegral(Ctx, Value, Type, IsDefaulted); -} - static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx, QualType T, const APValue &V) { // Pointers to members are relatively easy. @@ -236,17 +212,17 @@ static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx, } TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted) { + const APValue &V) { if (Type->isIntegralOrEnumerationType() && V.isInt()) - initFromIntegral(Ctx, V.getInt(), Type, IsDefaulted); + initFromIntegral(Ctx, V.getInt(), Type); else if ((V.isLValue() && V.isNullPointer()) || (V.isMemberPointer() && !V.getMemberPointerDecl())) - initFromType(Type, /*isNullPtr=*/true, IsDefaulted); + initFromType(Type, /*IsNullPtr=*/true); else if (const ValueDecl *VD = getAsSimpleValueDeclRef(Ctx, Type, V)) // FIXME: The Declaration form should expose a const ValueDecl*. - initFromDeclaration(const_cast<ValueDecl *>(VD), Type, IsDefaulted); + initFromDeclaration(const_cast<ValueDecl *>(VD), Type); else - initFromStructural(Ctx, Type, V, IsDefaulted); + initFromStructural(Ctx, Type, V); } TemplateArgument diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 52ff0d5b5771b..1402feaa07c13 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1413,6 +1413,7 @@ void TypePrinter::printDeducedTemplateSpecializationBefore( Name.print(OS, Policy); } if (DeducedTD) { + DefaultTemplateArgsPolicyRAII _1(Policy); printTemplateArgumentList(OS, Args, Policy, DeducedTD->getTemplateParameters()); } @@ -2547,7 +2548,11 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy, llvm::SmallVector<TemplateArgument, 8> OrigArgs; for (const TA &A : Args) OrigArgs.push_back(getArgument(A)); - while (!Args.empty() && getArgument(Args.back()).getIsDefaulted()) + ASTContext &Ctx = TPL->getParam(0)->getASTContext(); + while (!Args.empty() && + isSubstitutedDefaultArgument(Ctx, getArgument(Args.back()), + TPL->getParam(Args.size() - 1), + OrigArgs, TPL->getDepth())) Args = Args.drop_back(); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index c44fea3e6383d..e46a2eecd42df 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1318,9 +1318,10 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { return Tag; } -llvm::DICompositeType * -CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, - llvm::DIScope *Ctx) { +llvm::DICompositeType *CGDebugInfo::getOrCreateRecordFwdDecl( + const RecordType *Ty, llvm::DIScope *Ctx, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); if (llvm::DIType *T = getTypeOrNull(QualType(Ty, 0))) return cast<llvm::DICompositeType>(T); @@ -1354,12 +1355,19 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, Flags, Identifier); - if (CGM.getCodeGenOpts().DebugFwdTemplateParams) - if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - DBuilder.replaceArrays(RetTy, llvm::DINodeArray(), - CollectCXXTemplateParams(TSpecial, DefUnit)); + if (CGM.getCodeGenOpts().DebugFwdTemplateParams) { + if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + DBuilder.replaceArrays( + RetTy, llvm::DINodeArray(), + CollectTemplateParams(GetTemplateArgs(TSpecial, AsWrittenArgsOrNone), + DefUnit)); + } else { + assert(!AsWrittenArgsOrNone); + } + } + ReplaceMap.emplace_back( - std::piecewise_construct, std::make_tuple(Ty), + std::piecewise_construct, std::make_tuple(OrigTy), std::make_tuple(static_cast<llvm::Metadata *>(RetTy))); return RetTy; } @@ -1536,7 +1544,10 @@ GetTemplateArgs(const TemplateDecl *TD, const TemplateSpecializationType *Ty) { llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, llvm::DIFile *Unit) { - assert(Ty->isTypeAlias()); + if (!Ty->isTypeAlias()) + return CreateType(cast<RecordType>(Ty->desugar()), Ty->template_arguments(), + Ty); + llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit); const TemplateDecl *TD = Ty->getTemplateName().getAsTemplateDecl(); @@ -1557,7 +1568,6 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, if (CGM.getCodeGenOpts().DebugTemplateAlias) { auto ArgVector = ::GetTemplateArgs(TD, Ty); - TemplateArgs Args = {TD->getTemplateParameters(), ArgVector}; // FIXME: Respect DebugTemplateNameKind::Mangled, e.g. by using GetName. // Note we can't use GetName without additional work: TypeAliasTemplateDecl @@ -1569,8 +1579,12 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, TD->getNameForDiagnostic(OS, PP, /*Qualified=*/false); if (CGM.getCodeGenOpts().getDebugSimpleTemplateNames() != llvm::codegenoptions::DebugTemplateNamesKind::Simple || - !HasReconstitutableArgs(Args.Args)) - printTemplateArgumentList(OS, Args.Args, PP); + !HasReconstitutableArgs(ArgVector)) + printTemplateArgumentList(OS, ArgVector, PP); + + TemplateArgs Args = {TD->getTemplateParameters(), + /*AsWrittenArgs=*/ArgVector, + /*ConvertedArgs=*/{}}; llvm::DIDerivedType *AliasTy = DBuilder.createTemplateAlias( Src, Name, getOrCreateFile(Loc), getLineNumber(Loc), @@ -2403,14 +2417,31 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs, llvm::DIFile *Unit) { if (!OArgs) return llvm::DINodeArray(); - TemplateArgs &Args = *OArgs; + auto [TList, AsWrittenArgs, ConvertedArgs] = *OArgs; + + SmallVector<TemplateArgument> UnpackedArgs; + if (!ConvertedArgs.empty() && + ConvertedArgs.back().getKind() == TemplateArgument::Pack) { + UnpackedArgs.resize(ConvertedArgs.size()); + unsigned NumPackedArgs = + int32_t(AsWrittenArgs.size()) - int32_t(ConvertedArgs.size() - 1); + assert(NumPackedArgs >= 0); + llvm::copy(AsWrittenArgs.drop_back(NumPackedArgs), UnpackedArgs.data()); + UnpackedArgs.back() = TemplateArgument::CreatePackCopy( + CGM.getContext(), AsWrittenArgs.take_back(NumPackedArgs)); + AsWrittenArgs = UnpackedArgs; + } + SmallVector<llvm::Metadata *, 16> TemplateParams; - for (unsigned i = 0, e = Args.Args.size(); i != e; ++i) { - const TemplateArgument &TA = Args.Args[i]; - StringRef Name; - const bool defaultParameter = TA.getIsDefaulted(); - if (Args.TList) - Name = Args.TList->getParam(i)->getName(); + for (unsigned i = 0, e = ConvertedArgs.empty() ? AsWrittenArgs.size() + : ConvertedArgs.size(); + i != e; ++i) { + auto [TA, defaultParameter] = i < AsWrittenArgs.size() + ? std::make_tuple(AsWrittenArgs[i], false) + : std::make_tuple(ConvertedArgs[i], true); + StringRef Name = + TList ? TList->getParam(std::min(i, TList->size() - 1))->getName() + : StringRef(); switch (TA.getKind()) { case TemplateArgument::Type: { @@ -2510,7 +2541,10 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs, case TemplateArgument::Pack: TemplateParams.push_back(DBuilder.createTemplateParameterPack( TheCU, Name, nullptr, - CollectTemplateParams({{nullptr, TA.getPackAsArray()}}, Unit))); + CollectTemplateParams( + {{nullptr, /*AsWrittenArgs=*/TA.getPackAsArray(), + /*ConvertedArgs=*/{}}}, + Unit))); break; case TemplateArgument::Expression: { const Expr *E = TA.getAsExpr(); @@ -2540,7 +2574,9 @@ CGDebugInfo::GetTemplateArgs(const FunctionDecl *FD) const { const TemplateParameterList *TList = FD->getTemplateSpecializationInfo() ->getTemplate() ->getTemplateParameters(); - return {{TList, FD->getTemplateSpecializationArgs()->asArray()}}; + return {{TList, + /*AsWrittenArgs=*/FD->getTemplateSpecializationArgs()->asArray(), + /*ConvertedArgs=*/{}}}; } return std::nullopt; } @@ -2555,10 +2591,11 @@ CGDebugInfo::GetTemplateArgs(const VarDecl *VD) const { VarTemplateDecl *T = TS->getSpecializedTemplate(); const TemplateParameterList *TList = T->getTemplateParameters(); auto TA = TS->getTemplateArgs().asArray(); - return {{TList, TA}}; + return {{TList, TA, /*ConvertedArgs=*/{}}}; } -std::optional<CGDebugInfo::TemplateArgs> -CGDebugInfo::GetTemplateArgs(const RecordDecl *RD) const { +std::optional<CGDebugInfo::TemplateArgs> CGDebugInfo::GetTemplateArgs( + const RecordDecl *RD, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone) const { if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { // Always get the full list of parameters, not just the ones from the // specialization. A partial specialization may have fewer parameters than @@ -2566,7 +2603,12 @@ CGDebugInfo::GetTemplateArgs(const RecordDecl *RD) const { TemplateParameterList *TPList = TSpecial->getSpecializedTemplate()->getTemplateParameters(); const TemplateArgumentList &TAList = TSpecial->getTemplateArgs(); - return {{TPList, TAList.asArray()}}; + return {{TPList, + /*AsWrittenArgs=*/ + AsWrittenArgsOrNone ? *AsWrittenArgsOrNone : TAList.asArray(), + /*ConvertedArgs=*/ + AsWrittenArgsOrNone ? TAList.asArray() + : ArrayRef<TemplateArgument>()}}; } return std::nullopt; } @@ -2582,11 +2624,6 @@ llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL, return CollectTemplateParams(GetTemplateArgs(VL), Unit); } -llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD, - llvm::DIFile *Unit) { - return CollectTemplateParams(GetTemplateArgs(RD), Unit); -} - llvm::DINodeArray CGDebugInfo::CollectBTFDeclTagAnnotations(const Decl *D) { if (!D->hasAttr<BTFDeclTagAttr>()) return nullptr; @@ -2913,7 +2950,9 @@ void CGDebugInfo::completeClass(const RecordDecl *RD) { // We want the canonical definition of the structure to not // be the typedef. Since that would lead to circular typedef // metadata. - auto [Res, PrefRes] = CreateTypeDefinition(dyn_cast<RecordType>(Ty)); + auto [Res, PrefRes] = CreateTypeDefinition( + dyn_cast<RecordType>(Ty), /*AsWrittenArgsOrNone=*/std::nullopt, + /*OrigTy=*/Ty->getTypePtr()); assert(!Res->isForwardDecl()); TypeCache[TyPtr].reset(Res); } @@ -3023,17 +3062,21 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { completeClassData(RD); } -llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { +llvm::DIType *CGDebugInfo::CreateType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0))); if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) { if (!T) - T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD)); + T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD), + AsWrittenArgsOrNone, OrigTy); return T; } - auto [Def, Pref] = CreateTypeDefinition(Ty); + auto [Def, Pref] = CreateTypeDefinition(Ty, AsWrittenArgsOrNone, OrigTy); return Pref ? Pref : Def; } @@ -3050,8 +3093,10 @@ llvm::DIType *CGDebugInfo::GetPreferredNameType(const CXXRecordDecl *RD, return getOrCreateType(PNA->getTypedefType(), Unit); } -std::pair<llvm::DIType *, llvm::DIType *> -CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { +std::pair<llvm::DIType *, llvm::DIType *> CGDebugInfo::CreateTypeDefinition( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. @@ -3063,7 +3108,8 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // its members. Finally, we create a descriptor for the complete type (which // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. - llvm::DICompositeType *FwdDecl = getOrCreateLimitedType(Ty); + llvm::DICompositeType *FwdDecl = + getOrCreateLimitedType(Ty, AsWrittenArgsOrNone, OrigTy); const RecordDecl *D = RD->getDefinition(); if (!D || !D->isCompleteDefinition()) @@ -3822,11 +3868,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { return C.getQualifiedType(T->getCanonicalTypeUnqualified().getTypePtr(), Quals); case Type::TemplateSpecialization: { - const auto *Spec = cast<TemplateSpecializationType>(T); - if (Spec->isTypeAlias()) - return C.getQualifiedType(T.getTypePtr(), Quals); - T = Spec->desugar(); - break; + return C.getQualifiedType(T.getTypePtr(), Quals); } case Type::TypeOfExpr: T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType(); @@ -4012,7 +4054,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit); case Type::Record: - return CreateType(cast<RecordType>(Ty)); + return CreateType(cast<RecordType>(Ty), + /*AsWrittenArgsOrNone=*/std::nullopt, + /*OrigTy=*/Ty.getTypePtr()); case Type::Enum: return CreateEnumType(cast<EnumType>(Ty)); case Type::FunctionProto: @@ -4070,8 +4114,10 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { llvm_unreachable("type should have been unwrapped!"); } -llvm::DICompositeType * -CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { +llvm::DICompositeType *CGDebugInfo::getOrCreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { QualType QTy(Ty, 0); auto *T = cast_or_null<llvm::DICompositeType>(getTypeOrNull(QTy)); @@ -4083,7 +4129,8 @@ CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { return T; // Otherwise create the type. - llvm::DICompositeType *Res = CreateLimitedType(Ty); + llvm::DICompositeType *Res = + CreateLimitedType(Ty, AsWrittenArgsOrNone, OrigTy); // Propagate members from the declaration to the definition // CreateType(const RecordType*) will overwrite this with the members in the @@ -4096,7 +4143,10 @@ CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { } // TODO: Currently used for context chains when limiting debug info. -llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { +llvm::DICompositeType *CGDebugInfo::CreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. @@ -4122,7 +4172,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { // appropriately marked node and just return it. const RecordDecl *D = RD->getDefinition(); if (!D || !D->isCompleteDefinition()) - return getOrCreateRecordFwdDecl(Ty, RDContext); + return getOrCreateRecordFwdDecl(Ty, RDContext, AsWrittenArgsOrNone, OrigTy); uint64_t Size = CGM.getContext().getTypeSize(Ty); // __attribute__((aligned)) can increase or decrease alignment *except* on a @@ -4195,8 +4245,10 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl); if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(), - CollectCXXTemplateParams(TSpecial, DefUnit)); + DBuilder.replaceArrays( + RealDecl, llvm::DINodeArray(), + CollectTemplateParams(GetTemplateArgs(TSpecial, AsWrittenArgsOrNone), + DefUnit)); return RealDecl; } @@ -5819,7 +5871,7 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { bool IsOperatorOverload = false; // isa<CXXConversionDecl>(ND); if (auto *RD = dyn_cast<CXXRecordDecl>(ND)) { - Args = GetTemplateArgs(RD); + Args = GetTemplateArgs(RD, /*AsWrittenArgsOrNone=*/std::nullopt); } else if (auto *FD = dyn_cast<FunctionDecl>(ND)) { Args = GetTemplateArgs(FD); auto NameKind = ND->getDeclName().getNameKind(); @@ -5851,8 +5903,8 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { // Other operator overloads that aren't conversion operators could be // reconstituted but would require a bit more nuance about detecting the // difference between these different operators during that rebuilding. - bool Reconstitutable = - Args && HasReconstitutableArgs(Args->Args) && !IsOperatorOverload; + bool Reconstitutable = Args && HasReconstitutableArgs(Args->AsWrittenArgs) && + !IsOperatorOverload; PrintingPolicy PP = getPrintingPolicy(); @@ -5873,8 +5925,8 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { if (Mangled) { OS << "|"; - printTemplateArgumentList(OS, Args->Args, PP); - printTemplateArgumentList(EncodedOriginalNameOS, Args->Args, PP); + printTemplateArgumentList(OS, Args->AsWrittenArgs, PP); + printTemplateArgumentList(EncodedOriginalNameOS, Args->AsWrittenArgs, PP); #ifndef NDEBUG std::string CanonicalOriginalName; llvm::raw_string_ostream OriginalOS(CanonicalOriginalName); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index ff9c3cd2d1136..e7f31803df0b2 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -140,7 +140,7 @@ class CGDebugInfo { std::vector<void *> RetainedTypes; /// Cache of forward declared types to RAUW at the end of compilation. - std::vector<std::pair<const TagType *, llvm::TrackingMDRef>> ReplaceMap; + std::vector<std::pair<const Type *, llvm::TrackingMDRef>> ReplaceMap; /// Cache of replaceable forward declarations (functions and /// variables) to RAUW at the end of compilation. @@ -212,7 +212,10 @@ class CGDebugInfo { llvm::DIFile *F); llvm::DIType *CreateType(const HLSLInlineSpirvType *Ty, llvm::DIFile *F); /// Get structure or union type. - llvm::DIType *CreateType(const RecordType *Tyg); + llvm::DIType * + CreateType(const RecordType *Tyg, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); /// Create definition for the specified 'Ty'. /// @@ -220,9 +223,14 @@ class CGDebugInfo { /// of the 'Ty'. The second is the type specified by the preferred_name /// attribute on 'Ty', which can be a nullptr if no such attribute /// exists. - std::pair<llvm::DIType *, llvm::DIType *> - CreateTypeDefinition(const RecordType *Ty); - llvm::DICompositeType *CreateLimitedType(const RecordType *Ty); + std::pair<llvm::DIType *, llvm::DIType *> CreateTypeDefinition( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); + llvm::DICompositeType *CreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType *CT); /// Get Objective-C interface type. @@ -318,7 +326,8 @@ class CGDebugInfo { struct TemplateArgs { const TemplateParameterList *TList; - llvm::ArrayRef<TemplateArgument> Args; + llvm::ArrayRef<TemplateArgument> AsWrittenArgs; + llvm::ArrayRef<TemplateArgument> ConvertedArgs; }; /// A helper function to collect template parameters. llvm::DINodeArray CollectTemplateParams(std::optional<TemplateArgs> Args, @@ -334,14 +343,11 @@ class CGDebugInfo { llvm::DIFile *Unit); std::optional<TemplateArgs> GetTemplateArgs(const VarDecl *) const; - std::optional<TemplateArgs> GetTemplateArgs(const RecordDecl *) const; + std::optional<TemplateArgs> + GetTemplateArgs(const RecordDecl *, + std::optional<ArrayRef<TemplateArgument>>) const; std::optional<TemplateArgs> GetTemplateArgs(const FunctionDecl *) const; - /// A helper function to collect debug info for template - /// parameters. - llvm::DINodeArray CollectCXXTemplateParams(const RecordDecl *TS, - llvm::DIFile *F); - /// A helper function to collect debug info for btf_decl_tag annotations. llvm::DINodeArray CollectBTFDeclTagAnnotations(const Decl *D); @@ -724,8 +730,10 @@ class CGDebugInfo { llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl); /// Create a forward decl for a RecordType in a given context. - llvm::DICompositeType *getOrCreateRecordFwdDecl(const RecordType *, - llvm::DIScope *); + llvm::DICompositeType * + getOrCreateRecordFwdDecl(const RecordType *, llvm::DIScope *, + std::optional<ArrayRef<TemplateArgument>>, + const Type *OrigTy); /// Return current directory name. StringRef getCurrentDirname(); @@ -763,7 +771,10 @@ class CGDebugInfo { /// Get the type from the cache or create a new partial type if /// necessary. - llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty); + llvm::DICompositeType *getOrCreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); /// Create type metadata for a source language type. llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg); diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 726581d131623..2277435ad5ec2 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -85,8 +85,7 @@ void HLSLExternalSemaSource::defineHLSLVectorAlias() { &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy, false, AST.getTrivialTypeSourceInfo(AST.IntTy)); llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4); - TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy, - /*IsDefaulted=*/true); + TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy); SizeParam->setDefaultArgument( AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy, SourceLocation(), SizeParam)); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 36bffc5e5e3c9..26563a7c9eafa 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5914,10 +5914,6 @@ bool Sema::CheckTemplateArgumentList( CTAK_Specified)) return true; Arg = NewArgLoc.getArgument(); - CTAI.CanonicalConverted.back().setIsDefaulted( - clang::isSubstitutedDefaultArgument(Context, Arg, *Param, - CTAI.CanonicalConverted, - Params->getDepth())); } ArgLoc = TemplateArgumentLoc(TemplateArgument::CreatePackCopy(Context, Args), @@ -5928,10 +5924,6 @@ bool Sema::CheckTemplateArgumentList( RAngleLoc, SugaredArgumentPack.size(), CTAI, CTAK_Specified)) return true; - CTAI.CanonicalConverted.back().setIsDefaulted( - clang::isSubstitutedDefaultArgument(Context, ArgLoc.getArgument(), - *Param, CTAI.CanonicalConverted, - Params->getDepth())); if (ArgIsExpansion && NonPackParameter) { // CWG1430/CWG2686: we have a pack expansion as an argument to an // alias template or concept, and it's not part of a parameter pack. @@ -6078,9 +6070,6 @@ bool Sema::CheckTemplateArgumentList( CTAI, CTAK_Specified)) return true; - CTAI.SugaredConverted.back().setIsDefaulted(true); - CTAI.CanonicalConverted.back().setIsDefaulted(true); - // Core issue 150 (assumed resolution): if this is a template template // parameter, keep track of the default template arguments from the // template definition. diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ec3dda1fcdf48..2e2c66b6eb74f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2403,7 +2403,6 @@ getFunctionDeclAbbrev(serialization::DeclCode Code) { Abv->Add(BitCodeAbbrevOp(TemplateArgument::Type)); // Template Argument Kind Abv->Add( BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template Argument Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is Defaulted Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(0)); diff --git a/clang/test/DebugInfo/CXX/template-parameter.cpp b/clang/test/DebugInfo/CXX/template-parameter.cpp index b2ca54a02f1c9..fdcf29037b291 100644 --- a/clang/test/DebugInfo/CXX/template-parameter.cpp +++ b/clang/test/DebugInfo/CXX/template-parameter.cpp @@ -4,15 +4,14 @@ // RUN: %clang_cc1 -emit-llvm %std_cxx11-14 -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,PRE17 // RUN: %clang_cc1 -emit-llvm %std_cxx17- -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,CXX17 // RUN: %clang_cc1 -emit-llvm %std_cxx17- -dwarf-version=4 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,CXX17 -// RUN: %clang_cc1 -emit-llvm %std_cxx20- -dwarf-version=5 -DCXX20=1 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefix=CHECK-CXX20 +// RUN: %clang_cc1 -emit-llvm %std_cxx20- -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK-CXX20 // CHECK: DILocalVariable(name: "f1", {{.*}}, type: ![[TEMPLATE_TYPE:[0-9]+]] // CHECK: [[TEMPLATE_TYPE]] = {{.*}}!DICompositeType({{.*}}, templateParams: ![[F1_TYPE:[0-9]+]] // CHECK: [[F1_TYPE]] = !{![[FIRST:[0-9]+]], ![[SECOND:[0-9]+]], ![[THIRD:[0-9]+]], ![[FORTH:[0-9]+]], ![[FIFTH:[0-9]+]]} // CHECK: [[FIRST]] = !DITemplateTypeParameter(name: "T", type: !{{[0-9]*}}) // CHECK: [[SECOND]] = !DITemplateValueParameter(name: "i", type: !{{[0-9]*}}, value: i32 6) -// PRE17: [[THIRD]] = !DITemplateValueParameter(name: "b", type: !{{[0-9]*}}, value: i8 0) -// CXX17: [[THIRD]] = !DITemplateValueParameter(name: "b", type: !{{[0-9]*}}, value: i1 false) +// CHECK: [[THIRD]] = !DITemplateValueParameter(name: "b", type: !{{[0-9]*}}, value: i1 false) // CHECK: [[FIFTH]] = !DITemplateTypeParameter(name: "d", type: !{{[0-9]*}}) // CHECK: DILocalVariable(name: "f2", {{.*}}, type: ![[TEMPLATE_TYPE:[0-9]+]] @@ -51,7 +50,7 @@ template <template <typename T> class CT = bar> class baz { }; -#ifdef CXX20 +#if __cplusplus >= 202002L struct non_empty { int mem; int mem2; } ne; template<float f = -1.5f, double d = 5.2, int * p = &ne.mem2> @@ -72,7 +71,7 @@ nttp<> n1; // CHECK-CXX20-SAME: defaulted: true // CHECK-CXX20-SAME: value: ptr getelementptr (i8, ptr @ne, i64 4) -#endif // CXX20 +#endif // C++20 int main() { foo<int, 6, false, 3, double> f1; diff --git a/clang/test/DebugInfo/CXX/template.cpp b/clang/test/DebugInfo/CXX/template.cpp index a5a17c932604c..5b2599232a02d 100644 --- a/clang/test/DebugInfo/CXX/template.cpp +++ b/clang/test/DebugInfo/CXX/template.cpp @@ -95,14 +95,15 @@ TC <int, // CHECK: [[TCNARG2]] = !DITemplateValueParameter(type: [[INT]], value: i32 -3) -3, -// CHECK: [[TCNARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR]], value: i8 0) +// CHECK: [[TCNARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR]], value: ptr null) nullptr, // The interesting null pointer: -1 for member data pointers (since they are // just an offset in an object, they can be zero and non-null for the first // member) -// CHECK: [[TCNARG4]] = !DITemplateValueParameter(name: "a", type: [[MEMINTPTR]], value: i64 -1) +// CHECK: [[TCNARG4]] = !DITemplateValueParameter(name: "a", type: [[FOO_MEM:![0-9]*]], value: i64 -1) +// CHECK: [[FOO_MEM]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo_mem", {{.*}}baseType: [[MEMINTPTR]]) nullptr, // // In some future iteration we could possibly emit the value of a null member @@ -110,9 +111,9 @@ TC // naturally from the LLVM CodeGen side once we decide how to handle non-null // member function pointers. For now, it's simpler just to emit the 'i8 0'. // -// CHECK: [[TCNARG5]] = !DITemplateValueParameter(name: "b", type: [[MEMFUNPTR]], value: i8 0) +// CHECK: [[TCNARG5]] = !DITemplateValueParameter(name: "b", type: [[MEMFUNPTR]], value: { i64, i64 } zeroinitializer) nullptr, -// CHECK: [[TCNARG6]] = !DITemplateValueParameter(name: "f", type: [[FUNPTR]], value: i8 0) +// CHECK: [[TCNARG6]] = !DITemplateValueParameter(name: "f", type: [[FUNPTR]], value: ptr null) nullptr // CHECK: [[TCNARG7]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Is", value: [[EMPTY]]) > tcn; @@ -221,7 +222,7 @@ struct t1; // use this to ensure the type parameter doesn't shift due to other t template<typename T1, typename T2, typename T3, typename T4> void f1() { } template void f1<t1 () volatile, t1 () const volatile, t1 () &, t1 () &&>(); -// CHECK: !DISubprogram(name: "f1<RawFuncQual::t1 () volatile, RawFuncQual::t1 () const volatile, RawFuncQual::t1 () &, RawFuncQual::t1 () &&>", +// CHECK: !DISubprogram(name: "f1<RawFuncQual::t1 () volatile, RawFuncQual::t1 () const volatile, RawFuncQual::t1 () &, RawFuncQual::t1 () &&>", // CHECK-SAME: templateParams: ![[RAW_FUNC_QUAL_ARGS:[0-9]*]] // CHECK: ![[RAW_FUNC_QUAL_ARGS]] = !{![[RAW_FUNC_QUAL_T1:[0-9]*]], ![[RAW_FUNC_QUAL_T2:[0-9]*]], ![[RAW_FUNC_QUAL_T3:[0-9]*]], ![[RAW_FUNC_QUAL_T4:[0-9]*]]} diff --git a/clang/test/DebugInfo/Generic/preferred_name-chain.cpp b/clang/test/DebugInfo/Generic/preferred_name-chain.cpp index 3108caef02dd7..3cbd58d84ad8b 100644 --- a/clang/test/DebugInfo/Generic/preferred_name-chain.cpp +++ b/clang/test/DebugInfo/Generic/preferred_name-chain.cpp @@ -48,7 +48,7 @@ int main() { // COMMON-SAME: templateParams: ![[PARAM:[0-9]+]] // COMMON: ![[PARAM]] = !{![[TEMPL_TYPE_PARAM:[0-9]+]]} // GDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) -// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) +// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[FOO_INT]]) Foo<Foo<char>> varFooChar; @@ -57,7 +57,7 @@ int main() { // COMMON-SAME: templateParams: ![[CHAR_PARAM:[0-9]+]] // COMMON: ![[CHAR_PARAM]] = !{![[CHAR_TEMPL_TYPE_PARAM:[0-9]+]]} // GDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_CHAR_TY]]) -// LLDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_CHAR_TY]]) +// LLDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[FOO_CHAR]]) return 0; } diff --git a/clang/test/DebugInfo/Generic/preferred_name.cpp b/clang/test/DebugInfo/Generic/preferred_name.cpp index 9b3f532faf978..28a4fe6e4524b 100644 --- a/clang/test/DebugInfo/Generic/preferred_name.cpp +++ b/clang/test/DebugInfo/Generic/preferred_name.cpp @@ -53,7 +53,7 @@ int main() { // COMMON-SAME: templateParams: ![[PARAM:[0-9]+]] // COMMON: ![[PARAM]] = !{![[TEMPL_TYPE_PARAM:[0-9]+]]} // GDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) -// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) +// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_BASE]]) BarInt barInt; @@ -75,14 +75,10 @@ int main() { Bar<char> barChar; -// LLDB: ![[BAR_SHORT_TY_2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar<short>", file: ![[#]], line: [[#]], baseType: ![[BAR_SHORT_TY]]) - // LLDB: !DILocalVariable(name: "barChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TY_2:[0-9]+]]) // GDB: !DILocalVariable(name: "barChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TYPEDEF:[0-9]+]]) // GDB: ![[BAR_CHAR_TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar<char>" -// LLDB: ![[BAR_CHAR_TY_2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar<char>", file: ![[#]], line: [[#]], baseType: ![[BAR_CHAR_TY]]) - return 0; } diff --git a/clang/test/Modules/gmodules-preferred-name-typedef.cpp b/clang/test/Modules/gmodules-preferred-name-typedef.cpp index 1d2bbd75fe866..cbd186f9cf268 100644 --- a/clang/test/Modules/gmodules-preferred-name-typedef.cpp +++ b/clang/test/Modules/gmodules-preferred-name-typedef.cpp @@ -12,4 +12,4 @@ #include "gmodules-preferred-name-typedef.h" // CHECK: ![[#]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[PREF_BASE:[0-9]+]]) -// CHECK: ![[PREF_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo<char>" +// CHECK: ![[PREF_BASE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo<char>" diff --git a/clang/test/SemaCXX/cxx14-compat.cpp b/clang/test/SemaCXX/cxx14-compat.cpp index d6396a7de4df7..9492d92affe5c 100644 --- a/clang/test/SemaCXX/cxx14-compat.cpp +++ b/clang/test/SemaCXX/cxx14-compat.cpp @@ -16,7 +16,7 @@ namespace [[]] NS_with_attr {} // expected-warning {{incompatible with C++ stand enum { e [[]] }; // expected-warning {{incompatible with C++ standards before C++17}} template<typename T = int> struct X {}; -X x; // expected-warning {{class template argument deduction is incompatible with C++ standards before C++17; for compatibility, use explicit type name 'X<>'}} +X x; // expected-warning {{class template argument deduction is incompatible with C++ standards before C++17; for compatibility, use explicit type name 'X<int>' (aka 'X<>')}} template<template<typename> class> struct Y {}; Y<X> yx; // ok, not class template argument deduction diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 15df9af889386..0a9389101da2c 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -1248,26 +1248,6 @@ TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) { ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U); } -TEST_P(ASTImporterOptionSpecificTestBase, TemplateArgumentsDefaulted) { - Decl *FromTU = getTuDecl(R"( - template<typename T> struct X {}; - template<typename TP = double, - int NTTP = 50, - template<typename> typename TT = X> struct S {}; - S<> s; - )", - Lang_CXX17); - auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( - FromTU, classTemplateSpecializationDecl(hasName("S"))); - ASSERT_TRUE(FromSpec); - auto *ToSpec = Import(FromSpec, Lang_CXX03); - ASSERT_TRUE(ToSpec); - auto const &TList = ToSpec->getTemplateArgs(); - for (auto const &Arg : TList.asArray()) { - ASSERT_TRUE(Arg.getIsDefaulted()); - } -} - TEST_P(ASTImporterOptionSpecificTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) { Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03); diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp index 6b443918ec137..6e3883c7b86ee 100644 --- a/clang/unittests/AST/DeclTest.cpp +++ b/clang/unittests/AST/DeclTest.cpp @@ -509,37 +509,6 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { EXPECT_TRUE(AlignedArrayDelete->isFromExplicitGlobalModule()); } -TEST(Decl, TemplateArgumentDefaulted) { - llvm::Annotations Code(R"cpp( - template<typename T1, typename T2> - struct Alloc {}; - - template <typename T1, - typename T2 = double, - int T3 = 42, - typename T4 = Alloc<T1, T2>> - struct Foo { - }; - - Foo<char, int, 42, Alloc<char, int>> X; - )cpp"); - - auto AST = - tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"}); - ASTContext &Ctx = AST->getASTContext(); - - auto const *CTSD = selectFirst<ClassTemplateSpecializationDecl>( - "id", - match(classTemplateSpecializationDecl(hasName("Foo")).bind("id"), Ctx)); - ASSERT_NE(CTSD, nullptr); - auto const &ArgList = CTSD->getTemplateArgs(); - - EXPECT_FALSE(ArgList.get(0).getIsDefaulted()); - EXPECT_FALSE(ArgList.get(1).getIsDefaulted()); - EXPECT_TRUE(ArgList.get(2).getIsDefaulted()); - EXPECT_TRUE(ArgList.get(3).getIsDefaulted()); -} - TEST(Decl, CXXDestructorDeclsShouldHaveWellFormedNameInfoRanges) { // GH71161 llvm::Annotations Code(R"cpp( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index a429ea848b7f7..481674519b2b6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2074,7 +2074,6 @@ bool DWARFASTParserClang::ParseTemplateDIE( CompilerType clang_type; uint64_t uval64 = 0; bool uval64_valid = false; - bool is_default_template_arg = false; DWARFFormValue form_value; for (size_t i = 0; i < attributes.Size(); ++i) { const dw_attr_t attr = attributes.AttributeAtIndex(i); @@ -2106,7 +2105,8 @@ bool DWARFASTParserClang::ParseTemplateDIE( break; case DW_AT_default_value: if (attributes.ExtractFormValueAtIndex(i, form_value)) - is_default_template_arg = form_value.Boolean(); + if (form_value.Boolean()) + return true; break; default: break; @@ -2125,9 +2125,9 @@ bool DWARFASTParserClang::ParseTemplateDIE( if (tag == DW_TAG_template_value_parameter && uval64_valid) { if (auto value = MakeAPValue(ast, clang_type, uval64)) { template_param_infos.InsertArg( - name, clang::TemplateArgument( - ast, ClangUtil::GetQualType(clang_type), - std::move(*value), is_default_template_arg)); + name, + clang::TemplateArgument(ast, ClangUtil::GetQualType(clang_type), + std::move(*value))); return true; } } @@ -2136,13 +2136,11 @@ bool DWARFASTParserClang::ParseTemplateDIE( // a non-type template parameter. template_param_infos.InsertArg( name, clang::TemplateArgument(ClangUtil::GetQualType(clang_type), - /*isNullPtr*/ false, - is_default_template_arg)); + /*isNullPtr*/ false); } else { auto *tplt_type = m_ast.CreateTemplateTemplateParmDecl(template_name); template_param_infos.InsertArg( - name, clang::TemplateArgument(clang::TemplateName(tplt_type), - is_default_template_arg)); + name, clang::TemplateArgument(clang::TemplateName(tplt_type))); } } return true; diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp index 0cae01de2902a..9baa3876a402c 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -584,10 +584,6 @@ TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) { auto const &args = ctsd->getTemplateArgs(); ASSERT_GT(args.size(), 0U); - - for (auto const &arg : args.asArray()) { - EXPECT_TRUE(arg.getIsDefaulted()); - } }; for (auto const &type_sp : types) { @@ -620,14 +616,14 @@ TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) { debug_str: - Foo - debug_line: + debug_line: - Version: 4 MinInstLength: 1 MaxOpsPerInst: 1 DefaultIsStmt: 1 LineBase: 0 LineRange: 0 - Files: + Files: - Name: main.cpp DirIdx: 0 ModTime: 0 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits