1212#include < tuple>
1313#include < utility>
1414
15+ struct OnExit {
16+ std::function<void ()> f;
17+
18+ ~OnExit () {
19+ f ();
20+ }
21+ };
22+
1523struct ForwardTraversal {
1624 enum class Progress { Continue, Break, Skip };
1725 enum class Terminate { None, Bail, Escape, Modified, Inconclusive, Conditional };
@@ -25,6 +33,7 @@ struct ForwardTraversal {
2533 bool analyzeTerminate;
2634 Analyzer::Terminate terminate = Analyzer::Terminate::None;
2735 bool forked = false ;
36+ std::vector<Token*> loopEnds = {};
2837
2938 Progress Break (Analyzer::Terminate t = Analyzer::Terminate::None) {
3039 if ((!analyzeOnly || analyzeTerminate) && t != Analyzer::Terminate::None)
@@ -85,9 +94,15 @@ struct ForwardTraversal {
8594
8695 template <class T , REQUIRES(" T must be a Token class" , std::is_convertible<T*, const Token*> )>
8796 Progress traverseTok (T* tok, std::function<Progress(T*)> f, bool traverseUnknown, T** out = nullptr) {
88- if (Token::Match (tok, " asm|goto|continue|setjmp|longjmp" ))
89- return Break ();
90- else if (Token::Match (tok, " return|throw" ) || isEscapeFunction (tok, &settings->library )) {
97+ if (Token::Match (tok, " asm|goto|setjmp|longjmp" ))
98+ return Break (Analyzer::Terminate::Bail);
99+ else if (Token::simpleMatch (tok, " continue" )) {
100+ if (loopEnds.empty ())
101+ return Break (Analyzer::Terminate::Escape);
102+ // If we are in a loop then jump to the end
103+ if (out)
104+ *out = loopEnds.back ();
105+ } else if (Token::Match (tok, " return|throw" ) || isEscapeFunction (tok, &settings->library )) {
91106 traverseRecursive (tok->astOperand1 (), f, traverseUnknown);
92107 traverseRecursive (tok->astOperand2 (), f, traverseUnknown);
93108 return Break (Analyzer::Terminate::Escape);
@@ -361,6 +376,10 @@ struct ForwardTraversal {
361376 }
362377
363378 Progress updateInnerLoop (Token* endBlock, Token* stepTok, Token* condTok) {
379+ loopEnds.push_back (endBlock);
380+ OnExit oe{[&] {
381+ loopEnds.pop_back ();
382+ }};
364383 if (endBlock && updateScope (endBlock) == Progress::Break)
365384 return Break ();
366385 if (stepTok && updateRecursive (stepTok) == Progress::Break)
@@ -632,7 +651,7 @@ struct ForwardTraversal {
632651 }
633652 actions |= (thenBranch.action | elseBranch.action );
634653 if (bail)
635- return Break ();
654+ return Break (Analyzer::Terminate::Bail );
636655 if (thenBranch.isDead () && elseBranch.isDead ()) {
637656 if (thenBranch.isModified () && elseBranch.isModified ())
638657 return Break (Analyzer::Terminate::Modified);
0 commit comments