[clang] [clang][bytecode] Enter a non-constant context when revisiting (PR #136104)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 17 01:04:31 PDT 2025
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/136104
Otherwise, things like __builtin_is_constant_evaluated() return the wrong value.
>From d55ada6a4b88db3579570a4f1fbd43ae38a715b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 17 Apr 2025 09:38:57 +0200
Subject: [PATCH] [clang][bytecode] Enter a non-constant context when
revisiting
Otherwise, things like __builtin_is_constant_evaluated() return
the wrong value.
---
clang/lib/AST/ByteCode/Compiler.cpp | 5 +++++
clang/lib/AST/ByteCode/Interp.h | 9 +++++++++
clang/lib/AST/ByteCode/InterpState.h | 2 +-
clang/lib/AST/ByteCode/Opcodes.td | 3 +++
clang/test/AST/ByteCode/builtin-constant-p.cpp | 8 ++++++++
5 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 157e306e5cdb3..bdff40c57b0e1 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(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..bca87fc937f9f 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) {
+ S.ConstantContextOverride = false;
+ 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..01e4aefdaffe0 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;
+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));
+}
More information about the cfe-commits
mailing list