1 /* Regions of memory.
2 Copyright (C) 2019-2021 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/complexity.h"
25
26 namespace ana {
27
28 /* An enum for discriminating between the different concrete subclasses
29 of region. */
30
31 enum region_kind
32 {
33 RK_FRAME,
34 RK_GLOBALS,
35 RK_CODE,
36 RK_FUNCTION,
37 RK_LABEL,
38 RK_STACK,
39 RK_HEAP,
40 RK_ROOT,
41 RK_SYMBOLIC,
42 RK_DECL,
43 RK_FIELD,
44 RK_ELEMENT,
45 RK_OFFSET,
46 RK_CAST,
47 RK_HEAP_ALLOCATED,
48 RK_ALLOCA,
49 RK_STRING,
50 RK_UNKNOWN
51 };
52
53 /* Region and its subclasses.
54
55 The class hierarchy looks like this (using indentation to show
56 inheritance, and with region_kinds shown for the concrete subclasses):
57
58 region
59 space_region
60 frame_region (RK_FRAME)
61 globals_region (RK_GLOBALS)
62 code_region (RK_CODE)
63 stack_region (RK_STACK)
64 heap_region (RK_HEAP)
65 root_region (RK_ROOT)
66 function_region (RK_FUNCTION)
67 label_region (RK_LABEL)
68 symbolic_region (RK_SYMBOLIC)
69 decl_region (RK_DECL),
70 field_region (RK_FIELD)
71 element_region (RK_ELEMENT)
72 offset_region (RK_OFFSET)
73 cast_region (RK_CAST)
74 heap_allocated_region (RK_HEAP_ALLOCATED)
75 alloca_region (RK_ALLOCA)
76 string_region (RK_STRING)
77 unknown_region (RK_UNKNOWN). */
78
79 /* Abstract base class for representing ways of accessing chunks of memory.
80
81 Regions form a tree-like hierarchy, with a root region at the base,
82 with memory space regions within it, representing the stack and
83 globals, with frames within the stack, and regions for variables
84 within the frames and the "globals" region. Regions for structs
85 can have subregions for fields. */
86
87 class region
88 {
89 public:
90 virtual ~region ();
91
get_id()92 unsigned get_id () const { return m_id; }
93 static int cmp_ids (const region *reg1, const region *reg2);
94
95 virtual enum region_kind get_kind () const = 0;
96 virtual const frame_region *
dyn_cast_frame_region()97 dyn_cast_frame_region () const { return NULL; }
98 virtual const function_region *
dyn_cast_function_region()99 dyn_cast_function_region () const { return NULL; }
100 virtual const symbolic_region *
dyn_cast_symbolic_region()101 dyn_cast_symbolic_region () const { return NULL; }
102 virtual const decl_region *
dyn_cast_decl_region()103 dyn_cast_decl_region () const { return NULL; }
104 virtual const field_region *
dyn_cast_field_region()105 dyn_cast_field_region () const { return NULL; }
106 virtual const element_region *
dyn_cast_element_region()107 dyn_cast_element_region () const { return NULL; }
108 virtual const offset_region *
dyn_cast_offset_region()109 dyn_cast_offset_region () const { return NULL; }
110 virtual const cast_region *
dyn_cast_cast_region()111 dyn_cast_cast_region () const { return NULL; }
112 virtual const string_region *
dyn_cast_string_region()113 dyn_cast_string_region () const { return NULL; }
114
115 virtual void accept (visitor *v) const;
116
get_parent_region()117 const region *get_parent_region () const { return m_parent; }
118 const region *get_base_region () const;
119 bool base_region_p () const;
120 bool descendent_of_p (const region *elder) const;
121 const frame_region *maybe_get_frame_region () const;
122
123 tree maybe_get_decl () const;
124
get_type()125 tree get_type () const { return m_type; }
126
127 void print (const region_model &model,
128 pretty_printer *pp) const;
129 label_text get_desc (bool simple=true) const;
130
131 virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
132 void dump (bool simple) const;
133
134 json::value *to_json () const;
135
136 bool non_null_p () const;
137
138 static int cmp_ptr_ptr (const void *, const void *);
139
140 region_offset get_offset () const;
141 bool get_byte_size (byte_size_t *out) const;
142 bool get_bit_size (bit_size_t *out) const;
143
144 void
145 get_subregions_for_binding (region_model_manager *mgr,
146 bit_offset_t start_bit_offset,
147 bit_size_t size_in_bits,
148 tree type,
149 auto_vec <const region *> *out) const;
150
151 bool symbolic_for_unknown_ptr_p () const;
152
get_complexity()153 const complexity &get_complexity () const { return m_complexity; }
154
155 protected:
156 region (complexity c, unsigned id, const region *parent, tree type);
157
158 private:
159 region_offset calc_offset () const;
160
161 complexity m_complexity;
162 unsigned m_id; // purely for deterministic sorting at this stage, for dumps
163 const region *m_parent;
164 tree m_type;
165
166 mutable region_offset *m_cached_offset;
167 };
168
169 } // namespace ana
170
171 template <>
172 template <>
173 inline bool
test(const region *)174 is_a_helper <const region *>::test (const region *)
175 {
176 return true;
177 }
178
179 namespace ana {
180
181 /* Abstract subclass of region, for regions that represent an untyped
182 space within memory, such as the stack or the heap. */
183
184 class space_region : public region
185 {
186 protected:
space_region(unsigned id,const region * parent)187 space_region (unsigned id, const region *parent)
188 : region (complexity (parent), id, parent, NULL_TREE)
189 {}
190 };
191
192 /* Concrete space_region subclass, representing a function frame on the stack,
193 to contain the locals.
194 The parent is the stack region; there's also a hierarchy of call-stack
195 prefixes expressed via m_calling_frame.
196 For example, given "oldest" calling "middle" called "newest" we would have
197 - a stack depth of 3
198 - frame (A) for "oldest" with index 0 for depth 1, calling_frame == NULL
199 - frame (B) for "middle" with index 1 for depth 2, calling_frame == (A)
200 - frame (C) for "newest" with index 2 for depth 3, calling_frame == (B)
201 where the parent region for each of the frames is the "stack" region.
202 The index is the count of frames earlier than this in the stack. */
203
204 class frame_region : public space_region
205 {
206 public:
207 /* A support class for uniquifying instances of frame_region. */
208 struct key_t
209 {
key_tkey_t210 key_t (const frame_region *calling_frame, function *fun)
211 : m_calling_frame (calling_frame), m_fun (fun)
212 {
213 /* calling_frame can be NULL. */
214 gcc_assert (fun);
215 }
216
hashkey_t217 hashval_t hash () const
218 {
219 inchash::hash hstate;
220 hstate.add_ptr (m_calling_frame);
221 hstate.add_ptr (m_fun);
222 return hstate.end ();
223 }
224
225 bool operator== (const key_t &other) const
226 {
227 return (m_calling_frame == other.m_calling_frame && m_fun == other.m_fun);
228 }
229
mark_deletedkey_t230 void mark_deleted () { m_fun = reinterpret_cast<function *> (1); }
mark_emptykey_t231 void mark_empty () { m_fun = NULL; }
is_deletedkey_t232 bool is_deleted () const
233 {
234 return m_fun == reinterpret_cast<function *> (1);
235 }
is_emptykey_t236 bool is_empty () const { return m_fun == NULL; }
237
238 const frame_region *m_calling_frame;
239 function *m_fun;
240 };
241
frame_region(unsigned id,const region * parent,const frame_region * calling_frame,function * fun,int index)242 frame_region (unsigned id, const region *parent,
243 const frame_region *calling_frame,
244 function *fun, int index)
245 : space_region (id, parent), m_calling_frame (calling_frame),
246 m_fun (fun), m_index (index)
247 {}
248 ~frame_region ();
249
250 /* region vfuncs. */
get_kind()251 enum region_kind get_kind () const FINAL OVERRIDE { return RK_FRAME; }
dyn_cast_frame_region()252 const frame_region * dyn_cast_frame_region () const FINAL OVERRIDE
253 {
254 return this;
255 }
256 void accept (visitor *v) const FINAL OVERRIDE;
257 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
258
259 /* Accessors. */
get_calling_frame()260 const frame_region *get_calling_frame () const { return m_calling_frame; }
get_function()261 function *get_function () const { return m_fun; }
get_index()262 int get_index () const { return m_index; }
get_stack_depth()263 int get_stack_depth () const { return m_index + 1; }
264
265 const decl_region *get_region_for_local (region_model_manager *mgr,
266 tree expr) const;
267
get_num_locals()268 unsigned get_num_locals () const { return m_locals.elements (); }
269
270 private:
271 const frame_region *m_calling_frame;
272 function *m_fun;
273 int m_index;
274
275 /* The regions for the decls within this frame are managed by this
276 object, rather than the region_model_manager, to make it a simple
277 lookup by tree. */
278 typedef hash_map<tree, decl_region *> map_t;
279 map_t m_locals;
280 };
281
282 } // namespace ana
283
284 template <>
285 template <>
286 inline bool
test(const region * reg)287 is_a_helper <const frame_region *>::test (const region *reg)
288 {
289 return reg->get_kind () == RK_FRAME;
290 }
291
292 template <> struct default_hash_traits<frame_region::key_t>
293 : public member_function_hash_traits<frame_region::key_t>
294 {
295 static const bool empty_zero_p = true;
296 };
297
298 namespace ana {
299
300 /* Concrete space_region subclass, to hold global variables (data and bss). */
301
302 class globals_region : public space_region
303 {
304 public:
305 globals_region (unsigned id, const region *parent)
306 : space_region (id, parent)
307 {}
308
309 /* region vfuncs. */
310 enum region_kind get_kind () const FINAL OVERRIDE { return RK_GLOBALS; }
311 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
312 };
313
314 } // namespace ana
315
316 template <>
317 template <>
318 inline bool
319 is_a_helper <const globals_region *>::test (const region *reg)
320 {
321 return reg->get_kind () == RK_GLOBALS;
322 }
323
324 namespace ana {
325
326 /* Concrete space_region subclass, representing the code segment
327 containing functions. */
328
329 class code_region : public space_region
330 {
331 public:
332 code_region (unsigned id, const region *parent)
333 : space_region (id, parent)
334 {}
335
336 /* region vfuncs. */
337 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
338 enum region_kind get_kind () const FINAL OVERRIDE { return RK_CODE; }
339
340 const region *get_element (region_model *model,
341 const svalue *index,
342 region_model_context *ctxt);
343 };
344
345 } // namespace ana
346
347 template <>
348 template <>
349 inline bool
350 is_a_helper <const code_region *>::test (const region *reg)
351 {
352 return reg->get_kind () == RK_CODE;
353 }
354
355 namespace ana {
356
357 /* Concrete region subclass. A region representing the code for
358 a particular function. */
359
360 class function_region : public region
361 {
362 public:
363 function_region (unsigned id, const code_region *parent, tree fndecl)
364 : region (complexity (parent), id, parent, TREE_TYPE (fndecl)),
365 m_fndecl (fndecl)
366 {
367 gcc_assert (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (fndecl)));
368 }
369
370 /* region vfuncs. */
371 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
372 enum region_kind get_kind () const FINAL OVERRIDE { return RK_FUNCTION; }
373 const function_region *
374 dyn_cast_function_region () const FINAL OVERRIDE{ return this; }
375
376 tree get_fndecl () const { return m_fndecl; }
377
378 region *get_element (region_model *model,
379 const svalue *index_sid,
380 region_model_context *ctxt);
381
382 private:
383 tree m_fndecl;
384 };
385
386 } // namespace ana
387
388 template <>
389 template <>
390 inline bool
391 is_a_helper <const function_region *>::test (const region *reg)
392 {
393 return reg->get_kind () == RK_FUNCTION;
394 }
395
396 namespace ana {
397
398 /* Concrete region subclass. A region representing a particular label
399 within a function. */
400
401 class label_region : public region
402 {
403 public:
404 label_region (unsigned id, const function_region *parent, tree label)
405 : region (complexity (parent), id, parent, NULL_TREE), m_label (label)
406 {
407 gcc_assert (TREE_CODE (label) == LABEL_DECL);
408 }
409
410 /* region vfuncs. */
411 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
412 enum region_kind get_kind () const FINAL OVERRIDE { return RK_LABEL; }
413
414 tree get_label () const { return m_label; }
415
416 private:
417 tree m_label;
418 };
419
420 } // namespace ana
421
422 template <>
423 template <>
424 inline bool
425 is_a_helper <const label_region *>::test (const region *reg)
426 {
427 return reg->get_kind () == RK_LABEL;
428 }
429
430 namespace ana {
431
432 /* Concrete space_region subclass representing a stack, containing all stack
433 frames. */
434
435 class stack_region : public space_region
436 {
437 public:
438 stack_region (unsigned id, region *parent)
439 : space_region (id, parent)
440 {}
441
442 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
443
444 enum region_kind get_kind () const FINAL OVERRIDE { return RK_STACK; }
445 };
446
447 } // namespace ana
448
449 template <>
450 template <>
451 inline bool
452 is_a_helper <const stack_region *>::test (const region *reg)
453 {
454 return reg->get_kind () == RK_STACK;
455 }
456
457 namespace ana {
458
459 /* Concrete space_region subclass: a region within which regions can be
460 dynamically allocated. */
461
462 class heap_region : public space_region
463 {
464 public:
465 heap_region (unsigned id, region *parent)
466 : space_region (id, parent)
467 {}
468
469 enum region_kind get_kind () const FINAL OVERRIDE { return RK_HEAP; }
470 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
471 };
472
473 } // namespace ana
474
475 template <>
476 template <>
477 inline bool
478 is_a_helper <const heap_region *>::test (const region *reg)
479 {
480 return reg->get_kind () == RK_HEAP;
481 }
482
483 namespace ana {
484
485 /* Concrete region subclass. The root region, containing all regions
486 (either directly, or as descendents).
487 Unique within a region_model_manager. */
488
489 class root_region : public region
490 {
491 public:
492 root_region (unsigned id);
493
494 enum region_kind get_kind () const FINAL OVERRIDE { return RK_ROOT; }
495 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
496 };
497
498 } // namespace ana
499
500 template <>
501 template <>
502 inline bool
503 is_a_helper <const root_region *>::test (const region *reg)
504 {
505 return reg->get_kind () == RK_ROOT;
506 }
507
508 namespace ana {
509
510 /* Concrete region subclass: a region to use when dereferencing an unknown
511 pointer. */
512
513 class symbolic_region : public region
514 {
515 public:
516 /* A support class for uniquifying instances of symbolic_region. */
517 struct key_t
518 {
519 key_t (const region *parent, const svalue *sval_ptr)
520 : m_parent (parent), m_sval_ptr (sval_ptr)
521 {
522 gcc_assert (sval_ptr);
523 }
524
525 hashval_t hash () const
526 {
527 inchash::hash hstate;
528 hstate.add_ptr (m_parent);
529 hstate.add_ptr (m_sval_ptr);
530 return hstate.end ();
531 }
532
533 bool operator== (const key_t &other) const
534 {
535 return (m_parent == other.m_parent && m_sval_ptr == other.m_sval_ptr);
536 }
537
538 void mark_deleted () { m_sval_ptr = reinterpret_cast<const svalue *> (1); }
539 void mark_empty () { m_sval_ptr = NULL; }
540 bool is_deleted () const
541 {
542 return m_sval_ptr == reinterpret_cast<const svalue *> (1);
543 }
544 bool is_empty () const { return m_sval_ptr == NULL; }
545
546 const region *m_parent;
547 const svalue *m_sval_ptr;
548 };
549
550 symbolic_region (unsigned id, region *parent, const svalue *sval_ptr);
551
552 const symbolic_region *
553 dyn_cast_symbolic_region () const FINAL OVERRIDE { return this; }
554
555 enum region_kind get_kind () const FINAL OVERRIDE { return RK_SYMBOLIC; }
556 void accept (visitor *v) const FINAL OVERRIDE;
557 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
558
559 const svalue *get_pointer () const { return m_sval_ptr; }
560
561 private:
562 const svalue *m_sval_ptr;
563 };
564
565 } // namespace ana
566
567 template <>
568 template <>
569 inline bool
570 is_a_helper <const symbolic_region *>::test (const region *reg)
571 {
572 return reg->get_kind () == RK_SYMBOLIC;
573 }
574
575 template <> struct default_hash_traits<symbolic_region::key_t>
576 : public member_function_hash_traits<symbolic_region::key_t>
577 {
578 static const bool empty_zero_p = true;
579 };
580
581 namespace ana {
582
583 /* Concrete region subclass representing the memory occupied by a
584 variable (whether for a global or a local). */
585
586 class decl_region : public region
587 {
588 public:
589 decl_region (unsigned id, const region *parent, tree decl)
590 : region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl)
591 {}
592
593 enum region_kind get_kind () const FINAL OVERRIDE { return RK_DECL; }
594 const decl_region *
595 dyn_cast_decl_region () const FINAL OVERRIDE { return this; }
596
597 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
598
599 tree get_decl () const { return m_decl; }
600 int get_stack_depth () const;
601
602 const svalue *maybe_get_constant_value (region_model_manager *mgr) const;
603 const svalue *get_svalue_for_constructor (tree ctor,
604 region_model_manager *mgr) const;
605 const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
606
607 private:
608 tree m_decl;
609 };
610
611 } // namespace ana
612
613 template <>
614 template <>
615 inline bool
616 is_a_helper <const decl_region *>::test (const region *reg)
617 {
618 return reg->get_kind () == RK_DECL;
619 }
620
621 namespace ana {
622
623 /* Concrete region subclass representing the memory occupied by a
624 field within a struct or union. */
625
626 class field_region : public region
627 {
628 public:
629 /* A support class for uniquifying instances of field_region. */
630 struct key_t
631 {
632 key_t (const region *parent, tree field)
633 : m_parent (parent), m_field (field)
634 {
635 gcc_assert (field);
636 }
637
638 hashval_t hash () const
639 {
640 inchash::hash hstate;
641 hstate.add_ptr (m_parent);
642 hstate.add_ptr (m_field);
643 return hstate.end ();
644 }
645
646 bool operator== (const key_t &other) const
647 {
648 return (m_parent == other.m_parent && m_field == other.m_field);
649 }
650
651 void mark_deleted () { m_field = reinterpret_cast<tree> (1); }
652 void mark_empty () { m_field = NULL_TREE; }
653 bool is_deleted () const { return m_field == reinterpret_cast<tree> (1); }
654 bool is_empty () const { return m_field == NULL_TREE; }
655
656 const region *m_parent;
657 tree m_field;
658 };
659
660 field_region (unsigned id, const region *parent, tree field)
661 : region (complexity (parent), id, parent, TREE_TYPE (field)),
662 m_field (field)
663 {}
664
665 enum region_kind get_kind () const FINAL OVERRIDE { return RK_FIELD; }
666
667 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
668 const field_region *
669 dyn_cast_field_region () const FINAL OVERRIDE { return this; }
670
671 tree get_field () const { return m_field; }
672
673 private:
674 tree m_field;
675 };
676
677 } // namespace ana
678
679 template <>
680 template <>
681 inline bool
682 is_a_helper <const field_region *>::test (const region *reg)
683 {
684 return reg->get_kind () == RK_FIELD;
685 }
686
687 template <> struct default_hash_traits<field_region::key_t>
688 : public member_function_hash_traits<field_region::key_t>
689 {
690 static const bool empty_zero_p = true;
691 };
692
693 namespace ana {
694
695 /* An element within an array. */
696
697 class element_region : public region
698 {
699 public:
700 /* A support class for uniquifying instances of element_region. */
701 struct key_t
702 {
703 key_t (const region *parent, tree element_type, const svalue *index)
704 : m_parent (parent), m_element_type (element_type), m_index (index)
705 {
706 gcc_assert (index);
707 }
708
709 hashval_t hash () const
710 {
711 inchash::hash hstate;
712 hstate.add_ptr (m_parent);
713 hstate.add_ptr (m_element_type);
714 hstate.add_ptr (m_index);
715 return hstate.end ();
716 }
717
718 bool operator== (const key_t &other) const
719 {
720 return (m_parent == other.m_parent
721 && m_element_type == other.m_element_type
722 && m_index == other.m_index);
723 }
724
725 void mark_deleted () { m_index = reinterpret_cast<const svalue *> (1); }
726 void mark_empty () { m_index = NULL; }
727 bool is_deleted () const
728 {
729 return m_index == reinterpret_cast<const svalue *> (1);
730 }
731 bool is_empty () const { return m_index == NULL; }
732
733 const region *m_parent;
734 tree m_element_type;
735 const svalue *m_index;
736 };
737
738 element_region (unsigned id, const region *parent, tree element_type,
739 const svalue *index)
740 : region (complexity::from_pair (parent, index), id, parent, element_type),
741 m_index (index)
742 {}
743
744 enum region_kind get_kind () const FINAL OVERRIDE { return RK_ELEMENT; }
745 const element_region *
746 dyn_cast_element_region () const FINAL OVERRIDE { return this; }
747
748 void accept (visitor *v) const FINAL OVERRIDE;
749
750 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
751
752 const svalue *get_index () const { return m_index; }
753
754 private:
755 const svalue *m_index;
756 };
757
758 } // namespace ana
759
760 template <>
761 template <>
762 inline bool
763 is_a_helper <const element_region *>::test (const region *reg)
764 {
765 return reg->get_kind () == RK_ELEMENT;
766 }
767
768 template <> struct default_hash_traits<element_region::key_t>
769 : public member_function_hash_traits<element_region::key_t>
770 {
771 static const bool empty_zero_p = true;
772 };
773
774 namespace ana {
775
776 /* A byte-offset within another region, for handling pointer arithmetic
777 as a region. */
778
779 class offset_region : public region
780 {
781 public:
782 /* A support class for uniquifying instances of offset_region. */
783 struct key_t
784 {
785 key_t (const region *parent, tree element_type, const svalue *byte_offset)
786 : m_parent (parent), m_element_type (element_type), m_byte_offset (byte_offset)
787 {
788 gcc_assert (byte_offset);
789 }
790
791 hashval_t hash () const
792 {
793 inchash::hash hstate;
794 hstate.add_ptr (m_parent);
795 hstate.add_ptr (m_element_type);
796 hstate.add_ptr (m_byte_offset);
797 return hstate.end ();
798 }
799
800 bool operator== (const key_t &other) const
801 {
802 return (m_parent == other.m_parent
803 && m_element_type == other.m_element_type
804 && m_byte_offset == other.m_byte_offset);
805 }
806
807 void mark_deleted () { m_byte_offset = reinterpret_cast<const svalue *> (1); }
808 void mark_empty () { m_byte_offset = NULL; }
809 bool is_deleted () const
810 {
811 return m_byte_offset == reinterpret_cast<const svalue *> (1);
812 }
813 bool is_empty () const { return m_byte_offset == NULL; }
814
815 const region *m_parent;
816 tree m_element_type;
817 const svalue *m_byte_offset;
818 };
819
820 offset_region (unsigned id, const region *parent, tree type,
821 const svalue *byte_offset)
822 : region (complexity::from_pair (parent, byte_offset), id, parent, type),
823 m_byte_offset (byte_offset)
824 {}
825
826 enum region_kind get_kind () const FINAL OVERRIDE { return RK_OFFSET; }
827 const offset_region *
828 dyn_cast_offset_region () const FINAL OVERRIDE { return this; }
829
830 void accept (visitor *v) const FINAL OVERRIDE;
831
832 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
833
834 const svalue *get_byte_offset () const { return m_byte_offset; }
835
836 private:
837 const svalue *m_byte_offset;
838 };
839
840 } // namespace ana
841
842 template <>
843 template <>
844 inline bool
845 is_a_helper <const offset_region *>::test (const region *reg)
846 {
847 return reg->get_kind () == RK_OFFSET;
848 }
849
850 template <> struct default_hash_traits<offset_region::key_t>
851 : public member_function_hash_traits<offset_region::key_t>
852 {
853 static const bool empty_zero_p = true;
854 };
855
856 namespace ana {
857
858 /* A region that views another region using a different type. */
859
860 class cast_region : public region
861 {
862 public:
863 /* A support class for uniquifying instances of cast_region. */
864 struct key_t
865 {
866 key_t (const region *original_region, tree type)
867 : m_original_region (original_region), m_type (type)
868 {
869 gcc_assert (type);
870 }
871
872 hashval_t hash () const
873 {
874 inchash::hash hstate;
875 hstate.add_ptr (m_original_region);
876 hstate.add_ptr (m_type);
877 return hstate.end ();
878 }
879
880 bool operator== (const key_t &other) const
881 {
882 return (m_original_region == other.m_original_region
883 && m_type == other.m_type);
884 }
885
886 void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
887 void mark_empty () { m_type = NULL_TREE; }
888 bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
889 bool is_empty () const { return m_type == NULL_TREE; }
890
891 const region *m_original_region;
892 tree m_type;
893 };
894
895 cast_region (unsigned id, const region *original_region, tree type)
896 : region (complexity (original_region), id,
897 original_region->get_parent_region (), type),
898 m_original_region (original_region)
899 {}
900
901 enum region_kind get_kind () const FINAL OVERRIDE { return RK_CAST; }
902 const cast_region *
903 dyn_cast_cast_region () const FINAL OVERRIDE { return this; }
904 void accept (visitor *v) const FINAL OVERRIDE;
905 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
906
907 const region *get_original_region () const { return m_original_region; }
908
909 private:
910 const region *m_original_region;
911 };
912
913 } // namespace ana
914
915 template <>
916 template <>
917 inline bool
918 is_a_helper <const cast_region *>::test (const region *reg)
919 {
920 return reg->get_kind () == RK_CAST;
921 }
922
923 template <> struct default_hash_traits<cast_region::key_t>
924 : public member_function_hash_traits<cast_region::key_t>
925 {
926 static const bool empty_zero_p = true;
927 };
928
929 namespace ana {
930
931 /* An untyped region dynamically allocated on the heap via "malloc"
932 or similar. */
933
934 class heap_allocated_region : public region
935 {
936 public:
937 heap_allocated_region (unsigned id, const region *parent)
938 : region (complexity (parent), id, parent, NULL_TREE)
939 {}
940
941 enum region_kind
942 get_kind () const FINAL OVERRIDE { return RK_HEAP_ALLOCATED; }
943
944 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
945 };
946
947 /* An untyped region dynamically allocated on the stack via "alloca". */
948
949 class alloca_region : public region
950 {
951 public:
952 alloca_region (unsigned id, const frame_region *parent)
953 : region (complexity (parent), id, parent, NULL_TREE)
954 {}
955
956 enum region_kind get_kind () const FINAL OVERRIDE { return RK_ALLOCA; }
957
958 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
959 };
960
961 /* A region for a STRING_CST. */
962
963 class string_region : public region
964 {
965 public:
966 string_region (unsigned id, const region *parent, tree string_cst)
967 : region (complexity (parent), id, parent, TREE_TYPE (string_cst)),
968 m_string_cst (string_cst)
969 {}
970
971 const string_region *
972 dyn_cast_string_region () const FINAL OVERRIDE { return this; }
973
974 enum region_kind get_kind () const FINAL OVERRIDE { return RK_STRING; }
975
976 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
977
978 tree get_string_cst () const { return m_string_cst; }
979
980 private:
981 tree m_string_cst;
982 };
983
984 } // namespace ana
985
986 template <>
987 template <>
988 inline bool
989 is_a_helper <const string_region *>::test (const region *reg)
990 {
991 return reg->get_kind () == RK_STRING;
992 }
993
994 namespace ana {
995
996 /* An unknown region, for handling unimplemented tree codes. */
997
998 class unknown_region : public region
999 {
1000 public:
1001 unknown_region (unsigned id, const region *parent, tree type)
1002 : region (complexity (parent), id, parent, type)
1003 {}
1004
1005 enum region_kind get_kind () const FINAL OVERRIDE { return RK_UNKNOWN; }
1006
1007 void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
1008 };
1009
1010 } // namespace ana
1011
1012 #endif /* GCC_ANALYZER_REGION_H */
1013