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) {