valueFlowSizeForward: Bailout when function calls modify the container size

This commit is contained in:
Daniel Marjamäki 2018-08-13 06:54:18 +02:00
parent 183345a939
commit 55ab842083
2 changed files with 22 additions and 0 deletions

View File

@ -3456,6 +3456,16 @@ static bool hasContainerSizeGuard(const Token *tok, unsigned int containerId)
return false; return false;
} }
static bool isContainerSizeChangedByFunction(const Token *tok)
{
const Token *parent = tok->astParent();
if (parent && parent->str() == "&")
parent = parent->astParent();
while (parent && parent->str() == ",")
parent = parent->astParent();
return parent && Token::Match(parent->previous(), "%name% (");
}
static void valueFlowContainerReverse(const Token *tok, unsigned int containerId, const ValueFlow::Value &value, const Settings *settings) static void valueFlowContainerReverse(const Token *tok, unsigned int containerId, const ValueFlow::Value &value, const Settings *settings)
{ {
while (nullptr != (tok = tok->previous())) { while (nullptr != (tok = tok->previous())) {
@ -3465,6 +3475,8 @@ static void valueFlowContainerReverse(const Token *tok, unsigned int containerId
continue; continue;
if (Token::Match(tok, "%name% =")) if (Token::Match(tok, "%name% ="))
break; break;
if (isContainerSizeChangedByFunction(tok))
break;
if (!tok->valueType() || !tok->valueType()->container) if (!tok->valueType() || !tok->valueType()->container)
break; break;
if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION) if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION)
@ -3483,6 +3495,8 @@ static void valueFlowContainerForward(const Token *tok, unsigned int containerId
continue; continue;
if (Token::Match(tok, "%name% =")) if (Token::Match(tok, "%name% ="))
break; break;
if (isContainerSizeChangedByFunction(tok))
break;
if (!tok->valueType() || !tok->valueType()->container) if (!tok->valueType() || !tok->valueType()->container)
break; break;
if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION) if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION)

View File

@ -3343,6 +3343,14 @@ private:
" s.size();\n" " s.size();\n"
"}"; "}";
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3)); ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3));
// valueFlowContainerForward, function call
code = "void f() {\n"
" std::list<int> x;\n"
" f(x);\n"
" x.front();\n" // <- unknown container size
"}";
ASSERT(tokenValues(code, "x . front").empty());
} }
}; };