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