@@ -1529,7 +1529,7 @@ CallStackFrame::~CallStackFrame() {
1529
1529
1530
1530
static bool isRead(AccessKinds AK) {
1531
1531
return AK == AK_Read || AK == AK_ReadObjectRepresentation ||
1532
- AK == AK_IsWithinLifetime || AK == AK_CheckReferenceInitialization ;
1532
+ AK == AK_IsWithinLifetime || AK == AK_ReferenceInitialization ;
1533
1533
}
1534
1534
1535
1535
static bool isModification(AccessKinds AK) {
@@ -1540,7 +1540,7 @@ static bool isModification(AccessKinds AK) {
1540
1540
case AK_DynamicCast:
1541
1541
case AK_TypeId:
1542
1542
case AK_IsWithinLifetime:
1543
- case AK_CheckReferenceInitialization :
1543
+ case AK_ReferenceInitialization :
1544
1544
return false;
1545
1545
case AK_Assign:
1546
1546
case AK_Increment:
@@ -1559,7 +1559,7 @@ static bool isAnyAccess(AccessKinds AK) {
1559
1559
/// Is this an access per the C++ definition?
1560
1560
static bool isFormalAccess(AccessKinds AK) {
1561
1561
return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy &&
1562
- AK != AK_IsWithinLifetime && AK != AK_CheckReferenceInitialization ;
1562
+ AK != AK_IsWithinLifetime && AK != AK_ReferenceInitialization ;
1563
1563
}
1564
1564
1565
1565
/// Is this kind of axcess valid on an indeterminate object value?
@@ -1572,7 +1572,7 @@ static bool isValidIndeterminateAccess(AccessKinds AK) {
1572
1572
return false;
1573
1573
1574
1574
case AK_IsWithinLifetime:
1575
- case AK_CheckReferenceInitialization :
1575
+ case AK_ReferenceInitialization :
1576
1576
case AK_ReadObjectRepresentation:
1577
1577
case AK_Assign:
1578
1578
case AK_Construct:
@@ -4419,6 +4419,9 @@ 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
+
4422
4425
bool IsConstant = BaseType.isConstant(Info.Ctx);
4423
4426
bool ConstexprVar = false;
4424
4427
if (const auto *VD = dyn_cast_if_present<VarDecl>(
@@ -4427,7 +4430,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4427
4430
4428
4431
// Unless we're looking at a local variable or argument in a constexpr call,
4429
4432
// the variable we're reading must be const.
4430
- if (!Frame && AK != clang::AK_CheckReferenceInitialization ) {
4433
+ if (AK != clang::AK_ReferenceInitialization && !Frame ) {
4431
4434
if (IsAccess && isa<ParmVarDecl>(VD)) {
4432
4435
// Access of a parameter that's not associated with a frame isn't going
4433
4436
// to work out, but we can leave it to evaluateVarDeclInit to provide a
@@ -4491,7 +4494,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4491
4494
}
4492
4495
}
4493
4496
4494
- if (!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(), BaseVal))
4497
+ if (AK != clang::AK_ReferenceInitialization &&
4498
+ !evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(),
4499
+ BaseVal))
4495
4500
return CompleteObject();
4496
4501
} else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
4497
4502
std::optional<DynAlloc *> Alloc = Info.lookupDynamicAlloc(DA);
@@ -4504,7 +4509,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4504
4509
} else {
4505
4510
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
4506
4511
4507
- if (!Frame && AK != clang::AK_CheckReferenceInitialization ) {
4512
+ if (AK != clang::AK_ReferenceInitialization && !Frame ) {
4508
4513
if (const MaterializeTemporaryExpr *MTE =
4509
4514
dyn_cast_or_null<MaterializeTemporaryExpr>(Base)) {
4510
4515
assert(MTE->getStorageDuration() == SD_Static &&
@@ -4558,7 +4563,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4558
4563
NoteLValueLocation(Info, LVal.Base);
4559
4564
return CompleteObject();
4560
4565
}
4561
- } else if (AK != clang::AK_CheckReferenceInitialization ) {
4566
+ } else if (AK != clang::AK_ReferenceInitialization ) {
4562
4567
BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion());
4563
4568
assert(BaseVal && "missing value for temporary");
4564
4569
}
@@ -5224,6 +5229,24 @@ enum EvalStmtResult {
5224
5229
};
5225
5230
}
5226
5231
5232
+ static bool EvaluateInitForDeclOfReferenceType(EvalInfo &Info,
5233
+ const ValueDecl *D,
5234
+ const Expr *Init, LValue &Result,
5235
+ APValue &Val) {
5236
+ assert(Init->isGLValue() && D->getType()->isReferenceType());
5237
+ if (!EvaluateLValue(Init, Result, Info))
5238
+ return false;
5239
+ CompleteObject Obj = findCompleteObject(
5240
+ Info, Init, AK_ReferenceInitialization, Result, Init->getType());
5241
+ if (!Result.Designator.Invalid && Result.Designator.isOnePastTheEnd()) {
5242
+ Info.FFDiag(Init, diag::note_constexpr_access_past_end)
5243
+ << AK_ReferenceInitialization;
5244
+ return false;
5245
+ }
5246
+ Result.moveInto(Val);
5247
+ return !!Obj;
5248
+ }
5249
+
5227
5250
static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
5228
5251
if (VD->isInvalidDecl())
5229
5252
return false;
@@ -5244,18 +5267,8 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
5244
5267
if (InitE->isValueDependent())
5245
5268
return false;
5246
5269
5247
- if (VD->getType()->isReferenceType() && InitE->isGLValue()) {
5248
- if (!EvaluateLValue(InitE, Result, Info))
5249
- return false;
5250
- CompleteObject Obj = findCompleteObject(
5251
- Info, InitE, AK_CheckReferenceInitialization, Result, InitE->getType());
5252
- if (Result.Designator.isOnePastTheEnd()) {
5253
- Info.FFDiag(InitE, diag::note_constexpr_access_past_end)
5254
- << AK_CheckReferenceInitialization;
5255
- return false;
5256
- }
5257
- Result.moveInto(Val);
5258
- return !!Obj;
5270
+ if (VD->getType()->isReferenceType()) {
5271
+ return EvaluateInitForDeclOfReferenceType(Info, VD, InitE, Result, Val);
5259
5272
} else if (!EvaluateInPlace(Val, Info, Result, InitE)) {
5260
5273
// Wipe out any partially-computed value, to allow tracking that this
5261
5274
// evaluation failed.
@@ -6897,9 +6910,18 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
6897
6910
ThisOverrideRAII ThisOverride(*Info.CurrentCall, &SubobjectParent,
6898
6911
isa<CXXDefaultInitExpr>(Init));
6899
6912
FullExpressionRAII InitScope(Info);
6900
- if (!EvaluateInPlace(*Value, Info, Subobject, Init) ||
6901
- (FD && FD->isBitField() &&
6902
- !truncateBitfieldValue(Info, Init, *Value, FD))) {
6913
+
6914
+ if (FD && FD->getType()->isReferenceType()) {
6915
+ LValue Result;
6916
+ if (!EvaluateInitForDeclOfReferenceType(Info, FD, Init, Result,
6917
+ *Value)) {
6918
+ if (!Info.noteFailure())
6919
+ return false;
6920
+ Success = false;
6921
+ }
6922
+ } else if (!EvaluateInPlace(*Value, Info, Subobject, Init) ||
6923
+ (FD && FD->isBitField() &&
6924
+ !truncateBitfieldValue(Info, Init, *Value, FD))) {
6903
6925
// If we're checking for a potential constant expression, evaluate all
6904
6926
// initializers even if some of them fail.
6905
6927
if (!Info.noteFailure())
@@ -10926,9 +10948,18 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
10926
10948
isa<CXXDefaultInitExpr>(Init));
10927
10949
10928
10950
APValue &FieldVal = Result.getStructField(Field->getFieldIndex());
10929
- if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) ||
10930
- (Field->isBitField() && !truncateBitfieldValue(Info, Init,
10931
- FieldVal, Field))) {
10951
+
10952
+ if (Field->getType()->isReferenceType()) {
10953
+ LValue Result;
10954
+ if (!EvaluateInitForDeclOfReferenceType(Info, Field, Init, Result,
10955
+ FieldVal)) {
10956
+ if (!Info.noteFailure())
10957
+ return false;
10958
+ Success = false;
10959
+ }
10960
+ } else if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) ||
10961
+ (Field->isBitField() &&
10962
+ !truncateBitfieldValue(Info, Init, FieldVal, Field))) {
10932
10963
if (!Info.noteFailure())
10933
10964
return false;
10934
10965
Success = false;
0 commit comments