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