Home | History | Annotate | Line # | Download | only in analyzer
      1      1.1  mrg /* Classes for representing the state of interest at a given path of analysis.
      2  1.1.1.2  mrg    Copyright (C) 2019-2022 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by David Malcolm <dmalcolm (at) redhat.com>.
      4      1.1  mrg 
      5      1.1  mrg This file is part of GCC.
      6      1.1  mrg 
      7      1.1  mrg GCC is free software; you can redistribute it and/or modify it
      8      1.1  mrg under the terms of the GNU General Public License as published by
      9      1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     10      1.1  mrg any later version.
     11      1.1  mrg 
     12      1.1  mrg GCC is distributed in the hope that it will be useful, but
     13      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15      1.1  mrg General Public License for more details.
     16      1.1  mrg 
     17      1.1  mrg You should have received a copy of the GNU General Public License
     18      1.1  mrg along with GCC; see the file COPYING3.  If not see
     19      1.1  mrg <http://www.gnu.org/licenses/>.  */
     20      1.1  mrg 
     21      1.1  mrg #include "config.h"
     22      1.1  mrg #include "system.h"
     23      1.1  mrg #include "coretypes.h"
     24      1.1  mrg #include "tree.h"
     25      1.1  mrg #include "diagnostic-core.h"
     26      1.1  mrg #include "diagnostic.h"
     27      1.1  mrg #include "function.h"
     28  1.1.1.2  mrg #include "json.h"
     29      1.1  mrg #include "analyzer/analyzer.h"
     30      1.1  mrg #include "analyzer/analyzer-logging.h"
     31      1.1  mrg #include "analyzer/sm.h"
     32      1.1  mrg #include "sbitmap.h"
     33      1.1  mrg #include "bitmap.h"
     34      1.1  mrg #include "tristate.h"
     35      1.1  mrg #include "ordered-hash-map.h"
     36      1.1  mrg #include "selftest.h"
     37  1.1.1.2  mrg #include "analyzer/call-string.h"
     38  1.1.1.2  mrg #include "analyzer/program-point.h"
     39  1.1.1.2  mrg #include "analyzer/store.h"
     40      1.1  mrg #include "analyzer/region-model.h"
     41      1.1  mrg #include "analyzer/program-state.h"
     42      1.1  mrg #include "analyzer/constraint-manager.h"
     43      1.1  mrg #include "alloc-pool.h"
     44      1.1  mrg #include "fibonacci_heap.h"
     45      1.1  mrg #include "shortest-paths.h"
     46      1.1  mrg #include "diagnostic-event-id.h"
     47      1.1  mrg #include "analyzer/pending-diagnostic.h"
     48      1.1  mrg #include "analyzer/diagnostic-manager.h"
     49      1.1  mrg #include "cfg.h"
     50      1.1  mrg #include "basic-block.h"
     51      1.1  mrg #include "gimple.h"
     52      1.1  mrg #include "gimple-iterator.h"
     53      1.1  mrg #include "cgraph.h"
     54      1.1  mrg #include "digraph.h"
     55      1.1  mrg #include "analyzer/supergraph.h"
     56      1.1  mrg #include "analyzer/program-state.h"
     57      1.1  mrg #include "analyzer/exploded-graph.h"
     58      1.1  mrg #include "analyzer/state-purge.h"
     59      1.1  mrg #include "analyzer/analyzer-selftests.h"
     60      1.1  mrg 
     61      1.1  mrg #if ENABLE_ANALYZER
     62      1.1  mrg 
     63      1.1  mrg namespace ana {
     64      1.1  mrg 
     65      1.1  mrg /* class extrinsic_state.  */
     66      1.1  mrg 
     67      1.1  mrg /* Dump a multiline representation of this state to PP.  */
     68      1.1  mrg 
     69      1.1  mrg void
     70      1.1  mrg extrinsic_state::dump_to_pp (pretty_printer *pp) const
     71      1.1  mrg {
     72      1.1  mrg   pp_printf (pp, "extrinsic_state: %i checker(s)\n", get_num_checkers ());
     73      1.1  mrg   unsigned i;
     74      1.1  mrg   state_machine *checker;
     75      1.1  mrg   FOR_EACH_VEC_ELT (m_checkers, i, checker)
     76      1.1  mrg     {
     77      1.1  mrg       pp_printf (pp, "m_checkers[%i]: %qs\n", i, checker->get_name ());
     78      1.1  mrg       checker->dump_to_pp (pp);
     79      1.1  mrg     }
     80      1.1  mrg }
     81      1.1  mrg 
     82      1.1  mrg /* Dump a multiline representation of this state to OUTF.  */
     83      1.1  mrg 
     84      1.1  mrg void
     85      1.1  mrg extrinsic_state::dump_to_file (FILE *outf) const
     86      1.1  mrg {
     87      1.1  mrg   pretty_printer pp;
     88      1.1  mrg   if (outf == stderr)
     89      1.1  mrg     pp_show_color (&pp) = pp_show_color (global_dc->printer);
     90      1.1  mrg   pp.buffer->stream = outf;
     91      1.1  mrg   dump_to_pp (&pp);
     92      1.1  mrg   pp_flush (&pp);
     93      1.1  mrg }
     94      1.1  mrg 
     95      1.1  mrg /* Dump a multiline representation of this state to stderr.  */
     96      1.1  mrg 
     97      1.1  mrg DEBUG_FUNCTION void
     98      1.1  mrg extrinsic_state::dump () const
     99      1.1  mrg {
    100      1.1  mrg   dump_to_file (stderr);
    101      1.1  mrg }
    102      1.1  mrg 
    103  1.1.1.2  mrg /* Return a new json::object of the form
    104  1.1.1.2  mrg    {"checkers"  : array of objects, one for each state_machine}.  */
    105      1.1  mrg 
    106  1.1.1.2  mrg json::object *
    107  1.1.1.2  mrg extrinsic_state::to_json () const
    108  1.1.1.2  mrg {
    109  1.1.1.2  mrg   json::object *ext_state_obj = new json::object ();
    110  1.1.1.2  mrg 
    111  1.1.1.2  mrg   {
    112  1.1.1.2  mrg     json::array *checkers_arr = new json::array ();
    113  1.1.1.2  mrg     unsigned i;
    114  1.1.1.2  mrg     state_machine *sm;
    115  1.1.1.2  mrg     FOR_EACH_VEC_ELT (m_checkers, i, sm)
    116  1.1.1.2  mrg       checkers_arr->append (sm->to_json ());
    117  1.1.1.2  mrg     ext_state_obj->set ("checkers", checkers_arr);
    118  1.1.1.2  mrg   }
    119      1.1  mrg 
    120  1.1.1.2  mrg   return ext_state_obj;
    121  1.1.1.2  mrg }
    122  1.1.1.2  mrg 
    123  1.1.1.2  mrg /* Get the region_model_manager for this extrinsic_state.  */
    124  1.1.1.2  mrg 
    125  1.1.1.2  mrg region_model_manager *
    126  1.1.1.2  mrg extrinsic_state::get_model_manager () const
    127      1.1  mrg {
    128  1.1.1.2  mrg   if (m_engine)
    129  1.1.1.2  mrg     return m_engine->get_model_manager ();
    130  1.1.1.2  mrg   else
    131  1.1.1.2  mrg     return NULL; /* for selftests.  */
    132      1.1  mrg }
    133      1.1  mrg 
    134  1.1.1.2  mrg /* Try to find a state machine named NAME.
    135  1.1.1.2  mrg    If found, return true and write its index to *OUT.
    136  1.1.1.2  mrg    Otherwise return false.  */
    137      1.1  mrg 
    138  1.1.1.2  mrg bool
    139  1.1.1.2  mrg extrinsic_state::get_sm_idx_by_name (const char *name, unsigned *out) const
    140      1.1  mrg {
    141  1.1.1.2  mrg   unsigned i;
    142  1.1.1.2  mrg   state_machine *sm;
    143  1.1.1.2  mrg   FOR_EACH_VEC_ELT (m_checkers, i, sm)
    144  1.1.1.2  mrg     if (0 == strcmp (name, sm->get_name ()))
    145  1.1.1.2  mrg       {
    146  1.1.1.2  mrg 	/* Found NAME.  */
    147  1.1.1.2  mrg 	*out = i;
    148  1.1.1.2  mrg 	return true;
    149  1.1.1.2  mrg       }
    150  1.1.1.2  mrg 
    151  1.1.1.2  mrg   /* NAME not found.  */
    152  1.1.1.2  mrg   return false;
    153      1.1  mrg }
    154      1.1  mrg 
    155  1.1.1.2  mrg /* struct sm_state_map::entry_t.  */
    156      1.1  mrg 
    157  1.1.1.2  mrg int
    158  1.1.1.2  mrg sm_state_map::entry_t::cmp (const entry_t &entry_a, const entry_t &entry_b)
    159  1.1.1.2  mrg {
    160  1.1.1.2  mrg   gcc_assert (entry_a.m_state);
    161  1.1.1.2  mrg   gcc_assert (entry_b.m_state);
    162  1.1.1.2  mrg   if (int cmp_state = ((int)entry_a.m_state->get_id ()
    163  1.1.1.2  mrg 		       - (int)entry_b.m_state->get_id ()))
    164  1.1.1.2  mrg     return cmp_state;
    165  1.1.1.2  mrg   if (entry_a.m_origin && entry_b.m_origin)
    166  1.1.1.2  mrg     return svalue::cmp_ptr (entry_a.m_origin, entry_b.m_origin);
    167  1.1.1.2  mrg   if (entry_a.m_origin)
    168  1.1.1.2  mrg     return 1;
    169  1.1.1.2  mrg   if (entry_b.m_origin)
    170  1.1.1.2  mrg     return -1;
    171  1.1.1.2  mrg   return 0;
    172  1.1.1.2  mrg }
    173      1.1  mrg 
    174  1.1.1.2  mrg /* class sm_state_map.  */
    175  1.1.1.2  mrg 
    176  1.1.1.2  mrg /* sm_state_map's ctor.  */
    177  1.1.1.2  mrg 
    178  1.1.1.2  mrg sm_state_map::sm_state_map (const state_machine &sm)
    179  1.1.1.2  mrg : m_sm (sm), m_map (), m_global_state (sm.get_start_state ())
    180      1.1  mrg {
    181  1.1.1.2  mrg }
    182      1.1  mrg 
    183  1.1.1.2  mrg /* Clone the sm_state_map.  */
    184  1.1.1.2  mrg 
    185  1.1.1.2  mrg sm_state_map *
    186  1.1.1.2  mrg sm_state_map::clone () const
    187  1.1.1.2  mrg {
    188  1.1.1.2  mrg   return new sm_state_map (*this);
    189      1.1  mrg }
    190      1.1  mrg 
    191  1.1.1.2  mrg /* Print this sm_state_map to PP.
    192      1.1  mrg    If MODEL is non-NULL, print representative tree values where
    193      1.1  mrg    available.  */
    194      1.1  mrg 
    195      1.1  mrg void
    196  1.1.1.2  mrg sm_state_map::print (const region_model *model,
    197  1.1.1.2  mrg 		      bool simple, bool multiline,
    198  1.1.1.2  mrg 		      pretty_printer *pp) const
    199      1.1  mrg {
    200      1.1  mrg   bool first = true;
    201  1.1.1.2  mrg   if (!multiline)
    202  1.1.1.2  mrg     pp_string (pp, "{");
    203  1.1.1.2  mrg   if (m_global_state != m_sm.get_start_state ())
    204  1.1.1.2  mrg     {
    205  1.1.1.2  mrg       if (multiline)
    206  1.1.1.2  mrg 	pp_string (pp, "  ");
    207  1.1.1.2  mrg       pp_string (pp, "global: ");
    208  1.1.1.2  mrg       m_global_state->dump_to_pp (pp);
    209  1.1.1.2  mrg       if (multiline)
    210  1.1.1.2  mrg 	pp_newline (pp);
    211      1.1  mrg       first = false;
    212      1.1  mrg     }
    213  1.1.1.2  mrg   auto_vec <const svalue *> keys (m_map.elements ());
    214      1.1  mrg   for (map_t::iterator iter = m_map.begin ();
    215      1.1  mrg        iter != m_map.end ();
    216      1.1  mrg        ++iter)
    217  1.1.1.2  mrg     keys.quick_push ((*iter).first);
    218  1.1.1.2  mrg   keys.qsort (svalue::cmp_ptr_ptr);
    219  1.1.1.2  mrg   unsigned i;
    220  1.1.1.2  mrg   const svalue *sval;
    221  1.1.1.2  mrg   FOR_EACH_VEC_ELT (keys, i, sval)
    222      1.1  mrg     {
    223  1.1.1.2  mrg       if (multiline)
    224  1.1.1.2  mrg 	pp_string (pp, "  ");
    225  1.1.1.2  mrg       else if (!first)
    226      1.1  mrg 	pp_string (pp, ", ");
    227      1.1  mrg       first = false;
    228  1.1.1.2  mrg       if (!flag_dump_noaddr)
    229  1.1.1.2  mrg 	{
    230  1.1.1.2  mrg 	  pp_pointer (pp, sval);
    231  1.1.1.2  mrg 	  pp_string (pp, ": ");
    232  1.1.1.2  mrg 	}
    233  1.1.1.2  mrg       sval->dump_to_pp (pp, simple);
    234      1.1  mrg 
    235  1.1.1.2  mrg       entry_t e = *const_cast <map_t &> (m_map).get (sval);
    236  1.1.1.2  mrg       pp_string (pp, ": ");
    237  1.1.1.2  mrg       e.m_state->dump_to_pp (pp);
    238      1.1  mrg       if (model)
    239  1.1.1.2  mrg 	if (tree rep = model->get_representative_tree (sval))
    240      1.1  mrg 	  {
    241      1.1  mrg 	    pp_string (pp, " (");
    242      1.1  mrg 	    dump_quoted_tree (pp, rep);
    243      1.1  mrg 	    pp_character (pp, ')');
    244      1.1  mrg 	  }
    245  1.1.1.2  mrg       if (e.m_origin)
    246      1.1  mrg 	{
    247      1.1  mrg 	  pp_string (pp, " (origin: ");
    248  1.1.1.2  mrg 	  if (!flag_dump_noaddr)
    249  1.1.1.2  mrg 	    {
    250  1.1.1.2  mrg 	      pp_pointer (pp, e.m_origin);
    251  1.1.1.2  mrg 	      pp_string (pp, ": ");
    252  1.1.1.2  mrg 	    }
    253  1.1.1.2  mrg 	  e.m_origin->dump_to_pp (pp, simple);
    254      1.1  mrg 	  if (model)
    255      1.1  mrg 	    if (tree rep = model->get_representative_tree (e.m_origin))
    256      1.1  mrg 	      {
    257      1.1  mrg 		pp_string (pp, " (");
    258      1.1  mrg 		dump_quoted_tree (pp, rep);
    259      1.1  mrg 		pp_character (pp, ')');
    260      1.1  mrg 	      }
    261      1.1  mrg 	  pp_string (pp, ")");
    262      1.1  mrg 	}
    263  1.1.1.2  mrg       if (multiline)
    264  1.1.1.2  mrg 	pp_newline (pp);
    265      1.1  mrg     }
    266  1.1.1.2  mrg   if (!multiline)
    267  1.1.1.2  mrg     pp_string (pp, "}");
    268      1.1  mrg }
    269      1.1  mrg 
    270  1.1.1.2  mrg /* Dump this object to stderr.  */
    271      1.1  mrg 
    272      1.1  mrg DEBUG_FUNCTION void
    273  1.1.1.2  mrg sm_state_map::dump (bool simple) const
    274      1.1  mrg {
    275      1.1  mrg   pretty_printer pp;
    276  1.1.1.2  mrg   pp_format_decoder (&pp) = default_tree_printer;
    277      1.1  mrg   pp_show_color (&pp) = pp_show_color (global_dc->printer);
    278      1.1  mrg   pp.buffer->stream = stderr;
    279  1.1.1.2  mrg   print (NULL, simple, true, &pp);
    280      1.1  mrg   pp_newline (&pp);
    281      1.1  mrg   pp_flush (&pp);
    282      1.1  mrg }
    283      1.1  mrg 
    284  1.1.1.2  mrg /* Return a new json::object of the form
    285  1.1.1.2  mrg    {"global"  : (optional) value for global state,
    286  1.1.1.2  mrg     SVAL_DESC : value for state}.  */
    287  1.1.1.2  mrg 
    288  1.1.1.2  mrg json::object *
    289  1.1.1.2  mrg sm_state_map::to_json () const
    290  1.1.1.2  mrg {
    291  1.1.1.2  mrg   json::object *map_obj = new json::object ();
    292  1.1.1.2  mrg 
    293  1.1.1.2  mrg   if (m_global_state != m_sm.get_start_state ())
    294  1.1.1.2  mrg     map_obj->set ("global", m_global_state->to_json ());
    295  1.1.1.2  mrg   for (map_t::iterator iter = m_map.begin ();
    296  1.1.1.2  mrg        iter != m_map.end ();
    297  1.1.1.2  mrg        ++iter)
    298  1.1.1.2  mrg     {
    299  1.1.1.2  mrg       const svalue *sval = (*iter).first;
    300  1.1.1.2  mrg       entry_t e = (*iter).second;
    301  1.1.1.2  mrg 
    302  1.1.1.2  mrg       label_text sval_desc = sval->get_desc ();
    303  1.1.1.2  mrg       map_obj->set (sval_desc.m_buffer, e.m_state->to_json ());
    304  1.1.1.2  mrg       sval_desc.maybe_free ();
    305  1.1.1.2  mrg 
    306  1.1.1.2  mrg       /* This doesn't yet JSONify e.m_origin.  */
    307  1.1.1.2  mrg     }
    308  1.1.1.2  mrg   return map_obj;
    309  1.1.1.2  mrg }
    310  1.1.1.2  mrg 
    311      1.1  mrg /* Return true if no states have been set within this map
    312      1.1  mrg    (all expressions are for the start state).  */
    313      1.1  mrg 
    314      1.1  mrg bool
    315      1.1  mrg sm_state_map::is_empty_p () const
    316      1.1  mrg {
    317  1.1.1.2  mrg   return m_map.elements () == 0 && m_global_state == m_sm.get_start_state ();
    318      1.1  mrg }
    319      1.1  mrg 
    320      1.1  mrg /* Generate a hash value for this sm_state_map.  */
    321      1.1  mrg 
    322      1.1  mrg hashval_t
    323      1.1  mrg sm_state_map::hash () const
    324      1.1  mrg {
    325      1.1  mrg   hashval_t result = 0;
    326      1.1  mrg 
    327      1.1  mrg   /* Accumulate the result by xoring a hash for each slot, so that the
    328      1.1  mrg      result doesn't depend on the ordering of the slots in the map.  */
    329      1.1  mrg 
    330      1.1  mrg   for (map_t::iterator iter = m_map.begin ();
    331      1.1  mrg        iter != m_map.end ();
    332      1.1  mrg        ++iter)
    333      1.1  mrg     {
    334      1.1  mrg       inchash::hash hstate;
    335  1.1.1.2  mrg       hstate.add_ptr ((*iter).first);
    336      1.1  mrg       entry_t e = (*iter).second;
    337  1.1.1.2  mrg       hstate.add_int (e.m_state->get_id ());
    338  1.1.1.2  mrg       hstate.add_ptr (e.m_origin);
    339      1.1  mrg       result ^= hstate.end ();
    340      1.1  mrg     }
    341  1.1.1.2  mrg   result ^= m_global_state->get_id ();
    342      1.1  mrg 
    343      1.1  mrg   return result;
    344      1.1  mrg }
    345      1.1  mrg 
    346      1.1  mrg /* Equality operator for sm_state_map.  */
    347      1.1  mrg 
    348      1.1  mrg bool
    349      1.1  mrg sm_state_map::operator== (const sm_state_map &other) const
    350      1.1  mrg {
    351      1.1  mrg   if (m_global_state != other.m_global_state)
    352      1.1  mrg     return false;
    353      1.1  mrg 
    354      1.1  mrg   if (m_map.elements () != other.m_map.elements ())
    355      1.1  mrg     return false;
    356      1.1  mrg 
    357      1.1  mrg   for (map_t::iterator iter = m_map.begin ();
    358      1.1  mrg        iter != m_map.end ();
    359      1.1  mrg        ++iter)
    360      1.1  mrg     {
    361  1.1.1.2  mrg       const svalue *sval = (*iter).first;
    362      1.1  mrg       entry_t e = (*iter).second;
    363  1.1.1.2  mrg       entry_t *other_slot = const_cast <map_t &> (other.m_map).get (sval);
    364      1.1  mrg       if (other_slot == NULL)
    365      1.1  mrg 	return false;
    366      1.1  mrg       if (e != *other_slot)
    367      1.1  mrg 	return false;
    368      1.1  mrg     }
    369      1.1  mrg 
    370      1.1  mrg   gcc_checking_assert (hash () == other.hash ());
    371      1.1  mrg 
    372      1.1  mrg   return true;
    373      1.1  mrg }
    374      1.1  mrg 
    375  1.1.1.2  mrg /* Get the state of SVAL within this object.
    376      1.1  mrg    States default to the start state.  */
    377      1.1  mrg 
    378      1.1  mrg state_machine::state_t
    379  1.1.1.2  mrg sm_state_map::get_state (const svalue *sval,
    380  1.1.1.2  mrg 			  const extrinsic_state &ext_state) const
    381      1.1  mrg {
    382  1.1.1.2  mrg   gcc_assert (sval);
    383  1.1.1.2  mrg 
    384  1.1.1.2  mrg   sval = canonicalize_svalue (sval, ext_state);
    385      1.1  mrg 
    386      1.1  mrg   if (entry_t *slot
    387  1.1.1.2  mrg       = const_cast <map_t &> (m_map).get (sval))
    388      1.1  mrg     return slot->m_state;
    389  1.1.1.2  mrg 
    390  1.1.1.2  mrg   /* SVAL has no explicit sm-state.
    391  1.1.1.2  mrg      If this sm allows for state inheritance, then SVAL might have implicit
    392  1.1.1.2  mrg      sm-state inherited via a parent.
    393  1.1.1.2  mrg      For example INIT_VAL(foo.field) might inherit taintedness state from
    394  1.1.1.2  mrg      INIT_VAL(foo).  */
    395  1.1.1.2  mrg   if (m_sm.inherited_state_p ())
    396  1.1.1.2  mrg     if (region_model_manager *mgr = ext_state.get_model_manager ())
    397  1.1.1.2  mrg       {
    398  1.1.1.2  mrg 	if (const initial_svalue *init_sval = sval->dyn_cast_initial_svalue ())
    399  1.1.1.2  mrg 	  {
    400  1.1.1.2  mrg 	    const region *reg = init_sval->get_region ();
    401  1.1.1.2  mrg 	    /* Try recursing upwards (up to the base region for the
    402  1.1.1.2  mrg 	       cluster).  */
    403  1.1.1.2  mrg 	    if (!reg->base_region_p ())
    404  1.1.1.2  mrg 	      if (const region *parent_reg = reg->get_parent_region ())
    405  1.1.1.2  mrg 		{
    406  1.1.1.2  mrg 		  const svalue *parent_init_sval
    407  1.1.1.2  mrg 		    = mgr->get_or_create_initial_value (parent_reg);
    408  1.1.1.2  mrg 		  state_machine::state_t parent_state
    409  1.1.1.2  mrg 		    = get_state (parent_init_sval, ext_state);
    410  1.1.1.2  mrg 		  if (parent_state)
    411  1.1.1.2  mrg 		    return parent_state;
    412  1.1.1.2  mrg 		}
    413  1.1.1.2  mrg 	  }
    414  1.1.1.2  mrg 	else if (const sub_svalue *sub_sval = sval->dyn_cast_sub_svalue ())
    415  1.1.1.2  mrg 	  {
    416  1.1.1.2  mrg 	    const svalue *parent_sval = sub_sval->get_parent ();
    417  1.1.1.2  mrg 	    if (state_machine::state_t parent_state
    418  1.1.1.2  mrg 		  = get_state (parent_sval, ext_state))
    419  1.1.1.2  mrg 	      return parent_state;
    420  1.1.1.2  mrg 	  }
    421  1.1.1.2  mrg       }
    422  1.1.1.2  mrg 
    423  1.1.1.2  mrg   if (state_machine::state_t state
    424  1.1.1.2  mrg       = m_sm.alt_get_inherited_state (*this, sval, ext_state))
    425  1.1.1.2  mrg     return state;
    426  1.1.1.2  mrg 
    427  1.1.1.2  mrg   return m_sm.get_default_state (sval);
    428      1.1  mrg }
    429      1.1  mrg 
    430  1.1.1.2  mrg /* Get the "origin" svalue for any state of SVAL.  */
    431      1.1  mrg 
    432  1.1.1.2  mrg const svalue *
    433  1.1.1.2  mrg sm_state_map::get_origin (const svalue *sval,
    434  1.1.1.2  mrg 			   const extrinsic_state &ext_state) const
    435      1.1  mrg {
    436  1.1.1.2  mrg   gcc_assert (sval);
    437  1.1.1.2  mrg 
    438  1.1.1.2  mrg   sval = canonicalize_svalue (sval, ext_state);
    439      1.1  mrg 
    440      1.1  mrg   entry_t *slot
    441  1.1.1.2  mrg     = const_cast <map_t &> (m_map).get (sval);
    442      1.1  mrg   if (slot)
    443      1.1  mrg     return slot->m_origin;
    444      1.1  mrg   else
    445  1.1.1.2  mrg     return NULL;
    446      1.1  mrg }
    447      1.1  mrg 
    448      1.1  mrg /* Set the state of SID within MODEL to STATE, recording that
    449      1.1  mrg    the state came from ORIGIN.  */
    450      1.1  mrg 
    451      1.1  mrg void
    452      1.1  mrg sm_state_map::set_state (region_model *model,
    453  1.1.1.2  mrg 			 const svalue *sval,
    454      1.1  mrg 			 state_machine::state_t state,
    455  1.1.1.2  mrg 			 const svalue *origin,
    456  1.1.1.2  mrg 			 const extrinsic_state &ext_state)
    457      1.1  mrg {
    458      1.1  mrg   if (model == NULL)
    459      1.1  mrg     return;
    460      1.1  mrg 
    461  1.1.1.2  mrg   /* Reject attempts to set state on UNKNOWN/POISONED.  */
    462  1.1.1.2  mrg   if (!sval->can_have_associated_state_p ())
    463  1.1.1.2  mrg     return;
    464      1.1  mrg 
    465  1.1.1.2  mrg   equiv_class &ec = model->get_constraints ()->get_equiv_class (sval);
    466  1.1.1.2  mrg   if (!set_state (ec, state, origin, ext_state))
    467  1.1.1.2  mrg     return;
    468      1.1  mrg }
    469      1.1  mrg 
    470      1.1  mrg /* Set the state of EC to STATE, recording that the state came from
    471      1.1  mrg    ORIGIN.
    472      1.1  mrg    Return true if any states of svalue_ids within EC changed.  */
    473      1.1  mrg 
    474      1.1  mrg bool
    475      1.1  mrg sm_state_map::set_state (const equiv_class &ec,
    476      1.1  mrg 			 state_machine::state_t state,
    477  1.1.1.2  mrg 			 const svalue *origin,
    478  1.1.1.2  mrg 			 const extrinsic_state &ext_state)
    479      1.1  mrg {
    480      1.1  mrg   bool any_changed = false;
    481  1.1.1.2  mrg   for (const svalue *sval : ec.m_vars)
    482  1.1.1.2  mrg     any_changed |= impl_set_state (sval, state, origin, ext_state);
    483      1.1  mrg   return any_changed;
    484      1.1  mrg }
    485      1.1  mrg 
    486  1.1.1.2  mrg /* Set state of SVAL to STATE, bypassing equivalence classes.
    487      1.1  mrg    Return true if the state changed.  */
    488      1.1  mrg 
    489      1.1  mrg bool
    490  1.1.1.2  mrg sm_state_map::impl_set_state (const svalue *sval,
    491  1.1.1.2  mrg 			      state_machine::state_t state,
    492  1.1.1.2  mrg 			      const svalue *origin,
    493  1.1.1.2  mrg 			      const extrinsic_state &ext_state)
    494      1.1  mrg {
    495  1.1.1.2  mrg   sval = canonicalize_svalue (sval, ext_state);
    496  1.1.1.2  mrg 
    497  1.1.1.2  mrg   if (get_state (sval, ext_state) == state)
    498      1.1  mrg     return false;
    499      1.1  mrg 
    500  1.1.1.2  mrg   gcc_assert (sval->can_have_associated_state_p ());
    501  1.1.1.2  mrg 
    502  1.1.1.2  mrg   if (m_sm.inherited_state_p ())
    503  1.1.1.2  mrg     {
    504  1.1.1.2  mrg       if (const compound_svalue *compound_sval
    505  1.1.1.2  mrg 	    = sval->dyn_cast_compound_svalue ())
    506  1.1.1.2  mrg 	for (auto iter : *compound_sval)
    507  1.1.1.2  mrg 	  {
    508  1.1.1.2  mrg 	    const svalue *inner_sval = iter.second;
    509  1.1.1.2  mrg 	    if (inner_sval->can_have_associated_state_p ())
    510  1.1.1.2  mrg 	      impl_set_state (inner_sval, state, origin, ext_state);
    511  1.1.1.2  mrg 	  }
    512  1.1.1.2  mrg     }
    513  1.1.1.2  mrg 
    514      1.1  mrg   /* Special-case state 0 as the default value.  */
    515      1.1  mrg   if (state == 0)
    516      1.1  mrg     {
    517  1.1.1.2  mrg       if (m_map.get (sval))
    518  1.1.1.2  mrg 	m_map.remove (sval);
    519      1.1  mrg       return true;
    520      1.1  mrg     }
    521  1.1.1.2  mrg   gcc_assert (sval);
    522  1.1.1.2  mrg   m_map.put (sval, entry_t (state, origin));
    523      1.1  mrg   return true;
    524      1.1  mrg }
    525      1.1  mrg 
    526      1.1  mrg /* Set the "global" state within this state map to STATE.  */
    527      1.1  mrg 
    528      1.1  mrg void
    529      1.1  mrg sm_state_map::set_global_state (state_machine::state_t state)
    530      1.1  mrg {
    531      1.1  mrg   m_global_state = state;
    532      1.1  mrg }
    533      1.1  mrg 
    534      1.1  mrg /* Get the "global" state within this state map.  */
    535      1.1  mrg 
    536      1.1  mrg state_machine::state_t
    537      1.1  mrg sm_state_map::get_global_state () const
    538      1.1  mrg {
    539      1.1  mrg   return m_global_state;
    540      1.1  mrg }
    541      1.1  mrg 
    542  1.1.1.2  mrg /* Purge any state for SVAL.
    543  1.1.1.2  mrg    If !SM::can_purge_p, then report the state as leaking,
    544  1.1.1.2  mrg    using CTXT.  */
    545      1.1  mrg 
    546      1.1  mrg void
    547  1.1.1.2  mrg sm_state_map::on_svalue_leak (const svalue *sval,
    548  1.1.1.2  mrg 			      impl_region_model_context *ctxt)
    549      1.1  mrg {
    550  1.1.1.2  mrg   if (state_machine::state_t state = get_state (sval, ctxt->m_ext_state))
    551      1.1  mrg     {
    552  1.1.1.2  mrg       if (!m_sm.can_purge_p (state))
    553  1.1.1.2  mrg 	ctxt->on_state_leak (m_sm, sval, state);
    554  1.1.1.2  mrg       m_map.remove (sval);
    555      1.1  mrg     }
    556      1.1  mrg }
    557      1.1  mrg 
    558  1.1.1.2  mrg /* Purge any state for svalues that aren't live with respect to LIVE_SVALUES
    559  1.1.1.2  mrg    and MODEL.  */
    560      1.1  mrg 
    561      1.1  mrg void
    562  1.1.1.2  mrg sm_state_map::on_liveness_change (const svalue_set &live_svalues,
    563  1.1.1.2  mrg 				  const region_model *model,
    564  1.1.1.2  mrg 				  impl_region_model_context *ctxt)
    565      1.1  mrg {
    566  1.1.1.2  mrg   svalue_set svals_to_unset;
    567  1.1.1.2  mrg   uncertainty_t *uncertainty = ctxt->get_uncertainty ();
    568      1.1  mrg 
    569  1.1.1.2  mrg   auto_vec<const svalue *> leaked_svals (m_map.elements ());
    570      1.1  mrg   for (map_t::iterator iter = m_map.begin ();
    571      1.1  mrg        iter != m_map.end ();
    572      1.1  mrg        ++iter)
    573      1.1  mrg     {
    574  1.1.1.2  mrg       const svalue *iter_sval = (*iter).first;
    575  1.1.1.2  mrg       if (!iter_sval->live_p (&live_svalues, model))
    576  1.1.1.2  mrg 	{
    577  1.1.1.2  mrg 	  svals_to_unset.add (iter_sval);
    578  1.1.1.2  mrg 	  entry_t e = (*iter).second;
    579  1.1.1.2  mrg 	  if (!m_sm.can_purge_p (e.m_state))
    580  1.1.1.2  mrg 	    leaked_svals.quick_push (iter_sval);
    581  1.1.1.2  mrg 	}
    582  1.1.1.2  mrg       if (uncertainty)
    583  1.1.1.2  mrg 	if (uncertainty->unknown_sm_state_p (iter_sval))
    584  1.1.1.2  mrg 	  svals_to_unset.add (iter_sval);
    585      1.1  mrg     }
    586      1.1  mrg 
    587  1.1.1.2  mrg   leaked_svals.qsort (svalue::cmp_ptr_ptr);
    588      1.1  mrg 
    589  1.1.1.2  mrg   unsigned i;
    590  1.1.1.2  mrg   const svalue *sval;
    591  1.1.1.2  mrg   FOR_EACH_VEC_ELT (leaked_svals, i, sval)
    592      1.1  mrg     {
    593  1.1.1.2  mrg       entry_t e = *m_map.get (sval);
    594  1.1.1.2  mrg       ctxt->on_state_leak (m_sm, sval, e.m_state);
    595      1.1  mrg     }
    596  1.1.1.2  mrg 
    597  1.1.1.2  mrg   for (svalue_set::iterator iter = svals_to_unset.begin ();
    598  1.1.1.2  mrg        iter != svals_to_unset.end (); ++iter)
    599  1.1.1.2  mrg     m_map.remove (*iter);
    600      1.1  mrg }
    601      1.1  mrg 
    602  1.1.1.2  mrg /* Purge state from SVAL (in response to a call to an unknown function).  */
    603  1.1.1.2  mrg 
    604  1.1.1.2  mrg void
    605  1.1.1.2  mrg sm_state_map::on_unknown_change (const svalue *sval,
    606  1.1.1.2  mrg 				 bool is_mutable,
    607  1.1.1.2  mrg 				 const extrinsic_state &ext_state)
    608  1.1.1.2  mrg {
    609  1.1.1.2  mrg   svalue_set svals_to_unset;
    610      1.1  mrg 
    611      1.1  mrg   for (map_t::iterator iter = m_map.begin ();
    612      1.1  mrg        iter != m_map.end ();
    613      1.1  mrg        ++iter)
    614      1.1  mrg     {
    615  1.1.1.2  mrg       const svalue *key = (*iter).first;
    616  1.1.1.2  mrg       entry_t e = (*iter).second;
    617  1.1.1.2  mrg       /* We only want to purge state for some states when things
    618  1.1.1.2  mrg 	 are mutable.  For example, in sm-malloc.cc, an on-stack ptr
    619  1.1.1.2  mrg 	 doesn't stop being stack-allocated when passed to an unknown fn.  */
    620  1.1.1.2  mrg       if (!m_sm.reset_when_passed_to_unknown_fn_p (e.m_state, is_mutable))
    621  1.1.1.2  mrg 	continue;
    622  1.1.1.2  mrg       if (key == sval)
    623  1.1.1.2  mrg 	svals_to_unset.add (key);
    624  1.1.1.2  mrg       /* If we have INIT_VAL(BASE_REG), then unset any INIT_VAL(REG)
    625  1.1.1.2  mrg 	 for REG within BASE_REG.  */
    626  1.1.1.2  mrg       if (const initial_svalue *init_sval = sval->dyn_cast_initial_svalue ())
    627  1.1.1.2  mrg 	if (const initial_svalue *init_key = key->dyn_cast_initial_svalue ())
    628  1.1.1.2  mrg 	  {
    629  1.1.1.2  mrg 	    const region *changed_reg = init_sval->get_region ();
    630  1.1.1.2  mrg 	    const region *changed_key = init_key->get_region ();
    631  1.1.1.2  mrg 	    if (changed_key->get_base_region () == changed_reg)
    632  1.1.1.2  mrg 	      svals_to_unset.add (key);
    633  1.1.1.2  mrg 	  }
    634      1.1  mrg     }
    635      1.1  mrg 
    636  1.1.1.2  mrg   for (svalue_set::iterator iter = svals_to_unset.begin ();
    637  1.1.1.2  mrg        iter != svals_to_unset.end (); ++iter)
    638  1.1.1.2  mrg     impl_set_state (*iter, (state_machine::state_t)0, NULL, ext_state);
    639      1.1  mrg }
    640      1.1  mrg 
    641  1.1.1.2  mrg /* Purge state for things involving SVAL.
    642  1.1.1.2  mrg    For use when SVAL changes meaning, at the def_stmt on an SSA_NAME.   */
    643      1.1  mrg 
    644      1.1  mrg void
    645  1.1.1.2  mrg sm_state_map::purge_state_involving (const svalue *sval,
    646  1.1.1.2  mrg 				     const extrinsic_state &ext_state)
    647      1.1  mrg {
    648  1.1.1.2  mrg   /* Currently svalue::involves_p requires this.  */
    649  1.1.1.2  mrg   if (!(sval->get_kind () == SK_INITIAL
    650  1.1.1.2  mrg 	|| sval->get_kind () == SK_CONJURED))
    651  1.1.1.2  mrg     return;
    652      1.1  mrg 
    653  1.1.1.2  mrg   svalue_set svals_to_unset;
    654      1.1  mrg 
    655  1.1.1.2  mrg   for (map_t::iterator iter = m_map.begin ();
    656  1.1.1.2  mrg        iter != m_map.end ();
    657  1.1.1.2  mrg        ++iter)
    658  1.1.1.2  mrg     {
    659  1.1.1.2  mrg       const svalue *key = (*iter).first;
    660  1.1.1.2  mrg       entry_t e = (*iter).second;
    661  1.1.1.2  mrg       if (!m_sm.can_purge_p (e.m_state))
    662  1.1.1.2  mrg 	continue;
    663  1.1.1.2  mrg       if (key->involves_p (sval))
    664  1.1.1.2  mrg 	svals_to_unset.add (key);
    665  1.1.1.2  mrg     }
    666      1.1  mrg 
    667  1.1.1.2  mrg   for (svalue_set::iterator iter = svals_to_unset.begin ();
    668  1.1.1.2  mrg        iter != svals_to_unset.end (); ++iter)
    669  1.1.1.2  mrg     impl_set_state (*iter, (state_machine::state_t)0, NULL, ext_state);
    670      1.1  mrg }
    671      1.1  mrg 
    672  1.1.1.2  mrg /* Comparator for imposing an order on sm_state_map instances.  */
    673      1.1  mrg 
    674  1.1.1.2  mrg int
    675  1.1.1.2  mrg sm_state_map::cmp (const sm_state_map &smap_a, const sm_state_map &smap_b)
    676      1.1  mrg {
    677  1.1.1.2  mrg   if (int cmp_count = smap_a.elements () - smap_b.elements ())
    678  1.1.1.2  mrg     return cmp_count;
    679      1.1  mrg 
    680  1.1.1.2  mrg   auto_vec <const svalue *> keys_a (smap_a.elements ());
    681  1.1.1.2  mrg   for (map_t::iterator iter = smap_a.begin ();
    682  1.1.1.2  mrg        iter != smap_a.end ();
    683      1.1  mrg        ++iter)
    684  1.1.1.2  mrg     keys_a.quick_push ((*iter).first);
    685  1.1.1.2  mrg   keys_a.qsort (svalue::cmp_ptr_ptr);
    686      1.1  mrg 
    687  1.1.1.2  mrg   auto_vec <const svalue *> keys_b (smap_b.elements ());
    688  1.1.1.2  mrg   for (map_t::iterator iter = smap_b.begin ();
    689  1.1.1.2  mrg        iter != smap_b.end ();
    690  1.1.1.2  mrg        ++iter)
    691  1.1.1.2  mrg     keys_b.quick_push ((*iter).first);
    692  1.1.1.2  mrg   keys_b.qsort (svalue::cmp_ptr_ptr);
    693  1.1.1.2  mrg 
    694  1.1.1.2  mrg   unsigned i;
    695  1.1.1.2  mrg   const svalue *sval_a;
    696  1.1.1.2  mrg   FOR_EACH_VEC_ELT (keys_a, i, sval_a)
    697  1.1.1.2  mrg     {
    698  1.1.1.2  mrg       const svalue *sval_b = keys_b[i];
    699  1.1.1.2  mrg       if (int cmp_sval = svalue::cmp_ptr (sval_a, sval_b))
    700  1.1.1.2  mrg 	return cmp_sval;
    701  1.1.1.2  mrg       const entry_t *e_a = const_cast <map_t &> (smap_a.m_map).get (sval_a);
    702  1.1.1.2  mrg       const entry_t *e_b = const_cast <map_t &> (smap_b.m_map).get (sval_b);
    703  1.1.1.2  mrg       if (int cmp_entry = entry_t::cmp (*e_a, *e_b))
    704  1.1.1.2  mrg 	return cmp_entry;
    705      1.1  mrg     }
    706  1.1.1.2  mrg 
    707  1.1.1.2  mrg   return 0;
    708  1.1.1.2  mrg }
    709  1.1.1.2  mrg 
    710  1.1.1.2  mrg /* Canonicalize SVAL before getting/setting it within the map.
    711  1.1.1.2  mrg    Convert all NULL pointers to (void *) to avoid state explosions
    712  1.1.1.2  mrg    involving all of the various (foo *)NULL vs (bar *)NULL.  */
    713  1.1.1.2  mrg 
    714  1.1.1.2  mrg const svalue *
    715  1.1.1.2  mrg sm_state_map::canonicalize_svalue (const svalue *sval,
    716  1.1.1.2  mrg 				   const extrinsic_state &ext_state)
    717  1.1.1.2  mrg {
    718  1.1.1.2  mrg   region_model_manager *mgr = ext_state.get_model_manager ();
    719  1.1.1.2  mrg   if (mgr && sval->get_type () && POINTER_TYPE_P (sval->get_type ()))
    720  1.1.1.2  mrg     if (tree cst = sval->maybe_get_constant ())
    721  1.1.1.2  mrg       if (zerop (cst))
    722  1.1.1.2  mrg 	return mgr->get_or_create_constant_svalue (null_pointer_node);
    723  1.1.1.2  mrg 
    724  1.1.1.2  mrg   return sval;
    725      1.1  mrg }
    726      1.1  mrg 
    727      1.1  mrg /* class program_state.  */
    728      1.1  mrg 
    729      1.1  mrg /* program_state's ctor.  */
    730      1.1  mrg 
    731      1.1  mrg program_state::program_state (const extrinsic_state &ext_state)
    732  1.1.1.2  mrg : m_region_model (NULL),
    733      1.1  mrg   m_checker_states (ext_state.get_num_checkers ()),
    734      1.1  mrg   m_valid (true)
    735      1.1  mrg {
    736  1.1.1.2  mrg   engine *eng = ext_state.get_engine ();
    737  1.1.1.2  mrg   region_model_manager *mgr = eng->get_model_manager ();
    738  1.1.1.2  mrg   m_region_model = new region_model (mgr);
    739  1.1.1.2  mrg   const int num_states = ext_state.get_num_checkers ();
    740      1.1  mrg   for (int i = 0; i < num_states; i++)
    741  1.1.1.2  mrg     {
    742  1.1.1.2  mrg       sm_state_map *sm = new sm_state_map (ext_state.get_sm (i));
    743  1.1.1.2  mrg       m_checker_states.quick_push (sm);
    744  1.1.1.2  mrg     }
    745      1.1  mrg }
    746      1.1  mrg 
    747      1.1  mrg /* program_state's copy ctor.  */
    748      1.1  mrg 
    749      1.1  mrg program_state::program_state (const program_state &other)
    750      1.1  mrg : m_region_model (new region_model (*other.m_region_model)),
    751      1.1  mrg   m_checker_states (other.m_checker_states.length ()),
    752      1.1  mrg   m_valid (true)
    753      1.1  mrg {
    754      1.1  mrg   int i;
    755      1.1  mrg   sm_state_map *smap;
    756      1.1  mrg   FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
    757      1.1  mrg     m_checker_states.quick_push (smap->clone ());
    758      1.1  mrg }
    759      1.1  mrg 
    760      1.1  mrg /* program_state's assignment operator.  */
    761      1.1  mrg 
    762      1.1  mrg program_state&
    763      1.1  mrg program_state::operator= (const program_state &other)
    764      1.1  mrg {
    765      1.1  mrg   delete m_region_model;
    766      1.1  mrg   m_region_model = new region_model (*other.m_region_model);
    767      1.1  mrg 
    768      1.1  mrg   int i;
    769      1.1  mrg   sm_state_map *smap;
    770      1.1  mrg   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
    771      1.1  mrg     delete smap;
    772      1.1  mrg   m_checker_states.truncate (0);
    773      1.1  mrg   gcc_assert (m_checker_states.space (other.m_checker_states.length ()));
    774      1.1  mrg 
    775      1.1  mrg   FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
    776      1.1  mrg     m_checker_states.quick_push (smap->clone ());
    777      1.1  mrg 
    778      1.1  mrg   m_valid = other.m_valid;
    779      1.1  mrg 
    780      1.1  mrg   return *this;
    781      1.1  mrg }
    782      1.1  mrg 
    783      1.1  mrg /* Move constructor for program_state (when building with C++11).  */
    784      1.1  mrg program_state::program_state (program_state &&other)
    785      1.1  mrg : m_region_model (other.m_region_model),
    786      1.1  mrg   m_checker_states (other.m_checker_states.length ())
    787      1.1  mrg {
    788      1.1  mrg   other.m_region_model = NULL;
    789      1.1  mrg 
    790      1.1  mrg   int i;
    791      1.1  mrg   sm_state_map *smap;
    792      1.1  mrg   FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
    793      1.1  mrg     m_checker_states.quick_push (smap);
    794      1.1  mrg   other.m_checker_states.truncate (0);
    795      1.1  mrg 
    796      1.1  mrg   m_valid = other.m_valid;
    797      1.1  mrg }
    798      1.1  mrg 
    799      1.1  mrg /* program_state's dtor.  */
    800      1.1  mrg 
    801      1.1  mrg program_state::~program_state ()
    802      1.1  mrg {
    803      1.1  mrg   delete m_region_model;
    804      1.1  mrg }
    805      1.1  mrg 
    806      1.1  mrg /* Generate a hash value for this program_state.  */
    807      1.1  mrg 
    808      1.1  mrg hashval_t
    809      1.1  mrg program_state::hash () const
    810      1.1  mrg {
    811      1.1  mrg   hashval_t result = m_region_model->hash ();
    812      1.1  mrg 
    813      1.1  mrg   int i;
    814      1.1  mrg   sm_state_map *smap;
    815      1.1  mrg   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
    816      1.1  mrg     result ^= smap->hash ();
    817      1.1  mrg   return result;
    818      1.1  mrg }
    819      1.1  mrg 
    820      1.1  mrg /* Equality operator for program_state.
    821      1.1  mrg    All parts of the program_state (region model, checker states) must
    822      1.1  mrg    equal their counterparts in OTHER for the two program_states to be
    823      1.1  mrg    considered equal.  */
    824      1.1  mrg 
    825      1.1  mrg bool
    826      1.1  mrg program_state::operator== (const program_state &other) const
    827      1.1  mrg {
    828      1.1  mrg   if (!(*m_region_model == *other.m_region_model))
    829      1.1  mrg     return false;
    830      1.1  mrg 
    831      1.1  mrg   int i;
    832      1.1  mrg   sm_state_map *smap;
    833      1.1  mrg   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
    834      1.1  mrg     if (!(*smap == *other.m_checker_states[i]))
    835      1.1  mrg       return false;
    836      1.1  mrg 
    837      1.1  mrg   gcc_checking_assert (hash () == other.hash ());
    838      1.1  mrg 
    839      1.1  mrg   return true;
    840      1.1  mrg }
    841      1.1  mrg 
    842      1.1  mrg /* Print a compact representation of this state to PP.  */
    843      1.1  mrg 
    844      1.1  mrg void
    845      1.1  mrg program_state::print (const extrinsic_state &ext_state,
    846      1.1  mrg 		      pretty_printer *pp) const
    847      1.1  mrg {
    848      1.1  mrg   pp_printf (pp, "rmodel: ");
    849  1.1.1.2  mrg   m_region_model->dump_to_pp (pp, true, false);
    850      1.1  mrg   pp_newline (pp);
    851      1.1  mrg 
    852      1.1  mrg   int i;
    853      1.1  mrg   sm_state_map *smap;
    854      1.1  mrg   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
    855      1.1  mrg     {
    856      1.1  mrg       if (!smap->is_empty_p ())
    857      1.1  mrg 	{
    858      1.1  mrg 	  pp_printf (pp, "%s: ", ext_state.get_name (i));
    859  1.1.1.2  mrg 	  smap->print (m_region_model, true, false, pp);
    860      1.1  mrg 	  pp_newline (pp);
    861      1.1  mrg 	}
    862      1.1  mrg     }
    863      1.1  mrg   if (!m_valid)
    864      1.1  mrg     {
    865      1.1  mrg       pp_printf (pp, "invalid state");
    866      1.1  mrg       pp_newline (pp);
    867      1.1  mrg     }
    868      1.1  mrg }
    869      1.1  mrg 
    870  1.1.1.2  mrg /* Dump a representation of this state to PP.  */
    871      1.1  mrg 
    872      1.1  mrg void
    873      1.1  mrg program_state::dump_to_pp (const extrinsic_state &ext_state,
    874  1.1.1.2  mrg 			   bool /*summarize*/, bool multiline,
    875      1.1  mrg 			   pretty_printer *pp) const
    876      1.1  mrg {
    877  1.1.1.2  mrg   if (!multiline)
    878  1.1.1.2  mrg     pp_string (pp, "{");
    879  1.1.1.2  mrg   {
    880  1.1.1.2  mrg     pp_printf (pp, "rmodel:");
    881  1.1.1.2  mrg     if (multiline)
    882  1.1.1.2  mrg       pp_newline (pp);
    883  1.1.1.2  mrg     else
    884  1.1.1.2  mrg       pp_string (pp, " {");
    885  1.1.1.2  mrg     m_region_model->dump_to_pp (pp, true, multiline);
    886  1.1.1.2  mrg     if (!multiline)
    887  1.1.1.2  mrg       pp_string (pp, "}");
    888  1.1.1.2  mrg   }
    889      1.1  mrg 
    890      1.1  mrg   int i;
    891      1.1  mrg   sm_state_map *smap;
    892      1.1  mrg   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
    893      1.1  mrg     {
    894      1.1  mrg       if (!smap->is_empty_p ())
    895      1.1  mrg 	{
    896  1.1.1.2  mrg 	  if (!multiline)
    897  1.1.1.2  mrg 	    pp_string (pp, " {");
    898      1.1  mrg 	  pp_printf (pp, "%s: ", ext_state.get_name (i));
    899  1.1.1.2  mrg 	  if (multiline)
    900      1.1  mrg 	    pp_newline (pp);
    901  1.1.1.2  mrg 	  smap->print (m_region_model, true, multiline, pp);
    902  1.1.1.2  mrg 	  if (!multiline)
    903  1.1.1.2  mrg 	    pp_string (pp, "}");
    904      1.1  mrg 	}
    905      1.1  mrg     }
    906      1.1  mrg 
    907      1.1  mrg   if (!m_valid)
    908      1.1  mrg     {
    909  1.1.1.2  mrg       if (!multiline)
    910      1.1  mrg 	pp_space (pp);
    911      1.1  mrg       pp_printf (pp, "invalid state");
    912  1.1.1.2  mrg       if (multiline)
    913      1.1  mrg 	pp_newline (pp);
    914      1.1  mrg     }
    915  1.1.1.2  mrg   if (!multiline)
    916  1.1.1.2  mrg     pp_string (pp, "}");
    917      1.1  mrg }
    918      1.1  mrg 
    919  1.1.1.2  mrg /* Dump a representation of this state to OUTF.  */
    920      1.1  mrg 
    921      1.1  mrg void
    922      1.1  mrg program_state::dump_to_file (const extrinsic_state &ext_state,
    923  1.1.1.2  mrg 			     bool summarize, bool multiline,
    924      1.1  mrg 			     FILE *outf) const
    925      1.1  mrg {
    926      1.1  mrg   pretty_printer pp;
    927      1.1  mrg   pp_format_decoder (&pp) = default_tree_printer;
    928      1.1  mrg   if (outf == stderr)
    929      1.1  mrg     pp_show_color (&pp) = pp_show_color (global_dc->printer);
    930      1.1  mrg   pp.buffer->stream = outf;
    931  1.1.1.2  mrg   dump_to_pp (ext_state, summarize, multiline, &pp);
    932      1.1  mrg   pp_flush (&pp);
    933      1.1  mrg }
    934      1.1  mrg 
    935      1.1  mrg /* Dump a multiline representation of this state to stderr.  */
    936      1.1  mrg 
    937      1.1  mrg DEBUG_FUNCTION void
    938      1.1  mrg program_state::dump (const extrinsic_state &ext_state,
    939      1.1  mrg 		     bool summarize) const
    940      1.1  mrg {
    941  1.1.1.2  mrg   dump_to_file (ext_state, summarize, true, stderr);
    942  1.1.1.2  mrg }
    943  1.1.1.2  mrg 
    944  1.1.1.2  mrg /* Return a new json::object of the form
    945  1.1.1.2  mrg    {"store"  : object for store,
    946  1.1.1.2  mrg     "constraints" : object for constraint_manager,
    947  1.1.1.2  mrg     "curr_frame" : (optional) str for current frame,
    948  1.1.1.2  mrg     "checkers" : { STATE_NAME : object per sm_state_map },
    949  1.1.1.2  mrg     "valid" : true/false}.  */
    950  1.1.1.2  mrg 
    951  1.1.1.2  mrg json::object *
    952  1.1.1.2  mrg program_state::to_json (const extrinsic_state &ext_state) const
    953  1.1.1.2  mrg {
    954  1.1.1.2  mrg   json::object *state_obj = new json::object ();
    955  1.1.1.2  mrg 
    956  1.1.1.2  mrg   state_obj->set ("store", m_region_model->get_store ()->to_json ());
    957  1.1.1.2  mrg   state_obj->set ("constraints",
    958  1.1.1.2  mrg 		  m_region_model->get_constraints ()->to_json ());
    959  1.1.1.2  mrg   if (m_region_model->get_current_frame ())
    960  1.1.1.2  mrg     state_obj->set ("curr_frame",
    961  1.1.1.2  mrg 		    m_region_model->get_current_frame ()->to_json ());
    962  1.1.1.2  mrg 
    963  1.1.1.2  mrg   /* Provide m_checker_states as an object, using names as keys.  */
    964  1.1.1.2  mrg   {
    965  1.1.1.2  mrg     json::object *checkers_obj = new json::object ();
    966  1.1.1.2  mrg 
    967  1.1.1.2  mrg     int i;
    968  1.1.1.2  mrg     sm_state_map *smap;
    969  1.1.1.2  mrg     FOR_EACH_VEC_ELT (m_checker_states, i, smap)
    970  1.1.1.2  mrg       if (!smap->is_empty_p ())
    971  1.1.1.2  mrg 	checkers_obj->set (ext_state.get_name (i), smap->to_json ());
    972  1.1.1.2  mrg 
    973  1.1.1.2  mrg     state_obj->set ("checkers", checkers_obj);
    974  1.1.1.2  mrg   }
    975  1.1.1.2  mrg 
    976  1.1.1.2  mrg   state_obj->set ("valid", new json::literal (m_valid));
    977  1.1.1.2  mrg 
    978  1.1.1.2  mrg   return state_obj;
    979  1.1.1.2  mrg }
    980  1.1.1.2  mrg 
    981  1.1.1.2  mrg /* Update this program_state to reflect a top-level call to FUN.
    982  1.1.1.2  mrg    The params will have initial_svalues.  */
    983  1.1.1.2  mrg 
    984  1.1.1.2  mrg void
    985  1.1.1.2  mrg program_state::push_frame (const extrinsic_state &ext_state ATTRIBUTE_UNUSED,
    986  1.1.1.2  mrg 			   function *fun)
    987  1.1.1.2  mrg {
    988  1.1.1.2  mrg   m_region_model->push_frame (fun, NULL, NULL);
    989  1.1.1.2  mrg }
    990  1.1.1.2  mrg 
    991  1.1.1.2  mrg /* Get the current function of this state.  */
    992  1.1.1.2  mrg 
    993  1.1.1.2  mrg function *
    994  1.1.1.2  mrg program_state::get_current_function () const
    995  1.1.1.2  mrg {
    996  1.1.1.2  mrg   return m_region_model->get_current_function ();
    997      1.1  mrg }
    998      1.1  mrg 
    999      1.1  mrg /* Determine if following edge SUCC from ENODE is valid within the graph EG
   1000      1.1  mrg    and update this state accordingly in-place.
   1001      1.1  mrg 
   1002      1.1  mrg    Return true if the edge can be followed, or false otherwise.
   1003      1.1  mrg 
   1004      1.1  mrg    Check for relevant conditionals and switch-values for conditionals
   1005      1.1  mrg    and switch statements, adding the relevant conditions to this state.
   1006      1.1  mrg    Push/pop frames for interprocedural edges and update params/returned
   1007      1.1  mrg    values.
   1008      1.1  mrg 
   1009      1.1  mrg    This is the "state" half of exploded_node::on_edge.  */
   1010      1.1  mrg 
   1011      1.1  mrg bool
   1012      1.1  mrg program_state::on_edge (exploded_graph &eg,
   1013  1.1.1.2  mrg 			exploded_node *enode,
   1014      1.1  mrg 			const superedge *succ,
   1015  1.1.1.2  mrg 			uncertainty_t *uncertainty)
   1016      1.1  mrg {
   1017      1.1  mrg   /* Update state.  */
   1018  1.1.1.2  mrg   const program_point &point = enode->get_point ();
   1019      1.1  mrg   const gimple *last_stmt = point.get_supernode ()->get_last_stmt ();
   1020      1.1  mrg 
   1021      1.1  mrg   /* For conditionals and switch statements, add the
   1022      1.1  mrg      relevant conditions (for the specific edge) to new_state;
   1023      1.1  mrg      skip edges for which the resulting constraints
   1024      1.1  mrg      are impossible.
   1025      1.1  mrg      This also updates frame information for call/return superedges.
   1026      1.1  mrg      Adding the relevant conditions for the edge could also trigger
   1027      1.1  mrg      sm-state transitions (e.g. transitions due to ptrs becoming known
   1028      1.1  mrg      to be NULL or non-NULL) */
   1029      1.1  mrg 
   1030  1.1.1.2  mrg   impl_region_model_context ctxt (eg, enode,
   1031  1.1.1.2  mrg 				  &enode->get_state (),
   1032  1.1.1.2  mrg 				  this,
   1033  1.1.1.2  mrg 				  uncertainty, NULL,
   1034      1.1  mrg 				  last_stmt);
   1035      1.1  mrg   if (!m_region_model->maybe_update_for_edge (*succ,
   1036      1.1  mrg 					      last_stmt,
   1037  1.1.1.2  mrg 					      &ctxt, NULL))
   1038      1.1  mrg     {
   1039      1.1  mrg       logger * const logger = eg.get_logger ();
   1040      1.1  mrg       if (logger)
   1041      1.1  mrg 	logger->log ("edge to SN: %i is impossible"
   1042      1.1  mrg 		     " due to region_model constraints",
   1043      1.1  mrg 		     succ->m_dest->m_index);
   1044      1.1  mrg       return false;
   1045      1.1  mrg     }
   1046      1.1  mrg 
   1047  1.1.1.2  mrg   program_state::detect_leaks (enode->get_state (), *this,
   1048  1.1.1.2  mrg 			       NULL, eg.get_ext_state (),
   1049  1.1.1.2  mrg 			       &ctxt);
   1050  1.1.1.2  mrg 
   1051      1.1  mrg   return true;
   1052      1.1  mrg }
   1053      1.1  mrg 
   1054  1.1.1.2  mrg /* Update this program_state to reflect a call to function
   1055  1.1.1.2  mrg    represented by CALL_STMT.
   1056  1.1.1.2  mrg    currently used only when the call doesn't have a superedge representing
   1057  1.1.1.2  mrg    the call ( like call via a function pointer )  */
   1058  1.1.1.2  mrg void
   1059  1.1.1.2  mrg program_state::push_call (exploded_graph &eg,
   1060  1.1.1.2  mrg                           exploded_node *enode,
   1061  1.1.1.2  mrg                           const gcall *call_stmt,
   1062  1.1.1.2  mrg                           uncertainty_t *uncertainty)
   1063  1.1.1.2  mrg {
   1064  1.1.1.2  mrg   /* Update state.  */
   1065  1.1.1.2  mrg   const program_point &point = enode->get_point ();
   1066  1.1.1.2  mrg   const gimple *last_stmt = point.get_supernode ()->get_last_stmt ();
   1067  1.1.1.2  mrg 
   1068  1.1.1.2  mrg   impl_region_model_context ctxt (eg, enode,
   1069  1.1.1.2  mrg                                   &enode->get_state (),
   1070  1.1.1.2  mrg                                   this,
   1071  1.1.1.2  mrg                                   uncertainty,
   1072  1.1.1.2  mrg 				  NULL,
   1073  1.1.1.2  mrg                                   last_stmt);
   1074  1.1.1.2  mrg   m_region_model->update_for_gcall (call_stmt, &ctxt);
   1075  1.1.1.2  mrg }
   1076  1.1.1.2  mrg 
   1077  1.1.1.2  mrg /* Update this program_state to reflect a return from function
   1078  1.1.1.2  mrg    call to which is represented by CALL_STMT.
   1079  1.1.1.2  mrg    currently used only when the call doesn't have a superedge representing
   1080  1.1.1.2  mrg    the return */
   1081  1.1.1.2  mrg void
   1082  1.1.1.2  mrg program_state::returning_call (exploded_graph &eg,
   1083  1.1.1.2  mrg                                exploded_node *enode,
   1084  1.1.1.2  mrg                                const gcall *call_stmt,
   1085  1.1.1.2  mrg                                uncertainty_t *uncertainty)
   1086  1.1.1.2  mrg {
   1087  1.1.1.2  mrg   /* Update state.  */
   1088  1.1.1.2  mrg   const program_point &point = enode->get_point ();
   1089  1.1.1.2  mrg   const gimple *last_stmt = point.get_supernode ()->get_last_stmt ();
   1090  1.1.1.2  mrg 
   1091  1.1.1.2  mrg   impl_region_model_context ctxt (eg, enode,
   1092  1.1.1.2  mrg                                   &enode->get_state (),
   1093  1.1.1.2  mrg                                   this,
   1094  1.1.1.2  mrg                                   uncertainty,
   1095  1.1.1.2  mrg 				  NULL,
   1096  1.1.1.2  mrg                                   last_stmt);
   1097  1.1.1.2  mrg   m_region_model->update_for_return_gcall (call_stmt, &ctxt);
   1098  1.1.1.2  mrg }
   1099  1.1.1.2  mrg 
   1100      1.1  mrg /* Generate a simpler version of THIS, discarding state that's no longer
   1101      1.1  mrg    relevant at POINT.
   1102      1.1  mrg    The idea is that we're more likely to be able to consolidate
   1103      1.1  mrg    multiple (point, state) into single exploded_nodes if we discard
   1104  1.1.1.2  mrg    irrelevant state (e.g. at the end of functions).  */
   1105      1.1  mrg 
   1106      1.1  mrg program_state
   1107      1.1  mrg program_state::prune_for_point (exploded_graph &eg,
   1108      1.1  mrg 				const program_point &point,
   1109  1.1.1.2  mrg 				exploded_node *enode_for_diag,
   1110  1.1.1.2  mrg 				uncertainty_t *uncertainty) const
   1111      1.1  mrg {
   1112      1.1  mrg   logger * const logger = eg.get_logger ();
   1113      1.1  mrg   LOG_SCOPE (logger);
   1114      1.1  mrg 
   1115      1.1  mrg   function *fun = point.get_function ();
   1116      1.1  mrg   if (!fun)
   1117      1.1  mrg     return *this;
   1118      1.1  mrg 
   1119      1.1  mrg   program_state new_state (*this);
   1120      1.1  mrg 
   1121      1.1  mrg   const state_purge_map *pm = eg.get_purge_map ();
   1122      1.1  mrg   if (pm)
   1123      1.1  mrg     {
   1124  1.1.1.2  mrg       unsigned num_ssas_purged = 0;
   1125  1.1.1.2  mrg       unsigned num_decls_purged = 0;
   1126  1.1.1.2  mrg       auto_vec<const decl_region *> regs;
   1127  1.1.1.2  mrg       new_state.m_region_model->get_regions_for_current_frame (&regs);
   1128  1.1.1.2  mrg       regs.qsort (region::cmp_ptr_ptr);
   1129  1.1.1.2  mrg       unsigned i;
   1130  1.1.1.2  mrg       const decl_region *reg;
   1131  1.1.1.2  mrg       FOR_EACH_VEC_ELT (regs, i, reg)
   1132      1.1  mrg 	{
   1133  1.1.1.2  mrg 	  const tree node = reg->get_decl ();
   1134  1.1.1.2  mrg 	  if (TREE_CODE (node) == SSA_NAME)
   1135      1.1  mrg 	    {
   1136  1.1.1.2  mrg 	      const tree ssa_name = node;
   1137      1.1  mrg 	      const state_purge_per_ssa_name &per_ssa
   1138  1.1.1.2  mrg 		= pm->get_data_for_ssa_name (node);
   1139      1.1  mrg 	      if (!per_ssa.needed_at_point_p (point.get_function_point ()))
   1140      1.1  mrg 		{
   1141  1.1.1.2  mrg 		  /* Don't purge bindings of SSA names to svalues
   1142  1.1.1.2  mrg 		     that have unpurgable sm-state, so that leaks are
   1143  1.1.1.2  mrg 		     reported at the end of the function, rather than
   1144  1.1.1.2  mrg 		     at the last place that such an SSA name is referred to.
   1145  1.1.1.2  mrg 
   1146  1.1.1.2  mrg 		     But do purge them for temporaries (when SSA_NAME_VAR is
   1147  1.1.1.2  mrg 		     NULL), so that we report for cases where a leak happens when
   1148  1.1.1.2  mrg 		     a variable is overwritten with another value, so that the leak
   1149  1.1.1.2  mrg 		     is reported at the point of overwrite, rather than having
   1150  1.1.1.2  mrg 		     temporaries keep the value reachable until the frame is
   1151  1.1.1.2  mrg 		     popped.  */
   1152  1.1.1.2  mrg 		  const svalue *sval
   1153  1.1.1.2  mrg 		    = new_state.m_region_model->get_store_value (reg, NULL);
   1154  1.1.1.2  mrg 		  if (!new_state.can_purge_p (eg.get_ext_state (), sval)
   1155  1.1.1.2  mrg 		      && SSA_NAME_VAR (ssa_name))
   1156      1.1  mrg 		    {
   1157  1.1.1.2  mrg 		      /* (currently only state maps can keep things
   1158  1.1.1.2  mrg 			 alive).  */
   1159  1.1.1.2  mrg 		      if (logger)
   1160  1.1.1.2  mrg 			logger->log ("not purging binding for %qE"
   1161  1.1.1.2  mrg 				     " (used by state map)", ssa_name);
   1162  1.1.1.2  mrg 		      continue;
   1163      1.1  mrg 		    }
   1164  1.1.1.2  mrg 
   1165  1.1.1.2  mrg 		  new_state.m_region_model->purge_region (reg);
   1166  1.1.1.2  mrg 		  num_ssas_purged++;
   1167      1.1  mrg 		}
   1168      1.1  mrg 	    }
   1169  1.1.1.2  mrg 	  else
   1170  1.1.1.2  mrg 	    {
   1171  1.1.1.2  mrg 	      const tree decl = node;
   1172  1.1.1.2  mrg 	      gcc_assert (TREE_CODE (node) == VAR_DECL
   1173  1.1.1.2  mrg 			  || TREE_CODE (node) == PARM_DECL
   1174  1.1.1.2  mrg 			  || TREE_CODE (node) == RESULT_DECL);
   1175  1.1.1.2  mrg 	      if (const state_purge_per_decl *per_decl
   1176  1.1.1.2  mrg 		  = pm->get_any_data_for_decl (decl))
   1177  1.1.1.2  mrg 		if (!per_decl->needed_at_point_p (point.get_function_point ()))
   1178  1.1.1.2  mrg 		  {
   1179  1.1.1.2  mrg 		    /* Don't purge bindings of decls if there are svalues
   1180  1.1.1.2  mrg 		       that have unpurgable sm-state within the decl's cluster,
   1181  1.1.1.2  mrg 		       so that leaks are reported at the end of the function,
   1182  1.1.1.2  mrg 		       rather than at the last place that such a decl is
   1183  1.1.1.2  mrg 		       referred to.  */
   1184  1.1.1.2  mrg 		    if (!new_state.can_purge_base_region_p (eg.get_ext_state (),
   1185  1.1.1.2  mrg 							    reg))
   1186  1.1.1.2  mrg 		      {
   1187  1.1.1.2  mrg 			/* (currently only state maps can keep things
   1188  1.1.1.2  mrg 			   alive).  */
   1189  1.1.1.2  mrg 			if (logger)
   1190  1.1.1.2  mrg 			  logger->log ("not purging binding for %qE"
   1191  1.1.1.2  mrg 				       " (value in binding used by state map)",
   1192  1.1.1.2  mrg 				       decl);
   1193  1.1.1.2  mrg 			continue;
   1194  1.1.1.2  mrg 		      }
   1195  1.1.1.2  mrg 
   1196  1.1.1.2  mrg 		    new_state.m_region_model->purge_region (reg);
   1197  1.1.1.2  mrg 		    num_decls_purged++;
   1198  1.1.1.2  mrg 		  }
   1199  1.1.1.2  mrg 	    }
   1200      1.1  mrg 	}
   1201      1.1  mrg 
   1202  1.1.1.2  mrg       if (num_ssas_purged > 0 || num_decls_purged > 0)
   1203  1.1.1.2  mrg 	{
   1204  1.1.1.2  mrg 	  if (logger)
   1205  1.1.1.2  mrg 	    {
   1206  1.1.1.2  mrg 	      logger->log ("num_ssas_purged: %i", num_ssas_purged);
   1207  1.1.1.2  mrg 	      logger->log ("num_decl_purged: %i", num_decls_purged);
   1208  1.1.1.2  mrg 	    }
   1209  1.1.1.2  mrg 	  impl_region_model_context ctxt (eg, enode_for_diag,
   1210  1.1.1.2  mrg 					  this,
   1211  1.1.1.2  mrg 					  &new_state,
   1212  1.1.1.2  mrg 					  uncertainty, NULL,
   1213  1.1.1.2  mrg 					  point.get_stmt ());
   1214  1.1.1.2  mrg 	  detect_leaks (*this, new_state, NULL, eg.get_ext_state (), &ctxt);
   1215  1.1.1.2  mrg 	}
   1216      1.1  mrg     }
   1217      1.1  mrg 
   1218  1.1.1.2  mrg   new_state.m_region_model->canonicalize ();
   1219      1.1  mrg 
   1220      1.1  mrg   return new_state;
   1221      1.1  mrg }
   1222      1.1  mrg 
   1223  1.1.1.2  mrg /* Return true if there are no unpurgeable bindings within BASE_REG. */
   1224      1.1  mrg 
   1225  1.1.1.2  mrg bool
   1226  1.1.1.2  mrg program_state::can_purge_base_region_p (const extrinsic_state &ext_state,
   1227  1.1.1.2  mrg 					const region *base_reg) const
   1228      1.1  mrg {
   1229  1.1.1.2  mrg   binding_cluster *cluster
   1230  1.1.1.2  mrg     = m_region_model->get_store ()->get_cluster (base_reg);
   1231  1.1.1.2  mrg   if (!cluster)
   1232  1.1.1.2  mrg     return true;
   1233  1.1.1.2  mrg 
   1234  1.1.1.2  mrg   for (auto iter : *cluster)
   1235  1.1.1.2  mrg     {
   1236  1.1.1.2  mrg       const svalue *sval = iter.second;
   1237  1.1.1.2  mrg       if (!can_purge_p (ext_state, sval))
   1238  1.1.1.2  mrg 	return false;
   1239  1.1.1.2  mrg     }
   1240  1.1.1.2  mrg 
   1241  1.1.1.2  mrg   return true;
   1242      1.1  mrg }
   1243      1.1  mrg 
   1244  1.1.1.2  mrg /* Get a representative tree to use for describing SVAL.  */
   1245      1.1  mrg 
   1246      1.1  mrg tree
   1247  1.1.1.2  mrg program_state::get_representative_tree (const svalue *sval) const
   1248      1.1  mrg {
   1249  1.1.1.2  mrg   gcc_assert (m_region_model);
   1250  1.1.1.2  mrg   return m_region_model->get_representative_tree (sval);
   1251      1.1  mrg }
   1252      1.1  mrg 
   1253  1.1.1.2  mrg /* Attempt to merge this state with OTHER, both at POINT.
   1254      1.1  mrg    Write the result to *OUT.
   1255      1.1  mrg    If the states were merged successfully, return true.  */
   1256      1.1  mrg 
   1257      1.1  mrg bool
   1258      1.1  mrg program_state::can_merge_with_p (const program_state &other,
   1259      1.1  mrg 				 const extrinsic_state &ext_state,
   1260  1.1.1.2  mrg 				 const program_point &point,
   1261      1.1  mrg 				 program_state *out) const
   1262      1.1  mrg {
   1263      1.1  mrg   gcc_assert (out);
   1264  1.1.1.2  mrg   gcc_assert (m_region_model);
   1265      1.1  mrg 
   1266  1.1.1.2  mrg   /* Early reject if there are sm-differences between the states.  */
   1267  1.1.1.2  mrg   int i;
   1268  1.1.1.2  mrg   sm_state_map *smap;
   1269  1.1.1.2  mrg   FOR_EACH_VEC_ELT (out->m_checker_states, i, smap)
   1270  1.1.1.2  mrg     if (*m_checker_states[i] != *other.m_checker_states[i])
   1271  1.1.1.2  mrg       return false;
   1272      1.1  mrg 
   1273      1.1  mrg   /* Attempt to merge the region_models.  */
   1274      1.1  mrg   if (!m_region_model->can_merge_with_p (*other.m_region_model,
   1275  1.1.1.2  mrg 					  point,
   1276      1.1  mrg 					 out->m_region_model,
   1277  1.1.1.2  mrg 					 &ext_state,
   1278  1.1.1.2  mrg 					 this, &other))
   1279      1.1  mrg     return false;
   1280      1.1  mrg 
   1281  1.1.1.2  mrg   /* Copy m_checker_states to OUT.  */
   1282      1.1  mrg   FOR_EACH_VEC_ELT (out->m_checker_states, i, smap)
   1283      1.1  mrg     {
   1284  1.1.1.2  mrg       delete smap;
   1285  1.1.1.2  mrg       out->m_checker_states[i] = m_checker_states[i]->clone ();
   1286      1.1  mrg     }
   1287      1.1  mrg 
   1288  1.1.1.2  mrg   out->m_region_model->canonicalize ();
   1289      1.1  mrg 
   1290      1.1  mrg   return true;
   1291      1.1  mrg }
   1292      1.1  mrg 
   1293      1.1  mrg /* Assert that this object is valid.  */
   1294      1.1  mrg 
   1295      1.1  mrg void
   1296      1.1  mrg program_state::validate (const extrinsic_state &ext_state) const
   1297      1.1  mrg {
   1298      1.1  mrg   /* Skip this in a release build.  */
   1299      1.1  mrg #if !CHECKING_P
   1300      1.1  mrg   return;
   1301      1.1  mrg #endif
   1302      1.1  mrg 
   1303      1.1  mrg   gcc_assert (m_checker_states.length () == ext_state.get_num_checkers ());
   1304  1.1.1.2  mrg   m_region_model->validate ();
   1305      1.1  mrg }
   1306      1.1  mrg 
   1307  1.1.1.2  mrg static void
   1308  1.1.1.2  mrg log_set_of_svalues (logger *logger, const char *name,
   1309  1.1.1.2  mrg 		    const svalue_set &set)
   1310      1.1  mrg {
   1311  1.1.1.2  mrg   logger->log (name);
   1312  1.1.1.2  mrg   logger->inc_indent ();
   1313  1.1.1.2  mrg   auto_vec<const svalue *> sval_vecs (set.elements ());
   1314  1.1.1.2  mrg   for (svalue_set::iterator iter = set.begin ();
   1315  1.1.1.2  mrg        iter != set.end (); ++iter)
   1316  1.1.1.2  mrg     sval_vecs.quick_push (*iter);
   1317  1.1.1.2  mrg   sval_vecs.qsort (svalue::cmp_ptr_ptr);
   1318  1.1.1.2  mrg   unsigned i;
   1319  1.1.1.2  mrg   const svalue *sval;
   1320  1.1.1.2  mrg   FOR_EACH_VEC_ELT (sval_vecs, i, sval)
   1321  1.1.1.2  mrg     {
   1322  1.1.1.2  mrg       logger->start_log_line ();
   1323  1.1.1.2  mrg       pretty_printer *pp = logger->get_printer ();
   1324  1.1.1.2  mrg       if (!flag_dump_noaddr)
   1325  1.1.1.2  mrg 	{
   1326  1.1.1.2  mrg 	  pp_pointer (pp, sval);
   1327  1.1.1.2  mrg 	  pp_string (pp, ": ");
   1328  1.1.1.2  mrg 	}
   1329  1.1.1.2  mrg       sval->dump_to_pp (pp, false);
   1330  1.1.1.2  mrg       logger->end_log_line ();
   1331  1.1.1.2  mrg     }
   1332  1.1.1.2  mrg   logger->dec_indent ();
   1333      1.1  mrg }
   1334      1.1  mrg 
   1335  1.1.1.2  mrg /* Compare the sets of svalues reachable from each of SRC_STATE and DEST_STATE.
   1336  1.1.1.2  mrg    For all svalues that are reachable in SRC_STATE and are not live in
   1337  1.1.1.2  mrg    DEST_STATE (whether explicitly reachable in DEST_STATE, or implicitly live
   1338  1.1.1.2  mrg    based on the former set), call CTXT->on_svalue_leak for them.
   1339      1.1  mrg 
   1340  1.1.1.2  mrg    Call on_liveness_change on both the CTXT and on the DEST_STATE's
   1341  1.1.1.2  mrg    constraint_manager, purging dead svalues from sm-state and from
   1342  1.1.1.2  mrg    constraints, respectively.
   1343      1.1  mrg 
   1344  1.1.1.2  mrg    This function should be called at each fine-grained state change, not
   1345  1.1.1.2  mrg    just at exploded edges.  */
   1346      1.1  mrg 
   1347  1.1.1.2  mrg void
   1348  1.1.1.2  mrg program_state::detect_leaks (const program_state &src_state,
   1349  1.1.1.2  mrg 			     const program_state &dest_state,
   1350  1.1.1.2  mrg 			     const svalue *extra_sval,
   1351  1.1.1.2  mrg 			     const extrinsic_state &ext_state,
   1352  1.1.1.2  mrg 			     region_model_context *ctxt)
   1353      1.1  mrg {
   1354  1.1.1.2  mrg   logger *logger = ext_state.get_logger ();
   1355  1.1.1.2  mrg   LOG_SCOPE (logger);
   1356  1.1.1.2  mrg   const uncertainty_t *uncertainty = ctxt->get_uncertainty ();
   1357  1.1.1.2  mrg   if (logger)
   1358      1.1  mrg     {
   1359  1.1.1.2  mrg       pretty_printer *pp = logger->get_printer ();
   1360  1.1.1.2  mrg       logger->start_log_line ();
   1361  1.1.1.2  mrg       pp_string (pp, "src_state: ");
   1362  1.1.1.2  mrg       src_state.dump_to_pp (ext_state, true, false, pp);
   1363  1.1.1.2  mrg       logger->end_log_line ();
   1364  1.1.1.2  mrg       logger->start_log_line ();
   1365  1.1.1.2  mrg       pp_string (pp, "dest_state: ");
   1366  1.1.1.2  mrg       dest_state.dump_to_pp (ext_state, true, false, pp);
   1367  1.1.1.2  mrg       logger->end_log_line ();
   1368  1.1.1.2  mrg       if (extra_sval)
   1369  1.1.1.2  mrg 	{
   1370  1.1.1.2  mrg 	  logger->start_log_line ();
   1371  1.1.1.2  mrg 	  pp_string (pp, "extra_sval: ");
   1372  1.1.1.2  mrg 	  extra_sval->dump_to_pp (pp, true);
   1373  1.1.1.2  mrg 	  logger->end_log_line ();
   1374  1.1.1.2  mrg 	}
   1375  1.1.1.2  mrg       if (uncertainty)
   1376  1.1.1.2  mrg 	{
   1377  1.1.1.2  mrg 	  logger->start_log_line ();
   1378  1.1.1.2  mrg 	  pp_string (pp, "uncertainty: ");
   1379  1.1.1.2  mrg 	  uncertainty->dump_to_pp (pp, true);
   1380  1.1.1.2  mrg 	  logger->end_log_line ();
   1381  1.1.1.2  mrg 	}
   1382      1.1  mrg     }
   1383      1.1  mrg 
   1384  1.1.1.2  mrg   /* Get svalues reachable from each of src_state and dest_state.
   1385  1.1.1.2  mrg      Get svalues *known* to be reachable in src_state.
   1386  1.1.1.2  mrg      Pass in uncertainty for dest_state so that we additionally get svalues that
   1387  1.1.1.2  mrg      *might* still be reachable in dst_state.  */
   1388  1.1.1.2  mrg   svalue_set known_src_svalues;
   1389  1.1.1.2  mrg   src_state.m_region_model->get_reachable_svalues (&known_src_svalues,
   1390  1.1.1.2  mrg 						   NULL, NULL);
   1391  1.1.1.2  mrg   svalue_set maybe_dest_svalues;
   1392  1.1.1.2  mrg   dest_state.m_region_model->get_reachable_svalues (&maybe_dest_svalues,
   1393  1.1.1.2  mrg 						    extra_sval, uncertainty);
   1394      1.1  mrg 
   1395  1.1.1.2  mrg   if (logger)
   1396  1.1.1.2  mrg     {
   1397  1.1.1.2  mrg       log_set_of_svalues (logger, "src_state known reachable svalues:",
   1398  1.1.1.2  mrg 			  known_src_svalues);
   1399  1.1.1.2  mrg       log_set_of_svalues (logger, "dest_state maybe reachable svalues:",
   1400  1.1.1.2  mrg 			  maybe_dest_svalues);
   1401  1.1.1.2  mrg     }
   1402  1.1.1.2  mrg 
   1403  1.1.1.2  mrg   auto_vec <const svalue *> dead_svals (known_src_svalues.elements ());
   1404  1.1.1.2  mrg   for (svalue_set::iterator iter = known_src_svalues.begin ();
   1405  1.1.1.2  mrg        iter != known_src_svalues.end (); ++iter)
   1406  1.1.1.2  mrg     {
   1407  1.1.1.2  mrg       const svalue *sval = (*iter);
   1408  1.1.1.2  mrg       /* For each sval reachable from SRC_STATE, determine if it is
   1409  1.1.1.2  mrg 	 live in DEST_STATE: either explicitly reachable, implicitly
   1410  1.1.1.2  mrg 	 live based on the set of explicitly reachable svalues,
   1411  1.1.1.2  mrg 	 or possibly reachable as recorded in uncertainty.
   1412  1.1.1.2  mrg 	 Record those that have ceased to be live i.e. were known
   1413  1.1.1.2  mrg 	 to be live, and are now not known to be even possibly-live.  */
   1414  1.1.1.2  mrg       if (!sval->live_p (&maybe_dest_svalues, dest_state.m_region_model))
   1415  1.1.1.2  mrg 	dead_svals.quick_push (sval);
   1416  1.1.1.2  mrg     }
   1417  1.1.1.2  mrg 
   1418  1.1.1.2  mrg   /* Call CTXT->on_svalue_leak on all svals in SRC_STATE  that have ceased
   1419  1.1.1.2  mrg      to be live, sorting them first to ensure deterministic behavior.  */
   1420  1.1.1.2  mrg   dead_svals.qsort (svalue::cmp_ptr_ptr);
   1421  1.1.1.2  mrg   unsigned i;
   1422  1.1.1.2  mrg   const svalue *sval;
   1423  1.1.1.2  mrg   FOR_EACH_VEC_ELT (dead_svals, i, sval)
   1424  1.1.1.2  mrg     ctxt->on_svalue_leak (sval);
   1425      1.1  mrg 
   1426  1.1.1.2  mrg   /* Purge dead svals from sm-state.  */
   1427  1.1.1.2  mrg   ctxt->on_liveness_change (maybe_dest_svalues,
   1428  1.1.1.2  mrg 			    dest_state.m_region_model);
   1429      1.1  mrg 
   1430  1.1.1.2  mrg   /* Purge dead svals from constraints.  */
   1431  1.1.1.2  mrg   dest_state.m_region_model->get_constraints ()->on_liveness_change
   1432  1.1.1.2  mrg     (maybe_dest_svalues, dest_state.m_region_model);
   1433      1.1  mrg 
   1434  1.1.1.2  mrg   /* Purge dead heap-allocated regions from dynamic extents.  */
   1435  1.1.1.2  mrg   for (const svalue *sval : dead_svals)
   1436  1.1.1.2  mrg     if (const region *reg = sval->maybe_get_region ())
   1437  1.1.1.2  mrg       if (reg->get_kind () == RK_HEAP_ALLOCATED)
   1438  1.1.1.2  mrg 	dest_state.m_region_model->unset_dynamic_extents (reg);
   1439      1.1  mrg }
   1440      1.1  mrg 
   1441  1.1.1.2  mrg /* Handle calls to "__analyzer_dump_state".  */
   1442      1.1  mrg 
   1443      1.1  mrg void
   1444  1.1.1.2  mrg program_state::impl_call_analyzer_dump_state (const gcall *call,
   1445  1.1.1.2  mrg 					      const extrinsic_state &ext_state,
   1446  1.1.1.2  mrg 					      region_model_context *ctxt)
   1447      1.1  mrg {
   1448  1.1.1.2  mrg   call_details cd (call, m_region_model, ctxt);
   1449  1.1.1.2  mrg   const char *sm_name = cd.get_arg_string_literal (0);
   1450  1.1.1.2  mrg   if (!sm_name)
   1451      1.1  mrg     {
   1452  1.1.1.2  mrg       error_at (call->location, "cannot determine state machine");
   1453  1.1.1.2  mrg       return;
   1454      1.1  mrg     }
   1455  1.1.1.2  mrg   unsigned sm_idx;
   1456  1.1.1.2  mrg   if (!ext_state.get_sm_idx_by_name (sm_name, &sm_idx))
   1457      1.1  mrg     {
   1458  1.1.1.2  mrg       error_at (call->location, "unrecognized state machine %qs", sm_name);
   1459  1.1.1.2  mrg       return;
   1460      1.1  mrg     }
   1461  1.1.1.2  mrg   const sm_state_map *smap = m_checker_states[sm_idx];
   1462      1.1  mrg 
   1463  1.1.1.2  mrg   const svalue *sval = cd.get_arg_svalue (1);
   1464      1.1  mrg 
   1465  1.1.1.2  mrg   /* Strip off cast to int (due to variadic args).  */
   1466  1.1.1.2  mrg   if (const svalue *cast = sval->maybe_undo_cast ())
   1467  1.1.1.2  mrg     sval = cast;
   1468      1.1  mrg 
   1469  1.1.1.2  mrg   state_machine::state_t state = smap->get_state (sval, ext_state);
   1470  1.1.1.2  mrg   warning_at (call->location, 0, "state: %qs", state->get_name ());
   1471      1.1  mrg }
   1472      1.1  mrg 
   1473      1.1  mrg #if CHECKING_P
   1474      1.1  mrg 
   1475      1.1  mrg namespace selftest {
   1476      1.1  mrg 
   1477      1.1  mrg /* Tests for sm_state_map.  */
   1478      1.1  mrg 
   1479      1.1  mrg static void
   1480      1.1  mrg test_sm_state_map ()
   1481      1.1  mrg {
   1482      1.1  mrg   tree x = build_global_decl ("x", integer_type_node);
   1483      1.1  mrg   tree y = build_global_decl ("y", integer_type_node);
   1484      1.1  mrg   tree z = build_global_decl ("z", integer_type_node);
   1485      1.1  mrg 
   1486  1.1.1.2  mrg   state_machine *sm = make_malloc_state_machine (NULL);
   1487  1.1.1.2  mrg   auto_delete_vec <state_machine> checkers;
   1488  1.1.1.2  mrg   checkers.safe_push (sm);
   1489  1.1.1.2  mrg   engine eng;
   1490  1.1.1.2  mrg   extrinsic_state ext_state (checkers, &eng);
   1491  1.1.1.2  mrg   state_machine::state_t start = sm->get_start_state ();
   1492  1.1.1.2  mrg 
   1493      1.1  mrg   /* Test setting states on svalue_id instances directly.  */
   1494      1.1  mrg   {
   1495  1.1.1.2  mrg     const state_machine::state test_state_42 ("test state 42", 42);
   1496  1.1.1.2  mrg     const state_machine::state_t TEST_STATE_42 = &test_state_42;
   1497  1.1.1.2  mrg     region_model_manager mgr;
   1498  1.1.1.2  mrg     region_model model (&mgr);
   1499  1.1.1.2  mrg     const svalue *x_sval = model.get_rvalue (x, NULL);
   1500  1.1.1.2  mrg     const svalue *y_sval = model.get_rvalue (y, NULL);
   1501  1.1.1.2  mrg     const svalue *z_sval = model.get_rvalue (z, NULL);
   1502      1.1  mrg 
   1503  1.1.1.2  mrg     sm_state_map map (*sm);
   1504      1.1  mrg     ASSERT_TRUE (map.is_empty_p ());
   1505  1.1.1.2  mrg     ASSERT_EQ (map.get_state (x_sval, ext_state), start);
   1506      1.1  mrg 
   1507  1.1.1.2  mrg     map.impl_set_state (x_sval, TEST_STATE_42, z_sval, ext_state);
   1508  1.1.1.2  mrg     ASSERT_EQ (map.get_state (x_sval, ext_state), TEST_STATE_42);
   1509  1.1.1.2  mrg     ASSERT_EQ (map.get_origin (x_sval, ext_state), z_sval);
   1510  1.1.1.2  mrg     ASSERT_EQ (map.get_state (y_sval, ext_state), start);
   1511      1.1  mrg     ASSERT_FALSE (map.is_empty_p ());
   1512      1.1  mrg 
   1513  1.1.1.2  mrg     map.impl_set_state (y_sval, 0, z_sval, ext_state);
   1514  1.1.1.2  mrg     ASSERT_EQ (map.get_state (y_sval, ext_state), start);
   1515      1.1  mrg 
   1516  1.1.1.2  mrg     map.impl_set_state (x_sval, 0, z_sval, ext_state);
   1517  1.1.1.2  mrg     ASSERT_EQ (map.get_state (x_sval, ext_state), start);
   1518      1.1  mrg     ASSERT_TRUE (map.is_empty_p ());
   1519      1.1  mrg   }
   1520      1.1  mrg 
   1521  1.1.1.2  mrg   const state_machine::state test_state_5 ("test state 5", 5);
   1522  1.1.1.2  mrg   const state_machine::state_t TEST_STATE_5 = &test_state_5;
   1523  1.1.1.2  mrg 
   1524      1.1  mrg   /* Test setting states via equivalence classes.  */
   1525      1.1  mrg   {
   1526  1.1.1.2  mrg     region_model_manager mgr;
   1527  1.1.1.2  mrg     region_model model (&mgr);
   1528  1.1.1.2  mrg     const svalue *x_sval = model.get_rvalue (x, NULL);
   1529  1.1.1.2  mrg     const svalue *y_sval = model.get_rvalue (y, NULL);
   1530  1.1.1.2  mrg     const svalue *z_sval = model.get_rvalue (z, NULL);
   1531      1.1  mrg 
   1532  1.1.1.2  mrg     sm_state_map map (*sm);
   1533      1.1  mrg     ASSERT_TRUE (map.is_empty_p ());
   1534  1.1.1.2  mrg     ASSERT_EQ (map.get_state (x_sval, ext_state), start);
   1535  1.1.1.2  mrg     ASSERT_EQ (map.get_state (y_sval, ext_state), start);
   1536      1.1  mrg 
   1537      1.1  mrg     model.add_constraint (x, EQ_EXPR, y, NULL);
   1538      1.1  mrg 
   1539      1.1  mrg     /* Setting x to a state should also update y, as they
   1540      1.1  mrg        are in the same equivalence class.  */
   1541  1.1.1.2  mrg     map.set_state (&model, x_sval, TEST_STATE_5, z_sval, ext_state);
   1542  1.1.1.2  mrg     ASSERT_EQ (map.get_state (x_sval, ext_state), TEST_STATE_5);
   1543  1.1.1.2  mrg     ASSERT_EQ (map.get_state (y_sval, ext_state), TEST_STATE_5);
   1544  1.1.1.2  mrg     ASSERT_EQ (map.get_origin (x_sval, ext_state), z_sval);
   1545  1.1.1.2  mrg     ASSERT_EQ (map.get_origin (y_sval, ext_state), z_sval);
   1546      1.1  mrg   }
   1547      1.1  mrg 
   1548      1.1  mrg   /* Test equality and hashing.  */
   1549      1.1  mrg   {
   1550  1.1.1.2  mrg     region_model_manager mgr;
   1551  1.1.1.2  mrg     region_model model (&mgr);
   1552  1.1.1.2  mrg     const svalue *y_sval = model.get_rvalue (y, NULL);
   1553  1.1.1.2  mrg     const svalue *z_sval = model.get_rvalue (z, NULL);
   1554  1.1.1.2  mrg 
   1555  1.1.1.2  mrg     sm_state_map map0 (*sm);
   1556  1.1.1.2  mrg     sm_state_map map1 (*sm);
   1557  1.1.1.2  mrg     sm_state_map map2 (*sm);
   1558      1.1  mrg 
   1559      1.1  mrg     ASSERT_EQ (map0.hash (), map1.hash ());
   1560      1.1  mrg     ASSERT_EQ (map0, map1);
   1561      1.1  mrg 
   1562  1.1.1.2  mrg     map1.impl_set_state (y_sval, TEST_STATE_5, z_sval, ext_state);
   1563      1.1  mrg     ASSERT_NE (map0.hash (), map1.hash ());
   1564      1.1  mrg     ASSERT_NE (map0, map1);
   1565      1.1  mrg 
   1566      1.1  mrg     /* Make the same change to map2.  */
   1567  1.1.1.2  mrg     map2.impl_set_state (y_sval, TEST_STATE_5, z_sval, ext_state);
   1568      1.1  mrg     ASSERT_EQ (map1.hash (), map2.hash ());
   1569      1.1  mrg     ASSERT_EQ (map1, map2);
   1570      1.1  mrg   }
   1571      1.1  mrg 
   1572      1.1  mrg   /* Equality and hashing shouldn't depend on ordering.  */
   1573      1.1  mrg   {
   1574  1.1.1.2  mrg     const state_machine::state test_state_2 ("test state 2", 2);
   1575  1.1.1.2  mrg     const state_machine::state_t TEST_STATE_2 = &test_state_2;
   1576  1.1.1.2  mrg     const state_machine::state test_state_3 ("test state 3", 3);
   1577  1.1.1.2  mrg     const state_machine::state_t TEST_STATE_3 = &test_state_3;
   1578  1.1.1.2  mrg     sm_state_map map0 (*sm);
   1579  1.1.1.2  mrg     sm_state_map map1 (*sm);
   1580  1.1.1.2  mrg     sm_state_map map2 (*sm);
   1581      1.1  mrg 
   1582      1.1  mrg     ASSERT_EQ (map0.hash (), map1.hash ());
   1583      1.1  mrg     ASSERT_EQ (map0, map1);
   1584      1.1  mrg 
   1585  1.1.1.2  mrg     region_model_manager mgr;
   1586  1.1.1.2  mrg     region_model model (&mgr);
   1587  1.1.1.2  mrg     const svalue *x_sval = model.get_rvalue (x, NULL);
   1588  1.1.1.2  mrg     const svalue *y_sval = model.get_rvalue (y, NULL);
   1589  1.1.1.2  mrg     const svalue *z_sval = model.get_rvalue (z, NULL);
   1590  1.1.1.2  mrg 
   1591  1.1.1.2  mrg     map1.impl_set_state (x_sval, TEST_STATE_2, NULL, ext_state);
   1592  1.1.1.2  mrg     map1.impl_set_state (y_sval, TEST_STATE_3, NULL, ext_state);
   1593  1.1.1.2  mrg     map1.impl_set_state (z_sval, TEST_STATE_2, NULL, ext_state);
   1594  1.1.1.2  mrg 
   1595  1.1.1.2  mrg     map2.impl_set_state (z_sval, TEST_STATE_2, NULL, ext_state);
   1596  1.1.1.2  mrg     map2.impl_set_state (y_sval, TEST_STATE_3, NULL, ext_state);
   1597  1.1.1.2  mrg     map2.impl_set_state (x_sval, TEST_STATE_2, NULL, ext_state);
   1598      1.1  mrg 
   1599      1.1  mrg     ASSERT_EQ (map1.hash (), map2.hash ());
   1600      1.1  mrg     ASSERT_EQ (map1, map2);
   1601      1.1  mrg   }
   1602      1.1  mrg 
   1603      1.1  mrg   // TODO: coverage for purging
   1604      1.1  mrg }
   1605      1.1  mrg 
   1606  1.1.1.2  mrg /* Check program_state works as expected.  */
   1607      1.1  mrg 
   1608      1.1  mrg static void
   1609  1.1.1.2  mrg test_program_state_1 ()
   1610      1.1  mrg {
   1611      1.1  mrg   /* Create a program_state for a global ptr "p" that has
   1612      1.1  mrg      malloc sm-state, pointing to a region on the heap.  */
   1613      1.1  mrg   tree p = build_global_decl ("p", ptr_type_node);
   1614      1.1  mrg 
   1615      1.1  mrg   state_machine *sm = make_malloc_state_machine (NULL);
   1616      1.1  mrg   const state_machine::state_t UNCHECKED_STATE
   1617      1.1  mrg     = sm->get_state_by_name ("unchecked");
   1618      1.1  mrg   auto_delete_vec <state_machine> checkers;
   1619      1.1  mrg   checkers.safe_push (sm);
   1620      1.1  mrg 
   1621  1.1.1.2  mrg   engine eng;
   1622  1.1.1.2  mrg   extrinsic_state ext_state (checkers, &eng);
   1623  1.1.1.2  mrg   region_model_manager *mgr = eng.get_model_manager ();
   1624      1.1  mrg   program_state s (ext_state);
   1625      1.1  mrg   region_model *model = s.m_region_model;
   1626  1.1.1.2  mrg   const svalue *size_in_bytes
   1627  1.1.1.2  mrg     = mgr->get_or_create_unknown_svalue (size_type_node);
   1628  1.1.1.2  mrg   const region *new_reg
   1629  1.1.1.2  mrg     = model->create_region_for_heap_alloc (size_in_bytes, NULL);
   1630  1.1.1.2  mrg   const svalue *ptr_sval = mgr->get_ptr_svalue (ptr_type_node, new_reg);
   1631      1.1  mrg   model->set_value (model->get_lvalue (p, NULL),
   1632  1.1.1.2  mrg 		    ptr_sval, NULL);
   1633      1.1  mrg   sm_state_map *smap = s.m_checker_states[0];
   1634      1.1  mrg 
   1635  1.1.1.2  mrg   smap->impl_set_state (ptr_sval, UNCHECKED_STATE, NULL, ext_state);
   1636  1.1.1.2  mrg   ASSERT_EQ (smap->get_state (ptr_sval, ext_state), UNCHECKED_STATE);
   1637      1.1  mrg }
   1638      1.1  mrg 
   1639  1.1.1.2  mrg /* Check that program_state works for string literals.  */
   1640      1.1  mrg 
   1641      1.1  mrg static void
   1642  1.1.1.2  mrg test_program_state_2 ()
   1643      1.1  mrg {
   1644  1.1.1.2  mrg   /* Create a program_state for a global ptr "p" that points to
   1645  1.1.1.2  mrg      a string constant.  */
   1646      1.1  mrg   tree p = build_global_decl ("p", ptr_type_node);
   1647      1.1  mrg 
   1648      1.1  mrg   tree string_cst_ptr = build_string_literal (4, "foo");
   1649      1.1  mrg 
   1650      1.1  mrg   auto_delete_vec <state_machine> checkers;
   1651  1.1.1.2  mrg   engine eng;
   1652  1.1.1.2  mrg   extrinsic_state ext_state (checkers, &eng);
   1653      1.1  mrg 
   1654      1.1  mrg   program_state s (ext_state);
   1655      1.1  mrg   region_model *model = s.m_region_model;
   1656  1.1.1.2  mrg   const region *p_reg = model->get_lvalue (p, NULL);
   1657  1.1.1.2  mrg   const svalue *str_sval = model->get_rvalue (string_cst_ptr, NULL);
   1658  1.1.1.2  mrg   model->set_value (p_reg, str_sval, NULL);
   1659      1.1  mrg }
   1660      1.1  mrg 
   1661      1.1  mrg /* Verify that program_states with identical sm-state can be merged,
   1662      1.1  mrg    and that the merged program_state preserves the sm-state.  */
   1663      1.1  mrg 
   1664      1.1  mrg static void
   1665      1.1  mrg test_program_state_merging ()
   1666      1.1  mrg {
   1667      1.1  mrg   /* Create a program_state for a global ptr "p" that has
   1668      1.1  mrg      malloc sm-state, pointing to a region on the heap.  */
   1669      1.1  mrg   tree p = build_global_decl ("p", ptr_type_node);
   1670      1.1  mrg 
   1671  1.1.1.2  mrg   program_point point (program_point::origin ());
   1672      1.1  mrg   auto_delete_vec <state_machine> checkers;
   1673      1.1  mrg   checkers.safe_push (make_malloc_state_machine (NULL));
   1674  1.1.1.2  mrg   engine eng;
   1675  1.1.1.2  mrg   extrinsic_state ext_state (checkers, &eng);
   1676  1.1.1.2  mrg   region_model_manager *mgr = eng.get_model_manager ();
   1677      1.1  mrg 
   1678      1.1  mrg   program_state s0 (ext_state);
   1679  1.1.1.2  mrg   uncertainty_t uncertainty;
   1680  1.1.1.2  mrg   impl_region_model_context ctxt (&s0, ext_state, &uncertainty);
   1681      1.1  mrg 
   1682      1.1  mrg   region_model *model0 = s0.m_region_model;
   1683  1.1.1.2  mrg   const svalue *size_in_bytes
   1684  1.1.1.2  mrg     = mgr->get_or_create_unknown_svalue (size_type_node);
   1685  1.1.1.2  mrg   const region *new_reg
   1686  1.1.1.2  mrg     = model0->create_region_for_heap_alloc (size_in_bytes, NULL);
   1687  1.1.1.2  mrg   const svalue *ptr_sval = mgr->get_ptr_svalue (ptr_type_node, new_reg);
   1688      1.1  mrg   model0->set_value (model0->get_lvalue (p, &ctxt),
   1689  1.1.1.2  mrg 		     ptr_sval, &ctxt);
   1690      1.1  mrg   sm_state_map *smap = s0.m_checker_states[0];
   1691  1.1.1.2  mrg   const state_machine::state test_state ("test state", 0);
   1692  1.1.1.2  mrg   const state_machine::state_t TEST_STATE = &test_state;
   1693  1.1.1.2  mrg   smap->impl_set_state (ptr_sval, TEST_STATE, NULL, ext_state);
   1694  1.1.1.2  mrg   ASSERT_EQ (smap->get_state (ptr_sval, ext_state), TEST_STATE);
   1695      1.1  mrg 
   1696  1.1.1.2  mrg   model0->canonicalize ();
   1697      1.1  mrg 
   1698      1.1  mrg   /* Verify that canonicalization preserves sm-state.  */
   1699  1.1.1.2  mrg   ASSERT_EQ (smap->get_state (model0->get_rvalue (p, NULL), ext_state),
   1700  1.1.1.2  mrg 	     TEST_STATE);
   1701      1.1  mrg 
   1702      1.1  mrg   /* Make a copy of the program_state.  */
   1703      1.1  mrg   program_state s1 (s0);
   1704      1.1  mrg   ASSERT_EQ (s0, s1);
   1705      1.1  mrg 
   1706      1.1  mrg   /* We have two identical states with "p" pointing to a heap region
   1707      1.1  mrg      with the given sm-state.
   1708      1.1  mrg      They ought to be mergeable, preserving the sm-state.  */
   1709      1.1  mrg   program_state merged (ext_state);
   1710  1.1.1.2  mrg   ASSERT_TRUE (s0.can_merge_with_p (s1, ext_state, point, &merged));
   1711      1.1  mrg   merged.validate (ext_state);
   1712      1.1  mrg 
   1713      1.1  mrg   /* Verify that the merged state has the sm-state for "p".  */
   1714      1.1  mrg   region_model *merged_model = merged.m_region_model;
   1715      1.1  mrg   sm_state_map *merged_smap = merged.m_checker_states[0];
   1716  1.1.1.2  mrg   ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, NULL),
   1717  1.1.1.2  mrg 				     ext_state),
   1718      1.1  mrg 	     TEST_STATE);
   1719      1.1  mrg 
   1720      1.1  mrg   /* Try canonicalizing.  */
   1721  1.1.1.2  mrg   merged.m_region_model->canonicalize ();
   1722      1.1  mrg   merged.validate (ext_state);
   1723      1.1  mrg 
   1724      1.1  mrg   /* Verify that the merged state still has the sm-state for "p".  */
   1725  1.1.1.2  mrg   ASSERT_EQ (merged_smap->get_state (merged_model->get_rvalue (p, NULL),
   1726  1.1.1.2  mrg 				     ext_state),
   1727      1.1  mrg 	     TEST_STATE);
   1728      1.1  mrg 
   1729      1.1  mrg   /* After canonicalization, we ought to have equality with the inputs.  */
   1730      1.1  mrg   ASSERT_EQ (s0, merged);
   1731      1.1  mrg }
   1732      1.1  mrg 
   1733      1.1  mrg /* Verify that program_states with different global-state in an sm-state
   1734      1.1  mrg    can't be merged.  */
   1735      1.1  mrg 
   1736      1.1  mrg static void
   1737      1.1  mrg test_program_state_merging_2 ()
   1738      1.1  mrg {
   1739  1.1.1.2  mrg   program_point point (program_point::origin ());
   1740      1.1  mrg   auto_delete_vec <state_machine> checkers;
   1741      1.1  mrg   checkers.safe_push (make_signal_state_machine (NULL));
   1742  1.1.1.2  mrg   engine eng;
   1743  1.1.1.2  mrg   extrinsic_state ext_state (checkers, &eng);
   1744  1.1.1.2  mrg 
   1745  1.1.1.2  mrg   const state_machine::state test_state_0 ("test state 0", 0);
   1746  1.1.1.2  mrg   const state_machine::state test_state_1 ("test state 1", 1);
   1747  1.1.1.2  mrg   const state_machine::state_t TEST_STATE_0 = &test_state_0;
   1748  1.1.1.2  mrg   const state_machine::state_t TEST_STATE_1 = &test_state_1;
   1749      1.1  mrg 
   1750      1.1  mrg   program_state s0 (ext_state);
   1751      1.1  mrg   {
   1752      1.1  mrg     sm_state_map *smap0 = s0.m_checker_states[0];
   1753      1.1  mrg     smap0->set_global_state (TEST_STATE_0);
   1754      1.1  mrg     ASSERT_EQ (smap0->get_global_state (), TEST_STATE_0);
   1755      1.1  mrg   }
   1756      1.1  mrg 
   1757      1.1  mrg   program_state s1 (ext_state);
   1758      1.1  mrg   {
   1759      1.1  mrg     sm_state_map *smap1 = s1.m_checker_states[0];
   1760      1.1  mrg     smap1->set_global_state (TEST_STATE_1);
   1761      1.1  mrg     ASSERT_EQ (smap1->get_global_state (), TEST_STATE_1);
   1762      1.1  mrg   }
   1763      1.1  mrg 
   1764      1.1  mrg   ASSERT_NE (s0, s1);
   1765      1.1  mrg 
   1766      1.1  mrg   /* They ought to not be mergeable.  */
   1767      1.1  mrg   program_state merged (ext_state);
   1768  1.1.1.2  mrg   ASSERT_FALSE (s0.can_merge_with_p (s1, ext_state, point, &merged));
   1769      1.1  mrg }
   1770      1.1  mrg 
   1771      1.1  mrg /* Run all of the selftests within this file.  */
   1772      1.1  mrg 
   1773      1.1  mrg void
   1774      1.1  mrg analyzer_program_state_cc_tests ()
   1775      1.1  mrg {
   1776      1.1  mrg   test_sm_state_map ();
   1777  1.1.1.2  mrg   test_program_state_1 ();
   1778  1.1.1.2  mrg   test_program_state_2 ();
   1779      1.1  mrg   test_program_state_merging ();
   1780      1.1  mrg   test_program_state_merging_2 ();
   1781      1.1  mrg }
   1782      1.1  mrg 
   1783      1.1  mrg } // namespace selftest
   1784      1.1  mrg 
   1785      1.1  mrg #endif /* CHECKING_P */
   1786      1.1  mrg 
   1787      1.1  mrg } // namespace ana
   1788      1.1  mrg 
   1789      1.1  mrg #endif /* #if ENABLE_ANALYZER */
   1790