[lldb] [clang] [clang-tools-extra] Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type." (PR #79302)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 24 07:13:22 PST 2024
https://github.com/erichkeane created https://github.com/llvm/llvm-project/pull/79302
Reverts llvm/llvm-project#78041
Based on this comment: https://github.com/llvm/llvm-project/pull/78041#issuecomment-1908243345
and the author's nonavailability to get to it quickly, we're reverting (and will have to revert from the release branch). Hopefully this can be reapplied for 19.
>From 7d1982f62bfc9ec897d8dc8837100c6c2f2de156 Mon Sep 17 00:00:00 2001
From: Erich Keane <ekeane at nvidia.com>
Date: Wed, 24 Jan 2024 07:11:33 -0800
Subject: [PATCH] Revert "[c++20] P1907R1: Support for generalized non-type
template arguments of scalar type."
---
clang-tools-extra/clangd/DumpAST.cpp | 1 -
clang-tools-extra/clangd/FindTarget.cpp | 1 -
clang/include/clang/AST/ODRHash.h | 3 -
clang/include/clang/AST/PropertiesBase.td | 14 --
clang/include/clang/AST/RecursiveASTVisitor.h | 2 -
.../clang/AST/TemplateArgumentVisitor.h | 2 -
clang/include/clang/AST/TemplateBase.h | 86 +++----
.../clang/Basic/DiagnosticSemaKinds.td | 5 +
clang/include/clang/Sema/Sema.h | 4 +-
clang/lib/AST/ASTContext.cpp | 5 -
clang/lib/AST/ASTImporter.cpp | 13 --
clang/lib/AST/ASTStructuralEquivalence.cpp | 3 -
clang/lib/AST/Decl.cpp | 4 -
clang/lib/AST/ItaniumMangle.cpp | 36 +--
clang/lib/AST/MicrosoftMangle.cpp | 78 ++-----
clang/lib/AST/ODRHash.cpp | 67 ------
clang/lib/AST/StmtProfile.cpp | 6 -
clang/lib/AST/TemplateBase.cpp | 113 +--------
clang/lib/AST/TypeLoc.cpp | 1 -
clang/lib/CodeGen/CGDebugInfo.cpp | 10 -
clang/lib/CodeGen/CGExpr.cpp | 12 +-
clang/lib/Index/USRGeneration.cpp | 10 -
clang/lib/Sema/SemaLookup.cpp | 1 -
clang/lib/Sema/SemaOverload.cpp | 10 +-
clang/lib/Sema/SemaTemplate.cpp | 218 +++++++-----------
clang/lib/Sema/SemaTemplateDeduction.cpp | 64 ++---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 14 +-
clang/lib/Sema/SemaTemplateVariadic.cpp | 2 -
clang/lib/Sema/TreeTransform.h | 12 +-
clang/lib/Serialization/ASTReader.cpp | 1 -
clang/lib/Serialization/ASTWriter.cpp | 1 -
clang/test/CXX/drs/dr18xx.cpp | 4 +-
.../CXX/temp/temp.arg/temp.arg.nontype/p1.cpp | 4 +-
clang/test/CodeGenCXX/mangle-ms-templates.cpp | 48 ----
clang/test/CodeGenCXX/mangle-template.cpp | 40 +---
clang/test/CodeGenCXX/template-arguments.cpp | 113 ---------
.../Index/USR/structural-value-tpl-arg.cpp | 23 --
clang/test/Modules/odr_hash.cpp | 193 +---------------
clang/test/SemaCXX/warn-bool-conversion.cpp | 2 -
.../SemaTemplate/temp_arg_nontype_cxx1z.cpp | 40 ++--
.../SemaTemplate/temp_arg_nontype_cxx20.cpp | 40 ++--
clang/tools/libclang/CIndex.cpp | 5 -
clang/tools/libclang/CXCursor.cpp | 3 -
clang/www/cxx_status.html | 18 +-
lldb/include/lldb/lldb-enumerations.h | 1 -
.../TypeSystem/Clang/TypeSystemClang.cpp | 3 -
46 files changed, 230 insertions(+), 1106 deletions(-)
delete mode 100644 clang/test/CodeGenCXX/template-arguments.cpp
delete mode 100644 clang/test/Index/USR/structural-value-tpl-arg.cpp
diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp
index 9a525efb938e8d5..b0cec65c39fa31d 100644
--- a/clang-tools-extra/clangd/DumpAST.cpp
+++ b/clang-tools-extra/clangd/DumpAST.cpp
@@ -143,7 +143,6 @@ 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 e702c6b3537a098..3d73e77b16aff4e 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -1039,7 +1039,6 @@ 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/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h
index a1caa6d39a87c3c..cedf644520fc320 100644
--- a/clang/include/clang/AST/ODRHash.h
+++ b/clang/include/clang/AST/ODRHash.h
@@ -25,7 +25,6 @@
namespace clang {
-class APValue;
class Decl;
class IdentifierInfo;
class NestedNameSpecifier;
@@ -102,8 +101,6 @@ 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 0270c086d06b6ad..d86c4eba6a22511 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -808,20 +808,6 @@ 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 2aee6a947141b6c..8f2714e142bbe3e 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -850,7 +850,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::NullPtr:
- case TemplateArgument::StructuralValue:
return true;
case TemplateArgument::Type:
@@ -883,7 +882,6 @@ 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 cf0d32201580633..190aa97adf45516 100644
--- a/clang/include/clang/AST/TemplateArgumentVisitor.h
+++ b/clang/include/clang/AST/TemplateArgumentVisitor.h
@@ -37,7 +37,6 @@ class Base {
DISPATCH(Declaration);
DISPATCH(NullPtr);
DISPATCH(Integral);
- DISPATCH(StructuralValue);
DISPATCH(Template);
DISPATCH(TemplateExpansion);
DISPATCH(Expression);
@@ -60,7 +59,6 @@ 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 fea2c8ccfee675e..b7cd71f17c9442c 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -50,7 +50,6 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> {
namespace clang {
-class APValue;
class ASTContext;
class Expr;
struct PrintingPolicy;
@@ -81,13 +80,6 @@ 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,
@@ -138,14 +130,6 @@ 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;
@@ -172,19 +156,11 @@ 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}) {}
@@ -192,22 +168,25 @@ class TemplateArgument {
/// Construct a template type argument.
TemplateArgument(QualType T, bool isNullPtr = false,
bool IsDefaulted = false) {
- initFromType(T, isNullPtr, IsDefaulted);
+ TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
+ TypeOrValue.IsDefaulted = IsDefaulted;
+ TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
}
- /// Construct a template argument that refers to a (non-dependent)
- /// declaration.
+ /// Construct a template argument that refers to a
+ /// declaration, which is either an external declaration or a
+ /// template declaration.
TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) {
- initFromDeclaration(D, QT, IsDefaulted);
+ assert(D && "Expected decl");
+ DeclArg.Kind = Declaration;
+ DeclArg.IsDefaulted = IsDefaulted;
+ DeclArg.QT = QT.getAsOpaquePtr();
+ DeclArg.D = D;
}
/// 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);
-
- /// Construct a template argument from an arbitrary constant value.
- TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value,
+ TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type,
bool IsDefaulted = false);
/// Construct an integral constant template argument with the same
@@ -318,7 +297,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
@@ -336,7 +315,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.
@@ -392,14 +371,6 @@ 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;
@@ -545,7 +516,6 @@ class TemplateArgumentLoc {
assert(Argument.getKind() == TemplateArgument::NullPtr ||
Argument.getKind() == TemplateArgument::Integral ||
Argument.getKind() == TemplateArgument::Declaration ||
- Argument.getKind() == TemplateArgument::StructuralValue ||
Argument.getKind() == TemplateArgument::Expression);
}
@@ -571,9 +541,13 @@ 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)
@@ -601,11 +575,6 @@ 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)
@@ -637,7 +606,8 @@ 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
@@ -656,15 +626,21 @@ 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 a1c32abb4dcd880..cce58b571a584b3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5161,6 +5161,8 @@ 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<
+ "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">;
@@ -5212,6 +5214,9 @@ 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<
+ "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 1f1cbd11ff73581..d4c33dd65bb96f1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8595,8 +8595,8 @@ class Sema final {
QualType ParamType,
SourceLocation Loc);
ExprResult
- BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
- SourceLocation Loc);
+ BuildExpressionFromIntegralTemplateArgument(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 5eb7aa3664569dd..0fc0831b221aab3 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -6754,11 +6754,6 @@ 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 12734d62ed9fb76..b364796073022bd 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -823,17 +823,6 @@ 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)
@@ -3583,8 +3572,6 @@ 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 be7a850a2982c73..5103fc86a800513 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -685,9 +685,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
Arg2.getAsExpr());
- case TemplateArgument::StructuralValue:
- 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 26fdfa040796ed4..2c3a0afee8cefc2 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -343,10 +343,6 @@ 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 40b1e086ddd0c61..f78265df0713f55 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4833,23 +4833,9 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
E = cast<CXXStdInitializerListExpr>(E)->getSubExpr();
goto recurse;
- 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());
- assert(CE->hasAPValueResult() && "expected the NTTP to have an APValue");
- 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.
+ case Expr::SubstNonTypeTemplateParmExprClass:
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
@@ -6078,11 +6064,6 @@ 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';
@@ -6491,20 +6472,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
Out << "plcvPcad";
Kind = Offset;
} else {
- // Clang 11 and before mangled an array subject to array-to-pointer decay
- // as if it were the declaration itself.
- bool IsArrayToPointerDecayMangledAsDecl = false;
- if (TopLevel && Ctx.getLangOpts().getClangABICompat() <=
- LangOptions::ClangABI::Ver11) {
- QualType BType = B.getType();
- IsArrayToPointerDecayMangledAsDecl =
- BType->isArrayType() && V.getLValuePath().size() == 1 &&
- V.getLValuePath()[0].getAsArrayIndex() == 0 &&
- Ctx.hasSimilarType(T, Ctx.getDecayedType(BType));
- }
-
- if ((!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) &&
- !IsArrayToPointerDecayMangledAsDecl) {
+ if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) {
NotPrimaryExpr();
// A final conversion to the template parameter's type is usually
// folded into the 'so' mangling, but we can't do that for 'void*'
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 36b5bf64f675a88..8346ad87b409b61 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -337,7 +337,6 @@ class MicrosoftCXXNameMangler {
public:
enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
- enum class TplArgKind { ClassNTTP, StructuralValue };
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
: Context(C), Out(Out_), Structor(nullptr), StructorType(-1),
@@ -454,7 +453,7 @@ class MicrosoftCXXNameMangler {
const TemplateArgumentList &TemplateArgs);
void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
const NamedDecl *Parm);
- void mangleTemplateArgValue(QualType T, const APValue &V, TplArgKind,
+ void mangleTemplateArgValue(QualType T, const APValue &V,
bool WithScalarType = false);
void mangleObjCProtocol(const ObjCProtocolDecl *PD);
@@ -1089,7 +1088,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
Out << "?__N";
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
- TPO->getValue(), TplArgKind::ClassNTTP);
+ TPO->getValue());
break;
}
@@ -1605,22 +1604,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
}
}
-/// If value V (with type T) represents a decayed pointer to the first element
-/// of an array, return that array.
-static ValueDecl *getAsArrayToPointerDecayedDecl(QualType T, const APValue &V) {
- // Must be a pointer...
- if (!T->isPointerType() || !V.isLValue() || !V.hasLValuePath() ||
- !V.getLValueBase())
- return nullptr;
- // ... to element 0 of an array.
- QualType BaseT = V.getLValueBase().getType();
- if (!BaseT->isArrayType() || V.getLValuePath().size() != 1 ||
- V.getLValuePath()[0].getAsArrayIndex() != 0)
- return nullptr;
- return const_cast<ValueDecl *>(
- V.getLValueBase().dyn_cast<const ValueDecl *>());
-}
-
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
const TemplateArgument &TA,
const NamedDecl *Parm) {
@@ -1686,7 +1669,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
Out << "$";
auto *TPO = cast<TemplateParamObjectDecl>(ND);
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
- TPO->getValue(), TplArgKind::ClassNTTP);
+ TPO->getValue());
} else {
mangle(ND, "$1?");
}
@@ -1729,27 +1712,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
cast<NonTypeTemplateParmDecl>(Parm), T);
break;
}
- case TemplateArgument::StructuralValue:
- if (ValueDecl *D = getAsArrayToPointerDecayedDecl(
- TA.getStructuralValueType(), TA.getAsStructuralValue())) {
- // Mangle the result of array-to-pointer decay as if it were a reference
- // to the original declaration, to match MSVC's behavior. This can result
- // in mangling collisions in some cases!
- return mangleTemplateArg(
- TD, TemplateArgument(D, TA.getStructuralValueType()), Parm);
- }
- Out << "$";
- if (cast<NonTypeTemplateParmDecl>(Parm)
- ->getType()
- ->getContainedDeducedType()) {
- Out << "M";
- mangleType(TA.getNonTypeTemplateArgumentType(), SourceRange(), QMM_Drop);
- }
- mangleTemplateArgValue(TA.getStructuralValueType(),
- TA.getAsStructuralValue(),
- TplArgKind::StructuralValue,
- /*WithScalarType=*/false);
- break;
case TemplateArgument::Expression:
mangleExpression(TA.getAsExpr(), cast<NonTypeTemplateParmDecl>(Parm));
break;
@@ -1792,7 +1754,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const APValue &V,
- TplArgKind TAK,
bool WithScalarType) {
switch (V.getKind()) {
case APValue::None:
@@ -1845,7 +1806,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
break;
}
} else {
- if (TAK == TplArgKind::ClassNTTP && T->isPointerType())
+ if (T->isPointerType())
Out << "5";
SmallVector<char, 2> EntryTypes;
@@ -1889,12 +1850,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
auto *VD = Base.dyn_cast<const ValueDecl*>();
if (!VD)
break;
- Out << (TAK == TplArgKind::ClassNTTP ? 'E' : '1');
+ Out << "E";
mangle(VD);
for (const std::function<void()> &Mangler : EntryManglers)
Mangler();
- if (TAK == TplArgKind::ClassNTTP && T->isPointerType())
+ if (T->isPointerType())
Out << '@';
}
@@ -1908,18 +1869,11 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const CXXRecordDecl *RD =
T->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl();
const ValueDecl *D = V.getMemberPointerDecl();
- if (TAK == TplArgKind::ClassNTTP) {
- if (T->isMemberDataPointerType())
- mangleMemberDataPointerInClassNTTP(RD, D);
- else
- mangleMemberFunctionPointerInClassNTTP(RD,
- cast_or_null<CXXMethodDecl>(D));
- } else {
- if (T->isMemberDataPointerType())
- mangleMemberDataPointer(RD, D, "");
- else
- mangleMemberFunctionPointer(RD, cast_or_null<CXXMethodDecl>(D), "");
- }
+ if (T->isMemberDataPointerType())
+ mangleMemberDataPointerInClassNTTP(RD, D);
+ else
+ mangleMemberFunctionPointerInClassNTTP(RD,
+ cast_or_null<CXXMethodDecl>(D));
return;
}
@@ -1931,11 +1885,11 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
unsigned BaseIndex = 0;
for (const CXXBaseSpecifier &B : RD->bases())
- mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++), TAK);
+ mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++));
for (const FieldDecl *FD : RD->fields())
if (!FD->isUnnamedBitfield())
mangleTemplateArgValue(FD->getType(),
- V.getStructField(FD->getFieldIndex()), TAK,
+ V.getStructField(FD->getFieldIndex()),
/*WithScalarType*/ true);
Out << '@';
return;
@@ -1946,7 +1900,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
mangleType(T, SourceRange(), QMM_Escape);
if (const FieldDecl *FD = V.getUnionField()) {
mangleUnqualifiedName(FD);
- mangleTemplateArgValue(FD->getType(), V.getUnionValue(), TAK);
+ mangleTemplateArgValue(FD->getType(), V.getUnionValue());
}
Out << '@';
return;
@@ -1978,7 +1932,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const APValue &ElemV = I < V.getArrayInitializedElts()
? V.getArrayInitializedElt(I)
: V.getArrayFiller();
- mangleTemplateArgValue(ElemT, ElemV, TAK);
+ mangleTemplateArgValue(ElemT, ElemV);
Out << '@';
}
Out << '@';
@@ -1995,7 +1949,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
mangleType(ElemT, SourceRange(), QMM_Escape);
for (unsigned I = 0, N = V.getVectorLength(); I != N; ++I) {
const APValue &ElemV = V.getVectorElt(I);
- mangleTemplateArgValue(ElemT, ElemV, TAK);
+ mangleTemplateArgValue(ElemT, ElemV);
Out << '@';
}
Out << "@@";
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 5b98646a1e8dc0d..c5aa91a81da0535 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -180,10 +180,6 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) {
TA.getAsIntegral().Profile(ID);
break;
}
- case TemplateArgument::StructuralValue:
- AddQualType(TA.getStructuralValueType());
- AddStructuralValue(TA.getAsStructuralValue());
- break;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
AddTemplateName(TA.getAsTemplateOrTemplatePattern());
@@ -1300,66 +1296,3 @@ void ODRHash::AddQualType(QualType T) {
void ODRHash::AddBoolean(bool Value) {
Bools.push_back(Value);
}
-
-void ODRHash::AddStructuralValue(const APValue &Value) {
- ID.AddInteger(Value.getKind());
-
- // 'APValue::Profile' uses pointer values to make hash for LValue and
- // MemberPointer, but they differ from one compiler invocation to another.
- // So, handle them explicitly here.
-
- switch (Value.getKind()) {
- case APValue::LValue: {
- const APValue::LValueBase &Base = Value.getLValueBase();
- if (!Base) {
- ID.AddInteger(Value.getLValueOffset().getQuantity());
- break;
- }
-
- assert(Base.is<const ValueDecl *>());
- AddDecl(Base.get<const ValueDecl *>());
- ID.AddInteger(Value.getLValueOffset().getQuantity());
-
- bool OnePastTheEnd = Value.isLValueOnePastTheEnd();
- if (Value.hasLValuePath()) {
- QualType TypeSoFar = Base.getType();
- for (APValue::LValuePathEntry E : Value.getLValuePath()) {
- if (const auto *AT = TypeSoFar->getAsArrayTypeUnsafe()) {
- if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
- OnePastTheEnd |= CAT->getSize() == E.getAsArrayIndex();
- TypeSoFar = AT->getElementType();
- } else {
- const Decl *D = E.getAsBaseOrMember().getPointer();
- if (const auto *FD = dyn_cast<FieldDecl>(D)) {
- if (FD->getParent()->isUnion())
- ID.AddInteger(FD->getFieldIndex());
- TypeSoFar = FD->getType();
- } else {
- TypeSoFar =
- D->getASTContext().getRecordType(cast<CXXRecordDecl>(D));
- }
- }
- }
- }
- unsigned Val = 0;
- if (Value.isNullPointer())
- Val |= 1 << 0;
- if (OnePastTheEnd)
- Val |= 1 << 1;
- if (Value.hasLValuePath())
- Val |= 1 << 2;
- ID.AddInteger(Val);
- break;
- }
- case APValue::MemberPointer: {
- const ValueDecl *D = Value.getMemberPointerDecl();
- assert(D);
- AddDecl(D);
- ID.AddInteger(
- D->getASTContext().getMemberPointerPathAdjustment(Value).getQuantity());
- break;
- }
- default:
- Value.Profile(ID);
- }
-}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index dd0838edab7b3f9..d7b980a585702a5 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2416,12 +2416,6 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
Arg.getAsIntegral().Profile(ID);
break;
- case TemplateArgument::StructuralValue:
- VisitType(Arg.getStructuralValueType());
- // FIXME: Do we need to recursively decompose this ourselves?
- Arg.getAsStructuralValue().Profile(ID);
- break;
-
case TemplateArgument::Expression:
Visit(Arg.getAsExpr());
break;
diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index 2bdbeb08ef20465..2ec0b2cce08ca49 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -161,25 +161,8 @@ 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) {
+TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
+ QualType Type, bool IsDefaulted) {
Integer.Kind = Integral;
Integer.IsDefaulted = IsDefaulted;
// Copy the APSInt value into our decomposed form.
@@ -198,56 +181,6 @@ void TemplateArgument::initFromIntegral(const ASTContext &Ctx,
Integer.Type = Type.getAsOpaquePtr();
}
-void TemplateArgument::initFromStructural(const ASTContext &Ctx, QualType Type,
- const APValue &V, bool IsDefaulted) {
- 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.
- if (V.isMemberPointer() && V.getMemberPointerPath().empty())
- return V.getMemberPointerDecl();
-
- // We model class non-type template parameters as their template parameter
- // object declaration.
- if (V.isStruct() || V.isUnion())
- return Ctx.getTemplateParamObjectDecl(T, V);
-
- // Pointers and references with an empty path use the special 'Declaration'
- // representation.
- if (V.isLValue() && V.hasLValuePath() && V.getLValuePath().empty() &&
- !V.isLValueOnePastTheEnd())
- return V.getLValueBase().dyn_cast<const ValueDecl *>();
-
- // Everything else uses the 'structural' representation.
- return nullptr;
-}
-
-TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type,
- const APValue &V, bool IsDefaulted) {
- if (Type->isIntegralOrEnumerationType() && V.isInt())
- initFromIntegral(Ctx, V.getInt(), Type, IsDefaulted);
- else if ((V.isLValue() && V.isNullPointer()) ||
- (V.isMemberPointer() && !V.getMemberPointerDecl()))
- initFromType(Type, /*isNullPtr=*/true, IsDefaulted);
- 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);
- else
- initFromStructural(Ctx, Type, V, IsDefaulted);
-}
-
TemplateArgument
TemplateArgument::CreatePackCopy(ASTContext &Context,
ArrayRef<TemplateArgument> Args) {
@@ -288,7 +221,6 @@ TemplateArgumentDependence TemplateArgument::getDependence() const {
case NullPtr:
case Integral:
- case StructuralValue:
return TemplateArgumentDependence::None;
case Expression:
@@ -319,7 +251,6 @@ bool TemplateArgument::isPackExpansion() const {
case Null:
case Declaration:
case Integral:
- case StructuralValue:
case Pack:
case Template:
case NullPtr:
@@ -370,9 +301,6 @@ QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
case TemplateArgument::NullPtr:
return getNullPtrType();
-
- case TemplateArgument::StructuralValue:
- return getStructuralValueType();
}
llvm_unreachable("Invalid TemplateArgument Kind!");
@@ -406,13 +334,8 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
break;
case Integral:
- getIntegralType().Profile(ID);
getAsIntegral().Profile(ID);
- break;
-
- case StructuralValue:
- getStructuralValueType().Profile(ID);
- getAsStructuralValue().Profile(ID);
+ getIntegralType().Profile(ID);
break;
case Expression:
@@ -449,16 +372,6 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
return getIntegralType() == Other.getIntegralType() &&
getAsIntegral() == Other.getAsIntegral();
- case StructuralValue: {
- if (getStructuralValueType() != Other.getStructuralValueType())
- return false;
-
- llvm::FoldingSetNodeID A, B;
- getAsStructuralValue().Profile(A);
- Other.getAsStructuralValue().Profile(B);
- return A == B;
- }
-
case Pack:
if (Args.NumArgs != Other.Args.NumArgs) return false;
for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
@@ -485,7 +398,6 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
case Declaration:
case Integral:
- case StructuralValue:
case Pack:
case Null:
case Template:
@@ -528,10 +440,6 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
break;
}
- case StructuralValue:
- getAsStructuralValue().printPretty(Out, Policy, getStructuralValueType());
- break;
-
case NullPtr:
// FIXME: Include the type if it's not obvious from the context.
Out << "nullptr";
@@ -615,9 +523,6 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
case TemplateArgument::Integral:
return getSourceIntegralExpression()->getSourceRange();
- case TemplateArgument::StructuralValue:
- return getSourceStructuralValueExpression()->getSourceRange();
-
case TemplateArgument::Pack:
case TemplateArgument::Null:
return SourceRange();
@@ -646,18 +551,6 @@ static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
case TemplateArgument::Integral:
return DB << toString(Arg.getAsIntegral(), 10);
- case TemplateArgument::StructuralValue: {
- // FIXME: We're guessing at LangOptions!
- SmallString<32> Str;
- llvm::raw_svector_ostream OS(Str);
- LangOptions LangOpts;
- LangOpts.CPlusPlus = true;
- PrintingPolicy Policy(LangOpts);
- Arg.getAsStructuralValue().printPretty(OS, Policy,
- Arg.getStructuralValueType());
- return DB << OS.str();
- }
-
case TemplateArgument::Template:
return DB << Arg.getAsTemplate();
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 66732bba18e2d68..e12b9b50f6e7224 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -586,7 +586,6 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::NullPtr:
- case TemplateArgument::StructuralValue:
ArgInfos[i] = TemplateArgumentLocInfo();
break;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0f3f684d61dc943..c5b96f93b42c383 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2201,14 +2201,6 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
TheCU, Name, TTy, defaultParameter, V));
} break;
- case TemplateArgument::StructuralValue: {
- QualType T = TA.getStructuralValueType();
- llvm::DIType *TTy = getOrCreateType(T, Unit);
- llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(
- SourceLocation(), TA.getAsStructuralValue(), T);
- TemplateParams.push_back(DBuilder.createTemplateValueParameter(
- TheCU, Name, TTy, defaultParameter, V));
- } break;
case TemplateArgument::Template: {
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -5409,8 +5401,6 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const {
// feasible some day.
return TA.getAsIntegral().getBitWidth() <= 64 &&
IsReconstitutableType(TA.getIntegralType());
- case TemplateArgument::StructuralValue:
- return false;
case TemplateArgument::Type:
return IsReconstitutableType(TA.getAsType());
default:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index c5f6b6d3a99f0b2..d12e85b48d0b00b 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1516,14 +1516,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E,
return LV;
}
-static QualType getConstantExprReferredType(const FullExpr *E,
- const ASTContext &Ctx) {
- const Expr *SE = E->getSubExpr()->IgnoreImplicit();
- if (isa<OpaqueValueExpr>(SE))
- return SE->getType();
- return cast<CallExpr>(SE)->getCallReturnType(Ctx)->getPointeeType();
-}
-
LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
KnownNonNull_t IsKnownNonNull) {
ApplyDebugLocation DL(*this, E);
@@ -1562,7 +1554,9 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
case Expr::ConstantExprClass: {
const ConstantExpr *CE = cast<ConstantExpr>(E);
if (llvm::Value *Result = ConstantEmitter(*this).tryEmitConstantExpr(CE)) {
- QualType RetType = getConstantExprReferredType(CE, getContext());
+ QualType RetType = cast<CallExpr>(CE->getSubExpr()->IgnoreImplicit())
+ ->getCallReturnType(getContext())
+ ->getPointeeType();
return MakeNaturalAlignAddrLValue(Result, RetType);
}
return EmitLValue(cast<ConstantExpr>(E)->getSubExpr(), IsKnownNonNull);
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 5acc86191f8f9c0..fb936d9fbf8ab47 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -12,7 +12,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/ODRHash.h"
#include "clang/Basic/FileManager.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "llvm/Support/Path.h"
@@ -1052,15 +1051,6 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
VisitType(Arg.getIntegralType());
Out << Arg.getAsIntegral();
break;
-
- case TemplateArgument::StructuralValue: {
- Out << 'S';
- VisitType(Arg.getStructuralValueType());
- ODRHash Hash{};
- Hash.AddStructuralValue(Arg.getAsStructuralValue());
- Out << Hash.CalculateHash();
- break;
- }
}
}
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 02b1a045df44c20..996f8b57233ba22 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2982,7 +2982,6 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
case TemplateArgument::Integral:
case TemplateArgument::Expression:
case TemplateArgument::NullPtr:
- case TemplateArgument::StructuralValue:
// [Note: non-type template arguments do not contribute to the set of
// associated namespaces. ]
break;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 030878899b81223..c532f40f2a51475 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6217,15 +6217,7 @@ Sema::EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value,
if (Notes.empty()) {
// It's a constant expression.
- Expr *E = Result.get();
- if (const auto *CE = dyn_cast<ConstantExpr>(E)) {
- // We expect a ConstantExpr to have a value associated with it
- // by this point.
- assert(CE->getResultStorageKind() != ConstantResultStorageKind::None &&
- "ConstantExpr has no value associated with it");
- } else {
- E = ConstantExpr::Create(Context, Result.get(), Value);
- }
+ Expr *E = ConstantExpr::Create(Context, Result.get(), Value);
if (!PreNarrowingValue.isAbsent())
Value = std::move(PreNarrowingValue);
return E;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 9bfa71dc8bcf1db..839d508b911f063 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4427,7 +4427,6 @@ static bool isTemplateArgumentTemplateParameter(
case TemplateArgument::NullPtr:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
- case TemplateArgument::StructuralValue:
case TemplateArgument::Pack:
case TemplateArgument::TemplateExpansion:
return false;
@@ -5759,7 +5758,6 @@ bool Sema::CheckTemplateArgument(
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
- case TemplateArgument::StructuralValue:
case TemplateArgument::NullPtr:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
@@ -5914,10 +5912,11 @@ bool Sema::CheckTemplateArgument(
return true;
case TemplateArgument::Declaration:
+ llvm_unreachable("Declaration argument with template template parameter");
case TemplateArgument::Integral:
- case TemplateArgument::StructuralValue:
+ llvm_unreachable("Integral argument with template template parameter");
case TemplateArgument::NullPtr:
- llvm_unreachable("non-type argument with template template parameter");
+ llvm_unreachable("Null pointer argument with template template parameter");
case TemplateArgument::Pack:
llvm_unreachable("Caller must expand template argument packs");
@@ -7412,9 +7411,44 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (ArgResult.isInvalid())
return ExprError();
- // Prior to C++20, enforce restrictions on possible template argument
- // values.
- if (!getLangOpts().CPlusPlus20 && Value.isLValue()) {
+ // Convert the APValue to a TemplateArgument.
+ switch (Value.getKind()) {
+ case APValue::None:
+ assert(ParamType->isNullPtrType());
+ SugaredConverted = TemplateArgument(ParamType, /*isNullPtr=*/true);
+ CanonicalConverted = TemplateArgument(CanonParamType, /*isNullPtr=*/true);
+ break;
+ case APValue::Indeterminate:
+ llvm_unreachable("result of constant evaluation should be initialized");
+ break;
+ case APValue::Int:
+ assert(ParamType->isIntegralOrEnumerationType());
+ SugaredConverted = TemplateArgument(Context, Value.getInt(), ParamType);
+ CanonicalConverted =
+ TemplateArgument(Context, Value.getInt(), CanonParamType);
+ break;
+ case APValue::MemberPointer: {
+ assert(ParamType->isMemberPointerType());
+
+ // FIXME: We need TemplateArgument representation and mangling for these.
+ if (!Value.getMemberPointerPath().empty()) {
+ Diag(Arg->getBeginLoc(),
+ diag::err_template_arg_member_ptr_base_derived_not_supported)
+ << Value.getMemberPointerDecl() << ParamType
+ << Arg->getSourceRange();
+ return ExprError();
+ }
+
+ auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl());
+ SugaredConverted = VD ? TemplateArgument(VD, ParamType)
+ : TemplateArgument(ParamType, /*isNullPtr=*/true);
+ CanonicalConverted =
+ VD ? TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()),
+ CanonParamType)
+ : TemplateArgument(CanonParamType, /*isNullPtr=*/true);
+ break;
+ }
+ case APValue::LValue: {
// For a non-type template-parameter of pointer or reference type,
// the value of the constant expression shall not refer to
assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
@@ -7432,7 +7466,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
<< Arg->getSourceRange();
return ExprError();
}
- // -- a subobject [until C++20]
+ // -- a subobject
+ // FIXME: Until C++20
if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
VD && VD->getType()->isArrayType() &&
Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
@@ -7450,13 +7485,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
"null reference should not be a constant expression");
assert((!VD || !ParamType->isNullPtrType()) &&
"non-null value of type nullptr_t?");
- }
- if (Value.isAddrLabelDiff())
+ SugaredConverted = VD ? TemplateArgument(VD, ParamType)
+ : TemplateArgument(ParamType, /*isNullPtr=*/true);
+ CanonicalConverted =
+ VD ? TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()),
+ CanonParamType)
+ : TemplateArgument(CanonParamType, /*isNullPtr=*/true);
+ break;
+ }
+ case APValue::Struct:
+ case APValue::Union: {
+ // Get or create the corresponding template parameter object.
+ TemplateParamObjectDecl *D =
+ Context.getTemplateParamObjectDecl(ParamType, Value);
+ SugaredConverted = TemplateArgument(D, ParamType);
+ CanonicalConverted =
+ TemplateArgument(D->getCanonicalDecl(), CanonParamType);
+ break;
+ }
+ case APValue::AddrLabelDiff:
return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff);
+ case APValue::FixedPoint:
+ case APValue::Float:
+ case APValue::ComplexInt:
+ case APValue::ComplexFloat:
+ case APValue::Vector:
+ case APValue::Array:
+ return Diag(StartLoc, diag::err_non_type_template_arg_unsupported)
+ << ParamType;
+ }
- SugaredConverted = TemplateArgument(Context, ParamType, Value);
- CanonicalConverted = TemplateArgument(Context, CanonParamType, Value);
return ArgResult.get();
}
@@ -8040,9 +8099,12 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
/// This routine takes care of the mapping from an integral template
/// argument (which may have any integral type) to the appropriate
/// literal value.
-static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
- Sema &S, QualType OrigT, const llvm::APSInt &Int, SourceLocation Loc) {
- assert(OrigT->isIntegralOrEnumerationType());
+ExprResult
+Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+ SourceLocation Loc) {
+ assert(Arg.getKind() == TemplateArgument::Integral &&
+ "Operation is only valid for integral template arguments");
+ QualType OrigT = Arg.getIntegralType();
// If this is an enum type that we're instantiating, we need to use an integer
// type the same size as the enumerator. We don't want to build an
@@ -8058,7 +8120,7 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
CharacterLiteralKind Kind;
if (T->isWideCharType())
Kind = CharacterLiteralKind::Wide;
- else if (T->isChar8Type() && S.getLangOpts().Char8)
+ else if (T->isChar8Type() && getLangOpts().Char8)
Kind = CharacterLiteralKind::UTF8;
else if (T->isChar16Type())
Kind = CharacterLiteralKind::UTF16;
@@ -8067,133 +8129,29 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
else
Kind = CharacterLiteralKind::Ascii;
- E = new (S.Context) CharacterLiteral(Int.getZExtValue(), Kind, T, Loc);
+ E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(),
+ Kind, T, Loc);
} else if (T->isBooleanType()) {
- E = CXXBoolLiteralExpr::Create(S.Context, Int.getBoolValue(), T, Loc);
+ E = CXXBoolLiteralExpr::Create(Context, Arg.getAsIntegral().getBoolValue(),
+ T, Loc);
+ } else if (T->isNullPtrType()) {
+ E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc);
} else {
- E = IntegerLiteral::Create(S.Context, Int, T, Loc);
+ E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), T, Loc);
}
if (OrigT->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
- E = CStyleCastExpr::Create(S.Context, OrigT, VK_PRValue, CK_IntegralCast, E,
- nullptr, S.CurFPFeatureOverrides(),
- S.Context.getTrivialTypeSourceInfo(OrigT, Loc),
+ E = CStyleCastExpr::Create(Context, OrigT, VK_PRValue, CK_IntegralCast, E,
+ nullptr, CurFPFeatureOverrides(),
+ Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
}
return E;
}
-static Expr *BuildExpressionFromNonTypeTemplateArgumentValue(
- Sema &S, QualType T, const APValue &Val, SourceLocation Loc) {
- auto MakeInitList = [&](ArrayRef<Expr *> Elts) -> Expr * {
- auto *ILE = new (S.Context) InitListExpr(S.Context, Loc, Elts, Loc);
- ILE->setType(T);
- return ILE;
- };
-
- switch (Val.getKind()) {
- case APValue::AddrLabelDiff:
- // This cannot occur in a template argument at all.
- case APValue::Array:
- case APValue::Struct:
- case APValue::Union:
- // These can only occur within a template parameter object, which is
- // represented as a TemplateArgument::Declaration.
- llvm_unreachable("unexpected template argument value");
-
- case APValue::Int:
- return BuildExpressionFromIntegralTemplateArgumentValue(S, T, Val.getInt(),
- Loc);
-
- case APValue::Float:
- return FloatingLiteral::Create(S.Context, Val.getFloat(), /*IsExact=*/true,
- T, Loc);
-
- case APValue::FixedPoint:
- return FixedPointLiteral::CreateFromRawInt(
- S.Context, Val.getFixedPoint().getValue(), T, Loc,
- Val.getFixedPoint().getScale());
-
- case APValue::ComplexInt: {
- QualType ElemT = T->castAs<ComplexType>()->getElementType();
- return MakeInitList({BuildExpressionFromIntegralTemplateArgumentValue(
- S, ElemT, Val.getComplexIntReal(), Loc),
- BuildExpressionFromIntegralTemplateArgumentValue(
- S, ElemT, Val.getComplexIntImag(), Loc)});
- }
-
- case APValue::ComplexFloat: {
- QualType ElemT = T->castAs<ComplexType>()->getElementType();
- return MakeInitList(
- {FloatingLiteral::Create(S.Context, Val.getComplexFloatReal(), true,
- ElemT, Loc),
- FloatingLiteral::Create(S.Context, Val.getComplexFloatImag(), true,
- ElemT, Loc)});
- }
-
- case APValue::Vector: {
- QualType ElemT = T->castAs<VectorType>()->getElementType();
- llvm::SmallVector<Expr *, 8> Elts;
- for (unsigned I = 0, N = Val.getVectorLength(); I != N; ++I)
- Elts.push_back(BuildExpressionFromNonTypeTemplateArgumentValue(
- S, ElemT, Val.getVectorElt(I), Loc));
- return MakeInitList(Elts);
- }
-
- case APValue::None:
- case APValue::Indeterminate:
- llvm_unreachable("Unexpected APValue kind.");
- case APValue::LValue:
- case APValue::MemberPointer:
- // There isn't necessarily a valid equivalent source-level syntax for
- // these; in particular, a naive lowering might violate access control.
- // So for now we lower to a ConstantExpr holding the value, wrapped around
- // an OpaqueValueExpr.
- // FIXME: We should have a better representation for this.
- ExprValueKind VK = VK_PRValue;
- if (T->isReferenceType()) {
- T = T->getPointeeType();
- VK = VK_LValue;
- }
- auto *OVE = new (S.Context) OpaqueValueExpr(Loc, T, VK);
- return ConstantExpr::Create(S.Context, OVE, Val);
- }
- llvm_unreachable("Unhandled APValue::ValueKind enum");
-}
-
-ExprResult
-Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
- SourceLocation Loc) {
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- case TemplateArgument::Type:
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- case TemplateArgument::Pack:
- llvm_unreachable("not a non-type template argument");
-
- case TemplateArgument::Expression:
- return Arg.getAsExpr();
-
- case TemplateArgument::NullPtr:
- case TemplateArgument::Declaration:
- return BuildExpressionFromDeclTemplateArgument(
- Arg, Arg.getNonTypeTemplateArgumentType(), Loc);
-
- case TemplateArgument::Integral:
- return BuildExpressionFromIntegralTemplateArgumentValue(
- *this, Arg.getIntegralType(), Arg.getAsIntegral(), Loc);
-
- case TemplateArgument::StructuralValue:
- return BuildExpressionFromNonTypeTemplateArgumentValue(
- *this, Arg.getStructuralValueType(), Arg.getAsStructuralValue(), Loc);
- }
- llvm_unreachable("Unhandled TemplateArgument::ArgKind enum");
-}
-
/// Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(
Sema &S, NamedDecl *New,
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e9e7ab5bb6698a0..015b0abaf0e5ee2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -268,16 +268,6 @@ checkDeducedTemplateArguments(ASTContext &Context,
// All other combinations are incompatible.
return DeducedTemplateArgument();
- case TemplateArgument::StructuralValue:
- // If we deduced a value and a dependent expression, keep the value.
- if (Y.getKind() == TemplateArgument::Expression ||
- (Y.getKind() == TemplateArgument::StructuralValue &&
- X.structurallyEquals(Y)))
- return X;
-
- // All other combinations are incompatible.
- return DeducedTemplateArgument();
-
case TemplateArgument::Template:
if (Y.getKind() == TemplateArgument::Template &&
Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate()))
@@ -2310,45 +2300,27 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
Info.SecondArg = A;
return Sema::TDK_NonDeducedMismatch;
- case TemplateArgument::StructuralValue:
- if (A.getKind() == TemplateArgument::StructuralValue &&
- A.structurallyEquals(P))
- return Sema::TDK_Success;
-
- Info.FirstArg = P;
- Info.SecondArg = A;
- return Sema::TDK_NonDeducedMismatch;
-
case TemplateArgument::Expression:
if (const NonTypeTemplateParmDecl *NTTP =
getDeducedParameterFromExpr(Info, P.getAsExpr())) {
- switch (A.getKind()) {
- case TemplateArgument::Integral:
- case TemplateArgument::Expression:
- case TemplateArgument::StructuralValue:
+ if (A.getKind() == TemplateArgument::Integral)
return DeduceNonTypeTemplateArgument(
- S, TemplateParams, NTTP, DeducedTemplateArgument(A),
- A.getNonTypeTemplateArgumentType(), Info, Deduced);
-
- case TemplateArgument::NullPtr:
+ S, TemplateParams, NTTP, A.getAsIntegral(), A.getIntegralType(),
+ /*ArrayBound=*/false, Info, Deduced);
+ if (A.getKind() == TemplateArgument::NullPtr)
return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP,
A.getNullPtrType(), Info, Deduced);
-
- case TemplateArgument::Declaration:
+ if (A.getKind() == TemplateArgument::Expression)
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ A.getAsExpr(), Info, Deduced);
+ if (A.getKind() == TemplateArgument::Declaration)
return DeduceNonTypeTemplateArgument(
S, TemplateParams, NTTP, A.getAsDecl(), A.getParamTypeForDecl(),
Info, Deduced);
- case TemplateArgument::Null:
- case TemplateArgument::Type:
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- case TemplateArgument::Pack:
- Info.FirstArg = P;
- Info.SecondArg = A;
- return Sema::TDK_NonDeducedMismatch;
- }
- llvm_unreachable("Unknown template argument kind");
+ Info.FirstArg = P;
+ Info.SecondArg = A;
+ return Sema::TDK_NonDeducedMismatch;
}
// Can't deduce anything, but that's okay.
@@ -2533,9 +2505,6 @@ static bool isSameTemplateArg(ASTContext &Context,
case TemplateArgument::Integral:
return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral());
- case TemplateArgument::StructuralValue:
- return X.structurallyEquals(Y);
-
case TemplateArgument::Expression: {
llvm::FoldingSetNodeID XID, YID;
X.getAsExpr()->Profile(XID, Context, true);
@@ -2616,9 +2585,9 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
E);
}
- case TemplateArgument::Integral:
- case TemplateArgument::StructuralValue: {
- Expr *E = BuildExpressionFromNonTypeTemplateArgument(Arg, Loc).get();
+ case TemplateArgument::Integral: {
+ Expr *E =
+ BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
@@ -6480,8 +6449,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
+ break;
+
case TemplateArgument::NullPtr:
- case TemplateArgument::StructuralValue:
+ MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced,
+ Depth, Used);
break;
case TemplateArgument::Type:
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e12186d7d82f8d0..fc80515b45e35b4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1975,8 +1975,9 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
}
} else if (arg.getKind() == TemplateArgument::Declaration ||
arg.getKind() == TemplateArgument::NullPtr) {
+ ValueDecl *VD;
if (arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = arg.getAsDecl();
+ VD = arg.getAsDecl();
// Find the instantiation of the template argument. This is
// required for nested templates.
@@ -1984,20 +1985,21 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
if (!VD)
return ExprError();
+ } else {
+ // Propagate NULL template argument.
+ VD = nullptr;
}
- QualType paramType = arg.getNonTypeTemplateArgumentType();
+ QualType paramType = VD ? arg.getParamTypeForDecl() : arg.getNullPtrType();
assert(!paramType.isNull() && "type substitution failed for param type");
assert(!paramType->isDependentType() && "param type still dependent");
result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
refParam = paramType->isReferenceType();
} else {
- QualType paramType = arg.getNonTypeTemplateArgumentType();
- result = SemaRef.BuildExpressionFromNonTypeTemplateArgument(arg, loc);
- refParam = paramType->isReferenceType();
+ result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
assert(result.isInvalid() ||
SemaRef.Context.hasSameType(result.get()->getType(),
- paramType.getNonReferenceType()));
+ arg.getIntegralType()));
}
if (result.isInvalid())
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 4a7872b2cc73c59..0f4e9e7f94c81e9 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -1112,7 +1112,6 @@ TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern(
case TemplateArgument::NullPtr:
case TemplateArgument::Template:
case TemplateArgument::Integral:
- case TemplateArgument::StructuralValue:
case TemplateArgument::Pack:
case TemplateArgument::Null:
return TemplateArgumentLoc();
@@ -1163,7 +1162,6 @@ std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
case TemplateArgument::NullPtr:
case TemplateArgument::TemplateExpansion:
case TemplateArgument::Integral:
- case TemplateArgument::StructuralValue:
case TemplateArgument::Pack:
case TemplateArgument::Null:
return std::nullopt;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e55e752b9cc354c..c217b082a3704da 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3908,7 +3908,6 @@ class TreeTransform {
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
- case TemplateArgument::StructuralValue:
case TemplateArgument::Pack:
case TemplateArgument::TemplateExpansion:
case TemplateArgument::NullPtr:
@@ -4578,8 +4577,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Integral:
case TemplateArgument::NullPtr:
- case TemplateArgument::Declaration:
- case TemplateArgument::StructuralValue: {
+ case TemplateArgument::Declaration: {
// Transform a resolved template argument straight to a resolved template
// argument. We get here when substituting into an already-substituted
// template type argument during concept satisfaction checking.
@@ -4606,15 +4604,9 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
else if (Arg.getKind() == TemplateArgument::NullPtr)
Output = TemplateArgumentLoc(TemplateArgument(NewT, /*IsNullPtr=*/true),
TemplateArgumentLocInfo());
- else if (Arg.getKind() == TemplateArgument::Declaration)
+ else
Output = TemplateArgumentLoc(TemplateArgument(NewD, NewT),
TemplateArgumentLocInfo());
- else if (Arg.getKind() == TemplateArgument::StructuralValue)
- Output = TemplateArgumentLoc(
- TemplateArgument(getSema().Context, NewT, Arg.getAsStructuralValue()),
- TemplateArgumentLocInfo());
- else
- llvm_unreachable("unexpected template argument kind");
return false;
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index fecd94e875f671a..ec4de0c25d3eb69 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7460,7 +7460,6 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) {
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::NullPtr:
- case TemplateArgument::StructuralValue:
case TemplateArgument::Pack:
// FIXME: Is this right?
return TemplateArgumentLocInfo();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 03bddfe0f5047db..a3fa99c3d7e49f7 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5609,7 +5609,6 @@ void ASTRecordWriter::AddTemplateArgumentLocInfo(
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::NullPtr:
- case TemplateArgument::StructuralValue:
case TemplateArgument::Pack:
// FIXME: Is this right?
break;
diff --git a/clang/test/CXX/drs/dr18xx.cpp b/clang/test/CXX/drs/dr18xx.cpp
index 37ea450137ac5e7..f2c056e13ecad78 100644
--- a/clang/test/CXX/drs/dr18xx.cpp
+++ b/clang/test/CXX/drs/dr18xx.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx11-17,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14,cxx17 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
@@ -25,7 +25,7 @@ template <int &> struct S {}; // #dr1801-S
S<i> V; // #dr1801-S-i
// cxx98-14-error at -1 {{non-type template argument does not refer to any declaration}}
// cxx98-14-note@#dr1801-S {{template parameter is declared here}}
-// cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}}
+// since-cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}}
}
namespace dr1802 { // dr1802: 3.1
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
index 7fce6155169245e..a17720c9267ccf4 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
@@ -200,9 +200,7 @@ namespace bad_args {
// cxx17-note at -3 {{reinterpret_cast}}
X0<__builtin_constant_p(0) ? (int*)1 : (int*)1> x0d;
// precxx17-error at -1 {{non-type template argument '(int *)1' is invalid}}
-#if __cplusplus == 201703L
- // cxx17-error at -3 {{non-type template argument refers to subobject '(int *)1'}}
-#endif
+ // cxx17-error at -2 {{non-type template argument refers to subobject '(int *)1'}}
}
#endif // CPP11ONLY
diff --git a/clang/test/CodeGenCXX/mangle-ms-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-templates.cpp
index ec4250edf314f7b..cefe1e0cb5a5505 100644
--- a/clang/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -2,21 +2,6 @@
// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
-// RUN: %clang_cc1 -std=c++20 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix CXX20-X64 %s
-
-// Check that array-to-pointer decay is mangled as the underlying declaration.
-extern const char arr[4] = "foo";
-template<const char*> struct Decay1 {};
-// CHECK: "?decay1@@3U?$Decay1@$1?arr@@3QBDB@@A"
-Decay1<arr> decay1;
-#if __cplusplus >= 201702L
-// Note that this mangling approach can lead to collisions.
-template<const void*> struct Decay2 {};
-// CXX20-X64: "?decay2a@@3U?$Decay2@$1?arr@@3QBDB@@A"
-Decay2<(const void*)arr> decay2a;
-// CXX20-X64: "?decay2b@@3U?$Decay2@$1?arr@@3QBDB@@A"
-Decay2<(const void*)&arr> decay2b;
-#endif
template<typename T>
class Class {
@@ -342,36 +327,3 @@ void fun_uint128(UInt128<(unsigned __int128)-1>) {}
// X64: define {{.*}} @"?fun_uint128@@YAXU?$UInt128@$0DPPPPPPPPPPPPPPPAAAAAAAAAAAAAAAB@@@@Z"(
void fun_uint128(UInt128<(unsigned __int128)9223372036854775807 * (unsigned __int128)9223372036854775807>) {}
#endif
-
-#if __cplusplus >= 202002L
-
-template<float> struct Float {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$Float@$ADPIAAAAA@@@@Z"(
-void f(Float<1.0f>) {}
-template<auto> struct Auto {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$Auto@$MMADPIAAAAA@@@@Z"(
-void f(Auto<1.0f>) {}
-
-struct S2 {
- int arr[2][3];
- int i;
- void fn();
-} s2;
-
-template<int&> struct TplSubobjectRef {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplSubobjectRef@$CC61?s2@@3US2@@Aarr@@00 at 01@@@@Z"(
-void f(TplSubobjectRef<s2.arr[1][2]>) {}
-template<int*> struct TplSubobjectPtr {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplSubobjectPtr@$CC61?s2@@3US2@@Aarr@@00 at 01@@@@Z"(
-void f(TplSubobjectPtr<&s2.arr[1][2]>) {}
-
-struct Derived : S2 {};
-
-template <int Derived::*> struct TplMemberPtr {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplMemberPtr@$0BI@@@@Z"(
-void f(TplMemberPtr<(int Derived::*)&S2::i>) {}
-template <void (Derived::*)()> struct TplMemberFnPtr {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$TplMemberFnPtr@$1?fn at S2@@QEAAXXZ@@@Z"(
-void f(TplMemberFnPtr<(void (Derived::*)())&S2::fn>) {}
-
-#endif
diff --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp
index a4cb22739ac2a9b..8415bacbb9fc6d4 100644
--- a/clang/test/CodeGenCXX/mangle-template.cpp
+++ b/clang/test/CodeGenCXX/mangle-template.cpp
@@ -225,16 +225,6 @@ namespace test16 {
namespace cxx20 {
template<auto> struct A {};
template<typename T, T V> struct B {};
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AILf3f800000EEE(
- void f(A<1.0f>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AILd3ff0000000000000EEE(
- void f(A<1.0>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AILe3fff8000000000000000EEE(
- void f(A<1.0l>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXtlCiLi0ELi1EEEEE(
- void f(A<1i>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXtlCdLd0000000000000000ELd3ff0000000000000EEEEE(
- void f(A<1.0i>) {}
int x;
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1xEEEEE(
@@ -254,24 +244,7 @@ namespace cxx20 {
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadL_ZNS_1xEEEEE(
void f(B<const void*, (const void*)&x>) {}
- struct Q { int x; } q;
-
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadsoiL_ZNS_1qEEEEEE(
- void f(A<&q.x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPiXadsoiL_ZNS_1qEEEEEE(
- void f(B<int*, &q.x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadsoKiL_ZNS_1qEEEEEE(
- void f(A<(const int*)&q.x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKiXadsoS1_L_ZNS_1qEEEEEE
- void f(B<const int*, (const int*)&q.x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPvadsoiL_ZNS_1qEEEEEE(
- void f(A<(void*)&q.x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPvXadsoiL_ZNS_1qEEEEEE(
- void f(B<void*, (void*)&q.x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPKvadsoiL_ZNS_1qEEEEEE(
- void f(A<(const void*)&q.x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadsoiL_ZNS_1qEEEEEE(
- void f(B<const void*, (const void*)&q.x>) {}
+ struct Q { int x; };
// CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1Q1xEEEEE(
void f(A<&Q::x>) {}
@@ -281,17 +254,6 @@ namespace cxx20 {
void f(A<(const int Q::*)&Q::x>) {}
// CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1QEKiXadL_ZNS1_1xEEEEE(
void f(B<const int Q::*, (const int Q::*)&Q::x>) {}
-
- struct R : Q {};
-
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXmcMNS_1REiadL_ZNS_1Q1xEEEEEE(
- void f(A<(int R::*)&Q::x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1REiXmcS2_adL_ZNS_1Q1xEEEEEE(
- void f(B<int R::*, (int R::*)&Q::x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXmcMNS_1REKiadL_ZNS_1Q1xEEEEEE(
- void f(A<(const int R::*)&Q::x>) {}
- // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1REKiXmcS3_adL_ZNS_1Q1xEEEEEE(
- void f(B<const int R::*, (const int R::*)&Q::x>) {}
}
#endif
diff --git a/clang/test/CodeGenCXX/template-arguments.cpp b/clang/test/CodeGenCXX/template-arguments.cpp
deleted file mode 100644
index 14a454937122aa6..000000000000000
--- a/clang/test/CodeGenCXX/template-arguments.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR= | FileCheck %s
-// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR=constexpr | FileCheck %s --check-prefix=CONST
-
-template<typename T> CONSTEXPR T id(T v) { return v; }
-template<auto V> auto value = id(V);
-
-// CHECK: call {{.*}} @_Z2idIiET_S0_(i32 noundef 1)
-// CONST: @_Z5valueILi1EE = weak_odr {{.*}} i32 1,
-template int value<1>;
-
-// CHECK: call {{.*}} @_Z2idIyET_S0_(i64 noundef -1)
-// CONST: @_Z5valueILy18446744073709551615EE = weak_odr {{.*}} i64 -1,
-template unsigned long long value<-1ULL>;
-
-// CHECK: call {{.*}} @_Z2idIfET_S0_(float noundef 1.000000e+00)
-// CONST: @_Z5valueILf3f800000EE = weak_odr {{.*}} float 1.000000e+00,
-template float value<1.0f>;
-// CHECK: call {{.*}} @_Z2idIdET_S0_(double noundef 1.000000e+00)
-// CONST: @_Z5valueILd3ff0000000000000EE = weak_odr {{.*}} double 1.000000e+00,
-template double value<1.0>;
-
-enum E{ E1, E2};
-
-// CHECK: call {{.*}} @_Z2idI1EET_S1_(i32 noundef 1)
-// CONST: @_Z5valueIL1E1EE = weak_odr {{.*}} i32 1,
-template E value<E2>;
-
-int n;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @n)
-// CONST: @_Z5valueIXadL_Z1nEEE = weak_odr {{.*}} ptr @n,
-template int *value<&n>;
-
-struct A { int a[3]; } a;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @a)
-// CONST: @_Z5valueIXadsoiL_Z1aEEEE = weak_odr {{.*}} ptr @a,
-template int *value<&a.a[0]>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef getelementptr (i8, ptr @a, i64 4))
-// CONST: @_Z5valueIXadsoiL_Z1aE4EEE = weak_odr {{.*}} ptr getelementptr (i8, ptr @a, i64 4),
-template int *value<&a.a[1]>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef getelementptr (i8, ptr @a, i64 8))
-// CONST: @_Z5valueIXadsoiL_Z1aE8EEE = weak_odr {{.*}} ptr getelementptr (i8, ptr @a, i64 8),
-template int *value<&a.a[2]>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef getelementptr (i8, ptr @a, i64 12))
-// CONST: @_Z5valueIXadsoiL_Z1aE12pEEE = weak_odr {{.*}} ptr getelementptr (i8, ptr @a, i64 12),
-template int *value<&a.a[3]>;
-
-union U {
- int x, y;
- union {
- int x, y;
- } internal;
-} u;
-
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @u)
-// CONST: @_Z5valueIXadsoiL_Z1uE_EEE = weak_odr {{.*}} ptr @u,
-template int *value<&u.x>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @u)
-// CONST: @_Z5valueIXadsoiL_Z1uE_0EEE = weak_odr {{.*}} ptr @u,
-template int *value<&u.y>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(ptr noundef @u)
-// CONST: @_Z5valueIXadsoiL_Z1uE_1_0EEE = weak_odr {{.*}} ptr @u,
-template int *value<&u.internal.y>;
-
-struct B { int x, y; };
-// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 0)
-// CONST: @_Z5valueIXadL_ZN1B1xEEEE = weak_odr {{.*}} i64 0,
-template int B::*value<&B::x>;
-// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 4)
-// CONST: @_Z5valueIXadL_ZN1B1yEEEE = weak_odr {{.*}} i64 4,
-template int B::*value<&B::y>;
-
-struct C : A, B { int z; };
-// CHECK: call {{.*}} @_Z2idIM1CiET_S2_(i64 12)
-// CONST: @_Z5valueIXmcM1CiadL_ZN1B1xEE12EEE = weak_odr {{.*}} i64 12,
-template int C::*value<(int C::*)&B::x>;
-// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 8)
-// CONST: @_Z5valueIXmcM1BiadL_ZN1C1zEEn12EEE = weak_odr {{.*}} i64 8,
-template int B::*value<(int B::*)&C::z>;
-
-// CHECK: store i32 1,
-// CHECK: store i32 2,
-// CHECK: load i64,
-// CHECK: call {{.*}} @_Z2idICiET_S1_(i64 noundef %
-// CONST: @_Z5valueIXtlCiLi1ELi2EEEE = weak_odr {{.*}} { i32, i32 } { i32 1, i32 2 },
-template _Complex int value<1 + 2j>;
-
-// CHECK: store float 1.000000e+00,
-// CHECK: store float 2.000000e+00,
-// CHECK: load <2 x float>,
-// CHECK: call {{.*}} @_Z2idICfET_S1_(<2 x float> noundef %
-// CONST: @_Z5valueIXtlCfLf3f800000ELf40000000EEEE = weak_odr {{.*}} { float, float } { float 1.000000e+00, float 2.000000e+00 },
-template _Complex float value<1.0f + 2.0fj>;
-
-using V3i __attribute__((ext_vector_type(3))) = int;
-// CHECK: call {{.*}} @_Z2idIDv3_iET_S1_(<3 x i32> noundef <i32 1, i32 2, i32 3>)
-// CONST: @_Z5valueIXtlDv3_iLi1ELi2ELi3EEEE = weak_odr {{.*}} <3 x i32> <i32 1, i32 2, i32 3>
-template V3i value<V3i{1, 2, 3}>;
-
-using V3f [[gnu::vector_size(12)]] = float;
-// CHECK: call {{.*}} @_Z2idIDv3_fET_S1_(<3 x float> noundef <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>)
-// CONST: @_Z5valueIXtlDv3_fLf3f800000ELf40000000ELf40400000EEEE = weak_odr {{.*}} <3 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>
-template V3f value<V3f{1, 2, 3}>;
-
-
-template <int& i>
-void setByRef() {
- i = 1;
-}
-
-void callSetByRefWithSubobject() {
- // CHECK: store i32 1, ptr getelementptr (i8, ptr @a, i64 4)
- setByRef<a.a[1]>();
-}
diff --git a/clang/test/Index/USR/structural-value-tpl-arg.cpp b/clang/test/Index/USR/structural-value-tpl-arg.cpp
deleted file mode 100644
index 8130012451691cf..000000000000000
--- a/clang/test/Index/USR/structural-value-tpl-arg.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: c-index-test -test-load-source-usrs local -std=c++20 -- %s | FileCheck %s
-
-// Check USRs of template specializations with structural NTTP values.
-
-template <auto> struct Tpl{};
-
-struct {
- int n;
-} s;
-
-void fn1(Tpl<1.5>);
-// CHECK: fn1#$@S at Tpl>#Sd[[#HASH:]]#
-void fn2(Tpl<1.7>);
-// CHECK-NOT: [[#HASH]]
-void fn1(Tpl<1.5>) {}
-// CHECK: fn1#$@S at Tpl>#Sd[[#HASH]]#
-
-void fn(Tpl<&s.n>);
-// CHECK: #S*I[[#HASH:]]#
-void fn(Tpl<(void*)&s.n>);
-// CHECK: #S*v[[#HASH]]#
-void fn(Tpl<&s.n>) {}
-// CHECK: #S*I[[#HASH]]#
diff --git a/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp
index fa8b2c81ab46e1b..220ef767df849aa 100644
--- a/clang/test/Modules/odr_hash.cpp
+++ b/clang/test/Modules/odr_hash.cpp
@@ -13,8 +13,8 @@
// RUN: cat %s >> %t/Inputs/second.h
// Test that each header can compile
-// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++20 %t/Inputs/first.h
-// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++20 %t/Inputs/second.h
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/first.h
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/second.h
// Build module map file
// RUN: echo "module FirstModule {" >> %t/Inputs/module.modulemap
@@ -25,7 +25,7 @@
// RUN: echo "}" >> %t/Inputs/module.modulemap
// Run test
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++20 \
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++1z \
// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
// RUN: -I%t/Inputs -verify %s
@@ -2093,193 +2093,6 @@ struct S21 {
S21 s21;
#endif
-#if defined(FIRST)
-struct S22 {
- template <double> void f(){};
- template <> void f<1.5>(){};
-};
-#elif defined(SECOND)
-struct S22 {
- template <double> void f(){};
- template <> void f<1.7>(){};
-};
-#else
-S22 s22;
-// expected-error at second.h:* {{'TemplateArgument::S22' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 1.700000e+00 for 1st template argument}}
-// expected-note at first.h:* {{but in 'FirstModule' found method 'f' with 1.500000e+00 for 1st template argument}}
-#endif
-
-#if defined(FIRST)
-struct S23 {
- template <double> void f(){};
- template <> void f<2.7>(){};
-};
-#elif defined(SECOND)
-struct S23 {
- template <double> void f(){};
- template <> void f<2.7>(){};
-};
-#else
-S23 s23;
-#endif
-
-#if defined(FIRST) || defined(SECOND)
-struct Composite {
- int n1[4];
- int n2[4];
-};
-extern Composite composite;
-#endif
-
-#if defined(FIRST)
-struct S24 {
- template <int&> void f(){};
- template <> void f<composite.n1[1]>(){};
-};
-#elif defined(SECOND)
-struct S24 {
- template <int&> void f(){};
- template <> void f<composite.n1[2]>(){};
-};
-#else
-S24 s24;
-// expected-error at second.h:* {{'TemplateArgument::S24' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with composite.n1[2] for 1st template argument}}
-// expected-note at first.h:* {{but in 'FirstModule' found method 'f' with composite.n1[1] for 1st template argument}}
-#endif
-
-#if defined(FIRST) || defined(SECOND)
-struct S25 {
- template <int&> void f();
- template <> void f<composite.n1[2]>();
-};
-#else
-S25 s25;
-#endif
-
-#if defined(FIRST)
-struct S26 {
- template <int*> void f(){};
- template <> void f<&composite.n1[4]>(){}; // Past-the-end pointer.
-};
-#elif defined(SECOND)
-struct S26 {
- template <int*> void f(){};
- template <> void f<&composite.n2[0]>(){};
-};
-#else
-S26 s26;
-// expected-error at second.h:* {{'TemplateArgument::S26' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &composite.n2[0] for 1st template argument}}
-// expected-note at first.h:* {{but in 'FirstModule' found method 'f' with &composite.n1[4] for 1st template argument}}
-#endif
-
-#if defined(FIRST) || defined(SECOND)
-union Union {
- int i1;
- int i2;
-};
-extern Union u;
-#endif
-
-#if defined(FIRST)
-struct S27 {
- template <int&> void f(){};
- template <> void f<u.i1>(){};
-};
-#elif defined(SECOND)
-struct S27 {
- template <int&> void f(){};
- template <> void f<u.i2>(){};
-};
-#else
-S27 s27;
-// expected-error at second.h:* {{'TemplateArgument::S27' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with u.i2 for 1st template argument}}
-// expected-note at first.h:* {{but in 'FirstModule' found method 'f' with u.i1 for 1st template argument}}
-#endif
-
-#if defined(FIRST) || defined(SECOND)
-struct S28 {
- template <int&> void f(){};
- template <> void f<u.i1>(){};
-};
-#else
-S28 s28;
-#endif
-
-#if defined(FIRST) || defined(SECOND)
-struct A {
- int a;
-};
-struct B : A {};
-struct C : A {};
-struct D : B, C {};
-#endif
-
-#if defined(FIRST)
-struct S29 {
- template <int D::*> void f(){};
- template <> void f<(int D::*)(int B::*)&A::a>(){};
-};
-#elif defined(SECOND)
-struct S29 {
- template <int D::*> void f(){};
- template <> void f<(int D::*)(int C::*)&A::a>(){};
-};
-#else
-S29 s29;
-// expected-error at second.h:* {{'TemplateArgument::S29' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &A::a for 1st template argument}}
-// expected-note at first.h:* {{but in 'FirstModule' found method 'f' with &A::a for 1st template argument}}
-#endif
-
-#if defined(FIRST) || defined(SECOND)
-struct S30 {
- template <int D::*> void f(){};
- template <> void f<(int D::*)(int B::*)&A::a>(){};
-};
-#else
-S30 s30;
-#endif
-
-#if defined(FIRST)
-struct S31 {
- template <auto*> void f(){};
- template <> void f<&composite.n1[2]>(){};
-};
-#elif defined(SECOND)
-struct S31 {
- template <auto*> void f(){};
- template <> void f<(void*)&composite.n1[2]>(){};
-};
-#else
-S31 s31;
-// expected-error at second.h:* {{'TemplateArgument::S31' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &composite.n1[2] for 1st template argument}}
-// expected-note at first.h:* {{but in 'FirstModule' found method 'f' with &composite.n1[2] for 1st template argument}}
-#endif
-
-#if defined(FIRST)
-struct S32 {
- template <int*> void f(){};
- template <> void f<__builtin_constant_p(0) ? (int*)1 : (int*)1>(){};
-};
-#elif defined(SECOND)
-struct S32 {
- template <int*> void f(){};
- template <> void f<__builtin_constant_p(0) ? (int*)2 : (int*)2>(){};
-};
-#else
-S32 s32;
-// expected-error at second.h:* {{'TemplateArgument::S32' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with (int *)2 for 1st template argument}}
-// expected-note at first.h:* {{but in 'FirstModule' found method 'f' with (int *)1 for 1st template argument}}
-#endif
-
-#if defined(FIRST) || defined(SECOND)
-struct S33 {
- template <int*> void f(){};
- template <> void f<__builtin_constant_p(0) ? (int*)1 : (int*)1>(){};
-};
-#else
-S33 s33;
-#endif
-
#define DECLS \
OneClass<int> a; \
OneInt<1> b; \
diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp
index c81d52d864f2d27..7b671c52b5b9c02 100644
--- a/clang/test/SemaCXX/warn-bool-conversion.cpp
+++ b/clang/test/SemaCXX/warn-bool-conversion.cpp
@@ -186,7 +186,6 @@ namespace macros {
}
}
-#if __cplusplus < 201703L
namespace Template {
// FIXME: These cases should not warn.
template<int *p> void f() { if (p) {} } // expected-warning 2{{will always evaluate to 'true'}} expected-cxx11-warning {{implicit conversion of nullptr}}
@@ -206,4 +205,3 @@ namespace Template {
#endif
template void h<d>();
}
-#endif // __cplusplus < 201703L
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index ae06055bf52651d..b54b5a8007408db 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
@@ -2,7 +2,7 @@
template<typename T, T val> struct A {};
-template<typename T, typename U> constexpr bool is_same = false;
+template<typename T, typename U> constexpr bool is_same = false; // expected-note +{{here}}
template<typename T> constexpr bool is_same<T, T> = true;
namespace String {
@@ -84,32 +84,34 @@ namespace PtrMem {
constexpr int B::*b = &B::b;
constexpr int C::*cb = b;
constexpr int D::*db = b;
- constexpr int E::*ecb = cb;
- constexpr int E::*edb = db;
+ constexpr int E::*ecb = cb; // expected-note +{{here}}
+ constexpr int E::*edb = db; // expected-note +{{here}}
constexpr int E::*e = &E::e;
constexpr int D::*de = (int D::*)e;
constexpr int C::*ce = (int C::*)e;
- constexpr int B::*bde = (int B::*)de;
- constexpr int B::*bce = (int B::*)ce;
+ constexpr int B::*bde = (int B::*)de; // expected-note +{{here}}
+ constexpr int B::*bce = (int B::*)ce; // expected-note +{{here}}
+ // FIXME: This should all be accepted, but we don't yet have a representation
+ // nor mangling for this form of template argument.
using Ab = A<int B::*, b>;
using Ab = A<int B::*, &B::b>;
- using Abce = A<int B::*, bce>;
- using Abde = A<int B::*, bde>;
- static_assert(!is_same<Ab, Abce>, "");
- static_assert(!is_same<Ab, Abde>, "");
- static_assert(!is_same<Abce, Abde>, "");
- static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, "");
+ using Abce = A<int B::*, bce>; // expected-error {{not supported}}
+ using Abde = A<int B::*, bde>; // expected-error {{not supported}}
+ static_assert(!is_same<Ab, Abce>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+ static_assert(!is_same<Ab, Abde>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+ static_assert(!is_same<Abce, Abde>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
+ static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
using Ae = A<int E::*, e>;
using Ae = A<int E::*, &E::e>;
- using Aecb = A<int E::*, ecb>;
- using Aedb = A<int E::*, edb>;
- static_assert(!is_same<Ae, Aecb>, "");
- static_assert(!is_same<Ae, Aedb>, "");
- static_assert(!is_same<Aecb, Aedb>, "");
- static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, "");
+ using Aecb = A<int E::*, ecb>; // expected-error {{not supported}}
+ using Aedb = A<int E::*, edb>; // expected-error {{not supported}}
+ static_assert(!is_same<Ae, Aecb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+ static_assert(!is_same<Ae, Aedb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+ static_assert(!is_same<Aecb, Aedb>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
+ static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
using An = A<int E::*, nullptr>;
using A0 = A<int E::*, (int E::*)0>;
@@ -203,9 +205,9 @@ namespace Auto {
struct Y : X {};
void type_affects_identity(B<&X::n>) {}
- void type_affects_identity(B<(int Y::*)&X::n>) {}
+ void type_affects_identity(B<(int Y::*)&X::n>) {} // FIXME: expected-error {{non-type template argument of pointer-to-member type}}
void type_affects_identity(B<(const int X::*)&X::n>) {}
- void type_affects_identity(B<(const int Y::*)&X::n>) {}
+ void type_affects_identity(B<(const int Y::*)&X::n>) {} // FIXME: expected-error {{non-type template argument of pointer-to-member type}}
// A case where we need to do auto-deduction, and check whether the
// resulting dependent types match during partial ordering. These
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
index b5b8cadc909ce00..e345a1f64b921a0 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
@@ -8,8 +8,8 @@ namespace std {
// floating-point arguments
template<float> struct Float {};
-using F1 = Float<1.0f>;
-using F1 = Float<2.0f / 2>;
+using F1 = Float<1.0f>; // FIXME expected-error {{non-type template argument of type}}
+using F1 = Float<2.0f / 2>; // FIXME expected-error {{non-type template argument of type}}
struct S { int n[3]; } s; // expected-note 1+{{here}}
union U { int a, b; } u;
@@ -17,28 +17,24 @@ int n; // expected-note 1+{{here}}
// pointers to subobjects
template<int *> struct IntPtr {};
-using IPn = IntPtr<&n + 1>;
-using IPn = IntPtr<&n + 1>;
+using IPn = IntPtr<&n + 1>; // FIXME expected-error {{refers to subobject}}
+using IPn = IntPtr<&n + 1>; // FIXME expected-error {{refers to subobject}}
-using IPn2 = IntPtr<&n + 2>; // expected-error {{not a constant expression}} expected-note {{cannot refer to element 2 of non-array object}}
+using IP2 = IntPtr<&s.n[2]>; // FIXME expected-error {{refers to subobject}}
+using IP2 = IntPtr<s.n + 2>; // FIXME expected-error {{refers to subobject}}
-using IP2 = IntPtr<&s.n[2]>;
-using IP2 = IntPtr<s.n + 2>;
-
-using IP3 = IntPtr<&s.n[3]>;
-using IP3 = IntPtr<s.n + 3>;
-
-using IP5 = IntPtr<&s.n[5]>; // expected-error {{not a constant expression}} expected-note {{cannot refer to element 5 of array of 3 elements}}
+using IP3 = IntPtr<&s.n[3]>; // FIXME expected-error {{refers to subobject}}
+using IP3 = IntPtr<s.n + 3>; // FIXME expected-error {{refers to subobject}}
template<int &> struct IntRef {};
-using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
-using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
+using IPn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
+using IPn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
-using IR2 = IntRef<s.n[2]>;
-using IR2 = IntRef<*(s.n + 2)>;
+using IP2 = IntRef<s.n[2]>; // FIXME expected-error {{refers to subobject}}
+using IP2 = IntRef<*(s.n + 2)>; // FIXME expected-error {{refers to subobject}}
-using IR3 = IntRef<s.n[3]>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
-using IR3 = IntRef<*(s.n + 3)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
+using IP3 = IntRef<s.n[3]>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
+using IP3 = IntRef<*(s.n + 3)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
// classes
template<S> struct Struct {};
@@ -52,12 +48,12 @@ using U1 = Union<U{.b = 1}>; // expected-error {{different types}}
// miscellaneous scalar types
template<_Complex int> struct ComplexInt {};
-using CI = ComplexInt<1 + 3i>;
-using CI = ComplexInt<3i + 1>;
+using CI = ComplexInt<1 + 3i>; // FIXME: expected-error {{non-type template argument of type}}
+using CI = ComplexInt<1 + 3i>; // FIXME: expected-error {{non-type template argument of type}}
template<_Complex float> struct ComplexFloat {};
-using CF = ComplexFloat<1.0f + 3.0fi>;
-using CF = ComplexFloat<3.0fi + 1.0f>;
+using CF = ComplexFloat<1.0f + 3.0fi>; // FIXME: expected-error {{non-type template argument of type}}
+using CF = ComplexFloat<1.0f + 3.0fi>; // FIXME: expected-error {{non-type template argument of type}}
namespace ClassNTTP {
struct A { // expected-note 2{{candidate}}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index b03ad6054b9acf1..00c0dff9cce4c4a 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1582,11 +1582,6 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
return false;
- case TemplateArgument::StructuralValue:
- if (Expr *E = TAL.getSourceStructuralValueExpression())
- return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
- return false;
-
case TemplateArgument::NullPtr:
if (Expr *E = TAL.getSourceNullPtrExpression())
return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index 978adac5521aaa0..fd03c48ba1a42aa 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -1466,9 +1466,6 @@ enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,
return CXTemplateArgumentKind_NullPtr;
case TemplateArgument::Integral:
return CXTemplateArgumentKind_Integral;
- case TemplateArgument::StructuralValue:
- // FIXME: Expose these values.
- return CXTemplateArgumentKind_Invalid;
case TemplateArgument::Template:
return CXTemplateArgumentKind_Template;
case TemplateArgument::TemplateExpansion:
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index a48f35eb5048378..197726f3aa3eee5 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -637,21 +637,13 @@ <h2 id="cxx20">C++20 implementation status</h2>
</tr>
<!-- Rapperswil papers -->
<tr>
- <td>Class types as non-type template parameters</td>
+ <td rowspan="2">Class types as non-type template parameters</td>
<td><a href="https://wg21.link/p0732r2">P0732R2</a></td>
- <td class="full" align="center">Clang 12</td>
- </tr>
- <tr> <!-- from Belfast -->
- <td>Generalized non-type template parameters of scalar type</td>
- <td><a href="https://wg21.link/p1907r1">P1907R1</a></td>
- <td class="partial" align="center">
- <details>
- <summary>Clang 18 (Partial)</summary>
- Reference type template arguments referring to instantiation-dependent objects and subobjects
- (i.e. declared inside a template but neither type- nor value-dependent) aren't fully supported.
- </details>
- </td>
+ <td rowspan="2" class="partial" align="center">Partial</td>
</tr>
+ <tr> <!-- from Belfast -->
+ <td><a href="https://wg21.link/p1907r1">P1907R1</a></td>
+ </tr>
<tr>
<td>Destroying operator delete</td>
<td><a href="https://wg21.link/p0722r3">P0722R3</a></td>
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 392d333c23a4470..ed1dec85d484061 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -875,7 +875,6 @@ enum TemplateArgumentKind {
eTemplateArgumentKindExpression,
eTemplateArgumentKindPack,
eTemplateArgumentKindNullPtr,
- eTemplateArgumentKindStructuralValue,
};
/// Type of match to be performed when looking for a formatter for a data type.
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 6f5ff105477be17..ba37afbb619fb7f 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -7168,9 +7168,6 @@ TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
case clang::TemplateArgument::Pack:
return eTemplateArgumentKindPack;
-
- case clang::TemplateArgument::StructuralValue:
- return eTemplateArgumentKindStructuralValue;
}
llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind");
}
More information about the cfe-commits
mailing list