@@ -4419,17 +4419,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4419
4419
return CompleteObject();
4420
4420
}
4421
4421
4422
- // if(AK == clang::AK_ReferenceInitialization)
4423
- // return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
4424
-
4425
4422
bool IsConstant = BaseType.isConstant(Info.Ctx);
4426
4423
bool ConstexprVar = false;
4427
4424
if (const auto *VD = dyn_cast_if_present<VarDecl>(
4428
4425
Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
4429
4426
ConstexprVar = VD->isConstexpr();
4430
4427
4431
4428
// Unless we're looking at a local variable or argument in a constexpr call,
4432
- // the variable we're reading must be const.
4429
+ // the variable we're reading must be const (unless we are binding to a
4430
+ // reference).
4433
4431
if (AK != clang::AK_ReferenceInitialization && !Frame) {
4434
4432
if (IsAccess && isa<ParmVarDecl>(VD)) {
4435
4433
// Access of a parameter that's not associated with a frame isn't going
@@ -4494,6 +4492,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4494
4492
}
4495
4493
}
4496
4494
4495
+ // When binding to a reference, the variable does not need to be constexpr
4496
+ // or have constant initalization.
4497
4497
if (AK != clang::AK_ReferenceInitialization &&
4498
4498
!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(),
4499
4499
BaseVal))
@@ -4506,10 +4506,13 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4506
4506
}
4507
4507
return CompleteObject(LVal.Base, &(*Alloc)->Value,
4508
4508
LVal.Base.getDynamicAllocType());
4509
- } else {
4509
+ }
4510
+ // When binding to a reference, the variable does not need to be
4511
+ // within its lifetime.
4512
+ else if (AK != clang::AK_ReferenceInitialization) {
4510
4513
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
4511
4514
4512
- if (AK != clang::AK_ReferenceInitialization && !Frame) {
4515
+ if (!Frame) {
4513
4516
if (const MaterializeTemporaryExpr *MTE =
4514
4517
dyn_cast_or_null<MaterializeTemporaryExpr>(Base)) {
4515
4518
assert(MTE->getStorageDuration() == SD_Static &&
@@ -5229,22 +5232,32 @@ enum EvalStmtResult {
5229
5232
};
5230
5233
}
5231
5234
5235
+ /// Evaluates the initializer of a reference.
5232
5236
static bool EvaluateInitForDeclOfReferenceType(EvalInfo &Info,
5233
5237
const ValueDecl *D,
5234
5238
const Expr *Init, LValue &Result,
5235
5239
APValue &Val) {
5236
5240
assert(Init->isGLValue() && D->getType()->isReferenceType());
5241
+ // A reference is an lvalue
5237
5242
if (!EvaluateLValue(Init, Result, Info))
5238
5243
return false;
5244
+ // [C++26][decl.ref]
5245
+ // The object designated by such a glvalue can be outside its lifetime
5246
+ // Because a null pointer value or a pointer past the end of an object
5247
+ // does not point to an object, a reference in a well-defined program cannot
5248
+ // refer to such things;
5239
5249
CompleteObject Obj = findCompleteObject(
5240
5250
Info, Init, AK_ReferenceInitialization, Result, Init->getType());
5251
+ if (!Obj)
5252
+ return false;
5241
5253
if (!Result.Designator.Invalid && Result.Designator.isOnePastTheEnd()) {
5242
5254
Info.FFDiag(Init, diag::note_constexpr_access_past_end)
5243
5255
<< AK_ReferenceInitialization;
5244
5256
return false;
5245
5257
}
5258
+ // save the result
5246
5259
Result.moveInto(Val);
5247
- return !!Obj ;
5260
+ return true ;
5248
5261
}
5249
5262
5250
5263
static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
0 commit comments