85 PREPARE_PTR_LIST(two, two_rel);
86 for (;;) {
87 if (!one_rel || !two_rel)
88 break;
89 if (cmp_relation(one_rel, two_rel) < 0) {
90 NEXT_PTR_LIST(one_rel);
91 } else if (cmp_relation(one_rel, two_rel) == 0) {
92 add_ptr_list(&ret, one_rel);
93 NEXT_PTR_LIST(one_rel);
94 NEXT_PTR_LIST(two_rel);
95 } else {
96 NEXT_PTR_LIST(two_rel);
97 }
98 }
99 FINISH_PTR_LIST(two_rel);
100 FINISH_PTR_LIST(one_rel);
101
102 return ret;
103 }
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 static void add_related(struct related_list **rlist, const char *name, struct symbol *sym)
121 {
122 struct relation *rel;
123 struct relation *new;
124 struct relation tmp = {
125 .name = (char *)name,
126 .sym = sym
127 };
128
129 debug_addition(*rlist, name);
130
131 FOR_EACH_PTR(*rlist, rel) {
132 if (cmp_relation(rel, &tmp) < 0)
133 continue;
134 if (cmp_relation(rel, &tmp) == 0)
135 return;
136 new = alloc_relation(name, sym);
137 INSERT_CURRENT(new, rel);
138 return;
139 } END_FOR_EACH_PTR(rel);
140 new = alloc_relation(name, sym);
141 add_ptr_list(rlist, new);
142 }
143
144 static struct related_list *del_related(struct smatch_state *state, const char *name, struct symbol *sym)
145 {
146 struct relation *tmp;
147 struct relation remove = {
148 .name = (char *)name,
149 .sym = sym,
150 };
195 goto free;
196 remove_from_equiv(name, sym);
197 free:
198 free_string(name);
199 }
200
201 void set_related(struct smatch_state *estate, struct related_list *rlist)
202 {
203 if (!estate_related(estate) && !rlist)
204 return;
205 get_dinfo(estate)->related = rlist;
206 }
207
208 /*
209 * set_equiv() is only used for assignments where we set one variable
210 * equal to the other. a = b;. It's not used for if conditions where
211 * a == b.
212 */
213 void set_equiv(struct expression *left, struct expression *right)
214 {
215 struct sm_state *right_sm, *left_sm;
216 struct relation *rel;
217 char *left_name;
218 struct symbol *left_sym;
219 struct related_list *rlist;
220
221 left_name = expr_to_var_sym(left, &left_sym);
222 if (!left_name || !left_sym)
223 goto free;
224
225 right_sm = get_sm_state_expr(SMATCH_EXTRA, right);
226 if (!right_sm)
227 right_sm = set_state_expr(SMATCH_EXTRA, right, alloc_estate_whole(get_type(right)));
228 if (!right_sm)
229 goto free;
230
231 /* This block is because we want to preserve the implications. */
232 left_sm = clone_sm(right_sm);
233 left_sm->name = alloc_string(left_name);
234 left_sm->sym = left_sym;
235 left_sm->state = clone_estate_cast(get_type(left), right_sm->state);
236 set_extra_mod_helper(left_name, left_sym, left, left_sm->state);
237 __set_sm(left_sm);
238
239 rlist = clone_related_list(estate_related(right_sm->state));
240 add_related(&rlist, right_sm->name, right_sm->sym);
241 add_related(&rlist, left_name, left_sym);
242
243 FOR_EACH_PTR(rlist, rel) {
244 struct sm_state *old_sm, *new_sm;
245
246 old_sm = get_sm_state(SMATCH_EXTRA, rel->name, rel->sym);
247 if (!old_sm) /* shouldn't happen */
248 continue;
249 new_sm = clone_sm(old_sm);
250 new_sm->state = clone_estate(old_sm->state);
251 get_dinfo(new_sm->state)->related = rlist;
252 __set_sm(new_sm);
253 } END_FOR_EACH_PTR(rel);
254 free:
255 free_string(left_name);
256 }
257
258 void set_equiv_state_expr(int id, struct expression *expr, struct smatch_state *state)
259 {
260 struct relation *rel;
261 struct smatch_state *estate;
|
85 PREPARE_PTR_LIST(two, two_rel);
86 for (;;) {
87 if (!one_rel || !two_rel)
88 break;
89 if (cmp_relation(one_rel, two_rel) < 0) {
90 NEXT_PTR_LIST(one_rel);
91 } else if (cmp_relation(one_rel, two_rel) == 0) {
92 add_ptr_list(&ret, one_rel);
93 NEXT_PTR_LIST(one_rel);
94 NEXT_PTR_LIST(two_rel);
95 } else {
96 NEXT_PTR_LIST(two_rel);
97 }
98 }
99 FINISH_PTR_LIST(two_rel);
100 FINISH_PTR_LIST(one_rel);
101
102 return ret;
103 }
104
105 static void add_related(struct related_list **rlist, const char *name, struct symbol *sym)
106 {
107 struct relation *rel;
108 struct relation *new;
109 struct relation tmp = {
110 .name = (char *)name,
111 .sym = sym
112 };
113
114 FOR_EACH_PTR(*rlist, rel) {
115 if (cmp_relation(rel, &tmp) < 0)
116 continue;
117 if (cmp_relation(rel, &tmp) == 0)
118 return;
119 new = alloc_relation(name, sym);
120 INSERT_CURRENT(new, rel);
121 return;
122 } END_FOR_EACH_PTR(rel);
123 new = alloc_relation(name, sym);
124 add_ptr_list(rlist, new);
125 }
126
127 static struct related_list *del_related(struct smatch_state *state, const char *name, struct symbol *sym)
128 {
129 struct relation *tmp;
130 struct relation remove = {
131 .name = (char *)name,
132 .sym = sym,
133 };
178 goto free;
179 remove_from_equiv(name, sym);
180 free:
181 free_string(name);
182 }
183
184 void set_related(struct smatch_state *estate, struct related_list *rlist)
185 {
186 if (!estate_related(estate) && !rlist)
187 return;
188 get_dinfo(estate)->related = rlist;
189 }
190
191 /*
192 * set_equiv() is only used for assignments where we set one variable
193 * equal to the other. a = b;. It's not used for if conditions where
194 * a == b.
195 */
196 void set_equiv(struct expression *left, struct expression *right)
197 {
198 struct sm_state *right_sm, *left_sm, *other_sm;
199 struct relation *rel;
200 char *left_name;
201 struct symbol *left_sym;
202 struct related_list *rlist;
203 char *other_name;
204 struct symbol *other_sym;
205
206 left_name = expr_to_var_sym(left, &left_sym);
207 if (!left_name || !left_sym)
208 goto free;
209
210 other_name = get_other_name_sym(left_name, left_sym, &other_sym);
211
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 }
220 if (!right_sm)
221 goto free;
222
223 /* This block is because we want to preserve the implications. */
224 left_sm = clone_sm(right_sm);
225 left_sm->name = alloc_string(left_name);
226 left_sm->sym = left_sym;
227 left_sm->state = clone_estate_cast(get_type(left), right_sm->state);
228 /* FIXME: The expression we're passing is wrong */
229 set_extra_mod_helper(left_name, left_sym, left, left_sm->state);
230 __set_sm(left_sm);
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
241 rlist = clone_related_list(estate_related(right_sm->state));
242 add_related(&rlist, right_sm->name, right_sm->sym);
243 add_related(&rlist, left_name, left_sym);
244 if (other_name && other_sym)
245 add_related(&rlist, other_name, other_sym);
246
247 FOR_EACH_PTR(rlist, rel) {
248 struct sm_state *old_sm, *new_sm;
249
250 old_sm = get_sm_state(SMATCH_EXTRA, rel->name, rel->sym);
251 if (!old_sm) /* shouldn't happen */
252 continue;
253 new_sm = clone_sm(old_sm);
254 new_sm->state = clone_estate(old_sm->state);
255 get_dinfo(new_sm->state)->related = rlist;
256 __set_sm(new_sm);
257 } END_FOR_EACH_PTR(rel);
258 free:
259 free_string(left_name);
260 }
261
262 void set_equiv_state_expr(int id, struct expression *expr, struct smatch_state *state)
263 {
264 struct relation *rel;
265 struct smatch_state *estate;
|