llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Matheus Izvekov (mizvekov) <details> <summary>Changes</summary> 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: <img width="1459" height="21" alt="image" src="https://github.com/user-attachments/assets/8c7afb31-c821-4c01-b07e-31974af75688" /> The small regression on `-O0 -g` test is explained by the increased amount of debug info generated. --- Patch is 56.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/155120.diff 19 Files Affected: - (modified) clang/include/clang/AST/PropertiesBase.td (+11-41) - (modified) clang/include/clang/AST/TemplateBase.h (+26-49) - (modified) clang/lib/AST/ASTContext.cpp (+7-11) - (modified) clang/lib/AST/ASTImporter.cpp (+6-10) - (modified) clang/lib/AST/TemplateBase.cpp (+7-31) - (modified) clang/lib/AST/TypePrinter.cpp (+6-1) - (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+107-55) - (modified) clang/lib/CodeGen/CGDebugInfo.h (+26-15) - (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (+1-2) - (modified) clang/lib/Sema/SemaTemplate.cpp (-11) - (modified) clang/lib/Serialization/ASTWriterDecl.cpp (-1) - (modified) clang/test/DebugInfo/CXX/template-parameter.cpp (+4-5) - (modified) clang/test/DebugInfo/CXX/template.cpp (+6-5) - (modified) clang/test/DebugInfo/Generic/preferred_name-chain.cpp (+2-2) - (modified) clang/test/DebugInfo/Generic/preferred_name.cpp (+1-5) - (modified) clang/test/Modules/gmodules-preferred-name-typedef.cpp (+1-1) - (modified) clang/test/SemaCXX/cxx14-compat.cpp (+1-1) - (modified) clang/unittests/AST/ASTImporterTest.cpp (-20) - (modified) clang/unittests/AST/DeclTest.cpp (-31) ``````````diff 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<TemplateArgum... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/155120 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits