Skip to content

Commit 4cd55ea

Browse files
committed
cleanup, add comments
1 parent 5a3c5f0 commit 4cd55ea

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
@@ -4419,17 +4419,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
44194419
return CompleteObject();
44204420
}
44214421

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

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

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

4512-
if (AK != clang::AK_ReferenceInitialization && !Frame) {
4515+
if (!Frame) {
45134516
if (const MaterializeTemporaryExpr *MTE =
45144517
dyn_cast_or_null<MaterializeTemporaryExpr>(Base)) {
45154518
assert(MTE->getStorageDuration() == SD_Static &&
@@ -5229,22 +5232,32 @@ enum EvalStmtResult {
52295232
};
52305233
}
52315234

5235+
/// Evaluates the initializer of a reference.
52325236
static bool EvaluateInitForDeclOfReferenceType(EvalInfo &Info,
52335237
const ValueDecl *D,
52345238
const Expr *Init, LValue &Result,
52355239
APValue &Val) {
52365240
assert(Init->isGLValue() && D->getType()->isReferenceType());
5241+
// A reference is an lvalue
52375242
if (!EvaluateLValue(Init, Result, Info))
52385243
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;
52395249
CompleteObject Obj = findCompleteObject(
52405250
Info, Init, AK_ReferenceInitialization, Result, Init->getType());
5251+
if (!Obj)
5252+
return false;
52415253
if (!Result.Designator.Invalid && Result.Designator.isOnePastTheEnd()) {
52425254
Info.FFDiag(Init, diag::note_constexpr_access_past_end)
52435255
<< AK_ReferenceInitialization;
52445256
return false;
52455257
}
5258+
// save the result
52465259
Result.moveInto(Val);
5247-
return !!Obj;
5260+
return true;
52485261
}
52495262

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

0 commit comments

Comments
 (0)