make everything use smatch_function_hashtable.h
[smatch.git] / check_signed.c
blobf4c846cabfa030ca17d25c16fc0fff3faca1a7a2
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 RIGHT 0
23 #define LEFT 1
25 static int is_unsigned(struct symbol *base_type)
27 if (base_type->ctype.modifiers & MOD_UNSIGNED)
28 return 1;
29 return 0;
32 static void match_assign(struct expression *expr)
34 struct symbol *sym;
35 long long val;
36 long long max;
37 long long min;
38 char *name;
40 sym = get_type(expr->left);
41 if (!sym) {
42 //sm_msg("could not get type");
43 return;
45 if (sym->bit_size >= 32) /* max_val limits this */
46 return;
47 if (!get_implied_value(expr->right, &val))
48 return;
49 max = type_max(sym);
50 if (max && max < val) {
51 name = get_variable_from_expr_complex(expr->left, NULL);
52 sm_msg("warn: value %lld can't fit into %lld '%s'", val, max, name);
53 free_string(name);
55 min = type_min(sym);
56 if (min > val) {
57 name = get_variable_from_expr_complex(expr->left, NULL);
58 sm_msg("warn: value %lld can't fit into %lld '%s'", val, min, name);
59 free_string(name);
64 static void match_condition(struct expression *expr)
66 long long known;
67 struct expression *var = NULL;
68 struct symbol *type = NULL;
69 long long max;
70 int lr;
71 char *name;
73 if (expr->type != EXPR_COMPARE)
74 return;
76 if (get_value(expr->left, &known)) {
77 lr = RIGHT;
78 var = expr->right;
79 } else if (get_value(expr->right, &known)) {
80 lr = LEFT;
81 var = expr->left;
82 } else {
83 return;
86 type = get_type(var);
87 if (!type || type->bit_size >= 32)
88 return;
90 max = type_max(type);
91 if (!max)
92 return;
94 name = get_variable_from_expr_complex(var, NULL);
96 if (known < 0) {
97 if (is_unsigned(type))
98 sm_msg("error: comparing unsigned '%s' to negative", name);
99 goto free;
102 if (known == 0) {
103 if (!is_unsigned(type))
104 goto free;
105 if (lr == LEFT) {
106 if (expr->op == '<')
107 sm_msg("error: unsigned '%s' cannot be less than 0", name);
108 if (expr->op == SPECIAL_LTE)
109 sm_msg("warn: unsigned '%s' cannot be less than 0", name);
111 if (lr == RIGHT) {
112 if (expr->op == '>')
113 sm_msg("error: unsigned '%s' cannot be less than 0", name);
114 if (expr->op == SPECIAL_GTE)
115 sm_msg("warn: unsigned '%s' cannot be less than 0", name);
117 goto free;
120 if (max < known) {
121 const char *tf = "the same";
123 if (expr->op == SPECIAL_EQUAL)
124 tf = "false";
125 if (expr->op == SPECIAL_NOTEQUAL)
126 tf = "true";
127 if (lr == LEFT && (expr->op == '<' || expr->op == SPECIAL_LTE))
128 tf = "true";
129 if (lr == RIGHT && (expr->op == '>' || expr->op == SPECIAL_GTE))
130 tf = "false";
131 sm_msg("warn: %lld is higher than %lld (max '%s' can be) so this is always %s.",
132 known, max, name, tf);
134 free:
135 free_string(name);
138 void check_signed(int id)
140 my_id = id;
142 add_hook(&match_assign, ASSIGNMENT_HOOK);
143 add_hook(&match_condition, CONDITION_HOOK);