3232#include " utils.h"
3333#include " valueflow.h"
3434#include " valueptr.h"
35+ #include " vf_common.h"
3536#include " vfvalue.h"
3637
3738#include " checkclass.h"
@@ -929,50 +930,6 @@ const Token* getCondTokFromEnd(const Token* endBlock)
929930 return getCondTokFromEndImpl (endBlock);
930931}
931932
932- static std::pair<MathLib::bigint, MathLib::bigint> getIntegralMinMaxValues (int bits, ValueType::Sign sign)
933- {
934- using bigint = MathLib::bigint;
935- using biguint = MathLib::biguint;
936-
937- if (bits <= 0 )
938- return { bigint (0 ), bigint (0 ) };
939-
940- // Unsigned: [0, 2^bits - 1]
941- if (sign == ValueType::Sign::UNSIGNED) {
942- // If bits exceed what MathLib can safely shift, saturate to max representable
943- if (bits >= MathLib::bigint_bits) {
944- biguint max_u = std::numeric_limits<biguint>::max ();
945- return { bigint (0 ), bigint (max_u) };
946- }
947- biguint max_u = (biguint (1 ) << bits) - 1 ;
948- return { bigint (0 ), bigint (max_u) };
949- }
950-
951- // Signed: [-(2^(bits-1)), 2^(bits-1)-1]
952- if (bits >= MathLib::bigint_bits) {
953- bigint min_s = std::numeric_limits<bigint>::min ();
954- bigint max_s = std::numeric_limits<bigint>::max ();
955- return { min_s, max_s };
956- }
957- bigint max_s = (bigint (1 ) << (bits - 1 )) - 1 ;
958- bigint min_s = -(bigint (1 ) << (bits - 1 ));
959- return { min_s, max_s };
960- }
961-
962- static bool getIntegralTypeRange (const ValueType* type, const Settings& settings, std::pair<MathLib::bigint, MathLib::bigint>& range)
963- {
964- if (!type || !type->isIntegral ())
965- return false ;
966-
967- const int bits = type->getSizeOf (settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer) * 8 ;
968- if (bits <= 0 || bits > 64 )
969- return false ;
970-
971- range = getIntegralMinMaxValues (bits, type->sign );
972-
973- return true ;
974- }
975-
976933bool getExpressionResultRange (const Token* expr, const Settings& settings, std::pair<MathLib::bigint, MathLib::bigint>& exprRange)
977934{
978935 if (!expr)
@@ -1020,7 +977,7 @@ bool getExpressionResultRange(const Token* expr, const Settings& settings, std::
1020977 exprToCheck = castFrom;
1021978 }
1022979
1023- return getIntegralTypeRange (exprToCheck->valueType (), settings, exprRange);
980+ return ValueFlow::getMinMaxValues (exprToCheck->valueType (), settings. platform , exprRange. first , exprRange. second );
1024981}
1025982
1026983template <typename Op>
@@ -1045,6 +1002,10 @@ bool isOperationResultWithinIntRange(const Token* op, const Settings& settings,
10451002 if ((rightRange->first >= INTEGER_SHIFT_LIMIT) || rightRange->second >= INTEGER_SHIFT_LIMIT)
10461003 return false ;
10471004
1005+ // Leftshift with negative values is undefined behavior.
1006+ if ((rightRange->first < 0 ) || rightRange->second < 0 )
1007+ return false ;
1008+
10481009 return checkAllRangeOperations (*leftRange, *rightRange, settings,
10491010 [](MathLib::bigint a, MathLib::bigint b) {
10501011 return a << b;
0 commit comments