diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f007bb814..b9dd9430e 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -231,6 +231,24 @@ static bool bailoutSelfAssignment(const Token * const tok) return false; } +static bool isReturn(const Token *tok) +{ + const Token *prev = tok ? tok->previous() : nullptr; + if (Token::simpleMatch(prev, "}") && Token::simpleMatch(prev->link()->tokAt(-2),"} else {")) + return isReturn(prev) && isReturn(prev->link()->tokAt(-2)); + if (Token::simpleMatch(prev, ";")) { + // noreturn function + if (Token::simpleMatch(prev->previous(), ") ;") && Token::Match(prev->linkAt(-1)->tokAt(-2), "[;{}] %var% (")) + return true; + // return statement + prev = prev->previous(); + while (prev && !Token::Match(prev,"[;{}]")) + prev = prev->previous(); + return Token::Match(prev, "[;{}] return"); + } + return false; +} + static bool isVariableChanged(const Token *start, const Token *end, const unsigned int varid) { for (const Token *tok = start; tok != end; tok = tok->next()) { @@ -1014,6 +1032,9 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg bailout(tokenlist, errorLogger, after, "possible noreturn scope"); continue; } + + bool isreturn = (codeblock == 1 && isReturn(after)); + if (Token::simpleMatch(after, "} else {")) { after = after->linkAt(2); if (Token::simpleMatch(after->tokAt(-2), ") ; }")) { @@ -1021,8 +1042,11 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg bailout(tokenlist, errorLogger, after, "possible noreturn scope"); continue; } + isreturn |= (codeblock == 2 && isReturn(after)); } - valueFlowForward(after->next(), top->scope()->classEnd, var, varid, values, true, tokenlist, errorLogger, settings); + + if (!isreturn) + valueFlowForward(after->next(), top->scope()->classEnd, var, varid, values, true, tokenlist, errorLogger, settings); } } } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 68d83e15e..ac5406503 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -998,6 +998,15 @@ private: TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, 0)); ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); + // stop at return + code = "void f(int x) {\n" + " if (x == 5) {\n" + " if (z) return; else return;\n" + " }\n" + " a = x;\n" + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 5U, 5)); + // TODO: float code = "void f(float x) {\n" " if (x == 0.5) {}\n"