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