Skip to content

Commit fff79c4

Browse files
committed
cleanup, add comments
1 parent e467b50 commit fff79c4

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4420,17 +4420,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
44204420
return CompleteObject();
44214421
}
44224422

4423-
// if(AK == clang::AK_ReferenceInitialization)
4424-
// return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
4425-
44264423
bool IsConstant = BaseType.isConstant(Info.Ctx);
44274424
bool ConstexprVar = false;
44284425
if (const auto *VD = dyn_cast_if_present<VarDecl>(
44294426
Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
44304427
ConstexprVar = VD->isConstexpr();
44314428

44324429
// 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).
44344432
if (AK != clang::AK_ReferenceInitialization && !Frame) {
44354433
if (IsAccess && isa<ParmVarDecl>(VD)) {
44364434
// 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,
44954493
}
44964494
}
44974495

4496+
// When binding to a reference, the variable does not need to be constexpr
4497+
// or have constant initalization.
44984498
if (AK != clang::AK_ReferenceInitialization &&
44994499
!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(),
45004500
BaseVal))
@@ -4507,10 +4507,13 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
45074507
}
45084508
return CompleteObject(LVal.Base, &(*Alloc)->Value,
45094509
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) {
45114514
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
45124515

4513-
if (AK != clang::AK_ReferenceInitialization && !Frame) {
4516+
if (!Frame) {
45144517
if (const MaterializeTemporaryExpr *MTE =
45154518
dyn_cast_or_null<MaterializeTemporaryExpr>(Base)) {
45164519
assert(MTE->getStorageDuration() == SD_Static &&
@@ -5230,22 +5233,32 @@ enum EvalStmtResult {
52305233
};
52315234
}
52325235

5236+
/// Evaluates the initializer of a reference.
52335237
static bool EvaluateInitForDeclOfReferenceType(EvalInfo &Info,
52345238
const ValueDecl *D,
52355239
const Expr *Init, LValue &Result,
52365240
APValue &Val) {
52375241
assert(Init->isGLValue() && D->getType()->isReferenceType());
5242+
// A reference is an lvalue
52385243
if (!EvaluateLValue(Init, Result, Info))
52395244
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;
52405250
CompleteObject Obj = findCompleteObject(
52415251
Info, Init, AK_ReferenceInitialization, Result, Init->getType());
5252+
if (!Obj)
5253+
return false;
52425254
if (!Result.Designator.Invalid && Result.Designator.isOnePastTheEnd()) {
52435255
Info.FFDiag(Init, diag::note_constexpr_access_past_end)
52445256
<< AK_ReferenceInitialization;
52455257
return false;
52465258
}
5259+
// save the result
52475260
Result.moveInto(Val);
5248-
return !!Obj;
5261+
return true;
52495262
}
52505263

52515264
static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {

0 commit comments

Comments
 (0)