@@ -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;
1532
+ AK == AK_IsWithinLifetime || AK == AK_CheckReferenceInitialization ;
1533
1533
}
1534
1534
1535
1535
static bool isModification(AccessKinds AK) {
@@ -1540,6 +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
1544
return false;
1544
1545
case AK_Assign:
1545
1546
case AK_Increment:
@@ -1558,7 +1559,7 @@ static bool isAnyAccess(AccessKinds AK) {
1558
1559
/// Is this an access per the C++ definition?
1559
1560
static bool isFormalAccess(AccessKinds AK) {
1560
1561
return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy &&
1561
- AK != AK_IsWithinLifetime;
1562
+ AK != AK_IsWithinLifetime && AK != AK_CheckReferenceInitialization ;
1562
1563
}
1563
1564
1564
1565
/// Is this kind of axcess valid on an indeterminate object value?
@@ -1571,6 +1572,7 @@ static bool isValidIndeterminateAccess(AccessKinds AK) {
1571
1572
return false;
1572
1573
1573
1574
case AK_IsWithinLifetime:
1575
+ case AK_CheckReferenceInitialization:
1574
1576
case AK_ReadObjectRepresentation:
1575
1577
case AK_Assign:
1576
1578
case AK_Construct:
@@ -4425,7 +4427,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4425
4427
4426
4428
// Unless we're looking at a local variable or argument in a constexpr call,
4427
4429
// the variable we're reading must be const.
4428
- if (!Frame) {
4430
+ if (!Frame && AK != clang::AK_CheckReferenceInitialization ) {
4429
4431
if (IsAccess && isa<ParmVarDecl>(VD)) {
4430
4432
// Access of a parameter that's not associated with a frame isn't going
4431
4433
// to work out, but we can leave it to evaluateVarDeclInit to provide a
@@ -4502,7 +4504,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4502
4504
} else {
4503
4505
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
4504
4506
4505
- if (!Frame) {
4507
+ if (!Frame && AK != clang::AK_CheckReferenceInitialization ) {
4506
4508
if (const MaterializeTemporaryExpr *MTE =
4507
4509
dyn_cast_or_null<MaterializeTemporaryExpr>(Base)) {
4508
4510
assert(MTE->getStorageDuration() == SD_Static &&
@@ -4556,7 +4558,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4556
4558
NoteLValueLocation(Info, LVal.Base);
4557
4559
return CompleteObject();
4558
4560
}
4559
- } else {
4561
+ } else if (AK != clang::AK_CheckReferenceInitialization) {
4560
4562
BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion());
4561
4563
assert(BaseVal && "missing value for temporary");
4562
4564
}
@@ -5242,7 +5244,19 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
5242
5244
if (InitE->isValueDependent())
5243
5245
return false;
5244
5246
5245
- if (!EvaluateInPlace(Val, Info, Result, InitE)) {
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;
5259
+ } else if (!EvaluateInPlace(Val, Info, Result, InitE)) {
5246
5260
// Wipe out any partially-computed value, to allow tracking that this
5247
5261
// evaluation failed.
5248
5262
Val = APValue();
0 commit comments