diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index bdf648110..7a717e879 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -48,6 +48,7 @@ struct ForwardTraversal { bool check = false; bool escape = false; bool escapeUnknown = false; + bool active = false; bool isEscape() const { return escape || escapeUnknown; } @@ -628,9 +629,11 @@ struct ForwardTraversal { // Traverse then block thenBranch.escape = isEscapeScope(endBlock, thenBranch.escapeUnknown); if (thenBranch.check) { + thenBranch.active = true; if (updateRange(endCond->next(), endBlock, depth - 1) == Progress::Break) return Break(); } else if (!elseBranch.check) { + thenBranch.active = true; if (checkBranch(thenBranch)) bail = true; } @@ -638,10 +641,12 @@ struct ForwardTraversal { if (hasElse) { elseBranch.escape = isEscapeScope(endBlock->linkAt(2), elseBranch.escapeUnknown); if (elseBranch.check) { + elseBranch.active = true; Progress result = updateRange(endBlock->tokAt(2), endBlock->linkAt(2), depth - 1); if (result == Progress::Break) return Break(); } else if (!thenBranch.check) { + elseBranch.active = true; if (checkBranch(elseBranch)) bail = true; } @@ -649,7 +654,10 @@ struct ForwardTraversal { } else { tok = endBlock; } - actions |= (thenBranch.action | elseBranch.action); + if (thenBranch.active) + actions |= thenBranch.action; + if (elseBranch.active) + actions |= elseBranch.action; if (bail) return Break(Analyzer::Terminate::Bail); if (thenBranch.isDead() && elseBranch.isDead()) { @@ -660,7 +668,7 @@ struct ForwardTraversal { return Break(Analyzer::Terminate::Bail); } // Conditional return - if (thenBranch.isEscape() && !hasElse) { + if (thenBranch.active && thenBranch.isEscape() && !hasElse) { if (!thenBranch.isConclusiveEscape()) { if (!analyzer->lowerToInconclusive()) return Break(Analyzer::Terminate::Bail); diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 7cde18eab..11f33779f 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -122,6 +122,7 @@ private: TEST_CASE(nullpointer80); // #10410 TEST_CASE(nullpointer81); // #8724 TEST_CASE(nullpointer82); // #10331 + TEST_CASE(nullpointer83); // #9870 TEST_CASE(nullpointer_addressOf); // address of TEST_CASE(nullpointerSwitch); // #2626 TEST_CASE(nullpointer_cast); // #4692 @@ -2495,6 +2496,21 @@ private: ASSERT_EQUALS("", errout.str()); } + void nullpointer83() // #9870 + { + check("int* qux();\n" + "int* f7c2(int *x) {\n" + " int* p = 0;\n" + " if (nullptr == x)\n" + " p = qux();\n" + " if (nullptr == x)\n" + " return x;\n" + " *p = 1;\n" + " return x;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:8]: (warning) Possible null pointer dereference: p\n", errout.str()); + } + void nullpointer_addressOf() { // address of check("void f() {\n" " struct X *x = 0;\n"