Print this page
new smatch

*** 39,53 **** --- 39,59 ---- #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,171 **** expr->fvalue = (float)expr->fvalue; } expr->type = EXPR_FVALUE; } ! static int check_shift_count(struct expression *expr, struct symbol *ctype, unsigned int count) { ! warning(expr->pos, "shift too big (%u) for type %s", count, show_typename(ctype)); ! count &= ctype->bit_size-1; ! return count; } /* * CAREFUL! We need to get the size and sign of the * result right! */ #define CONVERT(op,s) (((op)<<1)+(s)) --- 161,199 ---- expr->fvalue = (float)expr->fvalue; } expr->type = EXPR_FVALUE; } ! static void warn_shift_count(struct expression *expr, struct symbol *ctype, long long 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,196 **** 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) 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); --- 208,220 ---- if (right->type != EXPR_VALUE) return 0; r = right->value; if (expr->op == SPECIAL_LEFTSHIFT || expr->op == SPECIAL_RIGHTSHIFT) { ! if (!check_shift_count(expr, right)) return 0; } 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,486 **** expr->taint |= Taint_comma | taint; } return cost; } ! #define MOD_IGN (MOD_VOLATILE | MOD_CONST) static int compare_types(int op, struct symbol *left, struct symbol *right) { struct ctype c1 = {.base_type = left}; struct ctype c2 = {.base_type = right}; --- 500,510 ---- expr->taint |= Taint_comma | taint; } return cost; } ! #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,570 **** } static int expand_conditional(struct expression *expr) { struct expression *cond = expr->conditional; ! struct expression *true = expr->cond_true; ! struct expression *false = 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; expr->flags = flags; if (expr->type == EXPR_VALUE) expr->taint |= cond->taint; return cost; } ! cost = expand_expression(true); ! cost += expand_expression(false); if (cost < SELECT_COST) { expr->type = EXPR_SELECT; cost -= BRANCH_COST - 1; } return cost + cond_cost + BRANCH_COST; } static int expand_assignment(struct expression *expr) { expand_expression(expr->left); expand_expression(expr->right); return SIDE_EFFECTS; } static int expand_addressof(struct expression *expr) { --- 551,613 ---- } static int expand_conditional(struct expression *expr) { struct expression *cond = expr->conditional; ! 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) ! 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(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,590 **** */ static struct expression *constant_symbol_value(struct symbol *sym, int offset) { struct expression *value; ! if (sym->ctype.modifiers & (MOD_ASSIGNED | MOD_ADDRESSABLE)) return NULL; value = sym->initializer; if (!value) return NULL; if (value->type == EXPR_INITIALIZER) { --- 623,633 ---- */ static struct expression *constant_symbol_value(struct symbol *sym, int offset) { struct expression *value; ! if (sym->ctype.modifiers & MOD_ACCESS) return NULL; value = sym->initializer; if (!value) return NULL; if (value->type == EXPR_INITIALIZER) {
*** 642,651 **** --- 685,696 ---- /* 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,795 **** --- 831,842 ---- 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,1055 **** --- 1093,1105 ---- 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,1259 **** --- 1296,1311 ---- 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) {