valueFlowContainerSize: Fix FP when container size is changed
This commit is contained in:
parent
7074eeb869
commit
183345a939
|
@ -3492,6 +3492,38 @@ static void valueFlowContainerForward(const Token *tok, unsigned int containerId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isContainerSizeChanged(unsigned int varId, const Token *start, const Token *end)
|
||||||
|
{
|
||||||
|
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
||||||
|
if (tok->varId() != varId)
|
||||||
|
continue;
|
||||||
|
if (!tok->valueType() || !tok->valueType()->container)
|
||||||
|
return true;
|
||||||
|
if (Token::Match(tok, "%name% ="))
|
||||||
|
return true;
|
||||||
|
if (Token::Match(tok, "%name% . %name% (")) {
|
||||||
|
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
||||||
|
switch (action) {
|
||||||
|
case Library::Container::Action::RESIZE:
|
||||||
|
case Library::Container::Action::CLEAR:
|
||||||
|
case Library::Container::Action::PUSH:
|
||||||
|
case Library::Container::Action::POP:
|
||||||
|
case Library::Container::Action::CHANGE:
|
||||||
|
case Library::Container::Action::INSERT:
|
||||||
|
case Library::Container::Action::ERASE:
|
||||||
|
case Library::Container::Action::CHANGE_INTERNAL:
|
||||||
|
return true;
|
||||||
|
case Library::Container::Action::NO_ACTION: // might be unknown action
|
||||||
|
return true;
|
||||||
|
case Library::Container::Action::FIND:
|
||||||
|
case Library::Container::Action::CHANGE_CONTENT:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void valueFlowContainerSize(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger * /*errorLogger*/, const Settings *settings)
|
static void valueFlowContainerSize(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger * /*errorLogger*/, const Settings *settings)
|
||||||
{
|
{
|
||||||
// declaration
|
// declaration
|
||||||
|
@ -3565,7 +3597,7 @@ static void valueFlowContainerSize(TokenList *tokenlist, SymbolDatabase* symbold
|
||||||
const Token *after = scope.bodyEnd;
|
const Token *after = scope.bodyEnd;
|
||||||
if (Token::simpleMatch(after, "} else {"))
|
if (Token::simpleMatch(after, "} else {"))
|
||||||
after = isEscapeScope(after->tokAt(2), tokenlist) ? nullptr : after->linkAt(2);
|
after = isEscapeScope(after->tokAt(2), tokenlist) ? nullptr : after->linkAt(2);
|
||||||
if (after)
|
if (after && !isContainerSizeChanged(tok->varId(), scope.bodyStart, after))
|
||||||
valueFlowContainerForward(after, tok->varId(), value, settings);
|
valueFlowContainerForward(after, tok->varId(), value, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3313,6 +3313,12 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT(tokenValues(code, "ints . front").empty());
|
ASSERT(tokenValues(code, "ints . front").empty());
|
||||||
|
|
||||||
|
code = "void f(const std::list<int> &ints) {\n"
|
||||||
|
" if (ints.empty()) { ints.push_back(0); }\n"
|
||||||
|
" ints.front();\n" // <- container is not empty
|
||||||
|
"}";
|
||||||
|
ASSERT(tokenValues(code, "ints . front").empty());
|
||||||
|
|
||||||
code = "void f(const std::list<int> &ints) {\n"
|
code = "void f(const std::list<int> &ints) {\n"
|
||||||
" if (ints.empty()) {\n"
|
" if (ints.empty()) {\n"
|
||||||
" ints.front();\n" // <- container is empty
|
" ints.front();\n" // <- container is empty
|
||||||
|
|
Loading…
Reference in New Issue