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

@@ -75,10 +75,28 @@
         }
         right = get_type(expr->right);
         if (!right)
                 return NULL;
 
+        if (type_is_fp(left)) {
+                if (type_is_fp(right)) {
+                        if (type_bits(left) > type_bits(right))
+                                return left;
+                        return right;
+                }
+                return left;
+        }
+
+        if (type_is_fp(right)) {
+                if (type_is_fp(left)) {
+                        if (type_bits(right) > type_bits(left))
+                                return right;
+                        return left;
+                }
+                return right;
+        }
+
         if (expr->op == '-' &&
             (is_ptr_type(left) && is_ptr_type(right)))
                 return ssize_t_ctype;
 
         if (left->type == SYM_PTR || left->type == SYM_ARRAY)

@@ -141,14 +159,34 @@
         if (!sym)
                 return NULL;
         return get_real_base_type(sym);
 }
 
+static struct symbol *handle__builtin_choose_expr(struct expression *expr)
+{
+        struct expression *const_expr, *expr1, *expr2;
+        sval_t sval;
+
+        const_expr = get_argument_from_call_expr(expr->args, 0);
+        expr1 = get_argument_from_call_expr(expr->args, 1);
+        expr2 = get_argument_from_call_expr(expr->args, 2);
+
+        if (!get_value(const_expr, &sval) || !expr1 || !expr2)
+                return NULL;
+        if (sval.value)
+                return get_type(expr1);
+        else
+                return get_type(expr2);
+}
+
 static struct symbol *get_return_type(struct expression *expr)
 {
         struct symbol *tmp;
 
+        if (sym_name_is("__builtin_choose_expr", expr->fn))
+                return handle__builtin_choose_expr(expr);
+
         tmp = get_type(expr->fn);
         if (!tmp)
                 return NULL;
         /* this is to handle __builtin_constant_p() */
         if (tmp->type != SYM_FN)

@@ -401,26 +439,60 @@
         if (sym && sym->type == SYM_PTR)
                 return 1;
         return 0;
 }
 
+static sval_t fp_max(struct symbol *type)
+{
+        sval_t ret = { .type = type };
+
+        if (type == &float_ctype)
+                ret.fvalue = FLT_MAX;
+        else if (type == &double_ctype)
+                ret.dvalue = DBL_MAX;
+        else
+                ret.ldvalue = LDBL_MAX;
+
+        return ret;
+}
+
 sval_t sval_type_max(struct symbol *base_type)
 {
         sval_t ret;
 
+        if (type_is_fp(base_type))
+                return fp_max(base_type);
+
         if (!base_type || !type_bits(base_type))
                 base_type = &llong_ctype;
         ret.type = base_type;
 
         ret.value = (~0ULL) >> (64 - type_positive_bits(base_type));
         return ret;
 }
 
+static sval_t fp_min(struct symbol *type)
+{
+        sval_t ret = { .type = type };
+
+        if (type == &float_ctype)
+                ret.fvalue = -FLT_MAX;
+        else if (type == &double_ctype)
+                ret.dvalue = -DBL_MAX;
+        else
+                ret.ldvalue = -LDBL_MAX;
+
+        return ret;
+}
+
 sval_t sval_type_min(struct symbol *base_type)
 {
         sval_t ret;
 
+        if (type_is_fp(base_type))
+                return fp_min(base_type);
+
         if (!base_type || !type_bits(base_type))
                 base_type = &llong_ctype;
         ret.type = base_type;
 
         if (type_unsigned(base_type) || is_ptr_type(base_type)) {