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