Skip to content

Commit 9e08e51

Browse files
committed
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type.
1 parent 333d41e commit 9e08e51

36 files changed

+621
-188
lines changed

clang/include/clang/AST/PropertiesBase.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
7272

7373
def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
7474
def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
75+
def APValue : PropertyType { let PassByReference = 1; }
7576
def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
7677
def AttrKind : EnumPropertyType<"attr::Kind">;
7778
def AutoTypeKeyword : EnumPropertyType;
@@ -450,6 +451,17 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
450451
return TemplateArgument(ctx, value, type);
451452
}]>;
452453
}
454+
let Class = PropertyTypeCase<TemplateArgument, "UncommonValue"> in {
455+
def : Property<"value", APValue> {
456+
let Read = [{ node.getAsUncommonValue() }];
457+
}
458+
def : Property<"type", QualType> {
459+
let Read = [{ node.getUncommonValueType() }];
460+
}
461+
def : Creator<[{
462+
return TemplateArgument(ctx, type, value);
463+
}]>;
464+
}
453465
let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
454466
def : Property<"name", TemplateName> {
455467
let Read = [{ node.getAsTemplateOrTemplatePattern() }];

clang/include/clang/AST/RecursiveASTVisitor.h

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

772773
case TemplateArgument::Type:
@@ -800,6 +801,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
800801
case TemplateArgument::Declaration:
801802
case TemplateArgument::Integral:
802803
case TemplateArgument::NullPtr:
804+
case TemplateArgument::UncommonValue:
803805
return true;
804806

805807
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
@@ -4656,8 +4656,6 @@ def err_non_type_template_arg_subobject : Error<
46564656
"non-type template argument refers to subobject '%0'">;
46574657
def err_non_type_template_arg_addr_label_diff : Error<
46584658
"template argument / label address difference / what did you expect?">;
4659-
def err_non_type_template_arg_unsupported : Error<
4660-
"sorry, non-type template argument of type %0 is not yet supported">;
46614659
def err_template_arg_not_convertible : Error<
46624660
"non-type template argument of type %0 cannot be converted to a value "
46634661
"of type %1">;
@@ -4709,9 +4707,6 @@ def err_template_arg_not_object_or_func : Error<
47094707
"non-type template argument does not refer to an object or function">;
47104708
def err_template_arg_not_pointer_to_member_form : Error<
47114709
"non-type template argument is not a pointer to member constant">;
4712-
def err_template_arg_member_ptr_base_derived_not_supported : Error<
4713-
"sorry, non-type template argument of pointer-to-member type %1 that refers "
4714-
"to member %q0 of a different class is not supported yet">;
47154710
def ext_template_arg_extra_parens : ExtWarn<
47164711
"address non-type template argument cannot be surrounded by parentheses">;
47174712
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
@@ -7623,8 +7623,8 @@ class Sema final {
76237623
QualType ParamType,
76247624
SourceLocation Loc);
76257625
ExprResult
7626-
BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
7627-
SourceLocation Loc);
7626+
BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
7627+
SourceLocation Loc);
76287628

76297629
/// Enumeration describing how template parameter lists are compared
76307630
/// for equality.

clang/include/clang/Serialization/ASTRecordWriter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class ASTRecordWriter
166166

167167
/// Emit an APvalue.
168168
void AddAPValue(const APValue &Value);
169+
void writeAPValue(const APValue &Value) { AddAPValue(Value); }
169170

170171
/// Emit a reference to an identifier.
171172
void AddIdentifierRef(const IdentifierInfo *II) {

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;

0 commit comments

Comments
 (0)