diff options
author | Matheus Izvekov <mizvekov@gmail.com> | 2025-08-09 18:14:46 -0300 |
---|---|---|
committer | Matheus Izvekov <mizvekov@gmail.com> | 2025-08-23 20:23:30 -0300 |
commit | e1c4ead49256ce93ca35dda58b57d96fdb7e001d (patch) | |
tree | 1d20012f2ce41572261b97ace4c7d9ffb348d3de | |
parent | 0c28482d91dbc80fb26990d0b4fac2974a72322e (diff) | |
download | llvm-users/mizvekov/remove-template-arg-defaulted.zip llvm-users/mizvekov/remove-template-arg-defaulted.tar.gz llvm-users/mizvekov/remove-template-arg-defaulted.tar.bz2 |
[clang] remove isDefaulted bit from TemplateArgumentusers/mizvekov/remove-template-arg-defaulted
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.
22 files changed, 224 insertions, 316 deletions
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 5b10127..f5cc1ba 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 69481e8..46e8437 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -113,8 +113,6 @@ private: struct DA { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; void *QT; ValueDecl *D; }; @@ -122,13 +120,11 @@ private: 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 @@ private: 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 @@ private: 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 @@ private: 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 @@ public: /// 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 @@ public: /// /// \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 @@ public: /// 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 @@ public: /// 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 @@ public: 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 bbb9570..2f33ea8 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 6299efa..617aff4 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 76050ce..6ab364a 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 52ff0d5..1402fea 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 c44fea3..e46a2ee 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 ff9c3cd..e7f3180 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 @@ private: 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 @@ private: /// 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 @@ private: 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 @@ private: 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 @@ private: 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 @@ private: /// 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 726581d..2277435 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 36bffc5..26563a7 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 ec3dda1..2e2c66b 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 b2ca54a..fdcf290 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 a5a17c9..5b25992 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 3108cae..3cbd58d 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 9b3f532..28a4fe6 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 1d2bbd7..cbd186f 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 d6396a7d..9492d92 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 15df9af..0a93891 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 6b44391..6e3883c 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/ExpressionParser/Clang/CxxModuleHandler.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp index 9381a29..563449c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp @@ -239,8 +239,7 @@ std::optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); return std::nullopt; } - imported_args.push_back( - TemplateArgument(*type, /*isNullPtr*/ false, arg.getIsDefaulted())); + imported_args.push_back(TemplateArgument(*type, /*isNullPtr=*/false)); break; } case TemplateArgument::Integral: { @@ -251,8 +250,8 @@ std::optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); return std::nullopt; } - imported_args.push_back(TemplateArgument(d->getASTContext(), integral, - *type, arg.getIsDefaulted())); + imported_args.push_back( + TemplateArgument(d->getASTContext(), integral, *type)); break; } default: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index a429ea8..810ad91 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 0cae01d..9baa387 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 @@ DWARF: 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 |