diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 11cb19d3a..7d85a71c4 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -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())) { if (Token::Match(tok, "[{}]")) @@ -3490,6 +3490,25 @@ static void valueFlowContainerForward(const Token *tok, unsigned int containerId continue; if (Token::Match(tok, "%name% =")) 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())) break; if (isContainerSizeChangedByFunction(tok)) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 991878015..8618fc328 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -3384,6 +3384,20 @@ private: "}"; 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 code = "void f() {\n" " std::list x;\n"