Timm =?utf-8?q?Bäder?= <[email protected]>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/[email protected]>


https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/226217

>From 6a8aa7591252662a5a79a9a34ea256630c9f9053 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Thu, 24 Sep 2026 16:08:13 +0200
Subject: [PATCH 1/2] [clang][bytecode] Use EvalSettings struct

---
 clang/lib/AST/ByteCode/Context.cpp     | 114 +++++++++++++-------
 clang/lib/AST/ByteCode/Context.h       |  41 ++++---
 clang/lib/AST/ByteCode/EvalEmitter.cpp |   6 ++
 clang/lib/AST/ByteCode/EvalEmitter.h   |   3 +
 clang/lib/AST/ByteCode/EvalSettings.h  |  35 ++++++
 clang/lib/AST/ByteCode/InterpState.cpp |  30 ++++--
 clang/lib/AST/ByteCode/InterpState.h   |   6 +-
 clang/lib/AST/ExprConstant.cpp         | 143 +++++++++++++++----------
 8 files changed, 260 insertions(+), 118 deletions(-)
 create mode 100644 clang/lib/AST/ByteCode/EvalSettings.h

diff --git a/clang/lib/AST/ByteCode/Context.cpp 
b/clang/lib/AST/ByteCode/Context.cpp
index 9cdb2725a92040..a08f93335957ef 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -12,6 +12,7 @@
 #include "Char.h"
 #include "Compiler.h"
 #include "EvalEmitter.h"
+#include "EvalSettings.h"
 #include "Integral.h"
 #include "InterpFrame.h"
 #include "InterpHelpers.h"
@@ -37,7 +38,8 @@ Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new 
Program(*this)) {
 
 Context::~Context() = default;
 
-bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
+bool Context::isPotentialConstantExpr(const EvalSettings &Settings,
+                                      const FunctionDecl *FD) {
   assert(Stk.empty());
 
   // Get a function handle.
@@ -54,15 +56,16 @@ bool Context::isPotentialConstantExpr(State &Parent, const 
FunctionDecl *FD) {
 
   ++EvalID;
   // And run it.
-  return Run(Parent, Func);
+  return Run(Settings, Func);
 }
 
-void Context::isPotentialConstantExprUnevaluated(State &Parent, const Expr *E,
+void Context::isPotentialConstantExprUnevaluated(const EvalSettings &Settings,
+                                                 const Expr *E,
                                                  const FunctionDecl *FD) {
   assert(Stk.empty());
   ++EvalID;
   size_t StackSizeBefore = Stk.size();
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
 
   if (!C.interpretCall(FD, E)) {
     C.cleanup();
@@ -99,12 +102,42 @@ bool Context::evaluateAsRValue(State &Parent, const Expr 
*E, APValue &Result) {
   return true;
 }
 
-bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
-                       ConstantExprKind Kind) {
+bool Context::evaluateAsRValue(const EvalSettings &Settings, const Expr *E,
+                               APValue &Result) {
   ++EvalID;
   bool Recursing = !Stk.empty();
   size_t StackSizeBefore = Stk.size();
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc, Kind);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
+
+  auto Res = C.interpretExpr(E);
+
+  if (Res.isInvalid()) {
+    C.cleanup();
+    Stk.clearTo(StackSizeBefore);
+    return false;
+  }
+
+  if (!Recursing) {
+    // We *can* actually get here with a non-empty stack, since
+    // things like InterpState::noteSideEffect() exist.
+    C.cleanup();
+#ifndef NDEBUG
+    // Make sure we don't rely on some value being still alive in
+    // InterpStack memory.
+    Stk.clearTo(StackSizeBefore);
+#endif
+  }
+
+  Result = Res.stealAPValue();
+  return true;
+}
+
+bool Context::evaluate(const EvalSettings &Settings, const Expr *E,
+                       APValue &Result, ConstantExprKind Kind) {
+  ++EvalID;
+  bool Recursing = !Stk.empty();
+  size_t StackSizeBefore = Stk.size();
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc, Kind);
 
   auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
                              /*DestroyToplevelScope=*/true);
@@ -128,12 +161,13 @@ bool Context::evaluate(State &Parent, const Expr *E, 
APValue &Result,
   return true;
 }
 
-bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
-                                    const Expr *Init, APValue &Result) {
+bool Context::evaluateAsInitializer(const EvalSettings &Settings,
+                                    const VarDecl *VD, const Expr *Init,
+                                    APValue &Result) {
   ++EvalID;
   bool Recursing = !Stk.empty();
   size_t StackSizeBefore = Stk.size();
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
 
   bool CheckGlobalInitialized =
       (VD->getType()->isRecordType() || VD->getType()->isArrayType());
@@ -160,10 +194,10 @@ bool Context::evaluateAsInitializer(State &Parent, const 
VarDecl *VD,
   return true;
 }
 
-bool Context::evaluateDestruction(State &Parent, const VarDecl *VD,
-                                  APValue Value) {
+bool Context::evaluateDestruction(const EvalSettings &Settings,
+                                  const VarDecl *VD, APValue Value) {
   assert(Stk.empty());
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
 
   auto Res = C.interpretDestructor(VD, Value);
 
@@ -186,14 +220,15 @@ void Context::registerRedecl(const VarDecl *VD, const 
APValue &V) {
 }
 
 template <typename ResultT>
-bool Context::evaluateStringRepr(State &Parent, const Expr *SizeExpr,
-                                 const Expr *PtrExpr, ResultT &Result) {
+bool Context::evaluateStringRepr(const EvalSettings &Settings,
+                                 const Expr *SizeExpr, const Expr *PtrExpr,
+                                 ResultT &Result) {
   assert(Stk.empty());
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
 
   // Evaluate size value.
   APValue SizeValue;
-  if (!evaluateAsRValue(Parent, SizeExpr, SizeValue))
+  if (!evaluateAsRValue(Settings, SizeExpr, SizeValue))
     return false;
 
   if (!SizeValue.isInt())
@@ -269,26 +304,28 @@ bool Context::evaluateStringRepr(State &Parent, const 
Expr *SizeExpr,
   return true;
 }
 
-bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
-                                const Expr *PtrExpr, APValue &Result) {
+bool Context::evaluateCharRange(const EvalSettings &Settings,
+                                const Expr *SizeExpr, const Expr *PtrExpr,
+                                APValue &Result) {
   assert(SizeExpr);
   assert(PtrExpr);
 
-  return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
+  return evaluateStringRepr(Settings, SizeExpr, PtrExpr, Result);
 }
 
-bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
-                                const Expr *PtrExpr, std::string &Result) {
+bool Context::evaluateCharRange(const EvalSettings &Settings,
+                                const Expr *SizeExpr, const Expr *PtrExpr,
+                                std::string &Result) {
   assert(SizeExpr);
   assert(PtrExpr);
 
-  return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
+  return evaluateStringRepr(Settings, SizeExpr, PtrExpr, Result);
 }
 
-bool Context::evaluateString(State &Parent, const Expr *E,
+bool Context::evaluateString(const EvalSettings &Settings, const Expr *E,
                              std::string &Result) {
   assert(Stk.empty());
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
 
   auto PtrRes = C.interpretAsPointer(E, [&](InterpState &S, CodePtr OpPC,
                                             const Pointer &Ptr) {
@@ -350,9 +387,10 @@ bool Context::evaluateString(State &Parent, const Expr *E,
   return true;
 }
 
-std::optional<uint64_t> Context::evaluateStrlen(State &Parent, const Expr *E) {
+std::optional<uint64_t> Context::evaluateStrlen(const EvalSettings &Settings,
+                                                const Expr *E) {
   assert(Stk.empty());
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
 
   std::optional<uint64_t> Result;
   auto PtrRes = C.interpretAsPointer(E, [&](InterpState &S, CodePtr OpPC,
@@ -416,12 +454,11 @@ std::optional<uint64_t> Context::evaluateStrlen(State 
&Parent, const Expr *E) {
   return Result;
 }
 
-std::optional<uint64_t> Context::tryEvaluateObjectSize(State &Parent,
-                                                       const Expr *E,
-                                                       unsigned Kind,
-                                                       bool IsDynamic) {
+std::optional<uint64_t>
+Context::tryEvaluateObjectSize(const EvalSettings &Settings, const Expr *E,
+                               unsigned Kind, bool IsDynamic) {
   assert(Stk.empty());
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
 
   std::optional<uint64_t> Result;
   auto PtrRes = C.interpretAsLValuePointer(E, [&](InterpState &S, CodePtr OpPC,
@@ -448,17 +485,16 @@ std::optional<uint64_t> 
Context::tryEvaluateObjectSize(State &Parent,
   return Result;
 }
 
-std::optional<bool>
-Context::evaluateWithSubstitution(State &Parent, const FunctionDecl *Callee,
-                                  ArrayRef<const Expr *> Args, const Expr 
*This,
-                                  const Expr *Condition) {
+std::optional<bool> Context::evaluateWithSubstitution(
+    const EvalSettings &Settings, const FunctionDecl *Callee,
+    ArrayRef<const Expr *> Args, const Expr *This, const Expr *Condition) {
   if (OptPrimType ConditionT = classify(Condition);
       !ConditionT || ConditionT != PT_Bool) {
     return std::nullopt;
   }
 
   assert(Stk.empty());
-  Compiler<EvalEmitter> C(*this, *P, Parent, Stk, FrameAlloc);
+  Compiler<EvalEmitter> C(*this, *P, Settings, Stk, FrameAlloc);
   std::optional<bool> Result =
       C.interpretWithSubstitutions(Callee, Args, This, Condition);
 
@@ -599,9 +635,9 @@ const llvm::fltSemantics 
&Context::getFloatSemantics(QualType T) const {
   return Ctx.getFloatTypeSemantics(T);
 }
 
-bool Context::Run(State &Parent, const Function *Func) {
+bool Context::Run(const EvalSettings &Settings, const Function *Func) {
   auto Memory = std::make_unique<char[]>(InterpFrame::allocSize(Func));
-  InterpState State(Parent, *P, Stk, FrameAlloc, *this, Func);
+  InterpState State(Settings, *P, Stk, FrameAlloc, *this, Func);
   InterpFrame *Frame = new (Memory.get()) InterpFrame(
       State, Func, /*Caller=*/nullptr, CodePtr(), Func->getArgSize());
   State.Current = Frame;
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index 1390bc280602e4..0565322d3f4e33 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -32,6 +32,7 @@ class Function;
 class Program;
 class State;
 enum PrimType : uint8_t;
+struct EvalSettings;
 
 struct ParamOffset {
   unsigned Offset;
@@ -54,37 +55,46 @@ class Context final {
   ~Context();
 
   /// Checks if a function is a potential constant expression.
-  bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FD);
-  void isPotentialConstantExprUnevaluated(State &Parent, const Expr *E,
+  bool isPotentialConstantExpr(const EvalSettings &Settings,
+                               const FunctionDecl *FD);
+  void isPotentialConstantExprUnevaluated(const EvalSettings &Settings,
+                                          const Expr *E,
                                           const FunctionDecl *FD);
 
   /// Evaluates a toplevel expression as an rvalue.
+  // FIXME: Get rid of the version using a parent State.
   bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
+  bool evaluateAsRValue(const EvalSettings &Settings, const Expr *E,
+                        APValue &Result);
 
   /// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue 
conversion.
-  bool evaluate(State &Parent, const Expr *E, APValue &Result,
+  // FIXME: Remove the Kind parameter, it's already in Settings.
+  bool evaluate(const EvalSettings &Settings, const Expr *E, APValue &Result,
                 ConstantExprKind Kind);
 
   /// Evaluates a toplevel initializer.
-  bool evaluateAsInitializer(State &Parent, const VarDecl *VD, const Expr 
*Init,
-                             APValue &Result);
+  bool evaluateAsInitializer(const EvalSettings &Settings, const VarDecl *VD,
+                             const Expr *Init, APValue &Result);
   void registerRedecl(const VarDecl *VD, const APValue &V);
 
   /// Evaluates the destruction of a variable.
-  bool evaluateDestruction(State &Parent, const VarDecl *VD, APValue Value);
+  bool evaluateDestruction(const EvalSettings &Settings, const VarDecl *VD,
+                           APValue Value);
 
-  bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
+  bool evaluateCharRange(const EvalSettings &Settings, const Expr *SizeExpr,
                          const Expr *PtrExpr, APValue &Result);
-  bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
+  bool evaluateCharRange(const EvalSettings &Settings, const Expr *SizeExpr,
                          const Expr *PtrExpr, std::string &Result);
 
   /// Evaluate \param E and if it can be evaluated to a null-terminated string,
   /// copy the result into \param Result.
-  bool evaluateString(State &Parent, const Expr *E, std::string &Result);
+  bool evaluateString(const EvalSettings &Settings, const Expr *E,
+                      std::string &Result);
 
   /// Evalute \param E and if it can be evaluated to a string literal,
   /// run strlen() on it.
-  std::optional<uint64_t> evaluateStrlen(State &Parent, const Expr *E);
+  std::optional<uint64_t> evaluateStrlen(const EvalSettings &Settings,
+                                         const Expr *E);
 
   /// If \param E evaluates to a pointer the number of accessible bytes
   /// past the pointer is estimated in \param Result as if evaluated by
@@ -96,10 +106,11 @@ class Context final {
   /// as the one referred to by E are considered, when Kind & 1 == 0
   /// bytes belonging to the same storage (stack, heap allocation,
   /// global variable) are considered.
-  std::optional<uint64_t> tryEvaluateObjectSize(State &Parent, const Expr *E,
-                                                unsigned Kind, bool IsDynamic);
+  std::optional<uint64_t> tryEvaluateObjectSize(const EvalSettings &Settings,
+                                                const Expr *E, unsigned Kind,
+                                                bool IsDynamic);
 
-  std::optional<bool> evaluateWithSubstitution(State &Parent,
+  std::optional<bool> evaluateWithSubstitution(const EvalSettings &Settings,
                                                const FunctionDecl *Callee,
                                                ArrayRef<const Expr *> Args,
                                                const Expr *This,
@@ -192,10 +203,10 @@ class Context final {
 private:
   friend class EvalIDScope;
   /// Runs a function.
-  bool Run(State &Parent, const Function *Func);
+  bool Run(const EvalSettings &Settings, const Function *Func);
 
   template <typename ResultT>
-  bool evaluateStringRepr(State &Parent, const Expr *SizeExpr,
+  bool evaluateStringRepr(const EvalSettings &Settings, const Expr *SizeExpr,
                           const Expr *PtrExpr, ResultT &Result);
 
   /// Current compilation context.
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp 
b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index ec7550eb4cc17a..caa7f4b28ddd81 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -23,6 +23,12 @@ EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State 
&Parent,
     : Ctx(Ctx), P(P), S(Parent, P, Stk, FA, Ctx, this), EvalResult(Ctx),
       ConstexprKind(ConstexprKind) {}
 
+EvalEmitter::EvalEmitter(Context &Ctx, Program &P, const EvalSettings 
&Settings,
+                         InterpStack &Stk, FrameAllocator &FA,
+                         ConstantExprKind ConstexprKind)
+    : Ctx(Ctx), P(P), S(Settings, P, Stk, FA, Ctx, this), EvalResult(Ctx),
+      ConstexprKind(ConstexprKind) {}
+
 EvalEmitter::EvalEmitter(Context &Ctx, Program &P, Expr::EvalStatus &Status,
                          InterpStack &Stk, FrameAllocator &FA)
     : Ctx(Ctx), P(P), S(Status, P, Stk, FA, Ctx, this), EvalResult(Ctx) {}
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h 
b/clang/lib/AST/ByteCode/EvalEmitter.h
index 70ad775e84f81c..8a4312bad5c589 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.h
+++ b/clang/lib/AST/ByteCode/EvalEmitter.h
@@ -74,6 +74,9 @@ class EvalEmitter : public SourceMapper {
   EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk,
               FrameAllocator &FrameAlloc,
               ConstantExprKind ConstexprKind = ConstantExprKind::Normal);
+  EvalEmitter(Context &Ctx, Program &P, const EvalSettings &Settings,
+              InterpStack &Stk, FrameAllocator &FrameAlloc,
+              ConstantExprKind ConstexprKind = ConstantExprKind::Normal);
 
   EvalEmitter(Context &Ctx, Program &P, Expr::EvalStatus &Status,
               InterpStack &Stk, FrameAllocator &FrameAlloc);
diff --git a/clang/lib/AST/ByteCode/EvalSettings.h 
b/clang/lib/AST/ByteCode/EvalSettings.h
new file mode 100644
index 00000000000000..df4dcda515ded2
--- /dev/null
+++ b/clang/lib/AST/ByteCode/EvalSettings.h
@@ -0,0 +1,35 @@
+//===--------------------------- EvalSettings.h -----------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_INTERP_EVALSETTINGS_H
+#define LLVM_CLANG_AST_INTERP_EVALSETTINGS_H
+
+#include "State.h"
+
+namespace clang {
+namespace interp {
+
+struct EvalSettings {
+  Expr::EvalStatus &EvalStatus;
+  const EvaluationMode EvalMode;
+  const ConstantExprKind ConstexprKind;
+
+  bool InConstantContext = false;
+  bool CheckingPotentialConstantExpression = false;
+  bool CheckingForUndefinedBehavior = false;
+
+  EvalSettings(EvaluationMode EvalMode, Expr::EvalStatus &EvalStatus,
+               ConstantExprKind ConstexprKind = ConstantExprKind::Normal)
+      : EvalStatus(EvalStatus), EvalMode(EvalMode),
+        ConstexprKind(ConstexprKind) {}
+};
+
+} // namespace interp
+} // namespace clang
+
+#endif
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp 
b/clang/lib/AST/ByteCode/InterpState.cpp
index 7d0364fa7d10d8..e69880d9e1a87e 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -7,6 +7,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "InterpState.h"
+#include "EvalSettings.h"
 #include "InterpFrame.h"
 #include "InterpStack.h"
 #include "Program.h"
@@ -30,19 +31,32 @@ InterpState::InterpState(const State &Parent, Program &P, 
InterpStack &Stk,
   CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
   EvalMode = Parent.EvalMode;
 }
+InterpState::InterpState(const EvalSettings &Settings, Program &P,
+                         InterpStack &Stk, FrameAllocator &FrameAlloc,
+                         Context &Ctx, SourceMapper *M)
+    : State(Ctx.getASTContext(), Settings.EvalStatus), M(M),
+      FrameAlloc(FrameAlloc), P(P), Stk(Stk), Ctx(Ctx), BottomFrame(*this),
+      Current(&BottomFrame), StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
+      InfiniteSteps(StepsLeft == 0), EvalID(Ctx.getEvalID()) {
+  InConstantContext = Settings.InConstantContext;
+  CheckingPotentialConstantExpression =
+      Settings.CheckingPotentialConstantExpression;
+  CheckingForUndefinedBehavior = Settings.CheckingForUndefinedBehavior;
+  EvalMode = Settings.EvalMode;
+}
 
-InterpState::InterpState(const State &Parent, Program &P, InterpStack &Stk,
-                         FrameAllocator &FrameAlloc, Context &Ctx,
-                         const Function *Func)
-    : State(Ctx.getASTContext(), Parent.getEvalStatus()), M(nullptr),
+InterpState::InterpState(const EvalSettings &Settings, Program &P,
+                         InterpStack &Stk, FrameAllocator &FrameAlloc,
+                         Context &Ctx, const Function *Func)
+    : State(Ctx.getASTContext(), Settings.EvalStatus), M(nullptr),
       FrameAlloc(FrameAlloc), P(P), Stk(Stk), Ctx(Ctx), BottomFrame(*this),
       Current(&BottomFrame), StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
       InfiniteSteps(StepsLeft == 0), EvalID(Ctx.getEvalID()) {
-  InConstantContext = Parent.InConstantContext;
+  InConstantContext = Settings.InConstantContext;
   CheckingPotentialConstantExpression =
-      Parent.CheckingPotentialConstantExpression;
-  CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
-  EvalMode = Parent.EvalMode;
+      Settings.CheckingPotentialConstantExpression;
+  CheckingForUndefinedBehavior = Settings.CheckingForUndefinedBehavior;
+  EvalMode = Settings.EvalMode;
 }
 
 InterpState::InterpState(Expr::EvalStatus &Status, Program &P, InterpStack 
&Stk,
diff --git a/clang/lib/AST/ByteCode/InterpState.h 
b/clang/lib/AST/ByteCode/InterpState.h
index b4f89e9583d972..eeb010ed216496 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -27,6 +27,7 @@ namespace clang {
 namespace interp {
 class Context;
 class SourceMapper;
+struct EvalSettings;
 
 struct StdAllocatorCaller {
 
@@ -48,8 +49,11 @@ class InterpState final : public State {
   InterpState(const State &Parent, Program &P, InterpStack &Stk,
               FrameAllocator &FrameAlloc, Context &Ctx,
               SourceMapper *M = nullptr);
+  InterpState(const EvalSettings &Settings, Program &P, InterpStack &Stk,
+              FrameAllocator &FrameAlloc, Context &Ctx,
+              SourceMapper *M = nullptr);
 
-  InterpState(const State &Parent, Program &P, InterpStack &Stk,
+  InterpState(const EvalSettings &Settings, Program &P, InterpStack &Stk,
               FrameAllocator &FA, Context &Ctx, const Function *Func);
 
   InterpState(Expr::EvalStatus &Status, Program &P, InterpStack &Stk,
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index dea859382918b0..e90f86e6279856 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -33,6 +33,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "ByteCode/Context.h"
+#include "ByteCode/EvalSettings.h"
 #include "ByteCode/Frame.h"
 #include "ByteCode/State.h"
 #include "ExprConstShared.h"
@@ -22001,16 +22002,19 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const 
ASTContext &Ctx,
          "Expression evaluator can't be called on a dependent expression.");
 
   ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsLValue");
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantFold, Result);
+    Settings.InConstantContext = InConstantContext;
+    return Ctx.getInterpContext().evaluate(Settings, this, Result.Val,
+                                           ConstantExprKind::Normal);
+  }
+
   EvalInfo Info(Ctx, Result, EvaluationMode::ConstantFold);
   Info.InConstantContext = InConstantContext;
   LValue LV;
   CheckedTemporaries CheckedTemps;
 
-  if (Info.EnableNewConstInterp) {
-    return Info.Ctx.getInterpContext().evaluate(Info, this, Result.Val,
-                                                ConstantExprKind::Normal);
-  }
-
   if (!EvaluateLValue(this, LV, Info) || !Info.discardCleanups() ||
       Result.HasSideEffects ||
       !CheckLValueConstantExpression(Info, getExprLoc(),
@@ -22056,13 +22060,16 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, 
const ASTContext &Ctx,
     return true;
 
   ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsConstantExpr");
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantExpression, Result);
+    Settings.InConstantContext = true;
+    return Ctx.getInterpContext().evaluate(Settings, this, Result.Val, Kind);
+  }
+
   EvaluationMode EM = EvaluationMode::ConstantExpression;
   EvalInfo Info(Ctx, Result, EM);
   Info.InConstantContext = true;
 
-  if (Info.EnableNewConstInterp)
-    return Info.Ctx.getInterpContext().evaluate(Info, this, Result.Val, Kind);
-
   // The type of the object we're initializing is 'const T' for a class NTTP.
   QualType T = getType();
   if (Kind == ConstantExprKind::ClassTemplateArgument)
@@ -22122,6 +22129,21 @@ bool Expr::EvaluateAsInitializer(const ASTContext 
&Ctx, const VarDecl *VD,
     return Name;
   });
 
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(
+        (IsConstantInitialization &&
+         (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23))
+            ? EvaluationMode::ConstantExpression
+            : EvaluationMode::ConstantFold,
+        EStatus);
+    Settings.InConstantContext = IsConstantInitialization;
+    return Ctx.getInterpContext().evaluateAsInitializer(Settings, VD, this,
+                                                        EStatus.Val);
+  }
+
+  SourceLocation DeclLoc = VD->getLocation();
+  QualType DeclTy = VD->getType();
+
   EvalInfo Info(Ctx, EStatus,
                 (IsConstantInitialization &&
                  (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23))
@@ -22130,14 +22152,6 @@ bool Expr::EvaluateAsInitializer(const ASTContext 
&Ctx, const VarDecl *VD,
   Info.setEvaluatingDecl(VD, EStatus.Val);
   Info.InConstantContext = IsConstantInitialization;
 
-  SourceLocation DeclLoc = VD->getLocation();
-  QualType DeclTy = VD->getType();
-
-  if (Info.EnableNewConstInterp) {
-    auto &InterpCtx = Ctx.getInterpContext();
-    return InterpCtx.evaluateAsInitializer(Info, VD, this, EStatus.Val);
-  }
-
   LValue LVal;
   LVal.set(VD);
 
@@ -22202,11 +22216,12 @@ bool VarDecl::evaluateDestruction(
     return false;
 
   if (Ctx.getLangOpts().EnableNewConstInterp) {
-    EvalInfo Info(Ctx, EStatus,
-                  IsConstantDestruction ? EvaluationMode::ConstantExpression
-                                        : EvaluationMode::ConstantFold);
-    Info.InConstantContext = IsConstantDestruction;
-    if (!Ctx.getInterpContext().evaluateDestruction(Info, this,
+    interp::EvalSettings Settings(IsConstantDestruction
+                                      ? EvaluationMode::ConstantExpression
+                                      : EvaluationMode::ConstantFold,
+                                  EStatus);
+    Settings.InConstantContext = IsConstantDestruction;
+    if (!Ctx.getInterpContext().evaluateDestruction(Settings, this,
                                                     std::move(DestroyedValue)))
       return false;
     ensureEvaluatedStmt()->HasConstantDestruction = true;
@@ -22905,19 +22920,23 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, 
ASTContext &Ctx,
   });
 
   Expr::EvalStatus Status;
-  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpressionUnevaluated);
-  Info.InConstantContext = true;
 
-  if (Info.EnableNewConstInterp) {
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    auto Settings = interp::EvalSettings(
+        EvaluationMode::ConstantExpressionUnevaluated, Status);
+    Settings.InConstantContext = true;
     if (std::optional<bool> BoolResult =
-            Info.Ctx.getInterpContext().evaluateWithSubstitution(
-                Info, Callee, Args, This, this)) {
+            Ctx.getInterpContext().evaluateWithSubstitution(Settings, Callee,
+                                                            Args, This, this)) 
{
       Value = APValue(APSInt(APInt(1, static_cast<uint64_t>(*BoolResult))));
       return true;
     }
     return false;
   }
 
+  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpressionUnevaluated);
+  Info.InConstantContext = true;
+
   LValue ThisVal;
   const LValue *ThisPtr = nullptr;
   if (This) {
@@ -22988,20 +23007,23 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl 
*FD,
     return Name;
   });
 
+  const ASTContext &Ctx = FD->getASTContext();
   Expr::EvalStatus Status;
   Status.Diag = &Diags;
 
-  EvalInfo Info(FD->getASTContext(), Status,
-                EvaluationMode::ConstantExpression);
-  Info.InConstantContext = true;
-  Info.CheckingPotentialConstantExpression = true;
-
   // The constexpr VM attempts to compile all methods to bytecode here.
-  if (Info.EnableNewConstInterp) {
-    Info.Ctx.getInterpContext().isPotentialConstantExpr(Info, FD);
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantExpression, Status);
+    Settings.InConstantContext = true;
+    Settings.CheckingPotentialConstantExpression = true;
+    Ctx.getInterpContext().isPotentialConstantExpr(Settings, FD);
     return Diags.empty();
   }
 
+  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression);
+  Info.InConstantContext = true;
+  Info.CheckingPotentialConstantExpression = true;
+
   const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
   const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr;
 
@@ -23038,19 +23060,23 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
   assert(!E->isValueDependent() &&
          "Expression evaluator can't be called on a dependent expression.");
 
+  const ASTContext &Ctx = FD->getASTContext();
   Expr::EvalStatus Status;
   Status.Diag = &Diags;
 
-  EvalInfo Info(FD->getASTContext(), Status,
-                EvaluationMode::ConstantExpressionUnevaluated);
-  Info.InConstantContext = true;
-  Info.CheckingPotentialConstantExpression = true;
-
-  if (Info.EnableNewConstInterp) {
-    Info.Ctx.getInterpContext().isPotentialConstantExprUnevaluated(Info, E, 
FD);
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings 
Settings(EvaluationMode::ConstantExpressionUnevaluated,
+                                  Status);
+    Settings.InConstantContext = true;
+    Settings.CheckingPotentialConstantExpression = true;
+    Ctx.getInterpContext().isPotentialConstantExprUnevaluated(Settings, E, FD);
     return Diags.empty();
   }
 
+  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpressionUnevaluated);
+  Info.InConstantContext = true;
+  Info.CheckingPotentialConstantExpression = true;
+
   // Fabricate a call stack frame to give the arguments a plausible cover 
story.
   CallStackFrame Frame(Info, SourceLocation(), FD, /*This=*/nullptr,
                        /*CallExpr=*/nullptr, CallRef());
@@ -23066,12 +23092,13 @@ std::optional<uint64_t> 
Expr::tryEvaluateObjectSize(const ASTContext &Ctx,
     return std::nullopt;
 
   Expr::EvalStatus Status;
-  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
-  if (Info.EnableNewConstInterp)
-    return Info.Ctx.getInterpContext().tryEvaluateObjectSize(
-        Info, this, Type,
-        /*IsDynamic=*/false);
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantFold, Status);
+    return Ctx.getInterpContext().tryEvaluateObjectSize(Settings, this, Type,
+                                                        /*IsDynamic=*/false);
+  }
 
+  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
   return tryEvaluateBuiltinObjectSize(this, Type, Info);
 }
 
@@ -23122,15 +23149,16 @@ EvaluateBuiltinStrLen(const Expr *E, EvalInfo &Info,
 
 std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const {
   Expr::EvalStatus Status;
-  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
   std::string StringResult;
 
-  if (Info.EnableNewConstInterp) {
-    if (!Info.Ctx.getInterpContext().evaluateString(Info, this, StringResult))
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantFold, Status);
+    if (!Ctx.getInterpContext().evaluateString(Settings, this, StringResult))
       return std::nullopt;
     return StringResult;
   }
 
+  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
   if (EvaluateBuiltinStrLen(this, Info, &StringResult))
     return StringResult;
   return std::nullopt;
@@ -23142,13 +23170,16 @@ static bool EvaluateCharRangeAsStringImpl(const Expr 
*, T &Result,
                                           const Expr *PtrExpression,
                                           ASTContext &Ctx,
                                           Expr::EvalResult &Status) {
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantExpression, Status);
+    Settings.InConstantContext = true;
+    return Ctx.getInterpContext().evaluateCharRange(Settings, SizeExpression,
+                                                    PtrExpression, Result);
+  }
+
   EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression);
   Info.InConstantContext = true;
 
-  if (Info.EnableNewConstInterp)
-    return Info.Ctx.getInterpContext().evaluateCharRange(Info, SizeExpression,
-                                                         PtrExpression, 
Result);
-
   LValue String;
   FullExpressionRAII Scope(Info);
   APSInt SizeValue;
@@ -23210,10 +23241,12 @@ bool Expr::EvaluateCharRangeAsString(APValue &Result,
 
 std::optional<uint64_t> Expr::tryEvaluateStrLen(const ASTContext &Ctx) const {
   Expr::EvalStatus Status;
-  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
 
-  if (Info.EnableNewConstInterp)
-    return Info.Ctx.getInterpContext().evaluateStrlen(Info, this);
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantFold, Status);
+    return Ctx.getInterpContext().evaluateStrlen(Settings, this);
+  }
+  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
   return EvaluateBuiltinStrLen(this, Info);
 }
 

>From a42fa447c80f1b55ed2bc50900165d297f3454e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Thu, 24 Sep 2026 16:22:09 +0200
Subject: [PATCH 2/2] Direct eval in accessor

---
 clang/lib/AST/ExprConstant.cpp | 143 ++++++++++++++++++++++++++++-----
 1 file changed, 123 insertions(+), 20 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index e90f86e6279856..726e9edf73639f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -780,10 +780,6 @@ namespace {
     /// we will evaluate.
     unsigned StepsLeft;
 
-    /// Enable the experimental new constant interpreter. If an expression is
-    /// not supported by the interpreter, an error is triggered.
-    bool EnableNewConstInterp;
-
     /// BottomFrame - The frame in which evaluation started. This must be
     /// initialized after CurrentCall and CallStackDepth.
     CallStackFrame BottomFrame;
@@ -888,7 +884,6 @@ namespace {
         : State(const_cast<ASTContext &>(C), S), CurrentCall(nullptr),
           CallStackDepth(0), NextCallIndex(1),
           StepsLeft(C.getLangOpts().ConstexprStepLimit),
-          EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp),
           BottomFrame(*this, SourceLocation(), /*Callee=*/nullptr,
                       /*This=*/nullptr,
                       /*CallExpr=*/nullptr, CallRef()),
@@ -21799,6 +21794,7 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo 
&Info, const LValue &This,
 /// lvalue-to-rvalue cast if it is an lvalue.
 static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
   assert(!E->isValueDependent());
+  assert(!Info.Ctx.getLangOpts().EnableNewConstInterp);
 
   if (E->getType().isNull())
     return false;
@@ -21806,9 +21802,6 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr 
*E, APValue &Result) {
   if (!CheckLiteralType(Info, E))
     return false;
 
-  if (Info.EnableNewConstInterp)
-    return Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result);
-
   if (!::Evaluate(Result, Info, E))
     return false;
 
@@ -21939,6 +21932,17 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const 
ASTContext &Ctx,
   assert(!isValueDependent() &&
          "Expression evaluator can't be called on a dependent expression.");
   ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsRValue");
+
+  bool IsConst;
+  if (FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst))
+    return IsConst;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::IgnoreSideEffects, Result);
+    Settings.InConstantContext = InConstantContext;
+    return Ctx.getInterpContext().evaluateAsRValue(Settings, this, Result.Val);
+  }
+
   EvalInfo Info(Ctx, Result, EvaluationMode::IgnoreSideEffects);
   Info.InConstantContext = InConstantContext;
   return ::EvaluateAsRValue(this, Result, Ctx, Info);
@@ -21959,7 +21963,28 @@ bool Expr::EvaluateAsInt(EvalResult &Result, const 
ASTContext &Ctx,
                          bool InConstantContext) const {
   assert(!isValueDependent() &&
          "Expression evaluator can't be called on a dependent expression.");
+
   ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsInt");
+
+  if (!getType()->isIntegralOrEnumerationType())
+    return false;
+
+  bool IsConst;
+  if (FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst))
+    return IsConst;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::IgnoreSideEffects, Result);
+    Settings.InConstantContext = InConstantContext;
+    if (!Ctx.getInterpContext().evaluateAsRValue(Settings, this, Result.Val))
+      return false;
+
+    if (!Result.Val.isInt() ||
+        hasUnacceptableSideEffect(Result, AllowSideEffects))
+      return false;
+    return true;
+  }
+
   EvalInfo Info(Ctx, Result, EvaluationMode::IgnoreSideEffects);
   Info.InConstantContext = InConstantContext;
   return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info);
@@ -21971,6 +21996,24 @@ bool Expr::EvaluateAsFixedPoint(EvalResult &Result, 
const ASTContext &Ctx,
   assert(!isValueDependent() &&
          "Expression evaluator can't be called on a dependent expression.");
   ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsFixedPoint");
+
+  if (!getType()->isFixedPointType())
+    return false;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::IgnoreSideEffects, Result);
+    Settings.InConstantContext = InConstantContext;
+
+    if (!Ctx.getInterpContext().evaluateAsRValue(Settings, this, Result.Val))
+      return false;
+
+    if (!Result.Val.isFixedPoint() ||
+        hasUnacceptableSideEffect(Result, AllowSideEffects))
+      return false;
+
+    return true;
+  }
+
   EvalInfo Info(Ctx, Result, EvaluationMode::IgnoreSideEffects);
   Info.InConstantContext = InConstantContext;
   return ::EvaluateAsFixedPoint(this, Result, Ctx, AllowSideEffects, Info);
@@ -22254,6 +22297,18 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext 
&Ctx) const {
 
   ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateKnownConstInt");
   EvalResult EVResult;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::IgnoreSideEffects, EVResult);
+    Settings.InConstantContext = true;
+    [[maybe_unused]] bool Result =
+        Ctx.getInterpContext().evaluateAsRValue(Settings, this, EVResult.Val);
+    assert(Result && "Could not evaluate expression");
+    assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
+
+    return EVResult.Val.getInt();
+  }
+
   EvalInfo Info(Ctx, EVResult, EvaluationMode::IgnoreSideEffects);
   Info.InConstantContext = true;
 
@@ -22273,6 +22328,19 @@ APSInt Expr::EvaluateKnownConstIntCheckOverflow(
   ExprTimeTraceScope TimeScope(this, Ctx, 
"EvaluateKnownConstIntCheckOverflow");
   EvalResult EVResult;
   EVResult.Diag = Diag;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::IgnoreSideEffects, EVResult);
+    Settings.InConstantContext = true;
+    Settings.CheckingForUndefinedBehavior = true;
+    [[maybe_unused]] bool Result =
+        Ctx.getInterpContext().evaluateAsRValue(Settings, this, EVResult.Val);
+    assert(Result && "Could not evaluate expression");
+    assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
+
+    return EVResult.Val.getInt();
+  }
+
   EvalInfo Info(Ctx, EVResult, EvaluationMode::IgnoreSideEffects);
   Info.InConstantContext = true;
   Info.CheckingForUndefinedBehavior = true;
@@ -22292,11 +22360,19 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) 
const {
   ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateForOverflow");
   bool IsConst;
   EvalResult EVResult;
-  if (!FastEvaluateAsRValue(this, EVResult.Val, Ctx, IsConst)) {
-    EvalInfo Info(Ctx, EVResult, EvaluationMode::IgnoreSideEffects);
-    Info.CheckingForUndefinedBehavior = true;
-    (void)::EvaluateAsRValue(Info, this, EVResult.Val);
+  if (FastEvaluateAsRValue(this, EVResult.Val, Ctx, IsConst))
+    return;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::IgnoreSideEffects, EVResult);
+    Settings.CheckingForUndefinedBehavior = true;
+    (void)Ctx.getInterpContext().evaluateAsRValue(Settings, this, 
EVResult.Val);
+    return;
   }
+
+  EvalInfo Info(Ctx, EVResult, EvaluationMode::IgnoreSideEffects);
+  Info.CheckingForUndefinedBehavior = true;
+  (void)::EvaluateAsRValue(Info, this, EVResult.Val);
 }
 
 bool Expr::EvalResult::isGlobalLValue() const {
@@ -22346,6 +22422,16 @@ static ICEDiag Worst(ICEDiag A, ICEDiag B) { return 
A.Kind >= B.Kind ? A : B; }
 
 static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) {
   Expr::EvalResult EVResult;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantExpression, 
EVResult);
+    Settings.InConstantContext = true;
+    if (!Ctx.getInterpContext().evaluateAsRValue(Settings, E, EVResult.Val) ||
+        EVResult.HasSideEffects || !EVResult.Val.isInt())
+      return ICEDiag(IK_NotICE, E->getBeginLoc());
+    return NoDiag();
+  }
+
   Expr::EvalStatus Status;
   EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression);
 
@@ -22855,6 +22941,17 @@ Expr::getIntegerConstantExpr(const ASTContext &Ctx,
   // required to treat the expression as an ICE, so we produce the folded
   // value.
   EvalResult ExprResult;
+
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::IgnoreSideEffects,
+                                  ExprResult);
+    Settings.InConstantContext = true;
+    if (!Ctx.getInterpContext().evaluateAsRValue(Settings, this,
+                                                 ExprResult.Val))
+      llvm_unreachable("ICE cannot be evaluated!");
+    return ExprResult.Val.getInt();
+  }
+
   Expr::EvalStatus Status;
   EvalInfo Info(Ctx, Status, EvaluationMode::IgnoreSideEffects);
   Info.InConstantContext = true;
@@ -22889,18 +22986,24 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, 
APValue *Result,
     return true;
   }
 
-  // Build evaluation settings.
+  bool IsConstExpr;
   Expr::EvalStatus Status;
-  EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression);
   SmallVector<PartialDiagnosticAt> MSRelaxedDiag;
   Status.ExtendedDiag = AllowRelaxedEval ? &MSRelaxedDiag : nullptr;
 
-  bool IsConstExpr =
-      ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) &&
-      // NOTE: We don't produce a diagnostic for this, but the callers that
-      // call us on arbitrary full-expressions should generally not care.
-      Info.discardCleanups() && !Status.HasSideEffects;
-
+  if (Ctx.getLangOpts().EnableNewConstInterp) {
+    interp::EvalSettings Settings(EvaluationMode::ConstantExpression, Status);
+    IsConstExpr = Ctx.getInterpContext().evaluateAsRValue(
+        Settings, this, Result ? *Result : Scratch);
+  } else {
+    // Build evaluation settings.
+    EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression);
+    IsConstExpr =
+        ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) &&
+        // NOTE: We don't produce a diagnostic for this, but the callers that
+        // call us on arbitrary full-expressions should generally not care.
+        Info.discardCleanups() && !Status.HasSideEffects;
+  }
   return IsConstExpr && !Status.DiagEmitted;
 }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to