Line data Source code
1 : /* Regions of memory.
2 : Copyright (C) 2019-2026 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 "analyzer/common.h"
22 :
23 : #include "ordered-hash-map.h"
24 : #include "options.h"
25 : #include "cgraph.h"
26 : #include "cfg.h"
27 : #include "digraph.h"
28 : #include "sbitmap.h"
29 : #include "fold-const.h"
30 : #include "tree-ssa.h"
31 :
32 : #include "analyzer/analyzer-logging.h"
33 : #include "analyzer/supergraph.h"
34 : #include "analyzer/call-string.h"
35 : #include "analyzer/program-point.h"
36 : #include "analyzer/store.h"
37 : #include "analyzer/region.h"
38 : #include "analyzer/region-model.h"
39 : #include "analyzer/sm.h"
40 : #include "analyzer/program-state.h"
41 : #include "text-art/dump.h"
42 :
43 : #if ENABLE_ANALYZER
44 :
45 : namespace ana {
46 :
47 : bool
48 854 : compare_bit_offsets_p (bit_offset_t a,
49 : enum tree_code op,
50 : bit_offset_t b)
51 : {
52 854 : switch (op)
53 : {
54 0 : default:
55 0 : gcc_unreachable ();
56 790 : case EQ_EXPR: return a == b;
57 0 : case NE_EXPR: return a != b;
58 16 : case GE_EXPR: return a >= b;
59 16 : case LE_EXPR: return a <= b;
60 16 : case GT_EXPR: return a > b;
61 16 : case LT_EXPR: return a < b;
62 : }
63 : }
64 :
65 : region_offset
66 1314 : region_offset::make_byte_offset (const region *base_region,
67 : const svalue *num_bytes_sval)
68 : {
69 1314 : if (tree num_bytes_cst = num_bytes_sval->maybe_get_constant ())
70 : {
71 982 : gcc_assert (TREE_CODE (num_bytes_cst) == INTEGER_CST);
72 982 : bit_offset_t num_bits = wi::to_offset (num_bytes_cst) * BITS_PER_UNIT;
73 982 : return make_concrete (base_region, num_bits);
74 : }
75 : else
76 : {
77 332 : return make_symbolic (base_region, num_bytes_sval);
78 : }
79 : }
80 :
81 : const svalue &
82 580 : region_offset::calc_symbolic_bit_offset (region_model_manager *mgr) const
83 : {
84 580 : if (symbolic_p ())
85 : {
86 127 : const svalue *bits_per_byte
87 127 : = mgr->get_or_create_int_cst (NULL_TREE, BITS_PER_UNIT);
88 127 : return *mgr->get_or_create_binop (NULL_TREE, MULT_EXPR,
89 127 : m_sym_offset, bits_per_byte);
90 : }
91 : else
92 453 : return *mgr->get_or_create_int_cst (NULL_TREE, m_offset);
93 : }
94 :
95 : const svalue *
96 206 : region_offset::calc_symbolic_byte_offset (region_model_manager *mgr) const
97 : {
98 206 : if (symbolic_p ())
99 : return m_sym_offset;
100 : else
101 : {
102 18 : byte_offset_t concrete_byte_offset;
103 18 : if (get_concrete_byte_offset (&concrete_byte_offset))
104 18 : return mgr->get_or_create_int_cst (size_type_node,
105 18 : concrete_byte_offset);
106 : else
107 : /* Can't handle bitfields; return UNKNOWN. */
108 0 : return mgr->get_or_create_unknown_svalue (size_type_node);
109 : }
110 : }
111 :
112 : void
113 0 : region_offset::dump_to_pp (pretty_printer *pp, bool simple) const
114 : {
115 0 : pp_string (pp, "{");
116 0 : m_base_region->dump_to_pp (pp, simple);
117 0 : if (symbolic_p ())
118 : {
119 0 : pp_string (pp, " byte ");
120 0 : m_sym_offset->dump_to_pp (pp, simple);
121 : }
122 : else
123 : {
124 0 : if (m_offset % BITS_PER_UNIT == 0)
125 : {
126 0 : pp_string (pp, " byte ");
127 0 : pp_wide_int (pp, m_offset / BITS_PER_UNIT, SIGNED);
128 : }
129 : else
130 : {
131 0 : pp_string (pp, " bit ");
132 0 : pp_wide_int (pp, m_offset, SIGNED);
133 : }
134 : }
135 0 : pp_string (pp, "}");
136 0 : }
137 :
138 : DEBUG_FUNCTION void
139 0 : region_offset::dump (bool simple) const
140 : {
141 0 : tree_dump_pretty_printer pp (stderr);
142 0 : dump_to_pp (&pp, simple);
143 0 : pp_newline (&pp);
144 0 : }
145 :
146 : /* An svalue that matches the pattern (BASE * FACTOR) + OFFSET
147 : where FACTOR or OFFSET could be the identity (represented as nullptr). */
148 :
149 : struct linear_op
150 : {
151 5470 : linear_op (const svalue *base,
152 : const svalue *factor,
153 : const svalue *offset)
154 1868 : : m_base (base), m_factor (factor), m_offset (offset)
155 : {
156 : }
157 :
158 3452 : bool maybe_get_cst_factor (bit_offset_t *out) const
159 : {
160 3452 : if (m_factor == nullptr)
161 : {
162 732 : *out = 1;
163 732 : return true;
164 : }
165 2720 : if (tree cst_factor = m_factor->maybe_get_constant ())
166 : {
167 2720 : *out = wi::to_offset (cst_factor);
168 2720 : return true;
169 : }
170 : return false;
171 : }
172 :
173 3126 : bool maybe_get_cst_offset (bit_offset_t *out) const
174 : {
175 3126 : if (m_offset == nullptr)
176 : {
177 842 : *out = 0;
178 842 : return true;
179 : }
180 2284 : if (tree cst_offset = m_offset->maybe_get_constant ())
181 : {
182 2222 : *out = wi::to_offset (cst_offset);
183 2222 : return true;
184 : }
185 : return false;
186 : }
187 :
188 : static tristate
189 1675 : less (const linear_op &a, const linear_op &b)
190 : {
191 : /* Same base. */
192 1675 : if (a.m_base == b.m_base)
193 : {
194 1611 : bit_offset_t a_wi_factor;
195 1611 : bit_offset_t b_wi_factor;
196 1611 : if (a.maybe_get_cst_factor (&a_wi_factor)
197 1611 : && b.maybe_get_cst_factor (&b_wi_factor))
198 : {
199 1611 : if (a_wi_factor != b_wi_factor)
200 172 : return tristate (a_wi_factor < b_wi_factor);
201 : else
202 : {
203 1495 : bit_offset_t a_wi_offset;
204 1495 : bit_offset_t b_wi_offset;
205 1495 : if (a.maybe_get_cst_offset (&a_wi_offset)
206 1495 : && b.maybe_get_cst_offset (&b_wi_offset))
207 2498 : return tristate (a_wi_offset < b_wi_offset);
208 : }
209 : }
210 : }
211 124 : return tristate::unknown ();
212 : }
213 :
214 : static tristate
215 115 : le (const linear_op &a, const linear_op &b)
216 : {
217 : /* Same base. */
218 115 : if (a.m_base == b.m_base)
219 : {
220 115 : bit_offset_t a_wi_factor;
221 115 : bit_offset_t b_wi_factor;
222 115 : if (a.maybe_get_cst_factor (&a_wi_factor)
223 115 : && b.maybe_get_cst_factor (&b_wi_factor))
224 : {
225 115 : if (a_wi_factor != b_wi_factor)
226 32 : return tristate (a_wi_factor <= b_wi_factor);
227 : else
228 : {
229 99 : bit_offset_t a_wi_offset;
230 99 : bit_offset_t b_wi_offset;
231 99 : if (a.maybe_get_cst_offset (&a_wi_offset)
232 99 : && b.maybe_get_cst_offset (&b_wi_offset))
233 140 : return tristate (a_wi_offset <= b_wi_offset);
234 : }
235 : }
236 : }
237 2 : return tristate::unknown ();
238 : }
239 :
240 : static bool
241 3680 : from_svalue (const svalue &sval, linear_op *out)
242 : {
243 3680 : switch (sval.get_kind ())
244 : {
245 : default:
246 : break;
247 3602 : case SK_BINOP:
248 3602 : {
249 3602 : const binop_svalue &binop_sval ((const binop_svalue &)sval);
250 3602 : if (binop_sval.get_op () == MULT_EXPR)
251 : {
252 1078 : *out = linear_op (binop_sval.get_arg0 (),
253 : binop_sval.get_arg1 (),
254 1078 : nullptr);
255 1078 : return true;
256 : }
257 2524 : else if (binop_sval.get_op () == PLUS_EXPR)
258 : {
259 2524 : if (binop_sval.get_arg0 ()->get_kind () == SK_BINOP)
260 : {
261 1786 : const binop_svalue &inner_binop_sval
262 1786 : ((const binop_svalue &)*binop_sval.get_arg0 ());
263 1786 : if (inner_binop_sval.get_op () == MULT_EXPR)
264 : {
265 1642 : *out = linear_op (inner_binop_sval.get_arg0 (),
266 : inner_binop_sval.get_arg1 (),
267 1642 : binop_sval.get_arg1 ());
268 1642 : return true;
269 : }
270 : }
271 :
272 882 : *out = linear_op (binop_sval.get_arg0 (),
273 : nullptr,
274 882 : binop_sval.get_arg1 ());
275 882 : return true;
276 : }
277 : }
278 : break;
279 : }
280 : return false;
281 : }
282 :
283 : const svalue *m_base;
284 : const svalue *m_factor;
285 : const svalue *m_offset;
286 : };
287 :
288 : bool
289 24035 : operator< (const region_offset &a, const region_offset &b)
290 : {
291 24035 : if (a.symbolic_p ())
292 : {
293 2152 : if (b.symbolic_p ())
294 : {
295 : /* Symbolic vs symbolic. */
296 1743 : const svalue &a_sval = *a.get_symbolic_byte_offset ();
297 1743 : const svalue &b_sval = *b.get_symbolic_byte_offset ();
298 :
299 1743 : linear_op op_a (nullptr, nullptr, nullptr);
300 1743 : linear_op op_b (nullptr, nullptr, nullptr);
301 1743 : if (linear_op::from_svalue (a_sval, &op_a)
302 1743 : && linear_op::from_svalue (b_sval, &op_b))
303 : {
304 1675 : tristate ts = linear_op::less (op_a, op_b);
305 1675 : if (ts.is_true ())
306 1743 : return true;
307 1243 : else if (ts.is_false ())
308 : return false;
309 : }
310 : /* Use svalue's deterministic order, for now. */
311 192 : return (svalue::cmp_ptr (a.get_symbolic_byte_offset (),
312 : b.get_symbolic_byte_offset ())
313 192 : < 0);
314 : }
315 : else
316 : /* Symbolic vs concrete: put all symbolic after all concrete. */
317 : return false;
318 : }
319 : else
320 : {
321 21883 : if (b.symbolic_p ())
322 : /* Concrete vs symbolic: put all concrete before all symbolic. */
323 : return true;
324 : else
325 : /* Concrete vs concrete. */
326 21526 : return a.get_bit_offset () < b.get_bit_offset ();
327 : }
328 : }
329 :
330 : bool
331 1567 : operator<= (const region_offset &a, const region_offset &b)
332 : {
333 1567 : if (a.symbolic_p ())
334 : {
335 168 : if (b.symbolic_p ())
336 : {
337 : /* Symbolic vs symbolic. */
338 125 : const svalue &a_sval = *a.get_symbolic_byte_offset ();
339 125 : const svalue &b_sval = *b.get_symbolic_byte_offset ();
340 :
341 125 : linear_op op_a (nullptr, nullptr, nullptr);
342 125 : linear_op op_b (nullptr, nullptr, nullptr);
343 125 : if (linear_op::from_svalue (a_sval, &op_a)
344 125 : && linear_op::from_svalue (b_sval, &op_b))
345 : {
346 115 : tristate ts = linear_op::le (op_a, op_b);
347 115 : if (ts.is_true ())
348 125 : return true;
349 61 : else if (ts.is_false ())
350 : return false;
351 : }
352 : /* Use svalue's deterministic order, for now. */
353 12 : return (svalue::cmp_ptr (a.get_symbolic_byte_offset (),
354 : b.get_symbolic_byte_offset ())
355 12 : <= 0);
356 : }
357 : else
358 : /* Symbolic vs concrete: put all symbolic after all concrete. */
359 : return false;
360 : }
361 : else
362 : {
363 1399 : if (b.symbolic_p ())
364 : /* Concrete vs symbolic: put all concrete before all symbolic. */
365 : return true;
366 : else
367 : /* Concrete vs concrete. */
368 1324 : return a.get_bit_offset () <= b.get_bit_offset ();
369 : }
370 : }
371 :
372 : bool
373 30 : operator> (const region_offset &a, const region_offset &b)
374 : {
375 30 : return b < a;
376 : }
377 :
378 : bool
379 136 : operator>= (const region_offset &a, const region_offset &b)
380 : {
381 136 : return b <= a;
382 : }
383 :
384 : region_offset
385 5176 : strip_types (const region_offset &offset, region_model_manager &mgr)
386 : {
387 5176 : if (offset.symbolic_p ())
388 877 : return region_offset::make_symbolic
389 877 : (offset.get_base_region (),
390 : strip_types (offset.get_symbolic_byte_offset (),
391 877 : mgr));
392 : else
393 4299 : return offset;
394 : }
395 :
396 : /* Ignoring base regions, compare the byte offset of OFFSET_A and OFFSET_B
397 : within their respective base regions. */
398 :
399 : static tristate
400 1070 : eval_byte_offset_comparison (region_offset offset_a,
401 : enum tree_code op,
402 : region_offset offset_b,
403 : const region_model &model)
404 : {
405 1070 : if (offset_a.concrete_p ())
406 : {
407 854 : if (offset_b.concrete_p ())
408 : {
409 : // Concrete vs concrete: we know the result:
410 854 : return compare_bit_offsets_p (offset_a.get_bit_offset (),
411 : op,
412 854 : offset_b.get_bit_offset ());
413 : }
414 : else
415 : {
416 : // Concrete vs symbolic
417 : // TODO: There may be room for improved precision here
418 0 : return tristate::unknown ();
419 : }
420 : }
421 : else
422 : {
423 216 : if (offset_b.concrete_p ())
424 : {
425 : // Symbolic vs concrete
426 : // TODO: There may be room for improved precision here
427 0 : return tristate::unknown ();
428 : }
429 : else
430 : {
431 : // Symbolic vs symbolic
432 216 : const svalue *offset_sval_a = offset_a.get_symbolic_byte_offset ();
433 216 : const svalue *offset_sval_b = offset_b.get_symbolic_byte_offset ();
434 216 : return model.eval_condition (offset_sval_a, op, offset_sval_b);
435 : }
436 : }
437 : }
438 :
439 : /* Evaluate the condition LHS_OFFSET OP RHS_OFFSET for comparing
440 : pointers.
441 :
442 : See if they point to the same base region, and if we know about
443 : the offsets within their regions.
444 :
445 : Use MODEL for aliasing information and any knowledge from
446 : constraint_manager about ordering of pointers. */
447 :
448 : tristate
449 910 : eval_region_offset_comparison (region_offset lhs_offset,
450 : enum tree_code op,
451 : region_offset rhs_offset,
452 : const region_model &model)
453 : {
454 : /* Try to determine if they're the same base region. */
455 910 : const tristate same_base_region
456 910 : = model.get_store ()->eval_alias (lhs_offset.get_base_region (),
457 : rhs_offset.get_base_region (),
458 : model);
459 :
460 : /* Try to determine if they're the same offset relative to their
461 : base region. */
462 910 : const tristate same_byte_offset
463 910 : = eval_byte_offset_comparison (lhs_offset, EQ_EXPR, rhs_offset, model);
464 :
465 : /* With that, we might know if they're equal/non-equal. */
466 910 : const tristate equality = same_base_region.and_(same_byte_offset);
467 :
468 910 : switch (op)
469 : {
470 0 : default:
471 0 : gcc_unreachable ();
472 :
473 324 : case EQ_EXPR:
474 324 : return equality;
475 :
476 290 : case NE_EXPR:
477 290 : return equality.not_ ();
478 :
479 148 : case GE_EXPR:
480 148 : case LE_EXPR:
481 148 : if (equality.is_true ())
482 16 : return tristate (true);
483 132 : else if (same_base_region.is_true ())
484 80 : return eval_byte_offset_comparison (lhs_offset, op, rhs_offset, model);
485 : else
486 52 : return tristate::unknown ();
487 :
488 148 : case GT_EXPR:
489 148 : case LT_EXPR:
490 148 : if (equality.is_true ())
491 16 : return tristate (false);
492 132 : else if (same_base_region.is_true ())
493 80 : return eval_byte_offset_comparison (lhs_offset, op, rhs_offset, model);
494 : else
495 52 : return tristate::unknown ();
496 : }
497 : }
498 :
499 : /* class region and its various subclasses. */
500 :
501 : /* class region. */
502 :
503 219108 : region::~region ()
504 : {
505 219108 : delete m_cached_offset;
506 219108 : }
507 :
508 : /* Determine the base region for this region: when considering bindings
509 : for this region, the base region is the ancestor which identifies
510 : which cluster they should be partitioned into.
511 : Regions within the same struct/union/array are in the same cluster.
512 : Different decls are in different clusters. */
513 :
514 : const region *
515 51569241 : region::get_base_region () const
516 : {
517 51569241 : const region *iter = this;
518 53459902 : while (iter)
519 : {
520 53459902 : switch (iter->get_kind ())
521 : {
522 1890661 : case RK_FIELD:
523 1890661 : case RK_ELEMENT:
524 1890661 : case RK_OFFSET:
525 1890661 : case RK_SIZED:
526 1890661 : case RK_BIT_RANGE:
527 1890661 : case RK_CAST:
528 1890661 : iter = iter->get_parent_region ();
529 1890661 : continue;
530 : default:
531 : return iter;
532 : }
533 : }
534 : return iter;
535 : }
536 :
537 : /* Return true if get_base_region() == this for this region. */
538 :
539 : bool
540 253347 : region::base_region_p () const
541 : {
542 253347 : switch (get_kind ())
543 : {
544 : /* Region kinds representing a descendent of a base region. */
545 : case RK_FIELD:
546 : case RK_ELEMENT:
547 : case RK_OFFSET:
548 : case RK_SIZED:
549 : case RK_CAST:
550 : case RK_BIT_RANGE:
551 : return false;
552 :
553 191738 : default:
554 191738 : return true;
555 : }
556 : }
557 :
558 : /* Return true if this region is ELDER or one of its descendents. */
559 :
560 : bool
561 259382 : region::descendent_of_p (const region *elder) const
562 : {
563 259382 : const region *iter = this;
564 999722 : while (iter)
565 : {
566 800119 : if (iter == elder)
567 : return true;
568 740340 : iter = iter->get_parent_region ();
569 : }
570 : return false;
571 : }
572 :
573 : /* If this region is a frame_region, or a descendent of one, return it.
574 : Otherwise return nullptr. */
575 :
576 : const frame_region *
577 2739089 : region::maybe_get_frame_region () const
578 : {
579 2739089 : const region *iter = this;
580 6690907 : while (iter)
581 : {
582 6094641 : if (const frame_region *frame_reg = iter->dyn_cast_frame_region ())
583 : return frame_reg;
584 3951818 : iter = iter->get_parent_region ();
585 : }
586 : return nullptr;
587 : }
588 :
589 : /* Get the memory space of this region. */
590 :
591 : enum memory_space
592 3929420 : region::get_memory_space () const
593 : {
594 3929420 : const region *iter = this;
595 8251636 : while (iter)
596 : {
597 7513791 : switch (iter->get_kind ())
598 : {
599 4322216 : default:
600 4322216 : break;
601 : case RK_GLOBALS:
602 : return MEMSPACE_GLOBALS;
603 : case RK_CODE:
604 : case RK_FUNCTION:
605 : case RK_LABEL:
606 : return MEMSPACE_CODE;
607 : case RK_FRAME:
608 : case RK_STACK:
609 : case RK_ALLOCA:
610 : return MEMSPACE_STACK;
611 : case RK_HEAP:
612 : case RK_HEAP_ALLOCATED:
613 : return MEMSPACE_HEAP;
614 : case RK_STRING:
615 : return MEMSPACE_READONLY_DATA;
616 : case RK_PRIVATE:
617 : return MEMSPACE_PRIVATE;
618 : }
619 4322216 : iter = iter->get_parent_region ();
620 : }
621 : return MEMSPACE_UNKNOWN;
622 : }
623 :
624 : /* Subroutine for use by region_model_manager::get_or_create_initial_value.
625 : Return true if this region has an initial_svalue.
626 : Return false if attempting to use INIT_VAL(this_region) should give
627 : the "UNINITIALIZED" poison value. */
628 :
629 : bool
630 3185943 : region::can_have_initial_svalue_p () const
631 : {
632 3185943 : const region *base_reg = get_base_region ();
633 :
634 : /* Check for memory spaces that are uninitialized by default. */
635 3185943 : enum memory_space mem_space = base_reg->get_memory_space ();
636 3185943 : switch (mem_space)
637 : {
638 0 : default:
639 0 : gcc_unreachable ();
640 : case MEMSPACE_UNKNOWN:
641 : case MEMSPACE_CODE:
642 : case MEMSPACE_GLOBALS:
643 : case MEMSPACE_READONLY_DATA:
644 : case MEMSPACE_PRIVATE:
645 : /* Such regions have initial_svalues. */
646 : return true;
647 :
648 : case MEMSPACE_HEAP:
649 : /* Heap allocations are uninitialized by default. */
650 : return false;
651 :
652 2281213 : case MEMSPACE_STACK:
653 2281213 : if (tree decl = base_reg->maybe_get_decl ())
654 : {
655 : /* See the assertion in frame_region::get_region_for_local for the
656 : tree codes we need to handle here. */
657 2275295 : switch (TREE_CODE (decl))
658 : {
659 0 : default:
660 0 : gcc_unreachable ();
661 :
662 : case PARM_DECL:
663 : /* Parameters have initial values. */
664 : return true;
665 :
666 : case VAR_DECL:
667 : case RESULT_DECL:
668 : /* Function locals don't have initial values. */
669 : return false;
670 :
671 2188067 : case SSA_NAME:
672 2188067 : {
673 : /* Some SSA names have an implicit default defined value. */
674 2188067 : tree ssa_name = decl;
675 2188067 : if (SSA_NAME_IS_DEFAULT_DEF (ssa_name))
676 2127624 : return ssa_defined_default_def_p (ssa_name);
677 : /* Others don't. */
678 : return false;
679 : }
680 : }
681 : }
682 :
683 : /* If we have an on-stack region that isn't associated with a decl
684 : or SSA name, then we have VLA/alloca, which is uninitialized. */
685 : return false;
686 : }
687 : }
688 :
689 : /* For regions within a global decl, get the svalue for the initial
690 : value of this region when the program starts, caching the result. */
691 :
692 : const svalue *
693 14707 : region::get_initial_value_at_main (region_model_manager *mgr) const
694 : {
695 14707 : if (!m_cached_init_sval_at_main)
696 421 : m_cached_init_sval_at_main = calc_initial_value_at_main (mgr);
697 14707 : return m_cached_init_sval_at_main;
698 : }
699 :
700 : /* Implementation of region::get_initial_value_at_main. */
701 :
702 : const svalue *
703 421 : region::calc_initial_value_at_main (region_model_manager *mgr) const
704 : {
705 421 : const decl_region *base_reg = get_base_region ()->dyn_cast_decl_region ();
706 421 : gcc_assert (base_reg);
707 :
708 : /* Attempt to get the initializer value for base_reg. */
709 842 : if (const svalue *base_reg_init
710 421 : = base_reg->get_svalue_for_initializer (mgr))
711 : {
712 304 : if (this == base_reg)
713 : return base_reg_init;
714 : else
715 : {
716 : /* Get the value for REG within base_reg_init. */
717 168 : binding_cluster c (*mgr->get_store_manager (), base_reg);
718 168 : c.bind (mgr->get_store_manager (), base_reg, base_reg_init);
719 168 : const svalue *sval
720 168 : = c.get_any_binding (mgr->get_store_manager (), this);
721 168 : if (sval)
722 : {
723 167 : if (get_type ())
724 147 : sval = mgr->get_or_create_cast (get_type (), sval);
725 167 : return sval;
726 : }
727 168 : }
728 : }
729 :
730 : /* Otherwise, return INIT_VAL(REG). */
731 118 : return mgr->get_or_create_initial_value (this);
732 : }
733 :
734 : /* If this region is a decl_region, return the decl.
735 : Otherwise return NULL_TREE. */
736 :
737 : tree
738 3489931 : region::maybe_get_decl () const
739 : {
740 3489931 : if (const decl_region *decl_reg = dyn_cast_decl_region ())
741 3119909 : return decl_reg->get_decl ();
742 : return NULL_TREE;
743 : }
744 :
745 : /* Get the region_offset for this region (calculating it on the
746 : first call and caching it internally). */
747 :
748 : region_offset
749 4867405 : region::get_offset (region_model_manager *mgr) const
750 : {
751 4867405 : if(!m_cached_offset)
752 150169 : m_cached_offset = new region_offset (calc_offset (mgr));
753 4867405 : return *m_cached_offset;
754 : }
755 :
756 : /* Get the region_offset for immediately beyond this region. */
757 :
758 : region_offset
759 1031 : region::get_next_offset (region_model_manager *mgr) const
760 : {
761 1031 : region_offset start = get_offset (mgr);
762 :
763 1031 : bit_size_t bit_size;
764 1031 : if (get_bit_size (&bit_size))
765 : {
766 1013 : if (start.concrete_p ())
767 : {
768 825 : bit_offset_t next_bit_offset = start.get_bit_offset () + bit_size;
769 825 : return region_offset::make_concrete (start.get_base_region (),
770 : next_bit_offset);
771 : }
772 : }
773 :
774 206 : const svalue *start_byte_offset_sval = start.calc_symbolic_byte_offset (mgr);
775 206 : const svalue *byte_size_sval = get_byte_size_sval (mgr);
776 206 : const svalue *sum_sval
777 206 : = mgr->get_or_create_binop (size_type_node,
778 : PLUS_EXPR,
779 : start_byte_offset_sval,
780 : byte_size_sval);
781 206 : return region_offset::make_symbolic (start.get_base_region (),
782 206 : sum_sval);
783 : }
784 :
785 : /* Base class implementation of region::get_byte_size vfunc.
786 : If the size of this region (in bytes) is known statically, write it to *OUT
787 : and return true.
788 : Otherwise return false. */
789 :
790 : bool
791 6274 : region::get_byte_size (byte_size_t *out) const
792 : {
793 6274 : tree type = get_type ();
794 :
795 : /* Bail out e.g. for heap-allocated regions. */
796 6274 : if (!type)
797 : return false;
798 :
799 6118 : HOST_WIDE_INT bytes = int_size_in_bytes (type);
800 6118 : if (bytes == -1)
801 : return false;
802 6118 : *out = bytes;
803 6118 : return true;
804 : }
805 :
806 : /* Base implementation of region::get_byte_size_sval vfunc. */
807 :
808 : const svalue *
809 57600 : region::get_byte_size_sval (region_model_manager *mgr) const
810 : {
811 57600 : tree type = get_type ();
812 :
813 : /* Bail out e.g. for heap-allocated regions. */
814 57600 : if (!type)
815 15130 : return mgr->get_or_create_unknown_svalue (size_type_node);
816 :
817 42470 : HOST_WIDE_INT bytes = int_size_in_bytes (type);
818 42470 : if (bytes == -1)
819 525 : return mgr->get_or_create_unknown_svalue (size_type_node);
820 :
821 41945 : tree byte_size = size_in_bytes (type);
822 41945 : if (TREE_TYPE (byte_size) != size_type_node)
823 41945 : byte_size = fold_build1 (NOP_EXPR, size_type_node, byte_size);
824 41945 : return mgr->get_or_create_constant_svalue (byte_size);
825 : }
826 :
827 : /* Attempt to get the size of TYPE in bits.
828 : If successful, return true and write the size to *OUT.
829 : Otherwise return false. */
830 :
831 : bool
832 10096521 : int_size_in_bits (const_tree type, bit_size_t *out)
833 : {
834 10096521 : if (INTEGRAL_TYPE_P (type))
835 : {
836 4221135 : *out = TYPE_PRECISION (type);
837 4221135 : return true;
838 : }
839 :
840 5875386 : tree sz = TYPE_SIZE (type);
841 5875386 : if (sz
842 5858524 : && tree_fits_uhwi_p (sz)
843 : /* If the size is zero, then we may have a zero-sized
844 : array; handle such cases by returning false. */
845 11733708 : && !integer_zerop (sz))
846 : {
847 5856033 : *out = TREE_INT_CST_LOW (sz);
848 5856033 : return true;
849 : }
850 : else
851 19353 : return false;
852 : }
853 :
854 : /* Base implementation of region::get_bit_size_sval vfunc. */
855 :
856 : const svalue *
857 863765 : region::get_bit_size_sval (region_model_manager *mgr) const
858 : {
859 863765 : tree type = get_type ();
860 :
861 : /* Bail out e.g. for heap-allocated regions. */
862 863765 : if (!type)
863 8324 : return mgr->get_or_create_unknown_svalue (size_type_node);
864 :
865 855441 : bit_size_t bits;
866 855441 : if (!int_size_in_bits (type, &bits))
867 71 : return mgr->get_or_create_unknown_svalue (size_type_node);
868 :
869 855370 : return mgr->get_or_create_int_cst (size_type_node, bits);
870 : }
871 :
872 : /* If the size of this region (in bits) is known statically, write it to *OUT
873 : and return true.
874 : Otherwise return false. */
875 :
876 : bool
877 10882034 : region::get_bit_size (bit_size_t *out) const
878 : {
879 10882034 : tree type = get_type ();
880 :
881 : /* Bail out e.g. for heap-allocated regions. */
882 10882034 : if (!type)
883 : return false;
884 :
885 9237994 : return int_size_in_bits (type, out);
886 : }
887 :
888 : /* Get the field within RECORD_TYPE at BIT_OFFSET. */
889 :
890 : tree
891 2030 : get_field_at_bit_offset (tree record_type, bit_offset_t bit_offset)
892 : {
893 2030 : gcc_assert (TREE_CODE (record_type) == RECORD_TYPE);
894 2030 : if (bit_offset < 0)
895 : return nullptr;
896 :
897 : /* Find the first field that has an offset > BIT_OFFSET,
898 : then return the one preceding it.
899 : Skip other trees within the chain, such as FUNCTION_DECLs. */
900 2030 : tree last_field = NULL_TREE;
901 48545 : for (tree iter = TYPE_FIELDS (record_type); iter != NULL_TREE;
902 46515 : iter = DECL_CHAIN (iter))
903 : {
904 47326 : if (TREE_CODE (iter) == FIELD_DECL)
905 : {
906 4702 : int iter_field_offset = int_bit_position (iter);
907 4702 : if (bit_offset < iter_field_offset)
908 811 : return last_field;
909 3891 : last_field = iter;
910 : }
911 : }
912 : return last_field;
913 : }
914 :
915 : /* Populate *OUT with descendent regions of type TYPE that match
916 : RELATIVE_BIT_OFFSET and SIZE_IN_BITS within this region. */
917 :
918 : void
919 8980 : region::get_subregions_for_binding (region_model_manager *mgr,
920 : bit_offset_t relative_bit_offset,
921 : bit_size_t size_in_bits,
922 : tree type,
923 : auto_vec <const region *> *out) const
924 : {
925 8980 : if (get_type () == NULL_TREE || type == NULL_TREE)
926 : return;
927 8710 : if (relative_bit_offset == 0
928 8710 : && types_compatible_p (get_type (), type))
929 : {
930 7430 : out->safe_push (this);
931 7430 : return;
932 : }
933 1280 : switch (TREE_CODE (get_type ()))
934 : {
935 79 : case ARRAY_TYPE:
936 79 : {
937 79 : tree element_type = TREE_TYPE (get_type ());
938 79 : HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (element_type);
939 79 : if (hwi_byte_size > 0)
940 : {
941 79 : HOST_WIDE_INT bits_per_element
942 : = hwi_byte_size << LOG2_BITS_PER_UNIT;
943 79 : HOST_WIDE_INT element_index
944 79 : = (relative_bit_offset.to_shwi () / bits_per_element);
945 79 : tree element_index_cst
946 79 : = build_int_cst (integer_type_node, element_index);
947 79 : HOST_WIDE_INT inner_bit_offset
948 79 : = relative_bit_offset.to_shwi () % bits_per_element;
949 79 : const region *subregion = mgr->get_element_region
950 79 : (this, element_type,
951 : mgr->get_or_create_constant_svalue (element_index_cst));
952 79 : subregion->get_subregions_for_binding (mgr, inner_bit_offset,
953 : size_in_bits, type, out);
954 : }
955 : }
956 : break;
957 1076 : case RECORD_TYPE:
958 1076 : {
959 : /* The bit offset might be *within* one of the fields (such as
960 : with nested structs).
961 : So we want to find the enclosing field, adjust the offset,
962 : and repeat. */
963 1076 : if (tree field = get_field_at_bit_offset (get_type (),
964 : relative_bit_offset))
965 : {
966 1076 : int field_bit_offset = int_bit_position (field);
967 1076 : const region *subregion = mgr->get_field_region (this, field);
968 1076 : subregion->get_subregions_for_binding
969 1076 : (mgr, relative_bit_offset - field_bit_offset,
970 : size_in_bits, type, out);
971 : }
972 : }
973 : break;
974 4 : case UNION_TYPE:
975 4 : {
976 12 : for (tree field = TYPE_FIELDS (get_type ()); field != NULL_TREE;
977 8 : field = DECL_CHAIN (field))
978 : {
979 8 : if (TREE_CODE (field) != FIELD_DECL)
980 0 : continue;
981 8 : const region *subregion = mgr->get_field_region (this, field);
982 8 : subregion->get_subregions_for_binding (mgr,
983 : relative_bit_offset,
984 : size_in_bits,
985 : type,
986 : out);
987 : }
988 : }
989 : break;
990 : default:
991 : /* Do nothing. */
992 : break;
993 : }
994 : }
995 :
996 : /* Walk from this region up to the base region within its cluster, calculating
997 : the offset relative to the base region, either as an offset in bits,
998 : or a symbolic offset. */
999 :
1000 : region_offset
1001 150169 : region::calc_offset (region_model_manager *mgr) const
1002 : {
1003 150169 : const region *iter_region = this;
1004 150169 : bit_offset_t accum_bit_offset = 0;
1005 150169 : const svalue *accum_byte_sval = nullptr;
1006 :
1007 182241 : while (iter_region)
1008 : {
1009 182241 : switch (iter_region->get_kind ())
1010 : {
1011 22571 : case RK_FIELD:
1012 22571 : case RK_ELEMENT:
1013 22571 : case RK_OFFSET:
1014 22571 : case RK_BIT_RANGE:
1015 22571 : if (accum_byte_sval)
1016 : {
1017 3093 : const svalue *sval
1018 3093 : = iter_region->get_relative_symbolic_offset (mgr);
1019 3093 : accum_byte_sval
1020 3093 : = mgr->get_or_create_binop (ptrdiff_type_node, PLUS_EXPR,
1021 : accum_byte_sval, sval);
1022 3093 : iter_region = iter_region->get_parent_region ();
1023 : }
1024 : else
1025 : {
1026 19478 : bit_offset_t rel_bit_offset;
1027 19478 : if (iter_region->get_relative_concrete_offset (&rel_bit_offset))
1028 : {
1029 16858 : accum_bit_offset += rel_bit_offset;
1030 16858 : iter_region = iter_region->get_parent_region ();
1031 : }
1032 : else
1033 : {
1034 : /* If the iter_region is not concrete anymore, convert the
1035 : accumulated bits to a svalue in bytes and revisit the
1036 : iter_region collecting the symbolic value. */
1037 2620 : byte_offset_t byte_offset = accum_bit_offset / BITS_PER_UNIT;
1038 2620 : tree offset_tree = wide_int_to_tree (ptrdiff_type_node,
1039 2620 : byte_offset);
1040 2620 : accum_byte_sval
1041 2620 : = mgr->get_or_create_constant_svalue (offset_tree);
1042 : }
1043 : }
1044 22571 : continue;
1045 9501 : case RK_SIZED:
1046 9501 : case RK_CAST:
1047 9501 : iter_region = iter_region->get_parent_region ();
1048 9501 : continue;
1049 :
1050 150169 : default:
1051 150169 : return accum_byte_sval
1052 150169 : ? region_offset::make_symbolic (iter_region,
1053 : accum_byte_sval)
1054 147549 : : region_offset::make_concrete (iter_region,
1055 : accum_bit_offset);
1056 32072 : }
1057 : }
1058 :
1059 0 : return accum_byte_sval ? region_offset::make_symbolic (iter_region,
1060 : accum_byte_sval)
1061 0 : : region_offset::make_concrete (iter_region,
1062 : accum_bit_offset);
1063 : }
1064 :
1065 : /* Base implementation of region::get_relative_concrete_offset vfunc. */
1066 :
1067 : bool
1068 32 : region::get_relative_concrete_offset (bit_offset_t *) const
1069 : {
1070 32 : return false;
1071 : }
1072 :
1073 : /* Base implementation of region::get_relative_symbolic_offset vfunc. */
1074 :
1075 : const svalue *
1076 0 : region::get_relative_symbolic_offset (region_model_manager *mgr) const
1077 : {
1078 0 : return mgr->get_or_create_unknown_svalue (ptrdiff_type_node);
1079 : }
1080 :
1081 : /* Attempt to get the position and size of this region expressed as a
1082 : concrete range of bytes relative to its parent.
1083 : If successful, return true and write to *OUT.
1084 : Otherwise return false. */
1085 :
1086 : bool
1087 6376 : region::get_relative_concrete_byte_range (byte_range *out) const
1088 : {
1089 : /* We must have a concrete offset relative to the parent. */
1090 6376 : bit_offset_t rel_bit_offset;
1091 6376 : if (!get_relative_concrete_offset (&rel_bit_offset))
1092 : return false;
1093 : /* ...which must be a whole number of bytes. */
1094 6274 : if (rel_bit_offset % BITS_PER_UNIT != 0)
1095 : return false;
1096 6274 : byte_offset_t start_byte_offset = rel_bit_offset / BITS_PER_UNIT;
1097 :
1098 : /* We must have a concrete size, which must be a whole number
1099 : of bytes. */
1100 6274 : byte_size_t num_bytes;
1101 6274 : if (!get_byte_size (&num_bytes))
1102 : return false;
1103 :
1104 : /* Success. */
1105 6118 : *out = byte_range (start_byte_offset, num_bytes);
1106 6118 : return true;
1107 : }
1108 :
1109 : /* Dump a description of this region to stderr. */
1110 :
1111 : DEBUG_FUNCTION void
1112 0 : region::dump (bool simple) const
1113 : {
1114 0 : tree_dump_pretty_printer pp (stderr);
1115 0 : dump_to_pp (&pp, simple);
1116 0 : pp_newline (&pp);
1117 0 : }
1118 :
1119 : /* Dump a tree-like representation of this region and its constituent symbols
1120 : to stderr, using global_dc's colorization and theming options.
1121 :
1122 : For example:
1123 : . (gdb) call reg->dump()
1124 : . (26): ‘int’: decl_region(‘x_10(D)’)
1125 : . ╰─ parent: (9): frame_region(‘test_bitmask_2’, index: 0, depth: 1)
1126 : . ╰─ parent: (1): stack region
1127 : . ╰─ parent: (0): root region
1128 : */
1129 :
1130 : DEBUG_FUNCTION void
1131 0 : region::dump () const
1132 : {
1133 0 : text_art::dump (*this);
1134 0 : }
1135 :
1136 : /* Return a new json::string describing the region. */
1137 :
1138 : std::unique_ptr<json::value>
1139 16 : region::to_json () const
1140 : {
1141 16 : label_text desc = get_desc (true);
1142 16 : auto reg_js = std::make_unique<json::string> (desc.get ());
1143 16 : return reg_js;
1144 16 : }
1145 :
1146 : bool
1147 34 : region::maybe_print_for_user (pretty_printer *pp,
1148 : const region_model &) const
1149 : {
1150 34 : switch (get_kind ())
1151 : {
1152 : default:
1153 : break;
1154 34 : case RK_DECL:
1155 34 : {
1156 34 : const decl_region *reg = (const decl_region *)this;
1157 34 : tree decl = reg->get_decl ();
1158 34 : if (TREE_CODE (decl) == SSA_NAME)
1159 34 : decl = SSA_NAME_VAR (decl);
1160 34 : print_expr_for_user (pp, decl);
1161 34 : return true;
1162 : }
1163 : }
1164 :
1165 : return false;
1166 : }
1167 :
1168 : /* Use DWI to create a text_art::widget describing this region in
1169 : a tree-like form, using PREFIX as a prefix (e.g. for field names). */
1170 :
1171 : std::unique_ptr<text_art::tree_widget>
1172 0 : region::make_dump_widget (const text_art::dump_widget_info &dwi,
1173 : const char *prefix) const
1174 : {
1175 0 : pretty_printer pp;
1176 0 : pp_format_decoder (&pp) = default_tree_printer;
1177 0 : pp_show_color (&pp) = true;
1178 :
1179 0 : if (prefix)
1180 0 : pp_printf (&pp, "%s: ", prefix);
1181 :
1182 0 : pp_printf (&pp, "(%i): ", get_id ());
1183 0 : if (get_type ())
1184 0 : pp_printf (&pp, "%qT: ", get_type ());
1185 :
1186 0 : print_dump_widget_label (&pp);
1187 :
1188 0 : std::unique_ptr<text_art::tree_widget> w
1189 0 : (text_art::tree_widget::make (dwi, &pp));
1190 :
1191 0 : add_dump_widget_children (*w, dwi);
1192 :
1193 0 : if (m_parent)
1194 0 : w->add_child (m_parent->make_dump_widget (dwi, "parent"));
1195 :
1196 0 : return w;
1197 0 : }
1198 :
1199 : void
1200 0 : region::add_dump_widget_children (text_art::tree_widget &,
1201 : const text_art::dump_widget_info &) const
1202 : {
1203 : /* By default, add nothing (parent is added in make_dump_widget). */
1204 0 : }
1205 :
1206 : /* Generate a description of this region. */
1207 :
1208 : DEBUG_FUNCTION label_text
1209 16 : region::get_desc (bool simple) const
1210 : {
1211 16 : pretty_printer pp;
1212 16 : pp_format_decoder (&pp) = default_tree_printer;
1213 16 : dump_to_pp (&pp, simple);
1214 16 : return label_text::take (xstrdup (pp_formatted_text (&pp)));
1215 16 : }
1216 :
1217 : /* Base implementation of region::accept vfunc.
1218 : Subclass implementations should chain up to this. */
1219 :
1220 : void
1221 51012488 : region::accept (visitor *v) const
1222 : {
1223 51012488 : v->visit_region (this);
1224 51012488 : if (m_parent)
1225 38696354 : m_parent->accept (v);
1226 51012488 : }
1227 :
1228 : /* Return true if this is a symbolic region for deferencing an
1229 : unknown ptr.
1230 : We shouldn't attempt to bind values for this region (but
1231 : can unbind values for other regions). */
1232 :
1233 : bool
1234 5327713 : region::symbolic_for_unknown_ptr_p () const
1235 : {
1236 5327713 : if (const symbolic_region *sym_reg = dyn_cast_symbolic_region ())
1237 628779 : if (sym_reg->get_pointer ()->get_kind () == SK_UNKNOWN)
1238 : return true;
1239 : return false;
1240 : }
1241 :
1242 : /* Return true if this is a symbolic region. */
1243 :
1244 : bool
1245 869644 : region::symbolic_p () const
1246 : {
1247 869644 : return get_kind () == RK_SYMBOLIC;
1248 : }
1249 :
1250 : /* Return true if this region is known to be zero bits in size. */
1251 :
1252 : bool
1253 7179892 : region::empty_p () const
1254 : {
1255 7179892 : bit_size_t num_bits;
1256 7179892 : if (get_bit_size (&num_bits))
1257 6852117 : if (num_bits == 0)
1258 : return true;
1259 : return false;
1260 : }
1261 :
1262 : /* Return true if this is a region for a decl with name DECL_NAME.
1263 : Intended for use when debugging (for assertions and conditional
1264 : breakpoints). */
1265 :
1266 : DEBUG_FUNCTION bool
1267 0 : region::is_named_decl_p (const char *decl_name) const
1268 : {
1269 0 : if (tree decl = maybe_get_decl ())
1270 0 : if (DECL_NAME (decl)
1271 0 : && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), decl_name))
1272 0 : return true;
1273 : return false;
1274 : }
1275 :
1276 : /* region's ctor. */
1277 :
1278 219192 : region::region (complexity c, symbol::id_t id, const region *parent, tree type)
1279 : : symbol (c, id),
1280 219192 : m_parent (parent), m_type (type),
1281 219192 : m_cached_offset (nullptr), m_cached_init_sval_at_main (nullptr)
1282 : {
1283 219192 : gcc_assert (type == NULL_TREE || TYPE_P (type));
1284 219192 : }
1285 :
1286 : /* Comparator for use by vec<const region *>::qsort,
1287 : using their IDs to order them. */
1288 :
1289 : int
1290 63081421 : region::cmp_ptr_ptr (const void *p1, const void *p2)
1291 : {
1292 63081421 : const region * const *reg1 = (const region * const *)p1;
1293 63081421 : const region * const *reg2 = (const region * const *)p2;
1294 :
1295 63081421 : return cmp_ids (*reg1, *reg2);
1296 : }
1297 :
1298 : /* Determine if a pointer to this region must be non-NULL.
1299 :
1300 : Generally, pointers to regions must be non-NULL, but pointers
1301 : to symbolic_regions might, in fact, be NULL.
1302 :
1303 : This allows us to simulate functions like malloc and calloc with:
1304 : - only one "outcome" from each statement,
1305 : - the idea that the pointer is on the heap if non-NULL
1306 : - the possibility that the pointer could be NULL
1307 : - the idea that successive values returned from malloc are non-equal
1308 : - to be able to zero-fill for calloc. */
1309 :
1310 : bool
1311 21257 : region::non_null_p () const
1312 : {
1313 21257 : switch (get_kind ())
1314 : {
1315 : default:
1316 : return true;
1317 : case RK_SYMBOLIC:
1318 : /* Are we within a symbolic_region? If so, it could be NULL, and we
1319 : have to fall back on the constraints. */
1320 : return false;
1321 : case RK_HEAP_ALLOCATED:
1322 : return false;
1323 : }
1324 : }
1325 :
1326 : /* Return true iff this region is defined in terms of SVAL. */
1327 :
1328 : bool
1329 461855 : region::involves_p (const svalue *sval) const
1330 : {
1331 461855 : if (const symbolic_region *symbolic_reg = dyn_cast_symbolic_region ())
1332 : {
1333 58474 : if (symbolic_reg->get_pointer ()->involves_p (sval))
1334 : return true;
1335 : }
1336 :
1337 : return false;
1338 : }
1339 :
1340 : /* Comparator for trees to impose a deterministic ordering on
1341 : T1 and T2. */
1342 :
1343 : static int
1344 73560 : tree_cmp (const_tree t1, const_tree t2)
1345 : {
1346 73560 : gcc_assert (t1);
1347 73560 : gcc_assert (t2);
1348 :
1349 : /* Test tree codes first. */
1350 73560 : if (TREE_CODE (t1) != TREE_CODE (t2))
1351 31744 : return TREE_CODE (t1) - TREE_CODE (t2);
1352 :
1353 : /* From this point on, we know T1 and T2 have the same tree code. */
1354 :
1355 41816 : if (DECL_P (t1))
1356 : {
1357 0 : if (DECL_NAME (t1) && DECL_NAME (t2))
1358 0 : return strcmp (IDENTIFIER_POINTER (DECL_NAME (t1)),
1359 0 : IDENTIFIER_POINTER (DECL_NAME (t2)));
1360 : else
1361 : {
1362 0 : if (DECL_NAME (t1))
1363 : return -1;
1364 0 : else if (DECL_NAME (t2))
1365 : return 1;
1366 : else
1367 0 : return DECL_UID (t1) - DECL_UID (t2);
1368 : }
1369 : }
1370 :
1371 41816 : switch (TREE_CODE (t1))
1372 : {
1373 0 : case SSA_NAME:
1374 0 : {
1375 0 : if (SSA_NAME_VAR (t1) && SSA_NAME_VAR (t2))
1376 : {
1377 0 : int var_cmp = tree_cmp (SSA_NAME_VAR (t1), SSA_NAME_VAR (t2));
1378 0 : if (var_cmp)
1379 : return var_cmp;
1380 0 : return SSA_NAME_VERSION (t1) - SSA_NAME_VERSION (t2);
1381 : }
1382 : else
1383 : {
1384 0 : if (SSA_NAME_VAR (t1))
1385 : return -1;
1386 0 : else if (SSA_NAME_VAR (t2))
1387 : return 1;
1388 : else
1389 0 : return SSA_NAME_VERSION (t1) - SSA_NAME_VERSION (t2);
1390 : }
1391 : }
1392 8384 : break;
1393 :
1394 8384 : case INTEGER_CST:
1395 8384 : return tree_int_cst_compare (t1, t2);
1396 :
1397 33432 : case REAL_CST:
1398 33432 : {
1399 33432 : const real_value *rv1 = TREE_REAL_CST_PTR (t1);
1400 33432 : const real_value *rv2 = TREE_REAL_CST_PTR (t2);
1401 33432 : if (real_compare (UNORDERED_EXPR, rv1, rv2))
1402 : {
1403 : /* Impose an arbitrary order on NaNs relative to other NaNs
1404 : and to non-NaNs. */
1405 25040 : if (int cmp_isnan = real_isnan (rv1) - real_isnan (rv2))
1406 : return cmp_isnan;
1407 16800 : if (int cmp_issignaling_nan
1408 8400 : = real_issignaling_nan (rv1) - real_issignaling_nan (rv2))
1409 : return cmp_issignaling_nan;
1410 4016 : return real_isneg (rv1) - real_isneg (rv2);
1411 : }
1412 8392 : if (real_compare (LT_EXPR, rv1, rv2))
1413 : return -1;
1414 5008 : if (real_compare (GT_EXPR, rv1, rv2))
1415 : return 1;
1416 : return 0;
1417 : }
1418 :
1419 0 : case STRING_CST:
1420 0 : return strcmp (TREE_STRING_POINTER (t1),
1421 0 : TREE_STRING_POINTER (t2));
1422 :
1423 0 : default:
1424 0 : gcc_unreachable ();
1425 : break;
1426 : }
1427 :
1428 : gcc_unreachable ();
1429 :
1430 : return 0;
1431 : }
1432 :
1433 : /* qsort comparator for trees to impose a deterministic ordering on
1434 : P1 and P2. */
1435 :
1436 : int
1437 73560 : tree_cmp (const void *p1, const void *p2)
1438 : {
1439 73560 : const_tree t1 = *(const_tree const *)p1;
1440 73560 : const_tree t2 = *(const_tree const *)p2;
1441 :
1442 73560 : return tree_cmp (t1, t2);
1443 : }
1444 :
1445 : /* class frame_region : public space_region. */
1446 :
1447 33012 : frame_region::~frame_region ()
1448 : {
1449 126794 : for (map_t::iterator iter = m_locals.begin ();
1450 126794 : iter != m_locals.end ();
1451 110288 : ++iter)
1452 110288 : delete (*iter).second;
1453 33012 : }
1454 :
1455 : void
1456 10057041 : frame_region::accept (visitor *v) const
1457 : {
1458 10612222 : region::accept (v);
1459 10612222 : if (m_calling_frame)
1460 : m_calling_frame->accept (v);
1461 10057041 : }
1462 :
1463 : /* Implementation of region::dump_to_pp vfunc for frame_region. */
1464 :
1465 : void
1466 4290 : frame_region::dump_to_pp (pretty_printer *pp, bool simple) const
1467 : {
1468 4290 : if (simple)
1469 4264 : pp_printf (pp, "frame: %qs@%i", function_name (&m_fun), get_stack_depth ());
1470 : else
1471 26 : pp_printf (pp, "frame_region(%qs, index: %i, depth: %i)",
1472 26 : function_name (&m_fun), m_index, get_stack_depth ());
1473 4290 : }
1474 :
1475 : void
1476 0 : frame_region::print_dump_widget_label (pretty_printer *pp) const
1477 : {
1478 0 : pp_printf (pp, "frame_region(%qs, index: %i, depth: %i)",
1479 0 : function_name (&m_fun), m_index, get_stack_depth ());
1480 0 : }
1481 :
1482 : const decl_region *
1483 1505286 : frame_region::get_region_for_local (region_model_manager *mgr,
1484 : tree expr,
1485 : const region_model_context *ctxt) const
1486 : {
1487 1505286 : if (CHECKING_P)
1488 : {
1489 : /* Verify that EXPR is a local or SSA name, and that it's for the
1490 : correct function for this stack frame. */
1491 1505286 : gcc_assert (TREE_CODE (expr) == PARM_DECL
1492 : || TREE_CODE (expr) == VAR_DECL
1493 : || TREE_CODE (expr) == SSA_NAME
1494 : || TREE_CODE (expr) == RESULT_DECL);
1495 1505286 : switch (TREE_CODE (expr))
1496 : {
1497 0 : default:
1498 0 : gcc_unreachable ();
1499 111646 : case VAR_DECL:
1500 111646 : gcc_assert (!is_global_var (expr));
1501 : /* Fall through. */
1502 145769 : case PARM_DECL:
1503 145769 : case RESULT_DECL:
1504 145769 : gcc_assert (DECL_CONTEXT (expr) == m_fun.decl);
1505 : break;
1506 1359517 : case SSA_NAME:
1507 1359517 : {
1508 1359517 : if (tree var = SSA_NAME_VAR (expr))
1509 : {
1510 650020 : if (DECL_P (var))
1511 650020 : gcc_assert (DECL_CONTEXT (var) == m_fun.decl);
1512 : }
1513 709497 : else if (ctxt)
1514 434269 : if (const extrinsic_state *ext_state = ctxt->get_ext_state ())
1515 370217 : if (const supergraph *sg
1516 370217 : = ext_state->get_engine ()->get_supergraph ())
1517 : {
1518 370217 : const gimple *def_stmt = SSA_NAME_DEF_STMT (expr);
1519 370217 : if (gimple_code (def_stmt) != GIMPLE_PHI)
1520 : {
1521 363734 : const supernode *snode
1522 363734 : = sg->get_supernode_for_stmt (def_stmt);
1523 363734 : gcc_assert (snode->get_function () == &m_fun);
1524 : }
1525 : }
1526 : }
1527 : break;
1528 : }
1529 : }
1530 :
1531 : /* Ideally we'd use mutable here. */
1532 1505286 : map_t &mutable_locals = const_cast <map_t &> (m_locals);
1533 :
1534 1505286 : if (decl_region **slot = mutable_locals.get (expr))
1535 1394998 : return *slot;
1536 110288 : decl_region *reg
1537 110288 : = new decl_region (mgr->alloc_symbol_id (), this, expr);
1538 110288 : mutable_locals.put (expr, reg);
1539 110288 : return reg;
1540 : }
1541 :
1542 : /* class globals_region : public space_region. */
1543 :
1544 : /* Implementation of region::dump_to_pp vfunc for globals_region. */
1545 :
1546 : void
1547 2347 : globals_region::dump_to_pp (pretty_printer *pp, bool simple) const
1548 : {
1549 2347 : if (simple)
1550 1278 : pp_string (pp, "::");
1551 : else
1552 1069 : pp_string (pp, "globals");
1553 2347 : }
1554 :
1555 : void
1556 0 : globals_region::print_dump_widget_label (pretty_printer *pp) const
1557 : {
1558 0 : pp_string (pp, "globals");
1559 0 : }
1560 :
1561 : /* class code_region : public map_region. */
1562 :
1563 : /* Implementation of region::dump_to_pp vfunc for code_region. */
1564 :
1565 : void
1566 0 : code_region::dump_to_pp (pretty_printer *pp, bool simple) const
1567 : {
1568 0 : if (simple)
1569 0 : pp_string (pp, "code region");
1570 : else
1571 0 : pp_string (pp, "code_region()");
1572 0 : }
1573 :
1574 : void
1575 0 : code_region::print_dump_widget_label (pretty_printer *pp) const
1576 : {
1577 0 : pp_string (pp, "code region");
1578 0 : }
1579 :
1580 : /* class function_region : public region. */
1581 :
1582 : /* Implementation of region::dump_to_pp vfunc for function_region. */
1583 :
1584 : void
1585 413 : function_region::dump_to_pp (pretty_printer *pp, bool simple) const
1586 : {
1587 413 : if (simple)
1588 : {
1589 413 : dump_quoted_tree (pp, m_fndecl);
1590 : }
1591 : else
1592 : {
1593 0 : pp_string (pp, "function_region(");
1594 0 : dump_quoted_tree (pp, m_fndecl);
1595 0 : pp_string (pp, ")");
1596 : }
1597 413 : }
1598 :
1599 : void
1600 0 : function_region::print_dump_widget_label (pretty_printer *pp) const
1601 : {
1602 0 : pp_string (pp, "function_region(");
1603 0 : dump_quoted_tree (pp, m_fndecl);
1604 0 : pp_string (pp, ")");
1605 0 : }
1606 :
1607 : /* class label_region : public region. */
1608 :
1609 : /* Implementation of region::dump_to_pp vfunc for label_region. */
1610 :
1611 : void
1612 0 : label_region::dump_to_pp (pretty_printer *pp, bool simple) const
1613 : {
1614 0 : if (simple)
1615 : {
1616 0 : dump_quoted_tree (pp, m_label);
1617 : }
1618 : else
1619 : {
1620 0 : pp_string (pp, "label_region(");
1621 0 : dump_quoted_tree (pp, m_label);
1622 0 : pp_string (pp, ")");
1623 : }
1624 0 : }
1625 :
1626 : void
1627 0 : label_region::print_dump_widget_label (pretty_printer *pp) const
1628 : {
1629 0 : pp_string (pp, "label_region(");
1630 0 : dump_quoted_tree (pp, m_label);
1631 0 : pp_string (pp, ")");
1632 0 : }
1633 :
1634 : /* class stack_region : public region. */
1635 :
1636 : /* Implementation of region::dump_to_pp vfunc for stack_region. */
1637 :
1638 : void
1639 0 : stack_region::dump_to_pp (pretty_printer *pp, bool simple) const
1640 : {
1641 0 : if (simple)
1642 0 : pp_string (pp, "stack region");
1643 : else
1644 0 : pp_string (pp, "stack_region()");
1645 0 : }
1646 :
1647 : void
1648 0 : stack_region::print_dump_widget_label (pretty_printer *pp) const
1649 : {
1650 0 : pp_string (pp, "stack region");
1651 0 : }
1652 :
1653 : /* class heap_region : public region. */
1654 :
1655 : /* Implementation of region::dump_to_pp vfunc for heap_region. */
1656 :
1657 : void
1658 190 : heap_region::dump_to_pp (pretty_printer *pp, bool simple) const
1659 : {
1660 190 : if (simple)
1661 190 : pp_string (pp, "heap region");
1662 : else
1663 0 : pp_string (pp, "heap_region()");
1664 190 : }
1665 :
1666 : void
1667 0 : heap_region::print_dump_widget_label (pretty_printer *pp) const
1668 : {
1669 0 : pp_string (pp, "heap_region");
1670 0 : }
1671 :
1672 : /* class root_region : public region. */
1673 :
1674 : /* root_region's ctor. */
1675 :
1676 4034 : root_region::root_region (symbol::id_t id)
1677 4034 : : region (complexity (1, 1), id, nullptr, NULL_TREE)
1678 : {
1679 4034 : }
1680 :
1681 : /* Implementation of region::dump_to_pp vfunc for root_region. */
1682 :
1683 : void
1684 1478 : root_region::dump_to_pp (pretty_printer *pp, bool simple) const
1685 : {
1686 1478 : if (simple)
1687 1370 : pp_string (pp, "root region");
1688 : else
1689 108 : pp_string (pp, "root_region()");
1690 1478 : }
1691 :
1692 : void
1693 0 : root_region::print_dump_widget_label (pretty_printer *pp) const
1694 : {
1695 0 : pp_string (pp, "root region");
1696 0 : }
1697 :
1698 : /* class thread_local_region : public space_region. */
1699 :
1700 : void
1701 0 : thread_local_region::dump_to_pp (pretty_printer *pp, bool simple) const
1702 : {
1703 0 : if (simple)
1704 0 : pp_string (pp, "thread_local_region");
1705 : else
1706 0 : pp_string (pp, "thread_local_region()");
1707 0 : }
1708 :
1709 : void
1710 0 : thread_local_region::print_dump_widget_label (pretty_printer *pp) const
1711 : {
1712 0 : pp_string (pp, "thread_local_region");
1713 0 : }
1714 :
1715 : /* class symbolic_region : public map_region. */
1716 :
1717 : /* symbolic_region's ctor. */
1718 :
1719 8908 : symbolic_region::symbolic_region (symbol::id_t id, region *parent,
1720 8908 : const svalue *sval_ptr)
1721 8908 : : region (complexity::from_pair (parent, sval_ptr), id, parent,
1722 8908 : (sval_ptr->get_type ()
1723 8825 : ? TREE_TYPE (sval_ptr->get_type ())
1724 : : NULL_TREE)),
1725 26641 : m_sval_ptr (sval_ptr)
1726 : {
1727 8908 : }
1728 :
1729 : /* Implementation of region::accept vfunc for symbolic_region. */
1730 :
1731 : void
1732 549642 : symbolic_region::accept (visitor *v) const
1733 : {
1734 549642 : region::accept (v);
1735 549642 : m_sval_ptr->accept (v);
1736 549642 : }
1737 :
1738 : /* Implementation of region::dump_to_pp vfunc for symbolic_region. */
1739 :
1740 : void
1741 7089 : symbolic_region::dump_to_pp (pretty_printer *pp, bool simple) const
1742 : {
1743 7089 : if (simple)
1744 : {
1745 6981 : pp_string (pp, "(*");
1746 6981 : m_sval_ptr->dump_to_pp (pp, simple);
1747 6981 : pp_string (pp, ")");
1748 : }
1749 : else
1750 : {
1751 108 : pp_string (pp, "symbolic_region(");
1752 108 : get_parent_region ()->dump_to_pp (pp, simple);
1753 108 : if (get_type ())
1754 : {
1755 108 : pp_string (pp, ", ");
1756 108 : print_quoted_type (pp, get_type ());
1757 : }
1758 108 : pp_string (pp, ", ");
1759 108 : m_sval_ptr->dump_to_pp (pp, simple);
1760 108 : pp_string (pp, ")");
1761 : }
1762 7089 : }
1763 :
1764 : void
1765 0 : symbolic_region::print_dump_widget_label (pretty_printer *pp) const
1766 : {
1767 0 : pp_string (pp, "symbolic_region: %<*%>");
1768 0 : }
1769 :
1770 : void
1771 0 : symbolic_region::
1772 : add_dump_widget_children (text_art::tree_widget &w,
1773 : const text_art::dump_widget_info &dwi) const
1774 : {
1775 0 : w.add_child (m_sval_ptr->make_dump_widget (dwi, "m_sval_ptr"));
1776 0 : }
1777 :
1778 : /* class decl_region : public region. */
1779 :
1780 : /* Implementation of region::dump_to_pp vfunc for decl_region. */
1781 :
1782 : void
1783 26249 : decl_region::dump_to_pp (pretty_printer *pp, bool simple) const
1784 : {
1785 26249 : if (simple)
1786 25154 : pp_printf (pp, "%E", m_decl);
1787 : else
1788 : {
1789 1095 : pp_string (pp, "decl_region(");
1790 1095 : get_parent_region ()->dump_to_pp (pp, simple);
1791 1095 : pp_string (pp, ", ");
1792 1095 : print_quoted_type (pp, get_type ());
1793 1095 : pp_printf (pp, ", %qE)", m_decl);
1794 : }
1795 26249 : }
1796 :
1797 : void
1798 0 : decl_region::print_dump_widget_label (pretty_printer *pp) const
1799 : {
1800 0 : pp_printf (pp, "decl_region(%qE)", m_decl);
1801 0 : }
1802 :
1803 : /* Get the stack depth for the frame containing this decl, or 0
1804 : for a global. */
1805 :
1806 : int
1807 10195 : decl_region::get_stack_depth () const
1808 : {
1809 10195 : if (get_parent_region () == nullptr)
1810 : return 0;
1811 20390 : if (const frame_region *frame_reg
1812 10195 : = get_parent_region ()->dyn_cast_frame_region ())
1813 9705 : return frame_reg->get_stack_depth ();
1814 : return 0;
1815 : }
1816 :
1817 : /* If the underlying decl is in the global constant pool,
1818 : return an svalue representing the constant value.
1819 : Otherwise return nullptr. */
1820 :
1821 : const svalue *
1822 3568554 : decl_region::maybe_get_constant_value (region_model_manager *mgr) const
1823 : {
1824 3568554 : if (VAR_P (m_decl)
1825 319423 : && DECL_IN_CONSTANT_POOL (m_decl)
1826 16 : && DECL_INITIAL (m_decl)
1827 3568570 : && TREE_CODE (DECL_INITIAL (m_decl)) == CONSTRUCTOR)
1828 16 : return get_svalue_for_constructor (DECL_INITIAL (m_decl), mgr);
1829 : return nullptr;
1830 : }
1831 :
1832 : /* Implementation of decl_region::get_svalue_for_constructor
1833 : for when the cached value hasn't yet been calculated. */
1834 :
1835 : const svalue *
1836 122 : decl_region::calc_svalue_for_constructor (tree ctor,
1837 : region_model_manager *mgr) const
1838 : {
1839 : /* Create a concrete_binding_map, applying ctor to it, using this
1840 : decl_region as the base region when building child regions
1841 : for offset calculations. */
1842 122 : concrete_binding_map map;
1843 122 : if (!map.apply_ctor_to_region (this, ctor, mgr))
1844 1 : return mgr->get_or_create_unknown_svalue (get_type ());
1845 :
1846 : /* Return a compound svalue for the map we built. */
1847 121 : return mgr->get_or_create_compound_svalue (get_type (), std::move (map));
1848 122 : }
1849 :
1850 : /* Get an svalue for CTOR, a CONSTRUCTOR for this region's decl. */
1851 :
1852 : const svalue *
1853 218 : decl_region::get_svalue_for_constructor (tree ctor,
1854 : region_model_manager *mgr) const
1855 : {
1856 218 : gcc_assert (!TREE_CLOBBER_P (ctor));
1857 218 : gcc_assert (ctor == DECL_INITIAL (m_decl));
1858 :
1859 218 : if (!m_ctor_svalue)
1860 122 : m_ctor_svalue = calc_svalue_for_constructor (ctor, mgr);
1861 :
1862 218 : return m_ctor_svalue;
1863 : }
1864 :
1865 : /* For use on decl_regions for global variables.
1866 :
1867 : Get an svalue for the initial value of this region at entry to
1868 : "main" (either based on DECL_INITIAL, or implicit initialization to
1869 : zero.
1870 :
1871 : Return nullptr if there is a problem. */
1872 :
1873 : const svalue *
1874 421 : decl_region::get_svalue_for_initializer (region_model_manager *mgr) const
1875 : {
1876 421 : tree init = DECL_INITIAL (m_decl);
1877 421 : if (!init)
1878 : {
1879 : /* If we have an "extern" decl then there may be an initializer in
1880 : another TU. */
1881 146 : if (DECL_EXTERNAL (m_decl))
1882 : return nullptr;
1883 :
1884 33 : if (empty_p ())
1885 : return nullptr;
1886 :
1887 : /* Implicit initialization to zero; use a compound_svalue for it.
1888 : Doing so requires that we have a concrete binding for this region,
1889 : which can fail if we have a region with unknown size
1890 : (e.g. "extern const char arr[];"). */
1891 33 : const binding_key *binding
1892 33 : = binding_key::make (mgr->get_store_manager (), this);
1893 33 : if (binding->symbolic_p ())
1894 : return nullptr;
1895 :
1896 : /* If we don't care about tracking the content of this region, then
1897 : it's unused, and the value doesn't matter. */
1898 33 : if (!tracked_p ())
1899 : return nullptr;
1900 :
1901 33 : binding_cluster c (*mgr->get_store_manager (), this);
1902 33 : c.zero_fill_region (mgr->get_store_manager (), this);
1903 33 : return mgr->get_or_create_compound_svalue (TREE_TYPE (m_decl),
1904 33 : c.get_map ().get_concrete_bindings ());
1905 33 : }
1906 :
1907 : /* LTO can write out error_mark_node as the DECL_INITIAL for simple scalar
1908 : values (to avoid writing out an extra section). */
1909 275 : if (init == error_mark_node)
1910 : return nullptr;
1911 :
1912 271 : if (TREE_CODE (init) == CONSTRUCTOR)
1913 202 : return get_svalue_for_constructor (init, mgr);
1914 :
1915 : /* Reuse the get_rvalue logic from region_model. */
1916 69 : region_model m (mgr);
1917 69 : return m.get_rvalue (path_var (init, 0), nullptr);
1918 69 : }
1919 :
1920 : /* Subroutine of symnode_requires_tracking_p; return true if REF
1921 : might imply that we should be tracking the value of its decl. */
1922 :
1923 : static bool
1924 4172 : ipa_ref_requires_tracking (ipa_ref *ref)
1925 : {
1926 : /* If we have a load/store/alias of the symbol, then we'll track
1927 : the decl's value. */
1928 4172 : if (ref->use != IPA_REF_ADDR)
1929 : return true;
1930 :
1931 4141 : if (ref->stmt == nullptr)
1932 : return true;
1933 :
1934 4141 : switch (ref->stmt->code)
1935 : {
1936 : default:
1937 : return true;
1938 4109 : case GIMPLE_CALL:
1939 4109 : {
1940 4157 : cgraph_node *caller_cnode = dyn_cast <cgraph_node *> (ref->referring);
1941 4109 : if (caller_cnode == nullptr)
1942 : return true;
1943 4109 : cgraph_edge *edge = caller_cnode->get_edge (ref->stmt);
1944 4109 : if (!edge)
1945 : return true;
1946 4109 : if (edge->callee == nullptr)
1947 : return true; /* e.g. call through function ptr. */
1948 4108 : if (edge->callee->definition)
1949 : return true;
1950 : /* If we get here, then this ref is a pointer passed to
1951 : a function we don't have the definition for. */
1952 : return false;
1953 : }
1954 17 : break;
1955 17 : case GIMPLE_ASM:
1956 17 : {
1957 17 : const gasm *asm_stmt = as_a <const gasm *> (ref->stmt);
1958 17 : if (gimple_asm_noutputs (asm_stmt) > 0)
1959 : return true;
1960 17 : if (gimple_asm_nclobbers (asm_stmt) > 0)
1961 : return true;
1962 : /* If we get here, then this ref is the decl being passed
1963 : by pointer to asm with no outputs. */
1964 : return false;
1965 : }
1966 : break;
1967 : }
1968 : }
1969 :
1970 : /* Determine if the decl for SYMNODE should have binding_clusters
1971 : in our state objects; return false to optimize away tracking
1972 : certain decls in our state objects, as an optimization. */
1973 :
1974 : static bool
1975 5506 : symnode_requires_tracking_p (symtab_node *symnode)
1976 : {
1977 5506 : gcc_assert (symnode);
1978 5506 : if (symnode->externally_visible)
1979 : return true;
1980 4729 : tree context_fndecl = DECL_CONTEXT (symnode->decl);
1981 4729 : if (context_fndecl == nullptr)
1982 : return true;
1983 4715 : if (TREE_CODE (context_fndecl) != FUNCTION_DECL)
1984 : return true;
1985 16511 : for (auto ref : symnode->ref_list.referring)
1986 4172 : if (ipa_ref_requires_tracking (ref))
1987 : return true;
1988 :
1989 : /* If we get here, then we don't have uses of this decl that require
1990 : tracking; we never read from it or write to it explicitly. */
1991 : return false;
1992 : }
1993 :
1994 : /* Subroutine of decl_region ctor: determine whether this decl_region
1995 : can have binding_clusters; return false to optimize away tracking
1996 : of certain decls in our state objects, as an optimization. */
1997 :
1998 : bool
1999 116686 : decl_region::calc_tracked_p (tree decl)
2000 : {
2001 : /* Precondition of symtab_node::get. */
2002 116686 : if (TREE_CODE (decl) == VAR_DECL
2003 116686 : && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p))
2004 6400 : if (symtab_node *symnode = symtab_node::get (decl))
2005 5506 : return symnode_requires_tracking_p (symnode);
2006 : return true;
2007 : }
2008 :
2009 : /* class field_region : public region. */
2010 :
2011 : /* Implementation of region::dump_to_pp vfunc for field_region. */
2012 :
2013 : void
2014 1941 : field_region::dump_to_pp (pretty_printer *pp, bool simple) const
2015 : {
2016 1941 : if (simple)
2017 : {
2018 1941 : get_parent_region ()->dump_to_pp (pp, simple);
2019 1941 : pp_string (pp, ".");
2020 1941 : pp_printf (pp, "%E", m_field);
2021 : }
2022 : else
2023 : {
2024 0 : pp_string (pp, "field_region(");
2025 0 : get_parent_region ()->dump_to_pp (pp, simple);
2026 0 : pp_string (pp, ", ");
2027 0 : print_quoted_type (pp, get_type ());
2028 0 : pp_printf (pp, ", %qE)", m_field);
2029 : }
2030 1941 : }
2031 :
2032 : void
2033 0 : field_region::print_dump_widget_label (pretty_printer *pp) const
2034 : {
2035 0 : pp_printf (pp, "field_region(%qE)", m_field);
2036 0 : }
2037 :
2038 : /* Implementation of region::get_relative_concrete_offset vfunc
2039 : for field_region. */
2040 :
2041 : bool
2042 11407 : field_region::get_relative_concrete_offset (bit_offset_t *out) const
2043 : {
2044 : /* Compare with e.g. gimple-fold.cc's
2045 : fold_nonarray_ctor_reference. */
2046 11407 : tree byte_offset = DECL_FIELD_OFFSET (m_field);
2047 11407 : if (TREE_CODE (byte_offset) != INTEGER_CST)
2048 : return false;
2049 11405 : tree field_offset = DECL_FIELD_BIT_OFFSET (m_field);
2050 : /* Compute bit offset of the field. */
2051 11405 : offset_int bitoffset
2052 11405 : = (wi::to_offset (field_offset)
2053 11405 : + (wi::to_offset (byte_offset) << LOG2_BITS_PER_UNIT));
2054 11405 : *out = bitoffset;
2055 11405 : return true;
2056 : }
2057 :
2058 :
2059 : /* Implementation of region::get_relative_symbolic_offset vfunc
2060 : for field_region.
2061 : If known, the returned svalue is equal to the offset converted to bytes and
2062 : rounded off. */
2063 :
2064 : const svalue *
2065 372 : field_region::get_relative_symbolic_offset (region_model_manager *mgr) const
2066 : {
2067 372 : bit_offset_t out;
2068 372 : if (get_relative_concrete_offset (&out))
2069 : {
2070 371 : tree cst_tree
2071 371 : = wide_int_to_tree (ptrdiff_type_node, out / BITS_PER_UNIT);
2072 371 : return mgr->get_or_create_constant_svalue (cst_tree);
2073 : }
2074 1 : return mgr->get_or_create_unknown_svalue (ptrdiff_type_node);
2075 : }
2076 :
2077 : /* class element_region : public region. */
2078 :
2079 : /* Implementation of region::accept vfunc for element_region. */
2080 :
2081 : void
2082 3939245 : element_region::accept (visitor *v) const
2083 : {
2084 3939245 : region::accept (v);
2085 3939245 : m_index->accept (v);
2086 3939245 : }
2087 :
2088 : /* Implementation of region::dump_to_pp vfunc for element_region. */
2089 :
2090 : void
2091 276 : element_region::dump_to_pp (pretty_printer *pp, bool simple) const
2092 : {
2093 276 : if (simple)
2094 : {
2095 : //pp_string (pp, "(");
2096 276 : get_parent_region ()->dump_to_pp (pp, simple);
2097 276 : pp_string (pp, "[");
2098 276 : m_index->dump_to_pp (pp, simple);
2099 276 : pp_string (pp, "]");
2100 : //pp_string (pp, ")");
2101 : }
2102 : else
2103 : {
2104 0 : pp_string (pp, "element_region(");
2105 0 : get_parent_region ()->dump_to_pp (pp, simple);
2106 0 : pp_string (pp, ", ");
2107 0 : print_quoted_type (pp, get_type ());
2108 0 : pp_string (pp, ", ");
2109 0 : m_index->dump_to_pp (pp, simple);
2110 0 : pp_printf (pp, ")");
2111 : }
2112 276 : }
2113 :
2114 : void
2115 0 : element_region::print_dump_widget_label (pretty_printer *pp) const
2116 : {
2117 0 : pp_printf (pp, "element_region: %<[]%>");
2118 0 : }
2119 :
2120 : void
2121 0 : element_region::
2122 : add_dump_widget_children (text_art::tree_widget &w,
2123 : const text_art::dump_widget_info &dwi) const
2124 : {
2125 0 : w.add_child (m_index->make_dump_widget (dwi, "m_index"));
2126 0 : }
2127 :
2128 : /* Implementation of region::get_relative_concrete_offset vfunc
2129 : for element_region. */
2130 :
2131 : bool
2132 10814 : element_region::get_relative_concrete_offset (bit_offset_t *out) const
2133 : {
2134 10814 : if (tree idx_cst = m_index->maybe_get_constant ())
2135 : {
2136 9657 : gcc_assert (TREE_CODE (idx_cst) == INTEGER_CST);
2137 :
2138 9657 : tree elem_type = get_type ();
2139 9657 : offset_int element_idx = wi::to_offset (idx_cst);
2140 :
2141 : /* First, use int_size_in_bytes, to reject the case where we
2142 : have an incomplete type, or a non-constant value. */
2143 9657 : HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (elem_type);
2144 9657 : if (hwi_byte_size > 0)
2145 : {
2146 9655 : offset_int element_bit_size
2147 9655 : = hwi_byte_size << LOG2_BITS_PER_UNIT;
2148 9655 : offset_int element_bit_offset
2149 9655 : = element_idx * element_bit_size;
2150 9655 : *out = element_bit_offset;
2151 9655 : return true;
2152 : }
2153 : }
2154 : return false;
2155 : }
2156 :
2157 : /* Implementation of region::get_relative_symbolic_offset vfunc
2158 : for element_region. */
2159 :
2160 : const svalue *
2161 1187 : element_region::get_relative_symbolic_offset (region_model_manager *mgr) const
2162 : {
2163 1187 : tree elem_type = get_type ();
2164 :
2165 : /* First, use int_size_in_bytes, to reject the case where we
2166 : have an incomplete type, or a non-constant value. */
2167 1187 : HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (elem_type);
2168 1187 : if (hwi_byte_size > 0)
2169 : {
2170 1184 : tree byte_size_tree = wide_int_to_tree (ptrdiff_type_node,
2171 1184 : hwi_byte_size);
2172 1184 : const svalue *byte_size_sval
2173 1184 : = mgr->get_or_create_constant_svalue (byte_size_tree);
2174 1184 : return mgr->get_or_create_binop (NULL_TREE, MULT_EXPR,
2175 1184 : m_index, byte_size_sval);
2176 : }
2177 3 : return mgr->get_or_create_unknown_svalue (ptrdiff_type_node);
2178 : }
2179 :
2180 : /* class offset_region : public region. */
2181 :
2182 : /* Implementation of region::accept vfunc for offset_region. */
2183 :
2184 : void
2185 84074 : offset_region::accept (visitor *v) const
2186 : {
2187 84074 : region::accept (v);
2188 84074 : m_byte_offset->accept (v);
2189 84074 : }
2190 :
2191 : /* Implementation of region::dump_to_pp vfunc for offset_region. */
2192 :
2193 : void
2194 2800 : offset_region::dump_to_pp (pretty_printer *pp, bool simple) const
2195 : {
2196 2800 : if (simple)
2197 : {
2198 : //pp_string (pp, "(");
2199 2731 : get_parent_region ()->dump_to_pp (pp, simple);
2200 2731 : pp_string (pp, "+");
2201 2731 : m_byte_offset->dump_to_pp (pp, simple);
2202 : //pp_string (pp, ")");
2203 : }
2204 : else
2205 : {
2206 69 : pp_string (pp, "offset_region(");
2207 69 : get_parent_region ()->dump_to_pp (pp, simple);
2208 69 : pp_string (pp, ", ");
2209 69 : print_quoted_type (pp, get_type ());
2210 69 : pp_string (pp, ", ");
2211 69 : m_byte_offset->dump_to_pp (pp, simple);
2212 69 : pp_printf (pp, ")");
2213 : }
2214 2800 : }
2215 :
2216 : void
2217 0 : offset_region::print_dump_widget_label (pretty_printer *pp) const
2218 : {
2219 0 : pp_printf (pp, "offset_region");
2220 0 : }
2221 :
2222 : void
2223 0 : offset_region::
2224 : add_dump_widget_children (text_art::tree_widget &w,
2225 : const text_art::dump_widget_info &dwi) const
2226 : {
2227 0 : w.add_child (m_byte_offset->make_dump_widget (dwi, "m_byte_offset"));
2228 0 : }
2229 :
2230 : const svalue *
2231 0 : offset_region::get_bit_offset (region_model_manager *mgr) const
2232 : {
2233 0 : const svalue *bits_per_byte_sval
2234 0 : = mgr->get_or_create_int_cst (NULL_TREE, BITS_PER_UNIT);
2235 0 : return mgr->get_or_create_binop (NULL_TREE, MULT_EXPR,
2236 0 : m_byte_offset, bits_per_byte_sval);
2237 : }
2238 :
2239 : /* Implementation of region::get_relative_concrete_offset vfunc
2240 : for offset_region. */
2241 :
2242 : bool
2243 3795 : offset_region::get_relative_concrete_offset (bit_offset_t *out) const
2244 : {
2245 3795 : if (tree byte_offset_cst = m_byte_offset->maybe_get_constant ())
2246 : {
2247 2265 : gcc_assert (TREE_CODE (byte_offset_cst) == INTEGER_CST);
2248 : /* Use a signed value for the byte offset, to handle
2249 : negative offsets. */
2250 2265 : HOST_WIDE_INT byte_offset
2251 2265 : = wi::to_offset (byte_offset_cst).to_shwi ();
2252 2265 : HOST_WIDE_INT bit_offset = byte_offset * BITS_PER_UNIT;
2253 2265 : *out = bit_offset;
2254 2265 : return true;
2255 : }
2256 : return false;
2257 : }
2258 :
2259 : /* Implementation of region::get_relative_symbolic_offset vfunc
2260 : for offset_region. */
2261 :
2262 : const svalue *
2263 1534 : offset_region::get_relative_symbolic_offset (region_model_manager *mgr
2264 : ATTRIBUTE_UNUSED) const
2265 : {
2266 1534 : return get_byte_offset ();
2267 : }
2268 :
2269 : /* class sized_region : public region. */
2270 :
2271 : /* Implementation of region::accept vfunc for sized_region. */
2272 :
2273 : void
2274 40986 : sized_region::accept (visitor *v) const
2275 : {
2276 40986 : region::accept (v);
2277 40986 : m_byte_size_sval->accept (v);
2278 40986 : }
2279 :
2280 : /* Implementation of region::dump_to_pp vfunc for sized_region. */
2281 :
2282 : void
2283 114 : sized_region::dump_to_pp (pretty_printer *pp, bool simple) const
2284 : {
2285 114 : if (simple)
2286 : {
2287 105 : pp_string (pp, "SIZED_REG(");
2288 105 : get_parent_region ()->dump_to_pp (pp, simple);
2289 105 : pp_string (pp, ", ");
2290 105 : m_byte_size_sval->dump_to_pp (pp, simple);
2291 105 : pp_string (pp, ")");
2292 : }
2293 : else
2294 : {
2295 9 : pp_string (pp, "sized_region(");
2296 9 : get_parent_region ()->dump_to_pp (pp, simple);
2297 9 : pp_string (pp, ", ");
2298 9 : m_byte_size_sval->dump_to_pp (pp, simple);
2299 9 : pp_printf (pp, ")");
2300 : }
2301 114 : }
2302 :
2303 : void
2304 0 : sized_region::print_dump_widget_label (pretty_printer *pp) const
2305 : {
2306 0 : pp_printf (pp, "sized_region");
2307 0 : }
2308 :
2309 : void
2310 0 : sized_region::
2311 : add_dump_widget_children (text_art::tree_widget &w,
2312 : const text_art::dump_widget_info &dwi) const
2313 : {
2314 0 : w.add_child (m_byte_size_sval->make_dump_widget (dwi, "m_byte_size_sval"));
2315 0 : }
2316 :
2317 : /* Implementation of region::get_byte_size vfunc for sized_region. */
2318 :
2319 : bool
2320 35416 : sized_region::get_byte_size (byte_size_t *out) const
2321 : {
2322 35416 : if (tree cst = m_byte_size_sval->maybe_get_constant ())
2323 : {
2324 25245 : gcc_assert (TREE_CODE (cst) == INTEGER_CST);
2325 25245 : *out = tree_to_uhwi (cst);
2326 25245 : return true;
2327 : }
2328 : return false;
2329 : }
2330 :
2331 : /* Implementation of region::get_bit_size vfunc for sized_region. */
2332 :
2333 : bool
2334 35416 : sized_region::get_bit_size (bit_size_t *out) const
2335 : {
2336 35416 : byte_size_t byte_size;
2337 35416 : if (!get_byte_size (&byte_size))
2338 : return false;
2339 25245 : *out = byte_size * BITS_PER_UNIT;
2340 25245 : return true;
2341 : }
2342 :
2343 : /* Implementation of region::get_bit_size_sval vfunc for sized_region. */
2344 :
2345 : const svalue *
2346 5811 : sized_region::get_bit_size_sval (region_model_manager *mgr) const
2347 : {
2348 5811 : const svalue *bits_per_byte_sval
2349 5811 : = mgr->get_or_create_int_cst (NULL_TREE, BITS_PER_UNIT);
2350 5811 : return mgr->get_or_create_binop (NULL_TREE, MULT_EXPR,
2351 5811 : m_byte_size_sval, bits_per_byte_sval);
2352 : }
2353 :
2354 : /* class cast_region : public region. */
2355 :
2356 : /* Implementation of region::dump_to_pp vfunc for cast_region. */
2357 :
2358 : void
2359 1378 : cast_region::dump_to_pp (pretty_printer *pp, bool simple) const
2360 : {
2361 1378 : if (simple)
2362 : {
2363 1320 : pp_string (pp, "CAST_REG(");
2364 1320 : print_quoted_type (pp, get_type ());
2365 1320 : pp_string (pp, ", ");
2366 1320 : get_parent_region ()->dump_to_pp (pp, simple);
2367 1320 : pp_string (pp, ")");
2368 : }
2369 : else
2370 : {
2371 58 : pp_string (pp, "cast_region(");
2372 58 : get_parent_region ()->dump_to_pp (pp, simple);
2373 58 : pp_string (pp, ", ");
2374 58 : print_quoted_type (pp, get_type ());
2375 58 : pp_printf (pp, ")");
2376 : }
2377 1378 : }
2378 :
2379 : void
2380 0 : cast_region::print_dump_widget_label (pretty_printer *pp) const
2381 : {
2382 0 : pp_printf (pp, "cast_region");
2383 0 : }
2384 :
2385 : /* Implementation of region::get_relative_concrete_offset vfunc
2386 : for cast_region. */
2387 :
2388 : bool
2389 23 : cast_region::get_relative_concrete_offset (bit_offset_t *out) const
2390 : {
2391 23 : *out = (int) 0;
2392 23 : return true;
2393 : }
2394 :
2395 : /* class heap_allocated_region : public region. */
2396 :
2397 : /* Implementation of region::dump_to_pp vfunc for heap_allocated_region. */
2398 :
2399 : void
2400 2076 : heap_allocated_region::dump_to_pp (pretty_printer *pp, bool simple) const
2401 : {
2402 2076 : if (simple)
2403 2076 : pp_printf (pp, "HEAP_ALLOCATED_REGION(%i)", get_id ());
2404 : else
2405 0 : pp_printf (pp, "heap_allocated_region(%i)", get_id ());
2406 2076 : }
2407 :
2408 : void
2409 0 : heap_allocated_region::print_dump_widget_label (pretty_printer *pp) const
2410 : {
2411 0 : pp_printf (pp, "heap_allocated_region");
2412 0 : }
2413 :
2414 : /* class alloca_region : public region. */
2415 :
2416 : /* Implementation of region::dump_to_pp vfunc for alloca_region. */
2417 :
2418 : void
2419 0 : alloca_region::dump_to_pp (pretty_printer *pp, bool simple) const
2420 : {
2421 0 : if (simple)
2422 0 : pp_printf (pp, "ALLOCA_REGION(%i)", get_id ());
2423 : else
2424 0 : pp_printf (pp, "alloca_region(%i)", get_id ());
2425 0 : }
2426 :
2427 : void
2428 0 : alloca_region::print_dump_widget_label (pretty_printer *pp) const
2429 : {
2430 0 : pp_printf (pp, "alloca_region");
2431 0 : }
2432 :
2433 : /* class string_region : public region. */
2434 :
2435 : /* Implementation of region::dump_to_pp vfunc for string_region. */
2436 :
2437 : void
2438 0 : string_region::dump_to_pp (pretty_printer *pp, bool simple) const
2439 : {
2440 0 : if (simple)
2441 0 : dump_tree (pp, m_string_cst);
2442 : else
2443 : {
2444 0 : pp_string (pp, "string_region(");
2445 0 : dump_tree (pp, m_string_cst);
2446 0 : if (!flag_dump_noaddr)
2447 : {
2448 0 : pp_string (pp, " (");
2449 0 : pp_pointer (pp, m_string_cst);
2450 0 : pp_string (pp, "))");
2451 : }
2452 : }
2453 0 : }
2454 :
2455 : void
2456 0 : string_region::print_dump_widget_label (pretty_printer *pp) const
2457 : {
2458 0 : pp_string (pp, "string_region(");
2459 0 : dump_tree (pp, m_string_cst);
2460 0 : pp_string (pp, ")");
2461 0 : }
2462 :
2463 : /* class bit_range_region : public region. */
2464 :
2465 : /* Implementation of region::dump_to_pp vfunc for bit_range_region. */
2466 :
2467 : void
2468 0 : bit_range_region::dump_to_pp (pretty_printer *pp, bool simple) const
2469 : {
2470 0 : if (simple)
2471 : {
2472 0 : pp_string (pp, "BIT_RANGE_REG(");
2473 0 : get_parent_region ()->dump_to_pp (pp, simple);
2474 0 : pp_string (pp, ", ");
2475 0 : m_bits.dump_to_pp (pp);
2476 0 : pp_string (pp, ")");
2477 : }
2478 : else
2479 : {
2480 0 : pp_string (pp, "bit_range_region(");
2481 0 : get_parent_region ()->dump_to_pp (pp, simple);
2482 0 : pp_string (pp, ", ");
2483 0 : m_bits.dump_to_pp (pp);
2484 0 : pp_printf (pp, ")");
2485 : }
2486 0 : }
2487 :
2488 : void
2489 0 : bit_range_region::print_dump_widget_label (pretty_printer *pp) const
2490 : {
2491 0 : pp_printf (pp, "bit_range_region(m_bits: ");
2492 0 : m_bits.dump_to_pp (pp);
2493 0 : pp_string (pp, ")");
2494 0 : }
2495 :
2496 : /* Implementation of region::get_byte_size vfunc for bit_range_region. */
2497 :
2498 : bool
2499 0 : bit_range_region::get_byte_size (byte_size_t *out) const
2500 : {
2501 0 : if (m_bits.m_size_in_bits % BITS_PER_UNIT == 0)
2502 : {
2503 0 : *out = m_bits.m_size_in_bits / BITS_PER_UNIT;
2504 0 : return true;
2505 : }
2506 : return false;
2507 : }
2508 :
2509 : /* Implementation of region::get_bit_size vfunc for bit_range_region. */
2510 :
2511 : bool
2512 812 : bit_range_region::get_bit_size (bit_size_t *out) const
2513 : {
2514 812 : *out = m_bits.m_size_in_bits;
2515 812 : return true;
2516 : }
2517 :
2518 : /* Implementation of region::get_byte_size_sval vfunc for bit_range_region. */
2519 :
2520 : const svalue *
2521 48 : bit_range_region::get_byte_size_sval (region_model_manager *mgr) const
2522 : {
2523 48 : if (m_bits.m_size_in_bits % BITS_PER_UNIT != 0)
2524 0 : return mgr->get_or_create_unknown_svalue (size_type_node);
2525 :
2526 48 : HOST_WIDE_INT num_bytes = m_bits.m_size_in_bits.to_shwi () / BITS_PER_UNIT;
2527 48 : return mgr->get_or_create_int_cst (size_type_node, num_bytes);
2528 : }
2529 :
2530 : /* Implementation of region::get_bit_size_sval vfunc for bit_range_region. */
2531 :
2532 : const svalue *
2533 136 : bit_range_region::get_bit_size_sval (region_model_manager *mgr) const
2534 : {
2535 272 : return mgr->get_or_create_int_cst (size_type_node,
2536 136 : m_bits.m_size_in_bits);
2537 : }
2538 :
2539 : /* Implementation of region::get_relative_concrete_offset vfunc for
2540 : bit_range_region. */
2541 :
2542 : bool
2543 155 : bit_range_region::get_relative_concrete_offset (bit_offset_t *out) const
2544 : {
2545 155 : *out = m_bits.get_start_bit_offset ();
2546 155 : return true;
2547 : }
2548 :
2549 : /* Implementation of region::get_relative_symbolic_offset vfunc for
2550 : bit_range_region.
2551 : The returned svalue is equal to the offset converted to bytes and
2552 : rounded off. */
2553 :
2554 : const svalue *
2555 0 : bit_range_region::get_relative_symbolic_offset (region_model_manager *mgr)
2556 : const
2557 : {
2558 0 : byte_offset_t start_byte = m_bits.get_start_bit_offset () / BITS_PER_UNIT;
2559 0 : tree start_bit_tree = wide_int_to_tree (ptrdiff_type_node, start_byte);
2560 0 : return mgr->get_or_create_constant_svalue (start_bit_tree);
2561 : }
2562 :
2563 : /* class var_arg_region : public region. */
2564 :
2565 : void
2566 0 : var_arg_region::dump_to_pp (pretty_printer *pp, bool simple) const
2567 : {
2568 0 : if (simple)
2569 : {
2570 0 : pp_string (pp, "VAR_ARG_REG(");
2571 0 : get_parent_region ()->dump_to_pp (pp, simple);
2572 0 : pp_printf (pp, ", arg_idx: %d)", m_idx);
2573 : }
2574 : else
2575 : {
2576 0 : pp_string (pp, "var_arg_region(");
2577 0 : get_parent_region ()->dump_to_pp (pp, simple);
2578 0 : pp_printf (pp, ", arg_idx: %d)", m_idx);
2579 : }
2580 0 : }
2581 :
2582 : void
2583 0 : var_arg_region::print_dump_widget_label (pretty_printer *pp) const
2584 : {
2585 0 : pp_printf (pp, "var_arg_region(arg_idx: %i)", m_idx);
2586 0 : }
2587 :
2588 : /* Get the frame_region for this var_arg_region. */
2589 :
2590 : const frame_region *
2591 625 : var_arg_region::get_frame_region () const
2592 : {
2593 625 : gcc_assert (get_parent_region ());
2594 625 : return as_a <const frame_region *> (get_parent_region ());
2595 : }
2596 :
2597 : /* class errno_region : public region. */
2598 :
2599 : void
2600 0 : errno_region::dump_to_pp (pretty_printer *pp, bool simple) const
2601 : {
2602 0 : if (simple)
2603 0 : pp_string (pp, "errno_region");
2604 : else
2605 0 : pp_string (pp, "errno_region()");
2606 0 : }
2607 :
2608 : void
2609 0 : errno_region::print_dump_widget_label (pretty_printer *pp) const
2610 : {
2611 0 : pp_printf (pp, "errno_region");
2612 0 : }
2613 :
2614 : /* class private_region : public region. */
2615 :
2616 : void
2617 0 : private_region::dump_to_pp (pretty_printer *pp, bool simple) const
2618 : {
2619 0 : if (simple)
2620 0 : pp_printf (pp, "PRIVATE_REG(%qs)", m_desc);
2621 : else
2622 0 : pp_printf (pp, "private_region(%qs)", m_desc);
2623 0 : }
2624 :
2625 : void
2626 0 : private_region::print_dump_widget_label (pretty_printer *pp) const
2627 : {
2628 0 : pp_printf (pp, "private_region(%qs)", m_desc);
2629 0 : }
2630 :
2631 : /* class unknown_region : public region. */
2632 :
2633 : /* Implementation of region::dump_to_pp vfunc for unknown_region. */
2634 :
2635 : void
2636 35 : unknown_region::dump_to_pp (pretty_printer *pp, bool /*simple*/) const
2637 : {
2638 35 : pp_string (pp, "UNKNOWN_REGION");
2639 35 : }
2640 :
2641 : void
2642 0 : unknown_region::print_dump_widget_label (pretty_printer *pp) const
2643 : {
2644 0 : pp_printf (pp, "unknown_region");
2645 0 : }
2646 :
2647 : } // namespace ana
2648 :
2649 : #endif /* #if ENABLE_ANALYZER */
|