LCOV - code coverage report
Current view: top level - gcc/analyzer - region-model-manager.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.6 % 1020 996
Test Date: 2025-06-28 16:12:38 Functions: 89.9 % 129 116
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Consolidation of svalues and regions.
       2                 :             :    Copyright (C) 2020-2025 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 "fold-const.h"
      24                 :             : #include "ordered-hash-map.h"
      25                 :             : #include "options.h"
      26                 :             : #include "analyzer/supergraph.h"
      27                 :             : #include "sbitmap.h"
      28                 :             : #include "target.h"
      29                 :             : 
      30                 :             : #include "analyzer/analyzer-logging.h"
      31                 :             : #include "analyzer/call-string.h"
      32                 :             : #include "analyzer/program-point.h"
      33                 :             : #include "analyzer/store.h"
      34                 :             : #include "analyzer/region-model.h"
      35                 :             : #include "analyzer/constraint-manager.h"
      36                 :             : 
      37                 :             : #if ENABLE_ANALYZER
      38                 :             : 
      39                 :             : namespace ana {
      40                 :             : 
      41                 :             : /* class region_model_manager.  */
      42                 :             : 
      43                 :             : /* region_model_manager's ctor.  */
      44                 :             : 
      45                 :        3901 : region_model_manager::region_model_manager (logger *logger)
      46                 :        3901 : : m_logger (logger),
      47                 :        3901 :   m_next_symbol_id (0),
      48                 :        3901 :   m_empty_call_string (),
      49                 :        3901 :   m_root_region (alloc_symbol_id ()),
      50                 :        3901 :   m_stack_region (alloc_symbol_id (), &m_root_region),
      51                 :        3901 :   m_heap_region (alloc_symbol_id (), &m_root_region),
      52                 :        3901 :   m_unknown_NULL (NULL),
      53                 :        3901 :   m_checking_feasibility (false),
      54                 :        3901 :   m_max_complexity (0, 0),
      55                 :        3901 :   m_code_region (alloc_symbol_id (), &m_root_region),
      56                 :        3901 :   m_fndecls_map (), m_labels_map (),
      57                 :        3901 :   m_globals_region (alloc_symbol_id (), &m_root_region),
      58                 :        3901 :   m_globals_map (),
      59                 :        3901 :   m_thread_local_region (alloc_symbol_id (), &m_root_region),
      60                 :        3901 :   m_errno_region (alloc_symbol_id (), &m_thread_local_region),
      61                 :        3901 :   m_store_mgr (this),
      62                 :        3901 :   m_range_mgr (new bounded_ranges_manager ()),
      63                 :       11703 :   m_known_fn_mgr (logger)
      64                 :             : {
      65                 :        3901 : }
      66                 :             : 
      67                 :             : /* region_model_manager's dtor.  Delete all of the managed svalues
      68                 :             :    and regions.  */
      69                 :             : 
      70                 :        7802 : region_model_manager::~region_model_manager ()
      71                 :             : {
      72                 :             :   /* Delete consolidated svalues.  */
      73                 :       57370 :   for (constants_map_t::iterator iter = m_constants_map.begin ();
      74                 :      110839 :        iter != m_constants_map.end (); ++iter)
      75                 :       53469 :     delete (*iter).second;
      76                 :       12640 :   for (unknowns_map_t::iterator iter = m_unknowns_map.begin ();
      77                 :       21379 :        iter != m_unknowns_map.end (); ++iter)
      78                 :        8739 :     delete (*iter).second;
      79                 :        3901 :   delete m_unknown_NULL;
      80                 :        9102 :   for (poisoned_values_map_t::iterator iter = m_poisoned_values_map.begin ();
      81                 :       14303 :        iter != m_poisoned_values_map.end (); ++iter)
      82                 :        5201 :     delete (*iter).second;
      83                 :        3935 :   for (setjmp_values_map_t::iterator iter = m_setjmp_values_map.begin ();
      84                 :        3969 :        iter != m_setjmp_values_map.end (); ++iter)
      85                 :          34 :     delete (*iter).second;
      86                 :       28556 :   for (initial_values_map_t::iterator iter = m_initial_values_map.begin ();
      87                 :       53211 :        iter != m_initial_values_map.end (); ++iter)
      88                 :       24655 :     delete (*iter).second;
      89                 :       28584 :   for (pointer_values_map_t::iterator iter = m_pointer_values_map.begin ();
      90                 :       53267 :        iter != m_pointer_values_map.end (); ++iter)
      91                 :       24683 :     delete (*iter).second;
      92                 :       12525 :   for (unaryop_values_map_t::iterator iter = m_unaryop_values_map.begin ();
      93                 :       21149 :        iter != m_unaryop_values_map.end (); ++iter)
      94                 :        8624 :     delete (*iter).second;
      95                 :       25169 :   for (binop_values_map_t::iterator iter = m_binop_values_map.begin ();
      96                 :       46437 :        iter != m_binop_values_map.end (); ++iter)
      97                 :       21268 :     delete (*iter).second;
      98                 :        6382 :   for (sub_values_map_t::iterator iter = m_sub_values_map.begin ();
      99                 :        8863 :        iter != m_sub_values_map.end (); ++iter)
     100                 :        2481 :     delete (*iter).second;
     101                 :        4903 :   for (auto iter : m_repeated_values_map)
     102                 :         501 :     delete iter.second;
     103                 :        5247 :   for (auto iter : m_bits_within_values_map)
     104                 :         673 :     delete iter.second;
     105                 :        4103 :   for (unmergeable_values_map_t::iterator iter
     106                 :        3901 :          = m_unmergeable_values_map.begin ();
     107                 :        4305 :        iter != m_unmergeable_values_map.end (); ++iter)
     108                 :         202 :     delete (*iter).second;
     109                 :        6384 :   for (widening_values_map_t::iterator iter = m_widening_values_map.begin ();
     110                 :        8867 :        iter != m_widening_values_map.end (); ++iter)
     111                 :        2483 :     delete (*iter).second;
     112                 :        4558 :   for (compound_values_map_t::iterator iter = m_compound_values_map.begin ();
     113                 :        5215 :        iter != m_compound_values_map.end (); ++iter)
     114                 :         657 :     delete (*iter).second;
     115                 :       32204 :   for (conjured_values_map_t::iterator iter = m_conjured_values_map.begin ();
     116                 :       60507 :        iter != m_conjured_values_map.end (); ++iter)
     117                 :       28303 :     delete (*iter).second;
     118                 :        4275 :   for (auto iter : m_asm_output_values_map)
     119                 :         187 :     delete iter.second;
     120                 :        4411 :   for (auto iter : m_const_fn_result_values_map)
     121                 :         255 :     delete iter.second;
     122                 :             : 
     123                 :             :   /* Delete consolidated regions.  */
     124                 :       13100 :   for (fndecls_map_t::iterator iter = m_fndecls_map.begin ();
     125                 :       22299 :        iter != m_fndecls_map.end (); ++iter)
     126                 :        9199 :     delete (*iter).second;
     127                 :        3947 :   for (labels_map_t::iterator iter = m_labels_map.begin ();
     128                 :        3993 :        iter != m_labels_map.end (); ++iter)
     129                 :          46 :     delete (*iter).second;
     130                 :       10285 :   for (globals_map_t::iterator iter = m_globals_map.begin ();
     131                 :       16669 :        iter != m_globals_map.end (); ++iter)
     132                 :        6384 :     delete (*iter).second;
     133                 :        7657 :   for (string_map_t::iterator iter = m_string_map.begin ();
     134                 :       11413 :        iter != m_string_map.end (); ++iter)
     135                 :        3756 :     delete (*iter).second;
     136                 :             : 
     137                 :        3901 :   delete m_range_mgr;
     138                 :        7802 : }
     139                 :             : 
     140                 :             : /* Return true if C exceeds the complexity limit for svalues.  */
     141                 :             : 
     142                 :             : bool
     143                 :      166046 : region_model_manager::too_complex_p (const complexity &c) const
     144                 :             : {
     145                 :      166046 :   if (c.m_max_depth > (unsigned)param_analyzer_max_svalue_depth)
     146                 :        1969 :     return true;
     147                 :             :   return false;
     148                 :             : }
     149                 :             : 
     150                 :             : /* If SVAL exceeds the complexity limit for svalues, delete it
     151                 :             :    and return true.
     152                 :             :    Otherwise update m_max_complexity and return false.  */
     153                 :             : 
     154                 :             : bool
     155                 :      175645 : region_model_manager::reject_if_too_complex (svalue *sval)
     156                 :             : {
     157                 :      175645 :   if (m_checking_feasibility)
     158                 :             :     return false;
     159                 :             : 
     160                 :      166046 :   const complexity &c = sval->get_complexity ();
     161                 :      166046 :   if (!too_complex_p (c))
     162                 :             :     {
     163                 :      164077 :       if (m_max_complexity.m_num_nodes < c.m_num_nodes)
     164                 :       11450 :         m_max_complexity.m_num_nodes = c.m_num_nodes;
     165                 :      164077 :       if (m_max_complexity.m_max_depth < c.m_max_depth)
     166                 :       10493 :         m_max_complexity.m_max_depth = c.m_max_depth;
     167                 :      164077 :       return false;
     168                 :             :     }
     169                 :             : 
     170                 :        1969 :   pretty_printer pp;
     171                 :        1969 :   pp_format_decoder (&pp) = default_tree_printer;
     172                 :        1969 :   sval->dump_to_pp (&pp, true);
     173                 :        1969 :   if (warning_at (input_location, OPT_Wanalyzer_symbol_too_complex,
     174                 :             :                   "symbol too complicated: %qs",
     175                 :             :                   pp_formatted_text (&pp)))
     176                 :           2 :     inform (input_location,
     177                 :             :             "max_depth %i exceeds --param=analyzer-max-svalue-depth=%i",
     178                 :           2 :             c.m_max_depth, param_analyzer_max_svalue_depth);
     179                 :             : 
     180                 :        1969 :   delete sval;
     181                 :        1969 :   return true;
     182                 :        1969 : }
     183                 :             : 
     184                 :             : /* Macro for imposing a complexity limit on svalues, for use within
     185                 :             :    region_model_manager member functions.
     186                 :             : 
     187                 :             :    If SVAL exceeds the complexity limit, delete it and return an UNKNOWN
     188                 :             :    value of the same type.
     189                 :             :    Otherwise update m_max_complexity and carry on.  */
     190                 :             : 
     191                 :             : #define RETURN_UNKNOWN_IF_TOO_COMPLEX(SVAL)                     \
     192                 :             :   do {                                                          \
     193                 :             :     svalue *sval_ = (SVAL);                                     \
     194                 :             :     tree type_ = sval_->get_type ();                         \
     195                 :             :     if (reject_if_too_complex (sval_))                          \
     196                 :             :       return get_or_create_unknown_svalue (type_);              \
     197                 :             :   } while (0)
     198                 :             : 
     199                 :             : /* svalue consolidation.  */
     200                 :             : 
     201                 :             : /* Return the svalue * for a constant_svalue for CST_EXPR,
     202                 :             :    creating it if necessary.
     203                 :             :    The constant_svalue instances are reused, based on pointer equality
     204                 :             :    of trees  */
     205                 :             : 
     206                 :             : const svalue *
     207                 :     2178252 : region_model_manager::get_or_create_constant_svalue (tree type, tree cst_expr)
     208                 :             : {
     209                 :     2178252 :   gcc_assert (cst_expr);
     210                 :     2178252 :   gcc_assert (CONSTANT_CLASS_P (cst_expr));
     211                 :     2178252 :   gcc_assert (type == TREE_TYPE (cst_expr) || type == NULL_TREE);
     212                 :             : 
     213                 :     2178252 :   constant_svalue::key_t key (type, cst_expr);
     214                 :     2178252 :   constant_svalue **slot = m_constants_map.get (key);
     215                 :     2178252 :   if (slot)
     216                 :     2124101 :     return *slot;
     217                 :       54151 :   constant_svalue *cst_sval
     218                 :       54151 :     = new constant_svalue (alloc_symbol_id (), type, cst_expr);
     219                 :       54151 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (cst_sval);
     220                 :       53469 :   m_constants_map.put (key, cst_sval);
     221                 :       53469 :   return cst_sval;
     222                 :             : }
     223                 :             : 
     224                 :             : const svalue *
     225                 :     1415855 : region_model_manager::get_or_create_constant_svalue (tree cst_expr)
     226                 :             : {
     227                 :     1415855 :   tree type = TREE_TYPE (cst_expr);
     228                 :     1415855 :   if (TREE_CODE (cst_expr) == RAW_DATA_CST)
     229                 :             :     /* The type of a RAW_DATA_CST is the type of each element, rather than
     230                 :             :        that of the constant as a whole, so use NULL_TREE for simplicity.  */
     231                 :          14 :     type = NULL_TREE;
     232                 :     1415855 :   return get_or_create_constant_svalue (type, cst_expr);
     233                 :             : }
     234                 :             : 
     235                 :             : /* Return the svalue * for a constant_svalue for the INTEGER_CST
     236                 :             :    for VAL of type TYPE, creating it if necessary.  */
     237                 :             : 
     238                 :             : const svalue *
     239                 :      721880 : region_model_manager::get_or_create_int_cst (tree type,
     240                 :             :                                              const poly_wide_int_ref &cst)
     241                 :             : {
     242                 :      721880 :   tree effective_type = type;
     243                 :      721880 :   if (!type)
     244                 :        6463 :     effective_type = ptrdiff_type_node;
     245                 :      721880 :   gcc_assert (INTEGRAL_TYPE_P (effective_type)
     246                 :             :               || POINTER_TYPE_P (effective_type));
     247                 :      721880 :   tree tree_cst = wide_int_to_tree (effective_type, cst);
     248                 :      721880 :   return get_or_create_constant_svalue (type, tree_cst);
     249                 :             : }
     250                 :             : 
     251                 :             : /* Return the svalue * for the constant_svalue for the NULL pointer
     252                 :             :    of POINTER_TYPE, creating it if necessary.  */
     253                 :             : 
     254                 :             : const svalue *
     255                 :        1267 : region_model_manager::get_or_create_null_ptr (tree pointer_type)
     256                 :             : {
     257                 :        1267 :   gcc_assert (pointer_type);
     258                 :        1267 :   gcc_assert (POINTER_TYPE_P (pointer_type));
     259                 :        1267 :   return get_or_create_int_cst (pointer_type, 0);
     260                 :             : }
     261                 :             : 
     262                 :             : /* Return the svalue * for a unknown_svalue for TYPE (which can be NULL),
     263                 :             :    creating it if necessary.
     264                 :             :    The unknown_svalue instances are reused, based on pointer equality
     265                 :             :    of the types  */
     266                 :             : 
     267                 :             : const svalue *
     268                 :      743331 : region_model_manager::get_or_create_unknown_svalue (tree type)
     269                 :             : {
     270                 :             :   /* Don't create unknown values when doing feasibility testing;
     271                 :             :      instead, create a unique svalue.  */
     272                 :      743331 :   if (m_checking_feasibility)
     273                 :       14437 :     return create_unique_svalue (type);
     274                 :             : 
     275                 :             :   /* Special-case NULL, so that the hash_map can use NULL as the
     276                 :             :      "empty" value.  */
     277                 :      728894 :   if (type == NULL_TREE)
     278                 :             :     {
     279                 :      145626 :       if (!m_unknown_NULL)
     280                 :        1696 :         m_unknown_NULL = new unknown_svalue (alloc_symbol_id (), type);
     281                 :      145626 :       return m_unknown_NULL;
     282                 :             :     }
     283                 :             : 
     284                 :      583268 :   unknown_svalue **slot = m_unknowns_map.get (type);
     285                 :      583268 :   if (slot)
     286                 :      574529 :     return *slot;
     287                 :        8739 :   unknown_svalue *sval = new unknown_svalue (alloc_symbol_id (), type);
     288                 :        8739 :   m_unknowns_map.put (type, sval);
     289                 :        8739 :   return sval;
     290                 :             : }
     291                 :             : 
     292                 :             : /* Return a freshly-allocated svalue of TYPE, owned by this manager.  */
     293                 :             : 
     294                 :             : const svalue *
     295                 :       14437 : region_model_manager::create_unique_svalue (tree type)
     296                 :             : {
     297                 :       14437 :   svalue *sval = new placeholder_svalue (alloc_symbol_id (), type, "unique");
     298                 :       14437 :   m_managed_dynamic_svalues.safe_push (sval);
     299                 :       14437 :   return sval;
     300                 :             : }
     301                 :             : 
     302                 :             : /* Return the svalue * for the initial value of REG, creating it if
     303                 :             :    necessary.  */
     304                 :             : 
     305                 :             : const svalue *
     306                 :     2787348 : region_model_manager::get_or_create_initial_value (const region *reg,
     307                 :             :                                                    bool check_poisoned)
     308                 :             : {
     309                 :     2787348 :   if (!reg->can_have_initial_svalue_p () && check_poisoned)
     310                 :      225038 :     return get_or_create_poisoned_svalue (poison_kind::uninit,
     311                 :      225038 :                                           reg->get_type ());
     312                 :             : 
     313                 :             :   /* The initial value of a cast is a cast of the initial value.  */
     314                 :     2562310 :   if (const cast_region *cast_reg = reg->dyn_cast_cast_region ())
     315                 :             :     {
     316                 :        2626 :       const region *original_reg = cast_reg->get_parent_region ();
     317                 :        2626 :       return get_or_create_cast (cast_reg->get_type (),
     318                 :        2626 :                                  get_or_create_initial_value (original_reg));
     319                 :             :     }
     320                 :             : 
     321                 :             :   /* Simplify:
     322                 :             :        INIT_VAL(ELEMENT_REG(STRING_REG), CONSTANT_SVAL)
     323                 :             :      to:
     324                 :             :        CONSTANT_SVAL(STRING[N]).  */
     325                 :     2559684 :   if (const element_region *element_reg = reg->dyn_cast_element_region ())
     326                 :       12770 :     if (tree cst_idx = element_reg->get_index ()->maybe_get_constant ())
     327                 :       15376 :       if (const string_region *string_reg
     328                 :        7688 :           = element_reg->get_parent_region ()->dyn_cast_string_region ())
     329                 :         834 :         if (tree_fits_shwi_p (cst_idx))
     330                 :             :           {
     331                 :         834 :             HOST_WIDE_INT idx = tree_to_shwi (cst_idx);
     332                 :         834 :             tree string_cst = string_reg->get_string_cst ();
     333                 :        1668 :             if (idx >= 0 && idx <= TREE_STRING_LENGTH (string_cst))
     334                 :             :               {
     335                 :         834 :                 int ch = TREE_STRING_POINTER (string_cst)[idx];
     336                 :         834 :                 return get_or_create_int_cst (reg->get_type (), ch);
     337                 :             :               }
     338                 :             :           }
     339                 :             : 
     340                 :             :   /* INIT_VAL (*UNKNOWN_PTR) -> UNKNOWN_VAL.  */
     341                 :     2558850 :   if (reg->symbolic_for_unknown_ptr_p ())
     342                 :        8384 :     return get_or_create_unknown_svalue (reg->get_type ());
     343                 :             : 
     344                 :     2550466 :   if (initial_svalue **slot = m_initial_values_map.get (reg))
     345                 :     2525266 :     return *slot;
     346                 :       25200 :   initial_svalue *initial_sval
     347                 :       25200 :     = new initial_svalue (alloc_symbol_id (), reg->get_type (), reg);
     348                 :       25200 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (initial_sval);
     349                 :       24655 :   m_initial_values_map.put (reg, initial_sval);
     350                 :       24655 :   return initial_sval;
     351                 :             : }
     352                 :             : 
     353                 :             : /* Return the svalue * for R using type TYPE, creating it if
     354                 :             :    necessary.  */
     355                 :             : 
     356                 :             : const svalue *
     357                 :          34 : region_model_manager::get_or_create_setjmp_svalue (const setjmp_record &r,
     358                 :             :                                                    tree type)
     359                 :             : {
     360                 :          34 :   setjmp_svalue::key_t key (r, type);
     361                 :          34 :   if (setjmp_svalue **slot = m_setjmp_values_map.get (key))
     362                 :           0 :     return *slot;
     363                 :          34 :   setjmp_svalue *setjmp_sval = new setjmp_svalue (r, alloc_symbol_id (), type);
     364                 :          34 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (setjmp_sval);
     365                 :          34 :   m_setjmp_values_map.put (key, setjmp_sval);
     366                 :          34 :   return setjmp_sval;
     367                 :             : }
     368                 :             : 
     369                 :             : /* Return the svalue * for a poisoned value of KIND and TYPE, creating it if
     370                 :             :    necessary.  */
     371                 :             : 
     372                 :             : const svalue *
     373                 :      233739 : region_model_manager::get_or_create_poisoned_svalue (enum poison_kind kind,
     374                 :             :                                                      tree type)
     375                 :             : {
     376                 :      233739 :   poisoned_svalue::key_t key (kind, type);
     377                 :      233739 :   if (poisoned_svalue **slot = m_poisoned_values_map.get (key))
     378                 :      228538 :     return *slot;
     379                 :        5201 :   poisoned_svalue *poisoned_sval
     380                 :        5201 :     = new poisoned_svalue (kind, alloc_symbol_id (), type);
     381                 :        5201 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (poisoned_sval);
     382                 :        5201 :   m_poisoned_values_map.put (key, poisoned_sval);
     383                 :        5201 :   return poisoned_sval;
     384                 :             : }
     385                 :             : 
     386                 :             : /* Return the svalue * for a pointer to POINTEE of type PTR_TYPE,
     387                 :             :    creating it if necessary.  */
     388                 :             : 
     389                 :             : const svalue *
     390                 :      967799 : region_model_manager::get_ptr_svalue (tree ptr_type, const region *pointee)
     391                 :             : {
     392                 :             :   /* If this is a symbolic region from dereferencing a pointer, and the types
     393                 :             :      match, then return the original pointer.  */
     394                 :      967799 :   if (const symbolic_region *sym_reg = pointee->dyn_cast_symbolic_region ())
     395                 :         179 :     if (ptr_type == sym_reg->get_pointer ()->get_type ())
     396                 :             :       return sym_reg->get_pointer ();
     397                 :             : 
     398                 :      967620 :   region_svalue::key_t key (ptr_type, pointee);
     399                 :      967620 :   if (region_svalue **slot = m_pointer_values_map.get (key))
     400                 :      942478 :     return *slot;
     401                 :       25142 :   region_svalue *sval
     402                 :       25142 :     = new region_svalue (alloc_symbol_id (), ptr_type, pointee);
     403                 :       25142 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (sval);
     404                 :       24683 :   m_pointer_values_map.put (key, sval);
     405                 :       24683 :   return sval;
     406                 :             : }
     407                 :             : 
     408                 :             : /* Subroutine of region_model_manager::get_or_create_unaryop.
     409                 :             :    Attempt to fold the inputs and return a simpler svalue *.
     410                 :             :    Otherwise, return NULL.  */
     411                 :             : 
     412                 :             : const svalue *
     413                 :      261801 : region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op,
     414                 :             :                                           const svalue *arg)
     415                 :             : {
     416                 :             :   /* Ops on "unknown" are also unknown.  */
     417                 :      263996 :   if (arg->get_kind () == SK_UNKNOWN)
     418                 :       47680 :     return get_or_create_unknown_svalue (type);
     419                 :             :   /* Likewise for "poisoned".  */
     420                 :      432632 :   else if (const poisoned_svalue *poisoned_sval
     421                 :      216316 :              = arg->dyn_cast_poisoned_svalue ())
     422                 :        1859 :     return get_or_create_poisoned_svalue (poisoned_sval->get_poison_kind (),
     423                 :        1859 :                                           type);
     424                 :             : 
     425                 :      214457 :   gcc_assert (arg->can_have_associated_state_p ());
     426                 :             : 
     427                 :      214457 :   switch (op)
     428                 :             :     {
     429                 :             :     default: break;
     430                 :      213514 :     case VIEW_CONVERT_EXPR:
     431                 :      213514 :     case NOP_EXPR:
     432                 :      213514 :       {
     433                 :      213514 :         if (!type)
     434                 :             :           return nullptr;
     435                 :             : 
     436                 :             :         /* Handle redundant casts.  */
     437                 :      212552 :         if (arg->get_type ()
     438                 :      212552 :             && useless_type_conversion_p (arg->get_type (), type))
     439                 :             :           return arg;
     440                 :             : 
     441                 :             :         /* Fold "cast<TYPE> (cast <INNER_TYPE> (innermost_arg))
     442                 :             :              => "cast<TYPE> (innermost_arg)",
     443                 :             :            unless INNER_TYPE is narrower than TYPE.  */
     444                 :       78940 :         if (const svalue *innermost_arg = arg->maybe_undo_cast ())
     445                 :             :           {
     446                 :        5546 :             if (tree inner_type = arg->get_type ())
     447                 :        5407 :               if (TYPE_SIZE (type)
     448                 :        5407 :                   && TYPE_SIZE (inner_type)
     449                 :       10814 :                   && (fold_binary (LE_EXPR, boolean_type_node,
     450                 :             :                                    TYPE_SIZE (type), TYPE_SIZE (inner_type))
     451                 :        5407 :                       == boolean_true_node))
     452                 :             :                 return maybe_fold_unaryop (type, op, innermost_arg);
     453                 :             :           }
     454                 :             :         /* Avoid creating symbolic regions for pointer casts by
     455                 :             :            simplifying (T*)(&REGION) to ((T*)&REGION).  */
     456                 :       76745 :         if (const region_svalue *region_sval = arg->dyn_cast_region_svalue ())
     457                 :        4372 :           if (POINTER_TYPE_P (type)
     458                 :         376 :               && region_sval->get_type ()
     459                 :        4544 :               && POINTER_TYPE_P (region_sval->get_type ()))
     460                 :          72 :             return get_ptr_svalue (type, region_sval->get_pointee ());
     461                 :             : 
     462                 :             :         /* Casting all zeroes should give all zeroes.  */
     463                 :       76673 :         if (type
     464                 :       76673 :             && arg->all_zeroes_p ()
     465                 :        5089 :             && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
     466                 :        4415 :           return get_or_create_int_cst (type, 0);
     467                 :             :       }
     468                 :             :       break;
     469                 :           8 :     case TRUTH_NOT_EXPR:
     470                 :           8 :       {
     471                 :             :         /* Invert comparisons e.g. "!(x == y)" => "x != y".  */
     472                 :           8 :         if (const binop_svalue *binop = arg->dyn_cast_binop_svalue ())
     473                 :           8 :           if (TREE_CODE_CLASS (binop->get_op ()) == tcc_comparison)
     474                 :             :             {
     475                 :           8 :               enum tree_code inv_op
     476                 :           8 :                 = invert_tree_comparison (binop->get_op (),
     477                 :           8 :                                           HONOR_NANS (binop->get_type ()));
     478                 :           8 :               if (inv_op != ERROR_MARK)
     479                 :           8 :                 return get_or_create_binop (binop->get_type (), inv_op,
     480                 :             :                                             binop->get_arg0 (),
     481                 :           8 :                                             binop->get_arg1 ());
     482                 :             :             }
     483                 :             :       }
     484                 :             :       break;
     485                 :         190 :     case NEGATE_EXPR:
     486                 :         190 :       {
     487                 :             :         /* -(-(VAL)) is VAL, for integer types.  */
     488                 :         190 :         if (const unaryop_svalue *unaryop = arg->dyn_cast_unaryop_svalue ())
     489                 :          13 :           if (unaryop->get_op () == NEGATE_EXPR
     490                 :           1 :               && type == unaryop->get_type ()
     491                 :           1 :               && type
     492                 :          14 :               && INTEGRAL_TYPE_P (type))
     493                 :           1 :             return unaryop->get_arg ();
     494                 :             :       }
     495                 :             :       break;
     496                 :             :     }
     497                 :             : 
     498                 :             :   /* Constants.  */
     499                 :       73192 :   if (tree cst = arg->maybe_get_constant ())
     500                 :       13016 :     if (tree result = fold_unary (op, type, cst))
     501                 :             :       {
     502                 :       12038 :         if (CONSTANT_CLASS_P (result))
     503                 :       12038 :           return get_or_create_constant_svalue (result);
     504                 :             : 
     505                 :             :         /* fold_unary can return casts of constants; try to handle them.  */
     506                 :           0 :         if (op != NOP_EXPR
     507                 :           0 :                  && type
     508                 :           0 :                  && TREE_CODE (result) == NOP_EXPR
     509                 :           0 :                  && CONSTANT_CLASS_P (TREE_OPERAND (result, 0)))
     510                 :             :           {
     511                 :           0 :             const svalue *inner_cst
     512                 :           0 :               = get_or_create_constant_svalue (TREE_OPERAND (result, 0));
     513                 :           0 :             return get_or_create_cast (type,
     514                 :           0 :                                        get_or_create_cast (TREE_TYPE (result),
     515                 :           0 :                                                            inner_cst));
     516                 :             :           }
     517                 :             :       }
     518                 :             : 
     519                 :             :   return NULL;
     520                 :             : }
     521                 :             : 
     522                 :             : /* Return the svalue * for an unary operation OP on ARG with a result of
     523                 :             :    type TYPE, creating it if necessary.  */
     524                 :             : 
     525                 :             : const svalue *
     526                 :      261801 : region_model_manager::get_or_create_unaryop (tree type, enum tree_code op,
     527                 :             :                                              const svalue *arg)
     528                 :             : {
     529                 :      261801 :   if (const svalue *folded = maybe_fold_unaryop  (type, op, arg))
     530                 :             :     return folded;
     531                 :       62116 :   unaryop_svalue::key_t key (type, op, arg);
     532                 :       62116 :   if (unaryop_svalue **slot = m_unaryop_values_map.get (key))
     533                 :       53436 :     return *slot;
     534                 :        8680 :   unaryop_svalue *unaryop_sval
     535                 :        8680 :     = new unaryop_svalue (alloc_symbol_id (), type, op, arg);
     536                 :        8680 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (unaryop_sval);
     537                 :        8624 :   m_unaryop_values_map.put (key, unaryop_sval);
     538                 :        8624 :   return unaryop_sval;
     539                 :             : }
     540                 :             : 
     541                 :             : /* Get a tree code for a cast to DST_TYPE from SRC_TYPE.
     542                 :             :    Use NOP_EXPR if possible (e.g. to help fold_unary convert casts
     543                 :             :    of 0 to (T*) to simple pointer constants), but use FIX_TRUNC_EXPR
     544                 :             :    and VIEW_CONVERT_EXPR for cases that fold_unary would otherwise crash
     545                 :             :    on.  */
     546                 :             : 
     547                 :             : static enum tree_code
     548                 :      212714 : get_code_for_cast (tree dst_type, tree src_type)
     549                 :             : {
     550                 :           0 :   if (!dst_type)
     551                 :             :     return NOP_EXPR;
     552                 :           0 :   if (!src_type)
     553                 :             :     return NOP_EXPR;
     554                 :             : 
     555                 :      207146 :   if (SCALAR_FLOAT_TYPE_P (src_type))
     556                 :             :     {
     557                 :         350 :       if (TREE_CODE (dst_type) == INTEGER_TYPE)
     558                 :             :         return FIX_TRUNC_EXPR;
     559                 :             :       else
     560                 :         346 :         return VIEW_CONVERT_EXPR;
     561                 :             :     }
     562                 :             : 
     563                 :             :   return NOP_EXPR;
     564                 :             : }
     565                 :             : 
     566                 :             : /* Return the svalue * for a cast of ARG to type TYPE, creating it
     567                 :             :    if necessary.  */
     568                 :             : 
     569                 :             : const svalue *
     570                 :     1152083 : region_model_manager::get_or_create_cast (tree type, const svalue *arg)
     571                 :             : {
     572                 :             :   /* No-op if the types are the same.  */
     573                 :     1152083 :   if (type == arg->get_type ())
     574                 :             :     return arg;
     575                 :             : 
     576                 :             :   /* Don't attempt to handle casts involving vector types for now.  */
     577                 :      221731 :   if (type)
     578                 :      212828 :     if (VECTOR_TYPE_P (type)
     579                 :      212828 :         || (arg->get_type ()
     580                 :      207146 :             && VECTOR_TYPE_P (arg->get_type ())))
     581                 :         114 :       return get_or_create_unknown_svalue (type);
     582                 :             : 
     583                 :      212714 :   enum tree_code op = get_code_for_cast (type, arg->get_type ());
     584                 :      221617 :   return get_or_create_unaryop (type, op, arg);
     585                 :             : }
     586                 :             : 
     587                 :             : /* Subroutine of region_model_manager::maybe_fold_binop for handling
     588                 :             :    (TYPE)(COMPOUND_SVAL BIT_AND_EXPR CST) that may have been generated by
     589                 :             :    optimize_bit_field_compare, where CST is from ARG1.
     590                 :             : 
     591                 :             :    Support masking out bits from a compound_svalue for comparing a bitfield
     592                 :             :    against a value, as generated by optimize_bit_field_compare for
     593                 :             :    BITFIELD == VALUE.
     594                 :             : 
     595                 :             :    If COMPOUND_SVAL has a value for the appropriate bits, return it,
     596                 :             :    shifted accordingly.
     597                 :             :    Otherwise return NULL.  */
     598                 :             : 
     599                 :             : const svalue *
     600                 :          58 : region_model_manager::
     601                 :             : maybe_undo_optimize_bit_field_compare (tree type,
     602                 :             :                                        const compound_svalue *compound_sval,
     603                 :             :                                        tree cst,
     604                 :             :                                        const svalue *arg1)
     605                 :             : {
     606                 :          58 :   if (!type)
     607                 :             :     return nullptr;
     608                 :          58 :   if (!INTEGRAL_TYPE_P (type))
     609                 :             :     return NULL;
     610                 :             : 
     611                 :          56 :   const binding_map &map = compound_sval->get_map ();
     612                 :          56 :   unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (cst);
     613                 :             :   /* If "mask" is a contiguous range of set bits, see if the
     614                 :             :      compound_sval has a value for those bits.  */
     615                 :          56 :   bit_range bits (0, 0);
     616                 :          56 :   if (!bit_range::from_mask (mask, &bits))
     617                 :             :     return NULL;
     618                 :             : 
     619                 :          56 :   bit_range bound_bits (bits);
     620                 :          56 :   if (BYTES_BIG_ENDIAN)
     621                 :             :     bound_bits = bit_range (BITS_PER_UNIT - bits.get_next_bit_offset (),
     622                 :             :                             bits.m_size_in_bits);
     623                 :          56 :   const concrete_binding *conc
     624                 :          56 :     = get_store_manager ()->get_concrete_binding (bound_bits);
     625                 :          56 :   const svalue *sval = map.get (conc);
     626                 :          56 :   if (!sval)
     627                 :           0 :     return NULL;
     628                 :             : 
     629                 :             :   /* We have a value;
     630                 :             :      shift it by the correct number of bits.  */
     631                 :          56 :   const svalue *lhs = get_or_create_cast (type, sval);
     632                 :          56 :   HOST_WIDE_INT bit_offset = bits.get_start_bit_offset ().to_shwi ();
     633                 :          56 :   const svalue *shift_sval = get_or_create_int_cst (type, bit_offset);
     634                 :          56 :   const svalue *shifted_sval = get_or_create_binop (type, LSHIFT_EXPR,
     635                 :             :                                                     lhs, shift_sval);
     636                 :             :   /* Reapply the mask (needed for negative
     637                 :             :      signed bitfields).  */
     638                 :          56 :   return get_or_create_binop (type, BIT_AND_EXPR,
     639                 :          56 :                               shifted_sval, arg1);
     640                 :             : }
     641                 :             : 
     642                 :             : /* Subroutine of region_model_manager::get_or_create_binop.
     643                 :             :    Attempt to fold the inputs and return a simpler svalue *.
     644                 :             :    Otherwise, return NULL.  */
     645                 :             : 
     646                 :             : const svalue *
     647                 :      205853 : region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
     648                 :             :                                         const svalue *arg0,
     649                 :             :                                         const svalue *arg1)
     650                 :             : {
     651                 :      205853 :   tree cst0 = arg0->maybe_get_constant ();
     652                 :      205853 :   tree cst1 = arg1->maybe_get_constant ();
     653                 :             :   /* (CST OP CST).  */
     654                 :      205853 :   if (cst0 && cst1)
     655                 :             :     {
     656                 :       62995 :       if (type)
     657                 :             :         {
     658                 :       22478 :           if (tree result = fold_binary (op, type, cst0, cst1))
     659                 :       22416 :             if (CONSTANT_CLASS_P (result))
     660                 :       22414 :               return get_or_create_constant_svalue (result);
     661                 :             :         }
     662                 :             :       else
     663                 :             :         {
     664                 :       40517 :           if (tree result = int_const_binop (op, cst0, cst1, -1))
     665                 :       40517 :             return get_or_create_constant_svalue (NULL_TREE, result);
     666                 :             :         }
     667                 :             :     }
     668                 :             : 
     669                 :       97722 :   if ((type && FLOAT_TYPE_P (type))
     670                 :      142384 :       || (arg0->get_type () && FLOAT_TYPE_P (arg0->get_type ()))
     671                 :      285254 :       || (arg1->get_type () && FLOAT_TYPE_P (arg1->get_type ())))
     672                 :             :     return NULL;
     673                 :             : 
     674                 :      142312 :   switch (op)
     675                 :             :     {
     676                 :             :     default:
     677                 :             :       break;
     678                 :       95104 :     case POINTER_PLUS_EXPR:
     679                 :       95104 :     case PLUS_EXPR:
     680                 :             :       /* (VAL + 0) -> VAL.  */
     681                 :       95104 :       if (cst1 && zerop (cst1))
     682                 :       15216 :         return get_or_create_cast (type, arg0);
     683                 :             :       break;
     684                 :        3569 :     case MINUS_EXPR:
     685                 :             :       /* (VAL - 0) -> VAL.  */
     686                 :        3569 :       if (cst1 && zerop (cst1))
     687                 :          31 :         return get_or_create_cast (type, arg0);
     688                 :             :       /* (0 - VAL) -> -VAL.  */
     689                 :        3538 :       if (cst0 && zerop (cst0))
     690                 :          16 :         return get_or_create_unaryop (type, NEGATE_EXPR, arg1);
     691                 :             :       /* (X + Y) - X -> Y.  */
     692                 :        3522 :       if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
     693                 :         142 :         if (binop->get_op () == PLUS_EXPR)
     694                 :         115 :           if (binop->get_arg0 () == arg1)
     695                 :          15 :             return get_or_create_cast (type, binop->get_arg1 ());
     696                 :             :       break;
     697                 :       27866 :     case MULT_EXPR:
     698                 :             :       /* (VAL * 0).  */
     699                 :       27866 :       if (cst1
     700                 :       27142 :           && zerop (cst1)
     701                 :       27906 :           && (type == NULL_TREE || INTEGRAL_TYPE_P (type)))
     702                 :          32 :         return get_or_create_int_cst (type, 0);
     703                 :             :       /* (VAL * 1) -> VAL.  */
     704                 :       27834 :       if (cst1 && integer_onep (cst1))
     705                 :         386 :         return get_or_create_cast (type, arg0);
     706                 :             :       break;
     707                 :        3246 :     case BIT_AND_EXPR:
     708                 :        3246 :       if (cst1)
     709                 :             :         {
     710                 :        2668 :           if (zerop (cst1)
     711                 :        2668 :               && (type == NULL_TREE || INTEGRAL_TYPE_P (type)))
     712                 :             :             /* "(ARG0 & 0)" -> "0".  */
     713                 :          82 :             return get_or_create_int_cst (type, 0);
     714                 :             : 
     715                 :        5172 :           if (const compound_svalue *compound_sval
     716                 :        2586 :                 = arg0->dyn_cast_compound_svalue ())
     717                 :         116 :             if (const svalue *sval
     718                 :          58 :                 = maybe_undo_optimize_bit_field_compare (type,
     719                 :             :                                                          compound_sval,
     720                 :             :                                                          cst1, arg1))
     721                 :             :               return sval;
     722                 :             :         }
     723                 :        3108 :       if (arg0->get_type () == boolean_type_node
     724                 :        3108 :           && arg1->get_type () == boolean_type_node)
     725                 :             :         {
     726                 :             :           /* If the LHS are both _Bool, then... */
     727                 :             :           /* ..."(1 & x) -> x".  */
     728                 :         442 :           if (cst0 && !zerop (cst0))
     729                 :           0 :             return get_or_create_cast (type, arg1);
     730                 :             :           /* ..."(x & 1) -> x".  */
     731                 :         442 :           if (cst1 && !zerop (cst1))
     732                 :         152 :             return get_or_create_cast (type, arg0);
     733                 :             :           /* ..."(0 & x) -> 0".  */
     734                 :         290 :           if (cst0 && zerop (cst0))
     735                 :           0 :             return get_or_create_int_cst (type, 0);
     736                 :             :           /* ..."(x & 0) -> 0".  */
     737                 :         290 :           if (cst1 && zerop (cst1))
     738                 :           0 :             return get_or_create_int_cst (type, 0);
     739                 :             :         }
     740                 :             :       break;
     741                 :         741 :     case BIT_IOR_EXPR:
     742                 :         741 :       if (arg0->get_type () == boolean_type_node
     743                 :         741 :           && arg1->get_type () == boolean_type_node)
     744                 :             :         {
     745                 :             :           /* If the LHS are both _Bool, then... */
     746                 :             :           /* ..."(1 | x) -> 1".  */
     747                 :         138 :           if (cst0 && !zerop (cst0))
     748                 :           0 :             return get_or_create_int_cst (type, 1);
     749                 :             :           /* ..."(x | 1) -> 1".  */
     750                 :         138 :           if (cst1 && !zerop (cst1))
     751                 :          48 :             return get_or_create_int_cst (type, 1);
     752                 :             :           /* ..."(0 | x) -> x".  */
     753                 :          90 :           if (cst0 && zerop (cst0))
     754                 :           0 :             return get_or_create_cast (type, arg1);
     755                 :             :           /* ..."(x | 0) -> x".  */
     756                 :          90 :           if (cst1 && zerop (cst1))
     757                 :          32 :             return get_or_create_cast (type, arg0);
     758                 :             :         }
     759                 :             :       break;
     760                 :          12 :     case TRUTH_ANDIF_EXPR:
     761                 :          12 :     case TRUTH_AND_EXPR:
     762                 :          12 :       if (cst1)
     763                 :             :         {
     764                 :          12 :           if (zerop (cst1) && INTEGRAL_TYPE_P (type))
     765                 :             :             /* "(ARG0 && 0)" -> "0".  */
     766                 :           4 :             return get_or_create_constant_svalue (build_int_cst (type, 0));
     767                 :             :           else
     768                 :             :             /* "(ARG0 && nonzero-cst)" -> "ARG0".  */
     769                 :           8 :             return get_or_create_cast (type, arg0);
     770                 :             :         }
     771                 :             :       break;
     772                 :          12 :     case TRUTH_ORIF_EXPR:
     773                 :          12 :     case TRUTH_OR_EXPR:
     774                 :          12 :       if (cst1)
     775                 :             :         {
     776                 :          12 :           if (zerop (cst1))
     777                 :             :             /* "(ARG0 || 0)" -> "ARG0".  */
     778                 :           8 :             return get_or_create_cast (type, arg0);
     779                 :             :           else
     780                 :             :             /* "(ARG0 && nonzero-cst)" -> "nonzero-cst".  */
     781                 :           4 :             return get_or_create_cast (type, arg1);
     782                 :             :         }
     783                 :             :       break;
     784                 :             :     }
     785                 :             : 
     786                 :             :   /* For associative ops, fold "(X op CST_A) op CST_B)" to
     787                 :             :      "X op (CST_A op CST_B)".  */
     788                 :      126222 :   if (cst1 && associative_tree_code (op))
     789                 :       78067 :     if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
     790                 :       17530 :       if (binop->get_op () == op
     791                 :       17530 :           && binop->get_arg1 ()->maybe_get_constant ())
     792                 :        2582 :         return get_or_create_binop
     793                 :        2582 :           (type, op, binop->get_arg0 (),
     794                 :             :            get_or_create_binop (type, op,
     795                 :        2582 :                                 binop->get_arg1 (), arg1));
     796                 :             : 
     797                 :             :   /* associative_tree_code is false for POINTER_PLUS_EXPR, but we
     798                 :             :      can fold:
     799                 :             :        "(PTR ptr+ CST_A) ptr+ CST_B)" to "PTR ptr+ (CST_A ptr+ CST_B)"
     800                 :             :      e.g. in data-model-1.c: test_4c.  */
     801                 :      123640 :   if (cst1 && op == POINTER_PLUS_EXPR)
     802                 :       12184 :     if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
     803                 :        1101 :       if (binop->get_op () == POINTER_PLUS_EXPR)
     804                 :        1101 :         if (binop->get_arg1 ()->maybe_get_constant ())
     805                 :         865 :           return get_or_create_binop
     806                 :         865 :             (type, op, binop->get_arg0 (),
     807                 :             :              get_or_create_binop (size_type_node, op,
     808                 :         865 :                                   binop->get_arg1 (), arg1));
     809                 :             : 
     810                 :             :   /* Distribute multiplication by a constant through addition/subtraction:
     811                 :             :      (X + Y) * CST => (X * CST) + (Y * CST).  */
     812                 :      122775 :   if (cst1 && op == MULT_EXPR)
     813                 :       26545 :     if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
     814                 :        1683 :       if (binop->get_op () == PLUS_EXPR
     815                 :        1683 :           || binop->get_op () == MINUS_EXPR)
     816                 :             :         {
     817                 :        1030 :           return get_or_create_binop
     818                 :        1030 :             (type, binop->get_op (),
     819                 :             :              get_or_create_binop (type, op,
     820                 :             :                                   binop->get_arg0 (), arg1),
     821                 :             :              get_or_create_binop (type, op,
     822                 :        1030 :                                   binop->get_arg1 (), arg1));
     823                 :             :         }
     824                 :             : 
     825                 :             : 
     826                 :             :   /* Typeless operations, assumed to be effectively arbitrary sized
     827                 :             :      integers following normal arithmetic rules.  */
     828                 :      121745 :   if (!type)
     829                 :       34399 :     switch (op)
     830                 :             :       {
     831                 :             :       default:
     832                 :             :         break;
     833                 :          55 :       case MINUS_EXPR:
     834                 :          55 :         {
     835                 :             :           /* (X - X) -> 0.  */
     836                 :          55 :           if (arg0 == arg1)
     837                 :          11 :             return get_or_create_int_cst (type, 0);
     838                 :             : 
     839                 :             :           /* (X + A) - (A + B) -> (A - B).  */
     840                 :          44 :           if (const binop_svalue *binop0 = arg0->dyn_cast_binop_svalue ())
     841                 :          44 :             if (const binop_svalue *binop1 = arg1->dyn_cast_binop_svalue ())
     842                 :          36 :               if (binop0->get_op () == PLUS_EXPR
     843                 :          28 :                   && binop1->get_op () == PLUS_EXPR
     844                 :          56 :                   && binop0->get_arg0 () == binop1->get_arg0 ())
     845                 :          20 :                 return get_or_create_binop (NULL_TREE, op,
     846                 :             :                                             binop0->get_arg1 (),
     847                 :          20 :                                             binop1->get_arg1 ());
     848                 :             :         }
     849                 :             :         break;
     850                 :             : 
     851                 :          73 :       case EXACT_DIV_EXPR:
     852                 :          73 :         {
     853                 :          73 :           if (const unaryop_svalue *unaryop0 = arg0->dyn_cast_unaryop_svalue ())
     854                 :             :             {
     855                 :           0 :               if (unaryop0->get_op () == NOP_EXPR)
     856                 :           0 :                 if (const svalue *sval = maybe_fold_binop (NULL_TREE, op,
     857                 :             :                                                            unaryop0->get_arg (),
     858                 :             :                                                            arg1))
     859                 :             :                   return sval;
     860                 :             :             }
     861                 :          73 :           if (const binop_svalue *binop0 = arg0->dyn_cast_binop_svalue ())
     862                 :             :             {
     863                 :          72 :               switch (binop0->get_op ())
     864                 :             :                 {
     865                 :             :                 default:
     866                 :             :                   break;
     867                 :             : 
     868                 :          26 :                 case PLUS_EXPR:
     869                 :          26 :                 case MINUS_EXPR:
     870                 :             :                   /* (A op B) / C -> (A / C) op (B / C).  */
     871                 :          26 :                   {
     872                 :          26 :                     if (const svalue *op_on_a
     873                 :          26 :                         = maybe_fold_binop (NULL_TREE, op,
     874                 :             :                                             binop0->get_arg0 (), arg1))
     875                 :          26 :                       if (const svalue *op_on_b
     876                 :          26 :                           = maybe_fold_binop (NULL_TREE, op,
     877                 :             :                                               binop0->get_arg1 (), arg1))
     878                 :          26 :                         return get_or_create_binop (NULL_TREE,
     879                 :             :                                                     binop0->get_op (),
     880                 :          26 :                                                     op_on_a, op_on_b);
     881                 :             :                   }
     882                 :             :                   break;
     883                 :             : 
     884                 :          46 :                 case MULT_EXPR:
     885                 :             :                   /* (A * B) / C -> A * (B / C) if C is a divisor of B.
     886                 :             :                      In particular, this should also handle the case
     887                 :             :                      (A * B) / B -> A.  */
     888                 :          46 :                   if (const svalue *b_div_c
     889                 :          46 :                       = maybe_fold_binop (NULL_TREE, op,
     890                 :             :                                           binop0->get_arg1 (), arg1))
     891                 :          46 :                     return get_or_create_binop (NULL_TREE, binop0->get_op (),
     892                 :          46 :                                                 binop0->get_arg0 (), b_div_c);
     893                 :             :                 }
     894                 :             :             }
     895                 :             :         }
     896                 :             :         break;
     897                 :             :       }
     898                 :             : 
     899                 :             :   /* etc.  */
     900                 :             : 
     901                 :             :   return NULL;
     902                 :             : }
     903                 :             : 
     904                 :             : /* Return the svalue * for an binary operation OP on ARG0 and ARG1
     905                 :             :    with a result of type TYPE, creating it if necessary.  */
     906                 :             : 
     907                 :             : const svalue *
     908                 :      205574 : region_model_manager::get_or_create_binop (tree type, enum tree_code op,
     909                 :             :                                            const svalue *arg0,
     910                 :             :                                            const svalue *arg1)
     911                 :             : {
     912                 :             :   /* For commutative ops, put any constant on the RHS.  */
     913                 :      205574 :   if (arg0->maybe_get_constant () && commutative_tree_code (op))
     914                 :             :     std::swap (arg0, arg1);
     915                 :             : 
     916                 :      205574 :   if (const svalue *folded = maybe_fold_binop (type, op, arg0, arg1))
     917                 :             :     return folded;
     918                 :             : 
     919                 :             :   /* Ops on "unknown"/"poisoned" are unknown (unless we were able to fold
     920                 :             :      it via an identity in maybe_fold_binop).  */
     921                 :      122251 :   if (!arg0->can_have_associated_state_p ()
     922                 :      122251 :       || !arg1->can_have_associated_state_p ())
     923                 :       30706 :     return get_or_create_unknown_svalue (type);
     924                 :             : 
     925                 :       91545 :   binop_svalue::key_t key (type, op, arg0, arg1);
     926                 :       91545 :   if (binop_svalue **slot = m_binop_values_map.get (key))
     927                 :       70151 :     return *slot;
     928                 :       21394 :   binop_svalue *binop_sval
     929                 :       21394 :     = new binop_svalue (alloc_symbol_id (), type, op, arg0, arg1);
     930                 :       21394 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (binop_sval);
     931                 :       21268 :   m_binop_values_map.put (key, binop_sval);
     932                 :       21268 :   return binop_sval;
     933                 :             : }
     934                 :             : 
     935                 :             : /* Subroutine of region_model_manager::get_or_create_sub_svalue.
     936                 :             :    Return a folded svalue, or NULL.  */
     937                 :             : 
     938                 :             : const svalue *
     939                 :       63729 : region_model_manager::maybe_fold_sub_svalue (tree type,
     940                 :             :                                              const svalue *parent_svalue,
     941                 :             :                                              const region *subregion)
     942                 :             : {
     943                 :             :   /* Subvalues of "unknown"/"poisoned" are unknown.  */
     944                 :       63729 :   if (!parent_svalue->can_have_associated_state_p ())
     945                 :       47921 :     return get_or_create_unknown_svalue (type);
     946                 :             : 
     947                 :             :   /* If we have a subvalue of a zero constant, it's zero.  */
     948                 :       15808 :   if (tree cst = parent_svalue->maybe_get_constant ())
     949                 :         954 :     if (TREE_CODE (cst) == INTEGER_CST)
     950                 :         114 :       if (zerop (cst))
     951                 :         102 :         return get_or_create_cast (type, parent_svalue);
     952                 :             : 
     953                 :             :   /* If we have a subregion of a zero-fill, it's zero.  */
     954                 :       31412 :   if (const unaryop_svalue *unary
     955                 :       15706 :       = parent_svalue->dyn_cast_unaryop_svalue ())
     956                 :             :     {
     957                 :         582 :       if (unary->get_op () == NOP_EXPR
     958                 :         582 :           || unary->get_op () == VIEW_CONVERT_EXPR)
     959                 :         582 :         if (tree cst = unary->get_arg ()->maybe_get_constant ())
     960                 :         582 :           if (zerop (cst) && type)
     961                 :             :             {
     962                 :         570 :               const svalue *cst_sval
     963                 :         570 :                 = get_or_create_constant_svalue (cst);
     964                 :         570 :               return get_or_create_cast (type, cst_sval);
     965                 :             :             }
     966                 :             :     }
     967                 :             : 
     968                 :             :   /* Handle getting individual chars from a STRING_CST or RAW_DATA_CST.  */
     969                 :       15136 :   if (tree cst = parent_svalue->maybe_get_constant ())
     970                 :         852 :     if (TREE_CODE (cst) == STRING_CST
     971                 :         852 :         || TREE_CODE (cst) == RAW_DATA_CST)
     972                 :             :       {
     973                 :             :         /* If we have a concrete 1-byte access within the parent region... */
     974                 :         824 :         byte_range subregion_bytes (0, 0);
     975                 :         824 :         if (subregion->get_relative_concrete_byte_range (&subregion_bytes)
     976                 :         824 :             && subregion_bytes.m_size_in_bytes == 1
     977                 :        1337 :             && type)
     978                 :             :           {
     979                 :             :             /* ...then attempt to get that char from the constant.  */
     980                 :         513 :             HOST_WIDE_INT hwi_start_byte
     981                 :         513 :               = subregion_bytes.m_start_byte_offset.to_shwi ();
     982                 :         513 :             tree cst_idx
     983                 :         513 :               = build_int_cst_type (size_type_node, hwi_start_byte);
     984                 :        1026 :             if (const svalue *char_sval
     985                 :         513 :                   = maybe_get_char_from_cst (cst, cst_idx))
     986                 :         457 :               return get_or_create_cast (type, char_sval);
     987                 :             :           }
     988                 :             :       }
     989                 :             : 
     990                 :       29358 :   if (const initial_svalue *init_sval
     991                 :       14679 :         = parent_svalue->dyn_cast_initial_svalue ())
     992                 :             :     {
     993                 :             :       /* SUB(INIT(r)).FIELD -> INIT(r.FIELD)
     994                 :             :          i.e.
     995                 :             :          Subvalue(InitialValue(R1), FieldRegion(R2, F))
     996                 :             :          -> InitialValue(FieldRegion(R1, F)).  */
     997                 :         663 :       if (const field_region *field_reg = subregion->dyn_cast_field_region ())
     998                 :             :         {
     999                 :         442 :           const region *field_reg_new
    1000                 :         442 :             = get_field_region (init_sval->get_region (),
    1001                 :             :                                 field_reg->get_field ());
    1002                 :         442 :           return get_or_create_initial_value (field_reg_new);
    1003                 :             :         }
    1004                 :             :       /* SUB(INIT(r)[ELEMENT] -> INIT(e[ELEMENT])
    1005                 :             :          i.e.
    1006                 :             :          Subvalue(InitialValue(R1), ElementRegion(R2, IDX))
    1007                 :             :          -> InitialValue(ElementRegion(R1, IDX)).  */
    1008                 :         221 :       if (const element_region *element_reg = subregion->dyn_cast_element_region ())
    1009                 :             :         {
    1010                 :         124 :           const region *element_reg_new
    1011                 :         124 :             = get_element_region (init_sval->get_region (),
    1012                 :             :                                   element_reg->get_type (),
    1013                 :             :                                   element_reg->get_index ());
    1014                 :         124 :           return get_or_create_initial_value (element_reg_new);
    1015                 :             :         }
    1016                 :             :     }
    1017                 :             : 
    1018                 :       28226 :   if (const repeated_svalue *repeated_sval
    1019                 :       14113 :         = parent_svalue->dyn_cast_repeated_svalue ())
    1020                 :         104 :     if (type)
    1021                 :         100 :       return get_or_create_cast (type, repeated_sval->get_inner_svalue ());
    1022                 :             : 
    1023                 :             :   return NULL;
    1024                 :             : }
    1025                 :             : 
    1026                 :             : /* Return the svalue * for extracting a subvalue of type TYPE from
    1027                 :             :    PARENT_SVALUE based on SUBREGION, creating it if necessary.  */
    1028                 :             : 
    1029                 :             : const svalue *
    1030                 :       63729 : region_model_manager::get_or_create_sub_svalue (tree type,
    1031                 :             :                                                 const svalue *parent_svalue,
    1032                 :             :                                                 const region *subregion)
    1033                 :             : {
    1034                 :      127458 :   if (const svalue *folded
    1035                 :       63729 :         = maybe_fold_sub_svalue (type, parent_svalue, subregion))
    1036                 :             :     return folded;
    1037                 :             : 
    1038                 :       14013 :   sub_svalue::key_t key (type, parent_svalue, subregion);
    1039                 :       14013 :   if (sub_svalue **slot = m_sub_values_map.get (key))
    1040                 :       11532 :     return *slot;
    1041                 :        2481 :   sub_svalue *sub_sval
    1042                 :        2481 :     = new sub_svalue (alloc_symbol_id (), type, parent_svalue, subregion);
    1043                 :        2481 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (sub_sval);
    1044                 :        2481 :   m_sub_values_map.put (key, sub_sval);
    1045                 :        2481 :   return sub_sval;
    1046                 :             : }
    1047                 :             : 
    1048                 :             : /* Subroutine of region_model_manager::get_or_create_repeated_svalue.
    1049                 :             :    Return a folded svalue, or NULL.  */
    1050                 :             : 
    1051                 :             : const svalue *
    1052                 :        3035 : region_model_manager::maybe_fold_repeated_svalue (tree type,
    1053                 :             :                                                   const svalue *outer_size,
    1054                 :             :                                                   const svalue *inner_svalue)
    1055                 :             : {
    1056                 :             :   /* Repeated "unknown"/"poisoned" is unknown.  */
    1057                 :        3035 :   if (!outer_size->can_have_associated_state_p ()
    1058                 :        3035 :       || !inner_svalue->can_have_associated_state_p ())
    1059                 :           4 :     return get_or_create_unknown_svalue (type);
    1060                 :             : 
    1061                 :             :   /* If INNER_SVALUE is the same size as OUTER_SIZE,
    1062                 :             :      turn into simply a cast.  */
    1063                 :        3031 :   if (tree cst_outer_num_bytes = outer_size->maybe_get_constant ())
    1064                 :             :     {
    1065                 :        2901 :       HOST_WIDE_INT num_bytes_inner_svalue
    1066                 :        2901 :         = int_size_in_bytes (inner_svalue->get_type ());
    1067                 :        2901 :       if (num_bytes_inner_svalue != -1)
    1068                 :        2901 :         if (num_bytes_inner_svalue
    1069                 :        2901 :             == (HOST_WIDE_INT)tree_to_uhwi (cst_outer_num_bytes))
    1070                 :             :           {
    1071                 :         337 :             if (type)
    1072                 :         317 :               return get_or_create_cast (type, inner_svalue);
    1073                 :             :             else
    1074                 :             :               return inner_svalue;
    1075                 :             :           }
    1076                 :             :     }
    1077                 :             : 
    1078                 :             :   /* Handle zero-fill of a specific type.  */
    1079                 :        2694 :   if (tree cst = inner_svalue->maybe_get_constant ())
    1080                 :        2689 :     if (zerop (cst) && type)
    1081                 :         637 :       return get_or_create_cast (type, inner_svalue);
    1082                 :             : 
    1083                 :             :   return NULL;
    1084                 :             : }
    1085                 :             : 
    1086                 :             : /* Return the svalue * of type TYPE in which INNER_SVALUE is repeated
    1087                 :             :    enough times to be of size OUTER_SIZE, creating it if necessary.
    1088                 :             :    e.g. for filling buffers with a constant value.  */
    1089                 :             : 
    1090                 :             : const svalue *
    1091                 :        3035 : region_model_manager::get_or_create_repeated_svalue (tree type,
    1092                 :             :                                                      const svalue *outer_size,
    1093                 :             :                                                      const svalue *inner_svalue)
    1094                 :             : {
    1095                 :        6070 :   if (const svalue *folded
    1096                 :        3035 :         = maybe_fold_repeated_svalue (type, outer_size, inner_svalue))
    1097                 :             :     return folded;
    1098                 :             : 
    1099                 :        2057 :   repeated_svalue::key_t key (type, outer_size, inner_svalue);
    1100                 :        2057 :   if (repeated_svalue **slot = m_repeated_values_map.get (key))
    1101                 :        1556 :     return *slot;
    1102                 :         501 :   repeated_svalue *repeated_sval
    1103                 :         501 :     = new repeated_svalue (alloc_symbol_id (), type, outer_size, inner_svalue);
    1104                 :         501 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (repeated_sval);
    1105                 :         501 :   m_repeated_values_map.put (key, repeated_sval);
    1106                 :         501 :   return repeated_sval;
    1107                 :             : }
    1108                 :             : 
    1109                 :             : /* Attempt to get the bit_range for FIELD within a RECORD_TYPE.
    1110                 :             :    Return true and write the result to OUT if successful.
    1111                 :             :    Return false otherwise.  */
    1112                 :             : 
    1113                 :             : static bool
    1114                 :         816 : get_bit_range_for_field (tree field, bit_range *out)
    1115                 :             : {
    1116                 :         816 :   bit_size_t bit_size;
    1117                 :         816 :   if (!int_size_in_bits (TREE_TYPE (field), &bit_size))
    1118                 :             :     return false;
    1119                 :         816 :   int field_bit_offset = int_bit_position (field);
    1120                 :         816 :   *out = bit_range (field_bit_offset, bit_size);
    1121                 :         816 :   return true;
    1122                 :             : }
    1123                 :             : 
    1124                 :             : /* Attempt to get the byte_range for FIELD within a RECORD_TYPE.
    1125                 :             :    Return true and write the result to OUT if successful.
    1126                 :             :    Return false otherwise.  */
    1127                 :             : 
    1128                 :             : static bool
    1129                 :         816 : get_byte_range_for_field (tree field, byte_range *out)
    1130                 :             : {
    1131                 :         816 :   bit_range field_bits (0, 0);
    1132                 :         816 :   if (!get_bit_range_for_field (field, &field_bits))
    1133                 :             :     return false;
    1134                 :         816 :   return field_bits.as_byte_range (out);
    1135                 :             : }
    1136                 :             : 
    1137                 :             : /* Attempt to determine if there is a specific field within RECORD_TYPE
    1138                 :             :    at BYTES.  If so, return it, and write the location of BYTES relative
    1139                 :             :    to the field to *OUT_RANGE_WITHIN_FIELD.
    1140                 :             :    Otherwise, return NULL_TREE.
    1141                 :             :    For example, given:
    1142                 :             :      struct foo { uint32 a; uint32; b};
    1143                 :             :    and
    1144                 :             :      bytes = {bytes 6-7} (of foo)
    1145                 :             :    we have bytes 3-4 of field b.  */
    1146                 :             : 
    1147                 :             : static tree
    1148                 :         816 : get_field_at_byte_range (tree record_type, const byte_range &bytes,
    1149                 :             :                          byte_range *out_range_within_field)
    1150                 :             : {
    1151                 :         816 :   bit_offset_t bit_offset = bytes.m_start_byte_offset * BITS_PER_UNIT;
    1152                 :             : 
    1153                 :         816 :   tree field = get_field_at_bit_offset (record_type, bit_offset);
    1154                 :         816 :   if (!field)
    1155                 :             :     return NULL_TREE;
    1156                 :             : 
    1157                 :         816 :   byte_range field_bytes (0,0);
    1158                 :         816 :   if (!get_byte_range_for_field (field, &field_bytes))
    1159                 :             :     return NULL_TREE;
    1160                 :             : 
    1161                 :             :   /* Is BYTES fully within field_bytes?  */
    1162                 :         804 :   byte_range bytes_within_field (0,0);
    1163                 :         804 :   if (!field_bytes.contains_p (bytes, &bytes_within_field))
    1164                 :             :     return NULL_TREE;
    1165                 :             : 
    1166                 :         323 :   *out_range_within_field = bytes_within_field;
    1167                 :         323 :   return field;
    1168                 :             : }
    1169                 :             : 
    1170                 :             : /* Subroutine of region_model_manager::get_or_create_bits_within.
    1171                 :             :    Return a folded svalue, or NULL.  */
    1172                 :             : 
    1173                 :             : const svalue *
    1174                 :       25428 : region_model_manager::maybe_fold_bits_within_svalue (tree type,
    1175                 :             :                                                      const bit_range &bits,
    1176                 :             :                                                      const svalue *inner_svalue)
    1177                 :             : {
    1178                 :       25428 :   tree inner_type = inner_svalue->get_type ();
    1179                 :             :   /* Fold:
    1180                 :             :        BITS_WITHIN ((0, sizeof (VAL), VAL))
    1181                 :             :      to:
    1182                 :             :        CAST(TYPE, VAL).  */
    1183                 :       25428 :   if (bits.m_start_bit_offset == 0 && inner_type)
    1184                 :             :     {
    1185                 :        3510 :       bit_size_t inner_type_size;
    1186                 :        3510 :       if (int_size_in_bits (inner_type, &inner_type_size))
    1187                 :        3510 :         if (inner_type_size == bits.m_size_in_bits)
    1188                 :             :           {
    1189                 :         532 :             if (type)
    1190                 :         532 :               return get_or_create_cast (type, inner_svalue);
    1191                 :             :             else
    1192                 :             :               return inner_svalue;
    1193                 :             :           }
    1194                 :             :     }
    1195                 :             : 
    1196                 :             :   /* Kind-specific folding.  */
    1197                 :       49792 :   if (const svalue *sval
    1198                 :       24896 :       = inner_svalue->maybe_fold_bits_within (type, bits, this))
    1199                 :             :     return sval;
    1200                 :             : 
    1201                 :        1602 :   byte_range bytes (0,0);
    1202                 :        1602 :   if (bits.as_byte_range (&bytes) && inner_type)
    1203                 :        1402 :     switch (TREE_CODE (inner_type))
    1204                 :             :       {
    1205                 :             :       default:
    1206                 :             :         break;
    1207                 :         411 :       case ARRAY_TYPE:
    1208                 :         411 :         {
    1209                 :             :           /* Fold:
    1210                 :             :                BITS_WITHIN (range, KIND(REG))
    1211                 :             :              to:
    1212                 :             :                BITS_WITHIN (range - offsetof(ELEMENT), KIND(REG.ELEMENT))
    1213                 :             :              if range1 is a byte-range fully within one ELEMENT.  */
    1214                 :         411 :           tree element_type = TREE_TYPE (inner_type);
    1215                 :         411 :           HOST_WIDE_INT element_byte_size
    1216                 :         411 :             = int_size_in_bytes (element_type);
    1217                 :         411 :           if (element_byte_size > 0)
    1218                 :             :             {
    1219                 :         411 :               HOST_WIDE_INT start_idx
    1220                 :         411 :                 = (bytes.get_start_byte_offset ().to_shwi ()
    1221                 :         411 :                    / element_byte_size);
    1222                 :         411 :               HOST_WIDE_INT last_idx
    1223                 :         411 :                 = (bytes.get_last_byte_offset ().to_shwi ()
    1224                 :         411 :                    / element_byte_size);
    1225                 :         411 :               if (start_idx == last_idx)
    1226                 :             :                 {
    1227                 :         452 :                   if (const initial_svalue *initial_sval
    1228                 :         226 :                       = inner_svalue->dyn_cast_initial_svalue ())
    1229                 :             :                     {
    1230                 :         167 :                       bit_offset_t start_of_element
    1231                 :         167 :                         = start_idx * element_byte_size * BITS_PER_UNIT;
    1232                 :         167 :                       bit_range bits_within_element
    1233                 :         167 :                         (bits.m_start_bit_offset - start_of_element,
    1234                 :         167 :                          bits.m_size_in_bits);
    1235                 :         167 :                       const svalue *idx_sval
    1236                 :         167 :                         = get_or_create_int_cst (integer_type_node, start_idx);
    1237                 :         167 :                       const region *element_reg =
    1238                 :         167 :                         get_element_region (initial_sval->get_region (),
    1239                 :             :                                             element_type, idx_sval);
    1240                 :         167 :                       const svalue *element_reg_sval
    1241                 :         167 :                         = get_or_create_initial_value (element_reg);
    1242                 :         167 :                       return get_or_create_bits_within (type,
    1243                 :             :                                                         bits_within_element,
    1244                 :             :                                                         element_reg_sval);
    1245                 :             :                     }
    1246                 :             :                 }
    1247                 :             :             }
    1248                 :             :         }
    1249                 :             :         break;
    1250                 :         816 :       case RECORD_TYPE:
    1251                 :         816 :         {
    1252                 :             :           /* Fold:
    1253                 :             :                BYTES_WITHIN (range, KIND(REG))
    1254                 :             :              to:
    1255                 :             :                BYTES_WITHIN (range - offsetof(FIELD), KIND(REG.FIELD))
    1256                 :             :              if range1 is fully within FIELD.  */
    1257                 :         816 :           byte_range bytes_within_field (0, 0);
    1258                 :         816 :           if (tree field = get_field_at_byte_range (inner_type, bytes,
    1259                 :             :                                                     &bytes_within_field))
    1260                 :             :             {
    1261                 :         646 :               if (const initial_svalue *initial_sval
    1262                 :         323 :                   = inner_svalue->dyn_cast_initial_svalue ())
    1263                 :             :                 {
    1264                 :         184 :                   const region *field_reg =
    1265                 :         184 :                     get_field_region (initial_sval->get_region (), field);
    1266                 :         184 :                   const svalue *initial_reg_sval
    1267                 :         184 :                     = get_or_create_initial_value (field_reg);
    1268                 :         184 :                   return get_or_create_bits_within
    1269                 :         184 :                     (type,
    1270                 :         368 :                      bytes_within_field.as_bit_range (),
    1271                 :             :                      initial_reg_sval);
    1272                 :             :                 }
    1273                 :             :             }
    1274                 :             :         }
    1275                 :         632 :         break;
    1276                 :             :       }
    1277                 :             :   return NULL;
    1278                 :             : }
    1279                 :             : 
    1280                 :             : /* Return the svalue * of type TYPE for extracting BITS from INNER_SVALUE,
    1281                 :             :    creating it if necessary.  */
    1282                 :             : 
    1283                 :             : const svalue *
    1284                 :       25428 : region_model_manager::get_or_create_bits_within (tree type,
    1285                 :             :                                                  const bit_range &bits,
    1286                 :             :                                                  const svalue *inner_svalue)
    1287                 :             : {
    1288                 :       50856 :   if (const svalue *folded
    1289                 :       25428 :         = maybe_fold_bits_within_svalue (type, bits, inner_svalue))
    1290                 :             :     return folded;
    1291                 :             : 
    1292                 :        1251 :   bits_within_svalue::key_t key (type, bits, inner_svalue);
    1293                 :        1251 :   if (bits_within_svalue **slot = m_bits_within_values_map.get (key))
    1294                 :         578 :     return *slot;
    1295                 :         673 :   bits_within_svalue *bits_within_sval
    1296                 :         673 :     = new bits_within_svalue (alloc_symbol_id (), type, bits, inner_svalue);
    1297                 :         673 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (bits_within_sval);
    1298                 :         673 :   m_bits_within_values_map.put (key, bits_within_sval);
    1299                 :         673 :   return bits_within_sval;
    1300                 :             : }
    1301                 :             : 
    1302                 :             : /* Return the svalue * that decorates ARG as being unmergeable,
    1303                 :             :    creating it if necessary.  */
    1304                 :             : 
    1305                 :             : const svalue *
    1306                 :         936 : region_model_manager::get_or_create_unmergeable (const svalue *arg)
    1307                 :             : {
    1308                 :         936 :   if (arg->get_kind () == SK_UNMERGEABLE)
    1309                 :             :     return arg;
    1310                 :             : 
    1311                 :         936 :   if (unmergeable_svalue **slot = m_unmergeable_values_map.get (arg))
    1312                 :         734 :     return *slot;
    1313                 :         202 :   unmergeable_svalue *unmergeable_sval
    1314                 :         202 :     = new unmergeable_svalue (alloc_symbol_id (), arg);
    1315                 :         202 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (unmergeable_sval);
    1316                 :         202 :   m_unmergeable_values_map.put (arg, unmergeable_sval);
    1317                 :         202 :   return unmergeable_sval;
    1318                 :             : }
    1319                 :             : 
    1320                 :             : /* Return the svalue * of type TYPE for the merger of value BASE_SVAL
    1321                 :             :    and ITER_SVAL at POINT, creating it if necessary.  */
    1322                 :             : 
    1323                 :             : const svalue *
    1324                 :        4871 : region_model_manager::
    1325                 :             : get_or_create_widening_svalue (tree type,
    1326                 :             :                                const function_point &point,
    1327                 :             :                                const svalue *base_sval,
    1328                 :             :                                const svalue *iter_sval)
    1329                 :             : {
    1330                 :        4871 :   gcc_assert (base_sval->get_kind () != SK_WIDENING);
    1331                 :        4871 :   gcc_assert (iter_sval->get_kind () != SK_WIDENING);
    1332                 :        4871 :   widening_svalue::key_t key (type, point, base_sval, iter_sval);
    1333                 :        4871 :   if (widening_svalue **slot = m_widening_values_map.get (key))
    1334                 :        2388 :     return *slot;
    1335                 :        2483 :   widening_svalue *widening_sval
    1336                 :             :     = new widening_svalue (alloc_symbol_id (), type, point, base_sval,
    1337                 :        2483 :                            iter_sval);
    1338                 :        2483 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (widening_sval);
    1339                 :        2483 :   m_widening_values_map.put (key, widening_sval);
    1340                 :        2483 :   return widening_sval;
    1341                 :             : }
    1342                 :             : 
    1343                 :             : /* Return the svalue * of type TYPE for the compound values in MAP,
    1344                 :             :    creating it if necessary.  */
    1345                 :             : 
    1346                 :             : const svalue *
    1347                 :        4227 : region_model_manager::get_or_create_compound_svalue (tree type,
    1348                 :             :                                                      const binding_map &map)
    1349                 :             : {
    1350                 :        4227 :   compound_svalue::key_t tmp_key (type, &map);
    1351                 :        4227 :   if (compound_svalue **slot = m_compound_values_map.get (tmp_key))
    1352                 :        3570 :     return *slot;
    1353                 :         657 :   compound_svalue *compound_sval
    1354                 :         657 :     = new compound_svalue (alloc_symbol_id (), type, map);
    1355                 :         657 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (compound_sval);
    1356                 :             :   /* Use make_key rather than reusing the key, so that we use a
    1357                 :             :      ptr to compound_sval's binding_map, rather than the MAP param.  */
    1358                 :         657 :   m_compound_values_map.put (compound_sval->make_key (), compound_sval);
    1359                 :         657 :   return compound_sval;
    1360                 :             : }
    1361                 :             : 
    1362                 :             : /* class conjured_purge.  */
    1363                 :             : 
    1364                 :             : /* Purge state relating to SVAL.  */
    1365                 :             : 
    1366                 :             : void
    1367                 :       38543 : conjured_purge::purge (const conjured_svalue *sval) const
    1368                 :             : {
    1369                 :       38543 :   m_model->purge_state_involving (sval, m_ctxt);
    1370                 :       38543 : }
    1371                 :             : 
    1372                 :             : /* Return the svalue * of type TYPE for the value conjured for ID_REG
    1373                 :             :    at STMT (using IDX for any further disambiguation),
    1374                 :             :    creating it if necessary.
    1375                 :             :    Use P to purge existing state from the svalue, for the case where a
    1376                 :             :    conjured_svalue would be reused along an execution path.  */
    1377                 :             : 
    1378                 :             : const svalue *
    1379                 :       66942 : region_model_manager::get_or_create_conjured_svalue (tree type,
    1380                 :             :                                                      const gimple *stmt,
    1381                 :             :                                                      const region *id_reg,
    1382                 :             :                                                      const conjured_purge &p,
    1383                 :             :                                                      unsigned idx)
    1384                 :             : {
    1385                 :       66942 :   conjured_svalue::key_t key (type, stmt, id_reg, idx);
    1386                 :       66942 :   if (conjured_svalue **slot = m_conjured_values_map.get (key))
    1387                 :             :     {
    1388                 :       38543 :       const conjured_svalue *sval = *slot;
    1389                 :             :       /* We're reusing an existing conjured_svalue, perhaps from a different
    1390                 :             :          state within this analysis, or perhaps from an earlier state on this
    1391                 :             :          execution path.  For the latter, purge any state involving the "new"
    1392                 :             :          svalue from the current program_state.  */
    1393                 :       38543 :       p.purge (sval);
    1394                 :       38543 :       return sval;
    1395                 :             :     }
    1396                 :       28399 :   conjured_svalue *conjured_sval
    1397                 :       28399 :     = new conjured_svalue (alloc_symbol_id (), type, stmt, id_reg, idx);
    1398                 :       28399 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (conjured_sval);
    1399                 :       28303 :   m_conjured_values_map.put (key, conjured_sval);
    1400                 :       28303 :   return conjured_sval;
    1401                 :             : }
    1402                 :             : 
    1403                 :             : /* Subroutine of region_model_manager::get_or_create_asm_output_svalue.
    1404                 :             :    Return a folded svalue, or NULL.  */
    1405                 :             : 
    1406                 :             : const svalue *
    1407                 :         403 : region_model_manager::
    1408                 :             : maybe_fold_asm_output_svalue (tree type,
    1409                 :             :                               const vec<const svalue *> &inputs)
    1410                 :             : {
    1411                 :             :   /* Unknown inputs should lead to unknown results.  */
    1412                 :        1833 :   for (const auto &iter : inputs)
    1413                 :         681 :     if (iter->get_kind () == SK_UNKNOWN)
    1414                 :           9 :       return get_or_create_unknown_svalue (type);
    1415                 :             : 
    1416                 :             :   return NULL;
    1417                 :             : }
    1418                 :             : 
    1419                 :             : /* Return the svalue * of type TYPE for OUTPUT_IDX of the deterministic
    1420                 :             :    asm stmt ASM_STMT, given INPUTS as inputs.  */
    1421                 :             : 
    1422                 :             : const svalue *
    1423                 :         301 : region_model_manager::
    1424                 :             : get_or_create_asm_output_svalue (tree type,
    1425                 :             :                                  const gasm *asm_stmt,
    1426                 :             :                                  unsigned output_idx,
    1427                 :             :                                  const vec<const svalue *> &inputs)
    1428                 :             : {
    1429                 :         301 :   gcc_assert (inputs.length () <= asm_output_svalue::MAX_INPUTS);
    1430                 :             : 
    1431                 :         602 :   if (const svalue *folded
    1432                 :         301 :         = maybe_fold_asm_output_svalue (type, inputs))
    1433                 :             :     return folded;
    1434                 :             : 
    1435                 :         292 :   const char *asm_string = gimple_asm_string (asm_stmt);
    1436                 :         292 :   const unsigned noutputs = gimple_asm_noutputs (asm_stmt);
    1437                 :             : 
    1438                 :         292 :   asm_output_svalue::key_t key (type, asm_string, output_idx, inputs);
    1439                 :         292 :   if (asm_output_svalue **slot = m_asm_output_values_map.get (key))
    1440                 :         120 :     return *slot;
    1441                 :         172 :   asm_output_svalue *asm_output_sval
    1442                 :             :     = new asm_output_svalue (alloc_symbol_id (), type, asm_string, output_idx,
    1443                 :         172 :                              noutputs, inputs);
    1444                 :         172 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (asm_output_sval);
    1445                 :         167 :   m_asm_output_values_map.put (key, asm_output_sval);
    1446                 :         167 :   return asm_output_sval;
    1447                 :             : }
    1448                 :             : 
    1449                 :             : /* Return the svalue * of type TYPE for OUTPUT_IDX of a deterministic
    1450                 :             :    asm stmt with string ASM_STRING with NUM_OUTPUTS outputs, given
    1451                 :             :    INPUTS as inputs.  */
    1452                 :             : 
    1453                 :             : const svalue *
    1454                 :         102 : region_model_manager::
    1455                 :             : get_or_create_asm_output_svalue (tree type,
    1456                 :             :                                  const char *asm_string,
    1457                 :             :                                  unsigned output_idx,
    1458                 :             :                                  unsigned num_outputs,
    1459                 :             :                                  const vec<const svalue *> &inputs)
    1460                 :             : {
    1461                 :         102 :   gcc_assert (inputs.length () <= asm_output_svalue::MAX_INPUTS);
    1462                 :             : 
    1463                 :         204 :   if (const svalue *folded
    1464                 :         102 :         = maybe_fold_asm_output_svalue (type, inputs))
    1465                 :             :     return folded;
    1466                 :             : 
    1467                 :         102 :   asm_output_svalue::key_t key (type, asm_string, output_idx, inputs);
    1468                 :         102 :   if (asm_output_svalue **slot = m_asm_output_values_map.get (key))
    1469                 :          82 :     return *slot;
    1470                 :          20 :   asm_output_svalue *asm_output_sval
    1471                 :             :     = new asm_output_svalue (alloc_symbol_id (), type, asm_string, output_idx,
    1472                 :          20 :                              num_outputs, inputs);
    1473                 :          20 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (asm_output_sval);
    1474                 :          20 :   m_asm_output_values_map.put (key, asm_output_sval);
    1475                 :          20 :   return asm_output_sval;
    1476                 :             : }
    1477                 :             : 
    1478                 :             : /* Return the svalue * of type TYPE for the result of a call to FNDECL
    1479                 :             :    with __attribute__((const)), given INPUTS as inputs.  */
    1480                 :             : 
    1481                 :             : const svalue *
    1482                 :        1098 : region_model_manager::
    1483                 :             : get_or_create_const_fn_result_svalue (tree type,
    1484                 :             :                                       tree fndecl,
    1485                 :             :                                       const vec<const svalue *> &inputs)
    1486                 :             : {
    1487                 :        1098 :   gcc_assert (fndecl);
    1488                 :        1098 :   gcc_assert (DECL_P (fndecl));
    1489                 :        1098 :   gcc_assert (TREE_READONLY (fndecl));
    1490                 :        1098 :   gcc_assert (inputs.length () <= const_fn_result_svalue::MAX_INPUTS);
    1491                 :             : 
    1492                 :        1098 :   const_fn_result_svalue::key_t key (type, fndecl, inputs);
    1493                 :        1098 :   if (const_fn_result_svalue **slot = m_const_fn_result_values_map.get (key))
    1494                 :         843 :     return *slot;
    1495                 :         255 :   const_fn_result_svalue *const_fn_result_sval
    1496                 :         255 :     = new const_fn_result_svalue (alloc_symbol_id (), type, fndecl, inputs);
    1497                 :         255 :   RETURN_UNKNOWN_IF_TOO_COMPLEX (const_fn_result_sval);
    1498                 :         255 :   m_const_fn_result_values_map.put (key, const_fn_result_sval);
    1499                 :         255 :   return const_fn_result_sval;
    1500                 :             : }
    1501                 :             : 
    1502                 :             : /* Given DATA_CST (a STRING_CST or RAW_DATA_CST) and BYTE_OFFSET_CST a constant,
    1503                 :             :    attempt to get the character at that offset, returning either
    1504                 :             :    the svalue for the character constant, or NULL if unsuccessful.  */
    1505                 :             : 
    1506                 :             : const svalue *
    1507                 :         513 : region_model_manager::maybe_get_char_from_cst (tree data_cst,
    1508                 :             :                                                tree byte_offset_cst)
    1509                 :             : {
    1510                 :         513 :   switch (TREE_CODE (data_cst))
    1511                 :             :     {
    1512                 :           0 :     default: gcc_unreachable ();
    1513                 :         447 :     case STRING_CST:
    1514                 :         447 :       return maybe_get_char_from_string_cst (data_cst, byte_offset_cst);
    1515                 :          66 :     case RAW_DATA_CST:
    1516                 :          66 :       return maybe_get_char_from_raw_data_cst (data_cst, byte_offset_cst);
    1517                 :             :     }
    1518                 :             : }
    1519                 :             : 
    1520                 :             : /* Get a tree for the size of STRING_CST, or NULL_TREE.
    1521                 :             :    Note that this may be larger than TREE_STRING_LENGTH (implying
    1522                 :             :    a run of trailing zero bytes from TREE_STRING_LENGTH up to this
    1523                 :             :    higher limit).  */
    1524                 :             : 
    1525                 :             : tree
    1526                 :        1145 : get_string_cst_size (const_tree string_cst)
    1527                 :             : {
    1528                 :        1145 :   gcc_assert (TREE_CODE (string_cst) == STRING_CST);
    1529                 :        1145 :   gcc_assert (TREE_CODE (TREE_TYPE (string_cst)) == ARRAY_TYPE);
    1530                 :             : 
    1531                 :        1145 :   return TYPE_SIZE_UNIT (TREE_TYPE (string_cst));
    1532                 :             : }
    1533                 :             : 
    1534                 :             : /* Given STRING_CST, a STRING_CST and BYTE_OFFSET_CST a constant,
    1535                 :             :    attempt to get the character at that offset, returning either
    1536                 :             :    the svalue for the character constant, or NULL if unsuccessful.  */
    1537                 :             : 
    1538                 :             : const svalue *
    1539                 :         840 : region_model_manager::maybe_get_char_from_string_cst (tree string_cst,
    1540                 :             :                                                       tree byte_offset_cst)
    1541                 :             : {
    1542                 :         840 :   gcc_assert (TREE_CODE (string_cst) == STRING_CST);
    1543                 :             : 
    1544                 :             :   /* Adapted from fold_read_from_constant_string.  */
    1545                 :         840 :   scalar_int_mode char_mode;
    1546                 :         840 :   if (TREE_CODE (byte_offset_cst) == INTEGER_CST
    1547                 :        1680 :       && is_int_mode (TYPE_MODE (TREE_TYPE (TREE_TYPE (string_cst))),
    1548                 :             :                       &char_mode)
    1549                 :        1680 :       && GET_MODE_SIZE (char_mode) == 1)
    1550                 :             :     {
    1551                 :             :       /* If we're beyond the string_cst, the read is unsuccessful.  */
    1552                 :         840 :       if (compare_constants (byte_offset_cst,
    1553                 :             :                              GE_EXPR,
    1554                 :         840 :                              get_string_cst_size (string_cst)).is_true ())
    1555                 :             :         return NULL;
    1556                 :             : 
    1557                 :         790 :       int char_val;
    1558                 :        1580 :       if (compare_tree_int (byte_offset_cst,
    1559                 :         790 :                             TREE_STRING_LENGTH (string_cst)) < 0)
    1560                 :             :         /* We're within the area defined by TREE_STRING_POINTER.  */
    1561                 :         788 :         char_val = (TREE_STRING_POINTER (string_cst)
    1562                 :         788 :                     [TREE_INT_CST_LOW (byte_offset_cst)]);
    1563                 :             :       else
    1564                 :             :         /* We're in the padding area of trailing zeroes.  */
    1565                 :             :         char_val = 0;
    1566                 :         790 :       tree char_cst
    1567                 :         790 :         = build_int_cst_type (TREE_TYPE (TREE_TYPE (string_cst)), char_val);
    1568                 :         790 :       return get_or_create_constant_svalue (char_cst);
    1569                 :             :     }
    1570                 :             :   return NULL;
    1571                 :             : }
    1572                 :             : 
    1573                 :             : /* Given RAW_DATA_CST, a RAW_DATA_CST and BYTE_OFFSET_CST a constant,
    1574                 :             :    attempt to get the character at that offset, returning either
    1575                 :             :    the svalue for the character constant, or NULL if unsuccessful.  */
    1576                 :             : 
    1577                 :             : const svalue *
    1578                 :          66 : region_model_manager::maybe_get_char_from_raw_data_cst (tree raw_data_cst,
    1579                 :             :                                                         tree byte_offset_cst)
    1580                 :             : {
    1581                 :          66 :   gcc_assert (TREE_CODE (raw_data_cst) == RAW_DATA_CST);
    1582                 :          66 :   gcc_assert (TREE_CODE (byte_offset_cst) == INTEGER_CST);
    1583                 :             : 
    1584                 :          66 :   offset_int o = (wi::to_offset (byte_offset_cst));
    1585                 :          66 :   if (o >= 0 && o < RAW_DATA_LENGTH (raw_data_cst))
    1586                 :          54 :     return get_or_create_int_cst
    1587                 :          54 :       (TREE_TYPE (raw_data_cst),
    1588                 :         108 :        RAW_DATA_UCHAR_ELT (raw_data_cst, o.to_uhwi ()));
    1589                 :             :   return nullptr;
    1590                 :             : }
    1591                 :             : 
    1592                 :             : /* region consolidation.  */
    1593                 :             : 
    1594                 :             : /* Return the region for FNDECL, creating it if necessary.  */
    1595                 :             : 
    1596                 :             : const function_region *
    1597                 :      892291 : region_model_manager::get_region_for_fndecl (tree fndecl)
    1598                 :             : {
    1599                 :      892291 :   gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
    1600                 :             : 
    1601                 :      892291 :   function_region **slot = m_fndecls_map.get (fndecl);
    1602                 :      892291 :   if (slot)
    1603                 :      883092 :     return *slot;
    1604                 :        9199 :   function_region *reg
    1605                 :        9199 :     = new function_region (alloc_symbol_id (), &m_code_region, fndecl);
    1606                 :        9199 :   m_fndecls_map.put (fndecl, reg);
    1607                 :        9199 :   return reg;
    1608                 :             : }
    1609                 :             : 
    1610                 :             : /* Return the region for LABEL, creating it if necessary.  */
    1611                 :             : 
    1612                 :             : const label_region *
    1613                 :         401 : region_model_manager::get_region_for_label (tree label)
    1614                 :             : {
    1615                 :         401 :   gcc_assert (TREE_CODE (label) == LABEL_DECL);
    1616                 :             : 
    1617                 :         401 :   label_region **slot = m_labels_map.get (label);
    1618                 :         401 :   if (slot)
    1619                 :         355 :     return *slot;
    1620                 :             : 
    1621                 :          46 :   tree fndecl = DECL_CONTEXT (label);
    1622                 :          46 :   gcc_assert (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL);
    1623                 :             : 
    1624                 :          46 :   const function_region *func_reg = get_region_for_fndecl (fndecl);
    1625                 :          46 :   label_region *reg
    1626                 :          46 :     = new label_region (alloc_symbol_id (), func_reg, label);
    1627                 :          46 :   m_labels_map.put (label, reg);
    1628                 :          46 :   return reg;
    1629                 :             : }
    1630                 :             : 
    1631                 :             : /* Return the region for EXPR, creating it if necessary.  */
    1632                 :             : 
    1633                 :             : const decl_region *
    1634                 :       58592 : region_model_manager::get_region_for_global (tree expr)
    1635                 :             : {
    1636                 :       58592 :   gcc_assert (VAR_P (expr));
    1637                 :             : 
    1638                 :       58592 :   decl_region **slot = m_globals_map.get (expr);
    1639                 :       58592 :   if (slot)
    1640                 :       52208 :     return *slot;
    1641                 :        6384 :   decl_region *reg
    1642                 :        6384 :     = new decl_region (alloc_symbol_id (), &m_globals_region, expr);
    1643                 :        6384 :   m_globals_map.put (expr, reg);
    1644                 :        6384 :   return reg;
    1645                 :             : }
    1646                 :             : 
    1647                 :             : /* Return the region for an unknown access of type REGION_TYPE,
    1648                 :             :    creating it if necessary.
    1649                 :             :    This is a symbolic_region, where the pointer is an unknown_svalue
    1650                 :             :    of type &REGION_TYPE.  */
    1651                 :             : 
    1652                 :             : const region *
    1653                 :       14965 : region_model_manager::get_unknown_symbolic_region (tree region_type)
    1654                 :             : {
    1655                 :       14965 :   tree ptr_type = region_type ? build_pointer_type (region_type) : NULL_TREE;
    1656                 :       14965 :   const svalue *unknown_ptr = get_or_create_unknown_svalue (ptr_type);
    1657                 :       14965 :   return get_symbolic_region (unknown_ptr);
    1658                 :             : }
    1659                 :             : 
    1660                 :             : /* Return the region that describes accessing field FIELD of PARENT,
    1661                 :             :    creating it if necessary.  */
    1662                 :             : 
    1663                 :             : const region *
    1664                 :       60260 : region_model_manager::get_field_region (const region *parent, tree field)
    1665                 :             : {
    1666                 :       60260 :   gcc_assert (TREE_CODE (field) == FIELD_DECL);
    1667                 :             : 
    1668                 :             :   /* (*UNKNOWN_PTR).field is (*UNKNOWN_PTR_OF_&FIELD_TYPE).  */
    1669                 :       60260 :   if (parent->symbolic_for_unknown_ptr_p ())
    1670                 :        4635 :     return get_unknown_symbolic_region (TREE_TYPE (field));
    1671                 :             : 
    1672                 :       55625 :   field_region::key_t key (parent, field);
    1673                 :      103328 :   if (field_region *reg = m_field_regions.get (key))
    1674                 :             :     return reg;
    1675                 :             : 
    1676                 :        7922 :   field_region *field_reg
    1677                 :        7922 :     = new field_region (alloc_symbol_id (), parent, field);
    1678                 :        7922 :   m_field_regions.put (key, field_reg);
    1679                 :        7922 :   return field_reg;
    1680                 :             : }
    1681                 :             : 
    1682                 :             : /* Return the region that describes accessing the element of type
    1683                 :             :    ELEMENT_TYPE at index INDEX of PARENT, creating it if necessary.  */
    1684                 :             : 
    1685                 :             : const region *
    1686                 :       16663 : region_model_manager::get_element_region (const region *parent,
    1687                 :             :                                           tree element_type,
    1688                 :             :                                           const svalue *index)
    1689                 :             : {
    1690                 :             :   /* (UNKNOWN_PTR[IDX]) is (UNKNOWN_PTR).  */
    1691                 :       16663 :   if (parent->symbolic_for_unknown_ptr_p ())
    1692                 :          60 :     return get_unknown_symbolic_region (element_type);
    1693                 :             : 
    1694                 :       16603 :   element_region::key_t key (parent, element_type, index);
    1695                 :       29364 :   if (element_region *reg = m_element_regions.get (key))
    1696                 :             :     return reg;
    1697                 :             : 
    1698                 :        3842 :   element_region *element_reg
    1699                 :        3842 :     = new element_region (alloc_symbol_id (), parent, element_type, index);
    1700                 :        3842 :   m_element_regions.put (key, element_reg);
    1701                 :        3842 :   return element_reg;
    1702                 :             : }
    1703                 :             : 
    1704                 :             : /* Return the region that describes accessing the subregion of type
    1705                 :             :    ELEMENT_TYPE at offset BYTE_OFFSET within PARENT, creating it if
    1706                 :             :    necessary.  */
    1707                 :             : 
    1708                 :             : const region *
    1709                 :      101142 : region_model_manager::get_offset_region (const region *parent,
    1710                 :             :                                          tree type,
    1711                 :             :                                          const svalue *byte_offset)
    1712                 :             : {
    1713                 :             :   /* (UNKNOWN_PTR + OFFSET) is (UNKNOWN_PTR).  */
    1714                 :      101640 :   if (parent->symbolic_for_unknown_ptr_p ())
    1715                 :        9896 :     return get_unknown_symbolic_region (type);
    1716                 :             : 
    1717                 :             :   /* If BYTE_OFFSET is zero, return PARENT.  */
    1718                 :       91744 :   if (tree cst_offset = byte_offset->maybe_get_constant ())
    1719                 :       81498 :     if (zerop (cst_offset))
    1720                 :       73029 :       return get_cast_region (parent, type);
    1721                 :             : 
    1722                 :             :   /* Fold OFFSET_REGION(OFFSET_REGION(REG, X), Y)
    1723                 :             :      to   OFFSET_REGION(REG, (X + Y)).  */
    1724                 :       37430 :   if (const offset_region *parent_offset_reg
    1725                 :       18715 :         = parent->dyn_cast_offset_region ())
    1726                 :             :     {
    1727                 :         498 :       const svalue *sval_x = parent_offset_reg->get_byte_offset ();
    1728                 :         498 :       const svalue *sval_sum
    1729                 :         498 :         = get_or_create_binop (byte_offset->get_type (),
    1730                 :             :                                PLUS_EXPR, sval_x, byte_offset);
    1731                 :         498 :       return get_offset_region (parent->get_parent_region (), type, sval_sum);
    1732                 :             :     }
    1733                 :             : 
    1734                 :       18217 :   offset_region::key_t key (parent, type, byte_offset);
    1735                 :       32691 :   if (offset_region *reg = m_offset_regions.get (key))
    1736                 :             :     return reg;
    1737                 :             : 
    1738                 :        3743 :   offset_region *offset_reg
    1739                 :        3743 :     = new offset_region (alloc_symbol_id (), parent, type, byte_offset);
    1740                 :        3743 :   m_offset_regions.put (key, offset_reg);
    1741                 :        3743 :   return offset_reg;
    1742                 :             : }
    1743                 :             : 
    1744                 :             : /* Return the region that describes accessing the subregion of type
    1745                 :             :    TYPE of size BYTE_SIZE_SVAL within PARENT, creating it if necessary.  */
    1746                 :             : 
    1747                 :             : const region *
    1748                 :        8802 : region_model_manager::get_sized_region (const region *parent,
    1749                 :             :                                         tree type,
    1750                 :             :                                         const svalue *byte_size_sval)
    1751                 :             : {
    1752                 :        8802 :   if (parent->symbolic_for_unknown_ptr_p ())
    1753                 :         320 :     return get_unknown_symbolic_region (type);
    1754                 :             : 
    1755                 :        8482 :   if (byte_size_sval->get_type () != size_type_node)
    1756                 :        2109 :     byte_size_sval = get_or_create_cast (size_type_node, byte_size_sval);
    1757                 :             : 
    1758                 :             :   /* If PARENT is already that size, return it.  */
    1759                 :        8482 :   const svalue *parent_byte_size_sval = parent->get_byte_size_sval (this);
    1760                 :        8482 :   if (tree parent_size_cst = parent_byte_size_sval->maybe_get_constant ())
    1761                 :        2648 :     if (tree size_cst = byte_size_sval->maybe_get_constant ())
    1762                 :             :       {
    1763                 :        2064 :         tree comparison
    1764                 :        2064 :           = fold_binary (EQ_EXPR, boolean_type_node, parent_size_cst, size_cst);
    1765                 :        2064 :         if (comparison == boolean_true_node)
    1766                 :             :           return parent;
    1767                 :             :       }
    1768                 :             : 
    1769                 :        7339 :   sized_region::key_t key (parent, type, byte_size_sval);
    1770                 :       11550 :   if (sized_region *reg = m_sized_regions.get (key))
    1771                 :             :     return reg;
    1772                 :             : 
    1773                 :        3128 :   sized_region *sized_reg
    1774                 :        3128 :     = new sized_region (alloc_symbol_id (), parent, type, byte_size_sval);
    1775                 :        3128 :   m_sized_regions.put (key, sized_reg);
    1776                 :        3128 :   return sized_reg;
    1777                 :             : }
    1778                 :             : 
    1779                 :             : /* Return the region that describes accessing PARENT_REGION as if
    1780                 :             :    it were of type TYPE, creating it if necessary.  */
    1781                 :             : 
    1782                 :             : const region *
    1783                 :       75555 : region_model_manager::get_cast_region (const region *original_region,
    1784                 :             :                                        tree type)
    1785                 :             : {
    1786                 :             :   /* If types match, return ORIGINAL_REGION.  */
    1787                 :       75555 :   if (type == original_region->get_type ())
    1788                 :             :     return original_region;
    1789                 :             : 
    1790                 :       21029 :   if (original_region->symbolic_for_unknown_ptr_p ())
    1791                 :          54 :     return get_unknown_symbolic_region (type);
    1792                 :             : 
    1793                 :       20975 :   cast_region::key_t key (original_region, type);
    1794                 :       39319 :   if (cast_region *reg = m_cast_regions.get (key))
    1795                 :             :     return reg;
    1796                 :             : 
    1797                 :        2631 :   cast_region *cast_reg
    1798                 :        2631 :     = new cast_region (alloc_symbol_id (), original_region, type);
    1799                 :        2631 :   m_cast_regions.put (key, cast_reg);
    1800                 :        2631 :   return cast_reg;
    1801                 :             : }
    1802                 :             : 
    1803                 :             : /* Return the frame_region for call to FUN from CALLING_FRAME, creating it
    1804                 :             :    if necessary.  CALLING_FRAME may be NULL.  */
    1805                 :             : 
    1806                 :             : const frame_region *
    1807                 :       33992 : region_model_manager::get_frame_region (const frame_region *calling_frame,
    1808                 :             :                                         const function &fun)
    1809                 :             : {
    1810                 :       33992 :   int index = calling_frame ? calling_frame->get_index () + 1 : 0;
    1811                 :             : 
    1812                 :       33992 :   frame_region::key_t key (calling_frame, fun);
    1813                 :       53575 :   if (frame_region *reg = m_frame_regions.get (key))
    1814                 :             :     return reg;
    1815                 :             : 
    1816                 :       14409 :   frame_region *frame_reg
    1817                 :             :     = new frame_region (alloc_symbol_id (), &m_stack_region, calling_frame,
    1818                 :       14409 :                          fun, index);
    1819                 :       14409 :   m_frame_regions.put (key, frame_reg);
    1820                 :       14409 :   return frame_reg;
    1821                 :             : }
    1822                 :             : 
    1823                 :             : /* Return the region that describes dereferencing SVAL, creating it
    1824                 :             :    if necessary.  */
    1825                 :             : 
    1826                 :             : const region *
    1827                 :       91624 : region_model_manager::get_symbolic_region (const svalue *sval)
    1828                 :             : {
    1829                 :       91624 :   symbolic_region::key_t key (&m_root_region, sval);
    1830                 :      174808 :   if (symbolic_region *reg = m_symbolic_regions.get (key))
    1831                 :             :     return reg;
    1832                 :             : 
    1833                 :        8440 :   symbolic_region *symbolic_reg
    1834                 :        8440 :     = new symbolic_region (alloc_symbol_id (), &m_root_region, sval);
    1835                 :        8440 :   m_symbolic_regions.put (key, symbolic_reg);
    1836                 :        8440 :   return symbolic_reg;
    1837                 :             : }
    1838                 :             : 
    1839                 :             : /* Return the region that describes accessing STRING_CST, creating it
    1840                 :             :    if necessary.  */
    1841                 :             : 
    1842                 :             : const string_region *
    1843                 :       17341 : region_model_manager::get_region_for_string (tree string_cst)
    1844                 :             : {
    1845                 :       17341 :   gcc_assert (TREE_CODE (string_cst) == STRING_CST);
    1846                 :             : 
    1847                 :       17341 :   string_region **slot = m_string_map.get (string_cst);
    1848                 :       17341 :   if (slot)
    1849                 :       13585 :     return *slot;
    1850                 :        3756 :   string_region *reg
    1851                 :        3756 :     = new string_region (alloc_symbol_id (), &m_root_region, string_cst);
    1852                 :        3756 :   m_string_map.put (string_cst, reg);
    1853                 :        3756 :   return reg;
    1854                 :             : }
    1855                 :             : 
    1856                 :             : /* Return the region that describes accessing BITS within PARENT as TYPE,
    1857                 :             :    creating it if necessary.  */
    1858                 :             : 
    1859                 :             : const region *
    1860                 :         242 : region_model_manager::get_bit_range (const region *parent, tree type,
    1861                 :             :                                      const bit_range &bits)
    1862                 :             : {
    1863                 :         242 :   gcc_assert (parent);
    1864                 :             : 
    1865                 :         242 :   if (parent->symbolic_for_unknown_ptr_p ())
    1866                 :           0 :     return get_unknown_symbolic_region (type);
    1867                 :             : 
    1868                 :         242 :   bit_range_region::key_t key (parent, type, bits);
    1869                 :         317 :   if (bit_range_region *reg = m_bit_range_regions.get (key))
    1870                 :             :     return reg;
    1871                 :             : 
    1872                 :         167 :   bit_range_region *bit_range_reg
    1873                 :         167 :     = new bit_range_region (alloc_symbol_id (), parent, type, bits);
    1874                 :         167 :   m_bit_range_regions.put (key, bit_range_reg);
    1875                 :         167 :   return bit_range_reg;
    1876                 :             : }
    1877                 :             : 
    1878                 :             : /* Return the region that describes accessing the IDX-th variadic argument
    1879                 :             :    within PARENT_FRAME, creating it if necessary.  */
    1880                 :             : 
    1881                 :             : const var_arg_region *
    1882                 :        1121 : region_model_manager::get_var_arg_region (const frame_region *parent_frame,
    1883                 :             :                                           unsigned idx)
    1884                 :             : {
    1885                 :        1121 :   gcc_assert (parent_frame);
    1886                 :             : 
    1887                 :        1121 :   var_arg_region::key_t key (parent_frame, idx);
    1888                 :        1763 :   if (var_arg_region *reg = m_var_arg_regions.get (key))
    1889                 :             :     return reg;
    1890                 :             : 
    1891                 :         479 :   var_arg_region *var_arg_reg
    1892                 :         479 :     = new var_arg_region (alloc_symbol_id (), parent_frame, idx);
    1893                 :         479 :   m_var_arg_regions.put (key, var_arg_reg);
    1894                 :         479 :   return var_arg_reg;
    1895                 :             : }
    1896                 :             : 
    1897                 :             : /* If we see a tree code we don't know how to handle, rather than
    1898                 :             :    ICE or generate bogus results, create a dummy region, and notify
    1899                 :             :    CTXT so that it can mark the new state as being not properly
    1900                 :             :    modelled.  The exploded graph can then stop exploring that path,
    1901                 :             :    since any diagnostics we might issue will have questionable
    1902                 :             :    validity.  */
    1903                 :             : 
    1904                 :             : const region *
    1905                 :          54 : region_model_manager::
    1906                 :             : get_region_for_unexpected_tree_code (region_model_context *ctxt,
    1907                 :             :                                      tree t,
    1908                 :             :                                      const dump_location_t &loc)
    1909                 :             : {
    1910                 :          54 :   tree type = TYPE_P (t) ? t : TREE_TYPE (t);
    1911                 :          54 :   region *new_reg
    1912                 :          54 :     = new unknown_region (alloc_symbol_id (), &m_root_region, type);
    1913                 :          54 :   if (ctxt)
    1914                 :          54 :     ctxt->on_unexpected_tree_code (t, loc);
    1915                 :          54 :   return new_reg;
    1916                 :             : }
    1917                 :             : 
    1918                 :             : /* Return a region describing a heap-allocated block of memory.
    1919                 :             :    Reuse an existing heap_allocated_region is its id is not within
    1920                 :             :    BASE_REGS_IN_USE.  */
    1921                 :             : 
    1922                 :             : const region *
    1923                 :       21076 : region_model_manager::
    1924                 :             : get_or_create_region_for_heap_alloc (const bitmap &base_regs_in_use)
    1925                 :             : {
    1926                 :             :   /* Try to reuse an existing region, if it's unreferenced in the
    1927                 :             :      client state.  */
    1928                 :       85632 :   for (auto existing_reg : m_managed_dynamic_regions)
    1929                 :       44070 :     if (!bitmap_bit_p (base_regs_in_use, existing_reg->get_id ()))
    1930                 :       19556 :       if (existing_reg->get_kind () == RK_HEAP_ALLOCATED)
    1931                 :             :         return existing_reg;
    1932                 :             : 
    1933                 :             :   /* All existing ones (if any) are in use; create a new one.  */
    1934                 :        1754 :   region *reg
    1935                 :        1754 :     = new heap_allocated_region (alloc_symbol_id (), &m_heap_region);
    1936                 :        1754 :   m_managed_dynamic_regions.safe_push (reg);
    1937                 :        1754 :   return reg;
    1938                 :             : }
    1939                 :             : 
    1940                 :             : /* Return a new region describing a block of memory allocated within FRAME.  */
    1941                 :             : 
    1942                 :             : const region *
    1943                 :        1105 : region_model_manager::create_region_for_alloca (const frame_region *frame)
    1944                 :             : {
    1945                 :        1105 :   gcc_assert (frame);
    1946                 :        1105 :   region *reg = new alloca_region (alloc_symbol_id (), frame);
    1947                 :        1105 :   m_managed_dynamic_regions.safe_push (reg);
    1948                 :        1105 :   return reg;
    1949                 :             : }
    1950                 :             : 
    1951                 :             : /* Log OBJ to LOGGER.  */
    1952                 :             : 
    1953                 :             : template <typename T>
    1954                 :             : static void
    1955                 :         110 : log_managed_object (logger *logger, const T *obj)
    1956                 :             : {
    1957                 :         110 :   logger->start_log_line ();
    1958                 :         110 :   pretty_printer *pp = logger->get_printer ();
    1959                 :         110 :   pp_string (pp, "    ");
    1960                 :         110 :   obj->dump_to_pp (pp, true);
    1961                 :         110 :   logger->end_log_line ();
    1962                 :         110 : }
    1963                 :             : 
    1964                 :             : /* Specialization for frame_region, which also logs the count of locals
    1965                 :             :    managed by the frame_region.  */
    1966                 :             : 
    1967                 :             : template <>
    1968                 :             : void
    1969                 :           2 : log_managed_object (logger *logger, const frame_region *obj)
    1970                 :             : {
    1971                 :           2 :   logger->start_log_line ();
    1972                 :           2 :   pretty_printer *pp = logger->get_printer ();
    1973                 :           2 :   pp_string (pp, "    ");
    1974                 :           2 :   obj->dump_to_pp (pp, true);
    1975                 :           2 :   pp_printf (pp, " [with %i region(s) for locals]", obj->get_num_locals ());
    1976                 :           2 :   logger->end_log_line ();
    1977                 :           2 : }
    1978                 :             : 
    1979                 :             : /* Dump the number of objects that were managed by UNIQ_MAP to LOGGER.
    1980                 :             :    If SHOW_OBJS is true, also dump the objects themselves.  */
    1981                 :             : 
    1982                 :             : template <typename K, typename T>
    1983                 :             : static void
    1984                 :          42 : log_uniq_map (logger *logger, bool show_objs, const char *title,
    1985                 :             :               const hash_map<K, T*> &uniq_map)
    1986                 :             : {
    1987                 :          42 :   logger->log ("  # %s: %li", title, (long)uniq_map.elements ());
    1988                 :          42 :   if (!show_objs)
    1989                 :           0 :     return;
    1990                 :          42 :   auto_vec<const T *> vec_objs (uniq_map.elements ());
    1991                 :          42 :   for (typename hash_map<K, T*>::iterator iter = uniq_map.begin ();
    1992                 :         172 :        iter != uniq_map.end (); ++iter)
    1993                 :          88 :     vec_objs.quick_push ((*iter).second);
    1994                 :             : 
    1995                 :         130 :   vec_objs.qsort (T::cmp_ptr_ptr);
    1996                 :             : 
    1997                 :             :   unsigned i;
    1998                 :             :   const T *obj;
    1999                 :         144 :   FOR_EACH_VEC_ELT (vec_objs, i, obj)
    2000                 :          88 :     log_managed_object<T> (logger, obj);
    2001                 :          42 : }
    2002                 :             : 
    2003                 :             : /* Dump the number of objects that were managed by MAP to LOGGER.
    2004                 :             :    If SHOW_OBJS is true, also dump the objects themselves.  */
    2005                 :             : 
    2006                 :             : template <typename T>
    2007                 :             : static void
    2008                 :          22 : log_uniq_map (logger *logger, bool show_objs, const char *title,
    2009                 :             :               const consolidation_map<T> &map)
    2010                 :             : {
    2011                 :          22 :   logger->log ("  # %s: %li", title, (long)map.elements ());
    2012                 :          22 :   if (!show_objs)
    2013                 :           0 :     return;
    2014                 :             : 
    2015                 :          22 :   auto_vec<const T *> vec_objs (map.elements ());
    2016                 :          22 :   for (typename consolidation_map<T>::iterator iter = map.begin ();
    2017                 :          67 :        iter != map.end (); ++iter)
    2018                 :          23 :     vec_objs.quick_push ((*iter).second);
    2019                 :             : 
    2020                 :          45 :   vec_objs.qsort (T::cmp_ptr_ptr);
    2021                 :             : 
    2022                 :             :   unsigned i;
    2023                 :             :   const T *obj;
    2024                 :          52 :   FOR_EACH_VEC_ELT (vec_objs, i, obj)
    2025                 :          23 :     log_managed_object<T> (logger, obj);
    2026                 :          22 : }
    2027                 :             : 
    2028                 :             : /* Dump the number of objects of each class that were managed by this
    2029                 :             :    manager to LOGGER.
    2030                 :             :    If SHOW_OBJS is true, also dump the objects themselves.  */
    2031                 :             : 
    2032                 :             : void
    2033                 :           2 : region_model_manager::log_stats (logger *logger, bool show_objs) const
    2034                 :             : {
    2035                 :           2 :   LOG_SCOPE (logger);
    2036                 :           2 :   logger->log ("call string consolidation");
    2037                 :           2 :   m_empty_call_string.recursive_log (logger);
    2038                 :           2 :   logger->log ("next symbol id: %i", m_next_symbol_id);
    2039                 :           2 :   logger->log ("svalue consolidation");
    2040                 :           2 :   log_uniq_map (logger, show_objs, "constant_svalue", m_constants_map);
    2041                 :           2 :   log_uniq_map (logger, show_objs, "unknown_svalue", m_unknowns_map);
    2042                 :           2 :   if (m_unknown_NULL)
    2043                 :           1 :     log_managed_object (logger, m_unknown_NULL);
    2044                 :           2 :   log_uniq_map (logger, show_objs, "poisoned_svalue", m_poisoned_values_map);
    2045                 :           2 :   log_uniq_map (logger, show_objs, "setjmp_svalue", m_setjmp_values_map);
    2046                 :           2 :   log_uniq_map (logger, show_objs, "initial_svalue", m_initial_values_map);
    2047                 :           2 :   log_uniq_map (logger, show_objs, "region_svalue", m_pointer_values_map);
    2048                 :           2 :   log_uniq_map (logger, show_objs, "unaryop_svalue", m_unaryop_values_map);
    2049                 :           2 :   log_uniq_map (logger, show_objs, "binop_svalue", m_binop_values_map);
    2050                 :           2 :   log_uniq_map (logger, show_objs, "sub_svalue", m_sub_values_map);
    2051                 :           2 :   log_uniq_map (logger, show_objs, "repeated_svalue", m_repeated_values_map);
    2052                 :           2 :   log_uniq_map (logger, show_objs, "bits_within_svalue",
    2053                 :           2 :                 m_bits_within_values_map);
    2054                 :           2 :   log_uniq_map (logger, show_objs, "unmergeable_svalue",
    2055                 :           2 :                 m_unmergeable_values_map);
    2056                 :           2 :   log_uniq_map (logger, show_objs, "widening_svalue", m_widening_values_map);
    2057                 :           2 :   log_uniq_map (logger, show_objs, "compound_svalue", m_compound_values_map);
    2058                 :           2 :   log_uniq_map (logger, show_objs, "conjured_svalue", m_conjured_values_map);
    2059                 :           2 :   log_uniq_map (logger, show_objs, "asm_output_svalue",
    2060                 :           2 :                 m_asm_output_values_map);
    2061                 :           2 :   log_uniq_map (logger, show_objs, "const_fn_result_svalue",
    2062                 :           2 :                 m_const_fn_result_values_map);
    2063                 :             : 
    2064                 :           2 :   logger->log ("max accepted svalue num_nodes: %i",
    2065                 :           2 :                m_max_complexity.m_num_nodes);
    2066                 :           2 :   logger->log ("max accepted svalue max_depth: %i",
    2067                 :           2 :                m_max_complexity.m_max_depth);
    2068                 :             : 
    2069                 :           2 :   logger->log ("region consolidation");
    2070                 :           2 :   log_uniq_map (logger, show_objs, "function_region", m_fndecls_map);
    2071                 :           2 :   log_uniq_map (logger, show_objs, "label_region", m_labels_map);
    2072                 :           2 :   log_uniq_map (logger, show_objs, "decl_region for globals", m_globals_map);
    2073                 :           2 :   log_uniq_map (logger, show_objs, "field_region", m_field_regions);
    2074                 :           2 :   log_uniq_map (logger, show_objs, "element_region", m_element_regions);
    2075                 :           2 :   log_uniq_map (logger, show_objs, "offset_region", m_offset_regions);
    2076                 :           2 :   log_uniq_map (logger, show_objs, "sized_region", m_sized_regions);
    2077                 :           2 :   log_uniq_map (logger, show_objs, "cast_region", m_cast_regions);
    2078                 :           2 :   log_uniq_map (logger, show_objs, "frame_region", m_frame_regions);
    2079                 :           2 :   log_uniq_map (logger, show_objs, "symbolic_region", m_symbolic_regions);
    2080                 :           2 :   log_uniq_map (logger, show_objs, "string_region", m_string_map);
    2081                 :           2 :   log_uniq_map (logger, show_objs, "bit_range_region", m_bit_range_regions);
    2082                 :           2 :   log_uniq_map (logger, show_objs, "var_arg_region", m_var_arg_regions);
    2083                 :           2 :   logger->log ("  # managed dynamic regions: %i",
    2084                 :             :                m_managed_dynamic_regions.length ());
    2085                 :           2 :   m_store_mgr.log_stats (logger, show_objs);
    2086                 :           2 :   m_range_mgr->log_stats (logger, show_objs);
    2087                 :           2 : }
    2088                 :             : 
    2089                 :             : /* Dump the number of objects of each class that were managed by this
    2090                 :             :    manager to LOGGER.
    2091                 :             :    If SHOW_OBJS is true, also dump the objects themselves.
    2092                 :             :    This is here so it can use log_uniq_map.  */
    2093                 :             : 
    2094                 :             : void
    2095                 :           2 : store_manager::log_stats (logger *logger, bool show_objs) const
    2096                 :             : {
    2097                 :           2 :   LOG_SCOPE (logger);
    2098                 :           2 :   log_uniq_map (logger, show_objs, "concrete_binding",
    2099                 :           2 :                 m_concrete_binding_key_mgr);
    2100                 :           2 :   log_uniq_map (logger, show_objs, "symbolic_binding",
    2101                 :           2 :                 m_symbolic_binding_key_mgr);
    2102                 :           2 : }
    2103                 :             : 
    2104                 :             : /* Emit a warning showing DECL_REG->tracked_p () for use in DejaGnu tests
    2105                 :             :    (using -fdump-analyzer-untracked).  */
    2106                 :             : 
    2107                 :             : static void
    2108                 :         163 : dump_untracked_region (const decl_region *decl_reg)
    2109                 :             : {
    2110                 :         163 :   tree decl = decl_reg->get_decl ();
    2111                 :         163 :   if (TREE_CODE (decl) != VAR_DECL)
    2112                 :             :     return;
    2113                 :             :   /* For now, don't emit the status of decls in the constant pool, to avoid
    2114                 :             :      differences in DejaGnu test results between targets that use these vs
    2115                 :             :      those that don't.
    2116                 :             :      (Eventually these decls should probably be untracked and we should test
    2117                 :             :      for that, but that's not stage 4 material).  */
    2118                 :          56 :   if (DECL_IN_CONSTANT_POOL (decl))
    2119                 :             :     return;
    2120                 :          85 :   warning_at (DECL_SOURCE_LOCATION (decl), 0,
    2121                 :             :               "track %qD: %s",
    2122                 :          56 :               decl, (decl_reg->tracked_p () ? "yes" : "no"));
    2123                 :             : }
    2124                 :             : 
    2125                 :             : /* Implementation of -fdump-analyzer-untracked.  */
    2126                 :             : 
    2127                 :             : void
    2128                 :          23 : region_model_manager::dump_untracked_regions () const
    2129                 :             : {
    2130                 :          74 :   for (auto iter : m_globals_map)
    2131                 :             :     {
    2132                 :          51 :       const decl_region *decl_reg = iter.second;
    2133                 :          51 :       dump_untracked_region (decl_reg);
    2134                 :             :     }
    2135                 :          75 :   for (auto frame_iter : m_frame_regions)
    2136                 :             :     {
    2137                 :          52 :       const frame_region *frame_reg = frame_iter.second;
    2138                 :          52 :       frame_reg->dump_untracked_regions ();
    2139                 :             :     }
    2140                 :          23 : }
    2141                 :             : 
    2142                 :             : void
    2143                 :          52 : frame_region::dump_untracked_regions () const
    2144                 :             : {
    2145                 :         164 :   for (auto iter : m_locals)
    2146                 :             :     {
    2147                 :         112 :       const decl_region *decl_reg = iter.second;
    2148                 :         112 :       dump_untracked_region (decl_reg);
    2149                 :             :     }
    2150                 :          52 : }
    2151                 :             : 
    2152                 :             : } // namespace ana
    2153                 :             : 
    2154                 :             : #endif /* #if ENABLE_ANALYZER */
        

Generated by: LCOV version 2.1-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.