================ @@ -54,36 +44,90 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) { bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { assert(Stk.empty()); ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); - if (Check(Parent, C.interpretExpr(E))) { - assert(Stk.empty()); -#ifndef NDEBUG - // Make sure we don't rely on some value being still alive in - // InterpStack memory. + + auto Res = C.interpretExpr(E); + + if (Res.isInvalid()) { Stk.clear(); + return false; + } + + assert(Stk.empty()); +#ifndef NDEBUG + // Make sure we don't rely on some value being still alive in + // InterpStack memory. + Stk.clear(); #endif - return true; + + // Implicit lvalue-to-rvalue conversion. + if (E->isGLValue()) { + std::optional<APValue> RValueResult = Res.toRValue(); + if (!RValueResult) { + return false; + } + Result = *RValueResult; + } else { + Result = Res.toAPValue(); } + return true; +} + +bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) { + assert(Stk.empty()); + ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); + + auto Res = C.interpretExpr(E); + if (Res.isInvalid()) { + Stk.clear(); + return false; + } + + assert(Stk.empty()); +#ifndef NDEBUG + // Make sure we don't rely on some value being still alive in + // InterpStack memory. Stk.clear(); - return false; +#endif + Result = Res.toAPValue(); + return true; } bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result) { assert(Stk.empty()); ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result); - if (Check(Parent, C.interpretDecl(VD))) { - assert(Stk.empty()); -#ifndef NDEBUG - // Make sure we don't rely on some value being still alive in - // InterpStack memory. + + auto Res = C.interpretDecl(VD); + if (Res.isInvalid()) { Stk.clear(); -#endif - return true; + return false; } + assert(Stk.empty()); +#ifndef NDEBUG + // Make sure we don't rely on some value being still alive in + // InterpStack memory. Stk.clear(); - return false; +#endif + + // Ensure global variables are fully initialized. + if (shouldBeGloballyIndexed(VD) && !Res.isInvalid() && + (VD->getType()->isRecordType() || VD->getType()->isArrayType())) { + assert(Res.isLValue()); + + if (!Res.checkFullyInitialized(C.getState())) + return false; + + // lvalue-to-rvalue conversion. + std::optional<APValue> RValueResult = Res.toRValue(); + if (!RValueResult) + return false; + Result = *RValueResult; ---------------- AaronBallman wrote:
Okay, that seems fine to do in a follow-up. https://github.com/llvm/llvm-project/pull/71315 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits