llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> This only calls `noteStep()` on jump opcodes, so this works for loops. It does not prevent "hangs" when a function is just _very_ long (could be interesting how this interfaces with expand statements?). Fixes https://github.com/llvm/llvm-project/issues/165951 --- Full diff: https://github.com/llvm/llvm-project/pull/176150.diff 4 Files Affected: - (modified) clang/lib/AST/ByteCode/Interp.cpp (+3-3) - (modified) clang/lib/AST/ByteCode/InterpState.cpp (+11) - (modified) clang/lib/AST/ByteCode/InterpState.h (+5) - (added) clang/test/AST/ByteCode/constexpr-steps.cpp (+10) ``````````diff diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 0205d840fd71e..cff8f6c83cd68 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -38,21 +38,21 @@ static bool RetValue(InterpState &S, CodePtr &Pt) { static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) { PC += Offset; - return true; + return S.noteStep(PC); } static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) { if (S.Stk.pop<bool>()) { PC += Offset; } - return true; + return S.noteStep(PC); } static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) { if (!S.Stk.pop<bool>()) { PC += Offset; } - return true; + return S.noteStep(PC); } // https://github.com/llvm/llvm-project/issues/102513 diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp index a95916cd63981..20207b9337e02 100644 --- a/clang/lib/AST/ByteCode/InterpState.cpp +++ b/clang/lib/AST/ByteCode/InterpState.cpp @@ -26,6 +26,7 @@ InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk, Parent.CheckingPotentialConstantExpression; CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior; EvalMode = Parent.EvalMode; + StepsLeft = Ctx.getLangOpts().ConstexprStepLimit; } InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk, @@ -38,6 +39,7 @@ InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk, Parent.CheckingPotentialConstantExpression; CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior; EvalMode = Parent.EvalMode; + StepsLeft = Ctx.getLangOpts().ConstexprStepLimit; } bool InterpState::inConstantContext() const { @@ -153,3 +155,12 @@ StdAllocatorCaller InterpState::getStdAllocatorCaller(StringRef Name) const { return {}; } + +bool InterpState::noteStep(CodePtr OpPC) { + --StepsLeft; + if (StepsLeft != 0) + return true; + + FFDiag(Current->getSource(OpPC), diag::note_constexpr_step_limit_exceeded); + return false; +} diff --git a/clang/lib/AST/ByteCode/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h index e2e4d5c985f93..197ea2b138e05 100644 --- a/clang/lib/AST/ByteCode/InterpState.h +++ b/clang/lib/AST/ByteCode/InterpState.h @@ -153,6 +153,10 @@ class InterpState final : public State, public SourceMapper { return Floating(Mem, llvm::APFloatBase::SemanticsToEnum(Sem)); } + /// Note that a step has been executed. If there are no more steps remaining, + /// diagnoses and returns \c false. + bool noteStep(CodePtr OpPC); + private: friend class EvaluationResult; friend class InterpStateCCOverride; @@ -184,6 +188,7 @@ class InterpState final : public State, public SourceMapper { SmallVectorImpl<PartialDiagnosticAt> *PrevDiags = nullptr; unsigned SpeculationDepth = 0; std::optional<bool> ConstantContextOverride; + unsigned StepsLeft; llvm::SmallVector< std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>> diff --git a/clang/test/AST/ByteCode/constexpr-steps.cpp b/clang/test/AST/ByteCode/constexpr-steps.cpp new file mode 100644 index 0000000000000..490425107a140 --- /dev/null +++ b/clang/test/AST/ByteCode/constexpr-steps.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s -fconstexpr-steps=100 + + +constexpr int foo() { // expected-error {{never produces a constant expression}} + while (1) {} // expected-note 2{{constexpr evaluation hit maximum step limit}} + return 0; +} +static_assert (foo() == 0, ""); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to}} + `````````` </details> https://github.com/llvm/llvm-project/pull/176150 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
