Print this page
11972 resync smatch

@@ -39,15 +39,21 @@
 #include "parse.h"
 #include "token.h"
 #include "symbol.h"
 #include "target.h"
 #include "expression.h"
+#include "evaluate.h"
 #include "expand.h"
 
 
 static int expand_expression(struct expression *);
 static int expand_statement(struct statement *);
+
+// If set, don't issue a warning on divide-by-0, invalid shift, ...
+// and don't mark the expression as erroneous but leave it as-is.
+// This allows testing some characteristics of the expression
+// without creating any side-effects (e.g.: is_zero_constant()).
 static int conservative;
 
 static int expand_symbol_expression(struct expression *expr)
 {
         struct symbol *sym = expr->symbol;

@@ -155,17 +161,39 @@
                         expr->fvalue = (float)expr->fvalue;
         }
         expr->type = EXPR_FVALUE;
 }
 
-static int check_shift_count(struct expression *expr, struct symbol *ctype, unsigned int count)
+static void warn_shift_count(struct expression *expr, struct symbol *ctype, long long count)
 {
-        warning(expr->pos, "shift too big (%u) for type %s", count, show_typename(ctype));
-        count &= ctype->bit_size-1;
-        return count;
+        if (count < 0) {
+                if (!Wshift_count_negative)
+                        return;
+                warning(expr->pos, "shift count is negative (%lld)", count);
+                return;
+        }
+        if (ctype->type == SYM_NODE)
+                ctype = ctype->ctype.base_type;
+
+        if (!Wshift_count_overflow)
+                return;
+        warning(expr->pos, "shift too big (%llu) for type %s", count, show_typename(ctype));
 }
 
+/* Return true if constant shift size is valid */
+static bool check_shift_count(struct expression *expr, struct expression *right)
+{
+        struct symbol *ctype = expr->ctype;
+        long long count = get_longlong(right);
+
+        if (count >= 0 && count < ctype->bit_size)
+                return true;
+        if (!conservative)
+                warn_shift_count(expr, ctype, count);
+        return false;
+}
+
 /*
  * CAREFUL! We need to get the size and sign of the
  * result right!
  */
 #define CONVERT(op,s)   (((op)<<1)+(s))

@@ -180,17 +208,13 @@
 
         if (right->type != EXPR_VALUE)
                 return 0;
         r = right->value;
         if (expr->op == SPECIAL_LEFTSHIFT || expr->op == SPECIAL_RIGHTSHIFT) {
-                if (r >= ctype->bit_size) {
-                        if (conservative)
+                if (!check_shift_count(expr, right))
                                 return 0;
-                        r = check_shift_count(expr, ctype, r);
-                        right->value = r;
                 }
-        }
         if (left->type != EXPR_VALUE)
                 return 0;
         l = left->value; r = right->value;
         is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED);
         mask = 1ULL << (ctype->bit_size-1);

@@ -476,11 +500,11 @@
                         expr->taint |= Taint_comma | taint;
         }
         return cost;
 }
 
-#define MOD_IGN (MOD_VOLATILE | MOD_CONST)
+#define MOD_IGN (MOD_QUALIFIER)
 
 static int compare_types(int op, struct symbol *left, struct symbol *right)
 {
         struct ctype c1 = {.base_type = left};
         struct ctype c2 = {.base_type = right};

@@ -527,44 +551,63 @@
 }
 
 static int expand_conditional(struct expression *expr)
 {
         struct expression *cond = expr->conditional;
-        struct expression *true = expr->cond_true;
-        struct expression *false = expr->cond_false;
+        struct expression *valt = expr->cond_true;
+        struct expression *valf = expr->cond_false;
         int cost, cond_cost;
 
         cond_cost = expand_expression(cond);
         if (cond->type == EXPR_VALUE) {
                 unsigned flags = expr->flags;
                 if (!cond->value)
-                        true = false;
-                if (!true)
-                        true = cond;
-                cost = expand_expression(true);
-                *expr = *true;
+                        valt = valf;
+                if (!valt)
+                        valt = cond;
+                cost = expand_expression(valt);
+                *expr = *valt;
                 expr->flags = flags;
                 if (expr->type == EXPR_VALUE)
                         expr->taint |= cond->taint;
                 return cost;
         }
 
-        cost = expand_expression(true);
-        cost += expand_expression(false);
+        cost = expand_expression(valt);
+        cost += expand_expression(valf);
 
         if (cost < SELECT_COST) {
                 expr->type = EXPR_SELECT;
                 cost -= BRANCH_COST - 1;
         }
 
         return cost + cond_cost + BRANCH_COST;
 }
                 
+static void check_assignment(struct expression *expr)
+{
+        struct expression *right;
+
+        switch (expr->op) {
+        case SPECIAL_SHL_ASSIGN:
+        case SPECIAL_SHR_ASSIGN:
+                right = expr->right;
+                if (right->type != EXPR_VALUE)
+                        break;
+                check_shift_count(expr, right);
+                break;
+        }
+        return;
+}
+
 static int expand_assignment(struct expression *expr)
 {
         expand_expression(expr->left);
         expand_expression(expr->right);
+
+        if (!conservative)
+                check_assignment(expr);
         return SIDE_EFFECTS;
 }
 
 static int expand_addressof(struct expression *expr)
 {

@@ -580,11 +623,11 @@
  */
 static struct expression *constant_symbol_value(struct symbol *sym, int offset)
 {
         struct expression *value;
 
-        if (sym->ctype.modifiers & (MOD_ASSIGNED | MOD_ADDRESSABLE))
+        if (sym->ctype.modifiers & MOD_ACCESS)
                 return NULL;
         value = sym->initializer;
         if (!value)
                 return NULL;
         if (value->type == EXPR_INITIALIZER) {

@@ -642,10 +685,12 @@
 
                 /* Const symbol with a constant initializer? */
                 if (value) {
                         /* FIXME! We should check that the size is right! */
                         if (value->type == EXPR_VALUE) {
+                                if (is_bitfield_type(value->ctype))
+                                        return UNSAFE;
                                 expr->type = EXPR_VALUE;
                                 expr->value = value->value;
                                 expr->taint = 0;
                                 return 0;
                         } else if (value->type == EXPR_FVALUE) {

@@ -786,10 +831,12 @@
 static int expand_symbol_call(struct expression *expr, int cost)
 {
         struct expression *fn = expr->fn;
         struct symbol *ctype = fn->ctype;
 
+        expand_expression(fn);
+
         if (fn->type != EXPR_PREOP)
                 return SIDE_EFFECTS;
 
         if (ctype->op && ctype->op->expand)
                 return ctype->op->expand(expr, cost);

@@ -1046,10 +1093,13 @@
         case EXPR_PTRSIZEOF:
         case EXPR_ALIGNOF:
         case EXPR_OFFSETOF:
                 expression_error(expr, "internal front-end error: sizeof in expansion?");
                 return UNSAFE;
+        case EXPR_ASM_OPERAND:
+                expression_error(expr, "internal front-end error: ASM_OPERAND in expansion?");
+                return UNSAFE;
         }
         return SIDE_EFFECTS;
 }
 
 static void expand_const_expression(struct expression *expr, const char *where)

@@ -1246,14 +1296,16 @@
         if (expr->type != EXPR_VALUE) {
                 if (strict != 2)
                         expression_error(expr, "bad constant expression");
                 return 0;
         }
+#if 0   // This complains about "1 ? 1 :__bits_per()" which the kernel use
         if ((strict == 1) && bad_integer_constant_expression(expr)) {
                 expression_error(expr, "bad integer constant expression");
                 return 0;
         }
+#endif
 
         value = expr->value;
         mask = 1ULL << (ctype->bit_size-1);
 
         if (value & mask) {