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}}
+


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

Reply via email to