aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-08-23 12:34:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-08-23 12:34:27 -0700
commit18f17cde1e9835bb301e4ca64e0898166b155c90 (patch)
tree23ebbd20b80dc718b17165e7afb3687aecf911b1
parentd618d8e6043e229de0358b24bc793ef10e3e041b (diff)
downloadsparse-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.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/evaluate.c b/evaluate.c
index ad4db0d5..f49a0614 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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);