Add a new function slist_has_state()
[smatch.git] / smatch_extra.c
blob1d9e232a89daa1b58f730180383164e6a282dad9
1 /*
2 * sparse/smatch_extra.c
4 * Copyright (C) 2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdlib.h>
11 #include "parse.h"
12 #include "smatch.h"
14 static int my_id;
16 static int _zero = 0;
17 static int _one = 1;
19 static struct smatch_state zero = {
20 .name = "zero",
21 .data = &_zero,
24 static struct smatch_state one = {
25 .name = "one",
26 .data = &_one,
29 static struct smatch_state *alloc_state(int val)
31 struct smatch_state *state;
33 if (val == 0)
34 return &zero;
35 if (val == 1)
36 return &one;
37 if (val == UNDEFINED)
38 return &undefined;
40 state = malloc(sizeof(*state));
41 state->name = "value";
42 state->data = malloc(sizeof(int));
43 *(int *)state->data = val;
44 return state;
47 static struct smatch_state *merge_func(const char *name, struct symbol *sym,
48 struct smatch_state *s1,
49 struct smatch_state *s2)
51 return &undefined;
54 static void match_function_call_after(struct expression *expr)
56 struct expression *tmp;
57 struct symbol *sym;
58 char *name;
59 int i = 0;
61 FOR_EACH_PTR(expr->args, tmp) {
62 if (tmp->op == '&') {
63 name = get_variable_from_expr(tmp->unop, &sym);
64 if (name) {
65 set_state(name, my_id, sym, &undefined);
68 i++;
69 } END_FOR_EACH_PTR(tmp);
72 static void match_assign(struct expression *expr)
74 struct expression *left;
75 struct symbol *sym;
76 char *name;
78 left = strip_expr(expr->left);
79 name = get_variable_from_expr(left, &sym);
80 if (!name)
81 return;
82 set_state(name, my_id, sym, alloc_state(get_value(expr->right)));
85 static void undef_expr(struct expression *expr)
87 struct symbol *sym;
88 char *name;
90 name = get_variable_from_expr(expr->unop, &sym);
91 if (!name)
92 return;
93 if (!get_state(name, my_id, sym)) {
94 free_string(name);
95 return;
97 set_state(name, my_id, sym, &undefined);
100 static void match_declarations(struct symbol *sym)
102 const char *name;
104 if (sym->ident) {
105 name = sym->ident->name;
106 if (sym->initializer) {
107 set_state(name, my_id, sym, alloc_state(get_value(sym->initializer)));
112 static void match_unop(struct expression *expr)
114 struct symbol *sym;
115 char *name;
116 const char *tmp;
119 name = get_variable_from_expr(expr->unop, &sym);
120 if (!name)
121 return;
123 tmp = show_special(expr->op);
124 if ((!strcmp(tmp, "--")) || (!strcmp(tmp, "++")))
125 set_state(name, my_id, sym, &undefined);
128 void register_smatch_extra(int id)
130 my_id = id;
131 add_merge_hook(my_id, &merge_func);
132 add_hook(&undef_expr, OP_HOOK);
133 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
134 add_hook(&match_assign, ASSIGNMENT_AFTER_HOOK);
135 add_hook(&match_declarations, DECLARATION_HOOK);
136 add_hook(&match_unop, OP_HOOK);
137 add_hook(&__implied_states_hook, WHOLE_CONDITION_HOOK);
140 static int expr_to_val(struct expression *expr)
142 struct smatch_state *state;
143 int val;
144 struct symbol *sym;
145 char *name;
147 val = get_value(expr);
148 if (val != UNDEFINED)
149 return val;
151 name = get_variable_from_expr(expr, &sym);
152 if (!name)
153 return UNDEFINED;
154 state = get_state(name, my_id, sym);
155 free_string(name);
156 if (!state || !state->data)
157 return UNDEFINED;
158 return *(int *)state->data;
161 static int true_comparison(int left, int comparison, int right)
163 switch(comparison){
164 case '<':
165 case SPECIAL_UNSIGNED_LT:
166 if (left < right)
167 return 1;
168 return 0;
169 case SPECIAL_UNSIGNED_LTE:
170 case SPECIAL_LTE:
171 if (left < right)
172 return 1;
173 case SPECIAL_EQUAL:
174 if (left == right)
175 return 1;
176 return 0;
177 case SPECIAL_UNSIGNED_GTE:
178 case SPECIAL_GTE:
179 if (left == right)
180 return 1;
181 case '>':
182 case SPECIAL_UNSIGNED_GT:
183 if (left > right)
184 return 1;
185 return 0;
186 case SPECIAL_NOTEQUAL:
187 if (left != right)
188 return 1;
189 return 0;
190 default:
191 smatch_msg("unhandled comparison %d\n", comparison);
193 return 0;
196 int known_condition_true(struct expression *expr)
198 int left, right, ret;
200 if (!expr || expr->type != EXPR_COMPARE)
201 return 0;
203 if ((left = expr_to_val(expr->left)) == UNDEFINED)
204 return 0;
206 if ((right = expr_to_val(expr->right)) == UNDEFINED)
207 return 0;
209 ret = true_comparison(left, expr->op, right);
210 if (ret)
211 SM_DEBUG("%d known condition: %d %s %d => true", get_lineno(),
212 left, show_special(expr->op), right);
213 else
214 smatch_msg("known condition: %d %s %d => false", left,
215 show_special(expr->op), right);
217 return ret;