@@ -7417,9 +7417,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
74177417 if (ArgResult.isInvalid ())
74187418 return ExprError ();
74197419
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 *> ());
74237423 // For a non-type template-parameter of pointer or reference type,
74247424 // the value of the constant expression shall not refer to
74257425 assert (ParamType->isPointerType () || ParamType->isReferenceType () ||
@@ -7428,33 +7428,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
74287428 // -- a string literal
74297429 // -- the result of a typeid expression, or
74307430 // -- a predefined __func__ variable
7431- APValue::LValueBase Base = Value.getLValueBase ();
7432- auto *VD = const_cast <ValueDecl *>(Base.dyn_cast <const ValueDecl *>());
74337431 if (Base &&
74347432 (!VD ||
74357433 isa<LifetimeExtendedTemporaryDecl, UnnamedGlobalConstantDecl>(VD))) {
74367434 Diag (Arg->getBeginLoc (), diag::err_template_arg_not_decl_ref)
74377435 << Arg->getSourceRange ();
74387436 return ExprError ();
74397437 }
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 () &&
74437441 Value.getLValuePath ()[0 ].getAsArrayIndex () == 0 &&
74447442 !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?" );
74537461 }
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?" );
74587462 }
74597463
74607464 if (Value.isAddrLabelDiff ())
0 commit comments