diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 34b7776d5..38ec9f4e5 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3422,6 +3422,8 @@ static void valueFlowContainerReverse(const Token *tok, unsigned int containerId continue; if (!tok->valueType() || !tok->valueType()->container) continue; + if (Token::Match(tok, "%name% . %name% (") && tok->valueType()->container->getAction(tok->strAt(2)) != Library::Container::Action::NO_ACTION) + break; setTokenValue(const_cast(tok), value, settings); } } @@ -3436,9 +3438,23 @@ static void valueFlowContainerSize(TokenList * /*tokenlist*/, SymbolDatabase* sy continue; if (!Token::Match(tok, "%name% . %name% (")) continue; - if (tok->valueType()->container->getYield(tok->strAt(2)) != Library::Container::Yield::EMPTY) + + const Token *conditionToken; + + 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()->str() != "0" && parent->astOperand2()->str() != "0") + continue; + conditionToken = parent; + } else if (tok->valueType()->container->getYield(tok->strAt(2)) == Library::Container::Yield::EMPTY) { + conditionToken = tok->tokAt(3); + } else { continue; - ValueFlow::Value value(tok->tokAt(3), 0LL); + } + + ValueFlow::Value value(conditionToken, 0LL); value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; valueFlowContainerReverse(scope.classDef, tok->varId(), value, settings); } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index c322ecb1f..5e7055866 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -3221,6 +3221,15 @@ private: ASSERT_EQUALS(true, values.empty() ? true : values.front().isContainerSizeValue()); ASSERT_EQUALS(0, values.empty() ? 0 : values.front().intvalue); + code = "void f(const std::list &ints) {\n" + " ints.front();\n" + " if (ints.size()==0) {}\n" + "}"; + values = tokenValues(code, "ints . front"); + ASSERT_EQUALS(1, values.size()); + ASSERT_EQUALS(true, values.empty() ? true : values.front().isContainerSizeValue()); + ASSERT_EQUALS(0, values.empty() ? 0 : values.front().intvalue); + code = "void f(std::list ints) {\n" " ints.front();\n" " ints.pop_back();\n"