Author: Timm Baeder
Date: 2025-04-17T12:50:28+02:00
New Revision: 90ddb5444030b8d7cca6e91a27994e4fa9a6525d

URL: 
https://github.com/llvm/llvm-project/commit/90ddb5444030b8d7cca6e91a27994e4fa9a6525d
DIFF: 
https://github.com/llvm/llvm-project/commit/90ddb5444030b8d7cca6e91a27994e4fa9a6525d.diff

LOG: [clang][bytecode] Enter a non-constant context when revisiting (#136104)

Otherwise, things like __builtin_is_constant_evaluated() return the
wrong value.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Compiler.cpp
    clang/lib/AST/ByteCode/Interp.h
    clang/lib/AST/ByteCode/InterpState.h
    clang/lib/AST/ByteCode/Opcodes.td
    clang/test/AST/ByteCode/builtin-constant-p.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 157e306e5cdb3..d3eabc513a9ac 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -6466,8 +6466,13 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
 
   // In case we need to re-visit a declaration.
   auto revisit = [&](const VarDecl *VD) -> bool {
+    if (!this->emitPushCC(VD->hasConstantInitialization(), E))
+      return false;
     auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);
 
+    if (!this->emitPopCC(E))
+      return false;
+
     if (VarState.notCreated())
       return true;
     if (!VarState)

diff  --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index bd58c2a88e9d9..49e2326186bf8 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2848,6 +2848,15 @@ inline bool EndSpeculation(InterpState &S, CodePtr OpPC) 
{
   return true;
 }
 
+inline bool PushCC(InterpState &S, CodePtr OpPC, bool Value) {
+  S.ConstantContextOverride = Value;
+  return true;
+}
+inline bool PopCC(InterpState &S, CodePtr OpPC) {
+  S.ConstantContextOverride = std::nullopt;
+  return true;
+}
+
 /// Do nothing and just abort execution.
 inline bool Error(InterpState &S, CodePtr OpPC) { return false; }
 

diff  --git a/clang/lib/AST/ByteCode/InterpState.h 
b/clang/lib/AST/ByteCode/InterpState.h
index 74001b80d9c00..528c1a24e7b05 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -127,7 +127,6 @@ class InterpState final : public State, public SourceMapper 
{
   SourceMapper *M;
   /// Allocator used for dynamic allocations performed via the program.
   DynamicAllocator Alloc;
-  std::optional<bool> ConstantContextOverride;
 
 public:
   /// Reference to the module containing all bytecode.
@@ -147,6 +146,7 @@ class InterpState final : public State, public SourceMapper 
{
   /// Things needed to do speculative execution.
   SmallVectorImpl<PartialDiagnosticAt> *PrevDiags = nullptr;
   unsigned SpeculationDepth = 0;
+  std::optional<bool> ConstantContextOverride;
 
   llvm::SmallVector<
       std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>

diff  --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index 5a9079fea0846..8451e54ad0c41 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -872,3 +872,6 @@ def GetTypeidPtr : Opcode { let Args = [ArgTypePtr]; }
 def DiagTypeid : Opcode;
 
 def CheckDestruction : Opcode;
+
+def PushCC : Opcode { let Args = [ArgBool]; }
+def PopCC : Opcode;

diff  --git a/clang/test/AST/ByteCode/builtin-constant-p.cpp 
b/clang/test/AST/ByteCode/builtin-constant-p.cpp
index ed9e606ed16aa..f5b16761bfdc9 100644
--- a/clang/test/AST/ByteCode/builtin-constant-p.cpp
+++ b/clang/test/AST/ByteCode/builtin-constant-p.cpp
@@ -121,3 +121,11 @@ constexpr int mutate6(bool mutate) {
 static_assert(mutate6(false) == 11);
 static_assert(mutate6(true) == 21); // ref-error {{static assertion failed}} \
                                     // ref-note {{evaluates to '10 == 21'}}
+
+#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
+void g() {
+  /// f will be revisited when evaluating the static_assert, since it's
+  /// a local variable. But it should be visited in a non-constant context.
+  const float f = __builtin_is_constant_evaluated();
+  static_assert(fold(f == 0.0f));
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to