LCOV - code coverage report
Current view: top level - gcc/analyzer - store.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.8 % 1984 1643
Test Date: 2026-05-30 15:37:04 Functions: 87.3 % 165 144
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Classes for modeling the state of memory.
       2              :    Copyright (C) 2020-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              : #include "analyzer/common.h"
      22              : 
      23              : #include "ordered-hash-map.h"
      24              : #include "cfg.h"
      25              : #include "sbitmap.h"
      26              : #include "stor-layout.h"
      27              : 
      28              : #include "text-art/tree-widget.h"
      29              : 
      30              : #include "analyzer/analyzer-logging.h"
      31              : #include "analyzer/supergraph.h"
      32              : #include "analyzer/call-string.h"
      33              : #include "analyzer/program-point.h"
      34              : #include "analyzer/store.h"
      35              : #include "analyzer/region-model.h"
      36              : #include "analyzer/call-summary.h"
      37              : #include "analyzer/analyzer-selftests.h"
      38              : 
      39              : #if ENABLE_ANALYZER
      40              : 
      41              : namespace ana {
      42              : 
      43              : /* Dump SVALS to PP, sorting them to ensure determinism.  */
      44              : 
      45              : static void
      46          482 : dump_svalue_set (const hash_set <const svalue *> &svals,
      47              :                  pretty_printer *pp, bool simple)
      48              : {
      49          482 :   auto_vec <const svalue *> v;
      50          482 :   for (hash_set<const svalue *>::iterator iter = svals.begin ();
      51          552 :        iter != svals.end (); ++iter)
      52              :     {
      53           35 :       v.safe_push (*iter);
      54              :     }
      55          482 :   v.qsort (svalue::cmp_ptr_ptr);
      56              : 
      57          482 :   pp_character (pp, '{');
      58          482 :   const svalue *sval;
      59          482 :   unsigned i;
      60          999 :   FOR_EACH_VEC_ELT (v, i, sval)
      61              :     {
      62           35 :       if (i > 0)
      63           20 :         pp_string (pp, ", ");
      64           35 :       sval->dump_to_pp (pp, simple);
      65              :     }
      66          482 :   pp_character (pp, '}');
      67          482 : }
      68              : 
      69              : /* class uncertainty_t.  */
      70              : 
      71              : /* Dump this object to PP.  */
      72              : 
      73              : void
      74          241 : uncertainty_t::dump_to_pp (pretty_printer *pp, bool simple) const
      75              : {
      76          241 :   pp_string (pp, "{m_maybe_bound_svals: ");
      77          241 :   dump_svalue_set (m_maybe_bound_svals, pp, simple);
      78              : 
      79          241 :   pp_string (pp, ", m_mutable_at_unknown_call_svals: ");
      80          241 :   dump_svalue_set (m_mutable_at_unknown_call_svals, pp, simple);
      81          241 :   pp_string (pp, "}");
      82          241 : }
      83              : 
      84              : /* Dump this object to stderr.  */
      85              : 
      86              : DEBUG_FUNCTION void
      87            0 : uncertainty_t::dump (bool simple) const
      88              : {
      89            0 :   tree_dump_pretty_printer pp (stderr);
      90            0 :   dump_to_pp (&pp, simple);
      91            0 :   pp_newline (&pp);
      92            0 : }
      93              : 
      94              : /* class binding_key.  */
      95              : 
      96              : const binding_key *
      97      3688425 : binding_key::make (store_manager *mgr, const region *r)
      98              : {
      99      3688425 :   region_offset offset = r->get_offset (mgr->get_svalue_manager ());
     100      3688425 :   if (offset.symbolic_p ())
     101        34902 :     return mgr->get_symbolic_binding (r);
     102              :   else
     103              :     {
     104      3653523 :       bit_size_t bit_size;
     105      3653523 :       if (r->get_bit_size (&bit_size))
     106              :         {
     107              :           /* Must be non-empty.  */
     108      2307823 :           gcc_assert (bit_size > 0);
     109      2307823 :           return mgr->get_concrete_binding (offset.get_bit_offset (),
     110      2307823 :                                             bit_size);
     111              :         }
     112              :       else
     113      1345700 :         return mgr->get_symbolic_binding (r);
     114              :     }
     115              : }
     116              : 
     117              : /* Dump this binding_key to stderr.  */
     118              : 
     119              : DEBUG_FUNCTION void
     120            0 : binding_key::dump (bool simple) const
     121              : {
     122            0 :   tree_dump_pretty_printer pp (stderr);
     123            0 :   dump_to_pp (&pp, simple);
     124            0 :   pp_newline (&pp);
     125            0 : }
     126              : 
     127              : /* Get a description of this binding_key.  */
     128              : 
     129              : label_text
     130            0 : binding_key::get_desc (bool simple) const
     131              : {
     132            0 :   pretty_printer pp;
     133            0 :   pp_format_decoder (&pp) = default_tree_printer;
     134            0 :   dump_to_pp (&pp, simple);
     135            0 :   return label_text::take (xstrdup (pp_formatted_text (&pp)));
     136            0 : }
     137              : 
     138              : /* qsort callback.  */
     139              : 
     140              : int
     141            0 : binding_key::cmp_ptrs (const void *p1, const void *p2)
     142              : {
     143            0 :   const binding_key * const *pk1 = (const binding_key * const *)p1;
     144            0 :   const binding_key * const *pk2 = (const binding_key * const *)p2;
     145            0 :   return cmp (*pk1, *pk2);
     146              : }
     147              : 
     148              : /* Comparator for binding_keys.  */
     149              : 
     150              : int
     151            0 : binding_key::cmp (const binding_key *k1, const binding_key *k2)
     152              : {
     153            0 :   int concrete1 = k1->concrete_p ();
     154            0 :   int concrete2 = k2->concrete_p ();
     155            0 :   if (int concrete_cmp = concrete1 - concrete2)
     156              :     return concrete_cmp;
     157            0 :   if (concrete1)
     158              :     {
     159            0 :       const concrete_binding *b1 = (const concrete_binding *)k1;
     160            0 :       const concrete_binding *b2 = (const concrete_binding *)k2;
     161            0 :       if (int start_cmp = wi::cmp (b1->get_start_bit_offset (),
     162            0 :                                    b2->get_start_bit_offset (),
     163              :                                    SIGNED))
     164              :         return start_cmp;
     165            0 :       return wi::cmp (b1->get_next_bit_offset (), b2->get_next_bit_offset (),
     166              :                       SIGNED);
     167              :     }
     168              :   else
     169              :     {
     170            0 :       const symbolic_binding *s1 = (const symbolic_binding *)k1;
     171            0 :       const symbolic_binding *s2 = (const symbolic_binding *)k2;
     172            0 :       if (s1 > s2)
     173              :         return 1;
     174            0 :       if (s1 < s2)
     175              :         return -1;
     176            0 :       return 0;
     177              :     }
     178              : }
     179              : 
     180              : /* struct bit_range.  */
     181              : 
     182              : void
     183         2021 : bit_range::dump_to_pp (pretty_printer *pp) const
     184              : {
     185         2021 :   byte_range bytes (0, 0);
     186         2021 :   if (as_byte_range (&bytes))
     187         2021 :     bytes.dump_to_pp (pp);
     188              :   else
     189              :     {
     190            0 :       pp_string (pp, "start: ");
     191            0 :       pp_wide_int (pp, m_start_bit_offset, SIGNED);
     192            0 :       pp_string (pp, ", size: ");
     193            0 :       pp_wide_int (pp, m_size_in_bits, SIGNED);
     194            0 :       pp_string (pp, ", next: ");
     195            0 :       pp_wide_int (pp, get_next_bit_offset (), SIGNED);
     196              :     }
     197         2021 : }
     198              : 
     199              : /* Dump this object to stderr.  */
     200              : 
     201              : DEBUG_FUNCTION void
     202            0 : bit_range::dump () const
     203              : {
     204            0 :   tree_dump_pretty_printer pp (stderr);
     205            0 :   dump_to_pp (&pp);
     206            0 :   pp_newline (&pp);
     207            0 : }
     208              : 
     209              : /* Generate a JSON value for this bit_range.
     210              :    This is intended for debugging the analyzer rather
     211              :    than serialization.  */
     212              : 
     213              : std::unique_ptr<json::object>
     214            4 : bit_range::to_json () const
     215              : {
     216            4 :   auto obj = std::make_unique<json::object> ();
     217            4 :   obj->set ("start_bit_offset",
     218            4 :             bit_offset_to_json (m_start_bit_offset));
     219            4 :   obj->set ("size_in_bits",
     220            4 :             bit_offset_to_json (m_size_in_bits));
     221            4 :   return obj;
     222              : }
     223              : 
     224              : /* If OTHER is a subset of this, return true and, if OUT is
     225              :    non-null, write to *OUT the relative range of OTHER within this.
     226              :    Otherwise return false.  */
     227              : 
     228              : bool
     229        23827 : bit_range::contains_p (const bit_range &other, bit_range *out) const
     230              : {
     231        23827 :   if (contains_p (other.get_start_bit_offset ())
     232        23827 :       && contains_p (other.get_last_bit_offset ()))
     233              :     {
     234        16289 :       if (out)
     235              :         {
     236        16289 :           out->m_start_bit_offset = other.m_start_bit_offset - m_start_bit_offset;
     237        16289 :           out->m_size_in_bits = other.m_size_in_bits;
     238              :         }
     239        16289 :       return true;
     240              :     }
     241              :   else
     242         7538 :     return false;
     243              : }
     244              : 
     245              : /* If OTHER intersects this, return true and write
     246              :    the relative range of OTHER within THIS to *OUT_THIS,
     247              :    and the relative range of THIS within OTHER to *OUT_OTHER.
     248              :    Otherwise return false.  */
     249              : 
     250              : bool
     251           84 : bit_range::intersects_p (const bit_range &other,
     252              :                          bit_range *out_this,
     253              :                          bit_range *out_other) const
     254              : {
     255           84 :   if (get_start_bit_offset () < other.get_next_bit_offset ()
     256          168 :       && other.get_start_bit_offset () < get_next_bit_offset ())
     257              :     {
     258           84 :       bit_offset_t overlap_start
     259           84 :         = MAX (get_start_bit_offset (),
     260              :                other.get_start_bit_offset ());
     261           84 :       bit_offset_t overlap_next
     262           84 :         = MIN (get_next_bit_offset (),
     263              :                other.get_next_bit_offset ());
     264           84 :       if (overlap_next <= overlap_start)
     265              :         /* If this has happened, some kind of overflow has happened in
     266              :            our arithmetic.  For now, reject such cases.  */
     267              :         return false;
     268           84 :       bit_range abs_overlap_bits (overlap_start, overlap_next - overlap_start);
     269           84 :       *out_this = abs_overlap_bits - get_start_bit_offset ();
     270           84 :       *out_other = abs_overlap_bits - other.get_start_bit_offset ();
     271           84 :       return true;
     272              :     }
     273              :   else
     274            0 :     return false;
     275              : }
     276              : 
     277              : /* Return true if THIS and OTHER intersect and write the number
     278              :    of bits both buffers overlap to *OUT_NUM_OVERLAP_BITS.
     279              : 
     280              :    Otherwise return false.  */
     281              : 
     282              : bool
     283            0 : bit_range::intersects_p (const bit_range &other,
     284              :                          bit_size_t *out_num_overlap_bits) const
     285              : {
     286            0 :   if (get_start_bit_offset () < other.get_next_bit_offset ()
     287            0 :       && other.get_start_bit_offset () < get_next_bit_offset ())
     288              :     {
     289            0 :       bit_offset_t overlap_start = MAX (get_start_bit_offset (),
     290              :                                          other.get_start_bit_offset ());
     291            0 :       bit_offset_t overlap_next = MIN (get_next_bit_offset (),
     292              :                                         other.get_next_bit_offset ());
     293            0 :       if (overlap_next <= overlap_start)
     294              :         /* If this has happened, some kind of overflow has happened in
     295              :            our arithmetic.  For now, reject such cases.  */
     296              :         return false;
     297            0 :       *out_num_overlap_bits = overlap_next - overlap_start;
     298            0 :       return true;
     299              :     }
     300              :   else
     301            0 :     return false;
     302              : }
     303              : 
     304              : /* Return true if THIS exceeds OTHER and write the overhanging
     305              :    bit range to OUT_OVERHANGING_BIT_RANGE.  */
     306              : 
     307              : bool
     308       815303 : bit_range::exceeds_p (const bit_range &other,
     309              :                       bit_range *out_overhanging_bit_range) const
     310              : {
     311       815303 :   gcc_assert (!empty_p ());
     312              : 
     313       815303 :   if (other.get_next_bit_offset () < get_next_bit_offset ())
     314              :     {
     315              :       /* THIS definitely exceeds OTHER.  */
     316          460 :       bit_offset_t start = MAX (get_start_bit_offset (),
     317              :                                  other.get_next_bit_offset ());
     318          460 :       bit_offset_t size = get_next_bit_offset () - start;
     319          460 :       if (size <= 0)
     320              :         /* If this has happened, some kind of overflow has happened in
     321              :            our arithmetic.  For now, reject such cases.  */
     322              :         return false;
     323          440 :       out_overhanging_bit_range->m_start_bit_offset = start;
     324          440 :       out_overhanging_bit_range->m_size_in_bits = size;
     325          440 :       return true;
     326              :     }
     327              :   else
     328              :     return false;
     329              : }
     330              : 
     331              : /* Return true if THIS falls short of OFFSET and write the
     332              :    bit range fallen short to OUT_FALL_SHORT_BITS.  */
     333              : 
     334              : bool
     335       818993 : bit_range::falls_short_of_p (bit_offset_t offset,
     336              :                              bit_range *out_fall_short_bits) const
     337              : {
     338       818993 :   gcc_assert (!empty_p ());
     339              : 
     340       818993 :   if (get_start_bit_offset () < offset)
     341              :     {
     342              :       /* THIS falls short of OFFSET.  */
     343          212 :       bit_offset_t start = get_start_bit_offset ();
     344          212 :       bit_offset_t size = MIN (offset, get_next_bit_offset ()) - start;
     345          212 :       if (size <= 0)
     346              :         /* If this has happened, some kind of overflow has happened in
     347              :            our arithmetic.  For now, reject such cases.  */
     348              :         return false;
     349          192 :       out_fall_short_bits->m_start_bit_offset = start;
     350          192 :       out_fall_short_bits->m_size_in_bits = size;
     351          192 :       return true;
     352              :     }
     353              :   else
     354              :     return false;
     355              : }
     356              : 
     357              : int
     358          442 : bit_range::cmp (const bit_range &br1, const bit_range &br2)
     359              : {
     360          442 :   if (int start_cmp = wi::cmps (br1.m_start_bit_offset,
     361          442 :                                 br2.m_start_bit_offset))
     362              :     return start_cmp;
     363              : 
     364           48 :   return wi::cmpu (br1.m_size_in_bits, br2.m_size_in_bits);
     365              : }
     366              : 
     367              : /* Offset this range by OFFSET.  */
     368              : 
     369              : bit_range
     370          168 : bit_range::operator- (bit_offset_t offset) const
     371              : {
     372          168 :   return bit_range (m_start_bit_offset - offset, m_size_in_bits);
     373              : }
     374              : 
     375              : /* If MASK is a contiguous range of set bits, write them
     376              :    to *OUT and return true.
     377              :    Otherwise return false.  */
     378              : 
     379              : bool
     380          144 : bit_range::from_mask (unsigned HOST_WIDE_INT mask, bit_range *out)
     381              : {
     382          144 :   unsigned iter_bit_idx = 0;
     383          144 :   unsigned HOST_WIDE_INT iter_bit_mask = 1;
     384              : 
     385              :   /* Find the first contiguous run of set bits in MASK.  */
     386              : 
     387              :   /* Find first set bit in MASK.  */
     388          780 :   while (iter_bit_idx < HOST_BITS_PER_WIDE_INT)
     389              :     {
     390          776 :       if (mask & iter_bit_mask)
     391              :         break;
     392          636 :       iter_bit_idx++;
     393          636 :       iter_bit_mask <<= 1;
     394              :     }
     395          144 :   if (iter_bit_idx == HOST_BITS_PER_WIDE_INT)
     396              :     /* MASK is zero.  */
     397              :     return false;
     398              : 
     399          140 :   unsigned first_set_iter_bit_idx = iter_bit_idx;
     400          140 :   unsigned num_set_bits = 1;
     401          140 :   iter_bit_idx++;
     402          140 :   iter_bit_mask <<= 1;
     403              : 
     404              :   /* Find next unset bit in MASK.  */
     405          396 :   while (iter_bit_idx < HOST_BITS_PER_WIDE_INT)
     406              :     {
     407          396 :       if (!(mask & iter_bit_mask))
     408              :         break;
     409          256 :       num_set_bits++;
     410          256 :       iter_bit_idx++;
     411          256 :       iter_bit_mask <<= 1;
     412              :     }
     413          140 :   if (iter_bit_idx == HOST_BITS_PER_WIDE_INT)
     414              :     {
     415            0 :       *out = bit_range (first_set_iter_bit_idx, num_set_bits);
     416            0 :       return true;
     417              :     }
     418              : 
     419              :   /* We now have the first contiguous run of set bits in MASK.
     420              :      Fail if any other bits are set.  */
     421         7892 :   while (iter_bit_idx < HOST_BITS_PER_WIDE_INT)
     422              :     {
     423         7760 :       if (mask & iter_bit_mask)
     424              :         return false;
     425         7752 :       iter_bit_idx++;
     426         7752 :       iter_bit_mask <<= 1;
     427              :     }
     428              : 
     429          132 :   *out = bit_range (first_set_iter_bit_idx, num_set_bits);
     430          132 :   return true;
     431              : }
     432              : 
     433              : /* Attempt to convert this bit_range to a byte_range.
     434              :    Return true if it is possible, writing the result to *OUT.
     435              :    Otherwise return false.  */
     436              : 
     437              : bool
     438         8199 : bit_range::as_byte_range (byte_range *out) const
     439              : {
     440         8199 :   if (m_start_bit_offset % BITS_PER_UNIT == 0
     441         8199 :       && m_size_in_bits % BITS_PER_UNIT == 0)
     442              :     {
     443         8186 :       out->m_start_byte_offset = m_start_bit_offset / BITS_PER_UNIT;
     444         8186 :       out->m_size_in_bytes = m_size_in_bits / BITS_PER_UNIT;
     445         8186 :       return true;
     446              :     }
     447              :   return false;
     448              : }
     449              : 
     450              : /* Dump this object to PP.  */
     451              : 
     452              : void
     453         2024 : byte_range::dump_to_pp (pretty_printer *pp) const
     454              : {
     455         2024 :   if (m_size_in_bytes == 0)
     456              :     {
     457            0 :       pp_string (pp, "empty");
     458              :     }
     459         2024 :   else if (m_size_in_bytes == 1)
     460              :     {
     461         1447 :       pp_string (pp, "byte ");
     462         1447 :       pp_wide_int (pp, m_start_byte_offset, SIGNED);
     463              :     }
     464              :   else
     465              :     {
     466          577 :       pp_string (pp, "bytes ");
     467          577 :       pp_wide_int (pp, m_start_byte_offset, SIGNED);
     468          577 :       pp_string (pp, "-");
     469          577 :       pp_wide_int (pp, get_last_byte_offset (), SIGNED);
     470              :     }
     471         2024 : }
     472              : 
     473              : /* Dump this object to stderr.  */
     474              : 
     475              : DEBUG_FUNCTION void
     476            0 : byte_range::dump () const
     477              : {
     478            0 :   tree_dump_pretty_printer pp (stderr);
     479            0 :   dump_to_pp (&pp);
     480            0 :   pp_newline (&pp);
     481            0 : }
     482              : 
     483              : /* Generate a JSON value for this byte_range.
     484              :    This is intended for debugging the analyzer rather
     485              :    than serialization.  */
     486              : 
     487              : std::unique_ptr<json::object>
     488            4 : byte_range::to_json () const
     489              : {
     490            4 :   auto obj = std::make_unique<json::object> ();
     491            4 :   obj->set ("start_byte_offset",
     492            4 :             byte_offset_to_json (m_start_byte_offset));
     493            4 :   obj->set ("size_in_bytes",
     494            4 :             byte_offset_to_json (m_size_in_bytes));
     495            4 :   return obj;
     496              : }
     497              : 
     498              : /* If OTHER is a subset of this, return true and write
     499              :    to *OUT the relative range of OTHER within this.
     500              :    Otherwise return false.  */
     501              : 
     502              : bool
     503          948 : byte_range::contains_p (const byte_range &other, byte_range *out) const
     504              : {
     505          948 :   if (contains_p (other.get_start_byte_offset ())
     506          948 :       && contains_p (other.get_last_byte_offset ()))
     507              :     {
     508          396 :       out->m_start_byte_offset = other.m_start_byte_offset - m_start_byte_offset;
     509          396 :       out->m_size_in_bytes = other.m_size_in_bytes;
     510          396 :       return true;
     511              :     }
     512              :   else
     513          552 :     return false;
     514              : }
     515              : 
     516              : /* qsort comparator for byte ranges.  */
     517              : 
     518              : int
     519         1977 : byte_range::cmp (const byte_range &br1, const byte_range &br2)
     520              : {
     521              :   /* Order first by offset.  */
     522         1977 :   if (int start_cmp = wi::cmps (br1.m_start_byte_offset,
     523         1977 :                                 br2.m_start_byte_offset))
     524              :     return start_cmp;
     525              : 
     526              :   /* ...then by size.  */
     527            0 :   return wi::cmpu (br1.m_size_in_bytes, br2.m_size_in_bytes);
     528              : }
     529              : 
     530              : /* class concrete_binding : public binding_key.  */
     531              : 
     532              : /* Implementation of binding_key::dump_to_pp vfunc for concrete_binding.  */
     533              : 
     534              : void
     535         1133 : concrete_binding::dump_to_pp (pretty_printer *pp, bool) const
     536              : {
     537         1133 :   m_bit_range.dump_to_pp (pp);
     538         1133 : }
     539              : 
     540              : /* Return true if this binding overlaps with OTHER.  */
     541              : 
     542              : bool
     543       305487 : concrete_binding::overlaps_p (const concrete_binding &other) const
     544              : {
     545       305487 :   if (get_start_bit_offset () < other.get_next_bit_offset ()
     546       305487 :       && get_next_bit_offset () > other.get_start_bit_offset ())
     547        60332 :     return true;
     548              :   return false;
     549              : }
     550              : 
     551              : /* If this is expressible as a concrete byte range, return true
     552              :    and write it to *OUT.  Otherwise return false.  */
     553              : 
     554              : bool
     555            0 : concrete_binding::get_byte_range (byte_range *out) const
     556              : {
     557            0 :   return m_bit_range.as_byte_range (out);
     558              : }
     559              : 
     560              : /* Comparator for use by vec<const concrete_binding *>::qsort.  */
     561              : 
     562              : int
     563           41 : concrete_binding::cmp_ptr_ptr (const void *p1, const void *p2)
     564              : {
     565           41 :   const concrete_binding *b1 = *(const concrete_binding * const *)p1;
     566           41 :   const concrete_binding *b2 = *(const concrete_binding * const *)p2;
     567              : 
     568           41 :   return bit_range::cmp (b1->m_bit_range, b2->m_bit_range);
     569              : }
     570              : 
     571              : /* class symbolic_binding : public binding_key.  */
     572              : 
     573              : void
     574           16 : symbolic_binding::dump_to_pp (pretty_printer *pp, bool simple) const
     575              : {
     576              :   //binding_key::dump_to_pp (pp, simple);
     577           16 :   pp_string (pp, "region: ");
     578           16 :   m_region->dump_to_pp (pp, simple);
     579           16 : }
     580              : 
     581              : /* Comparator for use by vec<const symbolic_binding *>::qsort.  */
     582              : 
     583              : int
     584           19 : symbolic_binding::cmp_ptr_ptr (const void *p1, const void *p2)
     585              : {
     586           19 :   const symbolic_binding *b1 = *(const symbolic_binding * const *)p1;
     587           19 :   const symbolic_binding *b2 = *(const symbolic_binding * const *)p2;
     588              : 
     589           19 :   return region::cmp_ids (b1->get_region (), b2->get_region ());
     590              : }
     591              : 
     592              : /* The store is oblivious to the types of the svalues bound within
     593              :    it: any type can get bound at any location.
     594              :    Simplify any casts before binding.
     595              : 
     596              :    For example, if we have:
     597              :      struct big { int ia[1024]; };
     598              :      struct big src, dst;
     599              :      memcpy (&dst, &src, sizeof (struct big));
     600              :    this reaches us in gimple form as:
     601              :      MEM <unsigned char[4096]> [(char * {ref-all})&dst]
     602              :        = MEM <unsigned char[4096]> [(char * {ref-all})&src];
     603              :    Using cast_region when handling the MEM_REF would give us:
     604              :      INIT_VAL(CAST_REG(unsigned char[4096], src))
     605              :    as rhs_sval, but we can fold that into a cast svalue:
     606              :      CAST(unsigned char[4096], INIT_VAL(src))
     607              :    We can discard that cast from the svalue when binding it in
     608              :    the store for "dst", and simply store:
     609              :      cluster for: dst
     610              :        key:   {kind: direct, start: 0, size: 32768, next: 32768}
     611              :        value: ‘struct big’ {INIT_VAL(src)}.  */
     612              : 
     613              : static const svalue *
     614       425799 : simplify_for_binding (const svalue *sval)
     615              : {
     616       425799 :   if (const svalue *cast_sval = sval->maybe_undo_cast ())
     617            0 :     sval = cast_sval;
     618        46064 :   return sval;
     619              : }
     620              : 
     621              : /* class concrete_binding_map.  */
     622              : 
     623              : /* Dump a representation of this concrete_binding_map to PP.
     624              :    SIMPLE controls how values and regions are to be printed.
     625              :    If MULTILINE, then split the dump over multiple lines and
     626              :    use whitespace for readability, otherwise put all on one line.  */
     627              : 
     628              : void
     629            2 : concrete_binding_map::dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const
     630              : {
     631            2 :   bool first = true;
     632            4 :   for (auto iter : *this)
     633              :     {
     634            2 :       const bit_range &bits = iter.first;
     635            2 :       const svalue *value = iter.second;
     636            2 :       if (multiline)
     637              :         {
     638            0 :           pp_string (pp, "    bits:   {");
     639            0 :           bits.dump_to_pp (pp);
     640            0 :           pp_string (pp, "}");
     641            0 :           pp_newline (pp);
     642            0 :           pp_string (pp, "    value: ");
     643            0 :           if (tree t = value->get_type ())
     644            0 :             dump_quoted_tree (pp, t);
     645            0 :           pp_string (pp, " {");
     646            0 :           value->dump_to_pp (pp, simple);
     647            0 :           pp_string (pp, "}");
     648            0 :           pp_newline (pp);
     649              :         }
     650              :       else
     651              :         {
     652            2 :           if (first)
     653              :             first = false;
     654              :           else
     655            0 :             pp_string (pp, ", ");
     656            2 :           pp_string (pp, "bits: {");
     657            2 :           bits.dump_to_pp (pp);
     658            2 :           pp_string (pp, "}, value: {");
     659            2 :           value->dump_to_pp (pp, simple);
     660            2 :           pp_string (pp, "}");
     661              :         }
     662              :     }
     663            2 : }
     664              : 
     665              : void
     666            0 : concrete_binding_map::dump (bool simple) const
     667              : {
     668            0 :   tree_dump_pretty_printer pp (stderr);
     669            0 :   dump_to_pp (&pp, simple, true);
     670            0 :   pp_newline (&pp);
     671            0 : }
     672              : 
     673              : void
     674            0 : concrete_binding_map::add_to_tree_widget (text_art::tree_widget &parent_widget,
     675              :                                           const text_art::dump_widget_info &dwi) const
     676              : {
     677            0 :   for (auto iter : *this)
     678              :     {
     679            0 :       const bit_range &bits = iter.first;
     680            0 :       const svalue *sval = iter.second;
     681              : 
     682            0 :       pretty_printer the_pp;
     683            0 :       pretty_printer * const pp = &the_pp;
     684            0 :       pp_format_decoder (pp) = default_tree_printer;
     685            0 :       pp_show_color (pp) = true;
     686            0 :       const bool simple = true;
     687              : 
     688            0 :       bits.dump_to_pp (pp);
     689            0 :       pp_string (pp, ": ");
     690            0 :       if (tree t = sval->get_type ())
     691            0 :         dump_quoted_tree (pp, t);
     692            0 :       pp_string (pp, " {");
     693            0 :       sval->dump_to_pp (pp, simple);
     694            0 :       pp_string (pp, "}");
     695              : 
     696            0 :       parent_widget.add_child (text_art::tree_widget::make (dwi, pp));
     697            0 :     }
     698            0 : }
     699              : 
     700              : void
     701     13369830 : concrete_binding_map::validate () const
     702              : {
     703     28454412 :   for (auto iter = m_map.begin (); iter != m_map.end (); ++iter)
     704              :     {
     705              :       /* Ensure we don't nest compound svalues
     706              :          within concrete_binding_map instances.  */
     707     15084582 :       const svalue *sval = iter->second;
     708     15084582 :       gcc_assert (sval->get_kind () != SK_COMPOUND);
     709              : 
     710              :       /* Check for overlapping concrete bindings.  */
     711     15084582 :       auto next (iter);
     712     15084582 :       ++next;
     713     15084582 :       if (next != m_map.end ())
     714              :         {
     715              :           /* Verify they are in order, and do not overlap.  */
     716      4146497 :           const bit_range &iter_bits = iter->first;
     717      4146497 :           const bit_range &next_bits = next->first;
     718      4146497 :           gcc_assert (iter_bits.get_start_bit_offset ()
     719              :                       < next_bits.get_start_bit_offset ());
     720      4146497 :           gcc_assert (iter_bits.get_last_bit_offset ()
     721              :                       < next_bits.get_start_bit_offset ());
     722      4146497 :           gcc_assert (iter_bits.get_next_bit_offset ()
     723              :                       <= next_bits.get_start_bit_offset ());
     724              :         }
     725              :     }
     726     13369830 : }
     727              : 
     728              : /* Comparator for imposing an order on concrete_binding_map instances.  */
     729              : 
     730              : int
     731           28 : concrete_binding_map::cmp (const concrete_binding_map &map1,
     732              :                            const concrete_binding_map &map2)
     733              : {
     734           28 :   if (int size_cmp = map1.size () - map2.size ())
     735              :     return size_cmp;
     736              : 
     737           28 :   auto iter1 = map1.begin ();
     738           28 :   auto iter2 = map2.begin ();
     739           28 :   while (iter1 != map1.end ())
     740              :     {
     741           28 :       gcc_assert (iter2 != map2.end ());
     742           28 :       if (int bit_cmp = bit_range::cmp (iter1->first, iter2->first))
     743              :         return bit_cmp;
     744           28 :       if (int sval_cmp = svalue::cmp_ptr (iter1->second, iter2->second))
     745              :         return sval_cmp;
     746            0 :       ++iter1;
     747            0 :       ++iter2;
     748              :     }
     749              :   return 0;
     750              : }
     751              : 
     752              : /* Get the svalue bound precisely to BITS, if any, otherwise
     753              :    return nullptr.  */
     754              : 
     755              : const svalue *
     756           56 : concrete_binding_map::get_any_exact_binding (const bit_range &bits) const
     757              : {
     758           56 :   auto iter = m_map.find (bits);
     759           56 :   if (iter == m_map.end ())
     760              :     return nullptr;
     761           56 :   return iter->second;
     762              : }
     763              : 
     764              : /* Calculate what the complexity of a compound_svalue instance for this
     765              :    map will be, based on the bound svalues.  */
     766              : 
     767              : complexity
     768          661 : concrete_binding_map::calc_complexity () const
     769              : {
     770          661 :   unsigned num_child_nodes = 0;
     771          661 :   unsigned max_child_depth = 0;
     772         2640 :   for (auto iter : m_map)
     773              :     {
     774         1979 :       const complexity &sval_c = iter.second->get_complexity ();
     775         1979 :       num_child_nodes += sval_c.m_num_nodes;
     776         1979 :       max_child_depth = MAX (max_child_depth, sval_c.m_max_depth);
     777              :     }
     778          661 :   return complexity (num_child_nodes + 1, max_child_depth + 1);
     779              : }
     780              : 
     781              : void
     782        39089 : concrete_binding_map::
     783              : remove_overlapping_binding (store_manager *mgr,
     784              :                             const bit_range &bits_to_drop,
     785              :                             const bit_range &affected_bound_bits,
     786              :                             const svalue &old_sval)
     787              : {
     788        39089 :   gcc_assert (bits_to_drop.intersects_p (affected_bound_bits));
     789              : 
     790              :   /* Remove existing binding.  */
     791        39089 :   erase (affected_bound_bits);
     792              : 
     793        39089 :   if (affected_bound_bits.get_start_bit_offset ()
     794        39089 :       < bits_to_drop.get_start_bit_offset ())
     795              :     {
     796              :       /* We have a truncated prefix.  */
     797         1540 :       bit_range prefix_bits (affected_bound_bits.get_start_bit_offset (),
     798         3080 :                              (bits_to_drop.get_start_bit_offset ()
     799         1540 :                               - affected_bound_bits.get_start_bit_offset ()));
     800         1540 :       bit_range rel_prefix (0, prefix_bits.m_size_in_bits);
     801         1540 :       const svalue *prefix_sval
     802         1540 :         = old_sval.extract_bit_range (NULL_TREE,
     803              :                                       rel_prefix,
     804              :                                       mgr->get_svalue_manager ());
     805         1540 :       insert (prefix_bits, prefix_sval);
     806              :     }
     807              : 
     808        78178 :   if (affected_bound_bits.get_next_bit_offset ()
     809        78178 :       > bits_to_drop.get_next_bit_offset ())
     810              :     {
     811              :       /* We have a truncated suffix.  */
     812        10761 :       bit_range suffix_bits (bits_to_drop.get_next_bit_offset (),
     813        10761 :                              (affected_bound_bits.get_next_bit_offset ()
     814        21522 :                               - bits_to_drop.get_next_bit_offset ()));
     815        10761 :       bit_range rel_suffix (bits_to_drop.get_next_bit_offset ()
     816        10761 :                             - affected_bound_bits.get_start_bit_offset (),
     817        10761 :                             suffix_bits.m_size_in_bits);
     818        10761 :       const svalue *suffix_sval
     819        10761 :         = old_sval.extract_bit_range (NULL_TREE,
     820              :                                       rel_suffix,
     821              :                                       mgr->get_svalue_manager ());
     822        10761 :       insert (suffix_bits, suffix_sval);
     823              :     }
     824        39089 : }
     825              : 
     826              : void
     827         8979 : concrete_binding_map::
     828              : remove_overlapping_bindings (store_manager *mgr,
     829              :                              const bit_range &bits_to_drop)
     830              : {
     831         8979 :   auto bindings = get_overlapping_bindings (bits_to_drop);
     832        17958 :   for (auto iter : bindings)
     833         8979 :     remove_overlapping_binding (mgr, bits_to_drop, iter.first, iter.second);
     834         8979 : }
     835              : 
     836              : std::vector<std::pair<bit_range, const svalue &>>
     837         8979 : concrete_binding_map::get_overlapping_bindings (const bit_range &bits)
     838              : {
     839         8979 :   std::vector<std::pair<bit_range, const svalue &>> result;
     840        18009 :   for (auto iter : m_map)
     841         9030 :     if (iter.first.intersects_p (bits))
     842              :       {
     843         8979 :         gcc_assert (iter.second);
     844         8979 :         result.push_back ({iter.first, *iter.second});
     845              :       }
     846         8979 :   return result;
     847              : }
     848              : 
     849              : /* class binding_map::const_iterator.  */
     850              : 
     851              : bool
     852     26056563 : binding_map::const_iterator::operator== (const binding_map::const_iterator &other) const
     853              : {
     854     26056563 :   if (m_concrete != other.m_concrete)
     855              :     return false;
     856     11960239 :   if (m_symbolic != other.m_symbolic)
     857       521080 :     return false;
     858              :   return true;
     859              : }
     860              : 
     861              : binding_map::const_iterator &
     862     14610018 : binding_map::const_iterator::operator++ ()
     863              : {
     864     14610018 :   if (m_concrete != m_map.m_concrete.end ())
     865     14088938 :     ++m_concrete;
     866              :   else
     867       521080 :     ++m_symbolic;
     868     14610018 :   return *this;
     869              : }
     870              : 
     871              : binding_map::binding_pair
     872      3628584 : binding_map::const_iterator::operator* ()
     873              : {
     874      3628584 :   if (m_concrete != m_map.m_concrete.end ())
     875              :     {
     876      3524595 :       const bit_range &bits = m_concrete->first;
     877      3524595 :       const svalue *sval = m_concrete->second;
     878      3524595 :       return binding_pair (m_map.m_store_mgr.get_concrete_binding (bits), sval);
     879              :     }
     880              :   else
     881              :     {
     882       103989 :       gcc_assert (m_symbolic != m_map.m_symbolic.end ());
     883       103989 :       const region *reg = m_symbolic->m_region;
     884       103989 :       const svalue *sval = m_symbolic->m_sval;
     885       103989 :       return binding_pair (m_map.m_store_mgr.get_symbolic_binding (reg), sval);
     886              :     }
     887              : }
     888              : 
     889              : const svalue *
     890     10988820 : binding_map::const_iterator::get_svalue () const
     891              : {
     892     10988820 :   if (m_concrete != m_map.m_concrete.end ())
     893     10571729 :     return m_concrete->second;
     894              :   else
     895              :     {
     896       417091 :       gcc_assert (m_symbolic != m_map.m_symbolic.end ());
     897       417091 :       return m_symbolic->m_sval;
     898              :     }
     899              : }
     900              : 
     901              : /* class binding_map::iterator.  */
     902              : 
     903              : bool
     904     15296727 : binding_map::iterator::operator== (const binding_map::iterator &other) const
     905              : {
     906     15296727 :   if (m_concrete != other.m_concrete)
     907              :     return false;
     908      7314520 :   if (m_symbolic != other.m_symbolic)
     909       402498 :     return false;
     910              :   return true;
     911              : }
     912              : 
     913              : binding_map::iterator &
     914      8383622 : binding_map::iterator::operator++ ()
     915              : {
     916      8383622 :   if (m_concrete != m_map.m_concrete.end ())
     917      7981129 :     ++m_concrete;
     918              :   else
     919       402493 :     ++m_symbolic;
     920      8383622 :   return *this;
     921              : }
     922              : 
     923              : binding_map::binding_pair
     924      8475401 : binding_map::iterator::operator* ()
     925              : {
     926      8475401 :   if (m_concrete != m_map.m_concrete.end ())
     927              :     {
     928      8066737 :       const bit_range &bits = m_concrete->first;
     929      8066737 :       const svalue *&sval = m_concrete->second;
     930      8066737 :       return binding_pair (m_map.m_store_mgr.get_concrete_binding (bits), sval);
     931              :     }
     932              :   else
     933              :     {
     934       408664 :       gcc_assert (m_symbolic != m_map.m_symbolic.end ());
     935       408664 :       const region *reg = m_symbolic->m_region;
     936       408664 :       const svalue *&sval = m_symbolic->m_sval;
     937       408664 :       return binding_pair (m_map.m_store_mgr.get_symbolic_binding (reg), sval);
     938              :     }
     939              : }
     940              : 
     941              : /* class binding_map.  */
     942              : 
     943              : // Construct an empty binding_map.
     944              : 
     945      1642625 : binding_map::binding_map (store_manager &store_mgr)
     946      1642625 : : m_store_mgr (store_mgr),
     947      1642625 :   m_concrete (),
     948      1642625 :   m_symbolic ()
     949              : {
     950      1642625 : }
     951              : 
     952              : /* binding_map's copy ctor.  */
     953              : 
     954     32021711 : binding_map::binding_map (const binding_map &other)
     955     32021711 : : m_store_mgr (other.m_store_mgr),
     956     32021711 :   m_concrete (other.m_concrete),
     957     32021711 :   m_symbolic (other.m_symbolic)
     958              : {
     959     32021711 : }
     960              : 
     961              : /* binding_map's assignment operator.  */
     962              : 
     963              : binding_map&
     964            4 : binding_map::operator= (const binding_map &other)
     965              : {
     966            4 :   gcc_assert (&m_store_mgr == &other.m_store_mgr);
     967              : 
     968              :   /* For now, assume we only ever copy to an empty cluster.  */
     969            4 :   gcc_assert (m_concrete.size () == 0);
     970            4 :   gcc_assert (m_symbolic.size () == 0);
     971              : 
     972            4 :   m_concrete = other.m_concrete;
     973            4 :   m_symbolic = other.m_symbolic;
     974              : 
     975            4 :   return *this;
     976              : }
     977              : 
     978              : /* binding_map's equality operator.  */
     979              : 
     980              : bool
     981      3376946 : binding_map::operator== (const binding_map &other) const
     982              : {
     983      3376946 :   if (m_concrete != other.m_concrete)
     984              :     return false;
     985      3316335 :   if (m_symbolic != other.m_symbolic)
     986              :     return false;
     987              : 
     988              :   return true;
     989              : }
     990              : 
     991              : /* Generate a hash value for this binding_map.  */
     992              : 
     993              : hashval_t
     994     21978531 : binding_map::hash () const
     995              : {
     996     21978531 :   hashval_t result = 0;
     997     46817223 :   for (auto iter : m_concrete)
     998              :     {
     999     24838692 :       result ^= iter.first.hash ();
    1000     24838692 :       inchash::hash hstate;
    1001     24838692 :       hstate.add_ptr (iter.second);
    1002     24838692 :       result ^= hstate.end ();
    1003              :     }
    1004     23140483 :   for (auto iter : m_symbolic)
    1005              :     {
    1006              :       /* Use a new hasher for each key to avoid depending on the ordering
    1007              :          of keys when accumulating the result.  */
    1008      1161952 :       inchash::hash hstate;
    1009      1161952 :       hstate.add_ptr (iter.m_region);
    1010      1161952 :       hstate.add_ptr (iter.m_sval);
    1011      1161952 :       result ^= hstate.end ();
    1012              :     }
    1013     21978531 :   return result;
    1014              : }
    1015              : 
    1016              : const svalue *
    1017      5296471 : binding_map::get (const binding_key *key) const
    1018              : {
    1019      5296471 :   if (key->symbolic_p ())
    1020              :     {
    1021       293015 :       const ana::symbolic_binding &sym_key
    1022              :         = *static_cast <const ana::symbolic_binding *> (key);
    1023       293015 :       const region *reg = sym_key.get_region ();
    1024              : 
    1025       345425 :       for (auto iter : m_symbolic)
    1026              :         {
    1027       214559 :           if (iter.m_region == reg)
    1028      5296471 :             return iter.m_sval;
    1029              :         }
    1030              :       return nullptr;
    1031              :     }
    1032              :   else
    1033              :     {
    1034      5003456 :       const concrete_binding &conc_key
    1035              :         = *static_cast <const concrete_binding *> (key);
    1036      5003456 :       const bit_range &bits = conc_key.get_bit_range ();
    1037              : 
    1038      5003456 :       concrete_bindings_t::const_iterator iter (m_concrete.find (bits));
    1039      5003456 :       if (iter != m_concrete.end ())
    1040      4556245 :         return iter->second;
    1041              :       else
    1042              :         return nullptr;
    1043              :     }
    1044              : }
    1045              : 
    1046              : void
    1047      2203166 : binding_map::put (const binding_key *key, const svalue *sval)
    1048              : {
    1049      2203166 :   if (key->symbolic_p ())
    1050              :     {
    1051        65917 :       const ana::symbolic_binding &sym_key
    1052              :         = *static_cast <const ana::symbolic_binding *> (key);
    1053        65917 :       const region *reg = sym_key.get_region ();
    1054              : 
    1055        65917 :       m_symbolic.clear ();
    1056              : 
    1057        65917 :       m_symbolic.push_back ({reg, sval});
    1058              :     }
    1059              :   else
    1060              :     {
    1061      2137249 :       const concrete_binding &conc_key
    1062              :         = *static_cast <const concrete_binding *> (key);
    1063      2137249 :       const bit_range &bits = conc_key.get_bit_range ();
    1064              : 
    1065      2137249 :       concrete_bindings_t::iterator iter (m_concrete.find (bits));
    1066      2137249 :       if (iter != m_concrete.end ())
    1067         3558 :         (*iter).second = sval;
    1068              :       else
    1069      2133691 :         m_concrete.insert (bits, sval);
    1070              :     }
    1071      2203166 : }
    1072              : 
    1073              : void
    1074          286 : binding_map::overwrite (iterator_t &pos, const svalue *v)
    1075              : {
    1076          286 :   gcc_assert (&pos.m_map == this);
    1077          286 :   if (pos.m_symbolic != m_symbolic.end ())
    1078            0 :     (*(pos.m_symbolic)).m_sval = v;
    1079              :   else
    1080              :     {
    1081          286 :       gcc_assert (pos.m_concrete != m_concrete.end ());
    1082          286 :       (*(pos.m_concrete)).second = v;
    1083              :     }
    1084          286 : }
    1085              : 
    1086              : void
    1087       306386 : binding_map::remove (const binding_key *key)
    1088              : {
    1089       306386 :   if (key->symbolic_p ())
    1090         9760 :     m_symbolic.clear ();
    1091              :   else
    1092              :     {
    1093       296626 :       const concrete_binding &conc_key
    1094              :         = *static_cast <const concrete_binding *> (key);
    1095       296626 :       const bit_range &bits = conc_key.get_bit_range ();
    1096       296626 :       m_concrete.erase (bits);
    1097              :     }
    1098       306386 : }
    1099              : 
    1100              : binding_map::const_iterator_t
    1101     11446545 : binding_map::begin () const
    1102              : {
    1103     11446545 :   return binding_map::const_iterator_t (*this,
    1104              :                                         m_concrete.begin (),
    1105     11446545 :                                         m_symbolic.begin ());
    1106              : }
    1107              : 
    1108              : binding_map::const_iterator_t
    1109     22435365 : binding_map::end () const
    1110              : {
    1111     22435365 :   return binding_map::const_iterator_t (*this,
    1112              :                                         m_concrete.end (),
    1113     22435365 :                                         m_symbolic.end ());
    1114              : }
    1115              : 
    1116              : binding_map::iterator_t
    1117      6913105 : binding_map::begin ()
    1118              : {
    1119      6913105 :   return binding_map::iterator_t (*this,
    1120              :                                   m_concrete.begin (),
    1121      6913105 :                                   m_symbolic.begin ());
    1122              : }
    1123              : 
    1124              : binding_map::iterator_t
    1125     14556374 : binding_map::end ()
    1126              : {
    1127     14556374 :   return binding_map::iterator_t (*this,
    1128              :                                   m_concrete.end (),
    1129     14556374 :                                   m_symbolic.end ());
    1130              : }
    1131              : 
    1132              : size_t
    1133       549702 : binding_map::elements () const
    1134              : {
    1135       549702 :   return m_concrete.size () + m_symbolic.size ();
    1136              : }
    1137              : 
    1138              : /* Dump a representation of this binding_map to PP.
    1139              :    SIMPLE controls how values and regions are to be printed.
    1140              :    If MULTILINE, then split the dump over multiple lines and
    1141              :    use whitespace for readability, otherwise put all on one line.  */
    1142              : 
    1143              : void
    1144         1731 : binding_map::dump_to_pp (pretty_printer *pp, bool simple,
    1145              :                          bool multiline) const
    1146              : {
    1147         1731 :   bool first = true;
    1148         2862 :   for (auto iter : *this)
    1149              :     {
    1150         1131 :       const binding_key *key = iter.m_key;
    1151         1131 :       const svalue *value = iter.m_sval;
    1152         1131 :       if (multiline)
    1153              :         {
    1154          300 :           pp_string (pp, "    key:   {");
    1155          300 :           key->dump_to_pp (pp, simple);
    1156          300 :           pp_string (pp, "}");
    1157          300 :           pp_newline (pp);
    1158          300 :           pp_string (pp, "    value: ");
    1159          300 :           if (tree t = value->get_type ())
    1160          300 :             dump_quoted_tree (pp, t);
    1161          300 :           pp_string (pp, " {");
    1162          300 :           value->dump_to_pp (pp, simple);
    1163          300 :           pp_string (pp, "}");
    1164          300 :           pp_newline (pp);
    1165              :         }
    1166              :       else
    1167              :         {
    1168          831 :           if (first)
    1169              :             first = false;
    1170              :           else
    1171          188 :             pp_string (pp, ", ");
    1172          831 :           pp_string (pp, "binding key: {");
    1173          831 :           key->dump_to_pp (pp, simple);
    1174          831 :           pp_string (pp, "}, value: {");
    1175          831 :           value->dump_to_pp (pp, simple);
    1176          831 :           pp_string (pp, "}");
    1177              :         }
    1178              :     }
    1179         1731 : }
    1180              : 
    1181              : /* Dump a multiline representation of this binding_map to stderr.  */
    1182              : 
    1183              : DEBUG_FUNCTION void
    1184            0 : binding_map::dump (bool simple) const
    1185              : {
    1186            0 :   tree_dump_pretty_printer pp (stderr);
    1187            0 :   dump_to_pp (&pp, simple, true);
    1188            0 :   pp_newline (&pp);
    1189            0 : }
    1190              : 
    1191              : /* Assert that this object is valid.  */
    1192              : 
    1193              : void
    1194     13369830 : binding_map::validate () const
    1195              : {
    1196     13369830 :   const size_t num_concrete = m_concrete.size ();
    1197     13369830 :   const size_t num_symbolic = m_symbolic.size ();
    1198              : 
    1199              :   /* We shouldn't have more than one symbolic key per cluster
    1200              :      (or one would have clobbered the other).  */
    1201     13369830 :   gcc_assert (num_symbolic < 2);
    1202              :   /* We can't have both concrete and symbolic keys.  */
    1203     13369830 :   gcc_assert (num_concrete == 0 || num_symbolic == 0);
    1204              : 
    1205     13369830 :   m_concrete.validate ();
    1206     13369830 : }
    1207              : 
    1208              : /* Return a new json::object of the form
    1209              :    {KEY_DESC : SVALUE_DESC,
    1210              :     ...for the various key/value pairs in this binding_map}.  */
    1211              : 
    1212              : std::unique_ptr<json::object>
    1213            0 : binding_map::to_json () const
    1214              : {
    1215            0 :   auto map_obj = std::make_unique<json::object> ();
    1216              : 
    1217            0 :   for (auto iter : *this)
    1218              :     {
    1219            0 :       const svalue *value = iter.m_sval;
    1220            0 :       label_text key_desc = iter.m_key->get_desc ();
    1221            0 :       map_obj->set (key_desc.get (), value->to_json ());
    1222            0 :     }
    1223              : 
    1224            0 :   return map_obj;
    1225              : }
    1226              : 
    1227              : /* Add a child to PARENT_WIDGET expressing a binding between
    1228              :    KEY and SVAL.  */
    1229              : 
    1230              : static void
    1231            0 : add_binding_to_tree_widget (text_art::tree_widget &parent_widget,
    1232              :                             const text_art::dump_widget_info &dwi,
    1233              :                             const binding_key *key,
    1234              :                             const svalue *sval)
    1235              : {
    1236            0 :   pretty_printer the_pp;
    1237            0 :   pretty_printer * const pp = &the_pp;
    1238            0 :   pp_format_decoder (pp) = default_tree_printer;
    1239            0 :   pp_show_color (pp) = true;
    1240            0 :   const bool simple = true;
    1241              : 
    1242            0 :   key->dump_to_pp (pp, simple);
    1243            0 :   pp_string (pp, ": ");
    1244            0 :   if (tree t = sval->get_type ())
    1245            0 :     dump_quoted_tree (pp, t);
    1246            0 :   pp_string (pp, " {");
    1247            0 :   sval->dump_to_pp (pp, simple);
    1248            0 :   pp_string (pp, "}");
    1249              : 
    1250            0 :   parent_widget.add_child (text_art::tree_widget::make (dwi, pp));
    1251            0 : }
    1252              : 
    1253              : void
    1254            0 : binding_map::add_to_tree_widget (text_art::tree_widget &parent_widget,
    1255              :                                  const text_art::dump_widget_info &dwi) const
    1256              : {
    1257            0 :   for (auto iter : *this)
    1258              :     {
    1259            0 :       const binding_key *key = iter.m_key;
    1260            0 :       const svalue *sval = iter.m_sval;
    1261            0 :       add_binding_to_tree_widget (parent_widget, dwi,
    1262              :                                   key, sval);
    1263              :     }
    1264            0 : }
    1265              : 
    1266              : /* Get the child region of PARENT_REG based upon INDEX within a
    1267              :    CONSTRUCTOR.   */
    1268              : 
    1269              : static const region *
    1270          467 : get_subregion_within_ctor (const region *parent_reg, tree index,
    1271              :                            region_model_manager *mgr)
    1272              : {
    1273          467 :   switch (TREE_CODE (index))
    1274              :     {
    1275            0 :     default:
    1276            0 :       gcc_unreachable ();
    1277          403 :     case INTEGER_CST:
    1278          403 :       {
    1279          403 :         const svalue *index_sval
    1280          403 :           = mgr->get_or_create_constant_svalue (index);
    1281          403 :         return mgr->get_element_region (parent_reg,
    1282          403 :                                         TREE_TYPE (parent_reg->get_type ()),
    1283          403 :                                         index_sval);
    1284              :       }
    1285           64 :       break;
    1286           64 :     case FIELD_DECL:
    1287           64 :       return mgr->get_field_region (parent_reg, index);
    1288              :     }
    1289              : }
    1290              : 
    1291              : /* Get the child region of PARENT_REG based upon (INDEX, VALUE) within a
    1292              :    CONSTRUCTOR.   */
    1293              : 
    1294              : static const region *
    1295          467 : get_subregion_within_ctor_for_ctor_pair (const region *parent_reg,
    1296              :                                          tree index,
    1297              :                                          tree value,
    1298              :                                          region_model_manager *mgr)
    1299              : {
    1300          467 :   if (TREE_CODE (index) == INTEGER_CST
    1301          403 :       && TREE_CODE (value) == RAW_DATA_CST)
    1302              :     {
    1303              :       /* Special-case; see tree.def's description of CONSTRUCTOR.
    1304              :          We have RAW_DATA_LENGTH of bytes, starting at INDEX's start.  */
    1305           14 :       const region *start_reg
    1306           14 :         = get_subregion_within_ctor (parent_reg, index, mgr);
    1307              :       /* Build a bit range, relative to PARENT_REG.  */
    1308           14 :       region_offset start_offset = start_reg->get_offset (mgr);
    1309              : 
    1310           14 :       if (!start_offset.concrete_p ())
    1311              :         return nullptr;
    1312           14 :       bit_offset_t start_bit_offset = start_offset.get_bit_offset ();
    1313           14 :       int length = RAW_DATA_LENGTH (value);
    1314           14 :       bit_range bits (start_bit_offset, length * BITS_PER_UNIT);
    1315              : 
    1316           14 :       return mgr->get_bit_range (parent_reg, NULL_TREE, bits);
    1317              :     }
    1318              : 
    1319          453 :   return get_subregion_within_ctor (parent_reg, index, mgr);
    1320              : }
    1321              : 
    1322              : /* Get the svalue for VAL, a non-CONSTRUCTOR value within a CONSTRUCTOR.  */
    1323              : 
    1324              : static const svalue *
    1325          425 : get_svalue_for_ctor_val (tree val, region_model_manager *mgr)
    1326              : {
    1327              :   /* Reuse the get_rvalue logic from region_model.  */
    1328          425 :   region_model m (mgr);
    1329          425 :   return m.get_rvalue (path_var (val, 0), nullptr);
    1330          425 : }
    1331              : 
    1332              : /* Bind values from CONSTRUCTOR to this map, relative to
    1333              :    PARENT_REG's relationship to its base region.
    1334              :    Return true if successful, false if there was a problem (e.g. due
    1335              :    to hitting a complexity limit).  */
    1336              : 
    1337              : bool
    1338          164 : concrete_binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
    1339              :                                             region_model_manager *mgr)
    1340              : {
    1341          164 :   gcc_assert (parent_reg);
    1342          164 :   gcc_assert (TREE_CODE (ctor) == CONSTRUCTOR);
    1343              : 
    1344          164 :   unsigned ix;
    1345          164 :   tree index;
    1346          164 :   tree val;
    1347          164 :   tree parent_type = parent_reg->get_type ();
    1348          164 :   tree field;
    1349          164 :   if (TREE_CODE (parent_type) == RECORD_TYPE)
    1350           55 :     field = TYPE_FIELDS (parent_type);
    1351              :   else
    1352              :     field = NULL_TREE;
    1353          630 :   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, index, val)
    1354              :     {
    1355          467 :       if (!index)
    1356              :         {
    1357              :           /* If index is NULL, then iterate through the fields for
    1358              :              a RECORD_TYPE, or use an INTEGER_CST otherwise.
    1359              :              Compare with similar logic in output_constructor.  */
    1360          189 :           if (field)
    1361              :             {
    1362            0 :               index = field;
    1363            0 :               field = DECL_CHAIN (field);
    1364              :             }
    1365              :           else
    1366          189 :             index = build_int_cst (integer_type_node, ix);
    1367              :         }
    1368          278 :       else if (TREE_CODE (index) == RANGE_EXPR)
    1369              :         {
    1370            0 :           tree min_index = TREE_OPERAND (index, 0);
    1371            0 :           tree max_index = TREE_OPERAND (index, 1);
    1372            0 :           if (min_index == max_index)
    1373              :             {
    1374            0 :               if (!apply_ctor_pair_to_child_region (parent_reg, mgr,
    1375              :                                                     min_index, val))
    1376              :                 return false;
    1377              :             }
    1378              :           else
    1379              :             {
    1380            0 :               if (!apply_ctor_val_to_range (parent_reg, mgr,
    1381              :                                             min_index, max_index, val))
    1382              :                 return false;
    1383              :             }
    1384            0 :           continue;
    1385            0 :         }
    1386          467 :       if (!apply_ctor_pair_to_child_region (parent_reg, mgr, index, val))
    1387              :         return false;
    1388              :     }
    1389              :   return true;
    1390              : }
    1391              : 
    1392              : /* Bind the value VAL into the range of elements within PARENT_REF
    1393              :    from MIN_INDEX to MAX_INDEX (including endpoints).
    1394              :    For use in handling RANGE_EXPR within a CONSTRUCTOR.
    1395              :    Return true if successful, false if there was a problem (e.g. due
    1396              :    to hitting a complexity limit).  */
    1397              : 
    1398              : bool
    1399            0 : concrete_binding_map::apply_ctor_val_to_range (const region *parent_reg,
    1400              :                                                region_model_manager *mgr,
    1401              :                                                tree min_index, tree max_index,
    1402              :                                                tree val)
    1403              : {
    1404            0 :   gcc_assert (TREE_CODE (min_index) == INTEGER_CST);
    1405            0 :   gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
    1406              : 
    1407              :   /* Generate a binding key for the range.  */
    1408            0 :   const region *min_element
    1409            0 :     = get_subregion_within_ctor (parent_reg, min_index, mgr);
    1410            0 :   const region *max_element
    1411            0 :     = get_subregion_within_ctor (parent_reg, max_index, mgr);
    1412            0 :   region_offset min_offset = min_element->get_offset (mgr);
    1413            0 :   if (min_offset.symbolic_p ())
    1414              :     return false;
    1415            0 :   bit_offset_t start_bit_offset = min_offset.get_bit_offset ();
    1416            0 :   store_manager *smgr = mgr->get_store_manager ();
    1417            0 :   if (max_element->empty_p ())
    1418              :     return false;
    1419            0 :   const binding_key *max_element_key = binding_key::make (smgr, max_element);
    1420            0 :   if (max_element_key->symbolic_p ())
    1421              :     return false;
    1422            0 :   const concrete_binding *max_element_ckey
    1423            0 :     = max_element_key->dyn_cast_concrete_binding ();
    1424            0 :   bit_size_t range_size_in_bits
    1425            0 :     = max_element_ckey->get_next_bit_offset () - start_bit_offset;
    1426              : 
    1427              :   /* Get the value.  */
    1428            0 :   if (TREE_CODE (val) == CONSTRUCTOR)
    1429              :     return false;
    1430            0 :   const svalue *sval = get_svalue_for_ctor_val (val, mgr);
    1431              : 
    1432              :   /* Bind the value to the range.  */
    1433            0 :   const bit_range affected_bits (start_bit_offset, range_size_in_bits);
    1434            0 :   insert (affected_bits, sval);
    1435            0 :   return true;
    1436              : }
    1437              : 
    1438              : /* Bind the value VAL into INDEX within PARENT_REF.
    1439              :    For use in handling a pair of entries within a CONSTRUCTOR.
    1440              :    Return true if successful, false if there was a problem (e.g. due
    1441              :    to hitting a complexity limit).  */
    1442              : 
    1443              : bool
    1444          467 : concrete_binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
    1445              :                                                        region_model_manager *mgr,
    1446              :                                                        tree index, tree val)
    1447              : {
    1448          467 :   const region *child_reg
    1449          467 :     = get_subregion_within_ctor_for_ctor_pair (parent_reg, index, val, mgr);
    1450          467 :   if (!child_reg)
    1451              :     return false;
    1452          467 :   if (TREE_CODE (val) == CONSTRUCTOR)
    1453           42 :     return apply_ctor_to_region (child_reg, val, mgr);
    1454              :   else
    1455              :     {
    1456          425 :       const svalue *sval = get_svalue_for_ctor_val (val, mgr);
    1457          425 :       if (child_reg->empty_p ())
    1458              :         return false;
    1459          425 :       const binding_key *k
    1460          425 :         = binding_key::make (mgr->get_store_manager (), child_reg);
    1461              :       /* Handle the case where we have an unknown size for child_reg
    1462              :          (e.g. due to it being a trailing field with incomplete array
    1463              :          type.  */
    1464          425 :       if (!k->concrete_p ())
    1465              :         {
    1466              :           /* Assume that sval has a well-defined size for this case.  */
    1467            5 :           tree sval_type = sval->get_type ();
    1468            5 :           gcc_assert (sval_type);
    1469            5 :           HOST_WIDE_INT sval_byte_size = int_size_in_bytes (sval_type);
    1470            5 :           gcc_assert (sval_byte_size != -1);
    1471            5 :           bit_size_t sval_bit_size = sval_byte_size * BITS_PER_UNIT;
    1472              :           /* Get offset of child relative to base region.  */
    1473            5 :           region_offset child_base_offset = child_reg->get_offset (mgr);
    1474            5 :           if (child_base_offset.symbolic_p ())
    1475            1 :             return false;
    1476              :           /* Convert to an offset relative to the parent region.  */
    1477            4 :           region_offset parent_base_offset = parent_reg->get_offset (mgr);
    1478            4 :           gcc_assert (!parent_base_offset.symbolic_p ());
    1479            4 :           bit_offset_t child_parent_offset
    1480            4 :             = (child_base_offset.get_bit_offset ()
    1481            4 :                - parent_base_offset.get_bit_offset ());
    1482              :           /* Create a concrete key for the child within the parent.  */
    1483            4 :           k = mgr->get_store_manager ()->get_concrete_binding
    1484            4 :             (child_parent_offset, sval_bit_size);
    1485              :         }
    1486          424 :       gcc_assert (k->concrete_p ());
    1487          424 :       auto conc_key = as_a <const concrete_binding *> (k);
    1488          424 :       insert (conc_key->get_bit_range (), sval);
    1489          424 :       return true;
    1490              :     }
    1491              : }
    1492              : 
    1493              : /* Populate OUT with all bindings within this map that overlap KEY.  */
    1494              : 
    1495              : void
    1496        35320 : binding_map::get_overlapping_bindings (const binding_key *key,
    1497              :                                        auto_vec<const binding_key *> *out)
    1498              : {
    1499       313655 :   for (auto iter : *this)
    1500              :     {
    1501       278335 :       const binding_key *iter_key = iter.m_key;
    1502       556670 :       if (const concrete_binding *ckey
    1503       278335 :             = key->dyn_cast_concrete_binding ())
    1504              :         {
    1505       551468 :           if (const concrete_binding *iter_ckey
    1506       275734 :               = iter_key->dyn_cast_concrete_binding ())
    1507              :             {
    1508       275225 :               if (ckey->overlaps_p (*iter_ckey))
    1509        30110 :                 out->safe_push (iter_key);
    1510              :             }
    1511              :           else
    1512              :             {
    1513              :               /* Assume overlap.  */
    1514          509 :               out->safe_push (iter_key);
    1515              :             }
    1516              :         }
    1517              :       else
    1518              :         {
    1519              :           /* Assume overlap.  */
    1520         2601 :           out->safe_push (iter_key);
    1521              :         }
    1522              :     }
    1523        35320 : }
    1524              : 
    1525              : /* Remove, truncate, and/or split any bindings within this map that
    1526              :    overlap DROP_KEY.
    1527              : 
    1528              :    For example, if we have:
    1529              : 
    1530              :      +------------------------------------+
    1531              :      |             old binding            |
    1532              :      +------------------------------------+
    1533              : 
    1534              :    which is to be overwritten with:
    1535              : 
    1536              :      .......+----------------------+.......
    1537              :      .......|      new binding     |.......
    1538              :      .......+----------------------+.......
    1539              : 
    1540              :    this function "cuts a hole" out of the old binding:
    1541              : 
    1542              :      +------+......................+------+
    1543              :      |prefix| hole for new binding |suffix|
    1544              :      +------+......................+------+
    1545              : 
    1546              :    into which the new binding can be added without
    1547              :    overlapping the prefix or suffix.
    1548              : 
    1549              :    The prefix and suffix (if added) will be bound to the pertinent
    1550              :    parts of the value of the old binding.
    1551              : 
    1552              :    For example, given:
    1553              :      struct s5
    1554              :      {
    1555              :        char arr[8];
    1556              :      };
    1557              :      void test_5 (struct s5 *p)
    1558              :      {
    1559              :        struct s5 f = *p;
    1560              :        f.arr[3] = 42;
    1561              :      }
    1562              :    then after the "f = *p;" we have:
    1563              :      cluster for: f: INIT_VAL((*INIT_VAL(p_33(D))))
    1564              :    and at the "f.arr[3] = 42;" we remove the bindings overlapping
    1565              :    "f.arr[3]", replacing it with a prefix (bytes 0-2) and suffix (bytes 4-7)
    1566              :    giving:
    1567              :      cluster for: f
    1568              :        key:   {bytes 0-2}
    1569              :        value:  {BITS_WITHIN(bytes 0-2, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
    1570              :        key:   {bytes 4-7}
    1571              :        value:  {BITS_WITHIN(bytes 4-7, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
    1572              :    punching a hole into which the new value can be written at byte 3:
    1573              :      cluster for: f
    1574              :        key:   {bytes 0-2}
    1575              :        value:  {BITS_WITHIN(bytes 0-2, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
    1576              :        key:   {byte 3}
    1577              :        value: 'char' {(char)42}
    1578              :        key:   {bytes 4-7}
    1579              :        value:  {BITS_WITHIN(bytes 4-7, inner_val: INIT_VAL((*INIT_VAL(p_33(D))).arr))}
    1580              : 
    1581              :    If UNCERTAINTY is non-NULL, use it to record any svalues that
    1582              :    were removed, as being maybe-bound.
    1583              : 
    1584              :    If MAYBE_LIVE_VALUES is non-NULL, then use it to record any svalues that
    1585              :    were removed as being maybe-live.
    1586              : 
    1587              :    If ALWAYS_OVERLAP, then assume that DROP_KEY can overlap anything
    1588              :    in the map, due to one or both of the underlying clusters being
    1589              :    symbolic (but not the same symbolic region).  Hence even if DROP_KEY is a
    1590              :    concrete binding it could actually be referring to the same memory as
    1591              :    distinct concrete bindings in the map.  Remove all bindings, but
    1592              :    register any svalues with *UNCERTAINTY.  */
    1593              : 
    1594              : void
    1595        82539 : binding_map::remove_overlapping_bindings (store_manager *mgr,
    1596              :                                           const binding_key *drop_key,
    1597              :                                           uncertainty_t *uncertainty,
    1598              :                                           svalue_set *maybe_live_values,
    1599              :                                           bool always_overlap)
    1600              : {
    1601              :   /* Get the bindings of interest within this map.  */
    1602        82539 :   auto_vec<const binding_key *> bindings;
    1603        82539 :   if (always_overlap)
    1604        95066 :     for (auto iter : *this)
    1605        47847 :       bindings.safe_push (iter.m_key); /* Add all bindings.  */
    1606              :   else
    1607              :     /* Just add overlapping bindings.  */
    1608        35320 :     get_overlapping_bindings (drop_key, &bindings);
    1609              : 
    1610              :   unsigned i;
    1611              :   const binding_key *iter_binding;
    1612       228007 :   FOR_EACH_VEC_ELT (bindings, i, iter_binding)
    1613              :     {
    1614              :       /* Record any svalues that were removed to *UNCERTAINTY as being
    1615              :          maybe-bound, provided at least some part of the binding is symbolic.
    1616              : 
    1617              :          Specifically, if at least one of the bindings is symbolic, or we
    1618              :          have ALWAYS_OVERLAP for the case where we have possibly aliasing
    1619              :          regions, then we don't know that the svalue has been overwritten,
    1620              :          and should record that to *UNCERTAINTY.
    1621              : 
    1622              :          However, if we have concrete keys accessing within the same symbolic
    1623              :          region, then we *know* that the symbolic region has been overwritten,
    1624              :          so we don't record it to *UNCERTAINTY, as this could be a genuine
    1625              :          leak.  */
    1626        81067 :       const svalue *old_sval = get (iter_binding);
    1627        81067 :       if (uncertainty
    1628       104196 :           && (drop_key->symbolic_p ()
    1629        20914 :               || iter_binding->symbolic_p ()
    1630        18522 :               || always_overlap))
    1631        19334 :         uncertainty->on_maybe_bound_sval (old_sval);
    1632              : 
    1633              :       /* Record any svalues that were removed to *MAYBE_LIVE_VALUES as being
    1634              :          maybe-live. */
    1635        81067 :       if (maybe_live_values)
    1636        47873 :         maybe_live_values->add (old_sval);
    1637              : 
    1638              :       /* Begin by removing the old binding. */
    1639        81067 :       remove (iter_binding);
    1640              : 
    1641              :       /* Don't attempt to handle prefixes/suffixes for the
    1642              :          "always_overlap" case; everything's being removed.  */
    1643        81067 :       if (always_overlap)
    1644        47847 :         continue;
    1645              : 
    1646              :       /* Now potentially add the prefix and suffix.  */
    1647        66440 :       if (const concrete_binding *drop_ckey
    1648        33220 :           = drop_key->dyn_cast_concrete_binding ())
    1649        61238 :         if (const concrete_binding *iter_ckey
    1650        30619 :               = iter_binding->dyn_cast_concrete_binding ())
    1651              :           {
    1652        30110 :             gcc_assert (drop_ckey->overlaps_p (*iter_ckey));
    1653              : 
    1654        30110 :             const bit_range &drop_bits = drop_ckey->get_bit_range ();
    1655        30110 :             const bit_range &iter_bits = iter_ckey->get_bit_range ();
    1656        30110 :             gcc_assert (old_sval);
    1657        30110 :             m_concrete.remove_overlapping_binding (mgr, drop_bits, iter_bits,
    1658              :                                                    *old_sval);
    1659              :           }
    1660              :     }
    1661        82539 : }
    1662              : 
    1663              : /* class binding_cluster.  */
    1664              : 
    1665      1642617 : binding_cluster::binding_cluster (store_manager &store_mgr,
    1666      1642617 :                                   const region *base_region)
    1667      1642617 : : m_base_region (base_region), m_map (store_mgr),
    1668      1642617 :   m_escaped (false), m_touched (false)
    1669              : {
    1670      1642617 : }
    1671              : 
    1672              : /* binding_cluster's copy ctor.  */
    1673              : 
    1674     32021711 : binding_cluster::binding_cluster (const binding_cluster &other)
    1675     32021711 : : m_base_region (other.m_base_region), m_map (other.m_map),
    1676     32021711 :   m_escaped (other.m_escaped), m_touched (other.m_touched)
    1677              : {
    1678     32021711 : }
    1679              : 
    1680              : /* binding_cluster's assignment operator.  */
    1681              : 
    1682              : binding_cluster&
    1683            0 : binding_cluster::operator= (const binding_cluster &other)
    1684              : {
    1685            0 :   gcc_assert (m_base_region == other.m_base_region);
    1686            0 :   m_map = other.m_map;
    1687            0 :   m_escaped = other.m_escaped;
    1688            0 :   m_touched = other.m_touched;
    1689            0 :   return *this;
    1690              : }
    1691              : 
    1692              : /* binding_cluster's equality operator.  */
    1693              : 
    1694              : bool
    1695      3376942 : binding_cluster::operator== (const binding_cluster &other) const
    1696              : {
    1697      3376942 :   if (m_map != other.m_map)
    1698              :     return false;
    1699              : 
    1700      3314000 :   if (m_base_region != other.m_base_region)
    1701              :     return false;
    1702              : 
    1703      3314000 :   if (m_escaped != other.m_escaped)
    1704              :     return false;
    1705              : 
    1706      3313334 :   if (m_touched != other.m_touched)
    1707              :     return false;
    1708              : 
    1709      3310667 :   gcc_checking_assert (hash () == other.hash ());
    1710              : 
    1711              :   return true;
    1712              : }
    1713              : 
    1714              : /* Generate a hash value for this binding_cluster.  */
    1715              : 
    1716              : hashval_t
    1717     21978531 : binding_cluster::hash () const
    1718              : {
    1719     21978531 :   return m_map.hash ();
    1720              : }
    1721              : 
    1722              : /* Return true if this binding_cluster is symbolic
    1723              :    i.e. its base region is symbolic.  */
    1724              : 
    1725              : bool
    1726      9417926 : binding_cluster::symbolic_p () const
    1727              : {
    1728      9417926 :   return m_base_region->get_kind () == RK_SYMBOLIC;
    1729              : }
    1730              : 
    1731              : /* Dump a representation of this binding_cluster to PP.
    1732              :    SIMPLE controls how values and regions are to be printed.
    1733              :    If MULTILINE, then split the dump over multiple lines and
    1734              :    use whitespace for readability, otherwise put all on one line.  */
    1735              : 
    1736              : void
    1737         1731 : binding_cluster::dump_to_pp (pretty_printer *pp, bool simple,
    1738              :                              bool multiline) const
    1739              : {
    1740         1731 :   if (m_escaped)
    1741              :     {
    1742         1092 :       if (multiline)
    1743              :         {
    1744          904 :           pp_string (pp, "    ESCAPED");
    1745          904 :           pp_newline (pp);
    1746              :         }
    1747              :       else
    1748          188 :         pp_string (pp, "(ESCAPED)");
    1749              :     }
    1750         1731 :   if (m_touched)
    1751              :     {
    1752          272 :       if (multiline)
    1753              :         {
    1754           84 :           pp_string (pp, "    TOUCHED");
    1755           84 :           pp_newline (pp);
    1756              :         }
    1757              :       else
    1758          188 :         pp_string (pp, "(TOUCHED)");
    1759              :     }
    1760              : 
    1761         1731 :   m_map.dump_to_pp (pp, simple, multiline);
    1762         1731 : }
    1763              : 
    1764              : /* Dump a multiline representation of this binding_cluster to stderr.  */
    1765              : 
    1766              : DEBUG_FUNCTION void
    1767            0 : binding_cluster::dump (bool simple) const
    1768              : {
    1769            0 :   tree_dump_pretty_printer pp (stderr);
    1770            0 :   pp_string (&pp, "  cluster for: ");
    1771            0 :   m_base_region->dump_to_pp (&pp, simple);
    1772            0 :   pp_string (&pp, ": ");
    1773            0 :   pp_newline (&pp);
    1774            0 :   dump_to_pp (&pp, simple, true);
    1775            0 :   pp_newline (&pp);
    1776            0 : }
    1777              : 
    1778              : /* Assert that this object is valid.  */
    1779              : 
    1780              : void
    1781     13369830 : binding_cluster::validate () const
    1782              : {
    1783     13369830 :   m_map.validate ();
    1784     13369830 : }
    1785              : 
    1786              : /* Return a new json::object of the form
    1787              :    {"escaped": true/false,
    1788              :     "touched": true/false,
    1789              :     "map" : object for the binding_map.  */
    1790              : 
    1791              : std::unique_ptr<json::object>
    1792            0 : binding_cluster::to_json () const
    1793              : {
    1794            0 :   auto cluster_obj = std::make_unique<json::object> ();
    1795              : 
    1796            0 :   cluster_obj->set_bool ("escaped", m_escaped);
    1797            0 :   cluster_obj->set_bool ("touched", m_touched);
    1798            0 :   cluster_obj->set ("map", m_map.to_json ());
    1799              : 
    1800            0 :   return cluster_obj;
    1801              : }
    1802              : 
    1803              : std::unique_ptr<text_art::tree_widget>
    1804            0 : binding_cluster::make_dump_widget (const text_art::dump_widget_info &dwi,
    1805              :                                    store_manager *mgr) const
    1806              : {
    1807            0 :   pretty_printer the_pp;
    1808            0 :   pretty_printer * const pp = &the_pp;
    1809            0 :   pp_format_decoder (pp) = default_tree_printer;
    1810            0 :   pp_show_color (pp) = true;
    1811            0 :   const bool simple = true;
    1812              : 
    1813            0 :   m_base_region->dump_to_pp (pp, simple);
    1814            0 :   pp_string (pp, ": ");
    1815              : 
    1816            0 :   if (const svalue *sval = maybe_get_simple_value (mgr))
    1817              :     {
    1818              :       /* Special-case to simplify dumps for the common case where
    1819              :          we just have one value directly bound to the whole of a
    1820              :          region.  */
    1821            0 :       sval->dump_to_pp (pp, simple);
    1822            0 :       if (escaped_p ())
    1823            0 :         pp_string (pp, " (ESCAPED)");
    1824            0 :       if (touched_p ())
    1825            0 :         pp_string (pp, " (TOUCHED)");
    1826              : 
    1827            0 :       return text_art::tree_widget::make (dwi, pp);
    1828              :     }
    1829              :   else
    1830              :     {
    1831            0 :       if (escaped_p ())
    1832            0 :         pp_string (pp, " (ESCAPED)");
    1833            0 :       if (touched_p ())
    1834            0 :         pp_string (pp, " (TOUCHED)");
    1835              : 
    1836            0 :       std::unique_ptr<text_art::tree_widget> cluster_widget
    1837            0 :         (text_art::tree_widget::make (dwi, pp));
    1838              : 
    1839            0 :       m_map.add_to_tree_widget (*cluster_widget, dwi);
    1840              : 
    1841            0 :       return cluster_widget;
    1842            0 :     }
    1843            0 : }
    1844              : 
    1845              : /* Add a binding of SVAL of kind KIND to REG, unpacking SVAL if it is a
    1846              :    compound_sval.  */
    1847              : 
    1848              : void
    1849       461113 : binding_cluster::bind (store_manager *mgr,
    1850              :                        const region *reg, const svalue *sval)
    1851              : {
    1852       922226 :   if (const compound_svalue *compound_sval
    1853       461113 :         = sval->dyn_cast_compound_svalue ())
    1854              :     {
    1855          941 :       bind_compound_sval (mgr, reg, compound_sval);
    1856          941 :       return;
    1857              :     }
    1858              : 
    1859       460172 :   if (reg->empty_p ())
    1860              :     return;
    1861       460172 :   const binding_key *binding = binding_key::make (mgr, reg);
    1862       460172 :   bind_key (binding, sval);
    1863              : }
    1864              : 
    1865              : /* Bind SVAL to KEY.
    1866              :    Unpacking of compound_svalues should already have been done by the
    1867              :    time this is called.  */
    1868              : 
    1869              : void
    1870       463067 : binding_cluster::bind_key (const binding_key *key, const svalue *sval)
    1871              : {
    1872       463067 :   gcc_assert (sval->get_kind () != SK_COMPOUND);
    1873              : 
    1874       463067 :   m_map.put (key, sval);
    1875       463067 :   if (key->symbolic_p ())
    1876        25042 :     m_touched = true;
    1877       463067 : }
    1878              : 
    1879              : /* Subroutine of binding_cluster::bind.
    1880              :    Unpack compound_svals when binding them, so that we bind them
    1881              :    element-wise.  */
    1882              : 
    1883              : void
    1884          941 : binding_cluster::bind_compound_sval (store_manager *mgr,
    1885              :                                      const region *reg,
    1886              :                                      const compound_svalue *compound_sval)
    1887              : {
    1888          941 :   region_offset reg_offset
    1889          941 :     = reg->get_offset (mgr->get_svalue_manager ());
    1890          941 :   if (reg_offset.symbolic_p ())
    1891              :     {
    1892            4 :       m_touched = true;
    1893            4 :       clobber_region (mgr, reg);
    1894            4 :       return;
    1895              :     }
    1896              : 
    1897         3432 :   for (auto iter : *compound_sval)
    1898              :     {
    1899         2495 :       const bit_range &iter_bits = iter.first;
    1900         2495 :       const svalue *iter_sval = iter.second;
    1901              : 
    1902         2495 :       bit_offset_t effective_start
    1903         2495 :         = (iter_bits.get_start_bit_offset ()
    1904         2495 :            + reg_offset.get_bit_offset ());
    1905         2495 :       const bit_range affected_bits (effective_start,
    1906         2495 :                                      iter_bits.m_size_in_bits);
    1907         2495 :       bind_key (mgr->get_concrete_binding (affected_bits), iter_sval);
    1908              :     }
    1909              : }
    1910              : 
    1911              : /* Remove all bindings overlapping REG within this cluster.  */
    1912              : 
    1913              : void
    1914         6577 : binding_cluster::clobber_region (store_manager *mgr, const region *reg)
    1915              : {
    1916         6577 :   remove_overlapping_bindings (mgr, reg, nullptr, nullptr);
    1917         6577 : }
    1918              : 
    1919              : /* Remove any bindings for REG within this cluster.  */
    1920              : 
    1921              : void
    1922       225319 : binding_cluster::purge_region (store_manager *mgr, const region *reg)
    1923              : {
    1924       225319 :   gcc_assert (reg->get_kind () == RK_DECL);
    1925       225319 :   if (reg->empty_p ())
    1926              :     return;
    1927       225319 :   const binding_key *binding
    1928       225319 :     = binding_key::make (mgr, const_cast<region *> (reg));
    1929       225319 :   m_map.remove (binding);
    1930              : }
    1931              : 
    1932              : /* Clobber REG and fill it with repeated copies of SVAL.  */
    1933              : 
    1934              : void
    1935         1598 : binding_cluster::fill_region (store_manager *mgr,
    1936              :                               const region *reg,
    1937              :                               const svalue *sval)
    1938              : {
    1939         1598 :   clobber_region (mgr, reg);
    1940              : 
    1941         1598 :   region_model_manager *sval_mgr = mgr->get_svalue_manager ();
    1942         1598 :   const svalue *byte_size_sval = reg->get_byte_size_sval (sval_mgr);
    1943         1598 :   const svalue *fill_sval
    1944         1598 :     = sval_mgr->get_or_create_repeated_svalue (reg->get_type (),
    1945              :                                                byte_size_sval, sval);
    1946         1598 :   bind (mgr, reg, fill_sval);
    1947         1598 : }
    1948              : 
    1949              : /* Clobber REG within this cluster and fill it with zeroes.  */
    1950              : 
    1951              : void
    1952           33 : binding_cluster::zero_fill_region (store_manager *mgr, const region *reg)
    1953              : {
    1954           33 :   region_model_manager *sval_mgr = mgr->get_svalue_manager ();
    1955           33 :   const svalue *zero_sval = sval_mgr->get_or_create_int_cst (char_type_node, 0);
    1956           33 :   fill_region (mgr, reg, zero_sval);
    1957           33 : }
    1958              : 
    1959              : /* Mark REG_TO_BIND within this cluster as being unknown.
    1960              : 
    1961              :    Remove any bindings overlapping REG_FOR_OVERLAP.
    1962              :    If UNCERTAINTY is non-NULL, use it to record any svalues that
    1963              :    had bindings to them removed, as being maybe-bound.
    1964              :    If MAYBE_LIVE_VALUES is non-NULL, use it to record any svalues that
    1965              :    had bindings to them removed, as being maybe-live.
    1966              : 
    1967              :    REG_TO_BIND and REG_FOR_OVERLAP are the same for
    1968              :    store::mark_region_as_unknown, but are different in
    1969              :    store::set_value's alias handling, for handling the case where
    1970              :    we have a write to a symbolic REG_FOR_OVERLAP. */
    1971              : 
    1972              : void
    1973        47528 : binding_cluster::mark_region_as_unknown (store_manager *mgr,
    1974              :                                          const region *reg_to_bind,
    1975              :                                          const region *reg_for_overlap,
    1976              :                                          uncertainty_t *uncertainty,
    1977              :                                          svalue_set *maybe_live_values)
    1978              : {
    1979        47528 :   if (reg_to_bind->empty_p ())
    1980              :     return;
    1981              : 
    1982        47528 :   remove_overlapping_bindings (mgr, reg_for_overlap, uncertainty,
    1983              :                                maybe_live_values);
    1984              : 
    1985              :   /* Add a default binding to "unknown".  */
    1986        47528 :   region_model_manager *sval_mgr = mgr->get_svalue_manager ();
    1987        47528 :   const svalue *sval
    1988        47528 :     = sval_mgr->get_or_create_unknown_svalue (reg_to_bind->get_type ());
    1989        47528 :   bind (mgr, reg_to_bind, sval);
    1990              : }
    1991              : 
    1992              : /* Purge state involving SVAL.  */
    1993              : 
    1994              : void
    1995       405535 : binding_cluster::purge_state_involving (const svalue *sval,
    1996              :                                         region_model_manager *sval_mgr)
    1997              : {
    1998       405535 :   auto_vec<const binding_key *> to_remove;
    1999       405535 :   auto_vec<std::pair<const binding_key *, tree> > to_make_unknown;
    2000       813991 :   for (auto iter : m_map)
    2001              :     {
    2002       408456 :       const binding_key *iter_key = iter.m_key;
    2003       816912 :       if (const symbolic_binding *symbolic_key
    2004       408456 :             = iter_key->dyn_cast_symbolic_binding ())
    2005              :         {
    2006        32861 :           const region *reg = symbolic_key->get_region ();
    2007        32861 :           if (reg->involves_p (sval))
    2008            0 :             to_remove.safe_push (iter_key);
    2009              :         }
    2010       408456 :       const svalue *iter_sval = iter.m_sval;
    2011       408456 :       if (iter_sval->involves_p (sval))
    2012         3185 :         to_make_unknown.safe_push (std::make_pair(iter_key,
    2013         3185 :                                                   iter_sval->get_type ()));
    2014              :     }
    2015       405535 :   for (auto iter : to_remove)
    2016              :     {
    2017            0 :       m_map.remove (iter);
    2018            0 :       m_touched = true;
    2019              :     }
    2020       415090 :   for (auto iter : to_make_unknown)
    2021              :     {
    2022         3185 :       const svalue *new_sval
    2023         3185 :         = sval_mgr->get_or_create_unknown_svalue (iter.second);
    2024         3185 :       m_map.put (iter.first, new_sval);
    2025              :     }
    2026       405535 : }
    2027              : 
    2028              : /* Get any SVAL bound to REG within this cluster via kind KIND,
    2029              :    without checking parent regions of REG.  */
    2030              : 
    2031              : const svalue *
    2032      1473014 : binding_cluster::get_binding (store_manager *mgr,
    2033              :                               const region *reg) const
    2034              : {
    2035      1473014 :   if (reg->empty_p ())
    2036              :     return nullptr;
    2037      1473014 :   const binding_key *reg_binding = binding_key::make (mgr, reg);
    2038      1473014 :   const svalue *sval = m_map.get (reg_binding);
    2039      1473014 :   if (sval)
    2040              :     {
    2041              :       /* If we have a struct with a single field, then the binding of
    2042              :          the field will equal that of the struct, and looking up e.g.
    2043              :          PARENT_REG.field within:
    2044              :             cluster for PARENT_REG: INIT_VAL(OTHER_REG)
    2045              :          will erroneously return INIT_VAL(OTHER_REG), rather than
    2046              :            SUB_VALUE(INIT_VAL(OTHER_REG), FIELD) == INIT_VAL(OTHER_REG.FIELD).
    2047              :          Fix this issue by iterating upwards whilst the bindings are equal,
    2048              :          expressing the lookups as subvalues.
    2049              :          We have to gather a list of subregion accesses, then walk it
    2050              :          in reverse to get the subvalues.  */
    2051      1197569 :       auto_vec<const region *> regions;
    2052      1208511 :       while (const region *parent_reg = reg->get_parent_region ())
    2053              :         {
    2054      1208511 :           const binding_key *parent_reg_binding
    2055      1208511 :             = binding_key::make (mgr, parent_reg);
    2056      1208511 :           if (parent_reg_binding == reg_binding
    2057        14084 :               && sval->get_type ()
    2058        13268 :               && reg->get_type ()
    2059      1221779 :               && sval->get_type () != reg->get_type ())
    2060              :             {
    2061        10942 :               regions.safe_push (reg);
    2062        10942 :               reg = parent_reg;
    2063              :             }
    2064              :           else
    2065              :             break;
    2066        10942 :         }
    2067      1197569 :       if (sval->get_type ()
    2068      1187417 :           && reg->get_type ()
    2069      2383941 :           && sval->get_type () == reg->get_type ())
    2070              :         {
    2071       966736 :           unsigned i;
    2072       966736 :           const region *iter_reg;
    2073      1224384 :           FOR_EACH_VEC_ELT_REVERSE (regions, i, iter_reg)
    2074              :             {
    2075         9123 :               region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
    2076         9123 :               sval = rmm_mgr->get_or_create_sub_svalue (iter_reg->get_type (),
    2077              :                                                         sval, iter_reg);
    2078              :             }
    2079              :         }
    2080      1197569 :     }
    2081              :   return sval;
    2082              : }
    2083              : 
    2084              : /* Get any SVAL bound to REG within this cluster,
    2085              :    either directly for REG, or recursively checking for bindings within
    2086              :    parent regions and extracting subvalues if need be.  */
    2087              : 
    2088              : const svalue *
    2089      1473014 : binding_cluster::get_binding_recursive (store_manager *mgr,
    2090              :                                         const region *reg) const
    2091              : {
    2092      1473014 :   if (const svalue *sval = get_binding (mgr, reg))
    2093              :     return sval;
    2094       275445 :   if (reg != m_base_region)
    2095       169361 :     if (const region *parent_reg = reg->get_parent_region ())
    2096       338722 :       if (const svalue *parent_sval
    2097       169361 :           = get_binding_recursive (mgr, parent_reg))
    2098              :         {
    2099              :           /* Extract child svalue from parent svalue.  */
    2100        56662 :           region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
    2101        56662 :           return rmm_mgr->get_or_create_sub_svalue (reg->get_type (),
    2102        56662 :                                                     parent_sval, reg);
    2103              :         }
    2104              :   return nullptr;
    2105              : }
    2106              : 
    2107              : /* Get any value bound for REG within this cluster.  */
    2108              : 
    2109              : const svalue *
    2110      1303653 : binding_cluster::get_any_binding (store_manager *mgr,
    2111              :                                   const region *reg) const
    2112              : {
    2113              :   /* Look for a direct binding.  */
    2114      2607306 :   if (const svalue *direct_sval
    2115      1303653 :       = get_binding_recursive (mgr, reg))
    2116              :     return direct_sval;
    2117              : 
    2118              :   /* If we had a write to a cluster of unknown size, we might
    2119              :      have a self-binding of the whole base region with an svalue,
    2120              :      where the base region is symbolic.
    2121              :      Handle such cases by returning sub_svalue instances.  */
    2122       106084 :   if (const svalue *cluster_sval = maybe_get_simple_value (mgr))
    2123              :     {
    2124              :       /* Extract child svalue from parent svalue.  */
    2125            0 :       region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
    2126            0 :       return rmm_mgr->get_or_create_sub_svalue (reg->get_type (),
    2127            0 :                                                 cluster_sval, reg);
    2128              :     }
    2129              : 
    2130              :   /* If this cluster has been touched by a symbolic write, then the content
    2131              :      of any subregion not currently specifically bound is "UNKNOWN".  */
    2132       106084 :   if (m_touched)
    2133              :     {
    2134         7236 :       region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
    2135         7236 :       return rmm_mgr->get_or_create_unknown_svalue (reg->get_type ());
    2136              :     }
    2137              : 
    2138              :   /* Alternatively, if this is a symbolic read and the cluster has any bindings,
    2139              :      then we don't know if we're reading those values or not, so the result
    2140              :      is also "UNKNOWN".  */
    2141        98848 :   if (reg->get_offset (mgr->get_svalue_manager ()).symbolic_p ()
    2142        98848 :       && m_map.elements () > 0)
    2143              :     {
    2144          440 :       region_model_manager *rmm_mgr = mgr->get_svalue_manager ();
    2145          440 :       return rmm_mgr->get_or_create_unknown_svalue (reg->get_type ());
    2146              :     }
    2147              : 
    2148        98408 :   if (const svalue *compound_sval = maybe_get_compound_binding (mgr, reg))
    2149              :     return compound_sval;
    2150              : 
    2151              :   /* Otherwise, the initial value, or uninitialized.  */
    2152              :   return nullptr;
    2153              : }
    2154              : 
    2155              : /* Attempt to get a compound_svalue for the bindings within the cluster
    2156              :    affecting REG (which could be the base region itself).
    2157              : 
    2158              :    Create a compound_svalue with the subset of bindings the affect REG,
    2159              :    offsetting them so that the offsets are relative to the start of REG
    2160              :    within the cluster.
    2161              : 
    2162              :    For example, REG could be one element within an array of structs.
    2163              : 
    2164              :    Return the resulting compound_svalue, or nullptr if there's a problem.  */
    2165              : 
    2166              : const svalue *
    2167        98408 : binding_cluster::maybe_get_compound_binding (store_manager *mgr,
    2168              :                                              const region *reg) const
    2169              : {
    2170        98408 :   region_offset cluster_offset
    2171        98408 :     = m_base_region->get_offset (mgr->get_svalue_manager ());
    2172        98408 :   if (cluster_offset.symbolic_p ())
    2173              :     return nullptr;
    2174        98408 :   region_offset reg_offset = reg->get_offset (mgr->get_svalue_manager ());
    2175        98408 :   if (reg_offset.symbolic_p ())
    2176              :     return nullptr;
    2177              : 
    2178        78888 :   if (reg->empty_p ())
    2179              :     return nullptr;
    2180              : 
    2181        78888 :   region_model_manager *sval_mgr = mgr->get_svalue_manager ();
    2182              : 
    2183              :   /* We will a build the result map in two parts:
    2184              :      (a) result_map, holding the concrete keys from this cluster,
    2185              : 
    2186              :      (b) default_map, holding the initial values for the region
    2187              :      (e.g. uninitialized, initializer values, or zero), unless this
    2188              :      cluster has been touched.
    2189              : 
    2190              :      We will populate (a), and as we do, clobber (b), trimming and
    2191              :      splitting its bindings as necessary.
    2192              :      Finally, we will merge (b) into (a), giving a concrete map
    2193              :      that merges both the initial values and the bound values from
    2194              :      the binding_cluster.
    2195              :      Doing it this way reduces N for the O(N^2) intersection-finding,
    2196              :      perhaps we should have a spatial-organized data structure for
    2197              :      concrete keys, though.  */
    2198              : 
    2199        78888 :   concrete_binding_map result_map;
    2200        78888 :   concrete_binding_map default_map;
    2201              : 
    2202              :   /* Set up default values in default_map.  */
    2203        78888 :   const svalue *default_sval;
    2204        78888 :   if (m_touched)
    2205            0 :     default_sval = sval_mgr->get_or_create_unknown_svalue (reg->get_type ());
    2206              :   else
    2207        78888 :     default_sval = sval_mgr->get_or_create_initial_value (reg);
    2208        78888 :   const binding_key *default_key = binding_key::make (mgr, reg);
    2209              : 
    2210              :   /* Express the bit-range of the default key for REG relative to REG,
    2211              :      rather than to the base region.  */
    2212        78888 :   const concrete_binding *concrete_default_key
    2213        78888 :     = default_key->dyn_cast_concrete_binding ();
    2214        78888 :   if (!concrete_default_key)
    2215              :     return nullptr;
    2216        78011 :   const bit_range default_key_relative_to_reg
    2217        78011 :      (0, concrete_default_key->get_size_in_bits ());
    2218              : 
    2219        78011 :   default_map.insert (default_key_relative_to_reg, default_sval);
    2220              : 
    2221       154441 :   for (auto iter : m_map)
    2222              :     {
    2223        83816 :       const binding_key *key = iter.m_key;
    2224        83816 :       const svalue *sval = iter.m_sval;
    2225              : 
    2226       167632 :       if (const concrete_binding *concrete_key
    2227        83816 :           = key->dyn_cast_concrete_binding ())
    2228              :         {
    2229        83816 :           const bit_range &bound_range = concrete_key->get_bit_range ();
    2230              : 
    2231        83816 :           bit_size_t reg_bit_size;
    2232        83816 :           if (!reg->get_bit_size (&reg_bit_size))
    2233         7386 :             return nullptr;
    2234              : 
    2235        83816 :           bit_range reg_range (reg_offset.get_bit_offset (),
    2236        83816 :                                reg_bit_size);
    2237              : 
    2238              :           /* Skip bindings that are outside the bit range of REG.  */
    2239        83816 :           if (!bound_range.intersects_p (reg_range))
    2240        67451 :             continue;
    2241              : 
    2242              :           /* We shouldn't have an exact match; that should have been
    2243              :              handled already.  */
    2244        16365 :           gcc_assert (!(reg_range == bound_range));
    2245              : 
    2246        16365 :           bit_range subrange (0, 0);
    2247        16365 :           if (reg_range.contains_p (bound_range, &subrange))
    2248              :             {
    2249              :               /* We have a bound range fully within REG.
    2250              :                  Add it to result_map, offsetting accordingly.  */
    2251         8903 :               result_map.insert (subrange, sval);
    2252              : 
    2253              :               /* Clobber default_map, removing/trimming/spliting where
    2254              :                  it overlaps with offset_concrete_key.  */
    2255         8903 :               default_map.remove_overlapping_bindings (mgr, subrange);
    2256              :             }
    2257         7462 :           else if (bound_range.contains_p (reg_range, &subrange))
    2258              :             {
    2259              :               /* REG is fully within the bound range, but
    2260              :                  is not equal to it; we're extracting a subvalue.  */
    2261         7386 :               return sval->extract_bit_range (reg->get_type (),
    2262              :                                               subrange,
    2263         7386 :                                               mgr->get_svalue_manager ());
    2264              :             }
    2265              :           else
    2266              :             {
    2267              :               /* REG and the bound range partially overlap.  */
    2268           76 :               bit_range reg_subrange (0, 0);
    2269           76 :               bit_range bound_subrange (0, 0);
    2270           76 :               reg_range.intersects_p (bound_range,
    2271              :                                       &reg_subrange, &bound_subrange);
    2272              : 
    2273              :               /* Get the bits from the bound value for the bits at the
    2274              :                  intersection (relative to the bound value).  */
    2275           76 :               const svalue *overlap_sval
    2276           76 :                 = sval->extract_bit_range (NULL_TREE,
    2277              :                                            bound_subrange,
    2278              :                                            mgr->get_svalue_manager ());
    2279              : 
    2280           76 :               result_map.insert (reg_subrange, overlap_sval);
    2281              : 
    2282              :               /* Clobber default_map, removing/trimming/spliting where
    2283              :                  it overlaps with overlap_concrete_key.  */
    2284           76 :               default_map.remove_overlapping_bindings (mgr, reg_subrange);
    2285              :             }
    2286              :         }
    2287              :       else
    2288              :         /* Can't handle symbolic bindings.  */
    2289              :         return nullptr;
    2290              :     }
    2291              : 
    2292        70625 :   if (result_map.size () == 0)
    2293              :     return nullptr;
    2294              : 
    2295              :   /* Merge any bindings from default_map into result_map.  */
    2296         3659 :   for (auto iter : default_map)
    2297              :     {
    2298          323 :       const bit_range &key = iter.first;
    2299          323 :       const svalue *sval = iter.second;
    2300          323 :       result_map.insert (key, sval);
    2301              :     }
    2302              : 
    2303         3336 :   return sval_mgr->get_or_create_compound_svalue (reg->get_type (),
    2304         3336 :                                                   std::move (result_map));
    2305        78888 : }
    2306              : 
    2307              : /* Remove, truncate, and/or split any bindings within this map that
    2308              :    could overlap REG.
    2309              : 
    2310              :    If REG's base region or this cluster is symbolic and they're different
    2311              :    base regions, then remove everything in this cluster's map, on the
    2312              :    grounds that REG could be referring to the same memory as anything
    2313              :    in the map.
    2314              : 
    2315              :    If UNCERTAINTY is non-NULL, use it to record any svalues that
    2316              :    were removed, as being maybe-bound.
    2317              : 
    2318              :    If MAYBE_LIVE_VALUES is non-NULL, use it to record any svalues that
    2319              :    were removed, as being maybe-live.  */
    2320              : 
    2321              : void
    2322        82539 : binding_cluster::remove_overlapping_bindings (store_manager *mgr,
    2323              :                                               const region *reg,
    2324              :                                               uncertainty_t *uncertainty,
    2325              :                                               svalue_set *maybe_live_values)
    2326              : {
    2327        82539 :   if (reg->empty_p ())
    2328              :     return;
    2329        82539 :   const binding_key *reg_binding = binding_key::make (mgr, reg);
    2330              : 
    2331        82539 :   const region *cluster_base_reg = get_base_region ();
    2332        82539 :   const region *other_base_reg = reg->get_base_region ();
    2333              :   /* If at least one of the base regions involved is symbolic, and they're
    2334              :      not the same base region, then consider everything in the map as
    2335              :      potentially overlapping with reg_binding (even if it's a concrete
    2336              :      binding and things in the map are concrete - they could be referring
    2337              :      to the same memory when the symbolic base regions are taken into
    2338              :      account).  */
    2339        82539 :   bool always_overlap = (cluster_base_reg != other_base_reg
    2340        82539 :                          && (cluster_base_reg->get_kind () == RK_SYMBOLIC
    2341        18091 :                              || other_base_reg->get_kind () == RK_SYMBOLIC));
    2342        82539 :   m_map.remove_overlapping_bindings (mgr, reg_binding, uncertainty,
    2343              :                                      maybe_live_values,
    2344              :                                      always_overlap);
    2345              : }
    2346              : 
    2347              : /* Attempt to merge CLUSTER_A and CLUSTER_B into OUT_CLUSTER, using
    2348              :    MGR and MERGER.
    2349              :    Return true if they can be merged, false otherwise.  */
    2350              : 
    2351              : bool
    2352      1264244 : binding_cluster::can_merge_p (const binding_cluster *cluster_a,
    2353              :                               const binding_cluster *cluster_b,
    2354              :                               binding_cluster *out_cluster,
    2355              :                               store *out_store,
    2356              :                               store_manager *mgr,
    2357              :                               model_merger *merger)
    2358              : {
    2359      1264244 :   gcc_assert (out_cluster);
    2360              : 
    2361              :   /* Merge flags ("ESCAPED" and "TOUCHED") by setting the merged flag to
    2362              :      true if either of the inputs is true.  */
    2363      1264244 :   if ((cluster_a && cluster_a->m_escaped)
    2364       822129 :       || (cluster_b && cluster_b->m_escaped))
    2365         2708 :     out_cluster->m_escaped = true;
    2366      1264244 :   if ((cluster_a && cluster_a->m_touched)
    2367      1066231 :       || (cluster_b && cluster_b->m_touched))
    2368         7350 :     out_cluster->m_touched = true;
    2369              : 
    2370              :   /* At least one of CLUSTER_A and CLUSTER_B are non-NULL, but either
    2371              :      could be NULL.  Handle these cases.  */
    2372      1264244 :   if (cluster_a == nullptr)
    2373              :     {
    2374         7624 :       gcc_assert (cluster_b != nullptr);
    2375         7624 :       gcc_assert (cluster_b->m_base_region == out_cluster->m_base_region);
    2376         7624 :       out_cluster->make_unknown_relative_to (cluster_b, out_store, mgr);
    2377         7624 :       return true;
    2378              :     }
    2379      1256620 :   if (cluster_b == nullptr)
    2380              :     {
    2381        24661 :       gcc_assert (cluster_a != nullptr);
    2382        24661 :       gcc_assert (cluster_a->m_base_region == out_cluster->m_base_region);
    2383        24661 :       out_cluster->make_unknown_relative_to (cluster_a, out_store, mgr);
    2384        24661 :       return true;
    2385              :     }
    2386              : 
    2387              :   /* The "both inputs are non-NULL" case.  */
    2388      1231959 :   gcc_assert (cluster_a != nullptr && cluster_b != nullptr);
    2389      1231959 :   gcc_assert (cluster_a->m_base_region == out_cluster->m_base_region);
    2390      1231959 :   gcc_assert (cluster_b->m_base_region == out_cluster->m_base_region);
    2391              : 
    2392      1231959 :   hash_set<const binding_key *> keys;
    2393      3019284 :   for (auto iter_a  : cluster_a->m_map)
    2394              :     {
    2395      1787325 :       const binding_key *key_a = iter_a.m_key;
    2396      1787325 :       keys.add (key_a);
    2397              :     }
    2398      2913054 :   for (auto iter_b : cluster_b->m_map)
    2399              :     {
    2400      1681095 :       const binding_key *key_b = iter_b.m_key;
    2401      1681095 :       keys.add (key_b);
    2402              :     }
    2403      1231959 :   int num_symbolic_keys = 0;
    2404      1231959 :   int num_concrete_keys = 0;
    2405      2936539 :   for (hash_set<const binding_key *>::iterator iter = keys.begin ();
    2406      4641119 :        iter != keys.end (); ++iter)
    2407              :     {
    2408      1795044 :       region_model_manager *sval_mgr = mgr->get_svalue_manager ();
    2409      1795044 :       const binding_key *key = *iter;
    2410      1795044 :       const svalue *sval_a = cluster_a->get_any_value (key);
    2411      1795044 :       const svalue *sval_b = cluster_b->get_any_value (key);
    2412              : 
    2413      1795044 :       if (key->symbolic_p ())
    2414        52592 :         num_symbolic_keys++;
    2415              :       else
    2416      1742452 :         num_concrete_keys++;
    2417              : 
    2418      1795044 :       if (sval_a == sval_b)
    2419              :         {
    2420      1422182 :           gcc_assert (sval_a);
    2421      1422182 :           out_cluster->m_map.put (key, sval_a);
    2422      1422182 :           continue;
    2423              :         }
    2424       372862 :       else if (sval_a && sval_b)
    2425              :         {
    2426       433683 :           if (const svalue *merged_sval
    2427       160184 :               = sval_a->can_merge_p (sval_b, sval_mgr, merger))
    2428              :             {
    2429       113315 :               out_cluster->m_map.put (key, merged_sval);
    2430       113315 :               continue;
    2431              :             }
    2432              :           /* Merger of the svalues failed.  Reject merger of the cluster.   */
    2433        90464 :           return false;
    2434              :         }
    2435              : 
    2436              :       /* If we get here, then one cluster binds this key and the other
    2437              :          doesn't; merge them as "UNKNOWN".  */
    2438       212678 :       gcc_assert (sval_a || sval_b);
    2439              : 
    2440       212678 :       const svalue *bound_sval = sval_a ? sval_a : sval_b;
    2441       212678 :       tree type = bound_sval->get_type ();
    2442       212678 :       const svalue *unknown_sval
    2443       212678 :         = mgr->get_svalue_manager ()->get_or_create_unknown_svalue (type);
    2444              : 
    2445              :       /* ...but reject the merger if this sval shouldn't be mergeable
    2446              :          (e.g. reject merging svalues that have non-purgable sm-state,
    2447              :          to avoid falsely reporting memory leaks by merging them
    2448              :          with something else).  */
    2449       212678 :       if (!bound_sval->can_merge_p (unknown_sval, sval_mgr, merger))
    2450              :         return false;
    2451              : 
    2452       169083 :       out_cluster->m_map.put (key, unknown_sval);
    2453              :     }
    2454              : 
    2455              :   /* We might now have overlapping concrete clusters in OUT_CLUSTER.
    2456              :      Reject such cases.  */
    2457      1141495 :   if (num_concrete_keys > 0)
    2458              :     {
    2459              :       /* Check for overlapping concrete bindings.  */
    2460       851258 :       const auto &concrete_bindings
    2461       851258 :         = out_cluster->get_map ().get_concrete_bindings ();
    2462      2353934 :       for (auto iter = concrete_bindings.begin ();
    2463      2353934 :            iter != concrete_bindings.end (); ++iter)
    2464              :         {
    2465      1519242 :           auto next (iter);
    2466      1519242 :           ++next;
    2467      1519242 :           if (next != concrete_bindings.end ())
    2468              :             {
    2469       684550 :               const bit_range &iter_bits = iter->first;
    2470       684550 :               const bit_range &next_bits = next->first;
    2471       684550 :               if (iter_bits.intersects_p (next_bits))
    2472       107030 :                 return false;
    2473              :             }
    2474              :         }
    2475              :     }
    2476              : 
    2477              :   /* We can only have at most one symbolic key per cluster,
    2478              :      and if we do, we can't have any concrete keys.
    2479              :      If this happens, mark the cluster as touched, with no keys.  */
    2480      1124929 :   if (num_symbolic_keys >= 2
    2481      1124324 :       || (num_concrete_keys > 0 && num_symbolic_keys > 0))
    2482              :     {
    2483         2715 :       out_cluster->m_touched = true;
    2484         2715 :       out_cluster->m_map.clear ();
    2485              :     }
    2486              : 
    2487              :   /* We don't handle other kinds of overlaps yet.  */
    2488              : 
    2489              :   return true;
    2490      1231959 : }
    2491              : 
    2492              : /* Update this cluster to reflect an attempt to merge OTHER where there
    2493              :    is no other cluster to merge with, and so we're notionally merging the
    2494              :    bound values in OTHER with the initial value of the relevant regions.
    2495              : 
    2496              :    Any bound keys in OTHER should be bound to unknown in this.  */
    2497              : 
    2498              : void
    2499        32285 : binding_cluster::make_unknown_relative_to (const binding_cluster *other,
    2500              :                                            store *out_store,
    2501              :                                            store_manager *mgr)
    2502              : {
    2503        64619 :   for (auto iter : *other)
    2504              :     {
    2505        32334 :       const binding_key *iter_key = iter.m_key;
    2506        32334 :       const svalue *iter_sval = iter.m_sval;
    2507        32334 :       const svalue *unknown_sval
    2508              :         = mgr->get_svalue_manager ()->get_or_create_unknown_svalue
    2509        32334 :           (iter_sval->get_type ());
    2510        32334 :       m_map.put (iter_key, unknown_sval);
    2511              : 
    2512              :       /* For any pointers in OTHER, the merger means that the
    2513              :          concrete pointer becomes an unknown value, which could
    2514              :          show up as a false report of a leak when considering what
    2515              :          pointers are live before vs after.
    2516              :          Avoid this by marking the base regions they point to as having
    2517              :          escaped.  */
    2518        64668 :       if (const region_svalue *region_sval
    2519        32334 :           = iter_sval->dyn_cast_region_svalue ())
    2520              :         {
    2521         2115 :           const region *base_reg
    2522         2115 :             = region_sval->get_pointee ()->get_base_region ();
    2523         2115 :           if (base_reg->tracked_p ()
    2524         2115 :               && !base_reg->symbolic_for_unknown_ptr_p ())
    2525              :             {
    2526         2113 :               binding_cluster *c
    2527         2113 :                 = out_store->get_or_create_cluster (*mgr, base_reg);
    2528         2113 :               c->mark_as_escaped ();
    2529              :             }
    2530              :         }
    2531              :     }
    2532        32285 : }
    2533              : 
    2534              : /* Mark this cluster as having escaped.  */
    2535              : 
    2536              : void
    2537        36862 : binding_cluster::mark_as_escaped ()
    2538              : {
    2539        36862 :   m_escaped = true;
    2540        36862 : }
    2541              : 
    2542              : /* If this cluster has escaped (by this call, or by an earlier one, or
    2543              :    by being an external param), then unbind all values and mark it
    2544              :    as "touched", so that it has a conjured value, rather than an
    2545              :    initial_svalue.
    2546              :    Use P to purge state involving conjured_svalues.  */
    2547              : 
    2548              : void
    2549       124083 : binding_cluster::on_unknown_fncall (const gcall &call,
    2550              :                                     store_manager *mgr,
    2551              :                                     const conjured_purge &p)
    2552              : {
    2553       124083 :   if (m_escaped)
    2554              :     {
    2555        21206 :       m_map.clear ();
    2556              : 
    2557        21206 :       if (!m_base_region->empty_p ())
    2558              :         {
    2559              :           /* Bind it to a new "conjured" value using CALL.  */
    2560        21206 :           const svalue *sval
    2561              :             = mgr->get_svalue_manager ()->get_or_create_conjured_svalue
    2562        21206 :             (m_base_region->get_type (), &call, m_base_region, p);
    2563        21206 :           bind (mgr, m_base_region, sval);
    2564              :         }
    2565              : 
    2566        21206 :       m_touched = true;
    2567              :     }
    2568       124083 : }
    2569              : 
    2570              : /* Mark this cluster as having been clobbered by STMT.
    2571              :    Use P to purge state involving conjured_svalues.  */
    2572              : 
    2573              : void
    2574          510 : binding_cluster::on_asm (const gasm *stmt,
    2575              :                          store_manager *mgr,
    2576              :                          const conjured_purge &p)
    2577              : {
    2578          510 :   m_map.clear ();
    2579              : 
    2580              :   /* Bind it to a new "conjured" value using CALL.  */
    2581          510 :   const svalue *sval
    2582              :     = mgr->get_svalue_manager ()->get_or_create_conjured_svalue
    2583          510 :     (m_base_region->get_type (), stmt, m_base_region, p);
    2584          510 :   bind (mgr, m_base_region, sval);
    2585              : 
    2586          510 :   m_touched = true;
    2587          510 : }
    2588              : 
    2589              : /* Return true if this cluster has escaped.  */
    2590              : 
    2591              : bool
    2592      9529280 : binding_cluster::escaped_p () const
    2593              : {
    2594              :   /* Consider the "errno" region to always have escaped.  */
    2595      9529280 :   if (m_base_region->get_kind () == RK_ERRNO)
    2596              :     return true;
    2597      9505729 :   return m_escaped;
    2598              : }
    2599              : 
    2600              : /* Return true if this binding_cluster has no information
    2601              :    i.e. if there are no bindings, and it hasn't been marked as having
    2602              :    escaped, or touched symbolically.  */
    2603              : 
    2604              : bool
    2605       230294 : binding_cluster::redundant_p () const
    2606              : {
    2607       230294 :   return (m_map.elements () == 0
    2608       226385 :           && !m_escaped
    2609       455506 :           && !m_touched);
    2610              : }
    2611              : 
    2612              : /* Add PV to OUT_PVS, casting it to TYPE if it is not already of that type.  */
    2613              : 
    2614              : static void
    2615         7460 : append_pathvar_with_type (path_var pv,
    2616              :                           tree type,
    2617              :                           auto_vec<path_var> *out_pvs)
    2618              : {
    2619         7460 :   gcc_assert (pv.m_tree);
    2620              : 
    2621         7460 :   if (TREE_TYPE (pv.m_tree) != type)
    2622          879 :     pv.m_tree = build1 (NOP_EXPR, type, pv.m_tree);
    2623              : 
    2624         7460 :   out_pvs->safe_push (pv);
    2625         7460 : }
    2626              : 
    2627              : /* Find representative path_vars for SVAL within this binding of BASE_REG,
    2628              :    appending the results to OUT_PVS.  */
    2629              : 
    2630              : void
    2631        46064 : binding_cluster::get_representative_path_vars (const region_model *model,
    2632              :                                                svalue_set *visited,
    2633              :                                                const region *base_reg,
    2634              :                                                const svalue *sval,
    2635              :                                                logger *logger,
    2636              :                                                auto_vec<path_var> *out_pvs)
    2637              :   const
    2638              : {
    2639        46064 :   sval = simplify_for_binding (sval);
    2640              : 
    2641        88835 :   for (auto iter : m_map)
    2642              :     {
    2643        42771 :       const binding_key *key = iter.m_key;
    2644        42771 :       const svalue *bound_sval = iter.m_sval;
    2645        42771 :       if (bound_sval == sval)
    2646              :         {
    2647        15702 :           if (const concrete_binding *ckey
    2648         7851 :                 = key->dyn_cast_concrete_binding ())
    2649              :             {
    2650         7817 :               auto_vec <const region *> subregions;
    2651         7817 :               base_reg->get_subregions_for_binding
    2652         7817 :                 (model->get_manager (),
    2653              :                  ckey->get_start_bit_offset (),
    2654              :                  ckey->get_size_in_bits (),
    2655              :                  sval->get_type (),
    2656              :                  &subregions);
    2657         7817 :               unsigned i;
    2658         7817 :               const region *subregion;
    2659        22677 :               FOR_EACH_VEC_ELT (subregions, i, subregion)
    2660              :                 {
    2661        14860 :                   if (path_var pv
    2662         7430 :                       = model->get_representative_path_var (subregion,
    2663              :                                                             visited,
    2664         7430 :                                                             logger))
    2665         7426 :                     append_pathvar_with_type (pv, sval->get_type (), out_pvs);
    2666              :                 }
    2667         7817 :             }
    2668              :           else
    2669              :             {
    2670           34 :               const symbolic_binding *skey = (const symbolic_binding *)key;
    2671           68 :               if (path_var pv
    2672           34 :                   = model->get_representative_path_var (skey->get_region (),
    2673              :                                                         visited,
    2674           34 :                                                         logger))
    2675           34 :                 append_pathvar_with_type (pv, sval->get_type (), out_pvs);
    2676              :             }
    2677              :         }
    2678              :     }
    2679        46064 : }
    2680              : 
    2681              : /* Get any svalue bound to KEY, or nullptr.  */
    2682              : 
    2683              : const svalue *
    2684      3742390 : binding_cluster::get_any_value (const binding_key *key) const
    2685              : {
    2686      3742390 :   return m_map.get (key);
    2687              : }
    2688              : 
    2689              : /* If this cluster has a single direct binding for the whole of the region,
    2690              :    return it.
    2691              :    For use in simplifying dumps.  */
    2692              : 
    2693              : const svalue *
    2694       299448 : binding_cluster::maybe_get_simple_value (store_manager *mgr) const
    2695              : {
    2696              :   /* Fail gracefully if MGR is nullptr to make it easier to dump store
    2697              :      instances in the debugger.  */
    2698       299448 :   if (mgr == nullptr)
    2699              :     return nullptr;
    2700              : 
    2701       299448 :   if (m_map.elements () != 1)
    2702              :     return nullptr;
    2703              : 
    2704       152302 :   if (m_base_region->empty_p ())
    2705              :     return nullptr;
    2706              : 
    2707       152302 :   const binding_key *key = binding_key::make (mgr, m_base_region);
    2708       152302 :   return get_any_value (key);
    2709              : }
    2710              : 
    2711              : /* class store_manager.  */
    2712              : 
    2713              : logger *
    2714       392754 : store_manager::get_logger () const
    2715              : {
    2716       392754 :   return m_mgr->get_logger ();
    2717              : }
    2718              : 
    2719              : /* binding consolidation.  */
    2720              : 
    2721              : const concrete_binding *
    2722     13901686 : store_manager::get_concrete_binding (bit_offset_t start_bit_offset,
    2723              :                                      bit_offset_t size_in_bits)
    2724              : {
    2725     13901686 :   concrete_binding b (start_bit_offset, size_in_bits);
    2726     27790343 :   if (concrete_binding *existing = m_concrete_binding_key_mgr.get (b))
    2727              :     return existing;
    2728              : 
    2729        13029 :   concrete_binding *to_save = new concrete_binding (b);
    2730        13029 :   m_concrete_binding_key_mgr.put (b, to_save);
    2731        13029 :   return to_save;
    2732     13901686 : }
    2733              : 
    2734              : const symbolic_binding *
    2735      1893255 : store_manager::get_symbolic_binding (const region *reg)
    2736              : {
    2737      1893255 :   symbolic_binding b (reg);
    2738      3764529 :   if (symbolic_binding *existing = m_symbolic_binding_key_mgr.get (b))
    2739              :     return existing;
    2740              : 
    2741        21981 :   symbolic_binding *to_save = new symbolic_binding (b);
    2742        21981 :   m_symbolic_binding_key_mgr.put (b, to_save);
    2743        21981 :   return to_save;
    2744      1893255 : }
    2745              : 
    2746              : /* class store.  */
    2747              : 
    2748              : /* store's default ctor.  */
    2749              : 
    2750       419329 : store::store ()
    2751       419329 : : m_called_unknown_fn (false)
    2752              : {
    2753       419329 : }
    2754              : 
    2755              : /* store's copy ctor.  */
    2756              : 
    2757      3618409 : store::store (const store &other)
    2758      3618409 : : m_cluster_map (other.m_cluster_map.elements ()),
    2759      3618409 :   m_called_unknown_fn (other.m_called_unknown_fn)
    2760              : {
    2761      3618409 :   for (cluster_map_t::iterator iter = other.m_cluster_map.begin ();
    2762     34570014 :        iter != other.m_cluster_map.end ();
    2763     30951605 :        ++iter)
    2764              :     {
    2765     30951605 :       const region *reg = (*iter).first;
    2766            0 :       gcc_assert (reg);
    2767     30951605 :       binding_cluster *c = (*iter).second;
    2768     30951605 :       gcc_assert (c);
    2769     30951605 :       m_cluster_map.put (reg, new binding_cluster (*c));
    2770              :     }
    2771      3618409 : }
    2772              : 
    2773              : /* store's dtor.  */
    2774              : 
    2775      4037738 : store::~store ()
    2776              : {
    2777     36739917 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    2778     36739917 :        iter != m_cluster_map.end ();
    2779     32702179 :        ++iter)
    2780     32702179 :     delete (*iter).second;
    2781      4037738 : }
    2782              : 
    2783              : /* store's assignment operator.  */
    2784              : 
    2785              : store &
    2786        98815 : store::operator= (const store &other)
    2787              : {
    2788              :   /* Delete existing cluster map.  */
    2789       748646 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    2790       748646 :        iter != m_cluster_map.end ();
    2791       649831 :        ++iter)
    2792      1299662 :     delete (*iter).second;
    2793        98815 :   m_cluster_map.empty ();
    2794              : 
    2795        98815 :   m_called_unknown_fn = other.m_called_unknown_fn;
    2796              : 
    2797        98815 :   for (cluster_map_t::iterator iter = other.m_cluster_map.begin ();
    2798      1168921 :        iter != other.m_cluster_map.end ();
    2799      1070106 :        ++iter)
    2800              :     {
    2801      1070106 :       const region *reg = (*iter).first;
    2802      1070106 :       gcc_assert (reg);
    2803      1070106 :       binding_cluster *c = (*iter).second;
    2804      1070106 :       gcc_assert (c);
    2805      1070106 :       m_cluster_map.put (reg, new binding_cluster (*c));
    2806              :     }
    2807        98815 :   return *this;
    2808              : }
    2809              : 
    2810              : /* store's equality operator.  */
    2811              : 
    2812              : bool
    2813       526641 : store::operator== (const store &other) const
    2814              : {
    2815       526641 :   if (m_called_unknown_fn != other.m_called_unknown_fn)
    2816              :     return false;
    2817              : 
    2818       522579 :   if (m_cluster_map.elements () != other.m_cluster_map.elements ())
    2819              :     return false;
    2820              : 
    2821      3806832 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    2822      3806832 :        iter != m_cluster_map.end ();
    2823      3310667 :        ++iter)
    2824              :     {
    2825      3378992 :       const region *reg = (*iter).first;
    2826      3378992 :       binding_cluster *c = (*iter).second;
    2827      3378992 :       binding_cluster **other_slot
    2828      3378992 :         = const_cast <cluster_map_t &> (other.m_cluster_map).get (reg);
    2829      3378992 :       if (other_slot == nullptr)
    2830        68325 :         return false;
    2831      3376942 :       if (*c != **other_slot)
    2832              :         return false;
    2833              :     }
    2834              : 
    2835       427840 :   gcc_checking_assert (hash () == other.hash ());
    2836              : 
    2837              :   return true;
    2838              : }
    2839              : 
    2840              : /* Get a hash value for this store.  */
    2841              : 
    2842              : hashval_t
    2843      2166467 : store::hash () const
    2844              : {
    2845      2166467 :   hashval_t result = 0;
    2846      2166467 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    2847     17523664 :        iter != m_cluster_map.end ();
    2848     15357197 :        ++iter)
    2849     15357197 :     result ^= (*iter).second->hash ();
    2850      2166467 :   return result;
    2851              : }
    2852              : 
    2853              : /* Populate OUT with a sorted list of parent regions for the regions in IN,
    2854              :    removing duplicate parents.  */
    2855              : 
    2856              : static void
    2857         2134 : get_sorted_parent_regions (auto_vec<const region *> *out,
    2858              :                            auto_vec<const region *> &in)
    2859              : {
    2860              :   /* Get the set of parent regions.  */
    2861         2134 :   hash_set<const region *> parent_regions;
    2862         2134 :   const region *iter_reg;
    2863         2134 :   unsigned i;
    2864        10887 :   FOR_EACH_VEC_ELT (in, i, iter_reg)
    2865              :     {
    2866         8753 :       const region *parent_reg = iter_reg->get_parent_region ();
    2867         8753 :       gcc_assert (parent_reg);
    2868         8753 :       parent_regions.add (parent_reg);
    2869              :     }
    2870              : 
    2871              :   /* Write to OUT.  */
    2872         2134 :   for (hash_set<const region *>::iterator iter = parent_regions.begin();
    2873        11368 :        iter != parent_regions.end(); ++iter)
    2874         4617 :     out->safe_push (*iter);
    2875              : 
    2876              :   /* Sort OUT.  */
    2877         4066 :   out->qsort (region::cmp_ptr_ptr);
    2878         2134 : }
    2879              : 
    2880              : /* Dump a representation of this store to PP, using SIMPLE to control how
    2881              :    svalues and regions are printed.
    2882              :    MGR is used for simplifying dumps if non-NULL, but can also be nullptr
    2883              :    (to make it easier to use from the debugger).  */
    2884              : 
    2885              : void
    2886         2126 : store::dump_to_pp (pretty_printer *pp, bool simple, bool multiline,
    2887              :                    store_manager *mgr) const
    2888              : {
    2889              :   /* Sort into some deterministic order.  */
    2890         2126 :   auto_vec<const region *> base_regions;
    2891        10879 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    2892        19632 :        iter != m_cluster_map.end (); ++iter)
    2893              :     {
    2894         8753 :       const region *base_reg = (*iter).first;
    2895         8753 :       base_regions.safe_push (base_reg);
    2896              :     }
    2897         2126 :   base_regions.qsort (region::cmp_ptr_ptr);
    2898              : 
    2899              :   /* Gather clusters, organize by parent region, so that we can group
    2900              :      together locals, globals, etc.  */
    2901         2126 :   auto_vec<const region *> parent_regions;
    2902         2126 :   get_sorted_parent_regions (&parent_regions, base_regions);
    2903              : 
    2904         2126 :   const region *parent_reg;
    2905         2126 :   unsigned i;
    2906         6743 :   FOR_EACH_VEC_ELT (parent_regions, i, parent_reg)
    2907              :     {
    2908         4617 :       gcc_assert (parent_reg);
    2909         4617 :       pp_string (pp, "clusters within ");
    2910         4617 :       parent_reg->dump_to_pp (pp, simple);
    2911         4617 :       if (multiline)
    2912         1175 :         pp_newline (pp);
    2913              :       else
    2914         3442 :         pp_string (pp, " {");
    2915              : 
    2916              :       const region *base_reg;
    2917              :       unsigned j;
    2918        27008 :       FOR_EACH_VEC_ELT (base_regions, j, base_reg)
    2919              :         {
    2920              :           /* This is O(N * M), but N ought to be small.  */
    2921        22391 :           if (base_reg->get_parent_region () != parent_reg)
    2922        13638 :             continue;
    2923         8753 :           binding_cluster *cluster
    2924         8753 :             = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg);
    2925         8753 :           if (!multiline)
    2926              :             {
    2927         5854 :               if (j > 0)
    2928         4435 :                 pp_string (pp, ", ");
    2929              :             }
    2930         8753 :           if (const svalue *sval = cluster->maybe_get_simple_value (mgr))
    2931              :             {
    2932              :               /* Special-case to simplify dumps for the common case where
    2933              :                  we just have one value directly bound to the whole of a
    2934              :                  region.  */
    2935         7022 :               if (multiline)
    2936              :                 {
    2937         1811 :                   pp_string (pp, "  cluster for: ");
    2938         1811 :                   base_reg->dump_to_pp (pp, simple);
    2939         1811 :                   pp_string (pp, ": ");
    2940         1811 :                   sval->dump_to_pp (pp, simple);
    2941         1811 :                   if (cluster->escaped_p ())
    2942           48 :                     pp_string (pp, " (ESCAPED)");
    2943         1811 :                   if (cluster->touched_p ())
    2944            6 :                     pp_string (pp, " (TOUCHED)");
    2945         1811 :                   pp_newline (pp);
    2946              :                 }
    2947              :               else
    2948              :                 {
    2949         5211 :                   pp_string (pp, "region: {");
    2950         5211 :                   base_reg->dump_to_pp (pp, simple);
    2951         5211 :                   pp_string (pp, ", value: ");
    2952         5211 :                   sval->dump_to_pp (pp, simple);
    2953         5211 :                   if (cluster->escaped_p ())
    2954         1066 :                     pp_string (pp, " (ESCAPED)");
    2955         5211 :                   if (cluster->touched_p ())
    2956         1066 :                     pp_string (pp, " (TOUCHED)");
    2957         5211 :                   pp_string (pp, "}");
    2958              :                 }
    2959              :             }
    2960         1731 :           else if (multiline)
    2961              :             {
    2962         1088 :               pp_string (pp, "  cluster for: ");
    2963         1088 :               base_reg->dump_to_pp (pp, simple);
    2964         1088 :               pp_newline (pp);
    2965         1088 :               cluster->dump_to_pp (pp, simple, multiline);
    2966              :             }
    2967              :           else
    2968              :             {
    2969          643 :               pp_string (pp, "base region: {");
    2970          643 :               base_reg->dump_to_pp (pp, simple);
    2971          643 :               pp_string (pp, "} has cluster: {");
    2972          643 :               cluster->dump_to_pp (pp, simple, multiline);
    2973          643 :               pp_string (pp, "}");
    2974              :             }
    2975              :         }
    2976         4617 :       if (!multiline)
    2977         3442 :         pp_string (pp, "}");
    2978              :     }
    2979         2126 :   pp_printf (pp, "m_called_unknown_fn: %s",
    2980         2126 :              m_called_unknown_fn ? "TRUE" : "FALSE");
    2981         2126 :   if (multiline)
    2982          545 :     pp_newline (pp);
    2983         2126 : }
    2984              : 
    2985              : /* Dump a multiline representation of this store to stderr.  */
    2986              : 
    2987              : DEBUG_FUNCTION void
    2988            0 : store::dump (bool simple) const
    2989              : {
    2990            0 :   tree_dump_pretty_printer pp (stderr);
    2991            0 :   dump_to_pp (&pp, simple, true, nullptr);
    2992            0 :   pp_newline (&pp);
    2993            0 : }
    2994              : 
    2995              : /* Assert that this object is valid.  */
    2996              : 
    2997              : void
    2998      1811959 : store::validate () const
    2999              : {
    3000     15181789 :   for (auto iter : m_cluster_map)
    3001     13369830 :     iter.second->validate ();
    3002      1811959 : }
    3003              : 
    3004              : /* Return a new json::object of the form
    3005              :    {PARENT_REGION_DESC: {BASE_REGION_DESC: object for binding_map,
    3006              :                          ... for each cluster within parent region},
    3007              :     ...for each parent region,
    3008              :     "called_unknown_fn": true/false}.  */
    3009              : 
    3010              : std::unique_ptr<json::object>
    3011            4 : store::to_json () const
    3012              : {
    3013            4 :   auto store_obj = std::make_unique<json::object> ();
    3014              : 
    3015              :   /* Sort into some deterministic order.  */
    3016            4 :   auto_vec<const region *> base_regions;
    3017            4 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    3018            4 :        iter != m_cluster_map.end (); ++iter)
    3019              :     {
    3020            0 :       const region *base_reg = (*iter).first;
    3021            0 :       base_regions.safe_push (base_reg);
    3022              :     }
    3023            4 :   base_regions.qsort (region::cmp_ptr_ptr);
    3024              : 
    3025              :   /* Gather clusters, organize by parent region, so that we can group
    3026              :      together locals, globals, etc.  */
    3027            4 :   auto_vec<const region *> parent_regions;
    3028            4 :   get_sorted_parent_regions (&parent_regions, base_regions);
    3029              : 
    3030            4 :   const region *parent_reg;
    3031            4 :   unsigned i;
    3032            4 :   FOR_EACH_VEC_ELT (parent_regions, i, parent_reg)
    3033              :     {
    3034            0 :       gcc_assert (parent_reg);
    3035              : 
    3036            0 :       auto clusters_in_parent_reg_obj = std::make_unique<json::object> ();
    3037              : 
    3038            0 :       const region *base_reg;
    3039            0 :       unsigned j;
    3040            0 :       FOR_EACH_VEC_ELT (base_regions, j, base_reg)
    3041              :         {
    3042              :           /* This is O(N * M), but N ought to be small.  */
    3043            0 :           if (base_reg->get_parent_region () != parent_reg)
    3044            0 :             continue;
    3045            0 :           binding_cluster *cluster
    3046            0 :             = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg);
    3047            0 :           label_text base_reg_desc = base_reg->get_desc ();
    3048            0 :           clusters_in_parent_reg_obj->set (base_reg_desc.get (),
    3049            0 :                                            cluster->to_json ());
    3050            0 :         }
    3051            0 :       label_text parent_reg_desc = parent_reg->get_desc ();
    3052            0 :       store_obj->set (parent_reg_desc.get (),
    3053              :                       std::move (clusters_in_parent_reg_obj));
    3054            0 :     }
    3055              : 
    3056            4 :   store_obj->set_bool ("called_unknown_fn", m_called_unknown_fn);
    3057              : 
    3058            4 :   return store_obj;
    3059            4 : }
    3060              : 
    3061              : std::unique_ptr<text_art::tree_widget>
    3062            4 : store::make_dump_widget (const text_art::dump_widget_info &dwi,
    3063              :                          store_manager *mgr) const
    3064              : {
    3065            4 :   std::unique_ptr<text_art::tree_widget> store_widget
    3066            4 :     (text_art::tree_widget::make (dwi, "Store"));
    3067              : 
    3068            4 :   store_widget->add_child
    3069            8 :     (text_art::tree_widget::from_fmt (dwi, nullptr,
    3070              :                                       "m_called_unknown_fn: %s",
    3071            4 :                                       m_called_unknown_fn ? "true" : "false"));
    3072              : 
    3073              :     /* Sort into some deterministic order.  */
    3074            4 :   auto_vec<const region *> base_regions;
    3075            4 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    3076            4 :        iter != m_cluster_map.end (); ++iter)
    3077              :     {
    3078            0 :       const region *base_reg = (*iter).first;
    3079            0 :       base_regions.safe_push (base_reg);
    3080              :     }
    3081            4 :   base_regions.qsort (region::cmp_ptr_ptr);
    3082              : 
    3083              :   /* Gather clusters, organize by parent region, so that we can group
    3084              :      together locals, globals, etc.  */
    3085            4 :   auto_vec<const region *> parent_regions;
    3086            4 :   get_sorted_parent_regions (&parent_regions, base_regions);
    3087              : 
    3088            4 :   const region *parent_reg;
    3089            4 :   unsigned i;
    3090            4 :   FOR_EACH_VEC_ELT (parent_regions, i, parent_reg)
    3091              :     {
    3092            0 :       gcc_assert (parent_reg);
    3093              : 
    3094            0 :       pretty_printer the_pp;
    3095            0 :       pretty_printer * const pp = &the_pp;
    3096            0 :       pp_format_decoder (pp) = default_tree_printer;
    3097            0 :       pp_show_color (pp) = true;
    3098            0 :       const bool simple = true;
    3099              : 
    3100            0 :       parent_reg->dump_to_pp (pp, simple);
    3101              : 
    3102            0 :       std::unique_ptr<text_art::tree_widget> parent_reg_widget
    3103            0 :         (text_art::tree_widget::make (dwi, pp));
    3104              : 
    3105            0 :       const region *base_reg;
    3106            0 :       unsigned j;
    3107            0 :       FOR_EACH_VEC_ELT (base_regions, j, base_reg)
    3108              :         {
    3109              :           /* This is O(N * M), but N ought to be small.  */
    3110            0 :           if (base_reg->get_parent_region () != parent_reg)
    3111            0 :             continue;
    3112            0 :           binding_cluster *cluster
    3113            0 :             = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg);
    3114            0 :           parent_reg_widget->add_child
    3115            0 :             (cluster->make_dump_widget (dwi, mgr));
    3116              :         }
    3117            0 :       store_widget->add_child (std::move (parent_reg_widget));
    3118            0 :     }
    3119              : 
    3120            4 :   return store_widget;
    3121            4 : }
    3122              : 
    3123              : /* Get any svalue bound to REG, or nullptr.  */
    3124              : 
    3125              : const svalue *
    3126      4261268 : store::get_any_binding (store_manager *mgr, const region *reg) const
    3127              : {
    3128      4261268 :   const region *base_reg = reg->get_base_region ();
    3129      4261268 :   binding_cluster **cluster_slot
    3130      4261268 :     = const_cast <cluster_map_t &> (m_cluster_map).get (base_reg);
    3131      4261268 :   if (!cluster_slot)
    3132              :     return nullptr;
    3133      1303485 :   return (*cluster_slot)->get_any_binding (mgr, reg);
    3134              : }
    3135              : 
    3136              : /* Set the value of LHS_REG to RHS_SVAL.
    3137              :    Use MODEL when determining if regions alias each other.  */
    3138              : 
    3139              : void
    3140       392754 : store::set_value (store_manager *mgr, const region *lhs_reg,
    3141              :                   const svalue *rhs_sval,
    3142              :                   uncertainty_t *uncertainty,
    3143              :                   const region_model &model)
    3144              : {
    3145       392754 :   logger *logger = mgr->get_logger ();
    3146       392754 :   LOG_SCOPE (logger);
    3147              : 
    3148       392754 :   remove_overlapping_bindings (mgr, lhs_reg, uncertainty);
    3149              : 
    3150       392754 :   if (lhs_reg->get_type ())
    3151       379735 :     rhs_sval = simplify_for_binding (rhs_sval);
    3152              :   /* ...but if we have no type for the region, retain any cast.  */
    3153              : 
    3154       392754 :   const region *lhs_base_reg = lhs_reg->get_base_region ();
    3155       392754 :   binding_cluster *lhs_cluster;
    3156       392754 :   if (lhs_base_reg->symbolic_for_unknown_ptr_p ())
    3157              :     {
    3158              :       /* Reject attempting to bind values into a symbolic region
    3159              :          for an unknown ptr; merely invalidate values below.  */
    3160         2573 :       lhs_cluster = nullptr;
    3161              : 
    3162              :       /* The LHS of the write is *UNKNOWN.  If the RHS is a pointer,
    3163              :          then treat the region being pointed to as having escaped.  */
    3164         2573 :       if (const region_svalue *ptr_sval = rhs_sval->dyn_cast_region_svalue ())
    3165              :         {
    3166           83 :           const region *ptr_dst = ptr_sval->get_pointee ();
    3167           83 :           const region *ptr_base_reg = ptr_dst->get_base_region ();
    3168           83 :           mark_as_escaped (*mgr, ptr_base_reg);
    3169              :         }
    3170         2573 :       if (uncertainty)
    3171         1151 :         uncertainty->on_maybe_bound_sval (rhs_sval);
    3172              :     }
    3173       390181 :   else if (lhs_base_reg->tracked_p ())
    3174              :     {
    3175       390103 :       lhs_cluster = get_or_create_cluster (*mgr, lhs_base_reg);
    3176       390103 :       lhs_cluster->bind (mgr, lhs_reg, rhs_sval);
    3177              :     }
    3178              :   else
    3179              :     {
    3180              :       /* Reject attempting to bind values into an untracked region;
    3181              :          merely invalidate values below.  */
    3182              :       lhs_cluster = nullptr;
    3183              :     }
    3184              : 
    3185              :   /* Bindings to a cluster can affect other clusters if a symbolic
    3186              :      base region is involved.
    3187              :      Writes to concrete clusters can't affect other concrete clusters,
    3188              :      but can affect symbolic clusters.
    3189              :      Writes to symbolic clusters can affect both concrete and symbolic
    3190              :      clusters.
    3191              :      Invalidate our knowledge of other clusters that might have been
    3192              :      affected by the write.
    3193              :      Gather the set of all svalues that might still be live even if
    3194              :      the store doesn't refer to them.  */
    3195       392754 :   svalue_set maybe_live_values;
    3196      5559898 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    3197     10727042 :        iter != m_cluster_map.end (); ++iter)
    3198              :     {
    3199      5167144 :       const region *iter_base_reg = (*iter).first;
    3200      5167144 :       binding_cluster *iter_cluster = (*iter).second;
    3201      5167144 :       if (iter_base_reg != lhs_base_reg
    3202      5167144 :           && (lhs_cluster == nullptr
    3203      4737959 :               || lhs_cluster->symbolic_p ()
    3204      4679967 :               || iter_cluster->symbolic_p ()))
    3205              :         {
    3206       690049 :           tristate t_alias = eval_alias (lhs_base_reg, iter_base_reg,
    3207              :                                          model);
    3208       690049 :           switch (t_alias.get_value ())
    3209              :             {
    3210            0 :             default:
    3211            0 :               gcc_unreachable ();
    3212              : 
    3213        47219 :             case tristate::TS_UNKNOWN:
    3214        47219 :               if (logger)
    3215              :                 {
    3216            0 :                   pretty_printer *pp = logger->get_printer ();
    3217            0 :                   logger->start_log_line ();
    3218            0 :                   logger->log_partial ("possible aliasing of ");
    3219            0 :                   iter_base_reg->dump_to_pp (pp, true);
    3220            0 :                   logger->log_partial (" when writing SVAL: ");
    3221            0 :                   rhs_sval->dump_to_pp (pp, true);
    3222            0 :                   logger->log_partial (" to LHS_REG: ");
    3223            0 :                   lhs_reg->dump_to_pp (pp, true);
    3224            0 :                   logger->end_log_line ();
    3225              :                 }
    3226              :               /* Mark all of iter_cluster's iter_base_reg as unknown,
    3227              :                  using LHS_REG when considering overlaps, to handle
    3228              :                  symbolic vs concrete issues.  */
    3229        47219 :               iter_cluster->mark_region_as_unknown
    3230        47219 :                 (mgr,
    3231              :                  iter_base_reg, /* reg_to_bind */
    3232              :                  lhs_reg, /* reg_for_overlap */
    3233              :                  uncertainty,
    3234              :                  &maybe_live_values);
    3235        47219 :               break;
    3236              : 
    3237            0 :             case tristate::TS_TRUE:
    3238            0 :               gcc_unreachable ();
    3239              :               break;
    3240              : 
    3241              :             case tristate::TS_FALSE:
    3242              :               /* If they can't be aliases, then don't invalidate this
    3243              :                  cluster.  */
    3244              :               break;
    3245              :             }
    3246              :         }
    3247              :     }
    3248              :   /* Given the set of svalues that might still be live, process them
    3249              :      (e.g. marking regions as escaped).
    3250              :      We do this after the iteration to avoid potentially changing
    3251              :      m_cluster_map whilst iterating over it.  */
    3252       392754 :   on_maybe_live_values (*mgr, maybe_live_values);
    3253       392754 : }
    3254              : 
    3255              : /* Determine if BASE_REG_A could be an alias of BASE_REG_B.
    3256              :    Use information from MODEL when comparing pointers. */
    3257              : 
    3258              : tristate
    3259       691158 : store::eval_alias (const region *base_reg_a,
    3260              :                    const region *base_reg_b,
    3261              :                    const region_model &model) const
    3262              : {
    3263       691158 :   if (base_reg_a == base_reg_b)
    3264          383 :     return tristate (true);
    3265              : 
    3266              :   /* SSA names can't alias.  */
    3267       690775 :   tree decl_a = base_reg_a->maybe_get_decl ();
    3268       690775 :   if (decl_a && TREE_CODE (decl_a) == SSA_NAME)
    3269       497266 :     return tristate::TS_FALSE;
    3270       193509 :   tree decl_b = base_reg_b->maybe_get_decl ();
    3271       193509 :   if (decl_b && TREE_CODE (decl_b) == SSA_NAME)
    3272        43570 :     return tristate::TS_FALSE;
    3273              : 
    3274              :   /* Different decls don't alias.  */
    3275       149939 :   if (decl_a && decl_b && decl_a != decl_b)
    3276          221 :     return tristate::TS_FALSE;
    3277              : 
    3278              :   /* Try both ways, for symmetry.  */
    3279       149718 :   tristate ts_ab = eval_alias_1 (base_reg_a, base_reg_b, model);
    3280       149718 :   if (ts_ab.is_false ())
    3281        18790 :     return tristate::TS_FALSE;
    3282       130928 :   tristate ts_ba = eval_alias_1 (base_reg_b, base_reg_a, model);
    3283       130928 :   if (ts_ba.is_false ())
    3284        83296 :     return tristate::TS_FALSE;
    3285              : 
    3286        47632 :   gcc_assert (base_reg_a != base_reg_b);
    3287        47632 :   enum region_kind kind_a = base_reg_a->get_kind ();
    3288        47632 :   enum region_kind kind_b = base_reg_b->get_kind ();
    3289        47632 :   if (kind_a == kind_b)
    3290              :     {
    3291              :       /* We have two different base region instances of the same kind.
    3292              :          For many kinds of region this implies they must have different
    3293              :          addresses.  */
    3294        16937 :       switch (kind_a)
    3295              :         {
    3296              :         /* Invalid cases.  */
    3297              : 
    3298            0 :         default:
    3299            0 :           gcc_unreachable ();
    3300              : 
    3301            0 :         case RK_CODE:
    3302            0 :         case RK_ERRNO:
    3303            0 :         case RK_GLOBALS:
    3304            0 :         case RK_HEAP:
    3305            0 :         case RK_ROOT:
    3306            0 :         case RK_STACK:
    3307            0 :         case RK_THREAD_LOCAL:
    3308              :           /* We expect these to be singletons.  */
    3309            0 :           gcc_unreachable ();
    3310              : 
    3311            0 :         case RK_BIT_RANGE:
    3312            0 :         case RK_CAST:
    3313            0 :         case RK_ELEMENT:
    3314            0 :         case RK_FIELD:
    3315            0 :         case RK_OFFSET:
    3316            0 :         case RK_SIZED:
    3317              :           /* These aren't base regions.  */
    3318            0 :           gcc_unreachable ();
    3319              : 
    3320              :         /* Valid cases.  */
    3321              : 
    3322           43 :         case RK_ALLOCA:
    3323           43 :         case RK_DECL:
    3324           43 :         case RK_FRAME:
    3325           43 :         case RK_FUNCTION:
    3326           43 :         case RK_LABEL:
    3327           43 :         case RK_PRIVATE:
    3328           43 :         case RK_VAR_ARG:
    3329              :           /* We expect different regions of these kinds to have
    3330              :              different addresses.  */
    3331           43 :           return tristate (false);
    3332              : 
    3333          293 :         case RK_HEAP_ALLOCATED:
    3334              :           /* We have results of two different heap allocations.
    3335              :              If they were non-zero-sized allocations they are different from
    3336              :              each other, but zero-sized allocations might alias.
    3337              :              Note that this doesn't handle the case where of a freed pointer
    3338              :              possibly being reused, but we don't have a way to distinguish
    3339              :              this case from the "two different allocations case", and it seems
    3340              :              much more important to keep the latter from aliasing each
    3341              :              other (for precision when tracking writes).   */
    3342          293 :           {
    3343          293 :             tristate size_a_gt_zero (tristate::unknown ());
    3344          293 :             tristate size_b_gt_zero (tristate::unknown ());
    3345          293 :             const svalue *zero_size
    3346          293 :               = model.get_manager ()->get_or_create_int_cst (size_type_node, 0);
    3347              : 
    3348          293 :             if (auto sval_size_a = model.get_dynamic_extents (base_reg_a))
    3349              :               {
    3350          271 :                 size_a_gt_zero = model.eval_condition (sval_size_a,
    3351              :                                                        GT_EXPR,
    3352              :                                                        zero_size);
    3353              :               }
    3354          293 :             if (auto sval_size_b = model.get_dynamic_extents (base_reg_b))
    3355              :               {
    3356          232 :                 size_b_gt_zero = model.eval_condition (sval_size_b,
    3357              :                                                        GT_EXPR,
    3358              :                                                        zero_size);
    3359              :               }
    3360          293 :             if (size_a_gt_zero.is_known () && size_b_gt_zero.is_known ())
    3361              :               {
    3362              :                 /* We have results of two different heap allocations, and for
    3363              :                    each we know if the size was non-zero.  */
    3364          161 :                 if (size_a_gt_zero.is_false () && size_b_gt_zero.is_false ())
    3365              :                   {
    3366              :                     /* Different allocations, both zero-sized.  We don't
    3367              :                        know if they have the same address.  */
    3368            0 :                     return tristate::unknown ();
    3369              :                   }
    3370              :                 else
    3371              :                   {
    3372              :                     /* We either have different allocations of non-zero size,
    3373              :                        or different allocations where one has non-zero size, the
    3374              :                        other is zero-sized.  We know these have different
    3375              :                        addresses.  */
    3376          161 :                     return tristate (false);
    3377              :                   }
    3378              :               }
    3379          132 :             if (size_a_gt_zero.is_true () || size_b_gt_zero.is_true ())
    3380              :               {
    3381              :                 /* Different allocations, of which at least one > 0 in size.
    3382              :                    They must have different addresses.  */
    3383           74 :                 return tristate (false);
    3384              :               }
    3385              :             /* At least one size might be zero.  */
    3386           58 :             return tristate::unknown ();
    3387              :           }
    3388              : 
    3389        16593 :         case RK_SYMBOLIC:
    3390        16593 :         case RK_UNKNOWN:
    3391              :           /* We don't know that such regions are different from each other.  */
    3392        16593 :           return tristate::unknown ();
    3393              : 
    3394            8 :         case RK_STRING:
    3395              :           /* For now, don't attempt to decide if string literals alias
    3396              :              each other.  */
    3397            8 :           return tristate::unknown ();
    3398              :         }
    3399              :     }
    3400              :   else
    3401              :     {
    3402              :       /* We have two base region instances of different kinds.
    3403              :          For many kinds of region this implies they must have different
    3404              :          addresses.  */
    3405        30695 :       if (kind_b == RK_SYMBOLIC || kind_b == RK_UNKNOWN)
    3406        12599 :         return tristate::unknown ();
    3407              : 
    3408        18096 :       switch (kind_a)
    3409              :         {
    3410              :         /* Invalid cases.  */
    3411              : 
    3412            0 :         default:
    3413            0 :           gcc_unreachable ();
    3414              : 
    3415            0 :         case RK_CODE:
    3416            0 :         case RK_ERRNO:
    3417            0 :         case RK_GLOBALS:
    3418            0 :         case RK_HEAP:
    3419            0 :         case RK_ROOT:
    3420            0 :         case RK_STACK:
    3421            0 :         case RK_THREAD_LOCAL:
    3422              :           /* We expect these to be singletons.  */
    3423            0 :           gcc_unreachable ();
    3424              : 
    3425            0 :         case RK_BIT_RANGE:
    3426            0 :         case RK_CAST:
    3427            0 :         case RK_ELEMENT:
    3428            0 :         case RK_FIELD:
    3429            0 :         case RK_OFFSET:
    3430            0 :         case RK_SIZED:
    3431              :           /* These aren't base regions.  */
    3432            0 :           gcc_unreachable ();
    3433              : 
    3434              :         /* Valid cases.  */
    3435              : 
    3436            5 :         case RK_ALLOCA:
    3437            5 :         case RK_DECL:
    3438            5 :         case RK_FRAME:
    3439            5 :         case RK_FUNCTION:
    3440            5 :         case RK_HEAP_ALLOCATED:
    3441            5 :         case RK_LABEL:
    3442            5 :         case RK_PRIVATE:
    3443            5 :         case RK_STRING:
    3444            5 :         case RK_VAR_ARG:
    3445              :           /* We expect regions of these kinds to have different addresses
    3446              :              from regions of other kinds (apart from symbolic/unknown).  */
    3447            5 :           return tristate (false);
    3448              : 
    3449        18091 :         case RK_SYMBOLIC:
    3450        18091 :         case RK_UNKNOWN:
    3451              :           /* We don't know anything about such regions.  */
    3452        18091 :           return tristate::unknown ();
    3453              :         }
    3454              :     }
    3455              : }
    3456              : 
    3457              : /* Half of store::eval_alias; called twice for symmetry.  */
    3458              : 
    3459              : tristate
    3460       280646 : store::eval_alias_1 (const region *base_reg_a,
    3461              :                      const region *base_reg_b,
    3462              :                      const region_model &model) const
    3463              : {
    3464       280646 :   gcc_assert (base_reg_a != base_reg_b);
    3465              : 
    3466              :   /* If they're in different memory spaces, they can't alias.  */
    3467       280646 :   {
    3468       280646 :     enum memory_space memspace_a = base_reg_a->get_memory_space ();
    3469       280646 :     if (memspace_a != MEMSPACE_UNKNOWN)
    3470              :       {
    3471       109651 :         enum memory_space memspace_b = base_reg_b->get_memory_space ();
    3472       109651 :         if (memspace_b != MEMSPACE_UNKNOWN
    3473       109651 :             && memspace_a != memspace_b)
    3474          118 :           return tristate::TS_FALSE;
    3475              :       }
    3476              :   }
    3477              : 
    3478       561056 :   if (const symbolic_region *sym_reg_a
    3479       280528 :       = base_reg_a->dyn_cast_symbolic_region ())
    3480              :     {
    3481       165853 :       const svalue *sval_a = sym_reg_a->get_pointer ();
    3482       165853 :       if (tree decl_b = base_reg_b->maybe_get_decl ())
    3483              :         {
    3484       105979 :           if (!may_be_aliased (decl_b))
    3485        41035 :             return tristate::TS_FALSE;
    3486        64944 :           if (sval_a->get_kind () == SK_INITIAL)
    3487        55388 :             if (!is_global_var (decl_b))
    3488              :               {
    3489              :                 /* The initial value of a pointer can't point to a local.  */
    3490        49377 :                 return tristate::TS_FALSE;
    3491              :               }
    3492              :         }
    3493        75441 :       if (sval_a->get_kind () == SK_INITIAL
    3494        75441 :           && base_reg_b->get_kind () == RK_HEAP_ALLOCATED)
    3495              :         {
    3496              :           /* The initial value of a pointer can't point to a
    3497              :              region that was allocated on the heap after the beginning of the
    3498              :              path.  */
    3499        11474 :           return tristate::TS_FALSE;
    3500              :         }
    3501       127934 :       if (const widening_svalue *widening_sval_a
    3502        63967 :           = sval_a->dyn_cast_widening_svalue ())
    3503              :         {
    3504         2256 :           const svalue *base = widening_sval_a->get_base_svalue ();
    3505         4512 :           if (const region_svalue *region_sval
    3506         2256 :                 = base->dyn_cast_region_svalue ())
    3507              :             {
    3508          199 :               const region *pointee = region_sval->get_pointee ();
    3509              :               /* If we have sval_a is WIDENING(&REGION, OP), and
    3510              :                  B can't alias REGION, then B can't alias A either.
    3511              :                  For example, A might arise from
    3512              :                    for (ptr = &REGION; ...; ptr++)
    3513              :                  where sval_a is ptr in the 2nd iteration of the loop.
    3514              :                  We want to ensure that "*ptr" can only clobber things
    3515              :                  within REGION's base region.  */
    3516          199 :               tristate ts = eval_alias (pointee->get_base_region (),
    3517              :                                         base_reg_b,
    3518              :                                         model);
    3519          199 :               if (ts.is_false ())
    3520           82 :                 return tristate::TS_FALSE;
    3521              :             }
    3522              :         }
    3523              :     }
    3524              : 
    3525       178560 :   return tristate::TS_UNKNOWN;
    3526              : }
    3527              : 
    3528              : /* Record all of the values in MAYBE_LIVE_VALUES as being possibly live.  */
    3529              : 
    3530              : void
    3531       393063 : store::on_maybe_live_values (store_manager &mgr,
    3532              :                              const svalue_set &maybe_live_values)
    3533              : {
    3534       460973 :   for (auto sval : maybe_live_values)
    3535              :     {
    3536        33955 :       if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ())
    3537              :         {
    3538          173 :           const region *base_reg = ptr_sval->get_pointee ()->get_base_region ();
    3539          173 :           mark_as_escaped (mgr, base_reg);
    3540              :         }
    3541              :     }
    3542       393063 : }
    3543              : 
    3544              : /* Remove all bindings overlapping REG within this store.  */
    3545              : 
    3546              : void
    3547         7240 : store::clobber_region (store_manager *mgr, const region *reg)
    3548              : {
    3549         7240 :   const region *base_reg = reg->get_base_region ();
    3550         7240 :   binding_cluster **slot = m_cluster_map.get (base_reg);
    3551         7240 :   if (!slot)
    3552         2265 :     return;
    3553         4975 :   binding_cluster *cluster = *slot;
    3554         4975 :   cluster->clobber_region (mgr, reg);
    3555         4975 :   if (cluster->redundant_p ())
    3556              :     {
    3557         3438 :       delete cluster;
    3558         3438 :       m_cluster_map.remove (base_reg);
    3559              :     }
    3560              : }
    3561              : 
    3562              : /* Remove any bindings for REG within this store.  */
    3563              : 
    3564              : void
    3565       225319 : store::purge_region (store_manager *mgr, const region *reg)
    3566              : {
    3567       225319 :   const region *base_reg = reg->get_base_region ();
    3568       225319 :   binding_cluster **slot = m_cluster_map.get (base_reg);
    3569       225319 :   if (!slot)
    3570            0 :     return;
    3571       225319 :   binding_cluster *cluster = *slot;
    3572       225319 :   cluster->purge_region (mgr, reg);
    3573       225319 :   if (cluster->redundant_p ())
    3574              :     {
    3575       221267 :       delete cluster;
    3576       221267 :       m_cluster_map.remove (base_reg);
    3577              :     }
    3578              : }
    3579              : 
    3580              : /* Fill REG with SVAL.  */
    3581              : 
    3582              : void
    3583         1603 : store::fill_region (store_manager *mgr, const region *reg, const svalue *sval)
    3584              : {
    3585              :   /* Filling an empty region is a no-op.  */
    3586         1603 :   if (reg->empty_p ())
    3587              :     return;
    3588              : 
    3589         1571 :   const region *base_reg = reg->get_base_region ();
    3590         1571 :   if (base_reg->symbolic_for_unknown_ptr_p ()
    3591         1571 :       || !base_reg->tracked_p ())
    3592            6 :     return;
    3593         1565 :   binding_cluster *cluster = get_or_create_cluster (*mgr, base_reg);
    3594         1565 :   cluster->fill_region (mgr, reg, sval);
    3595              : }
    3596              : 
    3597              : /* Zero-fill REG.  */
    3598              : 
    3599              : void
    3600          861 : store::zero_fill_region (store_manager *mgr, const region *reg)
    3601              : {
    3602          861 :   region_model_manager *sval_mgr = mgr->get_svalue_manager ();
    3603          861 :   const svalue *zero_sval = sval_mgr->get_or_create_int_cst (char_type_node, 0);
    3604          861 :   fill_region (mgr, reg, zero_sval);
    3605          861 : }
    3606              : 
    3607              : /* Mark REG as having unknown content.  */
    3608              : 
    3609              : void
    3610          309 : store::mark_region_as_unknown (store_manager *mgr, const region *reg,
    3611              :                                uncertainty_t *uncertainty,
    3612              :                                svalue_set *maybe_live_values)
    3613              : {
    3614          309 :   const region *base_reg = reg->get_base_region ();
    3615          309 :   if (base_reg->symbolic_for_unknown_ptr_p ()
    3616          309 :       || !base_reg->tracked_p ())
    3617            0 :     return;
    3618          309 :   binding_cluster *cluster = get_or_create_cluster (*mgr, base_reg);
    3619          309 :   cluster->mark_region_as_unknown (mgr, reg, reg, uncertainty,
    3620              :                                    maybe_live_values);
    3621              : }
    3622              : 
    3623              : /* Purge state involving SVAL.  */
    3624              : 
    3625              : void
    3626        30249 : store::purge_state_involving (const svalue *sval,
    3627              :                               region_model_manager *sval_mgr)
    3628              : {
    3629        30249 :   auto_vec <const region *> base_regs_to_purge;
    3630       841561 :   for (auto iter : m_cluster_map)
    3631              :     {
    3632       405656 :       const region *base_reg = iter.first;
    3633       405656 :       if (base_reg->involves_p (sval))
    3634          121 :         base_regs_to_purge.safe_push (base_reg);
    3635              :       else
    3636              :         {
    3637       405535 :           binding_cluster *cluster = iter.second;
    3638       405535 :           cluster->purge_state_involving (sval, sval_mgr);
    3639              :         }
    3640              :     }
    3641              : 
    3642        30612 :   for (auto iter : base_regs_to_purge)
    3643          121 :     purge_cluster (iter);
    3644        30249 : }
    3645              : 
    3646              : /* Get the cluster for BASE_REG, or nullptr (const version).  */
    3647              : 
    3648              : const binding_cluster *
    3649      2812912 : store::get_cluster (const region *base_reg) const
    3650              : {
    3651      2812912 :   gcc_assert (base_reg);
    3652      2812912 :   gcc_assert (base_reg->get_base_region () == base_reg);
    3653      5625824 :   if (binding_cluster **slot
    3654      2812912 :         = const_cast <cluster_map_t &> (m_cluster_map).get (base_reg))
    3655      2758281 :     return *slot;
    3656              :   else
    3657              :     return nullptr;
    3658              : }
    3659              : 
    3660              : /* Get the cluster for BASE_REG, or nullptr (non-const version).  */
    3661              : 
    3662              : binding_cluster *
    3663     10815205 : store::get_cluster (const region *base_reg)
    3664              : {
    3665     10815205 :   gcc_assert (base_reg);
    3666     10815205 :   gcc_assert (base_reg->get_base_region () == base_reg);
    3667     10815205 :   if (binding_cluster **slot = m_cluster_map.get (base_reg))
    3668      8960588 :     return *slot;
    3669              :   else
    3670              :     return nullptr;
    3671              : }
    3672              : 
    3673              : /* Get the cluster for BASE_REG, creating it if doesn't already exist.  */
    3674              : 
    3675              : binding_cluster *
    3676      1694689 : store::get_or_create_cluster (store_manager &store_mgr,
    3677              :                               const region *base_reg)
    3678              : {
    3679      1694689 :   gcc_assert (base_reg);
    3680      1694689 :   gcc_assert (base_reg->get_base_region () == base_reg);
    3681              : 
    3682              :   /* We shouldn't create clusters for dereferencing an UNKNOWN ptr.  */
    3683      1694689 :   gcc_assert (!base_reg->symbolic_for_unknown_ptr_p ());
    3684              : 
    3685              :   /* We shouldn't create clusters for base regions that aren't trackable.  */
    3686      1694689 :   gcc_assert (base_reg->tracked_p ());
    3687              : 
    3688      1694689 :   if (binding_cluster **slot = m_cluster_map.get (base_reg))
    3689        52273 :     return *slot;
    3690              : 
    3691      1642416 :   binding_cluster *cluster = new binding_cluster (store_mgr, base_reg);
    3692      1642416 :   m_cluster_map.put (base_reg, cluster);
    3693              : 
    3694      1642416 :   return cluster;
    3695              : }
    3696              : 
    3697              : /* Remove any cluster for BASE_REG, for use by
    3698              :    region_model::unbind_region_and_descendents
    3699              :    when popping stack frames and handling deleted heap regions.  */
    3700              : 
    3701              : void
    3702        41342 : store::purge_cluster (const region *base_reg)
    3703              : {
    3704        41342 :   gcc_assert (base_reg->get_base_region () == base_reg);
    3705        41342 :   binding_cluster **slot = m_cluster_map.get (base_reg);
    3706        41342 :   if (!slot)
    3707              :     return;
    3708        41342 :   binding_cluster *cluster = *slot;
    3709        82684 :   delete cluster;
    3710        41342 :   m_cluster_map.remove (base_reg);
    3711              : }
    3712              : 
    3713              : /* Attempt to merge STORE_A and STORE_B into OUT_STORE.
    3714              :    Return true if successful, or false if the stores can't be merged.  */
    3715              : 
    3716              : bool
    3717       149560 : store::can_merge_p (const store *store_a, const store *store_b,
    3718              :                     store *out_store, store_manager *mgr,
    3719              :                     model_merger *merger)
    3720              : {
    3721       149560 :   if (store_a->m_called_unknown_fn || store_b->m_called_unknown_fn)
    3722        46142 :     out_store->m_called_unknown_fn = true;
    3723              : 
    3724              :   /* Get the union of all base regions for STORE_A and STORE_B.  */
    3725       149560 :   hash_set<const region *> base_regions;
    3726      1952915 :   for (cluster_map_t::iterator iter_a = store_a->m_cluster_map.begin ();
    3727      3756270 :        iter_a != store_a->m_cluster_map.end (); ++iter_a)
    3728              :     {
    3729      1803355 :       const region *base_reg_a = (*iter_a).first;
    3730      1803355 :       base_regions.add (base_reg_a);
    3731              :     }
    3732      1930365 :   for (cluster_map_t::iterator iter_b = store_b->m_cluster_map.begin ();
    3733      3711170 :        iter_b != store_b->m_cluster_map.end (); ++iter_b)
    3734              :     {
    3735      1780805 :       const region *base_reg_b = (*iter_b).first;
    3736      1780805 :       base_regions.add (base_reg_b);
    3737              :     }
    3738              : 
    3739              :   /* Sort the base regions before considering them.  This ought not to
    3740              :      affect the results, but can affect which types UNKNOWN_REGIONs are
    3741              :      created for in a run; sorting them thus avoids minor differences
    3742              :      in logfiles.  */
    3743       149560 :   auto_vec<const region *> vec_base_regions (base_regions.elements ());
    3744       149560 :   for (hash_set<const region *>::iterator iter = base_regions.begin ();
    3745      3795376 :        iter != base_regions.end (); ++iter)
    3746      1822908 :     vec_base_regions.quick_push (*iter);
    3747       149560 :   vec_base_regions.qsort (region::cmp_ptr_ptr);
    3748              :   unsigned i;
    3749              :   const region *base_reg;
    3750      1455466 :   FOR_EACH_VEC_ELT (vec_base_regions, i, base_reg)
    3751              :     {
    3752      1264244 :       const binding_cluster *cluster_a = store_a->get_cluster (base_reg);
    3753      1264244 :       const binding_cluster *cluster_b = store_b->get_cluster (base_reg);
    3754              :       /* At least one of cluster_a and cluster_b must be non-NULL.  */
    3755      1264244 :       binding_cluster *out_cluster
    3756      1264244 :         = out_store->get_or_create_cluster (*mgr, base_reg);
    3757      1264244 :       if (!binding_cluster::can_merge_p (cluster_a, cluster_b,
    3758              :                                          out_cluster, out_store, mgr, merger))
    3759              :         return false;
    3760              :     }
    3761              :   return true;
    3762       149560 : }
    3763              : 
    3764              : /* Mark the cluster for BASE_REG as having escaped.
    3765              :    For use when handling an unrecognized function call, and
    3766              :    for params to "top-level" calls.
    3767              :    Further unknown function calls could touch it, even if the cluster
    3768              :    isn't reachable from args of those calls.  */
    3769              : 
    3770              : void
    3771        37504 : store::mark_as_escaped (store_manager &mgr, const region *base_reg)
    3772              : {
    3773        37504 :   gcc_assert (base_reg);
    3774        37504 :   gcc_assert (base_reg->get_base_region () == base_reg);
    3775              : 
    3776        37504 :   if (base_reg->symbolic_for_unknown_ptr_p ()
    3777        37504 :       || !base_reg->tracked_p ())
    3778         5003 :     return;
    3779              : 
    3780        32501 :   binding_cluster *cluster = get_or_create_cluster (mgr, base_reg);
    3781        32501 :   cluster->mark_as_escaped ();
    3782              : }
    3783              : 
    3784              : /* Handle an unknown fncall by updating any clusters that have escaped
    3785              :    (either in this fncall, or in a prior one).  */
    3786              : 
    3787              : void
    3788        18151 : store::on_unknown_fncall (const gcall &call, store_manager *mgr,
    3789              :                           const conjured_purge &p)
    3790              : {
    3791        18151 :   m_called_unknown_fn = true;
    3792              : 
    3793       142234 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    3794       266317 :        iter != m_cluster_map.end (); ++iter)
    3795       124083 :     (*iter).second->on_unknown_fncall (call, mgr, p);
    3796        18151 : }
    3797              : 
    3798              : /* Return true if a non-const pointer to BASE_REG (or something within it)
    3799              :    has escaped to code outside of the TU being analyzed.  */
    3800              : 
    3801              : bool
    3802      9034886 : store::escaped_p (const region *base_reg) const
    3803              : {
    3804      9034886 :   gcc_assert (base_reg);
    3805      9034886 :   gcc_assert (base_reg->get_base_region () == base_reg);
    3806              : 
    3807              :   /* "errno" can always be modified by external code.  */
    3808      9034886 :   if (base_reg->get_kind () == RK_ERRNO)
    3809              :     return true;
    3810              : 
    3811     17921604 :   if (binding_cluster **cluster_slot
    3812      8960802 :       = const_cast <cluster_map_t &>(m_cluster_map).get (base_reg))
    3813      8960802 :     return (*cluster_slot)->escaped_p ();
    3814              :   return false;
    3815              : }
    3816              : 
    3817              : /* Populate OUT_PVS with a list of path_vars for describing SVAL based on
    3818              :    this store, using VISITED to ensure the traversal terminates.  */
    3819              : 
    3820              : void
    3821        12811 : store::get_representative_path_vars (const region_model *model,
    3822              :                                      svalue_set *visited,
    3823              :                                      const svalue *sval,
    3824              :                                      logger *logger,
    3825              :                                      auto_vec<path_var> *out_pvs) const
    3826              : {
    3827        12811 :   gcc_assert (sval);
    3828              : 
    3829              :   /* Find all bindings that reference SVAL.  */
    3830        58875 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    3831       104939 :        iter != m_cluster_map.end (); ++iter)
    3832              :     {
    3833        46064 :       const region *base_reg = (*iter).first;
    3834        46064 :       binding_cluster *cluster = (*iter).second;
    3835        46064 :       cluster->get_representative_path_vars (model, visited, base_reg, sval,
    3836              :                                              logger,
    3837              :                                              out_pvs);
    3838              :     }
    3839              : 
    3840        12811 :   if (const initial_svalue *init_sval = sval->dyn_cast_initial_svalue ())
    3841              :     {
    3842         2305 :       const region *reg = init_sval->get_region ();
    3843         2305 :       if (path_var pv = model->get_representative_path_var (reg,
    3844              :                                                             visited,
    3845         2305 :                                                             logger))
    3846         2221 :         out_pvs->safe_push (pv);
    3847              :     }
    3848        12811 : }
    3849              : 
    3850              : /* Remove all bindings overlapping REG within this store, removing
    3851              :    any clusters that become redundant.
    3852              : 
    3853              :    If UNCERTAINTY is non-NULL, use it to record any svalues that
    3854              :    were removed, as being maybe-bound.  */
    3855              : 
    3856              : void
    3857       392754 : store::remove_overlapping_bindings (store_manager *mgr, const region *reg,
    3858              :                                     uncertainty_t *uncertainty)
    3859              : {
    3860       392754 :   const region *base_reg = reg->get_base_region ();
    3861       392754 :   if (binding_cluster **cluster_slot = m_cluster_map.get (base_reg))
    3862              :     {
    3863        74504 :       binding_cluster *cluster = *cluster_slot;
    3864        74504 :       if (reg == base_reg && !escaped_p (base_reg))
    3865              :         {
    3866              :           /* Remove whole cluster.  */
    3867        46070 :           m_cluster_map.remove (base_reg);
    3868        92140 :           delete cluster;
    3869        46070 :           return;
    3870              :         }
    3871              :       /* Pass nullptr for the maybe_live_values here, as we don't want to
    3872              :          record the old svalues as being maybe-bound.  */
    3873        28434 :       cluster->remove_overlapping_bindings (mgr, reg, uncertainty, nullptr);
    3874              :     }
    3875              : }
    3876              : 
    3877              : /* Subclass of visitor that accumulates a hash_set of the regions that
    3878              :    were visited.  */
    3879              : 
    3880      1739956 : struct region_finder : public visitor
    3881              : {
    3882     47637618 :   void visit_region (const region *reg) final override
    3883              :   {
    3884     47637618 :     m_regs.add (reg);
    3885     47637618 :   }
    3886              : 
    3887              :   hash_set<const region *> m_regs;
    3888              : };
    3889              : 
    3890              : /* Canonicalize this store, to maximize the chance of equality between
    3891              :    instances.  */
    3892              : 
    3893              : void
    3894       869978 : store::canonicalize (store_manager *mgr)
    3895              : {
    3896              :   /* If we have e.g.:
    3897              :          cluster for: HEAP_ALLOCATED_REGION(543)
    3898              :            ESCAPED
    3899              :            TOUCHED
    3900              :      where the heap region is empty and unreferenced, then purge that
    3901              :      cluster, to avoid unbounded state chains involving these.  */
    3902              : 
    3903              :   /* Find regions that are referenced by bound values in the store.  */
    3904       869978 :   region_finder s;
    3905      7102938 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    3906     13335898 :        iter != m_cluster_map.end (); ++iter)
    3907              :     {
    3908      6232960 :       binding_cluster *cluster = (*iter).second;
    3909      6232960 :       for (binding_cluster::iterator_t bind_iter = cluster->m_map.begin ();
    3910     13626446 :            bind_iter != cluster->m_map.end (); ++bind_iter)
    3911      7393486 :         (*bind_iter).m_sval->accept (&s);
    3912              :     }
    3913              : 
    3914              :   /* Locate heap-allocated regions that have empty bindings that weren't
    3915              :      found above.  */
    3916       869978 :   hash_set<const region *> purgeable_regions;
    3917      7102938 :   for (cluster_map_t::iterator iter = m_cluster_map.begin ();
    3918     13335898 :        iter != m_cluster_map.end (); ++iter)
    3919              :     {
    3920      6232960 :       const region *base_reg = (*iter).first;
    3921      6232960 :       binding_cluster *cluster = (*iter).second;
    3922      6232960 :       if (base_reg->get_kind () == RK_HEAP_ALLOCATED)
    3923              :         {
    3924              :           /* Don't purge a heap-allocated region that's been marked as
    3925              :              escaping, since this could be recording that a ptr to it
    3926              :              was written to an unknown symbolic region along this
    3927              :              path, and so we don't know whether it's referenced or
    3928              :              not, and hence should report it as leaking
    3929              :              (PR analyzer/106473).  */
    3930       298600 :           if (cluster->escaped_p ())
    3931       113989 :             continue;
    3932              : 
    3933       184611 :           if (cluster->empty_p ())
    3934          450 :             if (!s.m_regs.contains (base_reg))
    3935            0 :               purgeable_regions.add (base_reg);
    3936              : 
    3937              :           /* Also cover the UNKNOWN case.  */
    3938       184611 :           if (const svalue *sval = cluster->maybe_get_simple_value (mgr))
    3939        55326 :             if (sval->get_kind () == SK_UNKNOWN)
    3940        28783 :               if (!s.m_regs.contains (base_reg))
    3941          122 :                 purgeable_regions.add (base_reg);
    3942              :         }
    3943              :     }
    3944              : 
    3945              :   /* Purge them.  */
    3946       870100 :   for (hash_set<const region *>::iterator iter = purgeable_regions.begin ();
    3947      1740200 :        iter != purgeable_regions.end (); ++iter)
    3948              :     {
    3949          122 :       const region *base_reg = *iter;
    3950          122 :       purge_cluster (base_reg);
    3951              :     }
    3952       869978 : }
    3953              : 
    3954              : static bool
    3955        90696 : needs_loop_replay_fixup_p (const svalue &sval)
    3956              : {
    3957        90696 :   struct my_visitor : public visitor
    3958              :   {
    3959        90696 :     my_visitor () : m_found_widening (false) {}
    3960              : 
    3961              :     void
    3962          400 :     visit_widening_svalue (const widening_svalue *) final override
    3963              :     {
    3964          400 :       m_found_widening = true;
    3965          400 :     }
    3966              : 
    3967              :     bool m_found_widening;
    3968        90696 :   } v;
    3969              : 
    3970        90696 :   sval.accept (&v);
    3971        90696 :   return v.m_found_widening;
    3972              : }
    3973              : 
    3974              : /* Subroutine for use by exploded_path::feasible_p.
    3975              : 
    3976              :    We need to deal with state differences between:
    3977              :    (a) when the exploded_graph is being initially constructed and
    3978              :    (b) when replaying the state changes along a specific path in
    3979              :    in exploded_path::feasible_p.
    3980              : 
    3981              :    In (a), state merging happens, so when exploring a loop
    3982              :      for (i = 0; i < 1024; i++)
    3983              :    on successive iterations we have i == 0, then i == WIDENING.
    3984              : 
    3985              :    In (b), no state merging happens, so naively replaying the path
    3986              :    that goes twice through the loop then exits it
    3987              :    would lead to i == 0, then i == 1, and then a (i >= 1024) eedge
    3988              :    that exits the loop, which would be found to be infeasible as i == 1,
    3989              :    and the path would be rejected.
    3990              : 
    3991              :    We need to fix up state during replay.  This subroutine is
    3992              :    called whenever we enter a supernode that we've already
    3993              :    visited along this exploded_path, passing in OTHER_STORE
    3994              :    from the destination enode's state.
    3995              : 
    3996              :    Find bindings to widening values in OTHER_STORE.
    3997              :    For all that are found, update the binding in this store to UNKNOWN.  */
    3998              : 
    3999              : void
    4000         4656 : store::loop_replay_fixup (const store *other_store,
    4001              :                           region_model_manager *mgr)
    4002              : {
    4003         4656 :   gcc_assert (other_store);
    4004        34806 :   for (cluster_map_t::iterator iter = other_store->m_cluster_map.begin ();
    4005        64956 :        iter != other_store->m_cluster_map.end (); ++iter)
    4006              :     {
    4007        30150 :       const region *base_reg = (*iter).first;
    4008        30150 :       binding_cluster *cluster = (*iter).second;
    4009       120846 :       for (binding_cluster::iterator_t bind_iter = cluster->m_map.begin ();
    4010       120846 :            bind_iter != cluster->m_map.end (); ++bind_iter)
    4011              :         {
    4012        90696 :           const binding_key *key = (*bind_iter).m_key;
    4013        90696 :           const svalue *sval = (*bind_iter).m_sval;
    4014        90696 :           if (needs_loop_replay_fixup_p (*sval))
    4015              :             {
    4016          400 :               binding_cluster *this_cluster
    4017          400 :                 = get_or_create_cluster (*mgr->get_store_manager (),
    4018              :                                          base_reg);
    4019          400 :               const svalue *unknown
    4020          400 :                 = mgr->get_or_create_unknown_svalue (sval->get_type ());
    4021          400 :               this_cluster->bind_key (key, unknown);
    4022              :             }
    4023              :         }
    4024              :     }
    4025         4656 : }
    4026              : 
    4027              : /* Use R to replay the bindings from SUMMARY into this object.  */
    4028              : 
    4029              : void
    4030         1662 : store::replay_call_summary (call_summary_replay &r,
    4031              :                             const store &summary)
    4032              : {
    4033         1662 :   if (summary.m_called_unknown_fn)
    4034              :     {
    4035              :       /* A call to an external function occurred in the summary.
    4036              :          Hence we need to invalidate our knownledge of globals,
    4037              :          escaped regions, etc.  */
    4038           40 :       on_unknown_fncall (r.get_call_stmt (),
    4039              :                          r.get_store_manager (),
    4040           40 :                          conjured_purge (r.get_caller_model (),
    4041           40 :                                          r.get_ctxt ()));
    4042              :     }
    4043              : 
    4044         1662 :   auto_vec<const region *> keys (summary.m_cluster_map.elements ());
    4045        14135 :   for (auto kv : summary.m_cluster_map)
    4046        12473 :     keys.quick_push (kv.first);
    4047         1662 :   keys.qsort (region::cmp_ptr_ptr);
    4048        17451 :   for (auto base_reg : keys)
    4049        12473 :     replay_call_summary_cluster (r, summary, base_reg);
    4050         1662 : }
    4051              : 
    4052              : /* Use R and SUMMARY to replay the bindings in SUMMARY_CLUSTER
    4053              :    into this object.  */
    4054              : 
    4055              : void
    4056        12473 : store::replay_call_summary_cluster (call_summary_replay &r,
    4057              :                                     const store &summary,
    4058              :                                     const region *summary_base_reg)
    4059              : {
    4060        12473 :   const call_details &cd = r.get_call_details ();
    4061        12473 :   region_model_manager *reg_mgr = r.get_manager ();
    4062        12473 :   store_manager *mgr = reg_mgr->get_store_manager ();
    4063        12473 :   const binding_cluster *summary_cluster
    4064        12473 :     = summary.get_cluster (summary_base_reg);
    4065              : 
    4066              :   /* Handle "ESCAPED" and "TOUCHED" flags.  */
    4067        12473 :   if (summary_cluster->escaped_p () || summary_cluster->touched_p ())
    4068         7748 :     if (const region *caller_reg
    4069         3874 :         = r.convert_region_from_summary (summary_base_reg))
    4070              :       {
    4071         3871 :         const region *caller_base_reg = caller_reg->get_base_region ();
    4072         3871 :         if (caller_base_reg->tracked_p ()
    4073         3871 :             && !caller_base_reg->symbolic_for_unknown_ptr_p ())
    4074              :           {
    4075         2944 :             binding_cluster *caller_cluster
    4076         2944 :               = get_or_create_cluster (*mgr, caller_base_reg);
    4077         2944 :             if (summary_cluster->escaped_p ())
    4078         2248 :               caller_cluster->mark_as_escaped ();
    4079         2944 :             if (summary_cluster->touched_p ())
    4080         1762 :               caller_cluster->m_touched = true;
    4081              :           }
    4082              :       }
    4083              : 
    4084        12473 :   switch (summary_base_reg->get_kind ())
    4085              :     {
    4086              :     /* Top-level regions.  */
    4087            0 :     case RK_FRAME:
    4088            0 :     case RK_GLOBALS:
    4089            0 :     case RK_CODE:
    4090            0 :     case RK_STACK:
    4091            0 :     case RK_HEAP:
    4092            0 :     case RK_THREAD_LOCAL:
    4093            0 :     case RK_ROOT:
    4094              :     /* Child regions.  */
    4095            0 :     case RK_FIELD:
    4096            0 :     case RK_ELEMENT:
    4097            0 :     case RK_OFFSET:
    4098            0 :     case RK_SIZED:
    4099            0 :     case RK_CAST:
    4100            0 :     case RK_BIT_RANGE:
    4101              :     /* Other regions.  */
    4102            0 :     case RK_VAR_ARG:
    4103            0 :     case RK_UNKNOWN:
    4104              :       /* These should never be the base region of a binding cluster.  */
    4105            0 :       gcc_unreachable ();
    4106              :       break;
    4107              : 
    4108              :     case RK_FUNCTION:
    4109              :     case RK_LABEL:
    4110              :     case RK_STRING:
    4111              :       /* These can be marked as escaping.  */
    4112              :       break;
    4113              : 
    4114         2707 :     case RK_SYMBOLIC:
    4115         2707 :       {
    4116         2707 :         const symbolic_region *summary_symbolic_reg
    4117         2707 :           = as_a <const symbolic_region *> (summary_base_reg);
    4118         2707 :         const svalue *summary_ptr_sval = summary_symbolic_reg->get_pointer ();
    4119         2707 :         const svalue *caller_ptr_sval
    4120         2707 :           = r.convert_svalue_from_summary (summary_ptr_sval);
    4121         2707 :         if (!caller_ptr_sval)
    4122              :           return;
    4123         2293 :         const region *caller_dest_reg
    4124         2293 :           = cd.get_model ()->deref_rvalue (caller_ptr_sval,
    4125              :                                            NULL_TREE,
    4126              :                                            cd.get_ctxt ());
    4127         2293 :         const svalue *summary_sval
    4128         2293 :           = summary.get_any_binding (mgr, summary_base_reg);
    4129         2293 :         if (!summary_sval)
    4130              :           return;
    4131         1979 :         const svalue *caller_sval
    4132         1979 :           = r.convert_svalue_from_summary (summary_sval);
    4133         1979 :         if (!caller_sval)
    4134            2 :           caller_sval =
    4135            2 :             reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
    4136         1979 :         set_value (mgr, caller_dest_reg,
    4137              :                    caller_sval, nullptr /* uncertainty_t * */,
    4138         1979 :                    *cd.get_model ());
    4139              :       }
    4140         1979 :       break;
    4141              : 
    4142         9761 :     case RK_HEAP_ALLOCATED:
    4143         9761 :     case RK_DECL:
    4144         9761 :     case RK_ERRNO:
    4145         9761 :     case RK_PRIVATE:
    4146         9761 :       {
    4147         9761 :         const region *caller_dest_reg
    4148         9761 :           = r.convert_region_from_summary (summary_base_reg);
    4149         9761 :         if (!caller_dest_reg)
    4150              :           return;
    4151         9528 :         const svalue *summary_sval
    4152         9528 :           = summary.get_any_binding (mgr, summary_base_reg);
    4153         9528 :         if (!summary_sval)
    4154          187 :           summary_sval = reg_mgr->get_or_create_compound_svalue
    4155          187 :             (summary_base_reg->get_type (),
    4156          187 :              summary_cluster->get_map ().get_concrete_bindings ());
    4157         9528 :         const svalue *caller_sval
    4158         9528 :           = r.convert_svalue_from_summary (summary_sval);
    4159         9528 :         if (!caller_sval)
    4160            2 :           caller_sval =
    4161            2 :             reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ());
    4162         9528 :         set_value (mgr, caller_dest_reg,
    4163              :                    caller_sval, nullptr /* uncertainty_t * */,
    4164         9528 :                    *cd.get_model ());
    4165              :       }
    4166         9528 :       break;
    4167              : 
    4168              :     case RK_ALLOCA:
    4169              :       /* Ignore bindings of alloca regions in the summary.  */
    4170              :       break;
    4171              :     }
    4172              : }
    4173              : 
    4174              : #if CHECKING_P
    4175              : 
    4176              : namespace selftest {
    4177              : 
    4178              : /* Verify that bit_range::intersects_p works as expected.  */
    4179              : 
    4180              : static void
    4181            4 : test_bit_range_intersects_p ()
    4182              : {
    4183            4 :   bit_range b0 (0, 1);
    4184            4 :   bit_range b1 (1, 1);
    4185            4 :   bit_range b2 (2, 1);
    4186            4 :   bit_range b3 (3, 1);
    4187            4 :   bit_range b4 (4, 1);
    4188            4 :   bit_range b5 (5, 1);
    4189            4 :   bit_range b6 (6, 1);
    4190            4 :   bit_range b7 (7, 1);
    4191            4 :   bit_range b1_to_6 (1, 6);
    4192            4 :   bit_range b0_to_7 (0, 8);
    4193            4 :   bit_range b3_to_5 (3, 3);
    4194            4 :   bit_range b6_to_7 (6, 2);
    4195              : 
    4196              :   /* self-intersection is true.  */
    4197            4 :   ASSERT_TRUE (b0.intersects_p (b0));
    4198            4 :   ASSERT_TRUE (b7.intersects_p (b7));
    4199            4 :   ASSERT_TRUE (b1_to_6.intersects_p (b1_to_6));
    4200            4 :   ASSERT_TRUE (b0_to_7.intersects_p (b0_to_7));
    4201              : 
    4202            4 :   ASSERT_FALSE (b0.intersects_p (b1));
    4203            4 :   ASSERT_FALSE (b1.intersects_p (b0));
    4204            4 :   ASSERT_FALSE (b0.intersects_p (b7));
    4205            4 :   ASSERT_FALSE (b7.intersects_p (b0));
    4206              : 
    4207            4 :   ASSERT_TRUE (b0_to_7.intersects_p (b0));
    4208            4 :   ASSERT_TRUE (b0_to_7.intersects_p (b7));
    4209            4 :   ASSERT_TRUE (b0.intersects_p (b0_to_7));
    4210            4 :   ASSERT_TRUE (b7.intersects_p (b0_to_7));
    4211              : 
    4212            4 :   ASSERT_FALSE (b0.intersects_p (b1_to_6));
    4213            4 :   ASSERT_FALSE (b1_to_6.intersects_p (b0));
    4214            4 :   ASSERT_TRUE (b1.intersects_p (b1_to_6));
    4215            4 :   ASSERT_TRUE (b1_to_6.intersects_p (b1));
    4216            4 :   ASSERT_TRUE (b1_to_6.intersects_p (b6));
    4217            4 :   ASSERT_FALSE (b1_to_6.intersects_p (b7));
    4218              : 
    4219            4 :   ASSERT_TRUE (b1_to_6.intersects_p (b0_to_7));
    4220            4 :   ASSERT_TRUE (b0_to_7.intersects_p (b1_to_6));
    4221              : 
    4222            4 :   ASSERT_FALSE (b3_to_5.intersects_p (b6_to_7));
    4223            4 :   ASSERT_FALSE (b6_to_7.intersects_p (b3_to_5));
    4224              : 
    4225            4 :   bit_range r1 (0,0);
    4226            4 :   bit_range r2 (0,0);
    4227            4 :   ASSERT_TRUE (b1_to_6.intersects_p (b0_to_7, &r1, &r2));
    4228            4 :   ASSERT_EQ (r1.get_start_bit_offset (), 0);
    4229            4 :   ASSERT_EQ (r1.m_size_in_bits, 6);
    4230            4 :   ASSERT_EQ (r2.get_start_bit_offset (), 1);
    4231            4 :   ASSERT_EQ (r2.m_size_in_bits, 6);
    4232              : 
    4233            4 :   ASSERT_TRUE (b0_to_7.intersects_p (b1_to_6, &r1, &r2));
    4234            4 :   ASSERT_EQ (r1.get_start_bit_offset (), 1);
    4235            4 :   ASSERT_EQ (r1.m_size_in_bits, 6);
    4236            4 :   ASSERT_EQ (r2.get_start_bit_offset (), 0);
    4237            4 :   ASSERT_EQ (r2.m_size_in_bits, 6);
    4238            4 : }
    4239              : 
    4240              : /* Implementation detail of ASSERT_BIT_RANGE_FROM_MASK_EQ.  */
    4241              : 
    4242              : static void
    4243           76 : assert_bit_range_from_mask_eq (const location &loc,
    4244              :                                unsigned HOST_WIDE_INT mask,
    4245              :                                const bit_range &expected)
    4246              : {
    4247           76 :   bit_range actual (0, 0);
    4248           76 :   bool ok = bit_range::from_mask (mask, &actual);
    4249           76 :   ASSERT_TRUE_AT (loc, ok);
    4250           76 :   ASSERT_EQ_AT (loc, actual, expected);
    4251           76 : }
    4252              : 
    4253              : /* Assert that bit_range::from_mask (MASK) returns true, and writes
    4254              :    out EXPECTED_BIT_RANGE.  */
    4255              : 
    4256              : #define ASSERT_BIT_RANGE_FROM_MASK_EQ(MASK, EXPECTED_BIT_RANGE) \
    4257              :   SELFTEST_BEGIN_STMT                                                   \
    4258              :   assert_bit_range_from_mask_eq (SELFTEST_LOCATION, MASK,               \
    4259              :                                  EXPECTED_BIT_RANGE);                   \
    4260              :   SELFTEST_END_STMT
    4261              : 
    4262              : /* Implementation detail of ASSERT_NO_BIT_RANGE_FROM_MASK.  */
    4263              : 
    4264              : static void
    4265           12 : assert_no_bit_range_from_mask_eq (const location &loc,
    4266              :                                   unsigned HOST_WIDE_INT mask)
    4267              : {
    4268           12 :   bit_range actual (0, 0);
    4269           12 :   bool ok = bit_range::from_mask (mask, &actual);
    4270           12 :   ASSERT_FALSE_AT (loc, ok);
    4271           12 : }
    4272              : 
    4273              : /* Assert that bit_range::from_mask (MASK) returns false.  */
    4274              : 
    4275              : #define ASSERT_NO_BIT_RANGE_FROM_MASK(MASK) \
    4276              :   SELFTEST_BEGIN_STMT                                                   \
    4277              :   assert_no_bit_range_from_mask_eq (SELFTEST_LOCATION, MASK);           \
    4278              :   SELFTEST_END_STMT
    4279              : 
    4280              : /* Verify that bit_range::from_mask works as expected.  */
    4281              : 
    4282              : static void
    4283            4 : test_bit_range_from_mask ()
    4284              : {
    4285              :   /* Should fail on zero.  */
    4286            4 :   ASSERT_NO_BIT_RANGE_FROM_MASK (0);
    4287              : 
    4288              :   /* Verify 1-bit masks.  */
    4289            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (1, bit_range (0, 1));
    4290            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (2, bit_range (1, 1));
    4291            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (4, bit_range (2, 1));
    4292            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (8, bit_range (3, 1));
    4293            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (16, bit_range (4, 1));
    4294            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (32, bit_range (5, 1));
    4295            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (64, bit_range (6, 1));
    4296            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (128, bit_range (7, 1));
    4297              : 
    4298              :   /* Verify N-bit masks starting at bit 0.  */
    4299            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (3, bit_range (0, 2));
    4300            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (7, bit_range (0, 3));
    4301            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (15, bit_range (0, 4));
    4302            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (31, bit_range (0, 5));
    4303            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (63, bit_range (0, 6));
    4304            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (127, bit_range (0, 7));
    4305            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (255, bit_range (0, 8));
    4306            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (0xffff, bit_range (0, 16));
    4307              : 
    4308              :   /* Various other tests. */
    4309            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (0x30, bit_range (4, 2));
    4310            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (0x700, bit_range (8, 3));
    4311            4 :   ASSERT_BIT_RANGE_FROM_MASK_EQ (0x600, bit_range (9, 2));
    4312              : 
    4313              :   /* Multiple ranges of set bits should fail.  */
    4314            4 :   ASSERT_NO_BIT_RANGE_FROM_MASK (0x101);
    4315            4 :   ASSERT_NO_BIT_RANGE_FROM_MASK (0xf0f0f0f0);
    4316            4 : }
    4317              : 
    4318              : /* Implementation detail of ASSERT_OVERLAP.  */
    4319              : 
    4320              : static void
    4321           56 : assert_overlap (const location &loc,
    4322              :                 const concrete_binding *b1,
    4323              :                 const concrete_binding *b2)
    4324              : {
    4325           56 :   ASSERT_TRUE_AT (loc, b1->overlaps_p (*b2));
    4326           56 :   ASSERT_TRUE_AT (loc, b2->overlaps_p (*b1));
    4327           56 : }
    4328              : 
    4329              : /* Implementation detail of ASSERT_DISJOINT.  */
    4330              : 
    4331              : static void
    4332           20 : assert_disjoint (const location &loc,
    4333              :                  const concrete_binding *b1,
    4334              :                  const concrete_binding *b2)
    4335              : {
    4336           20 :   ASSERT_FALSE_AT (loc, b1->overlaps_p (*b2));
    4337           20 :   ASSERT_FALSE_AT (loc, b2->overlaps_p (*b1));
    4338           20 : }
    4339              : 
    4340              : /* Assert that B1 and B2 overlap, checking both ways.  */
    4341              : 
    4342              : #define ASSERT_OVERLAP(B1, B2) \
    4343              :   SELFTEST_BEGIN_STMT                           \
    4344              :   assert_overlap (SELFTEST_LOCATION, B1, B2);   \
    4345              :   SELFTEST_END_STMT
    4346              : 
    4347              : /* Assert that B1 and B2 do not overlap, checking both ways.  */
    4348              : 
    4349              : #define ASSERT_DISJOINT(B1, B2) \
    4350              :   SELFTEST_BEGIN_STMT                           \
    4351              :   assert_disjoint (SELFTEST_LOCATION, B1, B2);  \
    4352              :   SELFTEST_END_STMT
    4353              : 
    4354              : /* Verify that concrete_binding::overlaps_p works as expected.  */
    4355              : 
    4356              : static void
    4357            4 : test_binding_key_overlap ()
    4358              : {
    4359            4 :   store_manager mgr (nullptr);
    4360              : 
    4361              :   /* Various 8-bit bindings.  */
    4362            4 :   const concrete_binding *cb_0_7 = mgr.get_concrete_binding (0, 8);
    4363            4 :   const concrete_binding *cb_8_15 = mgr.get_concrete_binding (8, 8);
    4364            4 :   const concrete_binding *cb_16_23 = mgr.get_concrete_binding (16, 8);
    4365            4 :   const concrete_binding *cb_24_31 = mgr.get_concrete_binding (24, 8);
    4366              : 
    4367              :   /* 16-bit bindings.  */
    4368            4 :   const concrete_binding *cb_0_15 = mgr.get_concrete_binding (0, 16);
    4369            4 :   const concrete_binding *cb_8_23 = mgr.get_concrete_binding (8, 16);
    4370            4 :   const concrete_binding *cb_16_31 = mgr.get_concrete_binding (16, 16);
    4371              : 
    4372              :   /* 32-bit binding.  */
    4373            4 :   const concrete_binding *cb_0_31 = mgr.get_concrete_binding (0, 32);
    4374              : 
    4375              :   /* Everything should self-overlap.  */
    4376            4 :   ASSERT_OVERLAP (cb_0_7, cb_0_7);
    4377            4 :   ASSERT_OVERLAP (cb_8_15, cb_8_15);
    4378            4 :   ASSERT_OVERLAP (cb_16_23, cb_16_23);
    4379            4 :   ASSERT_OVERLAP (cb_24_31, cb_24_31);
    4380            4 :   ASSERT_OVERLAP (cb_0_15, cb_0_15);
    4381            4 :   ASSERT_OVERLAP (cb_8_23, cb_8_23);
    4382            4 :   ASSERT_OVERLAP (cb_16_31, cb_16_31);
    4383            4 :   ASSERT_OVERLAP (cb_0_31, cb_0_31);
    4384              : 
    4385              :   /* Verify the 8-bit bindings that don't overlap each other.  */
    4386            4 :   ASSERT_DISJOINT (cb_0_7, cb_8_15);
    4387            4 :   ASSERT_DISJOINT (cb_8_15, cb_16_23);
    4388              : 
    4389              :   /* Check for overlap of differently-sized bindings.  */
    4390            4 :   ASSERT_OVERLAP (cb_0_7, cb_0_31);
    4391              :   /* ...and with differing start points.  */
    4392            4 :   ASSERT_OVERLAP (cb_8_15, cb_0_31);
    4393            4 :   ASSERT_DISJOINT (cb_8_15, cb_16_31);
    4394            4 :   ASSERT_OVERLAP (cb_16_23, cb_0_31);
    4395            4 :   ASSERT_OVERLAP (cb_16_31, cb_0_31);
    4396              : 
    4397            4 :   ASSERT_DISJOINT (cb_0_7, cb_8_23);
    4398            4 :   ASSERT_OVERLAP (cb_8_23, cb_16_23);
    4399            4 :   ASSERT_OVERLAP (cb_8_23, cb_16_31);
    4400            4 :   ASSERT_DISJOINT (cb_8_23, cb_24_31);
    4401            4 : }
    4402              : 
    4403              : static void
    4404            4 : test_binding_map_ops ()
    4405              : {
    4406            4 :   region_model_manager region_mgr;
    4407            4 :   store_manager store_mgr (&region_mgr);
    4408              : 
    4409              :   /* Assignment of empty.  */
    4410            4 :   {
    4411            4 :     binding_map src (store_mgr);
    4412            4 :     binding_map dst (store_mgr);
    4413            4 :     dst = src;
    4414              : 
    4415            4 :     ASSERT_EQ (src, dst);
    4416            4 :  }
    4417            4 : }
    4418              : 
    4419              : /* Run all of the selftests within this file.  */
    4420              : 
    4421              : void
    4422            4 : analyzer_store_cc_tests ()
    4423              : {
    4424            4 :   test_bit_range_intersects_p ();
    4425            4 :   test_bit_range_from_mask ();
    4426            4 :   test_binding_key_overlap ();
    4427            4 :   test_binding_map_ops ();
    4428            4 : }
    4429              : 
    4430              : } // namespace selftest
    4431              : 
    4432              : #endif /* CHECKING_P */
    4433              : 
    4434              : } // namespace ana
    4435              : 
    4436              : #endif /* #if ENABLE_ANALYZER */
        

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.