Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_equiv.c
+++ new/usr/src/tools/smatch/src/smatch_equiv.c
1 1 /*
2 2 * Copyright (C) 2010 Dan Carpenter.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 /*
19 19 * smatch_equiv.c is for tracking how variables are the same
20 20 *
21 21 * if (a == b) {
22 22 * Or
23 23 * x = y;
24 24 *
25 25 * When a variable gets modified all the old relationships are
26 26 * deleted. remove_equiv(expr);
27 27 *
28 28 */
29 29
30 30 #include "smatch.h"
31 31 #include "smatch_slist.h"
32 32 #include "smatch_extra.h"
33 33
34 34 ALLOCATOR(relation, "related variables");
35 35
36 36 static struct relation *alloc_relation(const char *name, struct symbol *sym)
37 37 {
38 38 struct relation *tmp;
39 39
40 40 tmp = __alloc_relation(0);
41 41 tmp->name = alloc_string(name);
42 42 tmp->sym = sym;
43 43 return tmp;
44 44 }
45 45
46 46 struct related_list *clone_related_list(struct related_list *related)
47 47 {
48 48 struct relation *rel;
49 49 struct related_list *to_list = NULL;
50 50
51 51 FOR_EACH_PTR(related, rel) {
52 52 add_ptr_list(&to_list, rel);
53 53 } END_FOR_EACH_PTR(rel);
54 54
55 55 return to_list;
56 56 }
57 57
58 58 static int cmp_relation(struct relation *a, struct relation *b)
59 59 {
60 60 int ret;
61 61
62 62 if (a == b)
63 63 return 0;
64 64
65 65 if (a->sym > b->sym)
66 66 return -1;
67 67 if (a->sym < b->sym)
68 68 return 1;
69 69
70 70 ret = strcmp(a->name, b->name);
71 71 if (ret)
72 72 return ret;
73 73
74 74 return 0;
75 75 }
76 76
77 77 struct related_list *get_shared_relations(struct related_list *one,
78 78 struct related_list *two)
79 79 {
80 80 struct related_list *ret = NULL;
81 81 struct relation *one_rel;
82 82 struct relation *two_rel;
83 83
84 84 PREPARE_PTR_LIST(one, one_rel);
85 85 PREPARE_PTR_LIST(two, two_rel);
86 86 for (;;) {
87 87 if (!one_rel || !two_rel)
88 88 break;
89 89 if (cmp_relation(one_rel, two_rel) < 0) {
90 90 NEXT_PTR_LIST(one_rel);
91 91 } else if (cmp_relation(one_rel, two_rel) == 0) {
92 92 add_ptr_list(&ret, one_rel);
93 93 NEXT_PTR_LIST(one_rel);
94 94 NEXT_PTR_LIST(two_rel);
↓ open down ↓ |
94 lines elided |
↑ open up ↑ |
95 95 } else {
96 96 NEXT_PTR_LIST(two_rel);
97 97 }
98 98 }
99 99 FINISH_PTR_LIST(two_rel);
100 100 FINISH_PTR_LIST(one_rel);
101 101
102 102 return ret;
103 103 }
104 104
105 -static void debug_addition(struct related_list *rlist, const char *name)
106 -{
107 - struct relation *tmp;
108 -
109 - if (!option_debug_related)
110 - return;
111 -
112 - sm_prefix();
113 - sm_printf("(");
114 - FOR_EACH_PTR(rlist, tmp) {
115 - sm_printf("%s ", tmp->name);
116 - } END_FOR_EACH_PTR(tmp);
117 - sm_printf(") <-- %s\n", name);
118 -}
119 -
120 105 static void add_related(struct related_list **rlist, const char *name, struct symbol *sym)
121 106 {
122 107 struct relation *rel;
123 108 struct relation *new;
124 109 struct relation tmp = {
125 110 .name = (char *)name,
126 111 .sym = sym
127 112 };
128 113
129 - debug_addition(*rlist, name);
130 -
131 114 FOR_EACH_PTR(*rlist, rel) {
132 115 if (cmp_relation(rel, &tmp) < 0)
133 116 continue;
134 117 if (cmp_relation(rel, &tmp) == 0)
135 118 return;
136 119 new = alloc_relation(name, sym);
137 120 INSERT_CURRENT(new, rel);
138 121 return;
139 122 } END_FOR_EACH_PTR(rel);
140 123 new = alloc_relation(name, sym);
141 124 add_ptr_list(rlist, new);
142 125 }
143 126
144 127 static struct related_list *del_related(struct smatch_state *state, const char *name, struct symbol *sym)
145 128 {
146 129 struct relation *tmp;
147 130 struct relation remove = {
148 131 .name = (char *)name,
149 132 .sym = sym,
150 133 };
151 134 struct related_list *ret = NULL;
152 135
153 136 FOR_EACH_PTR(estate_related(state), tmp) {
154 137 if (cmp_relation(tmp, &remove) != 0)
155 138 add_ptr_list(&ret, tmp);
156 139 } END_FOR_EACH_PTR(tmp);
157 140
158 141 return ret;
159 142 }
160 143
161 144 void remove_from_equiv(const char *name, struct symbol *sym)
162 145 {
163 146 struct sm_state *orig_sm;
164 147 struct relation *rel;
165 148 struct smatch_state *state;
166 149 struct related_list *to_update;
167 150
168 151 orig_sm = get_sm_state(SMATCH_EXTRA, name, sym);
169 152 if (!orig_sm || !get_dinfo(orig_sm->state)->related)
170 153 return;
171 154
172 155 state = clone_estate(orig_sm->state);
173 156 to_update = del_related(state, name, sym);
174 157
175 158 FOR_EACH_PTR(to_update, rel) {
176 159 struct sm_state *old_sm, *new_sm;
177 160
178 161 old_sm = get_sm_state(SMATCH_EXTRA, rel->name, rel->sym);
179 162 if (!old_sm)
180 163 continue;
181 164
182 165 new_sm = clone_sm(old_sm);
183 166 get_dinfo(new_sm->state)->related = to_update;
184 167 __set_sm(new_sm);
185 168 } END_FOR_EACH_PTR(rel);
186 169 }
187 170
188 171 void remove_from_equiv_expr(struct expression *expr)
189 172 {
190 173 char *name;
191 174 struct symbol *sym;
192 175
193 176 name = expr_to_var_sym(expr, &sym);
194 177 if (!name || !sym)
195 178 goto free;
196 179 remove_from_equiv(name, sym);
197 180 free:
198 181 free_string(name);
199 182 }
200 183
201 184 void set_related(struct smatch_state *estate, struct related_list *rlist)
202 185 {
203 186 if (!estate_related(estate) && !rlist)
204 187 return;
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
205 188 get_dinfo(estate)->related = rlist;
206 189 }
207 190
208 191 /*
209 192 * set_equiv() is only used for assignments where we set one variable
210 193 * equal to the other. a = b;. It's not used for if conditions where
211 194 * a == b.
212 195 */
213 196 void set_equiv(struct expression *left, struct expression *right)
214 197 {
215 - struct sm_state *right_sm, *left_sm;
198 + struct sm_state *right_sm, *left_sm, *other_sm;
216 199 struct relation *rel;
217 200 char *left_name;
218 201 struct symbol *left_sym;
219 202 struct related_list *rlist;
203 + char *other_name;
204 + struct symbol *other_sym;
220 205
221 206 left_name = expr_to_var_sym(left, &left_sym);
222 207 if (!left_name || !left_sym)
223 208 goto free;
224 209
210 + other_name = get_other_name_sym(left_name, left_sym, &other_sym);
211 +
225 212 right_sm = get_sm_state_expr(SMATCH_EXTRA, right);
213 + if (!right_sm) {
214 + struct range_list *rl;
215 +
216 + if (!get_implied_rl(right, &rl))
217 + rl = alloc_whole_rl(get_type(right));
218 + right_sm = set_state_expr(SMATCH_EXTRA, right, alloc_estate_rl(rl));
219 + }
226 220 if (!right_sm)
227 - right_sm = set_state_expr(SMATCH_EXTRA, right, alloc_estate_whole(get_type(right)));
228 - if (!right_sm)
229 221 goto free;
230 222
231 223 /* This block is because we want to preserve the implications. */
232 224 left_sm = clone_sm(right_sm);
233 225 left_sm->name = alloc_string(left_name);
234 226 left_sm->sym = left_sym;
235 227 left_sm->state = clone_estate_cast(get_type(left), right_sm->state);
228 + /* FIXME: The expression we're passing is wrong */
236 229 set_extra_mod_helper(left_name, left_sym, left, left_sm->state);
237 230 __set_sm(left_sm);
238 231
232 + if (other_name && other_sym) {
233 + other_sm = clone_sm(right_sm);
234 + other_sm->name = alloc_string(other_name);
235 + other_sm->sym = other_sym;
236 + other_sm->state = clone_estate_cast(get_type(left), left_sm->state);
237 + set_extra_mod_helper(other_name, other_sym, NULL, other_sm->state);
238 + __set_sm(other_sm);
239 + }
240 +
239 241 rlist = clone_related_list(estate_related(right_sm->state));
240 242 add_related(&rlist, right_sm->name, right_sm->sym);
241 243 add_related(&rlist, left_name, left_sym);
244 + if (other_name && other_sym)
245 + add_related(&rlist, other_name, other_sym);
242 246
243 247 FOR_EACH_PTR(rlist, rel) {
244 248 struct sm_state *old_sm, *new_sm;
245 249
246 250 old_sm = get_sm_state(SMATCH_EXTRA, rel->name, rel->sym);
247 251 if (!old_sm) /* shouldn't happen */
248 252 continue;
249 253 new_sm = clone_sm(old_sm);
250 254 new_sm->state = clone_estate(old_sm->state);
251 255 get_dinfo(new_sm->state)->related = rlist;
252 256 __set_sm(new_sm);
253 257 } END_FOR_EACH_PTR(rel);
254 258 free:
255 259 free_string(left_name);
256 260 }
257 261
258 262 void set_equiv_state_expr(int id, struct expression *expr, struct smatch_state *state)
259 263 {
260 264 struct relation *rel;
261 265 struct smatch_state *estate;
262 266
263 267 estate = get_state_expr(SMATCH_EXTRA, expr);
264 268
265 269 if (!estate)
266 270 return;
267 271
268 272 FOR_EACH_PTR(get_dinfo(estate)->related, rel) {
269 273 set_state(id, rel->name, rel->sym, state);
270 274 } END_FOR_EACH_PTR(rel);
271 275 }
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX