1 /* Symbolic values.
2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "diagnostic-core.h"
26 #include "gimple-pretty-print.h"
27 #include "function.h"
28 #include "basic-block.h"
29 #include "gimple.h"
30 #include "gimple-iterator.h"
31 #include "diagnostic-core.h"
32 #include "graphviz.h"
33 #include "options.h"
34 #include "cgraph.h"
35 #include "tree-dfa.h"
36 #include "stringpool.h"
37 #include "convert.h"
38 #include "target.h"
39 #include "fold-const.h"
40 #include "tree-pretty-print.h"
41 #include "tristate.h"
42 #include "bitmap.h"
43 #include "selftest.h"
44 #include "function.h"
45 #include "json.h"
46 #include "analyzer/analyzer.h"
47 #include "analyzer/analyzer-logging.h"
48 #include "options.h"
49 #include "cgraph.h"
50 #include "cfg.h"
51 #include "digraph.h"
52 #include "analyzer/call-string.h"
53 #include "analyzer/program-point.h"
54 #include "analyzer/store.h"
55 #include "analyzer/svalue.h"
56 #include "analyzer/region-model.h"
57
58 #if ENABLE_ANALYZER
59
60 namespace ana {
61
62 static int cmp_csts_and_types (const_tree cst1, const_tree cst2);
63
64 /* class svalue and its various subclasses. */
65
66 /* class svalue. */
67
68 /* Dump a representation of this svalue to stderr. */
69
70 DEBUG_FUNCTION void
dump(bool simple) const71 svalue::dump (bool simple) const
72 {
73 pretty_printer pp;
74 pp_format_decoder (&pp) = default_tree_printer;
75 pp_show_color (&pp) = pp_show_color (global_dc->printer);
76 pp.buffer->stream = stderr;
77 dump_to_pp (&pp, simple);
78 pp_newline (&pp);
79 pp_flush (&pp);
80 }
81
82 /* Generate a textual representation of this svalue for debugging purposes. */
83
84 label_text
get_desc(bool simple) const85 svalue::get_desc (bool simple) const
86 {
87 pretty_printer pp;
88 pp_format_decoder (&pp) = default_tree_printer;
89 dump_to_pp (&pp, simple);
90 return label_text::take (xstrdup (pp_formatted_text (&pp)));
91 }
92
93 /* Return a new json::string describing the svalue. */
94
95 json::value *
to_json() const96 svalue::to_json () const
97 {
98 label_text desc = get_desc (true);
99 json::value *sval_js = new json::string (desc.m_buffer);
100 desc.maybe_free ();
101 return sval_js;
102 }
103
104 /* If this svalue is a constant_svalue, return the underlying tree constant.
105 Otherwise return NULL_TREE. */
106
107 tree
maybe_get_constant() const108 svalue::maybe_get_constant () const
109 {
110 const svalue *sval = unwrap_any_unmergeable ();
111 if (const constant_svalue *cst_sval = sval->dyn_cast_constant_svalue ())
112 return cst_sval->get_constant ();
113 else
114 return NULL_TREE;
115 }
116
117 /* If this svalue is a region_svalue, return the region it points to.
118 Otherwise return NULL. */
119
120 const region *
maybe_get_region() const121 svalue::maybe_get_region () const
122 {
123 if (const region_svalue *region_sval = dyn_cast_region_svalue ())
124 return region_sval->get_pointee ();
125 else
126 return NULL;
127 }
128
129 /* If this svalue is a cast (i.e a unaryop NOP_EXPR or VIEW_CONVERT_EXPR),
130 return the underlying svalue.
131 Otherwise return NULL. */
132
133 const svalue *
maybe_undo_cast() const134 svalue::maybe_undo_cast () const
135 {
136 if (const unaryop_svalue *unaryop_sval = dyn_cast_unaryop_svalue ())
137 {
138 enum tree_code op = unaryop_sval->get_op ();
139 if (op == NOP_EXPR || op == VIEW_CONVERT_EXPR)
140 return unaryop_sval->get_arg ();
141 }
142 return NULL;
143 }
144
145 /* If this svalue is an unmergeable decorator around another svalue, return
146 the underlying svalue.
147 Otherwise return this svalue. */
148
149 const svalue *
unwrap_any_unmergeable() const150 svalue::unwrap_any_unmergeable () const
151 {
152 if (const unmergeable_svalue *unmergeable = dyn_cast_unmergeable_svalue ())
153 return unmergeable->get_arg ();
154 return this;
155 }
156
157 /* Attempt to merge THIS with OTHER, returning the merged svalue.
158 Return NULL if not mergeable. */
159
160 const svalue *
can_merge_p(const svalue * other,region_model_manager * mgr,model_merger * merger) const161 svalue::can_merge_p (const svalue *other,
162 region_model_manager *mgr,
163 model_merger *merger) const
164 {
165 if (!(get_type () && other->get_type ()))
166 return NULL;
167
168 if (!types_compatible_p (get_type (), other->get_type ()))
169 return NULL;
170
171 /* Reject attempts to merge unmergeable svalues. */
172 if ((get_kind () == SK_UNMERGEABLE)
173 || (other->get_kind () == SK_UNMERGEABLE))
174 return NULL;
175
176 /* Reject attempts to merge poisoned svalues with other svalues
177 (either non-poisoned, or other kinds of poison), so that e.g.
178 we identify paths in which a variable is conditionally uninitialized. */
179 if (get_kind () == SK_POISONED
180 || other->get_kind () == SK_POISONED)
181 return NULL;
182
183 /* Reject attempts to merge NULL pointers with not-NULL-pointers. */
184 if (POINTER_TYPE_P (get_type ()))
185 {
186 bool null0 = false;
187 bool null1 = false;
188 if (tree cst0 = maybe_get_constant ())
189 if (zerop (cst0))
190 null0 = true;
191 if (tree cst1 = other->maybe_get_constant ())
192 if (zerop (cst1))
193 null1 = true;
194 if (null0 != null1)
195 return NULL;
196 }
197
198 /* Reject merging svalues that have non-purgable sm-state,
199 to avoid falsely reporting memory leaks by merging them
200 with something else. */
201 if (!merger->mergeable_svalue_p (this))
202 return NULL;
203 if (!merger->mergeable_svalue_p (other))
204 return NULL;
205
206 /* Widening. */
207 /* Merge: (new_cst, existing_cst) -> widen (existing, new). */
208 if (maybe_get_constant () && other->maybe_get_constant ())
209 {
210 return mgr->get_or_create_widening_svalue (other->get_type (),
211 merger->m_point,
212 other, this);
213 }
214
215 /* Merger of:
216 this: BINOP (X, OP, CST)
217 other: X, where X is non-widening
218 to: WIDENING (other, this). */
219 if (const binop_svalue *binop_sval = dyn_cast_binop_svalue ())
220 if (binop_sval->get_arg0 () == other
221 && binop_sval->get_arg1 ()->get_kind () == SK_CONSTANT
222 && other->get_kind () != SK_WIDENING)
223 return mgr->get_or_create_widening_svalue (other->get_type (),
224 merger->m_point,
225 other, this);
226
227 /* Merge: (Widen(existing_val, V), existing_val) -> Widen (existing_val, V)
228 and thus get a fixed point. */
229 if (const widening_svalue *widen_sval = dyn_cast_widening_svalue ())
230 {
231 if (other == widen_sval->get_base_svalue ())
232 return this;
233 if (other == widen_sval->get_iter_svalue ())
234 return this;
235 }
236
237 if (const binop_svalue *binop_sval = dyn_cast_binop_svalue ())
238 if (const widening_svalue *widen_arg0
239 = binop_sval->get_arg0 ()->dyn_cast_widening_svalue ())
240 {
241 if (other == binop_sval->get_arg1 ())
242 {
243 /* Merger of: (Widen(..., OTHER) BINOP X)
244 and : OTHER
245 to : (Widen(..., OTHER) BINOP X)
246 e.g. merge of Widen(0, 1) + 1 with 1 to the Widen(0, 1) + 1. */
247 return this;
248 }
249
250 /* Merger of : (Widen() BINOP X)
251 and : Widen()
252 to : Widen()
253 e.g. merge of Widen(0, 1) + 1 and Widen(0, 1) to Widen(0, 1).
254 However, we want to update constraints for this case, since we're
255 considering another iteration.
256 Presumably we also want to ensure that it converges; we don't want
257 a descending chain of constraints. */
258 if (other == widen_arg0)
259 {
260 return widen_arg0;
261 }
262
263 /* Merger of:
264 this: BINOP(WIDENING(BASE, BINOP(BASE, X)), X)
265 other: BINOP(BASE, X)
266 to: WIDENING(BASE, BINOP(BASE, X)). */
267 if (widen_arg0->get_iter_svalue () == other)
268 if (const binop_svalue *other_binop_sval
269 = other->dyn_cast_binop_svalue ())
270 if (other_binop_sval->get_arg0 () == widen_arg0->get_base_svalue ()
271 && other_binop_sval->get_arg1 () == binop_sval->get_arg1 ())
272 return widen_arg0;
273 }
274
275 return mgr->get_or_create_unknown_svalue (get_type ());
276 }
277
278 /* Determine if this svalue is either within LIVE_SVALUES, or is implicitly
279 live with respect to LIVE_SVALUES and MODEL.
280 LIVE_SVALUES can be NULL, in which case determine if this svalue is
281 intrinsically live. */
282
283 bool
live_p(const svalue_set * live_svalues,const region_model * model) const284 svalue::live_p (const svalue_set *live_svalues,
285 const region_model *model) const
286 {
287 /* Determine if SVAL is explicitly live. */
288 if (live_svalues)
289 if (const_cast<svalue_set *> (live_svalues)->contains (this))
290 return true;
291
292 /* Otherwise, determine if SVAL is implicitly live due to being made of
293 other live svalues. */
294 return implicitly_live_p (live_svalues, model);
295 }
296
297 /* Base implementation of svalue::implicitly_live_p. */
298
299 bool
implicitly_live_p(const svalue_set *,const region_model *) const300 svalue::implicitly_live_p (const svalue_set *, const region_model *) const
301 {
302 return false;
303 }
304
305 /* Comparator for imposing a deterministic order on constants that are
306 of the same type. */
307
308 static int
cmp_csts_same_type(const_tree cst1,const_tree cst2)309 cmp_csts_same_type (const_tree cst1, const_tree cst2)
310 {
311 gcc_assert (TREE_TYPE (cst1) == TREE_TYPE (cst2));
312 gcc_assert (TREE_CODE (cst1) == TREE_CODE (cst2));
313 switch (TREE_CODE (cst1))
314 {
315 default:
316 gcc_unreachable ();
317 case INTEGER_CST:
318 return tree_int_cst_compare (cst1, cst2);
319 case STRING_CST:
320 return strcmp (TREE_STRING_POINTER (cst1),
321 TREE_STRING_POINTER (cst2));
322 case REAL_CST:
323 /* Impose an arbitrary but deterministic order. */
324 return memcmp (TREE_REAL_CST_PTR (cst1),
325 TREE_REAL_CST_PTR (cst2),
326 sizeof (real_value));
327 case COMPLEX_CST:
328 if (int cmp_real = cmp_csts_and_types (TREE_REALPART (cst1),
329 TREE_REALPART (cst2)))
330 return cmp_real;
331 return cmp_csts_and_types (TREE_IMAGPART (cst1), TREE_IMAGPART (cst2));
332 case VECTOR_CST:
333 if (int cmp_log2_npatterns
334 = ((int)VECTOR_CST_LOG2_NPATTERNS (cst1)
335 - (int)VECTOR_CST_LOG2_NPATTERNS (cst2)))
336 return cmp_log2_npatterns;
337 if (int cmp_nelts_per_pattern
338 = ((int)VECTOR_CST_NELTS_PER_PATTERN (cst1)
339 - (int)VECTOR_CST_NELTS_PER_PATTERN (cst2)))
340 return cmp_nelts_per_pattern;
341 unsigned encoded_nelts = vector_cst_encoded_nelts (cst1);
342 for (unsigned i = 0; i < encoded_nelts; i++)
343 {
344 const_tree elt1 = VECTOR_CST_ENCODED_ELT (cst1, i);
345 const_tree elt2 = VECTOR_CST_ENCODED_ELT (cst2, i);
346 if (int el_cmp = cmp_csts_and_types (elt1, elt2))
347 return el_cmp;
348 }
349 return 0;
350 }
351 }
352
353 /* Comparator for imposing a deterministic order on constants that might
354 not be of the same type. */
355
356 static int
cmp_csts_and_types(const_tree cst1,const_tree cst2)357 cmp_csts_and_types (const_tree cst1, const_tree cst2)
358 {
359 int t1 = TYPE_UID (TREE_TYPE (cst1));
360 int t2 = TYPE_UID (TREE_TYPE (cst2));
361 if (int cmp_type = t1 - t2)
362 return cmp_type;
363 return cmp_csts_same_type (cst1, cst2);
364 }
365
366 /* Comparator for imposing a deterministic order on svalues. */
367
368 int
cmp_ptr(const svalue * sval1,const svalue * sval2)369 svalue::cmp_ptr (const svalue *sval1, const svalue *sval2)
370 {
371 if (sval1 == sval2)
372 return 0;
373 if (int cmp_kind = sval1->get_kind () - sval2->get_kind ())
374 return cmp_kind;
375 int t1 = sval1->get_type () ? TYPE_UID (sval1->get_type ()) : -1;
376 int t2 = sval2->get_type () ? TYPE_UID (sval2->get_type ()) : -1;
377 if (int cmp_type = t1 - t2)
378 return cmp_type;
379 switch (sval1->get_kind ())
380 {
381 default:
382 gcc_unreachable ();
383 case SK_REGION:
384 {
385 const region_svalue *region_sval1 = (const region_svalue *)sval1;
386 const region_svalue *region_sval2 = (const region_svalue *)sval2;
387 return region::cmp_ids (region_sval1->get_pointee (),
388 region_sval2->get_pointee ());
389 }
390 break;
391 case SK_CONSTANT:
392 {
393 const constant_svalue *constant_sval1 = (const constant_svalue *)sval1;
394 const constant_svalue *constant_sval2 = (const constant_svalue *)sval2;
395 const_tree cst1 = constant_sval1->get_constant ();
396 const_tree cst2 = constant_sval2->get_constant ();
397 return cmp_csts_same_type (cst1, cst2);
398 }
399 break;
400 case SK_UNKNOWN:
401 {
402 gcc_assert (sval1 == sval2);
403 return 0;
404 }
405 break;
406 case SK_POISONED:
407 {
408 const poisoned_svalue *poisoned_sval1 = (const poisoned_svalue *)sval1;
409 const poisoned_svalue *poisoned_sval2 = (const poisoned_svalue *)sval2;
410 return (poisoned_sval1->get_poison_kind ()
411 - poisoned_sval2->get_poison_kind ());
412 }
413 break;
414 case SK_SETJMP:
415 {
416 const setjmp_svalue *setjmp_sval1 = (const setjmp_svalue *)sval1;
417 const setjmp_svalue *setjmp_sval2 = (const setjmp_svalue *)sval2;
418 const setjmp_record &rec1 = setjmp_sval1->get_setjmp_record ();
419 const setjmp_record &rec2 = setjmp_sval2->get_setjmp_record ();
420 return setjmp_record::cmp (rec1, rec2);
421 }
422 break;
423 case SK_INITIAL:
424 {
425 const initial_svalue *initial_sval1 = (const initial_svalue *)sval1;
426 const initial_svalue *initial_sval2 = (const initial_svalue *)sval2;
427 return region::cmp_ids (initial_sval1->get_region (),
428 initial_sval2->get_region ());
429 }
430 break;
431 case SK_UNARYOP:
432 {
433 const unaryop_svalue *unaryop_sval1 = (const unaryop_svalue *)sval1;
434 const unaryop_svalue *unaryop_sval2 = (const unaryop_svalue *)sval2;
435 if (int op_cmp = unaryop_sval1->get_op () - unaryop_sval2->get_op ())
436 return op_cmp;
437 return svalue::cmp_ptr (unaryop_sval1->get_arg (),
438 unaryop_sval2->get_arg ());
439 }
440 break;
441 case SK_BINOP:
442 {
443 const binop_svalue *binop_sval1 = (const binop_svalue *)sval1;
444 const binop_svalue *binop_sval2 = (const binop_svalue *)sval2;
445 if (int op_cmp = binop_sval1->get_op () - binop_sval2->get_op ())
446 return op_cmp;
447 if (int arg0_cmp = svalue::cmp_ptr (binop_sval1->get_arg0 (),
448 binop_sval2->get_arg0 ()))
449 return arg0_cmp;
450 return svalue::cmp_ptr (binop_sval1->get_arg1 (),
451 binop_sval2->get_arg1 ());
452 }
453 break;
454 case SK_SUB:
455 {
456 const sub_svalue *sub_sval1 = (const sub_svalue *)sval1;
457 const sub_svalue *sub_sval2 = (const sub_svalue *)sval2;
458 if (int parent_cmp = svalue::cmp_ptr (sub_sval1->get_parent (),
459 sub_sval2->get_parent ()))
460 return parent_cmp;
461 return region::cmp_ids (sub_sval1->get_subregion (),
462 sub_sval2->get_subregion ());
463 }
464 break;
465 case SK_REPEATED:
466 {
467 const repeated_svalue *repeated_sval1 = (const repeated_svalue *)sval1;
468 const repeated_svalue *repeated_sval2 = (const repeated_svalue *)sval2;
469 return svalue::cmp_ptr (repeated_sval1->get_inner_svalue (),
470 repeated_sval2->get_inner_svalue ());
471 }
472 break;
473 case SK_BITS_WITHIN:
474 {
475 const bits_within_svalue *bits_within_sval1
476 = (const bits_within_svalue *)sval1;
477 const bits_within_svalue *bits_within_sval2
478 = (const bits_within_svalue *)sval2;
479 if (int cmp = bit_range::cmp (bits_within_sval1->get_bits (),
480 bits_within_sval2->get_bits ()))
481 return cmp;
482 return svalue::cmp_ptr (bits_within_sval1->get_inner_svalue (),
483 bits_within_sval2->get_inner_svalue ());
484 }
485 break;
486 case SK_UNMERGEABLE:
487 {
488 const unmergeable_svalue *unmergeable_sval1
489 = (const unmergeable_svalue *)sval1;
490 const unmergeable_svalue *unmergeable_sval2
491 = (const unmergeable_svalue *)sval2;
492 return svalue::cmp_ptr (unmergeable_sval1->get_arg (),
493 unmergeable_sval2->get_arg ());
494 }
495 break;
496 case SK_PLACEHOLDER:
497 {
498 const placeholder_svalue *placeholder_sval1
499 = (const placeholder_svalue *)sval1;
500 const placeholder_svalue *placeholder_sval2
501 = (const placeholder_svalue *)sval2;
502 return strcmp (placeholder_sval1->get_name (),
503 placeholder_sval2->get_name ());
504 }
505 break;
506 case SK_WIDENING:
507 {
508 const widening_svalue *widening_sval1 = (const widening_svalue *)sval1;
509 const widening_svalue *widening_sval2 = (const widening_svalue *)sval2;
510 if (int point_cmp = function_point::cmp (widening_sval1->get_point (),
511 widening_sval2->get_point ()))
512 return point_cmp;
513 if (int base_cmp = svalue::cmp_ptr (widening_sval1->get_base_svalue (),
514 widening_sval2->get_base_svalue ()))
515 return base_cmp;
516 return svalue::cmp_ptr (widening_sval1->get_iter_svalue (),
517 widening_sval2->get_iter_svalue ());
518 }
519 break;
520 case SK_COMPOUND:
521 {
522 const compound_svalue *compound_sval1 = (const compound_svalue *)sval1;
523 const compound_svalue *compound_sval2 = (const compound_svalue *)sval2;
524 return binding_map::cmp (compound_sval1->get_map (),
525 compound_sval2->get_map ());
526 }
527 break;
528 case SK_CONJURED:
529 {
530 const conjured_svalue *conjured_sval1 = (const conjured_svalue *)sval1;
531 const conjured_svalue *conjured_sval2 = (const conjured_svalue *)sval2;
532 if (int stmt_cmp = (conjured_sval1->get_stmt ()->uid
533 - conjured_sval2->get_stmt ()->uid))
534 return stmt_cmp;
535 return region::cmp_ids (conjured_sval1->get_id_region (),
536 conjured_sval2->get_id_region ());
537 }
538 break;
539 case SK_ASM_OUTPUT:
540 {
541 const asm_output_svalue *asm_output_sval1
542 = (const asm_output_svalue *)sval1;
543 const asm_output_svalue *asm_output_sval2
544 = (const asm_output_svalue *)sval2;
545 if (int asm_string_cmp = strcmp (asm_output_sval1->get_asm_string (),
546 asm_output_sval2->get_asm_string ()))
547 return asm_string_cmp;
548 if (int output_idx_cmp = ((int)asm_output_sval1->get_output_idx ()
549 - (int)asm_output_sval2->get_output_idx ()))
550 return output_idx_cmp;
551 if (int cmp = ((int)asm_output_sval1->get_num_inputs ()
552 - (int)asm_output_sval2->get_num_inputs ()))
553 return cmp;
554 for (unsigned i = 0; i < asm_output_sval1->get_num_inputs (); i++)
555 if (int input_cmp
556 = svalue::cmp_ptr (asm_output_sval1->get_input (i),
557 asm_output_sval2->get_input (i)))
558 return input_cmp;
559 return 0;
560 }
561 break;
562 case SK_CONST_FN_RESULT:
563 {
564 const const_fn_result_svalue *const_fn_result_sval1
565 = (const const_fn_result_svalue *)sval1;
566 const const_fn_result_svalue *const_fn_result_sval2
567 = (const const_fn_result_svalue *)sval2;
568 int d1 = DECL_UID (const_fn_result_sval1->get_fndecl ());
569 int d2 = DECL_UID (const_fn_result_sval2->get_fndecl ());
570 if (int cmp_fndecl = d1 - d2)
571 return cmp_fndecl;
572 if (int cmp = ((int)const_fn_result_sval1->get_num_inputs ()
573 - (int)const_fn_result_sval2->get_num_inputs ()))
574 return cmp;
575 for (unsigned i = 0; i < const_fn_result_sval1->get_num_inputs (); i++)
576 if (int input_cmp
577 = svalue::cmp_ptr (const_fn_result_sval1->get_input (i),
578 const_fn_result_sval2->get_input (i)))
579 return input_cmp;
580 return 0;
581 }
582 }
583 }
584
585 /* Comparator for use by vec<const svalue *>::qsort. */
586
587 int
cmp_ptr_ptr(const void * p1,const void * p2)588 svalue::cmp_ptr_ptr (const void *p1, const void *p2)
589 {
590 const svalue *sval1 = *(const svalue * const *)p1;
591 const svalue *sval2 = *(const svalue * const *)p2;
592 return cmp_ptr (sval1, sval2);
593 }
594
595 /* Subclass of visitor for use in implementing svalue::involves_p. */
596
597 class involvement_visitor : public visitor
598 {
599 public:
involvement_visitor(const svalue * needle)600 involvement_visitor (const svalue *needle)
601 : m_needle (needle), m_found (false) {}
602
visit_initial_svalue(const initial_svalue * candidate)603 void visit_initial_svalue (const initial_svalue *candidate)
604 {
605 if (candidate == m_needle)
606 m_found = true;
607 }
608
visit_conjured_svalue(const conjured_svalue * candidate)609 void visit_conjured_svalue (const conjured_svalue *candidate)
610 {
611 if (candidate == m_needle)
612 m_found = true;
613 }
614
found_p() const615 bool found_p () const { return m_found; }
616
617 private:
618 const svalue *m_needle;
619 bool m_found;
620 };
621
622 /* Return true iff this svalue is defined in terms of OTHER. */
623
624 bool
involves_p(const svalue * other) const625 svalue::involves_p (const svalue *other) const
626 {
627 /* Currently only implemented for these kinds. */
628 gcc_assert (other->get_kind () == SK_INITIAL
629 || other->get_kind () == SK_CONJURED);
630
631 involvement_visitor v (other);
632 accept (&v);
633 return v.found_p ();
634 }
635
636 /* Extract SUBRANGE from this value, of type TYPE. */
637
638 const svalue *
extract_bit_range(tree type,const bit_range & subrange,region_model_manager * mgr) const639 svalue::extract_bit_range (tree type,
640 const bit_range &subrange,
641 region_model_manager *mgr) const
642 {
643 return mgr->get_or_create_bits_within (type, subrange, this);
644 }
645
646 /* Base implementation of svalue::maybe_fold_bits_within vfunc. */
647
648 const svalue *
maybe_fold_bits_within(tree,const bit_range &,region_model_manager *) const649 svalue::maybe_fold_bits_within (tree,
650 const bit_range &,
651 region_model_manager *) const
652 {
653 /* By default, don't fold. */
654 return NULL;
655 }
656
657 /* Base implementation of svalue::all_zeroes_p.
658 Return true if this value is known to be all zeroes. */
659
660 bool
all_zeroes_p() const661 svalue::all_zeroes_p () const
662 {
663 return false;
664 }
665
666 /* If this svalue is a pointer, attempt to determine the base region it points
667 to. Return NULL on any problems. */
668
669 const region *
maybe_get_deref_base_region() const670 svalue::maybe_get_deref_base_region () const
671 {
672 const svalue *iter = this;
673 while (1)
674 {
675 switch (iter->get_kind ())
676 {
677 default:
678 return NULL;
679
680 case SK_REGION:
681 {
682 const region_svalue *region_sval
683 = as_a <const region_svalue *> (iter);
684 return region_sval->get_pointee ()->get_base_region ();
685 }
686
687 case SK_BINOP:
688 {
689 const binop_svalue *binop_sval
690 = as_a <const binop_svalue *> (iter);
691 switch (binop_sval->get_op ())
692 {
693 case POINTER_PLUS_EXPR:
694 /* If we have a symbolic value expressing pointer arithmetic,
695 use the LHS. */
696 iter = binop_sval->get_arg0 ();
697 continue;
698
699 default:
700 return NULL;
701 }
702 return NULL;
703 }
704 }
705 }
706 }
707
708 /* class region_svalue : public svalue. */
709
710 /* Implementation of svalue::dump_to_pp vfunc for region_svalue. */
711
712 void
dump_to_pp(pretty_printer * pp,bool simple) const713 region_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
714 {
715 if (simple)
716 {
717 pp_string (pp, "&");
718 m_reg->dump_to_pp (pp, simple);
719 }
720 else
721 {
722 pp_string (pp, "region_svalue(");
723 print_quoted_type (pp, get_type ());
724 pp_string (pp, ", ");
725 m_reg->dump_to_pp (pp, simple);
726 pp_string (pp, ")");
727 }
728 }
729
730 /* Implementation of svalue::accept vfunc for region_svalue. */
731
732 void
accept(visitor * v) const733 region_svalue::accept (visitor *v) const
734 {
735 v->visit_region_svalue (this);
736 m_reg->accept (v);
737 }
738
739 /* Implementation of svalue::implicitly_live_p vfunc for region_svalue. */
740
741 bool
implicitly_live_p(const svalue_set *,const region_model * model) const742 region_svalue::implicitly_live_p (const svalue_set *,
743 const region_model *model) const
744 {
745 /* Pointers into clusters that have escaped should be treated as live. */
746 const region *base_reg = get_pointee ()->get_base_region ();
747 const store *store = model->get_store ();
748 if (const binding_cluster *c = store->get_cluster (base_reg))
749 if (c->escaped_p ())
750 return true;
751
752 return false;
753 }
754
755 /* Evaluate the condition LHS OP RHS.
756 Subroutine of region_model::eval_condition for when we have a pair of
757 pointers. */
758
759 tristate
eval_condition(const region_svalue * lhs,enum tree_code op,const region_svalue * rhs)760 region_svalue::eval_condition (const region_svalue *lhs,
761 enum tree_code op,
762 const region_svalue *rhs)
763 {
764 /* See if they point to the same region. */
765 const region *lhs_reg = lhs->get_pointee ();
766 const region *rhs_reg = rhs->get_pointee ();
767 bool ptr_equality = lhs_reg == rhs_reg;
768 switch (op)
769 {
770 default:
771 gcc_unreachable ();
772
773 case EQ_EXPR:
774 if (ptr_equality)
775 return tristate::TS_TRUE;
776 else
777 return tristate::TS_FALSE;
778 break;
779
780 case NE_EXPR:
781 if (ptr_equality)
782 return tristate::TS_FALSE;
783 else
784 return tristate::TS_TRUE;
785 break;
786
787 case GE_EXPR:
788 case LE_EXPR:
789 if (ptr_equality)
790 return tristate::TS_TRUE;
791 break;
792
793 case GT_EXPR:
794 case LT_EXPR:
795 if (ptr_equality)
796 return tristate::TS_FALSE;
797 break;
798 }
799
800 return tristate::TS_UNKNOWN;
801 }
802
803 /* class constant_svalue : public svalue. */
804
805 /* Implementation of svalue::dump_to_pp vfunc for constant_svalue. */
806
807 void
dump_to_pp(pretty_printer * pp,bool simple) const808 constant_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
809 {
810 if (simple)
811 {
812 pp_string (pp, "(");
813 dump_tree (pp, get_type ());
814 pp_string (pp, ")");
815 dump_tree (pp, m_cst_expr);
816 }
817 else
818 {
819 pp_string (pp, "constant_svalue(");
820 print_quoted_type (pp, get_type ());
821 pp_string (pp, ", ");
822 dump_tree (pp, m_cst_expr);
823 pp_string (pp, ")");
824 }
825 }
826
827 /* Implementation of svalue::accept vfunc for constant_svalue. */
828
829 void
accept(visitor * v) const830 constant_svalue::accept (visitor *v) const
831 {
832 v->visit_constant_svalue (this);
833 }
834
835 /* Implementation of svalue::implicitly_live_p vfunc for constant_svalue.
836 Constants are implicitly live. */
837
838 bool
implicitly_live_p(const svalue_set *,const region_model *) const839 constant_svalue::implicitly_live_p (const svalue_set *,
840 const region_model *) const
841 {
842 return true;
843 }
844
845 /* Evaluate the condition LHS OP RHS.
846 Subroutine of region_model::eval_condition for when we have a pair of
847 constants. */
848
849 tristate
eval_condition(const constant_svalue * lhs,enum tree_code op,const constant_svalue * rhs)850 constant_svalue::eval_condition (const constant_svalue *lhs,
851 enum tree_code op,
852 const constant_svalue *rhs)
853 {
854 tree lhs_const = lhs->get_constant ();
855 tree rhs_const = rhs->get_constant ();
856
857 gcc_assert (CONSTANT_CLASS_P (lhs_const));
858 gcc_assert (CONSTANT_CLASS_P (rhs_const));
859
860 /* Check for comparable types. */
861 if (types_compatible_p (TREE_TYPE (lhs_const), TREE_TYPE (rhs_const)))
862 {
863 tree comparison
864 = fold_binary (op, boolean_type_node, lhs_const, rhs_const);
865 if (comparison == boolean_true_node)
866 return tristate (tristate::TS_TRUE);
867 if (comparison == boolean_false_node)
868 return tristate (tristate::TS_FALSE);
869 }
870 return tristate::TS_UNKNOWN;
871 }
872
873 /* Implementation of svalue::maybe_fold_bits_within vfunc
874 for constant_svalue. */
875
876 const svalue *
maybe_fold_bits_within(tree type,const bit_range &,region_model_manager * mgr) const877 constant_svalue::maybe_fold_bits_within (tree type,
878 const bit_range &,
879 region_model_manager *mgr) const
880 {
881 /* Bits within an all-zero value are also all zero. */
882 if (zerop (m_cst_expr))
883 {
884 if (type)
885 return mgr->get_or_create_cast (type, this);
886 else
887 return this;
888 }
889 /* Otherwise, don't fold. */
890 return NULL;
891 }
892
893 /* Implementation of svalue::all_zeroes_p for constant_svalue. */
894
895 bool
all_zeroes_p() const896 constant_svalue::all_zeroes_p () const
897 {
898 return zerop (m_cst_expr);
899 }
900
901 /* class unknown_svalue : public svalue. */
902
903 /* Implementation of svalue::dump_to_pp vfunc for unknown_svalue. */
904
905 void
dump_to_pp(pretty_printer * pp,bool simple) const906 unknown_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
907 {
908 if (simple)
909 {
910 pp_string (pp, "UNKNOWN(");
911 if (get_type ())
912 dump_tree (pp, get_type ());
913 pp_character (pp, ')');
914 }
915 else
916 {
917 pp_string (pp, "unknown_svalue(");
918 if (get_type ())
919 dump_tree (pp, get_type ());
920 pp_character (pp, ')');
921 }
922 }
923
924 /* Implementation of svalue::accept vfunc for unknown_svalue. */
925
926 void
accept(visitor * v) const927 unknown_svalue::accept (visitor *v) const
928 {
929 v->visit_unknown_svalue (this);
930 }
931
932 /* Implementation of svalue::maybe_fold_bits_within vfunc
933 for unknown_svalue. */
934
935 const svalue *
maybe_fold_bits_within(tree type,const bit_range &,region_model_manager * mgr) const936 unknown_svalue::maybe_fold_bits_within (tree type,
937 const bit_range &,
938 region_model_manager *mgr) const
939 {
940 /* Bits within an unknown_svalue are themselves unknown. */
941 return mgr->get_or_create_unknown_svalue (type);
942 }
943
944 /* Get a string for KIND for use in debug dumps. */
945
946 const char *
poison_kind_to_str(enum poison_kind kind)947 poison_kind_to_str (enum poison_kind kind)
948 {
949 switch (kind)
950 {
951 default:
952 gcc_unreachable ();
953 case POISON_KIND_UNINIT:
954 return "uninit";
955 case POISON_KIND_FREED:
956 return "freed";
957 case POISON_KIND_POPPED_STACK:
958 return "popped stack";
959 }
960 }
961
962 /* class poisoned_svalue : public svalue. */
963
964 /* Implementation of svalue::dump_to_pp vfunc for poisoned_svalue. */
965
966 void
dump_to_pp(pretty_printer * pp,bool simple) const967 poisoned_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
968 {
969 if (simple)
970 {
971 pp_string (pp, "POISONED(");
972 print_quoted_type (pp, get_type ());
973 pp_printf (pp, ", %s)", poison_kind_to_str (m_kind));
974 }
975 else
976 {
977 pp_string (pp, "poisoned_svalue(");
978 print_quoted_type (pp, get_type ());
979 pp_printf (pp, ", %s)", poison_kind_to_str (m_kind));
980 }
981 }
982
983 /* Implementation of svalue::accept vfunc for poisoned_svalue. */
984
985 void
accept(visitor * v) const986 poisoned_svalue::accept (visitor *v) const
987 {
988 v->visit_poisoned_svalue (this);
989 }
990
991 /* Implementation of svalue::maybe_fold_bits_within vfunc
992 for poisoned_svalue. */
993
994 const svalue *
maybe_fold_bits_within(tree type,const bit_range &,region_model_manager * mgr) const995 poisoned_svalue::maybe_fold_bits_within (tree type,
996 const bit_range &,
997 region_model_manager *mgr) const
998 {
999 /* Bits within a poisoned value are also poisoned. */
1000 return mgr->get_or_create_poisoned_svalue (m_kind, type);
1001 }
1002
1003 /* class setjmp_svalue's implementation is in engine.cc, so that it can use
1004 the declaration of exploded_node. */
1005
1006 /* class initial_svalue : public svalue. */
1007
1008 /* Implementation of svalue::dump_to_pp vfunc for initial_svalue. */
1009
1010 void
dump_to_pp(pretty_printer * pp,bool simple) const1011 initial_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1012 {
1013 if (simple)
1014 {
1015 pp_string (pp, "INIT_VAL(");
1016 m_reg->dump_to_pp (pp, simple);
1017 pp_string (pp, ")");
1018 }
1019 else
1020 {
1021 pp_string (pp, "initial_svalue(");
1022 print_quoted_type (pp, get_type ());
1023 pp_string (pp, ", ");
1024 m_reg->dump_to_pp (pp, simple);
1025 pp_string (pp, ")");
1026 }
1027 }
1028
1029 /* Implementation of svalue::accept vfunc for initial_svalue. */
1030
1031 void
accept(visitor * v) const1032 initial_svalue::accept (visitor *v) const
1033 {
1034 v->visit_initial_svalue (this);
1035 m_reg->accept (v);
1036 }
1037
1038 /* Implementation of svalue::implicitly_live_p vfunc for initial_svalue. */
1039
1040 bool
implicitly_live_p(const svalue_set *,const region_model * model) const1041 initial_svalue::implicitly_live_p (const svalue_set *,
1042 const region_model *model) const
1043 {
1044 /* This svalue may be implicitly live if the region still implicitly
1045 has its initial value and is reachable. */
1046
1047 /* It must be a region that exists; we don't want to consider
1048 INIT_VAL(R) as still being implicitly reachable if R is in
1049 a popped stack frame. */
1050 if (model->region_exists_p (m_reg))
1051 {
1052 const svalue *reg_sval = model->get_store_value (m_reg, NULL);
1053 if (reg_sval == this)
1054 return true;
1055 }
1056
1057 /* Assume that the initial values of params for the top level frame
1058 are still live, because (presumably) they're still
1059 live in the external caller. */
1060 if (initial_value_of_param_p ())
1061 if (const frame_region *frame_reg = m_reg->maybe_get_frame_region ())
1062 if (frame_reg->get_calling_frame () == NULL)
1063 return true;
1064
1065 return false;
1066 }
1067
1068 /* Return true if this is the initial value of a function parameter. */
1069
1070 bool
initial_value_of_param_p() const1071 initial_svalue::initial_value_of_param_p () const
1072 {
1073 if (tree reg_decl = m_reg->maybe_get_decl ())
1074 if (TREE_CODE (reg_decl) == SSA_NAME)
1075 {
1076 tree ssa_name = reg_decl;
1077 if (SSA_NAME_IS_DEFAULT_DEF (ssa_name)
1078 && SSA_NAME_VAR (ssa_name)
1079 && TREE_CODE (SSA_NAME_VAR (ssa_name)) == PARM_DECL)
1080 return true;
1081 }
1082 return false;
1083 }
1084
1085 /* class unaryop_svalue : public svalue. */
1086
1087 /* Implementation of svalue::dump_to_pp vfunc for unaryop_svalue. */
1088
1089 void
dump_to_pp(pretty_printer * pp,bool simple) const1090 unaryop_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1091 {
1092 if (simple)
1093 {
1094 if (m_op == VIEW_CONVERT_EXPR || m_op == NOP_EXPR)
1095 {
1096 pp_string (pp, "CAST(");
1097 dump_tree (pp, get_type ());
1098 pp_string (pp, ", ");
1099 m_arg->dump_to_pp (pp, simple);
1100 pp_character (pp, ')');
1101 }
1102 else
1103 {
1104 pp_character (pp, '(');
1105 pp_string (pp, get_tree_code_name (m_op));
1106 //pp_string (pp, op_symbol_code (m_op));
1107 m_arg->dump_to_pp (pp, simple);
1108 pp_character (pp, ')');
1109 }
1110 }
1111 else
1112 {
1113 pp_string (pp, "unaryop_svalue (");
1114 pp_string (pp, get_tree_code_name (m_op));
1115 pp_string (pp, ", ");
1116 m_arg->dump_to_pp (pp, simple);
1117 pp_character (pp, ')');
1118 }
1119 }
1120
1121 /* Implementation of svalue::accept vfunc for unaryop_svalue. */
1122
1123 void
accept(visitor * v) const1124 unaryop_svalue::accept (visitor *v) const
1125 {
1126 v->visit_unaryop_svalue (this);
1127 m_arg->accept (v);
1128 }
1129
1130 /* Implementation of svalue::implicitly_live_p vfunc for unaryop_svalue. */
1131
1132 bool
implicitly_live_p(const svalue_set * live_svalues,const region_model * model) const1133 unaryop_svalue::implicitly_live_p (const svalue_set *live_svalues,
1134 const region_model *model) const
1135 {
1136 return get_arg ()->live_p (live_svalues, model);
1137 }
1138
1139 /* Implementation of svalue::maybe_fold_bits_within vfunc
1140 for unaryop_svalue. */
1141
1142 const svalue *
maybe_fold_bits_within(tree type,const bit_range &,region_model_manager * mgr) const1143 unaryop_svalue::maybe_fold_bits_within (tree type,
1144 const bit_range &,
1145 region_model_manager *mgr) const
1146 {
1147 switch (m_op)
1148 {
1149 default:
1150 break;
1151 case NOP_EXPR:
1152 /* A cast of zero is zero. */
1153 if (tree cst = m_arg->maybe_get_constant ())
1154 if (zerop (cst))
1155 {
1156 if (type)
1157 return mgr->get_or_create_cast (type, this);
1158 else
1159 return this;
1160 }
1161 break;
1162 }
1163 /* Otherwise, don't fold. */
1164 return NULL;
1165 }
1166
1167 /* class binop_svalue : public svalue. */
1168
1169 /* Return whether OP be printed as an infix operator. */
1170
1171 static bool
infix_p(enum tree_code op)1172 infix_p (enum tree_code op)
1173 {
1174 switch (op)
1175 {
1176 default:
1177 return true;
1178 case MAX_EXPR:
1179 case MIN_EXPR:
1180 return false;
1181 }
1182 }
1183
1184 /* Implementation of svalue::dump_to_pp vfunc for binop_svalue. */
1185
1186 void
dump_to_pp(pretty_printer * pp,bool simple) const1187 binop_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1188 {
1189 if (simple)
1190 {
1191 if (infix_p (m_op))
1192 {
1193 /* Print "(A OP B)". */
1194 pp_character (pp, '(');
1195 m_arg0->dump_to_pp (pp, simple);
1196 pp_string (pp, op_symbol_code (m_op));
1197 m_arg1->dump_to_pp (pp, simple);
1198 pp_character (pp, ')');
1199 }
1200 else
1201 {
1202 /* Print "OP(A, B)". */
1203 pp_string (pp, op_symbol_code (m_op));
1204 pp_character (pp, '(');
1205 m_arg0->dump_to_pp (pp, simple);
1206 pp_string (pp, ", ");
1207 m_arg1->dump_to_pp (pp, simple);
1208 pp_character (pp, ')');
1209 }
1210 }
1211 else
1212 {
1213 pp_string (pp, "binop_svalue (");
1214 pp_string (pp, get_tree_code_name (m_op));
1215 pp_string (pp, ", ");
1216 m_arg0->dump_to_pp (pp, simple);
1217 pp_string (pp, ", ");
1218 m_arg1->dump_to_pp (pp, simple);
1219 pp_character (pp, ')');
1220 }
1221 }
1222
1223 /* Implementation of svalue::accept vfunc for binop_svalue. */
1224
1225 void
accept(visitor * v) const1226 binop_svalue::accept (visitor *v) const
1227 {
1228 v->visit_binop_svalue (this);
1229 m_arg0->accept (v);
1230 m_arg1->accept (v);
1231 }
1232
1233 /* Implementation of svalue::implicitly_live_p vfunc for binop_svalue. */
1234
1235 bool
implicitly_live_p(const svalue_set * live_svalues,const region_model * model) const1236 binop_svalue::implicitly_live_p (const svalue_set *live_svalues,
1237 const region_model *model) const
1238 {
1239 return (get_arg0 ()->live_p (live_svalues, model)
1240 && get_arg1 ()->live_p (live_svalues, model));
1241 }
1242
1243 /* class sub_svalue : public svalue. */
1244
1245 /* sub_svalue'c ctor. */
1246
sub_svalue(tree type,const svalue * parent_svalue,const region * subregion)1247 sub_svalue::sub_svalue (tree type, const svalue *parent_svalue,
1248 const region *subregion)
1249 : svalue (complexity::from_pair (parent_svalue->get_complexity (),
1250 subregion->get_complexity ()),
1251 type),
1252 m_parent_svalue (parent_svalue), m_subregion (subregion)
1253 {
1254 gcc_assert (parent_svalue->can_have_associated_state_p ());
1255 }
1256
1257 /* Implementation of svalue::dump_to_pp vfunc for sub_svalue. */
1258
1259 void
dump_to_pp(pretty_printer * pp,bool simple) const1260 sub_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1261 {
1262 if (simple)
1263 {
1264 pp_string (pp, "SUB(");
1265 m_parent_svalue->dump_to_pp (pp, simple);
1266 pp_string (pp, ", ");
1267 m_subregion->dump_to_pp (pp, simple);
1268 pp_character (pp, ')');
1269 }
1270 else
1271 {
1272 pp_string (pp, "sub_svalue (");
1273 pp_string (pp, ", ");
1274 m_parent_svalue->dump_to_pp (pp, simple);
1275 pp_string (pp, ", ");
1276 m_subregion->dump_to_pp (pp, simple);
1277 pp_character (pp, ')');
1278 }
1279 }
1280
1281 /* Implementation of svalue::accept vfunc for sub_svalue. */
1282
1283 void
accept(visitor * v) const1284 sub_svalue::accept (visitor *v) const
1285 {
1286 v->visit_sub_svalue (this);
1287 m_parent_svalue->accept (v);
1288 m_subregion->accept (v);
1289 }
1290
1291 /* Implementation of svalue::implicitly_live_p vfunc for sub_svalue. */
1292
1293 bool
implicitly_live_p(const svalue_set * live_svalues,const region_model * model) const1294 sub_svalue::implicitly_live_p (const svalue_set *live_svalues,
1295 const region_model *model) const
1296 {
1297 return get_parent ()->live_p (live_svalues, model);
1298 }
1299
1300 /* class repeated_svalue : public svalue. */
1301
1302 /* repeated_svalue'c ctor. */
1303
repeated_svalue(tree type,const svalue * outer_size,const svalue * inner_svalue)1304 repeated_svalue::repeated_svalue (tree type,
1305 const svalue *outer_size,
1306 const svalue *inner_svalue)
1307 : svalue (complexity::from_pair (outer_size, inner_svalue), type),
1308 m_outer_size (outer_size),
1309 m_inner_svalue (inner_svalue)
1310 {
1311 gcc_assert (outer_size->can_have_associated_state_p ());
1312 gcc_assert (inner_svalue->can_have_associated_state_p ());
1313 }
1314
1315 /* Implementation of svalue::dump_to_pp vfunc for repeated_svalue. */
1316
1317 void
dump_to_pp(pretty_printer * pp,bool simple) const1318 repeated_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1319 {
1320 if (simple)
1321 {
1322 pp_string (pp, "REPEATED(");
1323 if (get_type ())
1324 {
1325 print_quoted_type (pp, get_type ());
1326 pp_string (pp, ", ");
1327 }
1328 pp_string (pp, "outer_size: ");
1329 m_outer_size->dump_to_pp (pp, simple);
1330 pp_string (pp, ", inner_val: ");
1331 m_inner_svalue->dump_to_pp (pp, simple);
1332 pp_character (pp, ')');
1333 }
1334 else
1335 {
1336 pp_string (pp, "repeated_svalue (");
1337 if (get_type ())
1338 {
1339 print_quoted_type (pp, get_type ());
1340 pp_string (pp, ", ");
1341 }
1342 pp_string (pp, "outer_size: ");
1343 m_outer_size->dump_to_pp (pp, simple);
1344 pp_string (pp, ", inner_val: ");
1345 m_inner_svalue->dump_to_pp (pp, simple);
1346 pp_character (pp, ')');
1347 }
1348 }
1349
1350 /* Implementation of svalue::accept vfunc for repeated_svalue. */
1351
1352 void
accept(visitor * v) const1353 repeated_svalue::accept (visitor *v) const
1354 {
1355 v->visit_repeated_svalue (this);
1356 m_inner_svalue->accept (v);
1357 }
1358
1359 /* Implementation of svalue::all_zeroes_p for repeated_svalue. */
1360
1361 bool
all_zeroes_p() const1362 repeated_svalue::all_zeroes_p () const
1363 {
1364 return m_inner_svalue->all_zeroes_p ();
1365 }
1366
1367 /* Implementation of svalue::maybe_fold_bits_within vfunc
1368 for repeated_svalue. */
1369
1370 const svalue *
maybe_fold_bits_within(tree type,const bit_range & bits,region_model_manager * mgr) const1371 repeated_svalue::maybe_fold_bits_within (tree type,
1372 const bit_range &bits,
1373 region_model_manager *mgr) const
1374 {
1375 const svalue *innermost_sval = m_inner_svalue;
1376 /* Fold
1377 BITS_WITHIN (range, REPEATED_SVALUE (ZERO))
1378 to:
1379 REPEATED_SVALUE (ZERO). */
1380 if (all_zeroes_p ())
1381 {
1382 byte_range bytes (0,0);
1383 if (bits.as_byte_range (&bytes))
1384 {
1385 const svalue *byte_size
1386 = mgr->get_or_create_int_cst (size_type_node,
1387 bytes.m_size_in_bytes.to_uhwi ());
1388 return mgr->get_or_create_repeated_svalue (type, byte_size,
1389 innermost_sval);
1390 }
1391 }
1392
1393 /* Fold:
1394 BITS_WITHIN (range, REPEATED_SVALUE (INNERMOST_SVALUE))
1395 to:
1396 BITS_WITHIN (range - offset, INNERMOST_SVALUE)
1397 if range is fully within one instance of INNERMOST_SVALUE. */
1398 if (tree innermost_type = innermost_sval->get_type ())
1399 {
1400 bit_size_t element_bit_size;
1401 if (int_size_in_bits (innermost_type, &element_bit_size)
1402 && element_bit_size > 0)
1403 {
1404 HOST_WIDE_INT start_idx
1405 = (bits.get_start_bit_offset ()
1406 / element_bit_size).to_shwi ();
1407 HOST_WIDE_INT last_idx
1408 = (bits.get_last_bit_offset ()
1409 / element_bit_size).to_shwi ();
1410 if (start_idx == last_idx)
1411 {
1412 bit_offset_t start_of_element
1413 = start_idx * element_bit_size;
1414 bit_range range_within_element
1415 (bits.m_start_bit_offset - start_of_element,
1416 bits.m_size_in_bits);
1417 return mgr->get_or_create_bits_within (type,
1418 range_within_element,
1419 innermost_sval);
1420 }
1421 }
1422 }
1423
1424 return NULL;
1425 }
1426
1427 /* class bits_within_svalue : public svalue. */
1428
1429 /* bits_within_svalue'c ctor. */
1430
bits_within_svalue(tree type,const bit_range & bits,const svalue * inner_svalue)1431 bits_within_svalue::bits_within_svalue (tree type,
1432 const bit_range &bits,
1433 const svalue *inner_svalue)
1434 : svalue (complexity (inner_svalue), type),
1435 m_bits (bits),
1436 m_inner_svalue (inner_svalue)
1437 {
1438 gcc_assert (inner_svalue->can_have_associated_state_p ());
1439 }
1440
1441 /* Implementation of svalue::dump_to_pp vfunc for bits_within_svalue. */
1442
1443 void
dump_to_pp(pretty_printer * pp,bool simple) const1444 bits_within_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1445 {
1446 if (simple)
1447 {
1448 pp_string (pp, "BITS_WITHIN(");
1449 if (get_type ())
1450 {
1451 print_quoted_type (pp, get_type ());
1452 pp_string (pp, ", ");
1453 }
1454 m_bits.dump_to_pp (pp);
1455 pp_string (pp, ", inner_val: ");
1456 m_inner_svalue->dump_to_pp (pp, simple);
1457 pp_character (pp, ')');
1458 }
1459 else
1460 {
1461 pp_string (pp, "bits_within_svalue (");
1462 if (get_type ())
1463 {
1464 print_quoted_type (pp, get_type ());
1465 pp_string (pp, ", ");
1466 }
1467 m_bits.dump_to_pp (pp);
1468 pp_string (pp, ", inner_val: ");
1469 m_inner_svalue->dump_to_pp (pp, simple);
1470 pp_character (pp, ')');
1471 }
1472 }
1473
1474 /* Implementation of svalue::maybe_fold_bits_within vfunc
1475 for bits_within_svalue. */
1476
1477 const svalue *
maybe_fold_bits_within(tree type,const bit_range & bits,region_model_manager * mgr) const1478 bits_within_svalue::maybe_fold_bits_within (tree type,
1479 const bit_range &bits,
1480 region_model_manager *mgr) const
1481 {
1482 /* Fold:
1483 BITS_WITHIN (range1, BITS_WITHIN (range2, VAL))
1484 to:
1485 BITS_WITHIN (range1 in range 2, VAL). */
1486 bit_range offset_bits (m_bits.get_start_bit_offset ()
1487 + bits.m_start_bit_offset,
1488 bits.m_size_in_bits);
1489 return mgr->get_or_create_bits_within (type, offset_bits, m_inner_svalue);
1490 }
1491
1492 /* Implementation of svalue::accept vfunc for bits_within_svalue. */
1493
1494 void
accept(visitor * v) const1495 bits_within_svalue::accept (visitor *v) const
1496 {
1497 v->visit_bits_within_svalue (this);
1498 m_inner_svalue->accept (v);
1499 }
1500
1501 /* Implementation of svalue::implicitly_live_p vfunc for bits_within_svalue. */
1502
1503 bool
implicitly_live_p(const svalue_set * live_svalues,const region_model * model) const1504 bits_within_svalue::implicitly_live_p (const svalue_set *live_svalues,
1505 const region_model *model) const
1506 {
1507 return m_inner_svalue->live_p (live_svalues, model);
1508 }
1509
1510 /* class widening_svalue : public svalue. */
1511
1512 /* Implementation of svalue::dump_to_pp vfunc for widening_svalue. */
1513
1514 void
dump_to_pp(pretty_printer * pp,bool simple) const1515 widening_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1516 {
1517 if (simple)
1518 {
1519 pp_string (pp, "WIDENING(");
1520 pp_character (pp, '{');
1521 m_point.print (pp, format (false));
1522 pp_string (pp, "}, ");
1523 m_base_sval->dump_to_pp (pp, simple);
1524 pp_string (pp, ", ");
1525 m_iter_sval->dump_to_pp (pp, simple);
1526 pp_character (pp, ')');
1527 }
1528 else
1529 {
1530 pp_string (pp, "widening_svalue (");
1531 pp_string (pp, ", ");
1532 pp_character (pp, '{');
1533 m_point.print (pp, format (false));
1534 pp_string (pp, "}, ");
1535 m_base_sval->dump_to_pp (pp, simple);
1536 pp_string (pp, ", ");
1537 m_iter_sval->dump_to_pp (pp, simple);
1538 pp_character (pp, ')');
1539 }
1540 }
1541
1542 /* Implementation of svalue::accept vfunc for widening_svalue. */
1543
1544 void
accept(visitor * v) const1545 widening_svalue::accept (visitor *v) const
1546 {
1547 v->visit_widening_svalue (this);
1548 m_base_sval->accept (v);
1549 m_iter_sval->accept (v);
1550 }
1551
1552 /* Attempt to determine in which direction this value is changing
1553 w.r.t. the initial value. */
1554
1555 enum widening_svalue::direction_t
get_direction() const1556 widening_svalue::get_direction () const
1557 {
1558 tree base_cst = m_base_sval->maybe_get_constant ();
1559 if (base_cst == NULL_TREE)
1560 return DIR_UNKNOWN;
1561 tree iter_cst = m_iter_sval->maybe_get_constant ();
1562 if (iter_cst == NULL_TREE)
1563 return DIR_UNKNOWN;
1564
1565 tree iter_gt_base = fold_binary (GT_EXPR, boolean_type_node,
1566 iter_cst, base_cst);
1567 if (iter_gt_base == boolean_true_node)
1568 return DIR_ASCENDING;
1569
1570 tree iter_lt_base = fold_binary (LT_EXPR, boolean_type_node,
1571 iter_cst, base_cst);
1572 if (iter_lt_base == boolean_true_node)
1573 return DIR_DESCENDING;
1574
1575 return DIR_UNKNOWN;
1576 }
1577
1578 /* Compare this value against constant RHS_CST. */
1579
1580 tristate
eval_condition_without_cm(enum tree_code op,tree rhs_cst) const1581 widening_svalue::eval_condition_without_cm (enum tree_code op,
1582 tree rhs_cst) const
1583 {
1584 tree base_cst = m_base_sval->maybe_get_constant ();
1585 if (base_cst == NULL_TREE)
1586 return tristate::TS_UNKNOWN;
1587 tree iter_cst = m_iter_sval->maybe_get_constant ();
1588 if (iter_cst == NULL_TREE)
1589 return tristate::TS_UNKNOWN;
1590
1591 switch (get_direction ())
1592 {
1593 default:
1594 gcc_unreachable ();
1595 case DIR_ASCENDING:
1596 /* LHS is in [base_cst, +ve infinity), assuming no overflow. */
1597 switch (op)
1598 {
1599 case LE_EXPR:
1600 case LT_EXPR:
1601 {
1602 /* [BASE, +INF) OP RHS:
1603 This is either true or false at +ve ininity,
1604 It can be true for points X where X OP RHS, so we have either
1605 "false", or "unknown". */
1606 tree base_op_rhs = fold_binary (op, boolean_type_node,
1607 base_cst, rhs_cst);
1608 if (base_op_rhs == boolean_true_node)
1609 return tristate::TS_UNKNOWN;
1610 else
1611 return tristate::TS_FALSE;
1612 }
1613
1614 case GE_EXPR:
1615 case GT_EXPR:
1616 {
1617 /* [BASE, +INF) OP RHS:
1618 This is true at +ve infinity. It will be true everywhere
1619 in the range if BASE >= RHS. */
1620 tree base_op_rhs = fold_binary (op, boolean_type_node,
1621 base_cst, rhs_cst);
1622 if (base_op_rhs == boolean_true_node)
1623 return tristate::TS_TRUE;
1624 else
1625 return tristate::TS_UNKNOWN;
1626 }
1627
1628 case EQ_EXPR:
1629 {
1630 /* [BASE, +INF) == RHS:
1631 Could this be true at any point in the range? If so we
1632 have "unknown", otherwise we have "false". */
1633 tree base_le_rhs = fold_binary (LE_EXPR, boolean_type_node,
1634 base_cst, rhs_cst);
1635 if (base_le_rhs == boolean_true_node)
1636 return tristate::TS_UNKNOWN;
1637 else
1638 return tristate::TS_FALSE;
1639 }
1640
1641 case NE_EXPR:
1642 {
1643 /* [BASE, +INF) != RHS:
1644 Could we have equality at any point in the range? If so we
1645 have "unknown", otherwise we have "true". */
1646 tree base_le_rhs = fold_binary (LE_EXPR, boolean_type_node,
1647 base_cst, rhs_cst);
1648 if (base_le_rhs == boolean_true_node)
1649 return tristate::TS_UNKNOWN;
1650 else
1651 return tristate::TS_TRUE;
1652 }
1653
1654 default:
1655 return tristate::TS_UNKNOWN;
1656 }
1657
1658 case DIR_DESCENDING:
1659 /* LHS is in (-ve infinity, base_cst], assuming no overflow. */
1660 return tristate::TS_UNKNOWN;
1661
1662 case DIR_UNKNOWN:
1663 return tristate::TS_UNKNOWN;
1664 }
1665 }
1666
1667 /* class placeholder_svalue : public svalue. */
1668
1669 /* Implementation of svalue::dump_to_pp vfunc for placeholder_svalue. */
1670
1671 void
dump_to_pp(pretty_printer * pp,bool simple) const1672 placeholder_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1673 {
1674 if (simple)
1675 pp_printf (pp, "PLACEHOLDER(%qs)", m_name);
1676 else
1677 pp_printf (pp, "placeholder_svalue (%qs)", m_name);
1678 }
1679
1680 /* Implementation of svalue::accept vfunc for placeholder_svalue. */
1681
1682 void
accept(visitor * v) const1683 placeholder_svalue::accept (visitor *v) const
1684 {
1685 v->visit_placeholder_svalue (this);
1686 }
1687
1688 /* class unmergeable_svalue : public svalue. */
1689
1690 /* Implementation of svalue::dump_to_pp vfunc for unmergeable_svalue. */
1691
1692 void
dump_to_pp(pretty_printer * pp,bool simple) const1693 unmergeable_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1694 {
1695 if (simple)
1696 {
1697 pp_string (pp, "UNMERGEABLE(");
1698 m_arg->dump_to_pp (pp, simple);
1699 pp_character (pp, ')');
1700 }
1701 else
1702 {
1703 pp_string (pp, "unmergeable_svalue (");
1704 m_arg->dump_to_pp (pp, simple);
1705 pp_character (pp, ')');
1706 }
1707 }
1708
1709 /* Implementation of svalue::accept vfunc for unmergeable_svalue. */
1710
1711 void
accept(visitor * v) const1712 unmergeable_svalue::accept (visitor *v) const
1713 {
1714 v->visit_unmergeable_svalue (this);
1715 m_arg->accept (v);
1716 }
1717
1718 /* Implementation of svalue::implicitly_live_p vfunc for unmergeable_svalue. */
1719
1720 bool
implicitly_live_p(const svalue_set * live_svalues,const region_model * model) const1721 unmergeable_svalue::implicitly_live_p (const svalue_set *live_svalues,
1722 const region_model *model) const
1723 {
1724 return get_arg ()->live_p (live_svalues, model);
1725 }
1726
1727 /* class compound_svalue : public svalue. */
1728
compound_svalue(tree type,const binding_map & map)1729 compound_svalue::compound_svalue (tree type, const binding_map &map)
1730 : svalue (calc_complexity (map), type), m_map (map)
1731 {
1732 /* All keys within the underlying binding_map are required to be concrete,
1733 not symbolic. */
1734 #if CHECKING_P
1735 for (iterator_t iter = begin (); iter != end (); ++iter)
1736 {
1737 const binding_key *key = (*iter).first;
1738 gcc_assert (key->concrete_p ());
1739 }
1740 #endif
1741 }
1742
1743 /* Implementation of svalue::dump_to_pp vfunc for compound_svalue. */
1744
1745 void
dump_to_pp(pretty_printer * pp,bool simple) const1746 compound_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1747 {
1748 if (simple)
1749 {
1750 pp_string (pp, "COMPOUND(");
1751 if (get_type ())
1752 {
1753 print_quoted_type (pp, get_type ());
1754 pp_string (pp, ", ");
1755 }
1756 pp_character (pp, '{');
1757 m_map.dump_to_pp (pp, simple, false);
1758 pp_string (pp, "})");
1759 }
1760 else
1761 {
1762 pp_string (pp, "compound_svalue (");
1763 if (get_type ())
1764 {
1765 print_quoted_type (pp, get_type ());
1766 pp_string (pp, ", ");
1767 }
1768 pp_character (pp, '{');
1769 m_map.dump_to_pp (pp, simple, false);
1770 pp_string (pp, "})");
1771 }
1772 }
1773
1774 /* Implementation of svalue::accept vfunc for compound_svalue. */
1775
1776 void
accept(visitor * v) const1777 compound_svalue::accept (visitor *v) const
1778 {
1779 v->visit_compound_svalue (this);
1780 for (binding_map::iterator_t iter = m_map.begin ();
1781 iter != m_map.end (); ++iter)
1782 {
1783 //(*iter).first.accept (v);
1784 (*iter).second->accept (v);
1785 }
1786 }
1787
1788 /* Calculate what the complexity of a compound_svalue instance for MAP
1789 will be, based on the svalues bound within MAP. */
1790
1791 complexity
calc_complexity(const binding_map & map)1792 compound_svalue::calc_complexity (const binding_map &map)
1793 {
1794 unsigned num_child_nodes = 0;
1795 unsigned max_child_depth = 0;
1796 for (binding_map::iterator_t iter = map.begin ();
1797 iter != map.end (); ++iter)
1798 {
1799 const complexity &sval_c = (*iter).second->get_complexity ();
1800 num_child_nodes += sval_c.m_num_nodes;
1801 max_child_depth = MAX (max_child_depth, sval_c.m_max_depth);
1802 }
1803 return complexity (num_child_nodes + 1, max_child_depth + 1);
1804 }
1805
1806 /* Implementation of svalue::maybe_fold_bits_within vfunc
1807 for compound_svalue. */
1808
1809 const svalue *
maybe_fold_bits_within(tree type,const bit_range & bits,region_model_manager * mgr) const1810 compound_svalue::maybe_fold_bits_within (tree type,
1811 const bit_range &bits,
1812 region_model_manager *mgr) const
1813 {
1814 binding_map result_map;
1815 for (auto iter : m_map)
1816 {
1817 const binding_key *key = iter.first;
1818 if (const concrete_binding *conc_key
1819 = key->dyn_cast_concrete_binding ())
1820 {
1821 /* Ignore concrete bindings outside BITS. */
1822 if (!conc_key->get_bit_range ().intersects_p (bits))
1823 continue;
1824
1825 const svalue *sval = iter.second;
1826 /* Get the position of conc_key relative to BITS. */
1827 bit_range result_location (conc_key->get_start_bit_offset ()
1828 - bits.get_start_bit_offset (),
1829 conc_key->get_size_in_bits ());
1830 /* If conc_key starts after BITS, trim off leading bits
1831 from the svalue and adjust binding location. */
1832 if (result_location.m_start_bit_offset < 0)
1833 {
1834 bit_size_t leading_bits_to_drop
1835 = -result_location.m_start_bit_offset;
1836 result_location = bit_range
1837 (0, result_location.m_size_in_bits - leading_bits_to_drop);
1838 bit_range bits_within_sval (leading_bits_to_drop,
1839 result_location.m_size_in_bits);
1840 /* Trim off leading bits from iter_sval. */
1841 sval = mgr->get_or_create_bits_within (NULL_TREE,
1842 bits_within_sval,
1843 sval);
1844 }
1845 /* If conc_key finishes after BITS, trim off trailing bits
1846 from the svalue and adjust binding location. */
1847 if (conc_key->get_next_bit_offset ()
1848 > bits.get_next_bit_offset ())
1849 {
1850 bit_size_t trailing_bits_to_drop
1851 = (conc_key->get_next_bit_offset ()
1852 - bits.get_next_bit_offset ());
1853 result_location = bit_range
1854 (result_location.m_start_bit_offset,
1855 result_location.m_size_in_bits - trailing_bits_to_drop);
1856 bit_range bits_within_sval (0,
1857 result_location.m_size_in_bits);
1858 /* Trim off leading bits from iter_sval. */
1859 sval = mgr->get_or_create_bits_within (NULL_TREE,
1860 bits_within_sval,
1861 sval);
1862 }
1863 const concrete_binding *offset_conc_key
1864 = mgr->get_store_manager ()->get_concrete_binding
1865 (result_location);
1866 result_map.put (offset_conc_key, sval);
1867 }
1868 else
1869 /* If we have any symbolic keys we can't get it as bits. */
1870 return NULL;
1871 }
1872 return mgr->get_or_create_compound_svalue (type, result_map);
1873 }
1874
1875 /* class conjured_svalue : public svalue. */
1876
1877 /* Implementation of svalue::dump_to_pp vfunc for conjured_svalue. */
1878
1879 void
dump_to_pp(pretty_printer * pp,bool simple) const1880 conjured_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1881 {
1882 if (simple)
1883 {
1884 pp_string (pp, "CONJURED(");
1885 pp_gimple_stmt_1 (pp, m_stmt, 0, (dump_flags_t)0);
1886 pp_string (pp, ", ");
1887 m_id_reg->dump_to_pp (pp, simple);
1888 pp_character (pp, ')');
1889 }
1890 else
1891 {
1892 pp_string (pp, "conjured_svalue (");
1893 pp_string (pp, ", ");
1894 pp_gimple_stmt_1 (pp, m_stmt, 0, (dump_flags_t)0);
1895 pp_string (pp, ", ");
1896 m_id_reg->dump_to_pp (pp, simple);
1897 pp_character (pp, ')');
1898 }
1899 }
1900
1901 /* Implementation of svalue::accept vfunc for conjured_svalue. */
1902
1903 void
accept(visitor * v) const1904 conjured_svalue::accept (visitor *v) const
1905 {
1906 v->visit_conjured_svalue (this);
1907 m_id_reg->accept (v);
1908 }
1909
1910 /* class asm_output_svalue : public svalue. */
1911
1912 /* Implementation of svalue::dump_to_pp vfunc for asm_output_svalue. */
1913
1914 void
dump_to_pp(pretty_printer * pp,bool simple) const1915 asm_output_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1916 {
1917 if (simple)
1918 {
1919 pp_printf (pp, "ASM_OUTPUT(%qs, %%%i, {",
1920 get_asm_string (),
1921 get_output_idx ());
1922 for (unsigned i = 0; i < m_num_inputs; i++)
1923 {
1924 if (i > 0)
1925 pp_string (pp, ", ");
1926 dump_input (pp, 0, m_input_arr[i], simple);
1927 }
1928 pp_string (pp, "})");
1929 }
1930 else
1931 {
1932 pp_printf (pp, "asm_output_svalue (%qs, %%%i, {",
1933 get_asm_string (),
1934 get_output_idx ());
1935 for (unsigned i = 0; i < m_num_inputs; i++)
1936 {
1937 if (i > 0)
1938 pp_string (pp, ", ");
1939 dump_input (pp, 0, m_input_arr[i], simple);
1940 }
1941 pp_string (pp, "})");
1942 }
1943 }
1944
1945 /* Subroutine of asm_output_svalue::dump_to_pp. */
1946
1947 void
dump_input(pretty_printer * pp,unsigned input_idx,const svalue * sval,bool simple) const1948 asm_output_svalue::dump_input (pretty_printer *pp,
1949 unsigned input_idx,
1950 const svalue *sval,
1951 bool simple) const
1952 {
1953 pp_printf (pp, "%%%i: ", input_idx_to_asm_idx (input_idx));
1954 sval->dump_to_pp (pp, simple);
1955 }
1956
1957 /* Convert INPUT_IDX from an index into the array of inputs
1958 into the index of all operands for the asm stmt. */
1959
1960 unsigned
input_idx_to_asm_idx(unsigned input_idx) const1961 asm_output_svalue::input_idx_to_asm_idx (unsigned input_idx) const
1962 {
1963 return input_idx + m_num_outputs;
1964 }
1965
1966 /* Implementation of svalue::accept vfunc for asm_output_svalue. */
1967
1968 void
accept(visitor * v) const1969 asm_output_svalue::accept (visitor *v) const
1970 {
1971 v->visit_asm_output_svalue (this);
1972 for (unsigned i = 0; i < m_num_inputs; i++)
1973 m_input_arr[i]->accept (v);
1974 }
1975
1976 /* class const_fn_result_svalue : public svalue. */
1977
1978 /* Implementation of svalue::dump_to_pp vfunc for const_fn_result_svalue. */
1979
1980 void
dump_to_pp(pretty_printer * pp,bool simple) const1981 const_fn_result_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
1982 {
1983 if (simple)
1984 {
1985 pp_printf (pp, "CONST_FN_RESULT(%qD, {", m_fndecl);
1986 for (unsigned i = 0; i < m_num_inputs; i++)
1987 {
1988 if (i > 0)
1989 pp_string (pp, ", ");
1990 dump_input (pp, i, m_input_arr[i], simple);
1991 }
1992 pp_string (pp, "})");
1993 }
1994 else
1995 {
1996 pp_printf (pp, "CONST_FN_RESULT(%qD, {", m_fndecl);
1997 for (unsigned i = 0; i < m_num_inputs; i++)
1998 {
1999 if (i > 0)
2000 pp_string (pp, ", ");
2001 dump_input (pp, i, m_input_arr[i], simple);
2002 }
2003 pp_string (pp, "})");
2004 }
2005 }
2006
2007 /* Subroutine of const_fn_result_svalue::dump_to_pp. */
2008
2009 void
dump_input(pretty_printer * pp,unsigned input_idx,const svalue * sval,bool simple) const2010 const_fn_result_svalue::dump_input (pretty_printer *pp,
2011 unsigned input_idx,
2012 const svalue *sval,
2013 bool simple) const
2014 {
2015 pp_printf (pp, "arg%i: ", input_idx);
2016 sval->dump_to_pp (pp, simple);
2017 }
2018
2019 /* Implementation of svalue::accept vfunc for const_fn_result_svalue. */
2020
2021 void
accept(visitor * v) const2022 const_fn_result_svalue::accept (visitor *v) const
2023 {
2024 v->visit_const_fn_result_svalue (this);
2025 for (unsigned i = 0; i < m_num_inputs; i++)
2026 m_input_arr[i]->accept (v);
2027 }
2028
2029 } // namespace ana
2030
2031 #endif /* #if ENABLE_ANALYZER */
2032