@@ -202,7 +202,9 @@ namespace {
202
202
assert(!isBaseAnAllocSizeCall(Base) &&
203
203
"Unsized arrays shouldn't appear here");
204
204
unsigned MostDerivedLength = 0;
205
- Type = getType(Base);
205
+ // The type of Base is a reference type if the base is a constexpr-unknown
206
+ // variable. In that case, look through the reference type.
207
+ Type = getType(Base).getNonReferenceType();
206
208
207
209
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
208
210
if (Type->isArrayType()) {
@@ -289,7 +291,7 @@ namespace {
289
291
: Invalid(false), IsOnePastTheEnd(false),
290
292
FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false),
291
293
MostDerivedPathLength(0), MostDerivedArraySize(0),
292
- MostDerivedType(T) {}
294
+ MostDerivedType(T.isNull() ? QualType() : T.getNonReferenceType() ) {}
293
295
294
296
SubobjectDesignator(ASTContext &Ctx, const APValue &V)
295
297
: Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false),
@@ -571,7 +573,6 @@ namespace {
571
573
typedef std::map<MapKeyTy, APValue> MapTy;
572
574
/// Temporaries - Temporary lvalues materialized within this stack frame.
573
575
MapTy Temporaries;
574
- MapTy ConstexprUnknownAPValues;
575
576
576
577
/// CallRange - The source range of the call expression for this call.
577
578
SourceRange CallRange;
@@ -646,9 +647,6 @@ namespace {
646
647
APValue &createTemporary(const KeyT *Key, QualType T,
647
648
ScopeKind Scope, LValue &LV);
648
649
649
- APValue &createConstexprUnknownAPValues(const VarDecl *Key,
650
- APValue::LValueBase Base);
651
-
652
650
/// Allocate storage for a parameter of a function call made in this frame.
653
651
APValue &createParam(CallRef Args, const ParmVarDecl *PVD, LValue &LV);
654
652
@@ -1756,7 +1754,8 @@ namespace {
1756
1754
return;
1757
1755
}
1758
1756
if (checkSubobject(Info, E, CSK_ArrayToPointer)) {
1759
- assert(getType(Base)->isPointerType() || getType(Base)->isArrayType());
1757
+ assert(getType(Base).getNonReferenceType()->isPointerType() ||
1758
+ getType(Base).getNonReferenceType()->isArrayType());
1760
1759
Designator.FirstEntryIsAnUnsizedArray = true;
1761
1760
Designator.addUnsizedArrayUnchecked(ElemTy);
1762
1761
}
@@ -1955,15 +1954,6 @@ APValue &CallStackFrame::createTemporary(const KeyT *Key, QualType T,
1955
1954
return createLocal(Base, Key, T, Scope);
1956
1955
}
1957
1956
1958
- APValue &
1959
- CallStackFrame::createConstexprUnknownAPValues(const VarDecl *Key,
1960
- APValue::LValueBase Base) {
1961
- APValue &Result = ConstexprUnknownAPValues[MapKeyTy(Key, Base.getVersion())];
1962
- Result = APValue(Base, CharUnits::Zero(), APValue::ConstexprUnknown{});
1963
-
1964
- return Result;
1965
- }
1966
-
1967
1957
/// Allocate storage for a parameter of a function call made in this frame.
1968
1958
APValue &CallStackFrame::createParam(CallRef Args, const ParmVarDecl *PVD,
1969
1959
LValue &LV) {
@@ -3493,7 +3483,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
3493
3483
APValue::LValueBase Base(VD, Frame ? Frame->Index : 0, Version);
3494
3484
3495
3485
auto CheckUninitReference = [&](bool IsLocalVariable) {
3496
- if (!Result->hasValue() && VD->getType()->isReferenceType()) {
3486
+ if (!Result || (!Result ->hasValue() && VD->getType()->isReferenceType() )) {
3497
3487
// C++23 [expr.const]p8
3498
3488
// ... For such an object that is not usable in constant expressions, the
3499
3489
// dynamic type of the object is constexpr-unknown. For such a reference
@@ -3509,7 +3499,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
3509
3499
Info.FFDiag(E, diag::note_constexpr_use_uninit_reference);
3510
3500
return false;
3511
3501
}
3512
- Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base) ;
3502
+ Result = nullptr ;
3513
3503
}
3514
3504
return true;
3515
3505
};
@@ -3552,7 +3542,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
3552
3542
// ... its lifetime began within the evaluation of E;
3553
3543
if (isa<ParmVarDecl>(VD)) {
3554
3544
if (AllowConstexprUnknown) {
3555
- Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base) ;
3545
+ Result = nullptr ;
3556
3546
return true;
3557
3547
}
3558
3548
@@ -3659,12 +3649,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
3659
3649
3660
3650
Result = VD->getEvaluatedValue();
3661
3651
3662
- if (!Result) {
3663
- if (AllowConstexprUnknown)
3664
- Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base);
3665
- else
3666
- return false;
3667
- }
3652
+ if (!Result && !AllowConstexprUnknown)
3653
+ return false;
3668
3654
3669
3655
return CheckUninitReference(/*IsLocalVariable=*/false);
3670
3656
}
@@ -3947,11 +3933,6 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
3947
3933
const FieldDecl *LastField = nullptr;
3948
3934
const FieldDecl *VolatileField = nullptr;
3949
3935
3950
- // C++23 [expr.const]p8 If we have an unknown reference or pointers and it
3951
- // does not have a value then bail out.
3952
- if (O->allowConstexprUnknown() && !O->hasValue())
3953
- return false;
3954
-
3955
3936
// Walk the designator's path to find the subobject.
3956
3937
for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
3957
3938
// Reading an indeterminate value is undefined, but assigning over one is OK.
@@ -4491,6 +4472,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
4491
4472
4492
4473
if (!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(), BaseVal))
4493
4474
return CompleteObject();
4475
+ // If evaluateVarDeclInit sees a constexpr-unknown variable, it returns
4476
+ // a null BaseVal. Any constexpr-unknown variable seen here is an error:
4477
+ // we can't access a constexpr-unknown object.
4478
+ if (!BaseVal) {
4479
+ Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
4480
+ << AK << VD;
4481
+ Info.Note(VD->getLocation(), diag::note_declared_at);
4482
+ return CompleteObject();
4483
+ }
4494
4484
} else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
4495
4485
std::optional<DynAlloc *> Alloc = Info.lookupDynamicAlloc(DA);
4496
4486
if (!Alloc) {
@@ -6057,15 +6047,6 @@ struct CheckDynamicTypeHandler {
6057
6047
/// dynamic type.
6058
6048
static bool checkDynamicType(EvalInfo &Info, const Expr *E, const LValue &This,
6059
6049
AccessKinds AK, bool Polymorphic) {
6060
- // We are not allowed to invoke a virtual function whose dynamic type
6061
- // is constexpr-unknown, so stop early and let this fail later on if we
6062
- // attempt to do so.
6063
- // C++23 [expr.const]p5.6
6064
- // an invocation of a virtual function ([class.virtual]) for an object whose
6065
- // dynamic type is constexpr-unknown;
6066
- if (This.allowConstexprUnknown())
6067
- return true;
6068
-
6069
6050
if (This.Designator.Invalid)
6070
6051
return false;
6071
6052
@@ -6139,9 +6120,7 @@ static std::optional<DynamicType> ComputeDynamicType(EvalInfo &Info,
6139
6120
// meaningful dynamic type. (We consider objects of non-class type to have no
6140
6121
// dynamic type.)
6141
6122
if (!checkDynamicType(Info, E, This, AK,
6142
- (AK == AK_TypeId
6143
- ? (E->getType()->isReferenceType() ? true : false)
6144
- : true)))
6123
+ AK != AK_TypeId || This.AllowConstexprUnknown))
6145
6124
return std::nullopt;
6146
6125
6147
6126
if (This.Designator.Invalid)
@@ -9063,6 +9042,12 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
9063
9042
if (!evaluateVarDeclInit(Info, E, VD, Frame, Version, V))
9064
9043
return false;
9065
9044
9045
+ if (!V) {
9046
+ Result.set(VD);
9047
+ Result.AllowConstexprUnknown = true;
9048
+ return true;
9049
+ }
9050
+
9066
9051
return Success(*V, E);
9067
9052
}
9068
9053
0 commit comments