comparison: select the caller_info
[smatch.git] / smatch_var_sym.c
blobfcc4435feb70afaf6230fe49278b65cf8343bd35
1 /*
2 * Copyright (C) 2013 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #include "smatch.h"
20 ALLOCATOR(var_sym, "var_sym structs");
22 struct smatch_state *alloc_var_sym_state(const char *var, struct symbol *sym)
24 struct smatch_state *state;
26 state = __alloc_smatch_state(0);
27 state->name = alloc_string(var);
28 state->data = alloc_var_sym(var, sym);
29 return state;
32 struct var_sym *alloc_var_sym(const char *var, struct symbol *sym)
34 struct var_sym *tmp;
36 tmp = __alloc_var_sym(0);
37 tmp->var = alloc_string(var);
38 tmp->sym = sym;
39 return tmp;
42 struct var_sym_list *expr_to_vsl(struct expression *expr)
44 struct expression *unop;
45 struct var_sym_list *ret = NULL;
46 char *var;
47 struct symbol *sym;
49 expr = strip_expr(expr);
50 if (!expr)
51 return NULL;
53 if (expr_to_sym(expr))
54 goto one_var;
56 if (expr->type == EXPR_BINOP ||
57 expr->type == EXPR_LOGICAL ||
58 expr->type == EXPR_COMPARE) {
59 struct var_sym_list *left, *right;
61 left = expr_to_vsl(expr->left);
62 right = expr_to_vsl(expr->right);
63 ret = combine_var_sym_lists(left, right);
64 free_var_syms_and_list(&left);
65 free_var_syms_and_list(&right);
66 return ret;
69 // handle "*(foo[bar])" I guess */
70 if ((expr->type == EXPR_PREOP && expr->op == '*')) {
71 unop = strip_expr(expr->unop);
73 if (unop->type == EXPR_SYMBOL)
74 goto one_var;
75 return expr_to_vsl(unop);
78 if (expr->type == EXPR_DEREF)
79 return expr_to_vsl(expr->deref);
81 one_var:
82 var = expr_to_var_sym(expr, &sym);
83 if (!var || !sym) {
84 free_string(var);
85 return NULL;
87 add_var_sym(&ret, var, sym);
88 return ret;
91 int cmp_var_sym(const struct var_sym *a, const struct var_sym *b)
93 int ret;
95 if (a == b)
96 return 0;
97 if (!b)
98 return -1;
99 if (!a)
100 return 1;
102 ret = strcmp(a->var, b->var);
103 if (ret < 0)
104 return -1;
105 if (ret > 0)
106 return 1;
108 if (!b->sym && a->sym)
109 return -1;
110 if (!a->sym && b->sym)
111 return 1;
112 if (a->sym < b->sym)
113 return -1;
114 if (a->sym > b->sym)
115 return 1;
117 return 0;
120 void add_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym)
122 struct var_sym *tmp, *new;
124 if (in_var_sym_list(*list, var, sym))
125 return;
126 new = alloc_var_sym(var, sym);
128 FOR_EACH_PTR(*list, tmp) {
129 if (cmp_var_sym(tmp, new) < 0)
130 continue;
131 else if (cmp_var_sym(tmp, new) == 0) {
132 return;
133 } else {
134 INSERT_CURRENT(new, tmp);
135 return;
137 } END_FOR_EACH_PTR(tmp);
138 add_ptr_list(list, new);
141 void add_var_sym_expr(struct var_sym_list **list, struct expression *expr)
143 char *var;
144 struct symbol *sym;
146 var = expr_to_var_sym(expr, &sym);
147 if (!var || !sym)
148 goto free;
149 add_var_sym(list, var, sym);
150 free:
151 free_string(var);
154 static void free_var_sym(struct var_sym *vs)
156 free_string(vs->var);
157 __free_var_sym(vs);
160 void del_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym)
162 struct var_sym *tmp;
164 FOR_EACH_PTR(*list, tmp) {
165 if (tmp->sym == sym && strcmp(tmp->var, var) == 0) {
166 DELETE_CURRENT_PTR(tmp);
167 free_var_sym(tmp);
168 return;
170 } END_FOR_EACH_PTR(tmp);
173 int in_var_sym_list(struct var_sym_list *list, const char *var, struct symbol *sym)
175 struct var_sym *tmp;
177 FOR_EACH_PTR(list, tmp) {
178 if (tmp->sym == sym && strcmp(tmp->var, var) == 0)
179 return 1;
180 } END_FOR_EACH_PTR(tmp);
181 return 0;
184 struct var_sym_list *clone_var_sym_list(struct var_sym_list *from_vsl)
186 struct var_sym *tmp, *clone_vs;
187 struct var_sym_list *to_vsl = NULL;
189 FOR_EACH_PTR(from_vsl, tmp) {
190 clone_vs = alloc_var_sym(tmp->var, tmp->sym);
191 add_ptr_list(&to_vsl, clone_vs);
192 } END_FOR_EACH_PTR(tmp);
193 return to_vsl;
196 void merge_var_sym_list(struct var_sym_list **dest, struct var_sym_list *src)
198 struct var_sym *tmp;
200 FOR_EACH_PTR(src, tmp) {
201 add_var_sym(dest, tmp->var, tmp->sym);
202 } END_FOR_EACH_PTR(tmp);
205 struct var_sym_list *combine_var_sym_lists(struct var_sym_list *one, struct var_sym_list *two)
207 struct var_sym_list *to_vsl;
209 to_vsl = clone_var_sym_list(one);
210 merge_var_sym_list(&to_vsl, two);
211 return to_vsl;
214 int var_sym_lists_equiv(struct var_sym_list *one, struct var_sym_list *two)
216 struct var_sym *one_tmp, *two_tmp;
218 if (one == two)
219 return 1;
221 if (ptr_list_size((struct ptr_list *)one) != ptr_list_size((struct ptr_list *)two))
222 return 0;
224 PREPARE_PTR_LIST(one, one_tmp);
225 PREPARE_PTR_LIST(two, two_tmp);
226 for (;;) {
227 if (!one_tmp && !two_tmp)
228 return 1;
229 if (one_tmp->sym != two_tmp->sym)
230 return 0;
231 if (strcmp(one_tmp->var, two_tmp->var) != 0)
232 return 0;
233 NEXT_PTR_LIST(one_tmp);
234 NEXT_PTR_LIST(two_tmp);
236 FINISH_PTR_LIST(two_tmp);
237 FINISH_PTR_LIST(one_tmp);
239 return 1;
242 void free_var_sym_list(struct var_sym_list **list)
244 __free_ptr_list((struct ptr_list **)list);
247 void free_var_syms_and_list(struct var_sym_list **list)
249 struct var_sym *tmp;
251 FOR_EACH_PTR(*list, tmp) {
252 free_var_sym(tmp);
253 } END_FOR_EACH_PTR(tmp);
254 free_var_sym_list(list);