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