[Lldb-commits] [lldb] [clang-tools-extra] [clang] [c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (PR #78041)
via lldb-commits
lldb-commits at lists.llvm.org
Sat Jan 13 07:00:32 PST 2024
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
More information about the lldb-commits
mailing list