C has only positive constants: -1 is really an expression, the unary '-' operator applied to the constant 1. '-1' as a constant value only exists after the expansion of constant expressions. This is rather unfortunate since it inhibits easy testing of such constants in the evaluation phase, like here for restricted_value(). So, expand expressions like +CTE, -CTE or ~CTE before calling restricted_value(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- evaluate.c | 48 +++++++++++++++++++++++++++++++++- validation/bitwise-cast.c | 13 +++++++++ validation/bitwise-is-signed.c | 1 - 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/evaluate.c b/evaluate.c index bb8c0caa905a..33cc85c8d40f 100644 --- a/evaluate.c +++ b/evaluate.c @@ -413,11 +413,56 @@ static struct symbol *bad_expr_type(struct expression *expr) return expr->ctype = &bad_ctype; } +static bool expand_simple_constant(struct expression *expr, struct symbol *type) +{ + unsigned long long val, mask; + struct expression *pre; + struct symbol *ctype; + unsigned size; + + if (expr->type != EXPR_PREOP) + return false; + pre = expr->unop; + if (pre->type != EXPR_VALUE) + return false; + + ctype = pre->ctype; + if (!ctype || ctype != type) + return false; + + size = ctype->bit_size; + if (!size) + return false; + + mask = sign_bit(size); + switch (expr->op) { + case '+': + val = pre->value; + break; + case '-': + val = pre->value; + if (val == mask && !(ctype->ctype.modifiers & MOD_UNSIGNED)) + return false; + val = -val; + break; + case '~': + val = pre->value; + val = ~val; + break; + default: + return false; + } + expr->op = 0; + expr->type = EXPR_VALUE; + expr->value = val & bits_mask(size); + return true; +} + static int restricted_value(struct expression *v, struct symbol *type) { if (v->type != EXPR_VALUE) return 1; - if (v->value != 0 && v->value != bits_mask(type->bit_size)) + if (v->value != 0 && v->value != bits_mask(v->ctype->bit_size)) return 1; return 0; } @@ -1919,6 +1964,7 @@ Normal: if (!(class & TYPE_FLOAT)) { ctype = integer_promotion(ctype); expr->unop = cast_to(expr->unop, ctype); + expand_simple_constant(expr, ctype); } else if (expr->op != '~') { /* no conversions needed */ } else { diff --git a/validation/bitwise-cast.c b/validation/bitwise-cast.c index 1075a3e9410c..01af56c73751 100644 --- a/validation/bitwise-cast.c +++ b/validation/bitwise-cast.c @@ -48,6 +48,19 @@ static __be32 bar1(void) return (__be32)0xffffffff; } +/* Implicit casts of minus one, legal */ +static __be32 foom(void) +{ + __be32 x = -1; + return x; +} + +/* Explicit cast of minus one, legal */ +static __be32 barm(void) +{ + return (__be32)-1; +} + /* * check-name: conversions to bitwise types * check-command: sparse -Wbitwise $file diff --git a/validation/bitwise-is-signed.c b/validation/bitwise-is-signed.c index dd9c147173cd..99d16bd20f9b 100644 --- a/validation/bitwise-is-signed.c +++ b/validation/bitwise-is-signed.c @@ -15,7 +15,6 @@ int fou(void) { return !is_signed_type(u); } /* * check-name: bitwise-is-signed * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-returns: 1 -- 2.36.1