diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-23 12:34:27 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-23 12:34:27 -0700 |
commit | 18f17cde1e9835bb301e4ca64e0898166b155c90 (patch) | |
tree | 23ebbd20b80dc718b17165e7afb3687aecf911b1 | |
parent | d618d8e6043e229de0358b24bc793ef10e3e041b (diff) | |
download | sparse-18f17cde1e9835bb301e4ca64e0898166b155c90.tar.gz |
allow restricted ordered compares with unrestricted values
It's fine to order bitwise entities wrt the special values that have all
bits clear or all bits set.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | evaluate.c | 23 |
1 files changed, 20 insertions, 3 deletions
@@ -425,7 +425,17 @@ static int restricted_value(struct expression *v, struct symbol *type) return 0; } -static int restricted_binop(int op, struct symbol *type) +/* + * Bitwise types can do ordered comparisons with + * the unrestricted values, but not in general + */ +static bool can_order(struct expression *left, struct expression *right) +{ + return !restricted_value(left, left->ctype) || + !restricted_value(right, right->ctype); +} + +static int restricted_binop(int op, struct symbol *type, struct expression *left, struct expression *right) { switch (op) { case '&': @@ -438,6 +448,13 @@ static int restricted_binop(int op, struct symbol *type) case '^': case '?': return 2; /* keep fouled */ + case '<': + case '>': + case SPECIAL_LTE: + case SPECIAL_GTE: + if (can_order(left, right)) + return 3; + return 0; case SPECIAL_EQUAL: case SPECIAL_NOTEQUAL: return 3; /* warn if fouled */ @@ -490,7 +507,7 @@ static struct symbol *restricted_binop_type(int op, ctype = rtype; if (ctype) { - switch (restricted_binop(op, ctype)) { + switch (restricted_binop(op, ctype, left, right)) { case 1: if ((lclass ^ rclass) & TYPE_FOULED) ctype = unfoul(ctype); @@ -1311,7 +1328,7 @@ static int evaluate_assign_op(struct expression *expr) return 0; } if (tclass & TYPE_RESTRICT) { - if (!restricted_binop(op, t)) { + if (!restricted_binop(op, t, expr->left, expr->right)) { warning(expr->pos, "bad assignment (%s) to %s", show_special(op), show_typename(t)); expr->right = cast_to(expr->right, target); |