diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index f6fbbf949..67c48347d 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -408,8 +408,16 @@ struct ForwardTraversal { bool checkElse = false; if (condTok && !Token::simpleMatch(condTok, ":")) std::tie(checkThen, checkElse) = evalCond(condTok, isDoWhile ? endBlock->previous() : nullptr); - if (checkElse && exit && !hasJump(endBlock)) + // exiting a do while(false) + if (checkElse && exit) { + if (hasJump(endBlock)) { + if (!analyzer->lowerToPossible()) + return Break(Analyzer::Terminate::Bail); + if (analyzer->isConditional() && stopUpdates()) + return Break(Analyzer::Terminate::Conditional); + } return Progress::Continue; + } Analyzer::Action bodyAnalysis = analyzeScope(endBlock); Analyzer::Action allAnalysis = bodyAnalysis; Analyzer::Action condAnalysis; @@ -421,7 +429,7 @@ struct ForwardTraversal { allAnalysis |= analyzeRecursive(stepTok); actions |= allAnalysis; // do while(false) is not really a loop - if (checkElse && isDoWhile && !hasJump(endBlock) && + if (checkElse && isDoWhile && (condTok->hasKnownIntValue() || (!bodyAnalysis.isModified() && !condAnalysis.isModified() && condAnalysis.isRead()))) { if (updateRange(endBlock->link(), endBlock) == Progress::Break) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index e1c4e6111..04a902fbb 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -5112,6 +5112,23 @@ private: " return -1;\n" "}\n"); ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (error) Uninitialized variable: a\n", errout.str()); + + // #9772 + valueFlowUninit("int func(void) {\n" + " int rez;\n" + " struct sccb* ccb;\n" + " do {\n" + " if ((ccb = calloc(1, sizeof(*ccb))) == NULL) {\n" + " rez = 1;\n" + " break;\n" + " }\n" + " rez = 0;\n" + " } while (0);\n" + " if (rez != 0)\n" + " free(ccb);\n" + " return rez;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void valueFlowUninitBreak() { // Do not show duplicate warnings about the same uninitialized value