@@ -3411,29 +3411,36 @@ static bool isUsableValue(const ValueFlow::Value& value, const Settings& setting
34113411 return true ;
34123412}
34133413
3414+ // Get the first ValueFlow value of a token matching the predicate, preferring known values
3415+ template <class Predicate >
3416+ static const ValueFlow::Value* selectPreferredValue (const Token* tok, const Predicate& pred)
3417+ {
3418+ const ValueFlow::Value* result = nullptr ;
3419+ for (const ValueFlow::Value& value : tok->values ()) {
3420+ if (!pred (value))
3421+ continue ;
3422+ if (result && !(value.isKnown () && !result->isKnown ()))
3423+ continue ;
3424+ result = &value;
3425+ }
3426+ return result;
3427+ }
3428+
34143429// Get the iterator value of an iterator expression together with the container size value that
34153430// ValueFlow has added to the iterator
34163431static IteratorPosition getIteratorPosition (const Token* tok, const Settings& settings)
34173432{
34183433 IteratorPosition position;
34193434 if (!tok)
34203435 return position;
3421- for (const ValueFlow::Value& value : tok->values ()) {
3422- if (!isUsableValue (value, settings) || !value.isIteratorValue ())
3423- continue ;
3424- if (position.value && !(value.isKnown () && !position.value ->isKnown ()))
3425- continue ;
3426- position.value = &value;
3427- }
3436+ position.value = selectPreferredValue (tok, [&](const ValueFlow::Value& value) {
3437+ return isUsableValue (value, settings) && value.isIteratorValue ();
3438+ });
34283439 if (!position.value )
34293440 return position;
3430- for (const ValueFlow::Value& value : tok->values ()) {
3431- if (!isUsableValue (value, settings) || !value.isContainerSizeValue () || value.path != position.value ->path )
3432- continue ;
3433- if (position.sizeValue && !(value.isKnown () && !position.sizeValue ->isKnown ()))
3434- continue ;
3435- position.sizeValue = &value;
3436- }
3441+ position.sizeValue = selectPreferredValue (tok, [&](const ValueFlow::Value& value) {
3442+ return isUsableValue (value, settings) && value.isContainerSizeValue () && value.path == position.value ->path ;
3443+ });
34373444 return position;
34383445}
34393446
@@ -3485,18 +3492,10 @@ static const ValueFlow::Value* getCountValue(const Token* tok, const Settings& s
34853492{
34863493 if (!tok)
34873494 return nullptr ;
3488- const ValueFlow::Value* countValue = nullptr ;
3489- for (const ValueFlow::Value& value : tok->values ()) {
3490- if (!isUsableValue (value, settings) || !value.isIntValue ())
3491- continue ;
3492- // the count could be smaller, which would make fewer elements accessed
3493- if (value.bound == ValueFlow::Value::Bound::Upper)
3494- continue ;
3495- if (countValue && !(value.isKnown () && !countValue->isKnown ()))
3496- continue ;
3497- countValue = &value;
3498- }
3499- return countValue;
3495+ return selectPreferredValue (tok, [&](const ValueFlow::Value& value) {
3496+ // a count with an upper bound could be smaller, which would make fewer elements accessed
3497+ return isUsableValue (value, settings) && value.isIntValue () && value.bound != ValueFlow::Value::Bound::Upper;
3498+ });
35003499}
35013500
35023501void CheckStlImpl::algorithmOutOfBounds ()
@@ -3548,7 +3547,8 @@ void CheckStlImpl::algorithmOutOfBounds()
35483547 const ValueFlow::Value lastLifetime = getLifetimeIteratorValue (args[1 ]);
35493548 if (!firstLifetime.tokvalue || !lastLifetime.tokvalue )
35503549 continue ;
3551- if (!isSameExpression (false , firstLifetime.tokvalue , lastLifetime.tokvalue , mSettings , false , false ))
3550+ if (!isSameIteratorContainerExpression (
3551+ firstLifetime.tokvalue , lastLifetime.tokvalue , mSettings , firstLifetime.lifetimeKind ))
35523552 continue ;
35533553 accessed = getIteratorDistance (first, last);
35543554 if (!accessed)
@@ -3593,7 +3593,6 @@ void CheckStlImpl::algorithmOutOfBounds()
35933593 conditionValue ? conditionValue : (dest.sizeValue ? dest.sizeValue : dest.value );
35943594 algorithmOutOfBoundsError (args[argnr],
35953595 " std::" + nameTok->str (),
3596- args[argnr]->expressionString (),
35973596 accessed.count ,
35983597 available.count ,
35993598 pathValue,
@@ -3607,14 +3606,14 @@ void CheckStlImpl::algorithmOutOfBounds()
36073606
36083607void CheckStlImpl::algorithmOutOfBoundsError (const Token* tok,
36093608 const std::string& algoName,
3610- const std::string& iterExpr,
36113609 MathLib::bigint accessed,
36123610 MathLib::bigint available,
36133611 const ValueFlow::Value* value,
36143612 const Token* condition,
36153613 bool mayAccessFewer,
36163614 bool inconclusive)
36173615{
3616+ const std::string iterExpr = tok ? tok->expressionString () : " it" ;
36183617 const std::string accessedStr = MathLib::toString (accessed) + (accessed == 1 ? " element" : " elements" );
36193618 const std::string availableStr = MathLib::toString (available) + (available == 1 ? " element is" : " elements are" );
36203619 const std::string body = " algorithm '" + algoName + " ' " + (mayAccessFewer ? " may access up to " : " accesses " ) +
@@ -3782,7 +3781,7 @@ void CheckStl::getErrorMessages(ErrorLogger& errorLogger, const Settings& settin
37823781 c.dereferenceInvalidIteratorError (nullptr , " i" );
37833782 // TODO: derefInvalidIteratorRedundantCheck
37843783 c.eraseIteratorOutOfBoundsError (nullptr , nullptr );
3785- c.algorithmOutOfBoundsError (nullptr , " std::copy" , " it " , 10 , 6 , nullptr , nullptr , false , false );
3784+ c.algorithmOutOfBoundsError (nullptr , " std::copy" , 10 , 6 , nullptr , nullptr , false , false );
37863785 c.useStlAlgorithmError (nullptr , " " );
37873786 c.knownEmptyContainerError (nullptr , " " );
37883787 c.globalLockGuardError (nullptr );
0 commit comments