From b788e411913ff04ddf566fb352b5a67921c09f90 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Fri, 3 Sep 2021 16:07:08 -0500 Subject: [PATCH] Fix 10438: FP knownConditionTrueFalse after return in a catch clause (#3429) --- lib/forwardanalyzer.cpp | 20 ++++++++++++++++---- test/testcondition.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 3dc141508..529964df9 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -666,11 +666,23 @@ struct ForwardTraversal { } } else if (Token::simpleMatch(tok, "try {")) { Token* endBlock = tok->next()->link(); - Analyzer::Action a = analyzeScope(endBlock); - if (updateRange(tok->next(), endBlock, depth - 1) == Progress::Break) - return Break(); - if (a.isModified()) + ForwardTraversal tryTraversal = fork(); + tryTraversal.updateRange(tok->next(), endBlock, depth - 1); + bool bail = tryTraversal.actions.isModified(); + if (bail) analyzer->lowerToPossible(); + + while (Token::simpleMatch(endBlock, "} catch (")) { + Token* endCatch = endBlock->linkAt(2); + if (!Token::simpleMatch(endCatch, ") {")) + return Break(); + endBlock = endCatch->linkAt(1); + ForwardTraversal ft = fork(); + ft.updateRange(endBlock->link(), endBlock, depth - 1); + bail |= ft.terminate != Analyzer::Terminate::None || ft.actions.isModified(); + } + if (bail) + return Break(); tok = endBlock; } else if (Token::simpleMatch(tok, "do {")) { Token* endBlock = tok->next()->link(); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index c20921c51..587b4bfbb 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -119,6 +119,7 @@ private: TEST_CASE(alwaysTrueInfer); TEST_CASE(alwaysTrueContainer); TEST_CASE(alwaysTrueLoop); + TEST_CASE(alwaysTrueTryCatch); TEST_CASE(multiConditionAlwaysTrue); TEST_CASE(duplicateCondition); @@ -4079,6 +4080,44 @@ private: ASSERT_EQUALS("", errout.str()); } + void alwaysTrueTryCatch() + { + check("void g();\n" + "void f(int x)\n" + "{\n" + " if( x ) {\n" + " try {\n" + " g();\n" + " }\n" + " catch(...) {\n" + " return;\n" + " }\n" + " }\n" + " g();\n" + " if( x ) {\n" + " g();\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void g();\n" + "void h();\n" + "void f(int x) {\n" + " if( x ) {\n" + " try {\n" + " g();\n" + " return;\n" + " }\n" + " catch( ... ) {}\n" + " }\n" + " h();\n" + " if( x ) {\n" + " g();\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void multiConditionAlwaysTrue() { check("void f() {\n" " int val = 0;\n"