[clang] dcaab6d - [clang][bytecode] Add source info to jump ops (#188003)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 23 03:45:39 PDT 2026
Author: Timm Baeder
Date: 2026-03-23T11:45:34+01:00
New Revision: dcaab6dd99a33edbf98ad1ade0ea0d196b797910
URL: https://github.com/llvm/llvm-project/commit/dcaab6dd99a33edbf98ad1ade0ea0d196b797910
DIFF: https://github.com/llvm/llvm-project/commit/dcaab6dd99a33edbf98ad1ade0ea0d196b797910.diff
LOG: [clang][bytecode] Add source info to jump ops (#188003)
The attached test case otherwise results in a function with one jump op
but no source info at all.
Added:
Modified:
clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
clang/lib/AST/ByteCode/ByteCodeEmitter.h
clang/lib/AST/ByteCode/Compiler.cpp
clang/lib/AST/ByteCode/Compiler.h
clang/lib/AST/ByteCode/EvalEmitter.cpp
clang/lib/AST/ByteCode/EvalEmitter.h
clang/test/AST/ByteCode/constexpr-steps.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index c08ccf69aef85..393b8481fecd1 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -221,16 +221,16 @@ bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &...Args, SourceInfo SI) {
return Success;
}
-bool ByteCodeEmitter::jumpTrue(const LabelTy &Label) {
- return emitJt(getOffset(Label), SourceInfo{});
+bool ByteCodeEmitter::jumpTrue(const LabelTy &Label, SourceInfo SI) {
+ return emitJt(getOffset(Label), SI);
}
-bool ByteCodeEmitter::jumpFalse(const LabelTy &Label) {
- return emitJf(getOffset(Label), SourceInfo{});
+bool ByteCodeEmitter::jumpFalse(const LabelTy &Label, SourceInfo SI) {
+ return emitJf(getOffset(Label), SI);
}
-bool ByteCodeEmitter::jump(const LabelTy &Label) {
- return emitJmp(getOffset(Label), SourceInfo{});
+bool ByteCodeEmitter::jump(const LabelTy &Label, SourceInfo SI) {
+ return emitJmp(getOffset(Label), SI);
}
bool ByteCodeEmitter::fallthrough(const LabelTy &Label) {
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.h b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
index 873edeea71d96..102ce939c6717 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.h
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
@@ -52,9 +52,9 @@ class ByteCodeEmitter {
virtual bool emitBool(bool V, const Expr *E) = 0;
/// Emits jumps.
- bool jumpTrue(const LabelTy &Label);
- bool jumpFalse(const LabelTy &Label);
- bool jump(const LabelTy &Label);
+ bool jumpTrue(const LabelTy &Label, SourceInfo SI);
+ bool jumpFalse(const LabelTy &Label, SourceInfo SI);
+ bool jump(const LabelTy &Label, SourceInfo SI);
bool fallthrough(const LabelTy &Label);
/// Speculative execution.
bool speculate(const CallExpr *E, const LabelTy &EndLabel);
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 5e029643fb0d4..642a59cf75642 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1344,12 +1344,12 @@ bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
if (!this->visitBool(LHS))
return false;
- if (!this->jumpTrue(LabelTrue))
+ if (!this->jumpTrue(LabelTrue, E))
return false;
if (!this->visitBool(RHS))
return false;
- if (!this->jump(LabelEnd))
+ if (!this->jump(LabelEnd, E))
return false;
this->emitLabel(LabelTrue);
@@ -1366,12 +1366,12 @@ bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
if (!this->visitBool(LHS))
return false;
- if (!this->jumpFalse(LabelFalse))
+ if (!this->jumpFalse(LabelFalse, E))
return false;
if (!this->visitBool(RHS))
return false;
- if (!this->jump(LabelEnd))
+ if (!this->jump(LabelEnd, E))
return false;
this->emitLabel(LabelFalse);
@@ -2836,12 +2836,12 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
return false;
}
- if (!this->jumpFalse(LabelFalse))
+ if (!this->jumpFalse(LabelFalse, E))
return false;
if (!this->delegate(TrueExpr))
return false;
- if (!this->jump(LabelEnd))
+ if (!this->jump(LabelEnd, E))
return false;
this->emitLabel(LabelFalse);
if (!this->delegate(FalseExpr))
@@ -4031,7 +4031,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
return false;
if (!this->emitEQPtr(E))
return false;
- if (!this->jumpTrue(EndLabel))
+ if (!this->jumpTrue(EndLabel, E))
return false;
}
@@ -4052,7 +4052,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
return false;
if (!this->emitLT(SizeT, E))
return false;
- if (!this->jumpFalse(EndLabel))
+ if (!this->jumpFalse(EndLabel, E))
return false;
// Pointer to the allocated array is already on the stack.
@@ -4101,7 +4101,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
if (!this->emitIncPop(SizeT, false, E))
return false;
- if (!this->jump(StartLabel))
+ if (!this->jump(StartLabel, E))
return false;
this->fallthrough(EndLabel);
@@ -6080,11 +6080,11 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
if (const Stmt *Else = IS->getElse()) {
LabelTy LabelElse = this->getLabel();
LabelTy LabelEnd = this->getLabel();
- if (!this->jumpFalse(LabelElse))
+ if (!this->jumpFalse(LabelElse, IS))
return false;
if (!visitChildStmt(IS->getThen()))
return false;
- if (!this->jump(LabelEnd))
+ if (!this->jump(LabelEnd, IS))
return false;
this->emitLabel(LabelElse);
if (!visitChildStmt(Else))
@@ -6092,7 +6092,7 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
this->emitLabel(LabelEnd);
} else {
LabelTy LabelEnd = this->getLabel();
- if (!this->jumpFalse(LabelEnd))
+ if (!this->jumpFalse(LabelEnd, IS))
return false;
if (!visitChildStmt(IS->getThen()))
return false;
@@ -6132,7 +6132,7 @@ bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
return false;
- if (!this->jumpFalse(EndLabel))
+ if (!this->jumpFalse(EndLabel, S))
return false;
if (!this->visitStmt(Body))
@@ -6142,7 +6142,7 @@ bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
return false;
// } End of loop body.
- if (!this->jump(CondLabel))
+ if (!this->jump(CondLabel, S))
return false;
this->fallthrough(EndLabel);
this->emitLabel(EndLabel);
@@ -6175,7 +6175,7 @@ template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
if (!CondScope.destroyLocals())
return false;
}
- if (!this->jumpTrue(StartLabel))
+ if (!this->jumpTrue(StartLabel, S))
return false;
this->fallthrough(EndLabel);
@@ -6213,7 +6213,7 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
if (Cond) {
if (!this->visitBool(Cond))
return false;
- if (!this->jumpFalse(EndLabel))
+ if (!this->jumpFalse(EndLabel, S))
return false;
}
if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
@@ -6229,7 +6229,7 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
if (!CondScope.destroyLocals())
return false;
- if (!this->jump(CondLabel))
+ if (!this->jump(CondLabel, S))
return false;
// } End of loop body.
@@ -6270,7 +6270,7 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
this->emitLabel(CondLabel);
if (!this->visitBool(Cond))
return false;
- if (!this->jumpFalse(EndLabel))
+ if (!this->jumpFalse(EndLabel, S))
return false;
if (!this->visitDeclStmt(S->getLoopVarStmt(), /*EvaluateConditionDecl=*/true))
@@ -6287,7 +6287,7 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
return false;
}
- if (!this->jump(CondLabel))
+ if (!this->jump(CondLabel, S))
return false;
this->fallthrough(EndLabel);
@@ -6332,7 +6332,7 @@ bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
return false;
}
- return this->jump(*TargetLabel);
+ return this->jump(*TargetLabel, S);
}
template <class Emitter>
@@ -6369,7 +6369,7 @@ bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
return false;
}
- return this->jump(*TargetLabel);
+ return this->jump(*TargetLabel, S);
}
template <class Emitter>
@@ -6424,7 +6424,7 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
PrimType LT = this->classifyPrim(Low->getType());
if (!this->emitGE(LT, S))
return false;
- if (!this->jumpFalse(EndOfRangeCheck))
+ if (!this->jumpFalse(EndOfRangeCheck, S))
return false;
if (!this->emitGetLocal(CondT, CondVar, CS))
@@ -6434,7 +6434,7 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
PrimType HT = this->classifyPrim(High->getType());
if (!this->emitLE(HT, S))
return false;
- if (!this->jumpTrue(CaseLabels[CS]))
+ if (!this->jumpTrue(CaseLabels[CS], S))
return false;
this->emitLabel(EndOfRangeCheck);
continue;
@@ -6454,7 +6454,7 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
// Compare and jump to the case label.
if (!this->emitEQ(ValueT, S))
return false;
- if (!this->jumpTrue(CaseLabels[CS]))
+ if (!this->jumpTrue(CaseLabels[CS], S))
return false;
} else {
assert(!DefaultLabel);
@@ -6465,10 +6465,10 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
// If none of the conditions above were true, fall through to the default
// statement or jump after the switch statement.
if (DefaultLabel) {
- if (!this->jump(*DefaultLabel))
+ if (!this->jump(*DefaultLabel, S))
return false;
} else {
- if (!this->jump(EndLabel))
+ if (!this->jump(EndLabel, S))
return false;
}
@@ -7701,7 +7701,7 @@ bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {
// We now have the bool value of E[0] on the stack.
LabelTy LabelTrue = this->getLabel();
- if (!this->jumpTrue(LabelTrue))
+ if (!this->jumpTrue(LabelTrue, E))
return false;
if (!this->emitArrayElemPop(ElemT, 1, E))
@@ -7715,7 +7715,7 @@ bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {
}
// Leave the boolean value of E[1] on the stack.
LabelTy EndLabel = this->getLabel();
- this->jump(EndLabel);
+ this->jump(EndLabel, E);
this->emitLabel(LabelTrue);
if (!this->emitPopPtr(E))
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 717928dc1fbbd..f867fcc9fcbaa 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -597,7 +597,7 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
typename Emitter::LabelTy EndLabel = this->Ctx->getLabel();
if (!this->Ctx->emitGetLocalEnabled(Local.Offset, E))
return false;
- if (!this->Ctx->jumpFalse(EndLabel))
+ if (!this->Ctx->jumpFalse(EndLabel, E))
return false;
if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 1bc82b2ecab1a..3cfc1de1ff35e 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -125,25 +125,29 @@ Scope::Local EvalEmitter::createLocal(Descriptor *D) {
return {Off, D};
}
-bool EvalEmitter::jumpTrue(const LabelTy &Label) {
+bool EvalEmitter::jumpTrue(const LabelTy &Label, SourceInfo SI) {
if (isActive()) {
+ CurrentSource = SI;
if (S.Stk.pop<bool>())
ActiveLabel = Label;
}
return true;
}
-bool EvalEmitter::jumpFalse(const LabelTy &Label) {
+bool EvalEmitter::jumpFalse(const LabelTy &Label, SourceInfo SI) {
if (isActive()) {
+ CurrentSource = SI;
if (!S.Stk.pop<bool>())
ActiveLabel = Label;
}
return true;
}
-bool EvalEmitter::jump(const LabelTy &Label) {
- if (isActive())
+bool EvalEmitter::jump(const LabelTy &Label, SourceInfo SI) {
+ if (isActive()) {
+ CurrentSource = SI;
CurrentLabel = ActiveLabel = Label;
+ }
return true;
}
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h b/clang/lib/AST/ByteCode/EvalEmitter.h
index 3de12366a2b3d..8f6da7aef422a 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.h
+++ b/clang/lib/AST/ByteCode/EvalEmitter.h
@@ -68,9 +68,9 @@ class EvalEmitter : public SourceMapper {
virtual bool emitBool(bool V, const Expr *E) = 0;
/// Emits jumps.
- bool jumpTrue(const LabelTy &Label);
- bool jumpFalse(const LabelTy &Label);
- bool jump(const LabelTy &Label);
+ bool jumpTrue(const LabelTy &Label, SourceInfo SI);
+ bool jumpFalse(const LabelTy &Label, SourceInfo SI);
+ bool jump(const LabelTy &Label, SourceInfo SI);
bool fallthrough(const LabelTy &Label);
/// Speculative execution.
bool speculate(const CallExpr *E, const LabelTy &EndLabel);
diff --git a/clang/test/AST/ByteCode/constexpr-steps.cpp b/clang/test/AST/ByteCode/constexpr-steps.cpp
index 490425107a140..bd461547032a9 100644
--- a/clang/test/AST/ByteCode/constexpr-steps.cpp
+++ b/clang/test/AST/ByteCode/constexpr-steps.cpp
@@ -8,3 +8,10 @@ constexpr int foo() { // expected-error {{never produces a constant expression}}
static_assert (foo() == 0, ""); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to}}
+constexpr void addr() { // expected-error {{never produces a constant expression}}
+ for (;;) // expected-note 2{{constexpr evaluation hit maximum step limit}}
+ ;
+}
+static_assert((addr(), 1) == 1); // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to}}
+
More information about the cfe-commits
mailing list