4141#include < functional>
4242#include < initializer_list>
4343#include < iterator>
44+ #include < limits>
4445#include < list>
4546#include < set>
4647#include < type_traits>
@@ -955,29 +956,58 @@ bool extractForLoopValues(const Token *forToken,
955956 nonneg int &varid,
956957 bool &knownInitValue,
957958 MathLib::bigint &initValue,
959+ const ValueFlow::Value*& initValueSource,
960+ const ValueFlow::Value*& initValueWitnessSource,
958961 bool &partialCond,
959962 MathLib::bigint &stepValue,
960963 MathLib::bigint &lastValue)
961964{
965+ initValueSource = nullptr ;
966+ initValueWitnessSource = nullptr ;
962967 if (!Token::simpleMatch (forToken, " for (" ) || !Token::simpleMatch (forToken->next ()->astOperand2 (), " ;" ))
963968 return false ;
964969 const Token *initExpr = forToken->next ()->astOperand2 ()->astOperand1 ();
965970 const Token *condExpr = forToken->next ()->astOperand2 ()->astOperand2 ()->astOperand1 ();
966971 const Token *incExpr = forToken->next ()->astOperand2 ()->astOperand2 ()->astOperand2 ();
967972 if (!initExpr || !initExpr->isBinaryOp () || initExpr->str () != " =" || !Token::Match (initExpr->astOperand1 (), " %var%" ))
968973 return false ;
969- std::vector<MathLib::bigint> minInitValue =
970- getMinValue (makeIntegralInferModel (), initExpr->astOperand2 ()->values ());
974+ const Token* const initToken = initExpr->astOperand2 ();
975+ const std::vector<MathLib::bigint> minInitValue =
976+ getMinValue (makeIntegralInferModel (), initToken->values (), &initValueSource);
971977 if (minInitValue.empty ()) {
972- const ValueFlow::Value* v = initExpr->astOperand2 ()->getMinValue (true );
973- if (v)
974- minInitValue.push_back (v->intvalue );
978+ knownInitValue = false ;
979+ initValue = 0 ;
980+ } else {
981+ knownInitValue = initToken->hasKnownIntValue ();
982+ initValue = minInitValue.front ();
983+ if (knownInitValue && initValueSource && initValueSource->bound != ValueFlow::Value::Bound::Point) {
984+ const auto it = std::find_if (initToken->values ().cbegin (),
985+ initToken->values ().cend (),
986+ [initValue](const ValueFlow::Value& value) {
987+ return value.isIntValue () && !value.isImpossible () && !value.isInconclusive () &&
988+ value.bound == ValueFlow::Value::Bound::Point && value.intvalue == initValue;
989+ });
990+ if (it != initToken->values ().cend ())
991+ initValueSource = &*it;
992+ }
975993 }
976- if (minInitValue.empty ())
994+ const auto isNegativeEvidence = [](const ValueFlow::Value& candidate) {
995+ return candidate.isIntValue () && !candidate.isImpossible () && !candidate.isInconclusive () &&
996+ (candidate.isKnown () || candidate.isPossible ()) && candidate.path >= 0 && candidate.intvalue < 0 &&
997+ (candidate.bound == ValueFlow::Value::Bound::Point || candidate.bound == ValueFlow::Value::Bound::Upper);
998+ };
999+ if (initValueSource && isNegativeEvidence (*initValueSource)) {
1000+ initValueWitnessSource = initValueSource;
1001+ } else {
1002+ const auto it = std::find_if (initToken->values ().cbegin (),
1003+ initToken->values ().cend (),
1004+ isNegativeEvidence);
1005+ if (it != initToken->values ().cend ())
1006+ initValueWitnessSource = &*it;
1007+ }
1008+ if (minInitValue.empty () && !initValueWitnessSource)
9771009 return false ;
9781010 varid = initExpr->astOperand1 ()->varId ();
979- knownInitValue = initExpr->astOperand2 ()->hasKnownIntValue ();
980- initValue = minInitValue.front ();
9811011 partialCond = Token::Match (condExpr, " %oror%|&&" );
9821012 visitAstNodes (condExpr, [varid, &condExpr](const Token *tok) {
9831013 if (Token::Match (tok, " %oror%|&&" ))
@@ -993,10 +1023,14 @@ bool extractForLoopValues(const Token *forToken,
9931023 if (!incExpr || !incExpr->isUnaryOp (" ++" ) || incExpr->astOperand1 ()->varId () != varid)
9941024 return false ;
9951025 stepValue = 1 ;
996- if (condExpr->str () == " <" )
997- lastValue = condExpr->astOperand2 ()->getKnownIntValue () - 1 ;
998- else
1026+ if (condExpr->str () == " <" ) {
1027+ const MathLib::bigint limit = condExpr->astOperand2 ()->getKnownIntValue ();
1028+ if (limit == std::numeric_limits<MathLib::bigint>::min ())
1029+ return false ;
1030+ lastValue = limit - 1 ;
1031+ } else {
9991032 lastValue = condExpr->astOperand2 ()->getKnownIntValue ();
1033+ }
10001034 return true ;
10011035}
10021036
0 commit comments