Skip to content

Commit 4b57400

Browse files
committed
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type.
Previously committed as 9e08e51, and reverted because a dependency commit was reverted. This incorporates the following follow-on commits that were also reverted: 7e84aa1 by Simon Pilgrim ed13d8c by me 95c7b6c by Sam McCall 430d5d8 by Dave Zarzycki
1 parent 5a391d3 commit 4b57400

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+632
-191
lines changed

clang-tools-extra/clangd/DumpAST.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
143143
TEMPLATE_ARGUMENT_KIND(Declaration);
144144
TEMPLATE_ARGUMENT_KIND(Template);
145145
TEMPLATE_ARGUMENT_KIND(TemplateExpansion);
146+
TEMPLATE_ARGUMENT_KIND(UncommonValue);
146147
#undef TEMPLATE_ARGUMENT_KIND
147148
}
148149
llvm_unreachable("Unhandled ArgKind enum");

clang-tools-extra/clangd/FindTarget.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ class ExplicitReferenceCollector
10791079
case TemplateArgument::Pack:
10801080
case TemplateArgument::Type:
10811081
case TemplateArgument::Expression:
1082+
case TemplateArgument::UncommonValue:
10821083
break; // Handled by VisitType and VisitExpression.
10831084
};
10841085
return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A);

clang-tools-extra/clangd/index/remote/Client.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ class IndexClient : public clangd::SymbolIndex {
152152
});
153153
}
154154

155-
llvm::unique_function<bool(llvm::StringRef) const> indexedFiles() const {
155+
llvm::unique_function<bool(llvm::StringRef) const>
156+
indexedFiles() const override {
156157
// FIXME: For now we always return "false" regardless of whether the file
157158
// was indexed or not. A possible implementation could be based on
158159
// the idea that we do not want to send a request at every

clang/include/clang/AST/ASTContext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,8 +2818,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
28182818
/// for destruction.
28192819
template <typename T> void addDestruction(T *Ptr) const {
28202820
if (!std::is_trivially_destructible<T>::value) {
2821-
auto DestroyPtr = [](void *V) { static_cast<T *>(V)->~T(); };
2822-
AddDeallocation(DestroyPtr, Ptr);
2821+
auto DestroyPtr = [](void *V) { ((T*)V)->~T(); };
2822+
AddDeallocation(DestroyPtr, (void*)Ptr);
28232823
}
28242824
}
28252825

clang/include/clang/AST/PropertiesBase.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,17 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
758758
return TemplateArgument(ctx, value, type);
759759
}]>;
760760
}
761+
let Class = PropertyTypeCase<TemplateArgument, "UncommonValue"> in {
762+
def : Property<"value", APValue> {
763+
let Read = [{ node.getAsUncommonValue() }];
764+
}
765+
def : Property<"type", QualType> {
766+
let Read = [{ node.getUncommonValueType() }];
767+
}
768+
def : Creator<[{
769+
return TemplateArgument(ctx, type, value);
770+
}]>;
771+
}
761772
let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
762773
def : Property<"name", TemplateName> {
763774
let Read = [{ node.getAsTemplateOrTemplatePattern() }];

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
768768
case TemplateArgument::Declaration:
769769
case TemplateArgument::Integral:
770770
case TemplateArgument::NullPtr:
771+
case TemplateArgument::UncommonValue:
771772
return true;
772773

773774
case TemplateArgument::Type:
@@ -801,6 +802,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
801802
case TemplateArgument::Declaration:
802803
case TemplateArgument::Integral:
803804
case TemplateArgument::NullPtr:
805+
case TemplateArgument::UncommonValue:
804806
return true;
805807

806808
case TemplateArgument::Type: {

clang/include/clang/AST/TemplateArgumentVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Base {
3737
DISPATCH(Declaration);
3838
DISPATCH(NullPtr);
3939
DISPATCH(Integral);
40+
DISPATCH(UncommonValue);
4041
DISPATCH(Template);
4142
DISPATCH(TemplateExpansion);
4243
DISPATCH(Expression);
@@ -59,6 +60,7 @@ class Base {
5960
VISIT_METHOD(Declaration);
6061
VISIT_METHOD(NullPtr);
6162
VISIT_METHOD(Integral);
63+
VISIT_METHOD(UncommonValue);
6264
VISIT_METHOD(Template);
6365
VISIT_METHOD(TemplateExpansion);
6466
VISIT_METHOD(Expression);

clang/include/clang/AST/TemplateBase.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> {
5151

5252
namespace clang {
5353

54+
class APValue;
5455
class ASTContext;
5556
class DiagnosticBuilder;
5657
class Expr;
@@ -82,6 +83,12 @@ class TemplateArgument {
8283
/// that was provided for an integral non-type template parameter.
8384
Integral,
8485

86+
/// The template argument is a non-type template argument that can't be
87+
/// represented by the special-case Declaration, NullPtr, or Integral
88+
/// forms. These values are only ever produced by constant evaluation,
89+
/// so cannot be dependent.
90+
UncommonValue,
91+
8592
/// The template argument is a template name that was provided for a
8693
/// template template parameter.
8794
Template,
@@ -125,6 +132,11 @@ class TemplateArgument {
125132
};
126133
void *Type;
127134
};
135+
struct V {
136+
unsigned Kind;
137+
const APValue *Value;
138+
void *Type;
139+
};
128140
struct A {
129141
unsigned Kind;
130142
unsigned NumArgs;
@@ -142,6 +154,7 @@ class TemplateArgument {
142154
union {
143155
struct DA DeclArg;
144156
struct I Integer;
157+
struct V Value;
145158
struct A Args;
146159
struct TA TemplateArg;
147160
struct TV TypeOrValue;
@@ -157,9 +170,8 @@ class TemplateArgument {
157170
TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
158171
}
159172

160-
/// Construct a template argument that refers to a
161-
/// declaration, which is either an external declaration or a
162-
/// template declaration.
173+
/// Construct a template argument that refers to a (non-dependent)
174+
/// declaration.
163175
TemplateArgument(ValueDecl *D, QualType QT) {
164176
assert(D && "Expected decl");
165177
DeclArg.Kind = Declaration;
@@ -169,7 +181,11 @@ class TemplateArgument {
169181

170182
/// Construct an integral constant template argument. The memory to
171183
/// store the value is allocated with Ctx.
172-
TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
184+
TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value,
185+
QualType Type);
186+
187+
/// Construct a template argument from an arbitrary constant value.
188+
TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value);
173189

174190
/// Construct an integral constant template argument with the same
175191
/// value as Other but a different type.
@@ -340,6 +356,16 @@ class TemplateArgument {
340356
Integer.Type = T.getAsOpaquePtr();
341357
}
342358

359+
/// Get the value of an UncommonValue.
360+
const APValue &getAsUncommonValue() const {
361+
return *Value.Value;
362+
}
363+
364+
/// Get the type of an UncommonValue.
365+
QualType getUncommonValueType() const {
366+
return QualType::getFromOpaquePtr(Value.Type);
367+
}
368+
343369
/// If this is a non-type template argument, get its type. Otherwise,
344370
/// returns a null QualType.
345371
QualType getNonTypeTemplateArgumentType() const;
@@ -484,6 +510,7 @@ class TemplateArgumentLoc {
484510
assert(Argument.getKind() == TemplateArgument::NullPtr ||
485511
Argument.getKind() == TemplateArgument::Integral ||
486512
Argument.getKind() == TemplateArgument::Declaration ||
513+
Argument.getKind() == TemplateArgument::UncommonValue ||
487514
Argument.getKind() == TemplateArgument::Expression);
488515
}
489516

@@ -542,6 +569,11 @@ class TemplateArgumentLoc {
542569
return LocInfo.getAsExpr();
543570
}
544571

572+
Expr *getSourceUncommonValueExpression() const {
573+
assert(Argument.getKind() == TemplateArgument::UncommonValue);
574+
return LocInfo.getAsExpr();
575+
}
576+
545577
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
546578
if (Argument.getKind() != TemplateArgument::Template &&
547579
Argument.getKind() != TemplateArgument::TemplateExpansion)

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4695,8 +4695,6 @@ def err_non_type_template_arg_subobject : Error<
46954695
"non-type template argument refers to subobject '%0'">;
46964696
def err_non_type_template_arg_addr_label_diff : Error<
46974697
"template argument / label address difference / what did you expect?">;
4698-
def err_non_type_template_arg_unsupported : Error<
4699-
"sorry, non-type template argument of type %0 is not yet supported">;
47004698
def err_template_arg_not_convertible : Error<
47014699
"non-type template argument of type %0 cannot be converted to a value "
47024700
"of type %1">;
@@ -4748,9 +4746,6 @@ def err_template_arg_not_object_or_func : Error<
47484746
"non-type template argument does not refer to an object or function">;
47494747
def err_template_arg_not_pointer_to_member_form : Error<
47504748
"non-type template argument is not a pointer to member constant">;
4751-
def err_template_arg_member_ptr_base_derived_not_supported : Error<
4752-
"sorry, non-type template argument of pointer-to-member type %1 that refers "
4753-
"to member %q0 of a different class is not supported yet">;
47544749
def ext_template_arg_extra_parens : ExtWarn<
47554750
"address non-type template argument cannot be surrounded by parentheses">;
47564751
def warn_cxx98_compat_template_arg_extra_parens : Warning<

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7735,8 +7735,8 @@ class Sema final {
77357735
QualType ParamType,
77367736
SourceLocation Loc);
77377737
ExprResult
7738-
BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
7739-
SourceLocation Loc);
7738+
BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
7739+
SourceLocation Loc);
77407740

77417741
/// Enumeration describing how template parameter lists are compared
77427742
/// for equality.

clang/lib/AST/ASTContext.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5941,6 +5941,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
59415941
case TemplateArgument::Integral:
59425942
return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));
59435943

5944+
case TemplateArgument::UncommonValue:
5945+
return TemplateArgument(*this,
5946+
getCanonicalType(Arg.getUncommonValueType()),
5947+
Arg.getAsUncommonValue());
5948+
59445949
case TemplateArgument::Type:
59455950
return TemplateArgument(getCanonicalType(Arg.getAsType()));
59465951

clang/lib/AST/ASTImporter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,17 @@ ASTNodeImporter::import(const TemplateArgument &From) {
808808
return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true);
809809
}
810810

811+
case TemplateArgument::UncommonValue: {
812+
ExpectedType ToTypeOrErr = import(From.getUncommonValueType());
813+
if (!ToTypeOrErr)
814+
return ToTypeOrErr.takeError();
815+
Expected<APValue> ToValueOrErr = import(From.getAsUncommonValue());
816+
if (!ToValueOrErr)
817+
return ToValueOrErr.takeError();
818+
return TemplateArgument(Importer.getToContext(), *ToTypeOrErr,
819+
*ToValueOrErr);
820+
}
821+
811822
case TemplateArgument::Template: {
812823
Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
813824
if (!ToTemplateOrErr)

clang/lib/AST/ASTStructuralEquivalence.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
565565
return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
566566
Arg2.getAsExpr());
567567

568+
case TemplateArgument::UncommonValue:
569+
// FIXME: Do we need to customize the comparison?
570+
return Arg1.structurallyEquals(Arg2);
571+
568572
case TemplateArgument::Pack:
569573
if (Arg1.pack_size() != Arg2.pack_size())
570574
return false;

clang/lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
342342
LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
343343
continue;
344344

345+
case TemplateArgument::UncommonValue:
346+
LV.merge(getLVForValue(Arg.getAsUncommonValue(), computation));
347+
continue;
348+
345349
case TemplateArgument::Template:
346350
case TemplateArgument::TemplateExpansion:
347351
if (TemplateDecl *Template =

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4079,10 +4079,28 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
40794079
mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(), Arity);
40804080
break;
40814081

4082-
case Expr::SubstNonTypeTemplateParmExprClass:
4083-
mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
4084-
Arity);
4082+
case Expr::SubstNonTypeTemplateParmExprClass: {
4083+
// Mangle a substituted parameter the same way we mangle the template
4084+
// argument.
4085+
// As proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/111.
4086+
auto *SNTTPE = cast<SubstNonTypeTemplateParmExpr>(E);
4087+
if (auto *CE = dyn_cast<ConstantExpr>(SNTTPE->getReplacement())) {
4088+
// Pull out the constant value and mangle it as a template argument.
4089+
QualType ParamType = SNTTPE->getParameterType(Context.getASTContext());
4090+
if (CE->hasAPValueResult())
4091+
mangleValueInTemplateArg(ParamType, CE->getResultAsAPValue(), false,
4092+
/*NeedExactType=*/true);
4093+
else
4094+
mangleValueInTemplateArg(ParamType, CE->getAPValueResult(), false,
4095+
/*NeedExactType=*/true);
4096+
} else {
4097+
// The remaining cases all happen to be substituted with expressions that
4098+
// mangle the same as a corresponding template argument anyway.
4099+
mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
4100+
Arity);
4101+
}
40854102
break;
4103+
}
40864104

40874105
case Expr::UserDefinedLiteralClass:
40884106
// We follow g++'s approach of mangling a UDL as a call to the literal
@@ -5039,6 +5057,10 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
50395057
mangleNullPointer(A.getNullPtrType());
50405058
break;
50415059
}
5060+
case TemplateArgument::UncommonValue:
5061+
mangleValueInTemplateArg(A.getUncommonValueType(), A.getAsUncommonValue(),
5062+
/*TopLevel=*/true, NeedExactType);
5063+
break;
50425064
case TemplateArgument::Pack: {
50435065
// <template-arg> ::= J <template-arg>* E
50445066
Out << 'J';
@@ -5373,7 +5395,20 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
53735395
Out << "plcvPcad";
53745396
Kind = Offset;
53755397
} else {
5376-
if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) {
5398+
// Clang 11 and before mangled an array subject to array-to-pointer decay
5399+
// as if it were the declaration itself.
5400+
bool IsArrayToPointerDecayMangledAsDecl = false;
5401+
if (TopLevel && Ctx.getLangOpts().getClangABICompat() <=
5402+
LangOptions::ClangABI::Ver11) {
5403+
QualType BType = B.getType();
5404+
IsArrayToPointerDecayMangledAsDecl =
5405+
BType->isArrayType() && V.getLValuePath().size() == 1 &&
5406+
V.getLValuePath()[0].getAsArrayIndex() == 0 &&
5407+
Ctx.hasSimilarType(T, Ctx.getDecayedType(BType));
5408+
}
5409+
5410+
if ((!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) &&
5411+
!IsArrayToPointerDecayMangledAsDecl) {
53775412
NotPrimaryExpr();
53785413
// A final conversion to the template parameter's type is usually
53795414
// folded into the 'so' mangling, but we can't do that for 'void*'

clang/lib/AST/MicrosoftMangle.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,17 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
15751575
cast<NonTypeTemplateParmDecl>(Parm), T);
15761576
break;
15771577
}
1578+
case TemplateArgument::UncommonValue:
1579+
Out << "$";
1580+
if (cast<NonTypeTemplateParmDecl>(Parm)
1581+
->getType()
1582+
->getContainedDeducedType()) {
1583+
Out << "M";
1584+
mangleType(TA.getNonTypeTemplateArgumentType(), SourceRange(), QMM_Drop);
1585+
}
1586+
mangleTemplateArgValue(TA.getUncommonValueType(), TA.getAsUncommonValue(),
1587+
/*WithScalarType=*/false);
1588+
break;
15781589
case TemplateArgument::Expression:
15791590
mangleExpression(TA.getAsExpr(), cast<NonTypeTemplateParmDecl>(Parm));
15801591
break;

clang/lib/AST/ODRHash.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) {
169169
break;
170170
case TemplateArgument::NullPtr:
171171
case TemplateArgument::Integral:
172+
case TemplateArgument::UncommonValue:
173+
// FIXME: Include a representation of these arguments.
172174
break;
173175
case TemplateArgument::Template:
174176
case TemplateArgument::TemplateExpansion:

clang/lib/AST/StmtProfile.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2208,6 +2208,12 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
22082208
Arg.getAsIntegral().Profile(ID);
22092209
break;
22102210

2211+
case TemplateArgument::UncommonValue:
2212+
VisitType(Arg.getUncommonValueType());
2213+
// FIXME: Do we need to recursively decompose this ourselves?
2214+
Arg.getAsUncommonValue().Profile(ID);
2215+
break;
2216+
22112217
case TemplateArgument::Expression:
22122218
Visit(Arg.getAsExpr());
22132219
break;

0 commit comments

Comments
 (0)