@@ -7417,9 +7417,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
7417
7417
if (ArgResult.isInvalid())
7418
7418
return ExprError();
7419
7419
7420
- // Prior to C++20, enforce restrictions on possible template argument
7421
- // values.
7422
- if (! getLangOpts (). CPlusPlus20 && Value. isLValue ()) {
7420
+ if (Value.isLValue()) {
7421
+ APValue::LValueBase Base = Value.getLValueBase();
7422
+ auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *> ());
7423
7423
// For a non-type template-parameter of pointer or reference type,
7424
7424
// the value of the constant expression shall not refer to
7425
7425
assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
@@ -7428,33 +7428,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
7428
7428
// -- a string literal
7429
7429
// -- the result of a typeid expression, or
7430
7430
// -- a predefined __func__ variable
7431
- APValue::LValueBase Base = Value.getLValueBase ();
7432
- auto *VD = const_cast <ValueDecl *>(Base.dyn_cast <const ValueDecl *>());
7433
7431
if (Base &&
7434
7432
(!VD ||
7435
7433
isa<LifetimeExtendedTemporaryDecl, UnnamedGlobalConstantDecl>(VD))) {
7436
7434
Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
7437
7435
<< Arg->getSourceRange();
7438
7436
return ExprError();
7439
7437
}
7440
- // -- a subobject [until C++20]
7441
- if (Value.hasLValuePath () && Value.getLValuePath ().size () == 1 &&
7442
- VD && VD ->getType ()->isArrayType () &&
7438
+
7439
+ if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 && VD &&
7440
+ VD->getType()->isArrayType() &&
7443
7441
Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
7444
7442
!Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {
7445
- // Per defect report (no number yet):
7446
- // ... other than a pointer to the first element of a complete array
7447
- // object.
7448
- } else if (!Value.hasLValuePath () || Value.getLValuePath ().size () ||
7449
- Value.isLValueOnePastTheEnd ()) {
7450
- Diag (StartLoc, diag::err_non_type_template_arg_subobject)
7451
- << Value.getAsString (Context, ParamType);
7452
- return ExprError ();
7443
+ SugaredConverted = TemplateArgument(VD, ParamType);
7444
+ CanonicalConverted = TemplateArgument(
7445
+ cast<ValueDecl>(VD->getCanonicalDecl()), CanonParamType);
7446
+ return ArgResult.get();
7447
+ }
7448
+
7449
+ // -- a subobject [until C++20]
7450
+ if (!getLangOpts().CPlusPlus20) {
7451
+ if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
7452
+ Value.isLValueOnePastTheEnd()) {
7453
+ Diag(StartLoc, diag::err_non_type_template_arg_subobject)
7454
+ << Value.getAsString(Context, ParamType);
7455
+ return ExprError();
7456
+ }
7457
+ assert((VD || !ParamType->isReferenceType()) &&
7458
+ "null reference should not be a constant expression");
7459
+ assert((!VD || !ParamType->isNullPtrType()) &&
7460
+ "non-null value of type nullptr_t?");
7453
7461
}
7454
- assert ((VD || !ParamType->isReferenceType ()) &&
7455
- " null reference should not be a constant expression" );
7456
- assert ((!VD || !ParamType->isNullPtrType ()) &&
7457
- " non-null value of type nullptr_t?" );
7458
7462
}
7459
7463
7460
7464
if (Value.isAddrLabelDiff())
0 commit comments