Skip to content

Commit 90ddb54

Browse files
authored
[clang][bytecode] Enter a non-constant context when revisiting (#136104)
Otherwise, things like __builtin_is_constant_evaluated() return the wrong value.
1 parent d69ee88 commit 90ddb54

File tree

5 files changed

+26
-1
lines changed

5 files changed

+26
-1
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6466,8 +6466,13 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
64666466

64676467
// In case we need to re-visit a declaration.
64686468
auto revisit = [&](const VarDecl *VD) -> bool {
6469+
if (!this->emitPushCC(VD->hasConstantInitialization(), E))
6470+
return false;
64696471
auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);
64706472

6473+
if (!this->emitPopCC(E))
6474+
return false;
6475+
64716476
if (VarState.notCreated())
64726477
return true;
64736478
if (!VarState)

clang/lib/AST/ByteCode/Interp.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2848,6 +2848,15 @@ inline bool EndSpeculation(InterpState &S, CodePtr OpPC) {
28482848
return true;
28492849
}
28502850

2851+
inline bool PushCC(InterpState &S, CodePtr OpPC, bool Value) {
2852+
S.ConstantContextOverride = Value;
2853+
return true;
2854+
}
2855+
inline bool PopCC(InterpState &S, CodePtr OpPC) {
2856+
S.ConstantContextOverride = std::nullopt;
2857+
return true;
2858+
}
2859+
28512860
/// Do nothing and just abort execution.
28522861
inline bool Error(InterpState &S, CodePtr OpPC) { return false; }
28532862

clang/lib/AST/ByteCode/InterpState.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ class InterpState final : public State, public SourceMapper {
127127
SourceMapper *M;
128128
/// Allocator used for dynamic allocations performed via the program.
129129
DynamicAllocator Alloc;
130-
std::optional<bool> ConstantContextOverride;
131130

132131
public:
133132
/// Reference to the module containing all bytecode.
@@ -147,6 +146,7 @@ class InterpState final : public State, public SourceMapper {
147146
/// Things needed to do speculative execution.
148147
SmallVectorImpl<PartialDiagnosticAt> *PrevDiags = nullptr;
149148
unsigned SpeculationDepth = 0;
149+
std::optional<bool> ConstantContextOverride;
150150

151151
llvm::SmallVector<
152152
std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,3 +872,6 @@ def GetTypeidPtr : Opcode { let Args = [ArgTypePtr]; }
872872
def DiagTypeid : Opcode;
873873

874874
def CheckDestruction : Opcode;
875+
876+
def PushCC : Opcode { let Args = [ArgBool]; }
877+
def PopCC : Opcode;

clang/test/AST/ByteCode/builtin-constant-p.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,11 @@ constexpr int mutate6(bool mutate) {
121121
static_assert(mutate6(false) == 11);
122122
static_assert(mutate6(true) == 21); // ref-error {{static assertion failed}} \
123123
// ref-note {{evaluates to '10 == 21'}}
124+
125+
#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
126+
void g() {
127+
/// f will be revisited when evaluating the static_assert, since it's
128+
/// a local variable. But it should be visited in a non-constant context.
129+
const float f = __builtin_is_constant_evaluated();
130+
static_assert(fold(f == 0.0f));
131+
}

0 commit comments

Comments
 (0)