LCOV - code coverage report
Current view: top level - gcc/analyzer - svalue.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.3 % 435 410
Test Date: 2026-05-30 15:37:04 Functions: 91.0 % 89 81
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Symbolic values.
       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_SVALUE_H
      22              : #define GCC_ANALYZER_SVALUE_H
      23              : 
      24              : #include "analyzer/symbol.h"
      25              : #include "analyzer/store.h"
      26              : #include "analyzer/program-point.h"
      27              : #include "text-art/widget.h"
      28              : 
      29              : using namespace ana;
      30              : using text_art::dump_widget_info;
      31              : 
      32              : namespace ana {
      33              : 
      34              : /* An enum for discriminating between the different concrete subclasses
      35              :    of svalue.  */
      36              : 
      37              : enum svalue_kind
      38              : {
      39              :   SK_REGION,
      40              :   SK_CONSTANT,
      41              :   SK_UNKNOWN,
      42              :   SK_POISONED,
      43              :   SK_SETJMP,
      44              :   SK_INITIAL,
      45              :   SK_UNARYOP,
      46              :   SK_BINOP,
      47              :   SK_SUB,
      48              :   SK_REPEATED,
      49              :   SK_BITS_WITHIN,
      50              :   SK_UNMERGEABLE,
      51              :   SK_PLACEHOLDER,
      52              :   SK_WIDENING,
      53              :   SK_COMPOUND,
      54              :   SK_CONJURED,
      55              :   SK_ASM_OUTPUT,
      56              :   SK_CONST_FN_RESULT
      57              : };
      58              : 
      59              : /* svalue and its subclasses.
      60              : 
      61              :    The class hierarchy looks like this (using indentation to show
      62              :    inheritance, and with svalue_kinds shown for the concrete subclasses):
      63              : 
      64              :    svalue
      65              :      region_svalue (SK_REGION): a pointer to a region
      66              :      constant_svalue (SK_CONSTANT): a constant
      67              :      unknown_svalue (SK_UNKNOWN): an unknowable value
      68              :      poisoned_svalue (SK_POISONED): a unusable value (undefined)
      69              :      setjmp_svalue (SK_SETJMP): a setjmp/longjmp buffer
      70              :      initial_svalue (SK_INITIAL): the initial value of a region
      71              :      unaryop_svalue (SK_UNARYOP): unary operation on another svalue
      72              :      binop_svalue (SK_BINOP): binary operation on two svalues
      73              :      sub_svalue (SK_SUB): the result of accessing a subregion
      74              :      repeated_svalue (SK_REPEATED): repeating an svalue to fill a larger region
      75              :      bits_within_svalue (SK_BITS_WITHIN): a range of bits/bytes within a larger
      76              :        svalue
      77              :      unmergeable_svalue (SK_UNMERGEABLE): a value that is so interesting
      78              :        from a control-flow perspective that it can inhibit state-merging
      79              :      placeholder_svalue (SK_PLACEHOLDER): for use in selftests.
      80              :      widening_svalue (SK_WIDENING): a merger of two svalues (possibly
      81              :        in an iteration).
      82              :      compound_svalue (SK_COMPOUND): a mapping of bit-ranges to svalues
      83              :      conjured_svalue (SK_CONJURED): a value arising from a stmt
      84              :      asm_output_svalue (SK_ASM_OUTPUT): an output from a deterministic
      85              :        asm stmt.
      86              :      const_fn_result_svalue (SK_CONST_FN_RESULT): the return value from
      87              :        a function with __attribute((const)) for given inputs.  */
      88              : 
      89              : /* An abstract base class representing a value held by a region of memory.  */
      90              : 
      91              : class svalue : public symbol
      92              : {
      93              : public:
      94           28 :   virtual ~svalue () {}
      95              : 
      96     57033093 :   tree get_type () const { return m_type; }
      97              : 
      98              :   virtual enum svalue_kind get_kind () const = 0;
      99              : 
     100              :   void print (const region_model &model,
     101              :               pretty_printer *pp) const;
     102              : 
     103              :   virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
     104              :   void dump () const;
     105              :   void dump (bool simple) const;
     106              :   label_text get_desc (bool simple=true) const;
     107              : 
     108              :   std::unique_ptr<json::value> to_json () const;
     109              : 
     110              :   std::unique_ptr<text_art::tree_widget>
     111              :   make_dump_widget (const dump_widget_info &dwi,
     112              :                     const char *prefix = nullptr) const;
     113              : 
     114              :   virtual const region_svalue *
     115     14047289 :   dyn_cast_region_svalue () const { return nullptr; }
     116              :   virtual const constant_svalue *
     117      9462544 :   dyn_cast_constant_svalue () const { return nullptr; }
     118              :   virtual const poisoned_svalue *
     119      2071172 :   dyn_cast_poisoned_svalue () const { return nullptr; }
     120              :   virtual const setjmp_svalue *
     121           38 :   dyn_cast_setjmp_svalue () const { return nullptr; }
     122              :   virtual const initial_svalue *
     123      4018216 :   dyn_cast_initial_svalue () const { return nullptr; }
     124              :   virtual const unaryop_svalue *
     125     12514357 :   dyn_cast_unaryop_svalue () const { return nullptr; }
     126              :   virtual const binop_svalue *
     127      1136582 :   dyn_cast_binop_svalue () const { return nullptr; }
     128              :   virtual const sub_svalue *
     129      3693261 :   dyn_cast_sub_svalue () const { return nullptr; }
     130              :   virtual const repeated_svalue *
     131        16194 :   dyn_cast_repeated_svalue () const { return nullptr; }
     132              :   virtual const bits_within_svalue *
     133            0 :   dyn_cast_bits_within_svalue () const { return nullptr; }
     134              :   virtual const unmergeable_svalue *
     135     17294145 :   dyn_cast_unmergeable_svalue () const { return nullptr; }
     136              :   virtual const widening_svalue *
     137       495421 :   dyn_cast_widening_svalue () const { return nullptr; }
     138              :   virtual const compound_svalue *
     139     13198740 :   dyn_cast_compound_svalue () const { return nullptr; }
     140              :   virtual const conjured_svalue *
     141            0 :   dyn_cast_conjured_svalue () const { return nullptr; }
     142              :   virtual const asm_output_svalue *
     143            0 :   dyn_cast_asm_output_svalue () const { return nullptr; }
     144              :   virtual const const_fn_result_svalue *
     145            0 :   dyn_cast_const_fn_result_svalue () const { return nullptr; }
     146              : 
     147              :   tree maybe_get_constant () const;
     148              :   const region *maybe_get_region () const;
     149              :   const svalue *maybe_undo_cast () const;
     150              :   const svalue *unwrap_any_unmergeable () const;
     151              : 
     152              :   const svalue *can_merge_p (const svalue *other,
     153              :                               region_model_manager *mgr,
     154              :                               model_merger *merger) const;
     155              : 
     156              :   virtual void accept (visitor *v) const  = 0;
     157              : 
     158              :   bool live_p (const svalue_set *live_svalues,
     159              :                const region_model *model) const;
     160              :   virtual bool implicitly_live_p (const svalue_set *live_svalues,
     161              :                                   const region_model *model) const;
     162              : 
     163              :   static int cmp_ptr (const svalue *, const svalue *);
     164              :   static int cmp_ptr_ptr (const void *, const void *);
     165              : 
     166              :   bool involves_p (const svalue *other) const;
     167              : 
     168              :   const svalue *
     169              :   extract_bit_range (tree type,
     170              :                      const bit_range &subrange,
     171              :                      region_model_manager *mgr) const;
     172              : 
     173              :   virtual const svalue *
     174              :   maybe_fold_bits_within (tree type,
     175              :                           const bit_range &subrange,
     176              :                           region_model_manager *mgr) const;
     177              : 
     178              :   virtual bool all_zeroes_p () const;
     179              : 
     180              :   /* Can this svalue be involved in constraints and sm-state?
     181              :      Most can, but UNKNOWN and POISONED svalues are singletons
     182              :      per-type and thus it's meaningless for them to "have state".  */
     183      2406128 :   virtual bool can_have_associated_state_p () const { return true; }
     184              : 
     185              :   const region *maybe_get_deref_base_region () const;
     186              : 
     187              :   bool maybe_print_for_user (pretty_printer *pp,
     188              :                              const region_model &model,
     189              :                              const svalue *outer_sval = nullptr) const;
     190              : 
     191              :   tree maybe_get_type_from_typeinfo () const;
     192              : 
     193              :   /* If we can get a value_range for this svalue, write it to OUT
     194              :      and return true.  Otherwise return false.  */
     195              :   bool
     196       214432 :   maybe_get_value_range (value_range &out) const
     197              :   {
     198       214432 :     if (maybe_get_value_range_1 (out))
     199              :       {
     200       155021 :         gcc_assert (!out.undefined_p ());
     201              :         return true;
     202              :       }
     203              :     return false;
     204              :   }
     205              : 
     206              :  protected:
     207       206701 :   svalue (complexity c, symbol::id_t id, tree type)
     208        92078 :   : symbol (c, id), m_type (type)
     209              :   {}
     210              : 
     211              :   void print_svalue_node_label (pretty_printer *pp) const;
     212              : 
     213              :  private:
     214              :   virtual void
     215              :   print_dump_widget_label (pretty_printer *pp) const = 0;
     216              :   virtual void
     217              :   add_dump_widget_children (text_art::tree_widget &,
     218              :                             const dump_widget_info &dwi) const = 0;
     219              :   virtual bool
     220              :   maybe_get_value_range_1 (value_range &out) const;
     221              : 
     222              :   tree m_type;
     223              : };
     224              : 
     225              : /* Concrete subclass of svalue representing a pointer value that points to
     226              :    a known region  */
     227              : 
     228              : class region_svalue : public svalue
     229              : {
     230              : public:
     231              :   /* A support class for uniquifying instances of region_svalue.  */
     232              :   struct key_t
     233              :   {
     234      1011438 :     key_t (tree type, const region *reg)
     235      1011438 :     : m_type (type), m_reg (reg)
     236              :     {}
     237              : 
     238      5034348 :     hashval_t hash () const
     239              :     {
     240      5034348 :       inchash::hash hstate;
     241      5034348 :       hstate.add_ptr (m_type);
     242      5034348 :       hstate.add_ptr (m_reg);
     243      5034348 :       return hstate.end ();
     244              :     }
     245              : 
     246      4816665 :     bool operator== (const key_t &other) const
     247              :     {
     248      4816665 :       return (m_type == other.m_type && m_reg == other.m_reg);
     249              :     }
     250              : 
     251              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
     252       102391 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
     253      5361915 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
     254     18396142 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
     255              : 
     256              :     tree m_type;
     257              :     const region *m_reg;
     258              :   };
     259              : 
     260        26921 :   region_svalue (symbol::id_t id, tree type, const region *reg)
     261        26921 :   : svalue (complexity (reg), id, type),
     262        26921 :     m_reg (reg)
     263              :   {
     264        26921 :     gcc_assert (m_reg != nullptr);
     265        26921 :   }
     266              : 
     267     13887229 :   enum svalue_kind get_kind () const final override { return SK_REGION; }
     268              :   const region_svalue *
     269      2185463 :   dyn_cast_region_svalue () const final override { return this; }
     270              : 
     271              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     272              : 
     273              :   void
     274              :   print_dump_widget_label (pretty_printer *pp) const final override;
     275              :   void
     276              :   add_dump_widget_children (text_art::tree_widget &w,
     277              :                             const dump_widget_info &dwi) const final override;
     278              : 
     279              :   void accept (visitor *v) const final override;
     280              :   bool implicitly_live_p (const svalue_set *,
     281              :                           const region_model *) const final override;
     282              : 
     283      4037415 :   const region * get_pointee () const { return m_reg; }
     284              : 
     285              :   static tristate eval_condition (const region_svalue *lhs_ptr,
     286              :                                   enum tree_code op,
     287              :                                   const region_svalue *rhs_ptr,
     288              :                                   const region_model &model);
     289              : 
     290              :  private:
     291              :   const region *m_reg;
     292              : };
     293              : 
     294              : } // namespace ana
     295              : 
     296              : template <>
     297              : template <>
     298              : inline bool
     299        64084 : is_a_helper <const region_svalue *>::test (const svalue *sval)
     300              : {
     301        64084 :   return sval->get_kind () == SK_REGION;
     302              : }
     303              : 
     304              : template <> struct default_hash_traits<region_svalue::key_t>
     305              : : public member_function_hash_traits<region_svalue::key_t>
     306              : {
     307              :   static const bool empty_zero_p = false;
     308              : };
     309              : 
     310              : namespace ana {
     311              : 
     312              : /* Concrete subclass of svalue representing a specific constant value.
     313              :    The type will either be the same as that of the underlying tree constant,
     314              :    or NULL_TREE indicating the constant is intended to be "typeless".  */
     315              : 
     316              : class constant_svalue : public svalue
     317              : {
     318              : public:
     319              :   /* A support class for uniquifying instances of region_svalue.  */
     320              :   struct key_t
     321              :   {
     322      2629513 :     key_t (tree type, tree cst)
     323      2629513 :     : m_type (type), m_cst (cst)
     324              :     {}
     325              : 
     326     16374929 :     hashval_t hash () const
     327              :     {
     328     16374929 :       inchash::hash hstate;
     329     16374929 :       hstate.add_ptr (m_type);
     330     16374929 :       hstate.add_ptr (m_cst);
     331     16374929 :       return hstate.end ();
     332              :     }
     333              : 
     334     16497018 :     bool operator== (const key_t &other) const
     335              :     {
     336     16497018 :       return (m_type == other.m_type && m_cst == other.m_cst);
     337              :     }
     338              : 
     339              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
     340       182988 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
     341     17183608 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
     342     50705726 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
     343              : 
     344              :     tree m_type;
     345              :     tree m_cst;
     346              :   };
     347              : 
     348        58407 :   constant_svalue (symbol::id_t id, tree type, tree cst_expr)
     349        58407 :   : svalue (complexity (1, 1), id, type),
     350        58407 :     m_cst_expr (cst_expr)
     351              :   {
     352        58407 :     gcc_assert (cst_expr);
     353        58407 :     gcc_assert (CONSTANT_CLASS_P (cst_expr));
     354        58407 :     gcc_assert (type == TREE_TYPE (cst_expr) || type == NULL_TREE);
     355        58407 :   }
     356              : 
     357     37222755 :   enum svalue_kind get_kind () const final override { return SK_CONSTANT; }
     358              :   const constant_svalue *
     359      4969446 :   dyn_cast_constant_svalue () const final override { return this; }
     360              : 
     361              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     362              : 
     363              :   void
     364              :   print_dump_widget_label (pretty_printer *pp) const final override;
     365              :   void
     366              :   add_dump_widget_children (text_art::tree_widget &w,
     367              :                             const dump_widget_info &dwi) const final override;
     368              : 
     369              :   void accept (visitor *v) const final override;
     370              :   bool implicitly_live_p (const svalue_set *,
     371              :                           const region_model *) const final override;
     372              : 
     373      6461564 :   tree get_constant () const { return m_cst_expr; }
     374              :   static tristate eval_condition (const constant_svalue *lhs,
     375              :                                   enum tree_code op,
     376              :                                   const constant_svalue *rhs);
     377              : 
     378              :   const svalue *
     379              :   maybe_fold_bits_within (tree type,
     380              :                           const bit_range &subrange,
     381              :                           region_model_manager *mgr) const final override;
     382              : 
     383              :   bool all_zeroes_p () const final override;
     384              : 
     385              :   bool maybe_get_value_range_1 (value_range &out) const final override;
     386              : 
     387              :  private:
     388              :   tree m_cst_expr;
     389              : };
     390              : 
     391              : } // namespace ana
     392              : 
     393              : template <>
     394              : template <>
     395              : inline bool
     396         1955 : is_a_helper <const constant_svalue *>::test (const svalue *sval)
     397              : {
     398         1955 :   return sval->get_kind () == SK_CONSTANT;
     399              : }
     400              : 
     401              : template <> struct default_hash_traits<constant_svalue::key_t>
     402              : : public member_function_hash_traits<constant_svalue::key_t>
     403              : {
     404              :   static const bool empty_zero_p = false;
     405              : };
     406              : 
     407              : namespace ana {
     408              : 
     409              : /* Concrete subclass of svalue representing an unknowable value, the bottom
     410              :    value when thinking of svalues as a lattice.
     411              :    This is a singleton (w.r.t. its manager): there is a single unknown_svalue
     412              :    per type.  Self-comparisons of such instances yield "unknown".  */
     413              : 
     414              : class unknown_svalue : public svalue
     415              : {
     416              : public:
     417        10681 :   unknown_svalue (symbol::id_t id, tree type)
     418        10681 :   : svalue (complexity (1, 1), id, type)
     419              :   {}
     420              : 
     421      7778471 :   enum svalue_kind get_kind () const final override { return SK_UNKNOWN; }
     422              : 
     423              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     424              : 
     425              :   void
     426              :   print_dump_widget_label (pretty_printer *pp) const final override;
     427              :   void
     428              :   add_dump_widget_children (text_art::tree_widget &w,
     429              :                             const dump_widget_info &dwi) const final override;
     430              : 
     431              :   void accept (visitor *v) const final override;
     432              : 
     433              :   const svalue *
     434              :   maybe_fold_bits_within (tree type,
     435              :                           const bit_range &subrange,
     436              :                           region_model_manager *mgr) const final override;
     437              : 
     438              :   bool maybe_get_value_range_1 (value_range &out) const final override;
     439              : 
     440              :   /* Unknown values are singletons per-type, so can't have state.  */
     441       102473 :   bool can_have_associated_state_p () const final override { return false; }
     442              : };
     443              : 
     444              : /* An enum describing a particular kind of "poisoned" value.  */
     445              : 
     446              : enum class poison_kind
     447              : {
     448              :   /* For use to describe uninitialized memory.  */
     449              :   uninit,
     450              : 
     451              :   /* For use to describe freed memory.  */
     452              :   freed,
     453              : 
     454              :   /* For use to describe deleted memory.  */
     455              :   deleted,
     456              : 
     457              :   /* For use on pointers to regions within popped stack frames.  */
     458              :   popped_stack
     459              : };
     460              : 
     461              : extern const char *poison_kind_to_str (enum poison_kind);
     462              : 
     463              : /* Concrete subclass of svalue representing a value that should not
     464              :    be used (e.g. uninitialized memory, freed memory).  */
     465              : 
     466              : class poisoned_svalue : public svalue
     467              : {
     468              : public:
     469              :   /* A support class for uniquifying instances of poisoned_svalue.  */
     470              :   struct key_t
     471              :   {
     472       211337 :     key_t (enum poison_kind kind, tree type)
     473       211337 :     : m_kind (kind), m_type (type)
     474              :     {}
     475              : 
     476       821376 :     hashval_t hash () const
     477              :     {
     478       821376 :       inchash::hash hstate;
     479       821376 :       hstate.add_int (static_cast<int> (m_kind));
     480       821376 :       hstate.add_ptr (m_type);
     481       821376 :       return hstate.end ();
     482              :     }
     483              : 
     484       667962 :     bool operator== (const key_t &other) const
     485              :     {
     486       667962 :       return (m_kind == other.m_kind && m_type == other.m_type);
     487              :     }
     488              : 
     489              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
     490        53279 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
     491       860895 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
     492      3629726 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
     493              : 
     494              :     enum poison_kind m_kind;
     495              :     tree m_type;
     496              :   };
     497              : 
     498         6195 :   poisoned_svalue (enum poison_kind kind, symbol::id_t id, tree type)
     499         6195 :   : svalue (complexity (1, 1), id, type), m_kind (kind) {}
     500              : 
     501       311113 :   enum svalue_kind get_kind () const final override { return SK_POISONED; }
     502              :   const poisoned_svalue *
     503         5509 :   dyn_cast_poisoned_svalue () const final override { return this; }
     504              : 
     505              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     506              : 
     507              :   void
     508              :   print_dump_widget_label (pretty_printer *pp) const final override;
     509              :   void
     510              :   add_dump_widget_children (text_art::tree_widget &w,
     511              :                             const dump_widget_info &dwi) const final override;
     512              : 
     513              :   void accept (visitor *v) const final override;
     514              : 
     515              :   const svalue *
     516              :   maybe_fold_bits_within (tree type,
     517              :                           const bit_range &subrange,
     518              :                           region_model_manager *mgr) const final override;
     519              : 
     520         5525 :   enum poison_kind get_poison_kind () const { return m_kind; }
     521              : 
     522              :   /* Poisoned svalues are singletons per-type, so can't have state.  */
     523         8432 :   bool can_have_associated_state_p () const final override { return false; }
     524              : 
     525              :  private:
     526              :   enum poison_kind m_kind;
     527              : };
     528              : 
     529              : } // namespace ana
     530              : 
     531              : template <>
     532              : template <>
     533              : inline bool
     534            8 : is_a_helper <const poisoned_svalue *>::test (const svalue *sval)
     535              : {
     536            8 :   return sval->get_kind () == SK_POISONED;
     537              : }
     538              : 
     539              : template <> struct default_hash_traits<poisoned_svalue::key_t>
     540              : : public member_function_hash_traits<poisoned_svalue::key_t>
     541              : {
     542              :   static const bool empty_zero_p = false;
     543              : };
     544              : 
     545              : namespace ana {
     546              : 
     547              : /* A bundle of information recording a setjmp/sigsetjmp call, corresponding
     548              :    roughly to a jmp_buf.  */
     549              : 
     550              : struct setjmp_record
     551              : {
     552           34 :   setjmp_record (const exploded_node *enode,
     553              :                  const superedge *sedge,
     554              :                  const gcall &setjmp_call)
     555           34 :   : m_enode (enode), m_sedge (sedge), m_setjmp_call (&setjmp_call)
     556              :   {
     557              :   }
     558              : 
     559           12 :   bool operator== (const setjmp_record &other) const
     560              :   {
     561           12 :     return (m_enode == other.m_enode
     562            0 :             && m_sedge == other.m_sedge
     563            0 :             && m_setjmp_call == other.m_setjmp_call);
     564              :   }
     565              : 
     566           76 :   void add_to_hash (inchash::hash *hstate) const
     567              :   {
     568           76 :     hstate->add_ptr (m_enode);
     569           76 :     hstate->add_ptr (m_sedge);
     570           76 :     hstate->add_ptr (m_setjmp_call);
     571           76 :   }
     572              : 
     573              :   static int cmp (const setjmp_record &rec1, const setjmp_record &rec2);
     574              : 
     575              :   const exploded_node *m_enode;
     576              :   const superedge *m_sedge;
     577              :   const gcall *m_setjmp_call;
     578              :   // non-null, but we can't use a reference since we're putting these in a hash_map
     579              : };
     580              : 
     581              : /* Concrete subclass of svalue representing buffers for setjmp/sigsetjmp,
     582              :    so that longjmp/siglongjmp can potentially "return" to an entirely
     583              :    different function.  */
     584              : 
     585              : class setjmp_svalue : public svalue
     586              : {
     587              : public:
     588              :   /* A support class for uniquifying instances of poisoned_svalue.  */
     589              :   struct key_t
     590              :   {
     591           34 :     key_t (const setjmp_record &record, tree type)
     592           34 :     : m_record (record), m_type (type)
     593              :     {}
     594              : 
     595           76 :     hashval_t hash () const
     596              :     {
     597           76 :       inchash::hash hstate;
     598           76 :       m_record.add_to_hash (&hstate);
     599           76 :       hstate.add_ptr (m_type);
     600           76 :       return hstate.end ();
     601              :     }
     602              : 
     603           12 :     bool operator== (const key_t &other) const
     604              :     {
     605           12 :       return (m_record == other.m_record && m_type == other.m_type);
     606              :     }
     607              : 
     608              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
     609        52442 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
     610           80 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
     611       105917 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
     612              : 
     613              :     setjmp_record m_record;
     614              :     tree m_type;
     615              :   };
     616              : 
     617           34 :   setjmp_svalue (const setjmp_record &setjmp_record,
     618              :                  symbol::id_t id,
     619              :                  tree type)
     620           34 :   : svalue (complexity (1, 1), id, type), m_setjmp_record (setjmp_record)
     621              :   {}
     622              : 
     623         2775 :   enum svalue_kind get_kind () const final override { return SK_SETJMP; }
     624              :   const setjmp_svalue *
     625           25 :   dyn_cast_setjmp_svalue () const final override { return this; }
     626              : 
     627              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     628              : 
     629              :   void
     630              :   print_dump_widget_label (pretty_printer *pp) const final override;
     631              :   void
     632              :   add_dump_widget_children (text_art::tree_widget &w,
     633              :                             const dump_widget_info &dwi) const final override;
     634              : 
     635              :   void accept (visitor *v) const final override;
     636              : 
     637              :   int get_enode_index () const;
     638              : 
     639            0 :   const setjmp_record &get_setjmp_record () const { return m_setjmp_record; }
     640              : 
     641              :  private:
     642              :   setjmp_record m_setjmp_record;
     643              : };
     644              : 
     645              : } // namespace ana
     646              : 
     647              : template <>
     648              : template <>
     649              : inline bool
     650              : is_a_helper <const setjmp_svalue *>::test (const svalue *sval)
     651              : {
     652              :   return sval->get_kind () == SK_SETJMP;
     653              : }
     654              : 
     655              : template <> struct default_hash_traits<setjmp_svalue::key_t>
     656              : : public member_function_hash_traits<setjmp_svalue::key_t>
     657              : {
     658              :   static const bool empty_zero_p = false;
     659              : };
     660              : 
     661              : namespace ana {
     662              : 
     663              : /* Concrete subclass of svalue representing the initial value of a
     664              :    specific region.
     665              : 
     666              :    This represents the initial value at the start of the analysis path,
     667              :    as opposed to the first time the region is accessed during the path.
     668              :    Hence as soon as we have a call to an unknown function, all previously
     669              :    unmodelled globals become implicitly "unknown" rathen than "initial".  */
     670              : 
     671              : class initial_svalue : public svalue
     672              : {
     673              : public:
     674        28205 :   initial_svalue (symbol::id_t id, tree type, const region *reg)
     675        28205 :   : svalue (complexity (reg), id, type), m_reg (reg)
     676              :   {
     677        28205 :     gcc_assert (m_reg != nullptr);
     678        28205 :   }
     679              : 
     680     28942580 :   enum svalue_kind get_kind () const final override { return SK_INITIAL; }
     681              :   const initial_svalue *
     682       304713 :   dyn_cast_initial_svalue () const final override { return this; }
     683              : 
     684              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     685              : 
     686              :   void
     687              :   print_dump_widget_label (pretty_printer *pp) const final override;
     688              :   void
     689              :   add_dump_widget_children (text_art::tree_widget &w,
     690              :                             const dump_widget_info &dwi) const final override;
     691              : 
     692              :   void accept (visitor *v) const final override;
     693              :   bool implicitly_live_p (const svalue_set *,
     694              :                           const region_model *) const final override;
     695              : 
     696              :   bool initial_value_of_param_p () const;
     697              : 
     698      6132101 :   const region *get_region () const { return m_reg; }
     699              : 
     700              :  private:
     701              :   const region *m_reg;
     702              : };
     703              : 
     704              : } // namespace ana
     705              : 
     706              : template <>
     707              : template <>
     708              : inline bool
     709      1709578 : is_a_helper <const initial_svalue *>::test (const svalue *sval)
     710              : {
     711      1709578 :   return sval->get_kind () == SK_INITIAL;
     712              : }
     713              : 
     714              : namespace ana {
     715              : 
     716              : /* Concrete subclass of svalue representing a unary operation on
     717              :    another svalues (e.g. a cast).  */
     718              : 
     719              : class unaryop_svalue : public svalue
     720              : {
     721              : public:
     722              :   /* A support class for uniquifying instances of unaryop_svalue.  */
     723              :   struct key_t
     724              :   {
     725       121621 :     key_t (tree type, enum tree_code op, const svalue *arg)
     726       121621 :     : m_type (type), m_op (op), m_arg (arg)
     727              :     {}
     728              : 
     729       774455 :     hashval_t hash () const
     730              :     {
     731       774455 :       inchash::hash hstate;
     732       774455 :       hstate.add_ptr (m_type);
     733       774455 :       hstate.add_int (m_op);
     734       774455 :       hstate.add_ptr (m_arg);
     735       774455 :       return hstate.end ();
     736              :     }
     737              : 
     738       778594 :     bool operator== (const key_t &other) const
     739              :     {
     740       778594 :       return (m_type == other.m_type
     741       318620 :               && m_op == other.m_op
     742      1094891 :               && m_arg == other.m_arg);
     743              :     }
     744              : 
     745              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
     746        66395 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
     747       830929 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
     748      2600799 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
     749              : 
     750              :     tree m_type;
     751              :     enum tree_code m_op;
     752              :     const svalue *m_arg;
     753              :   };
     754              : 
     755         8839 :   unaryop_svalue (symbol::id_t id, tree type, enum tree_code op,
     756              :                   const svalue *arg)
     757         8839 :   : svalue (complexity (arg), id, type), m_op (op), m_arg (arg)
     758              :   {
     759         8839 :     gcc_assert (arg->can_have_associated_state_p ());
     760         8839 :   }
     761              : 
     762      9430999 :   enum svalue_kind get_kind () const final override { return SK_UNARYOP; }
     763              :   const unaryop_svalue *
     764       895650 :   dyn_cast_unaryop_svalue () const final override { return this; }
     765              : 
     766              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     767              : 
     768              :   void
     769              :   print_dump_widget_label (pretty_printer *pp) const final override;
     770              :   void
     771              :   add_dump_widget_children (text_art::tree_widget &w,
     772              :                             const dump_widget_info &dwi) const final override;
     773              : 
     774              :   void accept (visitor *v) const final override;
     775              :   bool implicitly_live_p (const svalue_set *,
     776              :                           const region_model *) const final override;
     777              : 
     778      2585623 :   enum tree_code get_op () const { return m_op; }
     779      2791537 :   const svalue *get_arg () const { return m_arg; }
     780              : 
     781              :   const svalue *
     782              :   maybe_fold_bits_within (tree type,
     783              :                           const bit_range &subrange,
     784              :                           region_model_manager *mgr) const final override;
     785              : 
     786              :   bool maybe_get_value_range_1 (value_range &out) const final override;
     787              : 
     788              :  private:
     789              :   enum tree_code m_op;
     790              :   const svalue *m_arg;
     791              : };
     792              : 
     793              : } // namespace ana
     794              : 
     795              : template <>
     796              : template <>
     797              : inline bool
     798       306726 : is_a_helper <const unaryop_svalue *>::test (const svalue *sval)
     799              : {
     800       306726 :   return sval->get_kind () == SK_UNARYOP;
     801              : }
     802              : 
     803              : template <> struct default_hash_traits<unaryop_svalue::key_t>
     804              : : public member_function_hash_traits<unaryop_svalue::key_t>
     805              : {
     806              :   static const bool empty_zero_p = false;
     807              : };
     808              : 
     809              : namespace ana {
     810              : 
     811              : /* Concrete subclass of svalue representing a binary operation of
     812              :    two svalues.  */
     813              : 
     814              : class binop_svalue : public svalue
     815              : {
     816              : public:
     817              :   /* A support class for uniquifying instances of binop_svalue.  */
     818              :   struct key_t
     819              :   {
     820       108139 :     key_t (tree type, enum tree_code op,
     821              :            const svalue *arg0, const svalue *arg1)
     822       108139 :     : m_type (type), m_op (op), m_arg0 (arg0), m_arg1 (arg1)
     823              :     {}
     824              : 
     825       717937 :     hashval_t hash () const
     826              :     {
     827       717937 :       inchash::hash hstate;
     828       717937 :       hstate.add_ptr (m_type);
     829       717937 :       hstate.add_int (m_op);
     830       717937 :       hstate.add_ptr (m_arg0);
     831       717937 :       hstate.add_ptr (m_arg1);
     832       717937 :       return hstate.end ();
     833              :     }
     834              : 
     835       720636 :     bool operator== (const key_t &other) const
     836              :     {
     837       720636 :       return (m_type == other.m_type
     838       326764 :               && m_op == other.m_op
     839       255226 :               && m_arg0 == other.m_arg0
     840       858261 :               && m_arg1 == other.m_arg1);
     841              :     }
     842              : 
     843              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
     844       102480 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
     845       802241 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
     846      2676305 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
     847              : 
     848              :     tree m_type;
     849              :     enum tree_code m_op;
     850              :     const svalue *m_arg0;
     851              :     const svalue *m_arg1;
     852              :   };
     853              : 
     854        21017 :   binop_svalue (symbol::id_t id, tree type, enum tree_code op,
     855              :                 const svalue *arg0, const svalue *arg1)
     856        21017 :   : svalue (complexity::from_pair (arg0->get_complexity (),
     857              :                                     arg1->get_complexity ()),
     858              :             id,
     859              :             type),
     860        21017 :     m_op (op), m_arg0 (arg0), m_arg1 (arg1)
     861              :   {
     862        21017 :     gcc_assert (arg0->can_have_associated_state_p ());
     863        21017 :     gcc_assert (arg1->can_have_associated_state_p ());
     864        21017 :   }
     865              : 
     866     20418550 :   enum svalue_kind get_kind () const final override { return SK_BINOP; }
     867       136813 :   const binop_svalue *dyn_cast_binop_svalue () const final override
     868              :   {
     869       136813 :     return this;
     870              :   }
     871              : 
     872              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     873              : 
     874              :   void
     875              :   print_dump_widget_label (pretty_printer *pp) const final override;
     876              :   void
     877              :   add_dump_widget_children (text_art::tree_widget &w,
     878              :                             const dump_widget_info &dwi) const final override;
     879              : 
     880              :   void accept (visitor *v) const final override;
     881              :   bool implicitly_live_p (const svalue_set *,
     882              :                           const region_model *) const final override;
     883              : 
     884              :   bool maybe_get_value_range_1 (value_range &out) const final override;
     885              : 
     886      5111396 :   enum tree_code get_op () const { return m_op; }
     887      3447799 :   const svalue *get_arg0 () const { return m_arg0; }
     888      2259946 :   const svalue *get_arg1 () const { return m_arg1; }
     889              : 
     890              :  private:
     891              :   enum tree_code m_op;
     892              :   const svalue *m_arg0;
     893              :   const svalue *m_arg1;
     894              : };
     895              : 
     896              : } // namespace ana
     897              : 
     898              : template <>
     899              : template <>
     900              : inline bool
     901       287757 : is_a_helper <const binop_svalue *>::test (const svalue *sval)
     902              : {
     903       287757 :   return sval->get_kind () == SK_BINOP;
     904              : }
     905              : 
     906              : template <> struct default_hash_traits<binop_svalue::key_t>
     907              : : public member_function_hash_traits<binop_svalue::key_t>
     908              : {
     909              :   static const bool empty_zero_p = false;
     910              : };
     911              : 
     912              : namespace ana {
     913              : 
     914              : /* Concrete subclass of svalue representing the result of accessing a subregion
     915              :    of another svalue (the value of a component/field of a struct, or an element
     916              :    from an array).  */
     917              : 
     918              : class sub_svalue : public svalue
     919              : {
     920              : public:
     921              :   /* A support class for uniquifying instances of sub_svalue.  */
     922              :   struct key_t
     923              :   {
     924        16198 :     key_t (tree type, const svalue *parent_svalue, const region *subregion)
     925        16198 :     : m_type (type), m_parent_svalue (parent_svalue), m_subregion (subregion)
     926              :     {}
     927              : 
     928       105449 :     hashval_t hash () const
     929              :     {
     930       105449 :       inchash::hash hstate;
     931       105449 :       hstate.add_ptr (m_type);
     932       105449 :       hstate.add_ptr (m_parent_svalue);
     933       105449 :       hstate.add_ptr (m_subregion);
     934       105449 :       return hstate.end ();
     935              :     }
     936              : 
     937       102271 :     bool operator== (const key_t &other) const
     938              :     {
     939       102271 :       return (m_type == other.m_type
     940        57197 :               && m_parent_svalue == other.m_parent_svalue
     941       143549 :               && m_subregion == other.m_subregion);
     942              :     }
     943              : 
     944              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
     945        55504 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
     946       114340 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
     947       461504 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
     948              : 
     949              :     tree m_type;
     950              :     const svalue *m_parent_svalue;
     951              :     const region *m_subregion;
     952              :   };
     953              :   sub_svalue (symbol::id_t id, tree type, const svalue *parent_svalue,
     954              :               const region *subregion);
     955              : 
     956      1409542 :   enum svalue_kind get_kind () const final override { return SK_SUB; }
     957        20340 :   const sub_svalue *dyn_cast_sub_svalue () const final override
     958              :   {
     959        20340 :     return this;
     960              :   }
     961              : 
     962              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
     963              : 
     964              :   void
     965              :   print_dump_widget_label (pretty_printer *pp) const final override;
     966              :   void
     967              :   add_dump_widget_children (text_art::tree_widget &w,
     968              :                             const dump_widget_info &dwi) const final override;
     969              : 
     970              :   void accept (visitor *v) const final override;
     971              :   bool implicitly_live_p (const svalue_set *,
     972              :                           const region_model *) const final override;
     973              : 
     974      1018554 :   const svalue *get_parent () const { return m_parent_svalue; }
     975       808101 :   const region *get_subregion () const { return m_subregion; }
     976              : 
     977              :  private:
     978              :   const svalue *m_parent_svalue;
     979              :   const region *m_subregion;
     980              : };
     981              : 
     982              : } // namespace ana
     983              : 
     984              : template <>
     985              : template <>
     986              : inline bool
     987            0 : is_a_helper <const sub_svalue *>::test (const svalue *sval)
     988              : {
     989            0 :   return sval->get_kind () == SK_SUB;
     990              : }
     991              : 
     992              : template <> struct default_hash_traits<sub_svalue::key_t>
     993              : : public member_function_hash_traits<sub_svalue::key_t>
     994              : {
     995              :   static const bool empty_zero_p = false;
     996              : };
     997              : 
     998              : namespace ana {
     999              : 
    1000              : /* Concrete subclass of svalue representing repeating an inner svalue
    1001              :    (possibly not a whole number of times) to fill a larger region of
    1002              :    type TYPE of size OUTER_SIZE bytes.  */
    1003              : 
    1004              : class repeated_svalue : public svalue
    1005              : {
    1006              : public:
    1007              :   /* A support class for uniquifying instances of repeated_svalue.  */
    1008              :   struct key_t
    1009              :   {
    1010         2016 :     key_t (tree type,
    1011              :            const svalue *outer_size,
    1012              :            const svalue *inner_svalue)
    1013         2016 :     : m_type (type), m_outer_size (outer_size), m_inner_svalue (inner_svalue)
    1014              :     {}
    1015              : 
    1016         9507 :     hashval_t hash () const
    1017              :     {
    1018         9507 :       inchash::hash hstate;
    1019         9507 :       hstate.add_ptr (m_type);
    1020         9507 :       hstate.add_ptr (m_outer_size);
    1021         9507 :       hstate.add_ptr (m_inner_svalue);
    1022         9507 :       return hstate.end ();
    1023              :     }
    1024              : 
    1025         8156 :     bool operator== (const key_t &other) const
    1026              :     {
    1027         8156 :       return (m_type == other.m_type
    1028         8039 :               && m_outer_size == other.m_outer_size
    1029         9724 :               && m_inner_svalue == other.m_inner_svalue);
    1030              :     }
    1031              : 
    1032              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
    1033        52938 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
    1034        10196 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
    1035       148138 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
    1036              : 
    1037              :     tree m_type;
    1038              :     const svalue *m_outer_size;
    1039              :     const svalue *m_inner_svalue;
    1040              :   };
    1041              :   repeated_svalue (symbol::id_t id,
    1042              :                    tree type,
    1043              :                    const svalue *outer_size,
    1044              :                    const svalue *inner_svalue);
    1045              : 
    1046       149055 :   enum svalue_kind get_kind () const final override { return SK_REPEATED; }
    1047          100 :   const repeated_svalue *dyn_cast_repeated_svalue () const final override
    1048              :   {
    1049          100 :     return this;
    1050              :   }
    1051              : 
    1052              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1053              : 
    1054              :   void
    1055              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1056              :   void
    1057              :   add_dump_widget_children (text_art::tree_widget &w,
    1058              :                             const dump_widget_info &dwi) const final override;
    1059              : 
    1060              :   void accept (visitor *v) const final override;
    1061              : 
    1062           54 :   const svalue *get_outer_size () const { return m_outer_size; }
    1063          449 :   const svalue *get_inner_svalue () const { return m_inner_svalue; }
    1064              : 
    1065              :   bool all_zeroes_p () const final override;
    1066              : 
    1067              :   const svalue *
    1068              :   maybe_fold_bits_within (tree type,
    1069              :                           const bit_range &subrange,
    1070              :                           region_model_manager *mgr) const final override;
    1071              : 
    1072              :  private:
    1073              :   const svalue *m_outer_size;
    1074              :   const svalue *m_inner_svalue;
    1075              : };
    1076              : 
    1077              : } // namespace ana
    1078              : 
    1079              : template <>
    1080              : template <>
    1081              : inline bool
    1082           42 : is_a_helper <const repeated_svalue *>::test (const svalue *sval)
    1083              : {
    1084           42 :   return sval->get_kind () == SK_REPEATED;
    1085              : }
    1086              : 
    1087              : template <> struct default_hash_traits<repeated_svalue::key_t>
    1088              : : public member_function_hash_traits<repeated_svalue::key_t>
    1089              : {
    1090              :   static const bool empty_zero_p = false;
    1091              : };
    1092              : 
    1093              : namespace ana {
    1094              : 
    1095              : /* A range of bits/bytes within another svalue
    1096              :    e.g. bytes 5-39 of INITIAL_SVALUE(R).
    1097              :    These can be generated for prefixes and suffixes when part of a binding
    1098              :    is clobbered, so that we don't lose too much information.  */
    1099              : 
    1100              : class bits_within_svalue : public svalue
    1101              : {
    1102              : public:
    1103              :   /* A support class for uniquifying instances of bits_within_svalue.  */
    1104              :   struct key_t
    1105              :   {
    1106         1511 :     key_t (tree type,
    1107              :            const bit_range &bits,
    1108              :            const svalue *inner_svalue)
    1109         1511 :     : m_type (type), m_bits (bits), m_inner_svalue (inner_svalue)
    1110              :     {}
    1111              : 
    1112         9723 :     hashval_t hash () const
    1113              :     {
    1114         9723 :       inchash::hash hstate;
    1115         9723 :       hstate.add_ptr (m_type);
    1116         9723 :       hstate.add_ptr (m_inner_svalue);
    1117         9723 :       return hstate.end ();
    1118              :     }
    1119              : 
    1120        10161 :     bool operator== (const key_t &other) const
    1121              :     {
    1122        10161 :       return (m_type == other.m_type
    1123         8505 :               && m_bits == other.m_bits
    1124        11539 :               && m_inner_svalue == other.m_inner_svalue);
    1125              :     }
    1126              : 
    1127              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
    1128        53844 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
    1129        15467 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
    1130       157729 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
    1131              : 
    1132              :     tree m_type;
    1133              :     bit_range m_bits;
    1134              :     const svalue *m_inner_svalue;
    1135              :   };
    1136              :   bits_within_svalue (symbol::id_t id,
    1137              :                       tree type,
    1138              :                       const bit_range &bits,
    1139              :                       const svalue *inner_svalue);
    1140              : 
    1141       180820 :   enum svalue_kind get_kind () const final override { return SK_BITS_WITHIN; }
    1142              :   const bits_within_svalue *
    1143            0 :   dyn_cast_bits_within_svalue () const final override
    1144              :   {
    1145            0 :     return this;
    1146              :   }
    1147              : 
    1148              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1149              : 
    1150              :   void
    1151              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1152              :   void
    1153              :   add_dump_widget_children (text_art::tree_widget &w,
    1154              :                             const dump_widget_info &dwi) const final override;
    1155              : 
    1156              :   void accept (visitor *v) const final override;
    1157              :   bool implicitly_live_p (const svalue_set *,
    1158              :                           const region_model *) const final override;
    1159              : 
    1160          451 :   const bit_range &get_bits () const { return m_bits; }
    1161           78 :   const svalue *get_inner_svalue () const { return m_inner_svalue; }
    1162              : 
    1163              :   const svalue *
    1164              :   maybe_fold_bits_within (tree type,
    1165              :                           const bit_range &subrange,
    1166              :                           region_model_manager *mgr) const final override;
    1167              : 
    1168              :  private:
    1169              :   const bit_range m_bits;
    1170              :   const svalue *m_inner_svalue;
    1171              : };
    1172              : 
    1173              : } // namespace ana
    1174              : 
    1175              : template <>
    1176              : template <>
    1177              : inline bool
    1178            0 : is_a_helper <const bits_within_svalue *>::test (const svalue *sval)
    1179              : {
    1180            0 :   return sval->get_kind () == SK_BITS_WITHIN;
    1181              : }
    1182              : 
    1183              : template <> struct default_hash_traits<bits_within_svalue::key_t>
    1184              : : public member_function_hash_traits<bits_within_svalue::key_t>
    1185              : {
    1186              :   static const bool empty_zero_p = false;
    1187              : };
    1188              : 
    1189              : namespace ana {
    1190              : 
    1191              : /* Concrete subclass of svalue: decorate another svalue,
    1192              :    so that the resulting svalue can be identified as being
    1193              :    "interesting to control flow".
    1194              :    For example, consider the return value from setjmp.  We
    1195              :    don't want to merge states in which the result is 0 with
    1196              :    those in which the result is non-zero.  By using an
    1197              :    unmergeable_svalue for the result, we can inhibit such merges
    1198              :    and have separate exploded nodes for those states, keeping
    1199              :    the first and second returns from setjmp distinct in the exploded
    1200              :    graph.  */
    1201              : 
    1202              : class unmergeable_svalue : public svalue
    1203              : {
    1204              : public:
    1205          210 :   unmergeable_svalue (symbol::id_t id, const svalue *arg)
    1206          210 :   : svalue (complexity (arg), id, arg->get_type ()), m_arg (arg)
    1207              :   {
    1208          210 :   }
    1209              : 
    1210        22648 :   enum svalue_kind get_kind () const final override { return SK_UNMERGEABLE; }
    1211              :   const unmergeable_svalue *
    1212         4370 :   dyn_cast_unmergeable_svalue () const final override { return this; }
    1213              : 
    1214              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1215              : 
    1216              :   void
    1217              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1218              :   void
    1219              :   add_dump_widget_children (text_art::tree_widget &w,
    1220              :                             const dump_widget_info &dwi) const final override;
    1221              : 
    1222              :   void accept (visitor *v) const final override;
    1223              :   bool implicitly_live_p (const svalue_set *,
    1224              :                           const region_model *) const final override;
    1225              : 
    1226         5264 :   const svalue *get_arg () const { return m_arg; }
    1227              : 
    1228              :  private:
    1229              :   const svalue *m_arg;
    1230              : };
    1231              : 
    1232              : } // namespace ana
    1233              : 
    1234              : template <>
    1235              : template <>
    1236              : inline bool
    1237            0 : is_a_helper <const unmergeable_svalue *>::test (const svalue *sval)
    1238              : {
    1239            0 :   return sval->get_kind () == SK_UNMERGEABLE;
    1240              : }
    1241              : 
    1242              : namespace ana {
    1243              : 
    1244              : /* Concrete subclass of svalue for use in selftests, where
    1245              :    we want a specific but unknown svalue.
    1246              :    Unlike other svalue subclasses these aren't managed by
    1247              :    region_model_manager.  */
    1248              : 
    1249           28 : class placeholder_svalue : public svalue
    1250              : {
    1251              : public:
    1252        12449 :   placeholder_svalue (symbol::id_t id, tree type, const char *name)
    1253        12449 :   : svalue (complexity (1, 1), id, type), m_name (name)
    1254              :   {
    1255              :   }
    1256              : 
    1257        33898 :   enum svalue_kind get_kind () const final override { return SK_PLACEHOLDER; }
    1258              : 
    1259              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1260              : 
    1261              :   void
    1262              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1263              :   void
    1264              :   add_dump_widget_children (text_art::tree_widget &w,
    1265              :                             const dump_widget_info &dwi) const final override;
    1266              : 
    1267              :   void accept (visitor *v) const final override;
    1268              : 
    1269            0 :   const char *get_name () const { return m_name; }
    1270              : 
    1271              :  private:
    1272              :   const char *m_name;
    1273              : };
    1274              : 
    1275              : } // namespace ana
    1276              : 
    1277              : template <>
    1278              : template <>
    1279              : inline bool
    1280              : is_a_helper <const placeholder_svalue *>::test (const svalue *sval)
    1281              : {
    1282              :   return sval->get_kind () == SK_PLACEHOLDER;
    1283              : }
    1284              : 
    1285              : namespace ana {
    1286              : 
    1287              : /* Concrete subclass of svalue representing a "widening" seen when merging
    1288              :    states, widening from a base value to {base value, iter value} and thus
    1289              :    representing a possible fixed point in an iteration from the base to
    1290              :    +ve infinity, or -ve infinity, and thus useful for representing a value
    1291              :    within a loop.
    1292              :    We also need to capture the program_point at which the merger happens,
    1293              :    so that distinguish between different iterators, and thus handle
    1294              :    nested loops.  (currently we capture the function_point instead, for
    1295              :    simplicity of hashing).  */
    1296              : 
    1297              : class widening_svalue : public svalue
    1298              : {
    1299              : public:
    1300              :   /* A support class for uniquifying instances of widening_svalue.  */
    1301              :   struct key_t
    1302              :   {
    1303         5772 :     key_t (tree type, const supernode *snode,
    1304              :            const svalue *base_sval, const svalue *iter_sval)
    1305         5772 :     : m_type (type), m_snode (snode),
    1306         5772 :       m_base_sval (base_sval), m_iter_sval (iter_sval)
    1307              :     {}
    1308              : 
    1309        35820 :     hashval_t hash () const
    1310              :     {
    1311        35820 :       inchash::hash hstate;
    1312        35820 :       hstate.add_ptr (m_base_sval);
    1313        35820 :       hstate.add_ptr (m_iter_sval);
    1314        35820 :       return hstate.end ();
    1315              :     }
    1316              : 
    1317        65594 :     bool operator== (const key_t &other) const
    1318              :     {
    1319        65594 :       return (m_type == other.m_type
    1320        54529 :               && m_snode == other.m_snode
    1321         4400 :               && m_base_sval == other.m_base_sval
    1322        69176 :               && m_iter_sval == other.m_iter_sval);
    1323              :     }
    1324              : 
    1325              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
    1326        54344 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
    1327        90881 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
    1328       356802 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
    1329              : 
    1330              :     tree m_type;
    1331              :     const supernode *m_snode;
    1332              :     const svalue *m_base_sval;
    1333              :     const svalue *m_iter_sval;
    1334              :   };
    1335              : 
    1336              :   enum direction_t
    1337              :     {
    1338              :      DIR_ASCENDING,
    1339              :      DIR_DESCENDING,
    1340              :      DIR_UNKNOWN
    1341              :     };
    1342              : 
    1343         2361 :   widening_svalue (symbol::id_t id, tree type, const supernode *snode,
    1344              :                    const svalue *base_sval, const svalue *iter_sval)
    1345         2361 :   : svalue (complexity::from_pair (base_sval->get_complexity (),
    1346              :                                    iter_sval->get_complexity ()),
    1347              :             id,
    1348              :             type),
    1349         2361 :     m_snode (snode),
    1350         2361 :     m_base_sval (base_sval), m_iter_sval (iter_sval)
    1351              :   {
    1352         2361 :     gcc_assert (base_sval->can_have_associated_state_p ());
    1353         2361 :     gcc_assert (iter_sval->can_have_associated_state_p ());
    1354         2361 :   }
    1355              : 
    1356      1065514 :   enum svalue_kind get_kind () const final override { return SK_WIDENING; }
    1357        18800 :   const widening_svalue *dyn_cast_widening_svalue () const final override
    1358              :   {
    1359        18800 :     return this;
    1360              :   }
    1361              : 
    1362              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1363              : 
    1364              :   void
    1365              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1366              :   void
    1367              :   add_dump_widget_children (text_art::tree_widget &w,
    1368              :                             const dump_widget_info &dwi) const final override;
    1369              : 
    1370              :   void accept (visitor *v) const final override;
    1371              : 
    1372         3595 :   const supernode *get_snode () const { return m_snode; }
    1373        14202 :   const svalue *get_base_svalue () const { return m_base_sval; }
    1374         4813 :   const svalue *get_iter_svalue () const { return m_iter_sval; }
    1375              : 
    1376              :   enum direction_t get_direction () const;
    1377              : 
    1378              :   tristate eval_condition_without_cm (enum tree_code op,
    1379              :                                       tree rhs_cst) const;
    1380              : 
    1381              :  private:
    1382              :   const supernode *m_snode;
    1383              :   const svalue *m_base_sval;
    1384              :   const svalue *m_iter_sval;
    1385              : };
    1386              : 
    1387              : } // namespace ana
    1388              : 
    1389              : template <>
    1390              : template <>
    1391              : inline bool
    1392          454 : is_a_helper <const widening_svalue *>::test (const svalue *sval)
    1393              : {
    1394          454 :   return sval->get_kind () == SK_WIDENING;
    1395              : }
    1396              : 
    1397              : template <> struct default_hash_traits<widening_svalue::key_t>
    1398              : : public member_function_hash_traits<widening_svalue::key_t>
    1399              : {
    1400              :   static const bool empty_zero_p = false;
    1401              : };
    1402              : 
    1403              : namespace ana {
    1404              : 
    1405              : /* Concrete subclass of svalue representing a mapping of bit-ranges
    1406              :    to svalues, analogous to a cluster within the store, but without
    1407              :    symbolic keys.
    1408              : 
    1409              :    This is for use in places where we want to represent a store-like
    1410              :    mapping, but are required to use an svalue, such as when handling
    1411              :    compound assignments and compound return values.
    1412              : 
    1413              :    Instances of this class shouldn't be bound as-is into the store;
    1414              :    instead they should be unpacked.  Similarly, they should not be
    1415              :    nested.  */
    1416              : 
    1417              : class compound_svalue : public svalue
    1418              : {
    1419              : public:
    1420              :   typedef concrete_binding_map::const_iterator const_iterator_t;
    1421              :   typedef concrete_binding_map::iterator iterator_t;
    1422              : 
    1423              :   /* A support class for uniquifying instances of compound_svalue.
    1424              :      Note that to avoid copies, keys store pointers to
    1425              :      concrete_binding_map, rather than the maps themselves.  */
    1426              :   struct key_t
    1427              :   {
    1428         4631 :     key_t (tree type, const concrete_binding_map *map_ptr)
    1429         3970 :     : m_type (type), m_map_ptr (map_ptr)
    1430              :     {}
    1431              : 
    1432        18404 :     hashval_t hash () const
    1433              :     {
    1434        18404 :       inchash::hash hstate;
    1435        18404 :       hstate.add_ptr (m_type);
    1436              :       //hstate.add_ptr (m_map_ptr); // TODO
    1437        18404 :       return hstate.end ();
    1438              :     }
    1439              : 
    1440        21833 :     bool operator== (const key_t &other) const
    1441              :     {
    1442        21833 :       return (m_type == other.m_type
    1443        21833 :               && *m_map_ptr == *other.m_map_ptr);
    1444              :     }
    1445              : 
    1446              :     void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
    1447        52723 :     void mark_empty () { m_type = reinterpret_cast<tree> (2); }
    1448        33026 :     bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
    1449       210021 :     bool is_empty () const { return m_type == reinterpret_cast<tree> (2); }
    1450              : 
    1451              :     tree m_type;
    1452              :     const concrete_binding_map *m_map_ptr;
    1453              :   };
    1454              : 
    1455              :   compound_svalue (symbol::id_t id, tree type, concrete_binding_map &&map);
    1456              :   compound_svalue (symbol::id_t id, tree type, const concrete_binding_map &map);
    1457              : 
    1458         6943 :   enum svalue_kind get_kind () const final override { return SK_COMPOUND; }
    1459         4209 :   const compound_svalue *dyn_cast_compound_svalue () const final override
    1460              :   {
    1461         4209 :     return this;
    1462              :   }
    1463              : 
    1464              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1465              : 
    1466              :   void
    1467              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1468              :   void
    1469              :   add_dump_widget_children (text_art::tree_widget &w,
    1470              :                             const dump_widget_info &dwi) const final override;
    1471              : 
    1472              :   void accept (visitor *v) const final override;
    1473              : 
    1474              :   const concrete_binding_map &
    1475          137 :   get_concrete_bindings () const { return m_map; }
    1476              : 
    1477         4400 :   const_iterator_t begin () const { return m_map.begin (); }
    1478        14563 :   const_iterator_t end () const { return m_map.end (); }
    1479          661 :   iterator_t begin () { return m_map.begin (); }
    1480          661 :   iterator_t end () { return m_map.end (); }
    1481              : 
    1482          661 :   struct key_t make_key () const
    1483              :   {
    1484          661 :     return key_t (get_type (), &m_map);
    1485              :   }
    1486              : 
    1487              :   const svalue *
    1488              :   maybe_fold_bits_within (tree type,
    1489              :                           const bit_range &subrange,
    1490              :                           region_model_manager *mgr) const final override;
    1491              : 
    1492              :  private:
    1493              :   concrete_binding_map m_map;
    1494              : };
    1495              : 
    1496              : } // namespace ana
    1497              : 
    1498              : template <>
    1499              : template <>
    1500              : inline bool
    1501          295 : is_a_helper <const compound_svalue *>::test (const svalue *sval)
    1502              : {
    1503          295 :   return sval->get_kind () == SK_COMPOUND;
    1504              : }
    1505              : 
    1506              : template <> struct default_hash_traits<compound_svalue::key_t>
    1507              : : public member_function_hash_traits<compound_svalue::key_t>
    1508              : {
    1509              :   static const bool empty_zero_p = false;
    1510              : };
    1511              : 
    1512              : namespace ana {
    1513              : 
    1514              : /* A bundle of state for purging information from a program_state about
    1515              :    a conjured_svalue.  We pass this whenever calling
    1516              :    get_or_create_conjured_svalue, so that if the program_state already
    1517              :    has information about this conjured_svalue on an execution path, we
    1518              :    can purge that information, to avoid the analyzer confusing the two
    1519              :    values as being the same.  */
    1520              : 
    1521              : class conjured_purge
    1522              : {
    1523              : public:
    1524        42573 :   conjured_purge (region_model *model, region_model_context *ctxt)
    1525        42425 :   : m_model (model), m_ctxt (ctxt)
    1526              :   {
    1527              :   }
    1528              :   void purge (const conjured_svalue *sval) const;
    1529              : 
    1530              : private:
    1531              :   region_model *m_model;
    1532              :   region_model_context *m_ctxt;
    1533              : };
    1534              : 
    1535              : /* A defined value arising from a statement, where we want to identify a
    1536              :    particular unknown value, rather than resorting to the unknown_value
    1537              :    singleton, so that the value can have sm-state.
    1538              : 
    1539              :    Comparisons of variables that share the same conjured_svalue are known
    1540              :    to be equal, even if we don't know what the value is.
    1541              : 
    1542              :    For example, this is used for the values of regions that may have been
    1543              :    touched when calling an unknown function.
    1544              : 
    1545              :    The value captures a region as well as a stmt in order to avoid falsely
    1546              :    aliasing the various values that could arise in one statement.  For
    1547              :    example, after:
    1548              :       unknown_fn (&a, &b);
    1549              :    we want values to clobber a and b with, but we don't want to use the
    1550              :    same value, or it would falsely implicitly assume that a == b.  */
    1551              : 
    1552              : class conjured_svalue : public svalue
    1553              : {
    1554              : public:
    1555              :   /* A support class for uniquifying instances of conjured_svalue.  */
    1556              :   struct key_t
    1557              :   {
    1558        56892 :     key_t (tree type, const gimple *stmt, const region *id_reg, unsigned idx)
    1559        56892 :     : m_type (type), m_stmt (stmt), m_id_reg (id_reg), m_idx (idx)
    1560              :     {}
    1561              : 
    1562       498130 :     hashval_t hash () const
    1563              :     {
    1564       498130 :       inchash::hash hstate;
    1565       498130 :       hstate.add_ptr (m_type);
    1566       498130 :       hstate.add_ptr (m_stmt);
    1567       498130 :       hstate.add_ptr (m_id_reg);
    1568       498130 :       return hstate.end ();
    1569              :     }
    1570              : 
    1571       500685 :     bool operator== (const key_t &other) const
    1572              :     {
    1573       500685 :       return (m_type == other.m_type
    1574       219894 :               && m_stmt == other.m_stmt
    1575        51287 :               && m_id_reg == other.m_id_reg
    1576       541220 :               && m_idx == other.m_idx);
    1577              :     }
    1578              : 
    1579              :     /* Use m_stmt to mark empty/deleted, as m_type can be NULL_TREE for
    1580              :        legitimate instances.  */
    1581              :     void mark_deleted () { m_stmt = reinterpret_cast<const gimple *> (1); }
    1582            0 :     void mark_empty () { m_stmt = nullptr; }
    1583       597447 :     bool is_deleted () const
    1584              :     {
    1585       597447 :       return m_stmt == reinterpret_cast<const gimple *> (1);
    1586              :     }
    1587      1972289 :     bool is_empty () const { return m_stmt == nullptr; }
    1588              : 
    1589              :     tree m_type;
    1590              :     const gimple *m_stmt;
    1591              :     const region *m_id_reg;
    1592              :     unsigned m_idx;
    1593              :   };
    1594              : 
    1595        26691 :   conjured_svalue (symbol::id_t id, tree type, const gimple *stmt,
    1596              :                    const region *id_reg, unsigned idx)
    1597        26691 :   : svalue (complexity (id_reg), id, type),
    1598        26691 :     m_stmt (stmt), m_id_reg (id_reg), m_idx (idx)
    1599              :   {
    1600        26691 :     gcc_assert (m_stmt != nullptr);
    1601        26691 :   }
    1602              : 
    1603     21990873 :   enum svalue_kind get_kind () const final override { return SK_CONJURED; }
    1604            0 :   const conjured_svalue *dyn_cast_conjured_svalue () const final override
    1605              :   {
    1606            0 :     return this;
    1607              :   }
    1608              : 
    1609              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1610              : 
    1611              :   void
    1612              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1613              :   void
    1614              :   add_dump_widget_children (text_art::tree_widget &w,
    1615              :                             const dump_widget_info &dwi) const final override;
    1616              : 
    1617              :   void accept (visitor *v) const final override;
    1618              : 
    1619      3183157 :   const gimple *get_stmt () const { return m_stmt; }
    1620        74316 :   const region *get_id_region () const { return m_id_reg; }
    1621              :   bool lhs_value_p () const;
    1622              : 
    1623              :  private:
    1624              :   const gimple *m_stmt;
    1625              :   const region *m_id_reg;
    1626              :   unsigned m_idx;
    1627              : };
    1628              : 
    1629              : } // namespace ana
    1630              : 
    1631              : template <>
    1632              : template <>
    1633              : inline bool
    1634              : is_a_helper <const conjured_svalue *>::test (const svalue *sval)
    1635              : {
    1636              :   return sval->get_kind () == SK_CONJURED;
    1637              : }
    1638              : 
    1639              : template <> struct default_hash_traits<conjured_svalue::key_t>
    1640              : : public member_function_hash_traits<conjured_svalue::key_t>
    1641              : {
    1642              :   static const bool empty_zero_p = true;
    1643              : };
    1644              : 
    1645              : namespace ana {
    1646              : 
    1647              : /* An output from a deterministic asm stmt, where we want to identify a
    1648              :    particular unknown value, rather than resorting to the unknown_value
    1649              :    singleton.
    1650              : 
    1651              :    Comparisons of variables that share the same asm_output_svalue are known
    1652              :    to be equal, even if we don't know what the value is.  */
    1653              : 
    1654              : class asm_output_svalue : public svalue
    1655              : {
    1656              : public:
    1657              :   /* Imposing an upper limit and using a (small) array allows key_t
    1658              :      to avoid memory management.  */
    1659              :   static const unsigned MAX_INPUTS = 2;
    1660              : 
    1661              :   /* A support class for uniquifying instances of asm_output_svalue.  */
    1662              :   struct key_t
    1663              :   {
    1664          358 :     key_t (tree type,
    1665              :            const char *asm_string,
    1666              :            unsigned output_idx,
    1667              :            const vec<const svalue *> &inputs)
    1668          358 :     : m_type (type), m_asm_string (asm_string), m_output_idx (output_idx),
    1669          358 :       m_num_inputs (inputs.length ())
    1670              :     {
    1671          358 :       gcc_assert (inputs.length () <= MAX_INPUTS);
    1672          958 :       for (unsigned i = 0; i < m_num_inputs; i++)
    1673          600 :         m_input_arr[i] = inputs[i];
    1674          358 :     }
    1675              : 
    1676         1500 :     hashval_t hash () const
    1677              :     {
    1678         1500 :       inchash::hash hstate;
    1679         1500 :       hstate.add_ptr (m_type);
    1680              :       /* We don't bother hashing m_asm_str.  */
    1681         1500 :       hstate.add_int (m_output_idx);
    1682         4079 :       for (unsigned i = 0; i < m_num_inputs; i++)
    1683         2579 :         hstate.add_ptr (m_input_arr[i]);
    1684         1500 :       return hstate.end ();
    1685              :     }
    1686              : 
    1687         1059 :     bool operator== (const key_t &other) const
    1688              :     {
    1689         1059 :       if (!(m_type == other.m_type
    1690          850 :             && 0 == (strcmp (m_asm_string, other.m_asm_string))
    1691          755 :             && m_output_idx == other.m_output_idx
    1692          585 :             && m_num_inputs == other.m_num_inputs))
    1693              :         return false;
    1694         1031 :       for (unsigned i = 0; i < m_num_inputs; i++)
    1695          865 :         if (m_input_arr[i] != other.m_input_arr[i])
    1696              :           return false;
    1697              :       return true;
    1698              :     }
    1699              : 
    1700              :     /* Use m_asm_string to mark empty/deleted, as m_type can be NULL_TREE for
    1701              :        legitimate instances.  */
    1702              :     void mark_deleted () { m_asm_string = reinterpret_cast<const char *> (1); }
    1703            0 :     void mark_empty () { m_asm_string = nullptr; }
    1704         1559 :     bool is_deleted () const
    1705              :     {
    1706         1559 :       return m_asm_string == reinterpret_cast<const char *> (1);
    1707              :     }
    1708       113486 :     bool is_empty () const { return m_asm_string == nullptr; }
    1709              : 
    1710              :     tree m_type;
    1711              :     const char *m_asm_string;
    1712              :     unsigned m_output_idx;
    1713              :     unsigned m_num_inputs;
    1714              :     const svalue *m_input_arr[MAX_INPUTS];
    1715              :   };
    1716              : 
    1717          192 :   asm_output_svalue (symbol::id_t id,
    1718              :                      tree type,
    1719              :                      const char *asm_string,
    1720              :                      unsigned output_idx,
    1721              :                      unsigned num_outputs,
    1722              :                      const vec<const svalue *> &inputs)
    1723          192 :   : svalue (complexity::from_vec_svalue (inputs), id, type),
    1724          192 :     m_asm_string (asm_string),
    1725          192 :     m_output_idx (output_idx),
    1726          192 :     m_num_outputs (num_outputs),
    1727          192 :     m_num_inputs (inputs.length ())
    1728              :   {
    1729          192 :     gcc_assert (inputs.length () <= MAX_INPUTS);
    1730          488 :     for (unsigned i = 0; i < m_num_inputs; i++)
    1731          296 :       m_input_arr[i] = inputs[i];
    1732          192 :   }
    1733              : 
    1734        18478 :   enum svalue_kind get_kind () const final override { return SK_ASM_OUTPUT; }
    1735              :   const asm_output_svalue *
    1736            0 :   dyn_cast_asm_output_svalue () const final override
    1737              :   {
    1738            0 :     return this;
    1739              :   }
    1740              : 
    1741              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1742              : 
    1743              :   void
    1744              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1745              :   void
    1746              :   add_dump_widget_children (text_art::tree_widget &w,
    1747              :                             const dump_widget_info &dwi) const final override;
    1748              : 
    1749              :   void accept (visitor *v) const final override;
    1750              : 
    1751          102 :   const char *get_asm_string () const { return m_asm_string; }
    1752          154 :   unsigned get_output_idx () const { return m_output_idx; }
    1753           78 :   unsigned get_num_outputs () const { return m_num_outputs; }
    1754          312 :   unsigned get_num_inputs () const { return m_num_inputs; }
    1755          164 :   const svalue *get_input (unsigned idx) const { return m_input_arr[idx]; }
    1756              : 
    1757              :  private:
    1758              :   void dump_input (pretty_printer *pp,
    1759              :                    unsigned input_idx,
    1760              :                    const svalue *sval,
    1761              :                    bool simple) const;
    1762              :   unsigned input_idx_to_asm_idx (unsigned input_idx) const;
    1763              : 
    1764              :   const char *m_asm_string;
    1765              :   unsigned m_output_idx;
    1766              : 
    1767              :   /* We capture this so that we can offset the input indices
    1768              :      to match the %0, %1, %2 in the asm_string when dumping.  */
    1769              :   unsigned m_num_outputs;
    1770              : 
    1771              :   unsigned m_num_inputs;
    1772              :   const svalue *m_input_arr[MAX_INPUTS];
    1773              : };
    1774              : 
    1775              : } // namespace ana
    1776              : 
    1777              : template <>
    1778              : template <>
    1779              : inline bool
    1780            8 : is_a_helper <const asm_output_svalue *>::test (const svalue *sval)
    1781              : {
    1782            8 :   return sval->get_kind () == SK_ASM_OUTPUT;
    1783              : }
    1784              : 
    1785              : template <> struct default_hash_traits<asm_output_svalue::key_t>
    1786              : : public member_function_hash_traits<asm_output_svalue::key_t>
    1787              : {
    1788              :   static const bool empty_zero_p = true;
    1789              : };
    1790              : 
    1791              : namespace ana {
    1792              : 
    1793              : /* The return value from a function with __attribute((const)) for given
    1794              :    inputs, provided that we don't have too many inputs, and all of them
    1795              :    are deterministic.
    1796              : 
    1797              :    Comparisons of variables that share the same const_fn_result_svalue are known
    1798              :    to be equal, even if we don't know what the value is.  */
    1799              : 
    1800              : class const_fn_result_svalue : public svalue
    1801              : {
    1802              : public:
    1803              :   /* Imposing an upper limit and using a (small) array allows key_t
    1804              :      to avoid memory management.  */
    1805              :   static const unsigned MAX_INPUTS = 2;
    1806              : 
    1807              :   /* A support class for uniquifying instances of const_fn_result_svalue.  */
    1808              :   struct key_t
    1809              :   {
    1810          955 :     key_t (tree type,
    1811              :            tree fndecl,
    1812              :            const vec<const svalue *> &inputs)
    1813          955 :     : m_type (type), m_fndecl (fndecl),
    1814          955 :       m_num_inputs (inputs.length ())
    1815              :     {
    1816          955 :       gcc_assert (inputs.length () <= MAX_INPUTS);
    1817         1421 :       for (unsigned i = 0; i < m_num_inputs; i++)
    1818          466 :         m_input_arr[i] = inputs[i];
    1819          955 :     }
    1820              : 
    1821         3113 :     hashval_t hash () const
    1822              :     {
    1823         3113 :       inchash::hash hstate;
    1824         3113 :       hstate.add_ptr (m_type);
    1825         3113 :       hstate.add_ptr (m_fndecl);
    1826         5716 :       for (unsigned i = 0; i < m_num_inputs; i++)
    1827         2603 :         hstate.add_ptr (m_input_arr[i]);
    1828         3113 :       return hstate.end ();
    1829              :     }
    1830              : 
    1831         2317 :     bool operator== (const key_t &other) const
    1832              :     {
    1833         2317 :       if (!(m_type == other.m_type
    1834         2170 :             && m_fndecl == other.m_fndecl
    1835         1534 :             && m_num_inputs == other.m_num_inputs))
    1836              :         return false;
    1837         1930 :       for (unsigned i = 0; i < m_num_inputs; i++)
    1838         1162 :         if (m_input_arr[i] != other.m_input_arr[i])
    1839              :           return false;
    1840              :       return true;
    1841              :     }
    1842              : 
    1843              :     /* Use m_fndecl to mark empty/deleted.  */
    1844              :     void mark_deleted () { m_fndecl = reinterpret_cast<tree> (1); }
    1845            0 :     void mark_empty () { m_fndecl = NULL_TREE; }
    1846         3299 :     bool is_deleted () const
    1847              :     {
    1848         3299 :       return m_fndecl == reinterpret_cast<tree> (1);
    1849              :     }
    1850       122865 :     bool is_empty () const { return m_fndecl == NULL_TREE; }
    1851              : 
    1852              :     tree m_type;
    1853              :     tree m_fndecl;
    1854              :     unsigned m_num_inputs;
    1855              :     const svalue *m_input_arr[MAX_INPUTS];
    1856              :   };
    1857              : 
    1858          187 :   const_fn_result_svalue (symbol::id_t id,
    1859              :                           tree type,
    1860              :                           tree fndecl,
    1861              :                           const vec<const svalue *> &inputs)
    1862          187 :   : svalue (complexity::from_vec_svalue (inputs), id, type),
    1863          187 :     m_fndecl (fndecl),
    1864          187 :     m_num_inputs (inputs.length ())
    1865              :   {
    1866          187 :     gcc_assert (inputs.length () <= MAX_INPUTS);
    1867          359 :     for (unsigned i = 0; i < m_num_inputs; i++)
    1868          172 :       m_input_arr[i] = inputs[i];
    1869          187 :   }
    1870              : 
    1871        39184 :   enum svalue_kind get_kind () const final override
    1872              :   {
    1873        39184 :     return SK_CONST_FN_RESULT;
    1874              :   }
    1875              :   const const_fn_result_svalue *
    1876            0 :   dyn_cast_const_fn_result_svalue () const final override
    1877              :   {
    1878            0 :     return this;
    1879              :   }
    1880              : 
    1881              :   void dump_to_pp (pretty_printer *pp, bool simple) const final override;
    1882              : 
    1883              :   void
    1884              :   print_dump_widget_label (pretty_printer *pp) const final override;
    1885              :   void
    1886              :   add_dump_widget_children (text_art::tree_widget &w,
    1887              :                             const dump_widget_info &dwi) const final override;
    1888              : 
    1889              :   void accept (visitor *v) const final override;
    1890              : 
    1891          146 :   tree get_fndecl () const { return m_fndecl; }
    1892          258 :   unsigned get_num_inputs () const { return m_num_inputs; }
    1893          114 :   const svalue *get_input (unsigned idx) const { return m_input_arr[idx]; }
    1894              : 
    1895              :  private:
    1896              :   void dump_input (pretty_printer *pp,
    1897              :                    unsigned input_idx,
    1898              :                    const svalue *sval,
    1899              :                    bool simple) const;
    1900              : 
    1901              :   tree m_fndecl;
    1902              :   unsigned m_num_inputs;
    1903              :   const svalue *m_input_arr[MAX_INPUTS];
    1904              : };
    1905              : 
    1906              : } // namespace ana
    1907              : 
    1908              : template <>
    1909              : template <>
    1910              : inline bool
    1911            2 : is_a_helper <const const_fn_result_svalue *>::test (const svalue *sval)
    1912              : {
    1913            2 :   return sval->get_kind () == SK_CONST_FN_RESULT;
    1914              : }
    1915              : 
    1916              : template <> struct default_hash_traits<const_fn_result_svalue::key_t>
    1917              : : public member_function_hash_traits<const_fn_result_svalue::key_t>
    1918              : {
    1919              :   static const bool empty_zero_p = true;
    1920              : };
    1921              : 
    1922              : #endif /* GCC_ANALYZER_SVALUE_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.