@@ -401,10 +401,14 @@ void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const Val
401401 result.valueType = value2.valueType ;
402402 result.tokvalue = value2.tokvalue ;
403403 }
404- if (value1.isIteratorValue ())
404+ if (value1.isIteratorValue ()) {
405405 result.valueType = value1.valueType ;
406- if (value2.isIteratorValue ())
406+ result.container = value1.container ;
407+ }
408+ if (value2.isIteratorValue ()) {
407409 result.valueType = value2.valueType ;
410+ result.container = value2.container ;
411+ }
408412 result.condition = value1.condition ? value1.condition : value2.condition ;
409413 result.varId = (value1.varId != 0 ) ? value1.varId : value2.varId ;
410414 result.varvalue = (result.varId == value1.varId ) ? value1.varvalue : value2.varvalue ;
@@ -3859,11 +3863,14 @@ static void valueFlowForwardConst(Token* start,
38593863 } else {
38603864 [&] {
38613865 // Add the container size to iterators of the container (mirrors ContainerExpressionAnalyzer::match)
3862- if (hasContainerSizeValue && astIsIterator (tok) && isAliasOf (tok, var->declarationId ())) {
3866+ if (hasContainerSizeValue && isIteratorOf (tok, var->declarationId ())) {
38633867 for (const ValueFlow::Value& value : values) {
38643868 if (!value.isContainerSizeValue ())
38653869 continue ;
3866- setTokenValue (tok, value, settings);
3870+ ValueFlow::Value sizeValue = value;
3871+ if (!sizeValue.container )
3872+ sizeValue.container = var->nameToken ();
3873+ setTokenValue (tok, std::move (sizeValue), settings);
38673874 }
38683875 return ;
38693876 }
@@ -4212,11 +4219,15 @@ static void valueFlowAfterAssign(const TokenList &tokenlist,
42124219 values.remove_if ([&](const ValueFlow::Value& value) {
42134220 return types.count (value.valueType ) > 0 ;
42144221 });
4215- // Remove container size if its not a container
4216- if (!astIsContainer (tok->astOperand2 ()))
4222+ // Remove container size if its not a container - unless the size records its container
4223+ // and flows into a pointer to the container data (e.g. p = v.data())
4224+ if (!astIsContainer (tok->astOperand2 ())) {
4225+ const bool lhsIsPointer = astIsPointer (tok->astOperand1 ());
42174226 values.remove_if ([&](const ValueFlow::Value& value) {
4218- return value.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE ;
4227+ return value.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE &&
4228+ (!value.container || !lhsIsPointer);
42194229 });
4230+ }
42204231 // Remove symbolic values that are the same as the LHS
42214232 values.remove_if ([&](const ValueFlow::Value& value) {
42224233 if (value.isSymbolicValue () && value.tokvalue )
@@ -6447,17 +6458,22 @@ static void valueFlowIterators(TokenList& tokenlist, const Settings& settings)
64476458 const Library::Container::Yield yield = findIteratorYield (tok, ftok, settings.library );
64486459 if (!ftok)
64496460 continue ;
6450- if (yield == Library::Container::Yield::START_ITERATOR ) {
6451- ValueFlow::Value v (0 );
6452- v.setKnown ();
6453- v.valueType = ValueFlow::Value::ValueType::ITERATOR_START ;
6454- setTokenValue (const_cast <Token*>(ftok)->next (), std::move (v), settings);
6455- } else if (yield == Library::Container::Yield::END_ITERATOR ) {
6456- ValueFlow::Value v (0 );
6457- v.setKnown ();
6458- v.valueType = ValueFlow::Value::ValueType::ITERATOR_END ;
6459- setTokenValue (const_cast <Token*>(ftok)->next (), std::move (v), settings);
6460- }
6461+ if (yield != Library::Container::Yield::START_ITERATOR && yield != Library::Container::Yield::END_ITERATOR )
6462+ continue ;
6463+ // The iterator value records the container it iterates. A pointer or a reference only
6464+ // transports the iterator, so record the container it refers to instead.
6465+ const Token* containerTok = tok;
6466+ if (astIsPointer (containerTok) || (containerTok->variable () && containerTok->variable ()->isReference ())) {
6467+ const ValueFlow::Value lifetime = ValueFlow::getLifetimeObjValue (containerTok);
6468+ if (lifetime.tokvalue && astIsContainer (lifetime.tokvalue ) && !astIsPointer (lifetime.tokvalue ))
6469+ containerTok = lifetime.tokvalue ;
6470+ }
6471+ ValueFlow::Value v (0 );
6472+ v.setKnown ();
6473+ v.valueType = yield == Library::Container::Yield::START_ITERATOR ? ValueFlow::Value::ValueType::ITERATOR_START
6474+ : ValueFlow::Value::ValueType::ITERATOR_END ;
6475+ v.container = containerTok;
6476+ setTokenValue (const_cast <Token*>(ftok)->next (), std::move (v), settings);
64616477 }
64626478}
64636479
0 commit comments