2 * sparse/check_signed.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * Check for things which are signed but probably should be unsigned.
13 * Hm... It seems like at this point in the processing, sparse makes all
14 * bitfields unsigned. Which is logical but not what GCC does.
22 #define VAR_ON_RIGHT 0
25 static void match_assign(struct expression
*expr
)
33 sym
= get_type(expr
->left
);
35 //sm_msg("could not get type");
38 if (sym
->bit_size
>= 32) /* max_val limits this */
40 if (!get_implied_value(expr
->right
, &val
))
43 if (max
&& max
< val
) {
44 name
= get_variable_from_expr_complex(expr
->left
, NULL
);
45 sm_msg("warn: value %lld can't fit into %lld '%s'", val
, max
, name
);
50 name
= get_variable_from_expr_complex(expr
->left
, NULL
);
51 sm_msg("warn: value %lld can't fit into %lld '%s'", val
, min
, name
);
57 static const char *get_tf(long long variable
, long long known
, int var_pos
, char op
)
59 if (op
== SPECIAL_EQUAL
)
61 if (op
== SPECIAL_NOTEQUAL
)
63 if (var_pos
== VAR_ON_LEFT
) {
64 if (variable
> known
&& (op
== '<' || op
== SPECIAL_LTE
))
66 if (variable
> known
&& (op
== '>' || op
== SPECIAL_GTE
))
68 if (variable
< known
&& (op
== '<' || op
== SPECIAL_LTE
))
70 if (variable
< known
&& (op
== '>' || op
== SPECIAL_GTE
))
73 if (var_pos
== VAR_ON_RIGHT
) {
74 if (known
> variable
&& (op
== '<' || op
== SPECIAL_LTE
))
76 if (known
> variable
&& (op
== '>' || op
== SPECIAL_GTE
))
78 if (known
< variable
&& (op
== '<' || op
== SPECIAL_LTE
))
80 if (known
< variable
&& (op
== '>' || op
== SPECIAL_GTE
))
86 static void match_condition(struct expression
*expr
)
89 struct expression
*var
= NULL
;
90 struct symbol
*type
= NULL
;
96 if (expr
->type
!= EXPR_COMPARE
)
99 if (get_value(expr
->left
, &known
)) {
102 } else if (get_value(expr
->right
, &known
)) {
109 type
= get_type(var
);
110 if (!type
|| type
->bit_size
>= 32)
113 max
= type_max(type
);
116 min
= type_min(type
);
118 name
= get_variable_from_expr_complex(var
, NULL
);
120 if (known
< 0 && type_unsigned(type
)) {
121 sm_msg("error: comparing unsigned '%s' to negative", name
);
126 if (!type_unsigned(type
))
128 if (lr
== VAR_ON_LEFT
) {
130 sm_msg("error: unsigned '%s' cannot be less than 0", name
);
131 if (expr
->op
== SPECIAL_LTE
)
132 sm_msg("warn: unsigned '%s' cannot be less than 0", name
);
134 if (lr
== VAR_ON_RIGHT
) {
136 sm_msg("error: unsigned '%s' cannot be less than 0", name
);
137 if (expr
->op
== SPECIAL_GTE
)
138 sm_msg("warn: unsigned '%s' cannot be less than 0", name
);
144 const char *tf
= get_tf(max
, known
, lr
, expr
->op
);
146 sm_msg("warn: %lld is more than %lld (max '%s' can be) so this is always %s.",
147 known
, max
, name
, tf
);
151 const char *tf
= get_tf(max
, known
, lr
, expr
->op
);
153 sm_msg("warn: %lld is less than %lld (min '%s' can be) so this is always %s.",
154 known
, min
, name
, tf
);
160 void check_signed(int id
)
164 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
165 add_hook(&match_condition
, CONDITION_HOOK
);