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

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.