valueFlowContainerSize: Fix wrong value after condition if conditional code escapes

This commit is contained in:
Daniel Marjamäki 2018-08-11 13:49:42 +02:00
parent 1f427eda8f
commit 6008bbdfb4
2 changed files with 20 additions and 11 deletions

View File

@ -3465,7 +3465,7 @@ static void valueFlowContainerForward(const Token *tok, unsigned int containerId
}
}
static void valueFlowContainerSize(TokenList * /*tokenlist*/, SymbolDatabase* symboldatabase, ErrorLogger * /*errorLogger*/, const Settings *settings)
static void valueFlowContainerSize(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger * /*errorLogger*/, const Settings *settings)
{
for (const Scope &scope : symboldatabase->scopeList) {
if (scope.type != Scope::ScopeType::eIf) // TODO: while
@ -3504,10 +3504,13 @@ static void valueFlowContainerSize(TokenList * /*tokenlist*/, SymbolDatabase* sy
valueFlowContainerReverse(scope.classDef, tok->varId(), value, settings);
// possible value after condition
const Token *after = scope.bodyEnd;
if (Token::simpleMatch(after, "} else {"))
after = after->linkAt(2);
valueFlowContainerForward(after, tok->varId(), value, settings);
if (!isEscapeScope(scope.bodyStart, tokenlist)) {
const Token *after = scope.bodyEnd;
if (Token::simpleMatch(after, "} else {"))
after = isEscapeScope(after->tokAt(2), tokenlist) ? nullptr : after->linkAt(2);
if (after)
valueFlowContainerForward(after, tok->varId(), value, settings);
}
// known value in conditional code
if (conditionToken->str() == "==" || conditionToken->str() == "(") {

View File

@ -3276,26 +3276,26 @@ private:
// valueFlowContainerReverse
code = "void f(const std::list<int> &ints) {\n"
" ints.front();\n"
" ints.front();\n" // <- container can be empty
" if (ints.empty()) {}\n"
"}";
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
code = "void f(const std::list<int> &ints) {\n"
" ints.front();\n"
" ints.front();\n" // <- container can be empty
" if (ints.size()==0) {}\n"
"}";
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
code = "void f(std::list<int> ints) {\n"
" ints.front();\n"
" ints.front();\n" // <- no container size
" ints.pop_back();\n"
" if (ints.empty()) {}\n"
"}";
ASSERT(tokenValues(code, "ints . front").empty());
code = "void f(std::vector<int> v) {\n"
" v[10] = 0;\n"
" v[10] = 0;\n" // <- container size can be 10
" if (v.size() == 10) {}\n"
"}";
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "v ["), 10));
@ -3303,13 +3303,19 @@ private:
// valueFlowContainerForward
code = "void f(const std::list<int> &ints) {\n"
" if (ints.empty()) {}\n"
" ints.front();\n"
" ints.front();\n" // <- container can be empty
"}";
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
code = "void f(const std::list<int> &ints) {\n"
" if (ints.empty()) { continue; }\n"
" ints.front();\n" // <- no container size
"}";
ASSERT(tokenValues(code, "ints . front").empty());
code = "void f(const std::list<int> &ints) {\n"
" if (ints.empty()) {\n"
" ints.front();\n"
" ints.front();\n" // <- container is empty
" }\n"
"}";
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "ints . front"), 0));