diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 368ac761a53..c38d93155ea 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -834,8 +834,13 @@ namespace { ++ft.forkDepth; ft.updateRange(thenBranch.endBlock, end, depth - 1); } - if (pElse == Progress::Break) + if (pElse == Progress::Break) { + // Only the else branch escaped; the then branch falls through, so + // the scope as a whole does not always escape. + if (terminate == Analyzer::Terminate::Escape && !thenBranch.isEscape()) + terminate = Analyzer::Terminate::None; return Break(); + } } } } else if (Token::simpleMatch(tok, "try {")) { diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 837cd4e78ba..da4ecae43b3 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -4935,6 +4935,20 @@ class TestCondition : public TestFixture { " if (v > 0) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("bool f(int x) {\n" // only the innermost else escapes - x is 0 or >1 afterwards, not known + " if (!x) {}\n" + " else if (x > 1) {}\n" + " else return false;\n" + " return x ? false : true;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + check("bool f(int x) {\n" // the branch's fall-through path must clear the escape + " if (x) { if (x > 1) {} else return false; }\n" + " return x ? false : true;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void alwaysTrueSymbolic()