LCOV - code coverage report
Current view: top level - gcc/analyzer - region-model-manager.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.9 % 1073 1050
Test Date: 2026-05-30 15:37:04 Functions: 92.4 % 131 121
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.