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