ValueFlow: handle x+=y for containers
This commit is contained in:
parent
b998dcb5aa
commit
06ede9c239
|
@ -3481,7 +3481,7 @@ static void valueFlowContainerReverse(const Token *tok, unsigned int containerId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowContainerForward(const Token *tok, unsigned int containerId, const ValueFlow::Value &value, const Settings *settings, bool cpp)
|
static void valueFlowContainerForward(const Token *tok, unsigned int containerId, ValueFlow::Value value, const Settings *settings, bool cpp)
|
||||||
{
|
{
|
||||||
while (nullptr != (tok = tok->next())) {
|
while (nullptr != (tok = tok->next())) {
|
||||||
if (Token::Match(tok, "[{}]"))
|
if (Token::Match(tok, "[{}]"))
|
||||||
|
@ -3490,6 +3490,25 @@ static void valueFlowContainerForward(const Token *tok, unsigned int containerId
|
||||||
continue;
|
continue;
|
||||||
if (Token::Match(tok, "%name% ="))
|
if (Token::Match(tok, "%name% ="))
|
||||||
break;
|
break;
|
||||||
|
if (Token::Match(tok, "%name% +=")) {
|
||||||
|
if (!tok->valueType() || !tok->valueType()->container || !tok->valueType()->container->stdStringLike)
|
||||||
|
break;
|
||||||
|
const Token *rhs = tok->next()->astOperand2();
|
||||||
|
if (rhs->tokType() == Token::eString)
|
||||||
|
value.intvalue += Token::getStrLength(rhs);
|
||||||
|
else if (rhs->valueType() && rhs->valueType()->container && rhs->valueType()->container->stdStringLike) {
|
||||||
|
bool found = false;
|
||||||
|
for (const ValueFlow::Value &rhsval : rhs->values()) {
|
||||||
|
if (rhsval.isKnown() && rhsval.isContainerSizeValue()) {
|
||||||
|
value.intvalue += rhsval.intvalue;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (isLikelyStreamRead(cpp, tok->astParent()))
|
if (isLikelyStreamRead(cpp, tok->astParent()))
|
||||||
break;
|
break;
|
||||||
if (isContainerSizeChangedByFunction(tok))
|
if (isContainerSizeChangedByFunction(tok))
|
||||||
|
|
|
@ -3384,6 +3384,20 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3));
|
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3));
|
||||||
|
|
||||||
|
code = "void f() {\n"
|
||||||
|
" std::string s=\"abc\";\n" // size of s is 3
|
||||||
|
" s += unknown;\n"
|
||||||
|
" s.size();\n"
|
||||||
|
"}";
|
||||||
|
ASSERT(tokenValues(code, "s . size").empty());
|
||||||
|
|
||||||
|
code = "void f() {\n"
|
||||||
|
" std::string s=\"abc\";\n" // size of s is 3
|
||||||
|
" s += \"def\";\n" // size of s => 6
|
||||||
|
" s.size();\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 6));
|
||||||
|
|
||||||
// valueFlowContainerForward, function call
|
// valueFlowContainerForward, function call
|
||||||
code = "void f() {\n"
|
code = "void f() {\n"
|
||||||
" std::list<int> x;\n"
|
" std::list<int> x;\n"
|
||||||
|
|
Loading…
Reference in New Issue