new function: type_unsigned()
[smatch.git] / check_signed.c
blob33508b060db025e5b843e7500aba1843a74d9955
1 /*
2 * sparse/check_signed.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
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.
18 #include "smatch.h"
20 static int my_id;
22 #define VAR_ON_RIGHT 0
23 #define VAR_ON_LEFT 1
25 static void match_assign(struct expression *expr)
27 struct symbol *sym;
28 long long val;
29 long long max;
30 long long min;
31 char *name;
33 sym = get_type(expr->left);
34 if (!sym) {
35 //sm_msg("could not get type");
36 return;
38 if (sym->bit_size >= 32) /* max_val limits this */
39 return;
40 if (!get_implied_value(expr->right, &val))
41 return;
42 max = type_max(sym);
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);
46 free_string(name);
48 min = type_min(sym);
49 if (min > val) {
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);
52 free_string(name);
57 static const char *get_tf(long long variable, long long known, int var_pos, char op)
59 if (op == SPECIAL_EQUAL)
60 return "false";
61 if (op == SPECIAL_NOTEQUAL)
62 return "true";
63 if (var_pos == VAR_ON_LEFT) {
64 if (variable > known && (op == '<' || op == SPECIAL_LTE))
65 return "false";
66 if (variable > known && (op == '>' || op == SPECIAL_GTE))
67 return "true";
68 if (variable < known && (op == '<' || op == SPECIAL_LTE))
69 return "true";
70 if (variable < known && (op == '>' || op == SPECIAL_GTE))
71 return "false";
73 if (var_pos == VAR_ON_RIGHT) {
74 if (known > variable && (op == '<' || op == SPECIAL_LTE))
75 return "false";
76 if (known > variable && (op == '>' || op == SPECIAL_GTE))
77 return "true";
78 if (known < variable && (op == '<' || op == SPECIAL_LTE))
79 return "true";
80 if (known < variable && (op == '>' || op == SPECIAL_GTE))
81 return "false";
83 return "the same";
86 static void match_condition(struct expression *expr)
88 long long known;
89 struct expression *var = NULL;
90 struct symbol *type = NULL;
91 long long max;
92 long long min;
93 int lr;
94 char *name;
96 if (expr->type != EXPR_COMPARE)
97 return;
99 if (get_value(expr->left, &known)) {
100 lr = VAR_ON_RIGHT;
101 var = expr->right;
102 } else if (get_value(expr->right, &known)) {
103 lr = VAR_ON_LEFT;
104 var = expr->left;
105 } else {
106 return;
109 type = get_type(var);
110 if (!type || type->bit_size >= 32)
111 return;
113 max = type_max(type);
114 if (!max)
115 return;
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);
122 goto free;
125 if (known == 0) {
126 if (!type_unsigned(type))
127 goto free;
128 if (lr == VAR_ON_LEFT) {
129 if (expr->op == '<')
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) {
135 if (expr->op == '>')
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);
140 goto free;
143 if (max < known) {
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);
150 if (min > known) {
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);
156 free:
157 free_string(name);
160 void check_signed(int id)
162 my_id = id;
164 add_hook(&match_assign, ASSIGNMENT_HOOK);
165 add_hook(&match_condition, CONDITION_HOOK);