diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 7d85a71c4..8a3500772 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3598,26 +3598,31 @@ static void valueFlowContainerSize(TokenList *tokenlist, SymbolDatabase* symbold for (const Token *tok = scope.classDef; tok && tok->str() != "{"; tok = tok->next()) { if (!tok->isName() || !tok->valueType() || tok->valueType()->type != ValueType::CONTAINER || !tok->valueType()->container) continue; - if (!Token::Match(tok, "%name% . %name% (")) - continue; const Token *conditionToken; MathLib::bigint intval; - if (tok->valueType()->container->getYield(tok->strAt(2)) == Library::Container::Yield::SIZE) { - const Token *parent = tok->tokAt(3)->astParent(); - if (!parent || !parent->isComparisonOp() || !parent->astOperand2()) + if (Token::Match(tok, "%name% . %name% (")) { + if (tok->valueType()->container->getYield(tok->strAt(2)) == Library::Container::Yield::SIZE) { + const Token *parent = tok->tokAt(3)->astParent(); + if (!parent || !parent->isComparisonOp() || !parent->astOperand2()) + continue; + if (parent->astOperand1()->hasKnownIntValue()) + intval = parent->astOperand1()->values().front().intvalue; + else if (parent->astOperand2()->hasKnownIntValue()) + intval = parent->astOperand2()->values().front().intvalue; + else + continue; + conditionToken = parent; + } else if (tok->valueType()->container->getYield(tok->strAt(2)) == Library::Container::Yield::EMPTY) { + conditionToken = tok->tokAt(3); + intval = 0; + } else { continue; - if (parent->astOperand1()->hasKnownIntValue()) - intval = parent->astOperand1()->values().front().intvalue; - else if (parent->astOperand2()->hasKnownIntValue()) - intval = parent->astOperand2()->values().front().intvalue; - else - continue; - conditionToken = parent; - } else if (tok->valueType()->container->getYield(tok->strAt(2)) == Library::Container::Yield::EMPTY) { - conditionToken = tok->tokAt(3); - intval = 0; + } + } else if (tok->valueType()->container->stdStringLike && Token::Match(tok, "%name% ==|!= %str%") && tok->next()->astOperand2() == tok->tokAt(2)) { + intval = Token::getStrLength(tok->tokAt(2)); + conditionToken = tok->next(); } else { continue; } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 8618fc328..152b24908 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -3398,6 +3398,30 @@ private: "}"; ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 6)); + code = "void f(std::string s) {\n" + " if (s == \"hello\")\n" + " s[40] = c;\n" + "}"; + ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s ["), 5)); + + code = "void f(std::string s) {\n" + " s[40] = c;\n" + " if (s == \"hello\") {}\n" + "}"; + ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "s ["), 5)); + + code = "void f(std::string s) {\n" + " if (s != \"hello\") {}\n" + " s[40] = c;\n" + "}"; + ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "s ["), 5)); + + code = "void f(std::string s) {\n" + " if (s != \"hello\")\n" + " s[40] = c;\n" + "}"; + ASSERT(tokenValues(code, "s [").empty()); + // valueFlowContainerForward, function call code = "void f() {\n" " std::list x;\n"