LCOV - code coverage report
Current view: top level - gcc/analyzer - region.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.1 % 323 304
Test Date: 2026-02-28 14:20:25 Functions: 93.8 % 81 76
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.