@@ -7412,9 +7412,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
74127412 if (ArgResult.isInvalid ())
74137413 return ExprError ();
74147414
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 *> ());
74187418 // For a non-type template-parameter of pointer or reference type,
74197419 // the value of the constant expression shall not refer to
74207420 assert (ParamType->isPointerType () || ParamType->isReferenceType () ||
@@ -7423,33 +7423,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
74237423 // -- a string literal
74247424 // -- the result of a typeid expression, or
74257425 // -- a predefined __func__ variable
7426- APValue::LValueBase Base = Value.getLValueBase ();
7427- auto *VD = const_cast <ValueDecl *>(Base.dyn_cast <const ValueDecl *>());
74287426 if (Base &&
74297427 (!VD ||
74307428 isa<LifetimeExtendedTemporaryDecl, UnnamedGlobalConstantDecl>(VD))) {
74317429 Diag (Arg->getBeginLoc (), diag::err_template_arg_not_decl_ref)
74327430 << Arg->getSourceRange ();
74337431 return ExprError ();
74347432 }
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 () &&
74387436 Value.getLValuePath ()[0 ].getAsArrayIndex () == 0 &&
74397437 !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?" );
74487456 }
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?" );
74537457 }
74547458
74557459 if (Value.isAddrLabelDiff ())
0 commit comments