@@ -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