@@ -202,7 +202,9 @@ namespace {
202202 assert(!isBaseAnAllocSizeCall(Base) &&
203203 "Unsized arrays shouldn't appear here");
204204 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();
206208
207209 for (unsigned I = 0, N = Path.size(); I != N; ++I) {
208210 if (Type->isArrayType()) {
@@ -289,7 +291,7 @@ namespace {
289291 : Invalid(false), IsOnePastTheEnd(false),
290292 FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false),
291293 MostDerivedPathLength(0), MostDerivedArraySize(0),
292- MostDerivedType(T) {}
294+ MostDerivedType(T.isNull() ? QualType() : T.getNonReferenceType() ) {}
293295
294296 SubobjectDesignator(ASTContext &Ctx, const APValue &V)
295297 : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false),
@@ -571,7 +573,6 @@ namespace {
571573 typedef std::map<MapKeyTy, APValue> MapTy;
572574 /// Temporaries - Temporary lvalues materialized within this stack frame.
573575 MapTy Temporaries;
574- MapTy ConstexprUnknownAPValues;
575576
576577 /// CallRange - The source range of the call expression for this call.
577578 SourceRange CallRange;
@@ -646,9 +647,6 @@ namespace {
646647 APValue &createTemporary(const KeyT *Key, QualType T,
647648 ScopeKind Scope, LValue &LV);
648649
649- APValue &createConstexprUnknownAPValues(const VarDecl *Key,
650- APValue::LValueBase Base);
651-
652650 /// Allocate storage for a parameter of a function call made in this frame.
653651 APValue &createParam(CallRef Args, const ParmVarDecl *PVD, LValue &LV);
654652
@@ -1756,7 +1754,8 @@ namespace {
17561754 return;
17571755 }
17581756 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());
17601759 Designator.FirstEntryIsAnUnsizedArray = true;
17611760 Designator.addUnsizedArrayUnchecked(ElemTy);
17621761 }
@@ -1955,15 +1954,6 @@ APValue &CallStackFrame::createTemporary(const KeyT *Key, QualType T,
19551954 return createLocal(Base, Key, T, Scope);
19561955}
19571956
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-
19671957/// Allocate storage for a parameter of a function call made in this frame.
19681958APValue &CallStackFrame::createParam(CallRef Args, const ParmVarDecl *PVD,
19691959 LValue &LV) {
@@ -3493,7 +3483,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
34933483 APValue::LValueBase Base(VD, Frame ? Frame->Index : 0, Version);
34943484
34953485 auto CheckUninitReference = [&](bool IsLocalVariable) {
3496- if (!Result->hasValue() && VD->getType()->isReferenceType()) {
3486+ if (!Result || (!Result ->hasValue() && VD->getType()->isReferenceType() )) {
34973487 // C++23 [expr.const]p8
34983488 // ... For such an object that is not usable in constant expressions, the
34993489 // dynamic type of the object is constexpr-unknown. For such a reference
@@ -3509,7 +3499,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
35093499 Info.FFDiag(E, diag::note_constexpr_use_uninit_reference);
35103500 return false;
35113501 }
3512- Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base) ;
3502+ Result = nullptr ;
35133503 }
35143504 return true;
35153505 };
@@ -3552,7 +3542,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
35523542 // ... its lifetime began within the evaluation of E;
35533543 if (isa<ParmVarDecl>(VD)) {
35543544 if (AllowConstexprUnknown) {
3555- Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base) ;
3545+ Result = nullptr ;
35563546 return true;
35573547 }
35583548
@@ -3659,12 +3649,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
36593649
36603650 Result = VD->getEvaluatedValue();
36613651
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;
36683654
36693655 return CheckUninitReference(/*IsLocalVariable=*/false);
36703656}
@@ -3947,11 +3933,6 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
39473933 const FieldDecl *LastField = nullptr;
39483934 const FieldDecl *VolatileField = nullptr;
39493935
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-
39553936 // Walk the designator's path to find the subobject.
39563937 for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
39573938 // Reading an indeterminate value is undefined, but assigning over one is OK.
@@ -4491,6 +4472,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
44914472
44924473 if (!evaluateVarDeclInit(Info, E, VD, Frame, LVal.getLValueVersion(), BaseVal))
44934474 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+ }
44944484 } else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
44954485 std::optional<DynAlloc *> Alloc = Info.lookupDynamicAlloc(DA);
44964486 if (!Alloc) {
@@ -6057,15 +6047,6 @@ struct CheckDynamicTypeHandler {
60576047/// dynamic type.
60586048static bool checkDynamicType(EvalInfo &Info, const Expr *E, const LValue &This,
60596049 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-
60696050 if (This.Designator.Invalid)
60706051 return false;
60716052
@@ -6139,9 +6120,7 @@ static std::optional<DynamicType> ComputeDynamicType(EvalInfo &Info,
61396120 // meaningful dynamic type. (We consider objects of non-class type to have no
61406121 // dynamic type.)
61416122 if (!checkDynamicType(Info, E, This, AK,
6142- (AK == AK_TypeId
6143- ? (E->getType()->isReferenceType() ? true : false)
6144- : true)))
6123+ AK != AK_TypeId || This.AllowConstexprUnknown))
61456124 return std::nullopt;
61466125
61476126 if (This.Designator.Invalid)
@@ -9063,6 +9042,12 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
90639042 if (!evaluateVarDeclInit(Info, E, VD, Frame, Version, V))
90649043 return false;
90659044
9045+ if (!V) {
9046+ Result.set(VD);
9047+ Result.AllowConstexprUnknown = true;
9048+ return true;
9049+ }
9050+
90669051 return Success(*V, E);
90679052}
90689053
0 commit comments