115115#include < string>
116116#include < tuple>
117117#include < type_traits>
118+ #include < unordered_map>
118119#include < unordered_set>
119120#include < vector>
120121
@@ -306,6 +307,10 @@ static ValueFlow::Value castValue(ValueFlow::Value value, const ValueType::Sign
306307 return value;
307308}
308309
310+ static bool isNumeric (const ValueFlow::Value& value) {
311+ return value.isIntValue () || value.isFloatValue ();
312+ }
313+
309314static void combineValueProperties (const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value *result)
310315{
311316 if (value1.isKnown () && value2.isKnown ())
@@ -316,6 +321,14 @@ static void combineValueProperties(const ValueFlow::Value &value1, const ValueFl
316321 result->setInconclusive ();
317322 else
318323 result->setPossible ();
324+ if (value1.isSymbolicValue ()) {
325+ result->valueType = value1.valueType ;
326+ result->tokvalue = value1.tokvalue ;
327+ }
328+ if (value2.isSymbolicValue ()) {
329+ result->valueType = value2.valueType ;
330+ result->tokvalue = value2.tokvalue ;
331+ }
319332 if (value1.isIteratorValue ())
320333 result->valueType = value1.valueType ;
321334 if (value2.isIteratorValue ())
@@ -420,14 +433,14 @@ static R calculate(const std::string& s, const T& x, const T& y, bool* error = n
420433 case ' <' :
421434 return wrap (x < y);
422435 case ' <<' :
423- if (y >= sizeof (MathLib::bigint) * 8 ) {
436+ if (y >= sizeof (MathLib::bigint) * 8 || y < 0 || x < 0 ) {
424437 if (error)
425438 *error = true ;
426439 return R{};
427440 }
428441 return wrap (MathLib::bigint (x) << MathLib::bigint (y));
429442 case ' >>' :
430- if (y >= sizeof (MathLib::bigint) * 8 ) {
443+ if (y >= sizeof (MathLib::bigint) * 8 || y < 0 || x < 0 ) {
431444 if (error)
432445 *error = true ;
433446 return R{};
@@ -458,8 +471,35 @@ static T calculate(const std::string& s, const T& x, const T& y, bool* error = n
458471/* * Set token value for cast */
459472static void setTokenValueCast (Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings *settings);
460473
474+ static bool isCompatibleValueTypes (ValueFlow::Value::ValueType x, ValueFlow::Value::ValueType y)
475+ {
476+ static const std::unordered_map<ValueFlow::Value::ValueType,
477+ std::unordered_set<ValueFlow::Value::ValueType, EnumClassHash>,
478+ EnumClassHash>
479+ compatibleTypes = {
480+ {ValueFlow::Value::ValueType::INT,
481+ {ValueFlow::Value::ValueType::FLOAT,
482+ ValueFlow::Value::ValueType::SYMBOLIC,
483+ ValueFlow::Value::ValueType::TOK}},
484+ {ValueFlow::Value::ValueType::FLOAT, {ValueFlow::Value::ValueType::INT}},
485+ {ValueFlow::Value::ValueType::TOK, {ValueFlow::Value::ValueType::INT}},
486+ {ValueFlow::Value::ValueType::ITERATOR_START, {ValueFlow::Value::ValueType::INT}},
487+ {ValueFlow::Value::ValueType::ITERATOR_END, {ValueFlow::Value::ValueType::INT}},
488+ };
489+ if (x == y)
490+ return true ;
491+ auto it = compatibleTypes.find (x);
492+ if (it == compatibleTypes.end ())
493+ return false ;
494+ return it->second .count (y) > 0 ;
495+ }
496+
461497static bool isCompatibleValues (const ValueFlow::Value& value1, const ValueFlow::Value& value2)
462498{
499+ if (value1.isSymbolicValue () && value2.isSymbolicValue () && value1.tokvalue ->exprId () != value2.tokvalue ->exprId ())
500+ return false ;
501+ if (!isCompatibleValueTypes (value1.valueType , value2.valueType ))
502+ return false ;
463503 if (value1.isKnown () || value2.isKnown ())
464504 return true ;
465505 if (value1.isImpossible () || value2.isImpossible ())
@@ -744,15 +784,18 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se
744784 continue ;
745785 ValueFlow::Value result (0 );
746786 combineValueProperties (value1, value2, &result);
747- const double floatValue1 = value1.isIntValue () ? value1.intvalue : value1.floatValue ;
748- const double floatValue2 = value2.isIntValue () ? value2.intvalue : value2.floatValue ;
749- const bool isFloat = value1.isFloatValue () || value2.isFloatValue ();
750- if (isFloat && Token::Match (parent, " &|^|%|<<|>>|%or%" ))
751- continue ;
752- if (Token::Match (parent, " <<|>>" ) &&
753- !(value1.intvalue >= 0 && value2.intvalue >= 0 && value2.intvalue < MathLib::bigint_bits))
754- continue ;
755- if (Token::Match (parent, " /|%" ) && isZero<double >(floatValue2))
787+ if (astIsFloat (parent, false )) {
788+ if (!result.isIntValue () && !result.isFloatValue ())
789+ continue ;
790+ result.valueType = ValueFlow::Value::ValueType::FLOAT;
791+ }
792+ const double floatValue1 = value1.isFloatValue () ? value1.floatValue : value1.intvalue ;
793+ const double floatValue2 = value2.isFloatValue () ? value2.floatValue : value2.intvalue ;
794+ const MathLib::bigint intValue1 =
795+ value1.isFloatValue () ? static_cast <MathLib::bigint>(value1.floatValue ) : value1.intvalue ;
796+ const MathLib::bigint intValue2 =
797+ value2.isFloatValue () ? static_cast <MathLib::bigint>(value2.floatValue ) : value2.intvalue ;
798+ if ((value1.isFloatValue () || value2.isFloatValue ()) && Token::Match (parent, " &|^|%|<<|>>|==|!=|%or%" ))
756799 continue ;
757800 if (Token::Match (parent, " ==|!=" )) {
758801 if ((value1.isIntValue () && value2.isTokValue ()) || (value1.isTokValue () && value2.isIntValue ())) {
@@ -761,28 +804,30 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se
761804 else if (parent->str () == " !=" )
762805 result.intvalue = 1 ;
763806 } else if (value1.isIntValue () && value2.isIntValue ()) {
764- result.intvalue = calculate (parent->str (), value1.intvalue , value2.intvalue );
807+ bool error = false ;
808+ result.intvalue = calculate (parent->str (), intValue1, intValue2, &error);
809+ if (error)
810+ continue ;
765811 } else {
766812 continue ;
767813 }
768814 setTokenValue (parent, result, settings);
769- } else if (Token::Match (parent, " %comp%" )) {
770- if (!isFloat && !value1.isIntValue () && !value2.isIntValue ())
771- continue ;
772- if (isFloat)
773- result.intvalue = calculate (parent->str (), floatValue1, floatValue2);
774- else
775- result.intvalue = calculate (parent->str (), value1.intvalue , value2.intvalue );
776- setTokenValue (parent, result, settings);
777815 } else if (Token::Match (parent, " %op%" )) {
778- if (value1.isTokValue () || value2.isTokValue ())
779- break ;
780- if (isFloat) {
781- result.valueType = ValueFlow::Value::ValueType::FLOAT;
782- result.floatValue = calculate (parent->str (), floatValue1, floatValue2);
816+ if (Token::Match (parent, " %comp%" )) {
817+ if (!result.isFloatValue () && !value1.isIntValue () && !value2.isIntValue ())
818+ continue ;
783819 } else {
784- result.intvalue = calculate (parent->str (), value1.intvalue , value2.intvalue );
820+ if (value1.isTokValue () || value2.isTokValue ())
821+ break ;
785822 }
823+ bool error = false ;
824+ if (result.isFloatValue ()) {
825+ result.floatValue = calculate (parent->str (), floatValue1, floatValue2, &error);
826+ } else {
827+ result.intvalue = calculate (parent->str (), intValue1, intValue2, &error);
828+ }
829+ if (error)
830+ continue ;
786831 // If the bound comes from the second value then invert the bound when subtracting
787832 if (Token::simpleMatch (parent, " -" ) && value2.bound == result.bound &&
788833 value2.bound != ValueFlow::Value::Bound::Point)
@@ -945,14 +990,13 @@ static void setTokenValueCast(Token *parent, const ValueType &valueType, const V
945990 setTokenValue (parent, castValue (value, valueType.sign , settings->long_bit ), settings);
946991 else if (valueType.type == ValueType::Type::LONGLONG)
947992 setTokenValue (parent, castValue (value, valueType.sign , settings->long_long_bit ), settings);
948- else if (valueType.isFloat ()) {
993+ else if (valueType.isFloat () && isNumeric (value) ) {
949994 ValueFlow::Value floatValue = value;
950995 floatValue.valueType = ValueFlow::Value::ValueType::FLOAT;
951996 if (value.isIntValue ())
952997 floatValue.floatValue = value.intvalue ;
953998 setTokenValue (parent, floatValue, settings);
954- }
955- else if (value.isIntValue ()) {
999+ } else if (value.isIntValue ()) {
9561000 const long long charMax = settings->signedCharMax ();
9571001 const long long charMin = settings->signedCharMin ();
9581002 if (charMin <= value.intvalue && value.intvalue <= charMax) {
0 commit comments