Print this page
12166 resync smatch to 0.6.1-rc1-il-3

@@ -72,10 +72,19 @@
         ret.type = type;
         ret.value = val;
         return ret;
 }
 
+sval_t sval_type_fval(struct symbol *type, long double fval)
+{
+        sval_t ret;
+
+        ret.type = &ldouble_ctype;
+        ret.ldvalue = fval;
+        return sval_cast(type, ret);
+}
+
 sval_t sval_from_val(struct expression *expr, long long val)
 {
         sval_t ret;
 
         ret = sval_blank(expr);

@@ -83,17 +92,33 @@
         ret = sval_cast(get_type(expr), ret);
 
         return ret;
 }
 
+sval_t sval_from_fval(struct expression *expr, long double fval)
+{
+        sval_t ret;
+
+        ret.type = &ldouble_ctype;
+        ret.ldvalue = fval;
+        ret = sval_cast(get_type(expr), ret);
+
+        return ret;
+}
+
 int sval_is_ptr(sval_t sval)
 {
         if (!sval.type)
                 return 0;
         return (sval.type->type == SYM_PTR || sval.type->type == SYM_ARRAY);
 }
 
+bool sval_is_fp(sval_t sval)
+{
+        return type_is_fp(sval.type);
+}
+
 int sval_unsigned(sval_t sval)
 {
         if (is_ptr_type(sval.type))
                 return true;
         return type_unsigned(sval.type);

@@ -132,36 +157,70 @@
 int sval_is_positive(sval_t sval)
 {
         return !sval_is_negative(sval);
 }
 
+static bool fp_is_min(sval_t sval)
+{
+        if (sval.type == &float_ctype)
+                return sval.fvalue == -FLT_MAX;
+        if (sval.type == &double_ctype)
+                return sval.dvalue == -DBL_MAX;
+        if (sval.type == &ldouble_ctype)
+                return sval.ldvalue == -LDBL_MAX;
+        sm_perror("%s: bad type: '%s'", __func__, type_to_str(sval.type));
+        return false;
+}
+
 int sval_is_min(sval_t sval)
 {
         sval_t min = sval_type_min(sval.type);
 
+        if (sval_is_fp(sval))
+                return fp_is_min(sval);
+
         if (sval_unsigned(sval)) {
                 if (sval.uvalue == 0)
                         return 1;
                 return 0;
         }
         /* return true for less than min as well */
         return (sval.value <= min.value);
 }
 
+static bool fp_is_max(sval_t sval)
+{
+        if (sval.type == &float_ctype)
+                return sval.fvalue == FLT_MAX;
+        if (sval.type == &double_ctype)
+                return sval.dvalue == DBL_MAX;
+        if (sval.type == &ldouble_ctype)
+                return sval.ldvalue == LDBL_MAX;
+        sm_perror("%s: bad type: '%s'", __func__, type_to_str(sval.type));
+        return false;
+}
+
 int sval_is_max(sval_t sval)
 {
         sval_t max = sval_type_max(sval.type);
 
+        if (sval_is_fp(sval))
+                return fp_is_max(sval);
+
         if (sval_unsigned(sval))
                 return (sval.uvalue >= max.value);
         return (sval.value >= max.value);
 }
 
 int sval_is_a_min(sval_t sval)
 {
         if (sval_is_min(sval))
                 return 1;
+
+        if (sval_is_fp(sval))
+                return 0;
+
         if (sval_signed(sval) && sval.value == SHRT_MIN)
                 return 1;
         if (sval_signed(sval) && sval.value == INT_MIN)
                 return 1;
         if (sval_signed(sval) && sval.value == LLONG_MIN)

@@ -171,10 +230,14 @@
 
 int sval_is_a_max(sval_t sval)
 {
         if (sval_is_max(sval))
                 return 1;
+
+        if (sval_is_fp(sval))
+                return 0;
+
         if (sval.uvalue == SHRT_MAX)
                 return 1;
         if (sval.uvalue == INT_MAX)
                 return 1;
         if (sval.uvalue == LLONG_MAX)

@@ -191,10 +254,13 @@
         return 0;
 }
 
 int sval_is_negative_min(sval_t sval)
 {
+        if (sval_is_fp(sval))
+                return 0;
+
         if (!sval_is_negative(sval))
                 return 0;
         return sval_is_min(sval);
 }
 

@@ -252,24 +318,101 @@
         return 0;
 }
 
 int sval_fits(struct symbol *type, sval_t sval)
 {
+        /* everything fits into floating point */
+        if (type_is_fp(type))
+                return 1;
+        /* floating points don't fit into int */
+        if (type_is_fp(sval.type))
+                return 0;
+
         if (sval_too_low(type, sval))
                 return 0;
         if (sval_too_high(type, sval))
                 return 0;
         return 1;
 }
 
+static sval_t cast_to_fp(struct symbol *type, sval_t sval)
+{
+        sval_t ret = {};
+
+        ret.type = type;
+        if (type == &float_ctype) {
+                if (!sval_is_fp(sval)) {
+                        if (sval_unsigned(sval))
+                                ret.fvalue = sval.uvalue;
+                        else
+                                ret.fvalue = sval.value;
+                } else if (sval.type == &float_ctype)
+                        ret.fvalue = sval.fvalue;
+                else if (sval.type == &double_ctype)
+                        ret.fvalue = sval.dvalue;
+                else
+                        ret.fvalue = sval.ldvalue;
+        } else if (type == &double_ctype) {
+                if (!sval_is_fp(sval)) {
+                        if (sval_unsigned(sval))
+                                ret.dvalue = sval.uvalue;
+                        else
+                                ret.dvalue = sval.value;
+                } else if (sval.type == &float_ctype)
+                        ret.dvalue = sval.fvalue;
+                else if (sval.type == &double_ctype)
+                        ret.dvalue = sval.dvalue;
+                else
+                        ret.dvalue = sval.ldvalue;
+        } else if (type == &ldouble_ctype) {
+                if (!sval_is_fp(sval)) {
+                        if (sval_unsigned(sval))
+                                ret.ldvalue = (long double)sval.uvalue;
+                        else
+                                ret.ldvalue = (long double)sval.value;
+                } else if (sval.type == &float_ctype)
+                        ret.ldvalue = sval.fvalue;
+                else if (sval.type == &double_ctype)
+                        ret.ldvalue = sval.dvalue;
+                else
+                        ret.ldvalue = sval.ldvalue;
+        } else {
+                sm_perror("%s: bad type: %s", __func__, type_to_str(type));
+        }
+
+        return ret;
+}
+
+static sval_t cast_from_fp(struct symbol *type, sval_t sval)
+{
+        sval_t ret = {};
+
+        ret.type = &llong_ctype;
+        if (sval.type == &float_ctype)
+                ret.value = sval.fvalue;
+        else if (sval.type == &double_ctype)
+                ret.value = sval.dvalue;
+        else if (sval.type == &ldouble_ctype)
+                ret.value = sval.ldvalue;
+        else
+                sm_perror("%s: bad type: %s", __func__, type_to_str(type));
+
+        return sval_cast(type, ret);
+}
+
 sval_t sval_cast(struct symbol *type, sval_t sval)
 {
         sval_t ret;
 
         if (!type)
                 type = &int_ctype;
 
+        if (type_is_fp(type))
+                return cast_to_fp(type, sval);
+        if (type_is_fp(sval.type))
+                return cast_from_fp(type, sval);
+
         ret.type = type;
         switch (sval_bits(ret)) {
         case 1:
                 ret.value = !!sval.value;
                 break;

@@ -624,14 +767,33 @@
 unsigned long long sval_fls_mask(sval_t sval)
 {
         return fls_mask(sval.uvalue);
 }
 
+static char *fp_to_str(sval_t sval)
+{
+        char buf[32];
+
+        if (sval.type == &float_ctype)
+                snprintf(buf, sizeof(buf), "%f", sval.fvalue);
+        else if (sval.type == &double_ctype)
+                snprintf(buf, sizeof(buf), "%e", sval.dvalue);
+        else if (sval.type == &ldouble_ctype) {
+                snprintf(buf, sizeof(buf), "%Lf", sval.ldvalue);
+        } else
+                snprintf(buf, sizeof(buf), "nan");
+
+        return alloc_sname(buf);
+}
+
 const char *sval_to_str(sval_t sval)
 {
-        char buf[30];
+        char buf[32];
 
+        if (sval_is_fp(sval))
+                return fp_to_str(sval);
+
         if (sval_is_ptr(sval) && sval.value == valid_ptr_max)
                 return "ptr_max";
         if (sval_unsigned(sval) && sval.value == ULLONG_MAX)
                 return "u64max";
         if (sval_unsigned(sval) && sval.value == UINT_MAX)

@@ -669,11 +831,11 @@
 
         if (option_project != PROJ_KERNEL ||
             !is_ptr_type(sval.type))
                 return sval_to_str(sval);
 
-        if (sval.uvalue >= -4905ULL) {
+        if (!sval_is_fp(sval) && sval.uvalue >= -4905ULL) {
                 snprintf(buf, sizeof(buf), "(%lld)", sval.value);
                 return alloc_sname(buf);
         }
 
         return sval_to_str(sval);

@@ -681,10 +843,13 @@
 
 const char *sval_to_numstr(sval_t sval)
 {
         char buf[30];
 
+        if (type_is_fp(sval.type))
+                return fp_to_str(sval);
+
         if (sval_unsigned(sval))
                 snprintf(buf, sizeof(buf), "%llu", sval.value);
         else if (sval.value < 0)
                 snprintf(buf, sizeof(buf), "(%lld)", sval.value);
         else