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
