diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 19cd196df..f6fbbf949 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -284,6 +284,10 @@ struct ForwardTraversal { return Token::findsimplematch(endBlock->link(), "goto", endBlock); } + bool hasJump(const Token* endBlock) { + return Token::findmatch(endBlock->link(), "goto|break", endBlock); + } + bool hasInnerReturnScope(const Token* start, const Token* end) const { for (const Token* tok=start; tok != end; tok = tok->previous()) { if (Token::simpleMatch(tok, "}")) { @@ -404,7 +408,7 @@ struct ForwardTraversal { bool checkElse = false; if (condTok && !Token::simpleMatch(condTok, ":")) std::tie(checkThen, checkElse) = evalCond(condTok, isDoWhile ? endBlock->previous() : nullptr); - if (checkElse && exit) + if (checkElse && exit && !hasJump(endBlock)) return Progress::Continue; Analyzer::Action bodyAnalysis = analyzeScope(endBlock); Analyzer::Action allAnalysis = bodyAnalysis; @@ -417,7 +421,7 @@ struct ForwardTraversal { allAnalysis |= analyzeRecursive(stepTok); actions |= allAnalysis; // do while(false) is not really a loop - if (checkElse && isDoWhile && + if (checkElse && isDoWhile && !hasJump(endBlock) && (condTok->hasKnownIntValue() || (!bodyAnalysis.isModified() && !condAnalysis.isModified() && condAnalysis.isRead()))) { if (updateRange(endBlock->link(), endBlock) == Progress::Break) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 8d66c8e2e..50fde0d5a 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -4211,6 +4211,19 @@ private: " return bFirst;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("void f() {\n" + " void * pool = NULL;\n" + " do {\n" + " pool = malloc(40);\n" + " if (dostuff())\n" + " break;\n" + " pool = NULL;\n" + " }\n" + " while (0);\n" + " if (pool) {}\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void alwaysTrueTryCatch()