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