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