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 : #ifndef GCC_ANALYZER_REGION_H
22 : #define GCC_ANALYZER_REGION_H
23 :
24 : #include "analyzer/symbol.h"
25 : #include "text-art/widget.h"
26 :
27 : namespace ana {
28 :
29 : /* An enum for identifying different spaces within memory. */
30 :
31 : enum memory_space
32 : {
33 : MEMSPACE_UNKNOWN,
34 : MEMSPACE_CODE,
35 : MEMSPACE_GLOBALS,
36 : MEMSPACE_STACK,
37 : MEMSPACE_HEAP,
38 : MEMSPACE_READONLY_DATA,
39 : MEMSPACE_THREAD_LOCAL,
40 : MEMSPACE_PRIVATE
41 : };
42 :
43 : /* An enum for discriminating between the different concrete subclasses
44 : of region. */
45 :
46 : enum region_kind
47 : {
48 : RK_FRAME,
49 : RK_GLOBALS,
50 : RK_CODE,
51 : RK_FUNCTION,
52 : RK_LABEL,
53 : RK_STACK,
54 : RK_HEAP,
55 : RK_THREAD_LOCAL,
56 : RK_ROOT,
57 : RK_SYMBOLIC,
58 : RK_DECL,
59 : RK_FIELD,
60 : RK_ELEMENT,
61 : RK_OFFSET,
62 : RK_SIZED,
63 : RK_CAST,
64 : RK_HEAP_ALLOCATED,
65 : RK_ALLOCA,
66 : RK_STRING,
67 : RK_BIT_RANGE,
68 : RK_VAR_ARG,
69 : RK_ERRNO,
70 : RK_PRIVATE,
71 : RK_UNKNOWN,
72 : };
73 :
74 : /* Region and its subclasses.
75 :
76 : The class hierarchy looks like this (using indentation to show
77 : inheritance, and with region_kinds shown for the concrete subclasses):
78 :
79 : region
80 : space_region
81 : frame_region (RK_FRAME): a function frame on the stack
82 : globals_region (RK_GLOBALS): holds globals variables (data and bss)
83 : code_region (RK_CODE): represents the code segment, containing functions
84 : stack_region (RK_STACK): a stack, containing all stack frames
85 : heap_region (RK_HEAP): the heap, containing heap_allocated_regions
86 : thread_local_region (RK_THREAD_LOCAL): thread-local data for the thread
87 : being analyzed
88 : root_region (RK_ROOT): the top-level region
89 : function_region (RK_FUNCTION): the code for a particular function
90 : label_region (RK_LABEL): a particular label within a function
91 : symbolic_region (RK_SYMBOLIC): dereferencing a symbolic pointer
92 : decl_region (RK_DECL): the memory occupied by a particular global, local,
93 : or SSA name
94 : field_region (RK_FIELD): the memory occupied by a field within a struct
95 : or union
96 : element_region (RK_ELEMENT): an element within an array
97 : offset_region (RK_OFFSET): a byte-offset within another region, for
98 : handling pointer arithmetic as a region
99 : sized_region (RK_SIZED): a subregion of symbolic size (in bytes)
100 : within its parent
101 : cast_region (RK_CAST): a region that views another region using a
102 : different type
103 : heap_allocated_region (RK_HEAP_ALLOCATED): an untyped region dynamically
104 : allocated on the heap via
105 : "malloc" or similar
106 : alloca_region (RK_ALLOCA): an untyped region dynamically allocated on the
107 : stack via "alloca"
108 : string_region (RK_STRING): a region for a STRING_CST
109 : bit_range_region (RK_BIT_RANGE): a region for a specific range of bits
110 : within another region
111 : var_arg_region (RK_VAR_ARG): a region for the N-th vararg within a
112 : frame_region for a variadic call
113 : errno_region (RK_ERRNO): a region for holding "errno"
114 : private_region (RK_PRIVATE): a region for internal state of an API
115 : unknown_region (RK_UNKNOWN): for handling unimplemented tree codes. */
116 :
117 : /* Abstract base class for representing ways of accessing chunks of memory.
118 :
119 : Regions form a tree-like hierarchy, with a root region at the base,
120 : with memory space regions within it, representing the stack and
121 : globals, with frames within the stack, and regions for variables
122 : within the frames and the "globals" region. Regions for structs
123 : can have subregions for fields. */
124 :
125 : class region : public symbol
126 : {
127 : public:
128 : virtual ~region ();
129 :
130 : virtual enum region_kind get_kind () const = 0;
131 : virtual const frame_region *
132 3866948 : dyn_cast_frame_region () const { return nullptr; }
133 : virtual const function_region *
134 24437 : dyn_cast_function_region () const { return nullptr; }
135 : virtual const symbolic_region *
136 12916874 : dyn_cast_symbolic_region () const { return nullptr; }
137 : virtual const decl_region *
138 1031754 : dyn_cast_decl_region () const { return nullptr; }
139 : virtual const field_region *
140 248 : dyn_cast_field_region () const { return nullptr; }
141 : virtual const element_region *
142 2876483 : dyn_cast_element_region () const { return nullptr; }
143 : virtual const offset_region *
144 2838756 : dyn_cast_offset_region () const { return nullptr; }
145 : virtual const sized_region *
146 0 : dyn_cast_sized_region () const { return nullptr; }
147 : virtual const cast_region *
148 5830098 : dyn_cast_cast_region () const { return nullptr; }
149 : virtual const string_region *
150 19568 : dyn_cast_string_region () const { return nullptr; }
151 : virtual const bit_range_region *
152 0 : dyn_cast_bit_range_region () const { return nullptr; }
153 : virtual const var_arg_region *
154 0 : dyn_cast_var_arg_region () const { return nullptr; }
155 :
156 : virtual void accept (visitor *v) const;
157 :
158 38025043 : const region *get_parent_region () const { return m_parent; }
159 : const region *get_base_region () const;
160 : bool base_region_p () const;
161 : bool descendent_of_p (const region *elder) const;
162 : const frame_region *maybe_get_frame_region () const;
163 : enum memory_space get_memory_space () const;
164 : bool can_have_initial_svalue_p () const;
165 : const svalue *get_initial_value_at_main (region_model_manager *mgr) const;
166 :
167 : tree maybe_get_decl () const;
168 :
169 16970853 : tree get_type () const { return m_type; }
170 :
171 : void print (const region_model &model,
172 : pretty_printer *pp) const;
173 : label_text get_desc (bool simple=true) const;
174 :
175 : virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
176 : void dump (bool simple) const;
177 : void dump () const;
178 :
179 : std::unique_ptr<json::value> to_json () const;
180 :
181 :
182 : bool maybe_print_for_user (pretty_printer *pp,
183 : const region_model &model) const;
184 :
185 : std::unique_ptr<text_art::tree_widget>
186 : make_dump_widget (const text_art::dump_widget_info &dwi,
187 : const char *prefix = nullptr) const;
188 :
189 : bool non_null_p () const;
190 :
191 : static int cmp_ptr_ptr (const void *, const void *);
192 :
193 : bool involves_p (const svalue *sval) const;
194 :
195 : region_offset get_offset (region_model_manager *mgr) const;
196 : region_offset get_next_offset (region_model_manager *mgr) const;
197 :
198 : /* Attempt to get the size of this region as a concrete number of bytes.
199 : If successful, return true and write the size to *OUT.
200 : Otherwise return false.
201 : This is the accessed size, not necessarily the size that's valid to
202 : access. */
203 : virtual bool get_byte_size (byte_size_t *out) const;
204 :
205 : /* Attempt to get the size of this region as a concrete number of bits.
206 : If successful, return true and write the size to *OUT.
207 : Otherwise return false.
208 : This is the accessed size, not necessarily the size that's valid to
209 : access. */
210 : virtual bool get_bit_size (bit_size_t *out) const;
211 :
212 : /* Get a symbolic value describing the size of this region in bytes
213 : (which could be "unknown").
214 : This is the accessed size, not necessarily the size that's valid to
215 : access. */
216 : virtual const svalue *get_byte_size_sval (region_model_manager *mgr) const;
217 :
218 : /* Get a symbolic value describing the size of this region in bits
219 : (which could be "unknown").
220 : This is the accessed size, not necessarily the size that's valid to
221 : access. */
222 : virtual const svalue *get_bit_size_sval (region_model_manager *mgr) const;
223 :
224 : /* Attempt to get the offset in bits of this region relative to its parent.
225 : If successful, return true and write to *OUT.
226 : Otherwise return false. */
227 : virtual bool get_relative_concrete_offset (bit_offset_t *out) const;
228 :
229 : /* Get the offset in bytes of this region relative to its parent as a svalue.
230 : Might return an unknown_svalue. */
231 : virtual const svalue *
232 : get_relative_symbolic_offset (region_model_manager *mgr) const;
233 :
234 : /* Attempt to get the position and size of this region expressed as a
235 : concrete range of bytes relative to its parent.
236 : If successful, return true and write to *OUT.
237 : Otherwise return false. */
238 : bool get_relative_concrete_byte_range (byte_range *out) const;
239 :
240 : void
241 : get_subregions_for_binding (region_model_manager *mgr,
242 : bit_offset_t start_bit_offset,
243 : bit_size_t size_in_bits,
244 : tree type,
245 : auto_vec <const region *> *out) const;
246 :
247 : bool symbolic_for_unknown_ptr_p () const;
248 :
249 : bool symbolic_p () const;
250 :
251 : /* For most base regions it makes sense to track the bindings of the region
252 : within the store. As an optimization, some are not tracked (to avoid
253 : bloating the store object with redundant binding clusters). */
254 563601 : virtual bool tracked_p () const { return true; }
255 :
256 : bool is_named_decl_p (const char *decl_name) const;
257 :
258 : bool empty_p () const;
259 :
260 : protected:
261 : region (complexity c, symbol::id_t id, const region *parent, tree type);
262 :
263 : private:
264 : region_offset calc_offset (region_model_manager *mgr) const;
265 : const svalue *calc_initial_value_at_main (region_model_manager *mgr) const;
266 :
267 : virtual void
268 : print_dump_widget_label (pretty_printer *pp) const = 0;
269 : virtual void
270 : add_dump_widget_children (text_art::tree_widget &,
271 : const text_art::dump_widget_info &dwi) const;
272 :
273 : const region *m_parent;
274 : tree m_type;
275 :
276 : mutable region_offset *m_cached_offset;
277 :
278 : /* For regions within a global decl, a cache of the svalue for the initial
279 : value of this region when the program starts. */
280 : mutable const svalue *m_cached_init_sval_at_main;
281 : };
282 :
283 : } // namespace ana
284 :
285 : template <>
286 : template <>
287 : inline bool
288 : is_a_helper <const region *>::test (const region *)
289 : {
290 : return true;
291 : }
292 :
293 : namespace ana {
294 :
295 : /* Abstract subclass of region, for regions that represent an untyped
296 : space within memory, such as the stack or the heap. */
297 :
298 34593 : class space_region : public region
299 : {
300 : protected:
301 34593 : space_region (symbol::id_t id, const region *parent)
302 34593 : : region (complexity (parent), id, parent, NULL_TREE)
303 34593 : {}
304 : };
305 :
306 : /* Concrete space_region subclass, representing a function frame on the stack,
307 : to contain the locals.
308 : The parent is the stack region; there's also a hierarchy of call-stack
309 : prefixes expressed via m_calling_frame.
310 : For example, given "oldest" calling "middle" called "newest" we would have
311 : - a stack depth of 3
312 : - frame (A) for "oldest" with index 0 for depth 1, calling_frame == NULL
313 : - frame (B) for "middle" with index 1 for depth 2, calling_frame == (A)
314 : - frame (C) for "newest" with index 2 for depth 3, calling_frame == (B)
315 : where the parent region for each of the frames is the "stack" region.
316 : The index is the count of frames earlier than this in the stack. */
317 :
318 : class frame_region : public space_region
319 : {
320 : public:
321 : /* A support class for uniquifying instances of frame_region. */
322 : struct key_t
323 : {
324 32640 : key_t (const frame_region *calling_frame, const function &fun)
325 32640 : : m_calling_frame (calling_frame), m_fun (&fun)
326 : {
327 : /* calling_frame can be nullptr. */
328 : }
329 :
330 212996 : hashval_t hash () const
331 : {
332 212996 : inchash::hash hstate;
333 212996 : hstate.add_ptr (m_calling_frame);
334 212996 : hstate.add_ptr (m_fun);
335 212996 : return hstate.end ();
336 : }
337 :
338 191254 : bool operator== (const key_t &other) const
339 : {
340 191254 : return (m_calling_frame == other.m_calling_frame
341 191254 : && m_fun == other.m_fun);
342 : }
343 :
344 : void mark_deleted () { m_fun = reinterpret_cast<function *> (1); }
345 0 : void mark_empty () { m_fun = nullptr; }
346 237205 : bool is_deleted () const
347 : {
348 237205 : return m_fun == reinterpret_cast<function *> (1);
349 : }
350 996807 : bool is_empty () const { return m_fun == nullptr; }
351 :
352 : const frame_region *m_calling_frame;
353 : const function *m_fun;
354 : };
355 :
356 14908 : frame_region (symbol::id_t id, const region *parent,
357 : const frame_region *calling_frame,
358 : const function &fun, int index)
359 29816 : : space_region (id, parent), m_calling_frame (calling_frame),
360 14908 : m_fun (fun), m_index (index)
361 14908 : {}
362 : ~frame_region ();
363 :
364 : /* region vfuncs. */
365 16686224 : enum region_kind get_kind () const final override { return RK_FRAME; }
366 2079751 : const frame_region * dyn_cast_frame_region () const final override
367 : {
368 2079751 : return this;
369 : }
370 : void accept (visitor *v) const final override;
371 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
372 :
373 : void print_dump_widget_label (pretty_printer *pp) const final override;
374 :
375 : /* Accessors. */
376 1981754 : const frame_region *get_calling_frame () const { return m_calling_frame; }
377 1397092 : const function &get_function () const { return m_fun; }
378 1022 : tree get_fndecl () const { return get_function ().decl; }
379 4611174 : int get_index () const { return m_index; }
380 5407605 : int get_stack_depth () const { return m_index + 1; }
381 :
382 : const decl_region *
383 : get_region_for_local (region_model_manager *mgr,
384 : tree expr,
385 : const region_model_context *ctxt) const;
386 :
387 6 : unsigned get_num_locals () const { return m_locals.elements (); }
388 :
389 : /* Implemented in region-model-manager.cc. */
390 : void dump_untracked_regions () const;
391 :
392 : private:
393 : const frame_region *m_calling_frame;
394 : const function &m_fun;
395 : int m_index;
396 :
397 : /* The regions for the decls within this frame are managed by this
398 : object, rather than the region_model_manager, to make it a simple
399 : lookup by tree. */
400 : typedef hash_map<tree, decl_region *> map_t;
401 : map_t m_locals;
402 : };
403 :
404 : } // namespace ana
405 :
406 : template <>
407 : template <>
408 : inline bool
409 608 : is_a_helper <const frame_region *>::test (const region *reg)
410 : {
411 608 : return reg->get_kind () == RK_FRAME;
412 : }
413 :
414 : template <> struct default_hash_traits<frame_region::key_t>
415 : : public member_function_hash_traits<frame_region::key_t>
416 : {
417 : static const bool empty_zero_p = true;
418 : };
419 :
420 : namespace ana {
421 :
422 : /* Concrete space_region subclass, to hold global variables (data and bss). */
423 :
424 3937 : class globals_region : public space_region
425 : {
426 : public:
427 3937 : globals_region (symbol::id_t id, const region *parent)
428 3937 : : space_region (id, parent)
429 : {}
430 :
431 : /* region vfuncs. */
432 1971276 : enum region_kind get_kind () const final override { return RK_GLOBALS; }
433 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
434 : void print_dump_widget_label (pretty_printer *pp) const final override;
435 : };
436 :
437 : } // namespace ana
438 :
439 : template <>
440 : template <>
441 : inline bool
442 : is_a_helper <const globals_region *>::test (const region *reg)
443 : {
444 : return reg->get_kind () == RK_GLOBALS;
445 : }
446 :
447 : namespace ana {
448 :
449 : /* Concrete space_region subclass, representing the code segment
450 : containing functions. */
451 :
452 3937 : class code_region : public space_region
453 : {
454 : public:
455 3937 : code_region (symbol::id_t id, const region *parent)
456 3937 : : space_region (id, parent)
457 : {}
458 :
459 : /* region vfuncs. */
460 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
461 : void print_dump_widget_label (pretty_printer *pp) const final override;
462 27167 : enum region_kind get_kind () const final override { return RK_CODE; }
463 : };
464 :
465 : } // namespace ana
466 :
467 : template <>
468 : template <>
469 : inline bool
470 : is_a_helper <const code_region *>::test (const region *reg)
471 : {
472 : return reg->get_kind () == RK_CODE;
473 : }
474 :
475 : namespace ana {
476 :
477 : /* Concrete region subclass. A region representing the code for
478 : a particular function. */
479 :
480 : class function_region : public region
481 : {
482 : public:
483 9385 : function_region (symbol::id_t id, const code_region *parent, tree fndecl)
484 18770 : : region (complexity (parent), id, parent, TREE_TYPE (fndecl)),
485 9385 : m_fndecl (fndecl)
486 : {
487 9385 : gcc_assert (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (fndecl)));
488 9385 : }
489 :
490 : /* region vfuncs. */
491 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
492 : void print_dump_widget_label (pretty_printer *pp) const final override;
493 :
494 123406 : enum region_kind get_kind () const final override { return RK_FUNCTION; }
495 : const function_region *
496 877904 : dyn_cast_function_region () const final override{ return this; }
497 :
498 877910 : tree get_fndecl () const { return m_fndecl; }
499 :
500 : private:
501 : tree m_fndecl;
502 : };
503 :
504 : } // namespace ana
505 :
506 : template <>
507 : template <>
508 : inline bool
509 10 : is_a_helper <const function_region *>::test (const region *reg)
510 : {
511 10 : return reg->get_kind () == RK_FUNCTION;
512 : }
513 :
514 : namespace ana {
515 :
516 : /* Concrete region subclass. A region representing a particular label
517 : within a function. */
518 :
519 : class label_region : public region
520 : {
521 : public:
522 46 : label_region (symbol::id_t id, const function_region *parent, tree label)
523 46 : : region (complexity (parent), id, parent, NULL_TREE), m_label (label)
524 : {
525 46 : gcc_assert (TREE_CODE (label) == LABEL_DECL);
526 46 : }
527 :
528 : /* region vfuncs. */
529 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
530 : void print_dump_widget_label (pretty_printer *pp) const final override;
531 12658 : enum region_kind get_kind () const final override { return RK_LABEL; }
532 :
533 5 : tree get_label () const { return m_label; }
534 :
535 : private:
536 : tree m_label;
537 : };
538 :
539 : } // namespace ana
540 :
541 : template <>
542 : template <>
543 : inline bool
544 5 : is_a_helper <const label_region *>::test (const region *reg)
545 : {
546 5 : return reg->get_kind () == RK_LABEL;
547 : }
548 :
549 : namespace ana {
550 :
551 : /* Concrete space_region subclass representing a stack, containing all stack
552 : frames. */
553 :
554 3937 : class stack_region : public space_region
555 : {
556 : public:
557 3937 : stack_region (symbol::id_t id, region *parent)
558 3937 : : space_region (id, parent)
559 : {}
560 :
561 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
562 : void print_dump_widget_label (pretty_printer *pp) const final override;
563 :
564 634956 : enum region_kind get_kind () const final override { return RK_STACK; }
565 : };
566 :
567 : } // namespace ana
568 :
569 : template <>
570 : template <>
571 : inline bool
572 : is_a_helper <const stack_region *>::test (const region *reg)
573 : {
574 : return reg->get_kind () == RK_STACK;
575 : }
576 :
577 : namespace ana {
578 :
579 : /* Concrete space_region subclass: a region within which regions can be
580 : dynamically allocated. */
581 :
582 3937 : class heap_region : public space_region
583 : {
584 : public:
585 3937 : heap_region (symbol::id_t id, region *parent)
586 3937 : : space_region (id, parent)
587 : {}
588 :
589 913898 : enum region_kind get_kind () const final override { return RK_HEAP; }
590 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
591 : void print_dump_widget_label (pretty_printer *pp) const final override;
592 : };
593 :
594 : } // namespace ana
595 :
596 : template <>
597 : template <>
598 : inline bool
599 : is_a_helper <const heap_region *>::test (const region *reg)
600 : {
601 : return reg->get_kind () == RK_HEAP;
602 : }
603 :
604 : namespace ana {
605 :
606 : /* Concrete space_region subclass: thread-local data for the thread
607 : being analyzed. */
608 :
609 3937 : class thread_local_region : public space_region
610 : {
611 : public:
612 3937 : thread_local_region (symbol::id_t id, region *parent)
613 3937 : : space_region (id, parent)
614 : {}
615 :
616 153136 : enum region_kind get_kind () const final override { return RK_THREAD_LOCAL; }
617 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
618 : void print_dump_widget_label (pretty_printer *pp) const final override;
619 : };
620 :
621 : } // namespace ana
622 :
623 : template <>
624 : template <>
625 : inline bool
626 : is_a_helper <const thread_local_region *>::test (const region *reg)
627 : {
628 : return reg->get_kind () == RK_THREAD_LOCAL;
629 : }
630 :
631 : namespace ana {
632 :
633 : /* Concrete region subclass. The root region, containing all regions
634 : (either directly, or as descendents).
635 : Unique within a region_model_manager. */
636 :
637 3937 : class root_region : public region
638 : {
639 : public:
640 : root_region (symbol::id_t id);
641 :
642 5371588 : enum region_kind get_kind () const final override { return RK_ROOT; }
643 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
644 : void print_dump_widget_label (pretty_printer *pp) const final override;
645 : };
646 :
647 : } // namespace ana
648 :
649 : template <>
650 : template <>
651 : inline bool
652 : is_a_helper <const root_region *>::test (const region *reg)
653 : {
654 : return reg->get_kind () == RK_ROOT;
655 : }
656 :
657 : namespace ana {
658 :
659 : /* Concrete region subclass: a region to use when dereferencing an unknown
660 : pointer. */
661 :
662 : class symbolic_region : public region
663 : {
664 : public:
665 : /* A support class for uniquifying instances of symbolic_region. */
666 : struct key_t
667 : {
668 73121 : key_t (const region *parent, const svalue *sval_ptr)
669 73121 : : m_parent (parent), m_sval_ptr (sval_ptr)
670 : {
671 73121 : gcc_assert (sval_ptr);
672 : }
673 :
674 430023 : hashval_t hash () const
675 : {
676 430023 : inchash::hash hstate;
677 430023 : hstate.add_ptr (m_parent);
678 430023 : hstate.add_ptr (m_sval_ptr);
679 430023 : return hstate.end ();
680 : }
681 :
682 416589 : bool operator== (const key_t &other) const
683 : {
684 416589 : return (m_parent == other.m_parent && m_sval_ptr == other.m_sval_ptr);
685 : }
686 :
687 : void mark_deleted () { m_sval_ptr = reinterpret_cast<const svalue *> (1); }
688 0 : void mark_empty () { m_sval_ptr = nullptr; }
689 464430 : bool is_deleted () const
690 : {
691 464430 : return m_sval_ptr == reinterpret_cast<const svalue *> (1);
692 : }
693 1607610 : bool is_empty () const { return m_sval_ptr == nullptr; }
694 :
695 : const region *m_parent;
696 : const svalue *m_sval_ptr;
697 : };
698 :
699 : symbolic_region (symbol::id_t id, region *parent, const svalue *sval_ptr);
700 :
701 : const symbolic_region *
702 2592903 : dyn_cast_symbolic_region () const final override { return this; }
703 :
704 17371606 : enum region_kind get_kind () const final override { return RK_SYMBOLIC; }
705 : void accept (visitor *v) const final override;
706 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
707 : void print_dump_widget_label (pretty_printer *pp) const final override;
708 : void
709 : add_dump_widget_children (text_art::tree_widget &w,
710 : const text_art::dump_widget_info &dwi)
711 : const final override;
712 :
713 2598514 : const svalue *get_pointer () const { return m_sval_ptr; }
714 :
715 : private:
716 : const svalue *m_sval_ptr;
717 : };
718 :
719 : } // namespace ana
720 :
721 : template <>
722 : template <>
723 : inline bool
724 5611 : is_a_helper <const symbolic_region *>::test (const region *reg)
725 : {
726 5611 : return reg->get_kind () == RK_SYMBOLIC;
727 : }
728 :
729 : template <> struct default_hash_traits<symbolic_region::key_t>
730 : : public member_function_hash_traits<symbolic_region::key_t>
731 : {
732 : static const bool empty_zero_p = true;
733 : };
734 :
735 : namespace ana {
736 :
737 : /* Concrete region subclass representing the memory occupied by a
738 : variable (whether for a global or a local).
739 : Also used for representing SSA names, as if they were locals. */
740 :
741 : class decl_region : public region
742 : {
743 : public:
744 107981 : decl_region (symbol::id_t id, const region *parent, tree decl)
745 323943 : : region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl),
746 215962 : m_tracked (calc_tracked_p (decl)),
747 107981 : m_ctor_svalue (nullptr)
748 107981 : {}
749 :
750 67461457 : enum region_kind get_kind () const final override { return RK_DECL; }
751 : const decl_region *
752 8404666 : dyn_cast_decl_region () const final override { return this; }
753 :
754 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
755 :
756 : void
757 : print_dump_widget_label (pretty_printer *pp) const final override;
758 :
759 89 : bool tracked_p () const final override { return m_tracked; }
760 :
761 6029217 : tree get_decl () const { return m_decl; }
762 : int get_stack_depth () const;
763 :
764 : const svalue *maybe_get_constant_value (region_model_manager *mgr) const;
765 : const svalue *get_svalue_for_constructor (tree ctor,
766 : region_model_manager *mgr) const;
767 : const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
768 :
769 : private:
770 : const svalue *calc_svalue_for_constructor (tree ctor,
771 : region_model_manager *mgr) const;
772 : static bool calc_tracked_p (tree decl);
773 :
774 : tree m_decl;
775 :
776 : /* Cached result of calc_tracked_p, so that we can quickly determine when
777 : we don't to track a binding_cluster for this decl (to avoid bloating
778 : store objects).
779 : This can be debugged using -fdump-analyzer-untracked. */
780 : bool m_tracked;
781 :
782 : /* Cached result of get_svalue_for_constructor. */
783 : mutable const svalue *m_ctor_svalue;
784 : };
785 :
786 : } // namespace ana
787 :
788 : template <>
789 : template <>
790 : inline bool
791 1057324 : is_a_helper <const decl_region *>::test (const region *reg)
792 : {
793 1057324 : return reg->get_kind () == RK_DECL;
794 : }
795 :
796 : namespace ana {
797 :
798 : /* Concrete region subclass representing the memory occupied by a
799 : field within a struct or union. */
800 :
801 : class field_region : public region
802 : {
803 : public:
804 : /* A support class for uniquifying instances of field_region. */
805 : struct key_t
806 : {
807 42893 : key_t (const region *parent, tree field)
808 42893 : : m_parent (parent), m_field (field)
809 : {
810 42893 : gcc_assert (field);
811 : }
812 :
813 276041 : hashval_t hash () const
814 : {
815 276041 : inchash::hash hstate;
816 276041 : hstate.add_ptr (m_parent);
817 276041 : hstate.add_ptr (m_field);
818 276041 : return hstate.end ();
819 : }
820 :
821 264696 : bool operator== (const key_t &other) const
822 : {
823 264696 : return (m_parent == other.m_parent && m_field == other.m_field);
824 : }
825 :
826 : void mark_deleted () { m_field = reinterpret_cast<tree> (1); }
827 0 : void mark_empty () { m_field = NULL_TREE; }
828 301650 : bool is_deleted () const { return m_field == reinterpret_cast<tree> (1); }
829 1077332 : bool is_empty () const { return m_field == NULL_TREE; }
830 :
831 : const region *m_parent;
832 : tree m_field;
833 : };
834 :
835 7759 : field_region (symbol::id_t id, const region *parent, tree field)
836 15518 : : region (complexity (parent), id, parent, TREE_TYPE (field)),
837 7759 : m_field (field)
838 7759 : {}
839 :
840 1076763 : enum region_kind get_kind () const final override { return RK_FIELD; }
841 :
842 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
843 : void print_dump_widget_label (pretty_printer *pp) const final override;
844 :
845 : const field_region *
846 453 : dyn_cast_field_region () const final override { return this; }
847 :
848 2199 : tree get_field () const { return m_field; }
849 :
850 : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
851 : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
852 : const final override;
853 :
854 : private:
855 : tree m_field;
856 : };
857 :
858 : } // namespace ana
859 :
860 : template <>
861 : template <>
862 : inline bool
863 1791 : is_a_helper <const field_region *>::test (const region *reg)
864 : {
865 1791 : return reg->get_kind () == RK_FIELD;
866 : }
867 :
868 : template <> struct default_hash_traits<field_region::key_t>
869 : : public member_function_hash_traits<field_region::key_t>
870 : {
871 : static const bool empty_zero_p = true;
872 : };
873 :
874 : namespace ana {
875 :
876 : /* An element within an array. */
877 :
878 : class element_region : public region
879 : {
880 : public:
881 : /* A support class for uniquifying instances of element_region. */
882 : struct key_t
883 : {
884 28182 : key_t (const region *parent, tree element_type, const svalue *index)
885 28182 : : m_parent (parent), m_element_type (element_type), m_index (index)
886 : {
887 28182 : gcc_assert (index);
888 : }
889 :
890 179681 : hashval_t hash () const
891 : {
892 179681 : inchash::hash hstate;
893 179681 : hstate.add_ptr (m_parent);
894 179681 : hstate.add_ptr (m_element_type);
895 179681 : hstate.add_ptr (m_index);
896 179681 : return hstate.end ();
897 : }
898 :
899 176299 : bool operator== (const key_t &other) const
900 : {
901 176299 : return (m_parent == other.m_parent
902 99498 : && m_element_type == other.m_element_type
903 275797 : && m_index == other.m_index);
904 : }
905 :
906 : void mark_deleted () { m_index = reinterpret_cast<const svalue *> (1); }
907 0 : void mark_empty () { m_index = nullptr; }
908 195610 : bool is_deleted () const
909 : {
910 195610 : return m_index == reinterpret_cast<const svalue *> (1);
911 : }
912 723678 : bool is_empty () const { return m_index == nullptr; }
913 :
914 : const region *m_parent;
915 : tree m_element_type;
916 : const svalue *m_index;
917 : };
918 :
919 4112 : element_region (symbol::id_t id, const region *parent, tree element_type,
920 : const svalue *index)
921 4112 : : region (complexity::from_pair (parent, index), id, parent, element_type),
922 8224 : m_index (index)
923 4112 : {}
924 :
925 130689 : enum region_kind get_kind () const final override { return RK_ELEMENT; }
926 : const element_region *
927 7317 : dyn_cast_element_region () const final override { return this; }
928 :
929 : void accept (visitor *v) const final override;
930 :
931 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
932 :
933 : void
934 : print_dump_widget_label (pretty_printer *pp) const final override;
935 : void
936 : add_dump_widget_children (text_art::tree_widget &,
937 : const text_art::dump_widget_info &dwi)
938 : const final override;
939 :
940 21174 : const svalue *get_index () const { return m_index; }
941 :
942 : virtual bool
943 : get_relative_concrete_offset (bit_offset_t *out) const final override;
944 : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
945 : const final override;
946 :
947 : private:
948 : const svalue *m_index;
949 : };
950 :
951 : } // namespace ana
952 :
953 : template <>
954 : template <>
955 : inline bool
956 172 : is_a_helper <const element_region *>::test (const region *reg)
957 : {
958 172 : return reg->get_kind () == RK_ELEMENT;
959 : }
960 :
961 : template <> struct default_hash_traits<element_region::key_t>
962 : : public member_function_hash_traits<element_region::key_t>
963 : {
964 : static const bool empty_zero_p = true;
965 : };
966 :
967 : namespace ana {
968 :
969 : /* A byte-offset within another region, for handling pointer arithmetic
970 : as a region. */
971 :
972 : class offset_region : public region
973 : {
974 : public:
975 : /* A support class for uniquifying instances of offset_region. */
976 : struct key_t
977 : {
978 22691 : key_t (const region *parent, tree element_type, const svalue *byte_offset)
979 22691 : : m_parent (parent), m_element_type (element_type), m_byte_offset (byte_offset)
980 : {
981 22691 : gcc_assert (byte_offset);
982 : }
983 :
984 154964 : hashval_t hash () const
985 : {
986 154964 : inchash::hash hstate;
987 154964 : hstate.add_ptr (m_parent);
988 154964 : hstate.add_ptr (m_element_type);
989 154964 : hstate.add_ptr (m_byte_offset);
990 154964 : return hstate.end ();
991 : }
992 :
993 153161 : bool operator== (const key_t &other) const
994 : {
995 153161 : return (m_parent == other.m_parent
996 92031 : && m_element_type == other.m_element_type
997 242774 : && m_byte_offset == other.m_byte_offset);
998 : }
999 :
1000 : void mark_deleted () { m_byte_offset = reinterpret_cast<const svalue *> (1); }
1001 0 : void mark_empty () { m_byte_offset = nullptr; }
1002 169754 : bool is_deleted () const
1003 : {
1004 169754 : return m_byte_offset == reinterpret_cast<const svalue *> (1);
1005 : }
1006 619955 : bool is_empty () const { return m_byte_offset == nullptr; }
1007 :
1008 : const region *m_parent;
1009 : tree m_element_type;
1010 : const svalue *m_byte_offset;
1011 : };
1012 :
1013 3578 : offset_region (symbol::id_t id, const region *parent, tree type,
1014 : const svalue *byte_offset)
1015 3578 : : region (complexity::from_pair (parent, byte_offset), id, parent, type),
1016 7156 : m_byte_offset (byte_offset)
1017 3578 : {}
1018 :
1019 567618 : enum region_kind get_kind () const final override { return RK_OFFSET; }
1020 : const offset_region *
1021 134139 : dyn_cast_offset_region () const final override { return this; }
1022 :
1023 : void accept (visitor *v) const final override;
1024 :
1025 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1026 :
1027 : void
1028 : print_dump_widget_label (pretty_printer *pp) const final override;
1029 : void
1030 : add_dump_widget_children (text_art::tree_widget &,
1031 : const text_art::dump_widget_info &dwi)
1032 : const final override;
1033 :
1034 152676 : const svalue *get_byte_offset () const { return m_byte_offset; }
1035 : const svalue *get_bit_offset (region_model_manager *mgr) const;
1036 :
1037 : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
1038 : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
1039 : const final override;
1040 :
1041 : private:
1042 : const svalue *m_byte_offset;
1043 : };
1044 :
1045 : } // namespace ana
1046 :
1047 : template <>
1048 : template <>
1049 : inline bool
1050 622 : is_a_helper <const offset_region *>::test (const region *reg)
1051 : {
1052 622 : return reg->get_kind () == RK_OFFSET;
1053 : }
1054 :
1055 : template <> struct default_hash_traits<offset_region::key_t>
1056 : : public member_function_hash_traits<offset_region::key_t>
1057 : {
1058 : static const bool empty_zero_p = true;
1059 : };
1060 :
1061 : namespace ana {
1062 :
1063 : /* A region that is size BYTES_SIZE_SVAL in size within its parent
1064 : region (or possibly larger, which would lead to an overflow. */
1065 :
1066 : class sized_region : public region
1067 : {
1068 : public:
1069 : /* A support class for uniquifying instances of sized_region. */
1070 : struct key_t
1071 : {
1072 7950 : key_t (const region *parent, tree element_type,
1073 : const svalue *byte_size_sval)
1074 7950 : : m_parent (parent), m_element_type (element_type),
1075 7950 : m_byte_size_sval (byte_size_sval)
1076 : {
1077 7950 : gcc_assert (byte_size_sval);
1078 : }
1079 :
1080 56626 : hashval_t hash () const
1081 : {
1082 56626 : inchash::hash hstate;
1083 56626 : hstate.add_ptr (m_parent);
1084 56626 : hstate.add_ptr (m_element_type);
1085 56626 : hstate.add_ptr (m_byte_size_sval);
1086 56626 : return hstate.end ();
1087 : }
1088 :
1089 51376 : bool operator== (const key_t &other) const
1090 : {
1091 51376 : return (m_parent == other.m_parent
1092 6642 : && m_element_type == other.m_element_type
1093 58010 : && m_byte_size_sval == other.m_byte_size_sval);
1094 : }
1095 :
1096 : void mark_deleted () { m_byte_size_sval = reinterpret_cast<const svalue *> (1); }
1097 0 : void mark_empty () { m_byte_size_sval = nullptr; }
1098 63533 : bool is_deleted () const
1099 : {
1100 63533 : return m_byte_size_sval == reinterpret_cast<const svalue *> (1);
1101 : }
1102 335372 : bool is_empty () const { return m_byte_size_sval == nullptr; }
1103 :
1104 : const region *m_parent;
1105 : tree m_element_type;
1106 : const svalue *m_byte_size_sval;
1107 : const svalue *m_end_offset;
1108 : };
1109 :
1110 3950 : sized_region (symbol::id_t id, const region *parent, tree type,
1111 : const svalue *byte_size_sval)
1112 3950 : : region (complexity::from_pair (parent, byte_size_sval),
1113 : id, parent, type),
1114 7900 : m_byte_size_sval (byte_size_sval)
1115 3950 : {}
1116 :
1117 37776 : enum region_kind get_kind () const final override { return RK_SIZED; }
1118 : const sized_region *
1119 0 : dyn_cast_sized_region () const final override { return this; }
1120 :
1121 : void accept (visitor *v) const final override;
1122 :
1123 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1124 : void
1125 : print_dump_widget_label (pretty_printer *pp) const final override;
1126 : void
1127 : add_dump_widget_children (text_art::tree_widget &,
1128 : const text_art::dump_widget_info &dwi)
1129 : const final override;
1130 :
1131 : bool get_byte_size (byte_size_t *out) const final override;
1132 : bool get_bit_size (bit_size_t *out) const final override;
1133 :
1134 : const svalue *
1135 8577 : get_byte_size_sval (region_model_manager *) const final override
1136 : {
1137 8577 : return m_byte_size_sval;
1138 : }
1139 :
1140 : const svalue *
1141 : get_bit_size_sval (region_model_manager *) const final override;
1142 :
1143 : private:
1144 : const svalue *m_byte_size_sval;
1145 : };
1146 :
1147 : } // namespace ana
1148 :
1149 : template <>
1150 : template <>
1151 : inline bool
1152 0 : is_a_helper <const sized_region *>::test (const region *reg)
1153 : {
1154 0 : return reg->get_kind () == RK_SIZED;
1155 : }
1156 :
1157 : template <> struct default_hash_traits<sized_region::key_t>
1158 : : public member_function_hash_traits<sized_region::key_t>
1159 : {
1160 : static const bool empty_zero_p = true;
1161 : };
1162 :
1163 : namespace ana {
1164 :
1165 : /* A region that views another region using a different type. */
1166 :
1167 : class cast_region : public region
1168 : {
1169 : public:
1170 : /* A support class for uniquifying instances of cast_region. */
1171 : struct key_t
1172 : {
1173 16961 : key_t (const region *parent, tree type)
1174 16961 : : m_parent (parent), m_type (type)
1175 : {
1176 16961 : gcc_assert (parent);
1177 : }
1178 :
1179 75609 : hashval_t hash () const
1180 : {
1181 75609 : inchash::hash hstate;
1182 75609 : hstate.add_ptr (m_parent);
1183 75609 : hstate.add_ptr (m_type);
1184 75609 : return hstate.end ();
1185 : }
1186 :
1187 62231 : bool operator== (const key_t &other) const
1188 : {
1189 62231 : return (m_parent == other.m_parent
1190 62231 : && m_type == other.m_type);
1191 : }
1192 :
1193 : void mark_deleted ()
1194 : {
1195 : m_parent = reinterpret_cast<const region *> (1);
1196 : }
1197 0 : void mark_empty () { m_parent = nullptr; }
1198 79487 : bool is_deleted () const
1199 : {
1200 79487 : return m_parent == reinterpret_cast<const region *> (1);
1201 : }
1202 428579 : bool is_empty () const { return m_parent == nullptr; }
1203 :
1204 : const region *m_parent;
1205 : tree m_type;
1206 : };
1207 :
1208 2637 : cast_region (symbol::id_t id, const region *parent, tree type)
1209 2637 : : region (complexity (parent), id,
1210 2637 : parent, type)
1211 2637 : {}
1212 :
1213 103323 : enum region_kind get_kind () const final override { return RK_CAST; }
1214 : const cast_region *
1215 4650 : dyn_cast_cast_region () const final override { return this; }
1216 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1217 : void
1218 : print_dump_widget_label (pretty_printer *pp) const final override;
1219 :
1220 : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
1221 : };
1222 :
1223 : } // namespace ana
1224 :
1225 : template <>
1226 : template <>
1227 : inline bool
1228 : is_a_helper <const cast_region *>::test (const region *reg)
1229 : {
1230 : return reg->get_kind () == RK_CAST;
1231 : }
1232 :
1233 : template <> struct default_hash_traits<cast_region::key_t>
1234 : : public member_function_hash_traits<cast_region::key_t>
1235 : {
1236 : static const bool empty_zero_p = true;
1237 : };
1238 :
1239 : namespace ana {
1240 :
1241 : /* An untyped region dynamically allocated on the heap via "malloc"
1242 : or similar. */
1243 :
1244 : class heap_allocated_region : public region
1245 : {
1246 : public:
1247 1701 : heap_allocated_region (symbol::id_t id, const region *parent)
1248 1701 : : region (complexity (parent), id, parent, NULL_TREE)
1249 1701 : {}
1250 :
1251 : enum region_kind
1252 4345254 : get_kind () const final override { return RK_HEAP_ALLOCATED; }
1253 :
1254 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1255 : void print_dump_widget_label (pretty_printer *pp) const final override;
1256 : };
1257 :
1258 : /* An untyped region dynamically allocated on the stack via "alloca". */
1259 :
1260 : class alloca_region : public region
1261 : {
1262 : public:
1263 956 : alloca_region (symbol::id_t id, const frame_region *parent)
1264 956 : : region (complexity (parent), id, parent, NULL_TREE)
1265 956 : {}
1266 :
1267 270393 : enum region_kind get_kind () const final override { return RK_ALLOCA; }
1268 :
1269 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1270 : void print_dump_widget_label (pretty_printer *pp) const final override;
1271 : };
1272 :
1273 : /* A region for a STRING_CST. */
1274 :
1275 : class string_region : public region
1276 : {
1277 : public:
1278 3748 : string_region (symbol::id_t id, const region *parent, tree string_cst)
1279 7496 : : region (complexity (parent), id, parent, TREE_TYPE (string_cst)),
1280 3748 : m_string_cst (string_cst)
1281 3748 : {}
1282 :
1283 : const string_region *
1284 10619 : dyn_cast_string_region () const final override { return this; }
1285 :
1286 684768 : enum region_kind get_kind () const final override { return RK_STRING; }
1287 :
1288 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1289 : void print_dump_widget_label (pretty_printer *pp) const final override;
1290 :
1291 : /* We assume string literals are immutable, so we don't track them in
1292 : the store. */
1293 951 : bool tracked_p () const final override { return false; }
1294 :
1295 11513 : tree get_string_cst () const { return m_string_cst; }
1296 :
1297 : private:
1298 : tree m_string_cst;
1299 : };
1300 :
1301 : } // namespace ana
1302 :
1303 : template <>
1304 : template <>
1305 : inline bool
1306 535 : is_a_helper <const string_region *>::test (const region *reg)
1307 : {
1308 535 : return reg->get_kind () == RK_STRING;
1309 : }
1310 :
1311 : namespace ana {
1312 :
1313 : /* A region for a specific range of bits within another region. */
1314 :
1315 : class bit_range_region : public region
1316 : {
1317 : public:
1318 : /* A support class for uniquifying instances of bit_range_region. */
1319 : struct key_t
1320 : {
1321 247 : key_t (const region *parent, tree type, const bit_range &bits)
1322 247 : : m_parent (parent), m_type (type), m_bits (bits)
1323 : {
1324 247 : gcc_assert (parent);
1325 247 : }
1326 :
1327 1720 : hashval_t hash () const
1328 : {
1329 1720 : inchash::hash hstate;
1330 1720 : hstate.add_ptr (m_parent);
1331 1720 : hstate.add_ptr (m_type);
1332 1720 : hstate.add_wide_int (m_bits.m_start_bit_offset);
1333 1720 : hstate.add_wide_int (m_bits.m_size_in_bits);
1334 1720 : return hstate.end ();
1335 : }
1336 :
1337 1457 : bool operator== (const key_t &other) const
1338 : {
1339 1457 : return (m_parent == other.m_parent
1340 1057 : && m_type == other.m_type
1341 2514 : && m_bits == other.m_bits);
1342 : }
1343 :
1344 : void mark_deleted () { m_parent = reinterpret_cast<const region *> (1); }
1345 0 : void mark_empty () { m_parent = nullptr; }
1346 1927 : bool is_deleted () const
1347 : {
1348 1927 : return m_parent == reinterpret_cast<const region *> (1);
1349 : }
1350 110217 : bool is_empty () const { return m_parent == nullptr; }
1351 :
1352 : const region *m_parent;
1353 : tree m_type;
1354 : bit_range m_bits;
1355 : };
1356 :
1357 167 : bit_range_region (symbol::id_t id, const region *parent, tree type,
1358 : const bit_range &bits)
1359 167 : : region (complexity (parent), id, parent, type),
1360 167 : m_bits (bits)
1361 167 : {}
1362 :
1363 : const bit_range_region *
1364 0 : dyn_cast_bit_range_region () const final override { return this; }
1365 :
1366 1047 : enum region_kind get_kind () const final override { return RK_BIT_RANGE; }
1367 :
1368 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1369 : void print_dump_widget_label (pretty_printer *pp) const final override;
1370 :
1371 0 : const bit_range &get_bits () const { return m_bits; }
1372 :
1373 : bool get_byte_size (byte_size_t *out) const final override;
1374 : bool get_bit_size (bit_size_t *out) const final override;
1375 : const svalue *get_byte_size_sval (region_model_manager *mgr) const final override;
1376 : const svalue *get_bit_size_sval (region_model_manager *mgr) const final override;
1377 : bool get_relative_concrete_offset (bit_offset_t *out) const final override;
1378 : const svalue *get_relative_symbolic_offset (region_model_manager *mgr)
1379 : const final override;
1380 :
1381 : private:
1382 : bit_range m_bits;
1383 : };
1384 :
1385 : } // namespace ana
1386 :
1387 : template <>
1388 : template <>
1389 : inline bool
1390 0 : is_a_helper <const bit_range_region *>::test (const region *reg)
1391 : {
1392 0 : return reg->get_kind () == RK_BIT_RANGE;
1393 : }
1394 :
1395 : template <> struct default_hash_traits<bit_range_region::key_t>
1396 : : public member_function_hash_traits<bit_range_region::key_t>
1397 : {
1398 : static const bool empty_zero_p = true;
1399 : };
1400 :
1401 : namespace ana {
1402 :
1403 : /* A region for the N-th vararg within a frame_region for a variadic call. */
1404 :
1405 : class var_arg_region : public region
1406 : {
1407 : public:
1408 : /* A support class for uniquifying instances of var_arg_region. */
1409 : struct key_t
1410 : {
1411 1199 : key_t (const frame_region *parent, unsigned idx)
1412 1199 : : m_parent (parent), m_idx (idx)
1413 : {
1414 1199 : gcc_assert (parent);
1415 : }
1416 :
1417 8913 : hashval_t hash () const
1418 : {
1419 8913 : inchash::hash hstate;
1420 8913 : hstate.add_ptr (m_parent);
1421 8913 : hstate.add_int (m_idx);
1422 8913 : return hstate.end ();
1423 : }
1424 :
1425 8349 : bool operator== (const key_t &other) const
1426 : {
1427 8349 : return (m_parent == other.m_parent
1428 8349 : && m_idx == other.m_idx);
1429 : }
1430 :
1431 : void mark_deleted ()
1432 : {
1433 : m_parent = reinterpret_cast<const frame_region *> (1);
1434 : }
1435 0 : void mark_empty () { m_parent = nullptr; }
1436 10065 : bool is_deleted () const
1437 : {
1438 10065 : return m_parent == reinterpret_cast<const frame_region *> (1);
1439 : }
1440 136557 : bool is_empty () const { return m_parent == nullptr; }
1441 :
1442 : const frame_region *m_parent;
1443 : unsigned m_idx;
1444 : };
1445 :
1446 496 : var_arg_region (symbol::id_t id, const frame_region *parent,
1447 : unsigned idx)
1448 496 : : region (complexity (parent), id, parent, NULL_TREE),
1449 496 : m_idx (idx)
1450 496 : {}
1451 :
1452 : const var_arg_region *
1453 566 : dyn_cast_var_arg_region () const final override { return this; }
1454 :
1455 168393 : enum region_kind get_kind () const final override { return RK_VAR_ARG; }
1456 :
1457 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1458 : void print_dump_widget_label (pretty_printer *pp) const final override;
1459 :
1460 : const frame_region *get_frame_region () const;
1461 688 : unsigned get_index () const { return m_idx; }
1462 :
1463 : private:
1464 : unsigned m_idx;
1465 : };
1466 :
1467 : } // namespace ana
1468 :
1469 : template <>
1470 : template <>
1471 : inline bool
1472 : is_a_helper <const var_arg_region *>::test (const region *reg)
1473 : {
1474 : return reg->get_kind () == RK_VAR_ARG;
1475 : }
1476 :
1477 : template <> struct default_hash_traits<var_arg_region::key_t>
1478 : : public member_function_hash_traits<var_arg_region::key_t>
1479 : {
1480 : static const bool empty_zero_p = true;
1481 : };
1482 :
1483 : namespace ana {
1484 :
1485 : /* A region for errno for the current thread. */
1486 :
1487 3937 : class errno_region : public region
1488 : {
1489 : public:
1490 3937 : errno_region (symbol::id_t id, const thread_local_region *parent)
1491 3937 : : region (complexity (parent), id, parent, integer_type_node)
1492 3937 : {}
1493 :
1494 522123 : enum region_kind get_kind () const final override { return RK_ERRNO; }
1495 :
1496 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1497 : void print_dump_widget_label (pretty_printer *pp) const final override;
1498 : };
1499 :
1500 : } // namespace ana
1501 :
1502 : template <>
1503 : template <>
1504 : inline bool
1505 : is_a_helper <const errno_region *>::test (const region *reg)
1506 : {
1507 : return reg->get_kind () == RK_ERRNO;
1508 : }
1509 :
1510 : namespace ana {
1511 :
1512 : /* Similar to a decl region, but we don't have the decl.
1513 : For implementing e.g. static buffers of known_functions,
1514 : or other internal state of an API.
1515 :
1516 : These are owned by known_function instances, rather than the
1517 : region_model_manager. */
1518 :
1519 : class private_region : public region
1520 : {
1521 : public:
1522 6754 : private_region (unsigned id, const region *parent, tree type,
1523 : const char *desc)
1524 6754 : : region (complexity (parent), id, parent, type),
1525 6754 : m_desc (desc)
1526 6754 : {}
1527 :
1528 24040 : enum region_kind get_kind () const final override { return RK_PRIVATE; }
1529 :
1530 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1531 : void print_dump_widget_label (pretty_printer *pp) const final override;
1532 :
1533 : private:
1534 : const char *m_desc;
1535 : };
1536 :
1537 : } // namespace ana
1538 :
1539 : template <>
1540 : template <>
1541 : inline bool
1542 : is_a_helper <const private_region *>::test (const region *reg)
1543 : {
1544 : return reg->get_kind () == RK_PRIVATE;
1545 : }
1546 :
1547 : namespace ana {
1548 :
1549 : /* An unknown region, for handling unimplemented tree codes. */
1550 :
1551 : class unknown_region : public region
1552 : {
1553 : public:
1554 56 : unknown_region (symbol::id_t id, const region *parent, tree type)
1555 56 : : region (complexity (parent), id, parent, type)
1556 56 : {}
1557 :
1558 1651 : enum region_kind get_kind () const final override { return RK_UNKNOWN; }
1559 :
1560 : void dump_to_pp (pretty_printer *pp, bool simple) const final override;
1561 : void print_dump_widget_label (pretty_printer *pp) const final override;
1562 : };
1563 :
1564 : } // namespace ana
1565 :
1566 : #endif /* GCC_ANALYZER_REGION_H */
|