llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang @llvm/pr-subscribers-lldb Author: Andrey Ali Khan Bolshakov (bolshakov-a) <details> <summary>Changes</summary> Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@<!-- -->zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed. --- Patch is 101.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/78041.diff 47 Files Affected: - (modified) clang-tools-extra/clangd/DumpAST.cpp (+1) - (modified) clang-tools-extra/clangd/FindTarget.cpp (+1) - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/include/clang/AST/ODRHash.h (+3) - (modified) clang/include/clang/AST/PropertiesBase.td (+14) - (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+2) - (modified) clang/include/clang/AST/TemplateArgumentVisitor.h (+2) - (modified) clang/include/clang/AST/TemplateBase.h (+55-31) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (-5) - (modified) clang/include/clang/Sema/Sema.h (+2-2) - (modified) clang/lib/AST/ASTContext.cpp (+5) - (modified) clang/lib/AST/ASTImporter.cpp (+13) - (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+4) - (modified) clang/lib/AST/Decl.cpp (+4) - (modified) clang/lib/AST/ItaniumMangle.cpp (+37-2) - (modified) clang/lib/AST/MicrosoftMangle.cpp (+62-16) - (modified) clang/lib/AST/ODRHash.cpp (+72) - (modified) clang/lib/AST/StmtProfile.cpp (+6) - (modified) clang/lib/AST/TemplateBase.cpp (+110-3) - (modified) clang/lib/AST/TypeLoc.cpp (+1) - (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+10) - (modified) clang/lib/CodeGen/CGExpr.cpp (+12-3) - (modified) clang/lib/Index/USRGeneration.cpp (+10) - (modified) clang/lib/Sema/SemaLookup.cpp (+1) - (modified) clang/lib/Sema/SemaOverload.cpp (+9-1) - (modified) clang/lib/Sema/SemaTemplate.cpp (+130-88) - (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+46-18) - (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+6-8) - (modified) clang/lib/Sema/SemaTemplateVariadic.cpp (+2) - (modified) clang/lib/Sema/TreeTransform.h (+10-2) - (modified) clang/lib/Serialization/ASTReader.cpp (+1) - (modified) clang/lib/Serialization/ASTWriter.cpp (+1) - (modified) clang/test/CXX/drs/dr18xx.cpp (+2-2) - (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (+3-1) - (modified) clang/test/CodeGenCXX/mangle-ms-templates.cpp (+48) - (modified) clang/test/CodeGenCXX/mangle-template.cpp (+39-1) - (added) clang/test/CodeGenCXX/template-arguments.cpp (+113) - (added) clang/test/Index/USR/structural-value-tpl-arg.cpp (+23) - (modified) clang/test/Modules/odr_hash.cpp (+190-3) - (modified) clang/test/SemaCXX/warn-bool-conversion.cpp (+2) - (modified) clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp (+19-21) - (modified) clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp (+22-18) - (modified) clang/tools/libclang/CIndex.cpp (+5) - (modified) clang/tools/libclang/CXCursor.cpp (+3) - (modified) clang/www/cxx_status.html (+13-5) - (modified) lldb/include/lldb/lldb-enumerations.h (+1) - (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+3) ``````````diff diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index b0cec65c39fa31..9a525efb938e8d 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -143,6 +143,7 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> { TEMPLATE_ARGUMENT_KIND(Declaration); TEMPLATE_ARGUMENT_KIND(Template); TEMPLATE_ARGUMENT_KIND(TemplateExpansion); + TEMPLATE_ARGUMENT_KIND(StructuralValue); #undef TEMPLATE_ARGUMENT_KIND } llvm_unreachable("Unhandled ArgKind enum"); diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 839cf6332fe8b0..a4a261030d399b 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -1032,6 +1032,7 @@ class ExplicitReferenceCollector case TemplateArgument::Pack: case TemplateArgument::Type: case TemplateArgument::Expression: + case TemplateArgument::StructuralValue: break; // Handled by VisitType and VisitExpression. }; return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A); diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3cbce1be159437..57c444fd95be1b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -180,6 +180,8 @@ C++ Language Changes C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Implemented `P1907R1 <https://wg21.link/P1907R1>` which extends allowed non-type template argument + kinds with e.g. floating point values and pointers and references to subobjects. C++23 Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index cedf644520fc32..a1caa6d39a87c3 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -25,6 +25,7 @@ namespace clang { +class APValue; class Decl; class IdentifierInfo; class NestedNameSpecifier; @@ -101,6 +102,8 @@ class ODRHash { // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); + void AddStructuralValue(const APValue &); + static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent); private: diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index d86c4eba6a2251..0270c086d06b6a 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -808,6 +808,20 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in { return TemplateArgument(ctx, value, type, isDefaulted); }]>; } +let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in { + def : Property<"value", APValue> { + let Read = [{ node.getAsStructuralValue() }]; + } + def : Property<"type", QualType> { + let Read = [{ node.getStructuralValueType() }]; + } + def : Property<"isDefaulted", Bool> { + let Read = [{ node.getIsDefaulted() }]; + } + def : Creator<[{ + return TemplateArgument(ctx, type, value, isDefaulted); + }]>; +} let Class = PropertyTypeCase<TemplateArgument, "Template"> in { def : Property<"name", TemplateName> { let Read = [{ node.getAsTemplateOrTemplatePattern() }]; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 8f2714e142bbe3..2aee6a947141b6 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -850,6 +850,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::NullPtr: + case TemplateArgument::StructuralValue: return true; case TemplateArgument::Type: @@ -882,6 +883,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::NullPtr: + case TemplateArgument::StructuralValue: return true; case TemplateArgument::Type: { diff --git a/clang/include/clang/AST/TemplateArgumentVisitor.h b/clang/include/clang/AST/TemplateArgumentVisitor.h index 190aa97adf4551..cf0d3220158063 100644 --- a/clang/include/clang/AST/TemplateArgumentVisitor.h +++ b/clang/include/clang/AST/TemplateArgumentVisitor.h @@ -37,6 +37,7 @@ class Base { DISPATCH(Declaration); DISPATCH(NullPtr); DISPATCH(Integral); + DISPATCH(StructuralValue); DISPATCH(Template); DISPATCH(TemplateExpansion); DISPATCH(Expression); @@ -59,6 +60,7 @@ class Base { VISIT_METHOD(Declaration); VISIT_METHOD(NullPtr); VISIT_METHOD(Integral); + VISIT_METHOD(StructuralValue); VISIT_METHOD(Template); VISIT_METHOD(TemplateExpansion); VISIT_METHOD(Expression); diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index b7cd71f17c9442..fea2c8ccfee675 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -50,6 +50,7 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> { namespace clang { +class APValue; class ASTContext; class Expr; struct PrintingPolicy; @@ -80,6 +81,13 @@ class TemplateArgument { /// that was provided for an integral non-type template parameter. Integral, + /// The template argument is a non-type template argument that can't be + /// represented by the special-case Declaration, NullPtr, or Integral + /// forms. These values are only ever produced by constant evaluation, + /// so cannot be dependent. + /// TODO: merge Declaration, NullPtr and Integral into this? + StructuralValue, + /// The template argument is a template name that was provided for a /// template template parameter. Template, @@ -130,6 +138,14 @@ class TemplateArgument { }; void *Type; }; + 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; @@ -156,11 +172,19 @@ class TemplateArgument { union { struct DA DeclArg; struct I Integer; + struct V Value; struct A Args; struct TA TemplateArg; struct TV TypeOrValue; }; + void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted); + void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted); + void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, + QualType Type, bool IsDefaulted); + void initFromStructural(const ASTContext &Ctx, QualType Type, + const APValue &V, bool IsDefaulted); + public: /// Construct an empty, invalid template argument. constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {} @@ -168,25 +192,22 @@ class TemplateArgument { /// Construct a template type argument. TemplateArgument(QualType T, bool isNullPtr = false, bool IsDefaulted = false) { - TypeOrValue.Kind = isNullPtr ? NullPtr : Type; - TypeOrValue.IsDefaulted = IsDefaulted; - TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + initFromType(T, isNullPtr, IsDefaulted); } - /// Construct a template argument that refers to a - /// declaration, which is either an external declaration or a - /// template declaration. + /// Construct a template argument that refers to a (non-dependent) + /// declaration. TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) { - assert(D && "Expected decl"); - DeclArg.Kind = Declaration; - DeclArg.IsDefaulted = IsDefaulted; - DeclArg.QT = QT.getAsOpaquePtr(); - DeclArg.D = D; + initFromDeclaration(D, QT, IsDefaulted); } /// Construct an integral constant template argument. The memory to /// store the value is allocated with Ctx. - TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type, + TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value, + QualType Type, bool IsDefaulted = false); + + /// Construct a template argument from an arbitrary constant value. + TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value, bool IsDefaulted = false); /// Construct an integral constant template argument with the same @@ -297,7 +318,7 @@ class TemplateArgument { /// Retrieve the type for a type template argument. QualType getAsType() const { assert(getKind() == Type && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); + return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V)); } /// Retrieve the declaration for a declaration non-type @@ -315,7 +336,7 @@ class TemplateArgument { /// Retrieve the type for null non-type template argument. QualType getNullPtrType() const { assert(getKind() == NullPtr && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); + return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V)); } /// Retrieve the template name for a template name argument. @@ -371,6 +392,14 @@ class TemplateArgument { /// default template parameter. bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } + /// Get the value of a StructuralValue. + const APValue &getAsStructuralValue() const { return *Value.Value; } + + /// Get the type of a StructuralValue. + QualType getStructuralValueType() const { + return QualType::getFromOpaquePtr(Value.Type); + } + /// If this is a non-type template argument, get its type. Otherwise, /// returns a null QualType. QualType getNonTypeTemplateArgumentType() const; @@ -516,6 +545,7 @@ class TemplateArgumentLoc { assert(Argument.getKind() == TemplateArgument::NullPtr || Argument.getKind() == TemplateArgument::Integral || Argument.getKind() == TemplateArgument::Declaration || + Argument.getKind() == TemplateArgument::StructuralValue || Argument.getKind() == TemplateArgument::Expression); } @@ -541,13 +571,9 @@ class TemplateArgumentLoc { /// - Fetches the full source range of the argument. SourceRange getSourceRange() const LLVM_READONLY; - const TemplateArgument &getArgument() const { - return Argument; - } + const TemplateArgument &getArgument() const { return Argument; } - TemplateArgumentLocInfo getLocInfo() const { - return LocInfo; - } + TemplateArgumentLocInfo getLocInfo() const { return LocInfo; } TypeSourceInfo *getTypeSourceInfo() const { if (Argument.getKind() != TemplateArgument::Type) @@ -575,6 +601,11 @@ class TemplateArgumentLoc { return LocInfo.getAsExpr(); } + Expr *getSourceStructuralValueExpression() const { + assert(Argument.getKind() == TemplateArgument::StructuralValue); + return LocInfo.getAsExpr(); + } + NestedNameSpecifierLoc getTemplateQualifierLoc() const { if (Argument.getKind() != TemplateArgument::Template && Argument.getKind() != TemplateArgument::TemplateExpansion) @@ -606,8 +637,7 @@ class TemplateArgumentListInfo { public: TemplateArgumentListInfo() = default; - TemplateArgumentListInfo(SourceLocation LAngleLoc, - SourceLocation RAngleLoc) + TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc) : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} // This can leak if used in an AST node, use ASTTemplateArgumentListInfo @@ -626,21 +656,15 @@ class TemplateArgumentListInfo { return Arguments.data(); } - llvm::ArrayRef<TemplateArgumentLoc> arguments() const { - return Arguments; - } + llvm::ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; } const TemplateArgumentLoc &operator[](unsigned I) const { return Arguments[I]; } - TemplateArgumentLoc &operator[](unsigned I) { - return Arguments[I]; - } + TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; } - void addArgument(const TemplateArgumentLoc &Loc) { - Arguments.push_back(Loc); - } + void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Loc); } }; /// Represents an explicit template argument list in C++, e.g., diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a79892e40030a..8c74d12e674624 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5138,8 +5138,6 @@ def err_non_type_template_arg_subobject : Error< "non-type template argument refers to subobject '%0'">; def err_non_type_template_arg_addr_label_diff : Error< "template argument / label address difference / what did you expect?">; -def err_non_type_template_arg_unsupported : Error< - "sorry, non-type template argument of type %0 is not yet supported">; def err_template_arg_not_convertible : Error< "non-type template argument of type %0 cannot be converted to a value " "of type %1">; @@ -5191,9 +5189,6 @@ def err_template_arg_not_object_or_func : Error< "non-type template argument does not refer to an object or function">; def err_template_arg_not_pointer_to_member_form : Error< "non-type template argument is not a pointer to member constant">; -def err_template_arg_member_ptr_base_derived_not_supported : Error< - "sorry, non-type template argument of pointer-to-member type %1 that refers " - "to member %q0 of a different class is not supported yet">; def err_template_arg_invalid : Error< "non-type template argument '%0' is invalid">; def ext_template_arg_extra_parens : ExtWarn< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index cf2d4fbe6d3ba1..a3881709263daa 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8569,8 +8569,8 @@ class Sema final { QualType ParamType, SourceLocation Loc); ExprResult - BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, - SourceLocation Loc); + BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, + SourceLocation Loc); /// Enumeration describing how template parameter lists are compared /// for equality. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d9cefcaa84d7e5..2df986c8541057 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6753,6 +6753,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::Integral: return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType())); + case TemplateArgument::StructuralValue: + return TemplateArgument(*this, + getCanonicalType(Arg.getStructuralValueType()), + Arg.getAsStructuralValue()); + case TemplateArgument::Type: return TemplateArgument(getCanonicalType(Arg.getAsType()), /*isNullPtr*/ false, Arg.getIsDefaulted()); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index b762d6a4cd3800..8c279dd1eb048b 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -823,6 +823,17 @@ ASTNodeImporter::import(const TemplateArgument &From) { From.getIsDefaulted()); } + case TemplateArgument::StructuralValue: { + ExpectedType ToTypeOrErr = import(From.getStructuralValueType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + Expected<APValue> ToValueOrErr = import(From.getAsStructuralValue()); + if (!ToValueOrErr) + return ToValueOrErr.takeError(); + return TemplateArgument(Importer.getToContext(), *ToTypeOrErr, + *ToValueOrErr); + } + case TemplateArgument::Template: { Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate()); if (!ToTemplateOrErr) @@ -3572,6 +3583,8 @@ class IsTypeDeclaredInsideVisitor case TemplateArgument::NullPtr: // FIXME: The type is not allowed to be in the function? return CheckType(Arg.getNullPtrType()); + case TemplateArgument::StructuralValue: + return CheckType(Arg.getStructuralValueType()); case TemplateArgument::Pack: for (const auto &PackArg : Arg.getPackAsArray()) if (checkTemplateArgument(PackArg)) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index a9e0d1698a9178..39a2f7ce61e135 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -628,6 +628,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return IsStructurallyEquivalent(Context, Arg1.getAsExpr(), Arg2.getAsExpr()); + case TemplateArgument::StructuralValue: + // FIXME: Do we need to customize the comparison? + return Arg1.structurallyEquals(Arg2); + case TemplateArgument::Pack: return IsStructurallyEquivalent(Context, Arg1.pack_elements(), Arg2.pack_elements()); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index e1440e5183a4e6..a2f50ae4ce8eeb 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -343,6 +343,10 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType())); continue; + case TemplateArgument::StructuralValue: + LV.merge(getLVForValue(Arg.getAsStructuralValue(), computation)); + continue; + case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: if (TemplateDecl *Template = diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index b1678479888eb7..d3ef822b371d5e 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4833,9 +4833,26 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, E = cast<CXXStdInitializerListExpr>(E)->getSubExpr(); goto recurse; - case Expr::SubstNonTypeTemplateParmExprClass: + case Expr::SubstNonTypeTemplateParmExprClass: { + // Mangle a substituted parameter the same way we mangle the template + // argument. + auto *SNTTPE = cast<SubstNonTypeTemplateParmExpr>(E); + if (auto *CE = dyn_cast<ConstantExpr>(SNTTPE->getReplacement())) { + // Pull out the constant value and mangle it as a template argument. + QualType ParamType = SNTTPE->getParameterType(Context.getASTContext()); + if (CE->hasAPValueResult()) + mangleValueInTemplateArg(ParamType, CE->getResultAsAPValue(), false, + /*NeedExactType=*/true); + else + mangleValueInTemplateArg(ParamType, CE->getAPValueResult(), false, + /*NeedExactType=*/true); + break; + } + // The remaining cases all happen to be substituted with expressions that + // mangle the same as a corresponding template argument anyway. E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(); goto recurse; + } case Expr::UserDefinedLiteralClass: // We follow g++'s approach of mangling a UDL as a call to the literal @@ -6064,6 +6081,11 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { mangleNullPointer(A.getNullPtrType()); break; } + case TemplateArgument::StructuralValue: + mangleValueInTemplateArg(A.getStructuralValueType(), + A.getAsStructuralValue(), + /*TopLevel=*/true, NeedExactType); + break; case TemplateArgument::Pack: { // <template-arg> ::= J <template-arg>* E Out << 'J'; @@ -6472,7 +6494,20 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, Out << "plcvPcad"; Kind = Offset; } else { - if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) { + // Clang 11 and before mangled ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/78041 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits