@@ -1529,7 +1529,7 @@ CallStackFrame::~CallStackFrame() {
15291529
15301530static bool isRead(AccessKinds AK) {
15311531 return AK == AK_Read || AK == AK_ReadObjectRepresentation ||
1532- AK == AK_IsWithinLifetime;
1532+ AK == AK_IsWithinLifetime || AK == AK_Dereference ;
15331533}
15341534
15351535static bool isModification(AccessKinds AK) {
@@ -1540,6 +1540,7 @@ static bool isModification(AccessKinds AK) {
15401540 case AK_DynamicCast:
15411541 case AK_TypeId:
15421542 case AK_IsWithinLifetime:
1543+ case AK_Dereference:
15431544 return false;
15441545 case AK_Assign:
15451546 case AK_Increment:
@@ -1558,15 +1559,16 @@ static bool isAnyAccess(AccessKinds AK) {
15581559/// Is this an access per the C++ definition?
15591560static bool isFormalAccess(AccessKinds AK) {
15601561 return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy &&
1561- AK != AK_IsWithinLifetime;
1562+ AK != AK_IsWithinLifetime && AK != AK_Dereference ;
15621563}
15631564
1564- /// Is this kind of axcess valid on an indeterminate object value?
1565+ /// Is this kind of access valid on an indeterminate object value?
15651566static bool isValidIndeterminateAccess(AccessKinds AK) {
15661567 switch (AK) {
15671568 case AK_Read:
15681569 case AK_Increment:
15691570 case AK_Decrement:
1571+ case AK_Dereference:
15701572 // These need the object's value.
15711573 return false;
15721574
@@ -1733,7 +1735,10 @@ namespace {
17331735 bool checkNullPointerForFoldAccess(EvalInfo &Info, const Expr *E,
17341736 AccessKinds AK) {
17351737 return checkNullPointerDiagnosingWith([&Info, E, AK] {
1736- Info.FFDiag(E, diag::note_constexpr_access_null) << AK;
1738+ if (AK == AccessKinds::AK_Dereference)
1739+ Info.FFDiag(E, diag::note_constexpr_dereferencing_null);
1740+ else
1741+ Info.FFDiag(E, diag::note_constexpr_access_null) << AK;
17371742 });
17381743 }
17391744
@@ -4305,7 +4310,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
43054310 }
43064311
43074312 if (!LVal.Base) {
4308- Info.FFDiag(E, diag::note_constexpr_access_null) << AK;
4313+ if (AK == AccessKinds::AK_Dereference)
4314+ Info.FFDiag(E, diag::note_constexpr_dereferencing_null);
4315+ else
4316+ Info.FFDiag(E, diag::note_constexpr_access_null) << AK;
43094317 return CompleteObject();
43104318 }
43114319
@@ -4407,8 +4415,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
44074415 ConstexprVar = VD->isConstexpr();
44084416
44094417 // Unless we're looking at a local variable or argument in a constexpr call,
4410- // the variable we're reading must be const.
4411- if (!Frame) {
4418+ // the variable we're reading must be const (unless we are binding to a
4419+ // reference).
4420+ if (AK != clang::AK_Dereference && !Frame) {
44124421 if (IsAccess && isa<ParmVarDecl>(VD)) {
44134422 // Access of a parameter that's not associated with a frame isn't going
44144423 // to work out, but we can leave it to evaluateVarDeclInit to provide a
@@ -4472,12 +4481,16 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
44724481 }
44734482 }
44744483
4475- if (!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(), BaseVal))
4484+ // When binding to a reference, the variable does not need to be constexpr
4485+ // or have constant initalization.
4486+ if (AK != clang::AK_Dereference &&
4487+ !evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(),
4488+ BaseVal))
44764489 return CompleteObject();
44774490 // If evaluateVarDeclInit sees a constexpr-unknown variable, it returns
44784491 // a null BaseVal. Any constexpr-unknown variable seen here is an error:
44794492 // we can't access a constexpr-unknown object.
4480- if (!BaseVal) {
4493+ if (AK != clang::AK_Dereference && !BaseVal) {
44814494 Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
44824495 << AK << VD;
44834496 Info.Note(VD->getLocation(), diag::note_declared_at);
@@ -4491,7 +4504,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
44914504 }
44924505 return CompleteObject(LVal.Base, &(*Alloc)->Value,
44934506 LVal.Base.getDynamicAllocType());
4494- } else {
4507+ }
4508+ // When binding to a reference, the variable does not need to be
4509+ // within its lifetime.
4510+ else if (AK != clang::AK_Dereference) {
44954511 const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
44964512
44974513 if (!Frame) {
@@ -4572,7 +4588,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
45724588 NoteLValueLocation(Info, LVal.Base);
45734589 return CompleteObject();
45744590 }
4575- } else {
4591+ } else if (AK != clang::AK_Dereference) {
45764592 BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion());
45774593 assert(BaseVal && "missing value for temporary");
45784594 }
@@ -5200,6 +5216,29 @@ enum EvalStmtResult {
52005216 ESR_CaseNotFound
52015217};
52025218}
5219+ /// Evaluates the initializer of a reference.
5220+ static bool EvaluateInitForDeclOfReferenceType(EvalInfo &Info,
5221+ const ValueDecl *D,
5222+ const Expr *Init, LValue &Result,
5223+ APValue &Val) {
5224+ assert(Init->isGLValue() && D->getType()->isReferenceType());
5225+ // A reference is an lvalue.
5226+ if (!EvaluateLValue(Init, Result, Info))
5227+ return false;
5228+ // [C++26][decl.ref]
5229+ // The object designated by such a glvalue can be outside its lifetime
5230+ // Because a null pointer value or a pointer past the end of an object
5231+ // does not point to an object, a reference in a well-defined program cannot
5232+ // refer to such things;
5233+ if (!Result.Designator.Invalid && Result.Designator.isOnePastTheEnd()) {
5234+ Info.FFDiag(Init, diag::note_constexpr_access_past_end) << AK_Dereference;
5235+ return false;
5236+ }
5237+
5238+ // Save the result.
5239+ Result.moveInto(Val);
5240+ return true;
5241+ }
52035242
52045243static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
52055244 if (VD->isInvalidDecl())
@@ -5221,7 +5260,11 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
52215260 if (InitE->isValueDependent())
52225261 return false;
52235262
5224- if (!EvaluateInPlace(Val, Info, Result, InitE)) {
5263+ // For references to objects, check they do not designate a one-past-the-end
5264+ // object.
5265+ if (VD->getType()->isReferenceType()) {
5266+ return EvaluateInitForDeclOfReferenceType(Info, VD, InitE, Result, Val);
5267+ } else if (!EvaluateInPlace(Val, Info, Result, InitE)) {
52255268 // Wipe out any partially-computed value, to allow tracking that this
52265269 // evaluation failed.
52275270 Val = APValue();
@@ -6851,9 +6894,18 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
68516894 ThisOverrideRAII ThisOverride(*Info.CurrentCall, &SubobjectParent,
68526895 isa<CXXDefaultInitExpr>(Init));
68536896 FullExpressionRAII InitScope(Info);
6854- if (!EvaluateInPlace(*Value, Info, Subobject, Init) ||
6855- (FD && FD->isBitField() &&
6856- !truncateBitfieldValue(Info, Init, *Value, FD))) {
6897+ if (FD && FD->getType()->isReferenceType() &&
6898+ !FD->getType()->isFunctionReferenceType()) {
6899+ LValue Result;
6900+ if (!EvaluateInitForDeclOfReferenceType(Info, FD, Init, Result,
6901+ *Value)) {
6902+ if (!Info.noteFailure())
6903+ return false;
6904+ Success = false;
6905+ }
6906+ } else if (!EvaluateInPlace(*Value, Info, Subobject, Init) ||
6907+ (FD && FD->isBitField() &&
6908+ !truncateBitfieldValue(Info, Init, *Value, FD))) {
68576909 // If we're checking for a potential constant expression, evaluate all
68586910 // initializers even if some of them fail.
68596911 if (!Info.noteFailure())
@@ -9287,7 +9339,13 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
92879339}
92889340
92899341bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) {
9290- return evaluatePointer(E->getSubExpr(), Result);
9342+ bool Success = evaluatePointer(E->getSubExpr(), Result);
9343+ // [C++26][expr.unary.op]
9344+ // If the operand points to an object or function, the result
9345+ // denotes that object or function; otherwise, the behavior is undefined.
9346+ return Success &&
9347+ (!E->getType().getNonReferenceType()->isObjectType() ||
9348+ findCompleteObject(Info, E, AK_Dereference, Result, E->getType()));
92919349}
92929350
92939351bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
@@ -10906,9 +10964,17 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
1090610964 isa<CXXDefaultInitExpr>(Init));
1090710965
1090810966 APValue &FieldVal = Result.getStructField(Field->getFieldIndex());
10909- if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) ||
10910- (Field->isBitField() && !truncateBitfieldValue(Info, Init,
10911- FieldVal, Field))) {
10967+ if (Field->getType()->isReferenceType()) {
10968+ LValue Result;
10969+ if (!EvaluateInitForDeclOfReferenceType(Info, Field, Init, Result,
10970+ FieldVal)) {
10971+ if (!Info.noteFailure())
10972+ return false;
10973+ Success = false;
10974+ }
10975+ } else if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) ||
10976+ (Field->isBitField() &&
10977+ !truncateBitfieldValue(Info, Init, FieldVal, Field))) {
1091210978 if (!Info.noteFailure())
1091310979 return false;
1091410980 Success = false;
0 commit comments