LCOV - code coverage report
Current view: top level - gcc - gimple-array-bounds.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.5 % 392 343
Test Date: 2024-12-21 13:15:12 Functions: 94.4 % 18 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Array bounds checking.
       2                 :             :    Copyright (C) 2005-2024 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify
       7                 :             : it under the terms of the GNU General Public License as published by
       8                 :             : the Free Software Foundation; either version 3, or (at your option)
       9                 :             : any later version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful,
      12                 :             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :             : GNU General Public License for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : #include "config.h"
      21                 :             : #include "system.h"
      22                 :             : #include "coretypes.h"
      23                 :             : #include "backend.h"
      24                 :             : #include "tree.h"
      25                 :             : #include "gimple.h"
      26                 :             : #include "ssa.h"
      27                 :             : #include "pointer-query.h"
      28                 :             : #include "gimple-array-bounds.h"
      29                 :             : #include "gimple-iterator.h"
      30                 :             : #include "gimple-walk.h"
      31                 :             : #include "tree-dfa.h"
      32                 :             : #include "fold-const.h"
      33                 :             : #include "diagnostic-core.h"
      34                 :             : #include "intl.h"
      35                 :             : #include "tree-vrp.h"
      36                 :             : #include "alloc-pool.h"
      37                 :             : #include "vr-values.h"
      38                 :             : #include "domwalk.h"
      39                 :             : #include "tree-cfg.h"
      40                 :             : #include "attribs.h"
      41                 :             : #include "tree-pass.h"
      42                 :             : #include "gimple-range.h"
      43                 :             : 
      44                 :             : // Always use the current range query for the bounds checker.
      45                 :      107837 : array_bounds_checker::array_bounds_checker (struct function *func)
      46                 :      215674 :   : fun (func), m_ptr_qry (get_range_query (func))
      47                 :             : {
      48                 :             :   /* No-op.  */
      49                 :      107837 : }
      50                 :             : 
      51                 :             : void
      52                 :      133681 : array_bounds_checker::get_value_range (irange &r, const_tree op, gimple *stmt)
      53                 :             : {
      54                 :      133681 :   if (m_ptr_qry.rvals->range_of_expr (r, const_cast<tree> (op), stmt))
      55                 :             :     return;
      56                 :           0 :   r.set_varying (TREE_TYPE (op));
      57                 :             : }
      58                 :             : 
      59                 :             : /* Try to determine the DECL that REF refers to.  Return the DECL or
      60                 :             :    the expression closest to it.  Used in informational notes pointing
      61                 :             :    to referenced objects or function parameters.  */
      62                 :             : 
      63                 :             : static tree
      64                 :      164526 : get_base_decl (tree ref)
      65                 :             : {
      66                 :      164526 :   tree base = get_base_address (ref);
      67                 :      164526 :   if (DECL_P (base))
      68                 :             :     return base;
      69                 :             : 
      70                 :       14881 :   if (TREE_CODE (base) == MEM_REF)
      71                 :       14420 :     base = TREE_OPERAND (base, 0);
      72                 :             : 
      73                 :       14881 :   if (TREE_CODE (base) != SSA_NAME)
      74                 :             :     return base;
      75                 :             : 
      76                 :       14459 :   do
      77                 :             :     {
      78                 :       14459 :       gimple *def = SSA_NAME_DEF_STMT (base);
      79                 :       14459 :       if (gimple_assign_single_p (def))
      80                 :             :         {
      81                 :        1954 :           base = gimple_assign_rhs1 (def);
      82                 :        1954 :           return base;
      83                 :             :         }
      84                 :             : 
      85                 :       12505 :       if (!gimple_nop_p (def))
      86                 :             :         return base;
      87                 :             : 
      88                 :        8279 :       break;
      89                 :             :     } while (true);
      90                 :             : 
      91                 :        8279 :   tree var = SSA_NAME_VAR (base);
      92                 :        8279 :   if (TREE_CODE (var) != PARM_DECL)
      93                 :           0 :     return base;
      94                 :             : 
      95                 :             :   return var;
      96                 :             : }
      97                 :             : 
      98                 :             : /* Return the constant byte size of the object or type referenced by
      99                 :             :    the MEM_REF ARG.  On success, set *PREF to the DECL or expression
     100                 :             :    ARG refers to.  Otherwise return null.  */
     101                 :             : 
     102                 :             : static tree
     103                 :       65604 : get_ref_size (tree arg, tree *pref)
     104                 :             : {
     105                 :       65604 :   if (TREE_CODE (arg) != MEM_REF)
     106                 :             :     return NULL_TREE;
     107                 :             : 
     108                 :       65604 :   arg = TREE_OPERAND (arg, 0);
     109                 :       65604 :   tree type = TREE_TYPE (arg);
     110                 :       65604 :   if (!POINTER_TYPE_P (type))
     111                 :             :     return NULL_TREE;
     112                 :             : 
     113                 :       65604 :   type = TREE_TYPE (type);
     114                 :       65604 :   if (TREE_CODE (type) != ARRAY_TYPE)
     115                 :             :     return NULL_TREE;
     116                 :             : 
     117                 :         563 :   tree nbytes = TYPE_SIZE_UNIT (type);
     118                 :         563 :   if (!nbytes || TREE_CODE (nbytes) != INTEGER_CST)
     119                 :             :     return NULL_TREE;
     120                 :             : 
     121                 :          39 :   *pref = get_base_decl (arg);
     122                 :          39 :   return nbytes;
     123                 :             : }
     124                 :             : 
     125                 :             : /* Return true if REF is (likely) an ARRAY_REF to a trailing array member
     126                 :             :    of a struct.  It refines array_ref_flexible_size_p by detecting a pointer
     127                 :             :    to an array and an array parameter declared using the [N] syntax (as
     128                 :             :    opposed to a pointer) and returning false.  Set *PREF to the decl or
     129                 :             :    expression REF refers to.  */
     130                 :             : 
     131                 :             : static bool
     132                 :      164487 : trailing_array (tree arg, tree *pref)
     133                 :             : {
     134                 :      164487 :   tree ref = arg;
     135                 :      164487 :   tree base = get_base_decl (arg);
     136                 :      500298 :   while (TREE_CODE (ref) == ARRAY_REF || TREE_CODE (ref) == MEM_REF)
     137                 :      171324 :     ref = TREE_OPERAND (ref, 0);
     138                 :             : 
     139                 :      164487 :   if (TREE_CODE (ref) == COMPONENT_REF)
     140                 :             :     {
     141                 :       37414 :       *pref = TREE_OPERAND (ref, 1);
     142                 :       37414 :       tree type = TREE_TYPE (*pref);
     143                 :       37414 :       if (TREE_CODE (type) == ARRAY_TYPE)
     144                 :             :         {
     145                 :             :           /* A multidimensional trailing array is not considered special
     146                 :             :              no matter what its major bound is.  */
     147                 :       37414 :           type = TREE_TYPE (type);
     148                 :       37414 :           if (TREE_CODE (type) == ARRAY_TYPE)
     149                 :             :             return false;
     150                 :             :         }
     151                 :             :     }
     152                 :             :   else
     153                 :      127073 :     *pref = base;
     154                 :             : 
     155                 :      160531 :   tree basetype = TREE_TYPE (base);
     156                 :      160531 :   if (TREE_CODE (base) == PARM_DECL
     157                 :       11377 :       && POINTER_TYPE_P (basetype))
     158                 :             :     {
     159                 :        7755 :       tree ptype = TREE_TYPE (basetype);
     160                 :        7755 :       if (TREE_CODE (ptype) == ARRAY_TYPE)
     161                 :             :         return false;
     162                 :             :     }
     163                 :             : 
     164                 :      160306 :   return array_ref_flexible_size_p (arg);
     165                 :             : }
     166                 :             : 
     167                 :             : /* Acquire the upper bound and upper bound plus one for the array
     168                 :             :    reference REF and record them into UP_BOUND and UP_BOUND_P1.
     169                 :             :    Set *DECL to the decl or expresssion REF refers to.  */
     170                 :             : 
     171                 :             : static void
     172                 :      238380 : get_up_bounds_for_array_ref (tree ref, tree *decl,
     173                 :             :                              tree *up_bound, tree *up_bound_p1)
     174                 :             : {
     175                 :      238380 :   if (!(*up_bound)
     176                 :      165930 :       || TREE_CODE (*up_bound) != INTEGER_CST
     177                 :      402867 :       || trailing_array (ref, decl))
     178                 :             :     {
     179                 :             :       /* Accesses to trailing arrays via pointers may access storage
     180                 :             :          beyond the types array bounds.  For such arrays, or for flexible
     181                 :             :          array members, as well as for other arrays of an unknown size,
     182                 :             :          replace the upper bound with a more permissive one that assumes
     183                 :             :          the size of the largest object is PTRDIFF_MAX.  */
     184                 :       80870 :       tree eltsize = array_ref_element_size (ref);
     185                 :             : 
     186                 :       80870 :       if (TREE_CODE (eltsize) != INTEGER_CST
     187                 :       80870 :           || integer_zerop (eltsize))
     188                 :             :         {
     189                 :         577 :           *up_bound = NULL_TREE;
     190                 :         577 :           *up_bound_p1 = NULL_TREE;
     191                 :             :         }
     192                 :             :       else
     193                 :             :         {
     194                 :       80293 :           tree ptrdiff_max = TYPE_MAX_VALUE (ptrdiff_type_node);
     195                 :       80293 :           tree maxbound = ptrdiff_max;
     196                 :       80293 :           tree arg = TREE_OPERAND (ref, 0);
     197                 :             : 
     198                 :       80293 :           const bool compref = TREE_CODE (arg) == COMPONENT_REF;
     199                 :       80293 :           if (compref)
     200                 :             :             {
     201                 :             :               /* Try to determine the size of the trailing array from
     202                 :             :                  its initializer (if it has one).  */
     203                 :       71548 :               if (tree refsize = component_ref_size (arg))
     204                 :        6458 :                 if (TREE_CODE (refsize) == INTEGER_CST)
     205                 :       80293 :                   maxbound = refsize;
     206                 :             :             }
     207                 :             : 
     208                 :       80293 :           if (maxbound == ptrdiff_max)
     209                 :             :             {
     210                 :             :               /* Try to determine the size of the base object.  Avoid
     211                 :             :                  COMPONENT_REF already tried above.  Using its DECL_SIZE
     212                 :             :                  size wouldn't necessarily be correct if the reference is
     213                 :             :                  to its flexible array member initialized in a different
     214                 :             :                  translation unit.  */
     215                 :       73838 :               poly_int64 off;
     216                 :       73838 :               if (tree base = get_addr_base_and_unit_offset (arg, &off))
     217                 :             :                 {
     218                 :       73530 :                   if (TREE_CODE (base) == MEM_REF)
     219                 :             :                     {
     220                 :             :                       /* Try to determine the size from a pointer to
     221                 :             :                          an array if BASE is one.  */
     222                 :       65604 :                       if (tree size = get_ref_size (base, decl))
     223                 :       73530 :                         maxbound = size;
     224                 :             :                     }
     225                 :        7926 :                   else if (!compref && DECL_P (base))
     226                 :        7884 :                     if (tree basesize = DECL_SIZE_UNIT (base))
     227                 :         128 :                       if (TREE_CODE (basesize) == INTEGER_CST)
     228                 :             :                         {
     229                 :         128 :                           maxbound = basesize;
     230                 :         128 :                           *decl = base;
     231                 :             :                         }
     232                 :             : 
     233                 :       73530 :                   if (known_gt (off, 0))
     234                 :       64897 :                     maxbound = wide_int_to_tree (sizetype,
     235                 :      129794 :                                                  wi::sub (wi::to_wide (maxbound),
     236                 :             :                                                           off));
     237                 :             :                 }
     238                 :             :             }
     239                 :             :           else
     240                 :        6455 :             maxbound = fold_convert (sizetype, maxbound);
     241                 :             : 
     242                 :       80293 :           *up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
     243                 :             : 
     244                 :       80293 :           if (*up_bound_p1 != NULL_TREE)
     245                 :       80293 :             *up_bound = int_const_binop (MINUS_EXPR, *up_bound_p1,
     246                 :      160586 :                                         build_int_cst (ptrdiff_type_node, 1));
     247                 :             :           else
     248                 :           0 :             *up_bound = NULL_TREE;
     249                 :             :         }
     250                 :             :     }
     251                 :             :   else
     252                 :      157510 :     *up_bound_p1 = int_const_binop (PLUS_EXPR, *up_bound,
     253                 :      315020 :                                    build_int_cst (TREE_TYPE (*up_bound), 1));
     254                 :      238380 :   return;
     255                 :             : }
     256                 :             : 
     257                 :             : /* Given the LOW_SUB_ORG, LOW_SUB and UP_SUB, and the computed UP_BOUND
     258                 :             :    and UP_BOUND_P1, check whether the array reference REF is out of bound.
     259                 :             :    When out of bounds, set OUT_OF_BOUND to true.
     260                 :             :    Issue warnings if FOR_ARRAY_BOUND is true.
     261                 :             :    return TRUE if warnings are issued.  */
     262                 :             : 
     263                 :             : static bool
     264                 :      238380 : check_out_of_bounds_and_warn (location_t location, tree ref,
     265                 :             :                               tree low_sub_org, tree low_sub, tree up_sub,
     266                 :             :                               tree up_bound, tree up_bound_p1,
     267                 :             :                               const irange *vr,
     268                 :             :                               bool ignore_off_by_one, bool for_array_bound,
     269                 :             :                               bool *out_of_bound)
     270                 :             : {
     271                 :      238380 :   tree min, max;
     272                 :      238380 :   tree low_bound = array_ref_low_bound (ref);
     273                 :      238380 :   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
     274                 :             : 
     275                 :      238380 :   bool warned = false;
     276                 :      238380 :   *out_of_bound = false;
     277                 :             : 
     278                 :             :   /* Empty array.  */
     279                 :      238380 :   if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
     280                 :             :     {
     281                 :         225 :       *out_of_bound = true;
     282                 :         225 :       if (for_array_bound)
     283                 :         224 :         warned = warning_at (location, OPT_Warray_bounds_,
     284                 :             :                              "array subscript %E is outside array"
     285                 :             :                              " bounds of %qT", low_sub_org, artype);
     286                 :             :     }
     287                 :             : 
     288                 :         224 :   if (warned)
     289                 :             :     ; /* Do nothing.  */
     290                 :      238156 :   else if (get_legacy_range (*vr, min, max) == VR_ANTI_RANGE)
     291                 :             :     {
     292                 :        1229 :       if (up_bound
     293                 :        1229 :           && TREE_CODE (up_sub) == INTEGER_CST
     294                 :          88 :           && (ignore_off_by_one
     295                 :        1229 :               ? tree_int_cst_lt (up_bound, up_sub)
     296                 :        1141 :               : tree_int_cst_le (up_bound, up_sub))
     297                 :         701 :           && TREE_CODE (low_sub) == INTEGER_CST
     298                 :        3159 :           && tree_int_cst_le (low_sub, low_bound))
     299                 :             :         {
     300                 :           2 :           *out_of_bound = true;
     301                 :           2 :           if (for_array_bound)
     302                 :           2 :             warned = warning_at (location, OPT_Warray_bounds_,
     303                 :             :                                  "array subscript [%E, %E] is outside "
     304                 :             :                                  "array bounds of %qT",
     305                 :             :                                  low_sub, up_sub, artype);
     306                 :             :         }
     307                 :             :     }
     308                 :      236927 :   else if (up_bound
     309                 :      236350 :            && TREE_CODE (up_sub) == INTEGER_CST
     310                 :      477801 :            && (ignore_off_by_one
     311                 :      232377 :                ? !tree_int_cst_le (up_sub, up_bound_p1)
     312                 :      223880 :                : !tree_int_cst_le (up_sub, up_bound)))
     313                 :             :     {
     314                 :         644 :       *out_of_bound = true;
     315                 :         644 :       if (for_array_bound)
     316                 :         639 :         warned = warning_at (location, OPT_Warray_bounds_,
     317                 :             :                              "array subscript %E is above array bounds of %qT",
     318                 :             :                              up_sub, artype);
     319                 :             :     }
     320                 :      236283 :   else if (TREE_CODE (low_sub) == INTEGER_CST
     321                 :      236283 :            && tree_int_cst_lt (low_sub, low_bound))
     322                 :             :     {
     323                 :         263 :       *out_of_bound = true;
     324                 :         263 :       if (for_array_bound)
     325                 :         263 :         warned = warning_at (location, OPT_Warray_bounds_,
     326                 :             :                              "array subscript %E is below array bounds of %qT",
     327                 :             :                              low_sub, artype);
     328                 :             :     }
     329                 :      238380 :   return warned;
     330                 :             : }
     331                 :             : 
     332                 :             : /* Checks one ARRAY_REF in REF, located at LOCUS.  Ignores flexible
     333                 :             :    arrays and "struct" hacks.  If VRP can determine that the array
     334                 :             :    subscript is a constant, check if it is outside valid range.  If
     335                 :             :    the array subscript is a RANGE, warn if it is non-overlapping with
     336                 :             :    valid range.  IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside
     337                 :             :    a ADDR_EXPR.  Return  true if a warning has been issued or if
     338                 :             :    no-warning is set.  */
     339                 :             : 
     340                 :             : bool
     341                 :      238467 : array_bounds_checker::check_array_ref (location_t location, tree ref,
     342                 :             :                                        gimple *stmt, bool ignore_off_by_one)
     343                 :             : {
     344                 :      238467 :   if (warning_suppressed_p (ref, OPT_Warray_bounds_))
     345                 :             :     /* Return true to have the caller prevent warnings for enclosing
     346                 :             :        refs.  */
     347                 :             :     return true;
     348                 :             : 
     349                 :             :   /* Upper bound and Upper bound plus one for -Warray-bounds.  */
     350                 :      238380 :   tree up_bound = array_ref_up_bound (ref);
     351                 :      238380 :   tree up_bound_p1 = NULL_TREE;
     352                 :             : 
     353                 :             :   /* Referenced decl if one can be determined.  */
     354                 :      238380 :   tree decl = NULL_TREE;
     355                 :             : 
     356                 :             :   /* Set to the type of the special array member for a COMPONENT_REF.  */
     357                 :      238380 :   special_array_member sam{ };
     358                 :      238380 :   tree afield_decl = NULL_TREE;
     359                 :      238380 :   tree arg = TREE_OPERAND (ref, 0);
     360                 :             : 
     361                 :      238380 :   if (TREE_CODE (arg) == COMPONENT_REF)
     362                 :             :     {
     363                 :             :       /* Try to determine special array member type for this COMPONENT_REF.  */
     364                 :      100130 :       sam = component_ref_sam_type (arg);
     365                 :      100130 :       afield_decl = TREE_OPERAND (arg, 1);
     366                 :             :     }
     367                 :             : 
     368                 :      238380 :   get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
     369                 :             : 
     370                 :      238380 :   bool warned = false;
     371                 :      238380 :   bool out_of_bound = false;
     372                 :             : 
     373                 :      238380 :   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
     374                 :      238380 :   tree low_sub_org = TREE_OPERAND (ref, 1);
     375                 :      238380 :   tree up_sub = low_sub_org;
     376                 :      238380 :   tree low_sub = low_sub_org;
     377                 :             : 
     378                 :      238380 :   int_range_max vr;
     379                 :      238380 :   if (TREE_CODE (low_sub_org) == SSA_NAME)
     380                 :             :     {
     381                 :      133681 :       get_value_range (vr, low_sub_org, stmt);
     382                 :      133681 :       if (!vr.undefined_p () && !vr.varying_p ())
     383                 :             :         {
     384                 :      129655 :           tree min, max;
     385                 :      129655 :           value_range_kind kind = get_legacy_range (vr, min, max);
     386                 :      129655 :           low_sub = kind == VR_RANGE ? max : min;
     387                 :      129655 :           up_sub = kind == VR_RANGE ? min : max;
     388                 :             :         }
     389                 :             :     }
     390                 :             : 
     391                 :      476760 :   warned = check_out_of_bounds_and_warn (location, ref,
     392                 :             :                                          low_sub_org, low_sub, up_sub,
     393                 :             :                                          up_bound, up_bound_p1, &vr,
     394                 :      238380 :                                          ignore_off_by_one, warn_array_bounds,
     395                 :             :                                          &out_of_bound);
     396                 :             : 
     397                 :             : 
     398                 :      238380 :   if (!warned && sam == special_array_member::int_0)
     399                 :          39 :     warned = warning_at (location, OPT_Wzero_length_bounds,
     400                 :          39 :                          (TREE_CODE (low_sub) == INTEGER_CST
     401                 :             :                           ? G_("array subscript %E is outside the bounds "
     402                 :             :                                "of an interior zero-length array %qT")
     403                 :             :                           : G_("array subscript %qE is outside the bounds "
     404                 :             :                                "of an interior zero-length array %qT")),
     405                 :             :                          low_sub, artype);
     406                 :             : 
     407                 :      238380 :   if (warned && dump_file && (dump_flags & TDF_DETAILS))
     408                 :             :     {
     409                 :           0 :       fprintf (dump_file, "Array bound warning for ");
     410                 :           0 :       dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
     411                 :           0 :       fprintf (dump_file, "\n");
     412                 :             :     }
     413                 :             : 
     414                 :             :    /* Issue warnings for -Wstrict-flex-arrays according to the level of
     415                 :             :       flag_strict_flex_arrays.  */
     416                 :        1134 :   if (out_of_bound && warn_strict_flex_arrays
     417                 :          18 :       && (sam == special_array_member::trail_0
     418                 :             :           || sam == special_array_member::trail_1
     419                 :          18 :           || sam == special_array_member::trail_n)
     420                 :      238398 :       && DECL_NOT_FLEXARRAY (afield_decl))
     421                 :             :     {
     422                 :          18 :       bool warned1
     423                 :          18 :         = warning_at (location, OPT_Wstrict_flex_arrays,
     424                 :             :                       "trailing array %qT should not be used as "
     425                 :             :                       "a flexible array member",
     426                 :             :                       artype);
     427                 :             : 
     428                 :          18 :       if (warned1 && dump_file && (dump_flags & TDF_DETAILS))
     429                 :             :         {
     430                 :           0 :           fprintf (dump_file, "Trailing non flexible-like array bound warning for ");
     431                 :           0 :           dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
     432                 :           0 :           fprintf (dump_file, "\n");
     433                 :             :         }
     434                 :          18 :       warned |= warned1;
     435                 :             :     }
     436                 :             : 
     437                 :      238380 :   if (warned)
     438                 :             :     {
     439                 :             :       /* Avoid more warnings when checking more significant subscripts
     440                 :             :          of the same expression.  */
     441                 :        1171 :       ref = TREE_OPERAND (ref, 0);
     442                 :        1171 :       suppress_warning (ref, OPT_Warray_bounds_);
     443                 :        1171 :       suppress_warning (ref, OPT_Wstrict_flex_arrays);
     444                 :             : 
     445                 :        1171 :       if (decl)
     446                 :         789 :         ref = decl;
     447                 :             : 
     448                 :        1171 :       tree rec = NULL_TREE;
     449                 :        1171 :       if (TREE_CODE (ref) == COMPONENT_REF)
     450                 :             :         {
     451                 :             :           /* For a reference to a member of a struct object also mention
     452                 :             :              the object if it's known.  It may be defined in a different
     453                 :             :              function than the out-of-bounds access.  */
     454                 :         257 :           rec = TREE_OPERAND (ref, 0);
     455                 :         257 :           if (!VAR_P (rec))
     456                 :         185 :             rec = NULL_TREE;
     457                 :         257 :           ref = TREE_OPERAND (ref, 1);
     458                 :             :         }
     459                 :             : 
     460                 :        1171 :       if (DECL_P (ref))
     461                 :        1071 :         inform (DECL_SOURCE_LOCATION (ref), "while referencing %qD", ref);
     462                 :        1171 :       if (rec && DECL_P (rec))
     463                 :          72 :         inform (DECL_SOURCE_LOCATION (rec), "defined here %qD", rec);
     464                 :             :     }
     465                 :             : 
     466                 :      238380 :   return warned;
     467                 :      238380 : }
     468                 :             : 
     469                 :             : /* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
     470                 :             :    references to string constants.  If VRP can determine that the array
     471                 :             :    subscript is a constant, check if it is outside valid range.
     472                 :             :    If the array subscript is a RANGE, warn if it is non-overlapping
     473                 :             :    with valid range.
     474                 :             :    IGNORE_OFF_BY_ONE is true if the MEM_REF is inside an ADDR_EXPR
     475                 :             :    (used to allow one-past-the-end indices for code that takes
     476                 :             :    the address of the just-past-the-end element of an array).
     477                 :             :    Returns true if a warning has been issued.  */
     478                 :             : 
     479                 :             : bool
     480                 :      614037 : array_bounds_checker::check_mem_ref (location_t location, tree ref,
     481                 :             :                                      bool ignore_off_by_one)
     482                 :             : {
     483                 :      614037 :   if (warning_suppressed_p (ref, OPT_Warray_bounds_))
     484                 :             :     return false;
     485                 :             : 
     486                 :             :   /* The statement used to allocate the array or null.  */
     487                 :      613964 :   gimple *alloc_stmt = NULL;
     488                 :             :   /* For an allocation statement, the low bound of the size range.  */
     489                 :      613964 :   offset_int minbound = 0;
     490                 :             :   /* The type and size of the access.  */
     491                 :      613964 :   tree axstype = TREE_TYPE (ref);
     492                 :      613964 :   offset_int axssize = 0;
     493                 :      613964 :   if (tree access_size = TYPE_SIZE_UNIT (axstype))
     494                 :      613175 :     if (TREE_CODE (access_size) == INTEGER_CST)
     495                 :      612311 :       axssize = wi::to_offset (access_size);
     496                 :             : 
     497                 :      613964 :   access_ref aref;
     498                 :      613964 :   if (!m_ptr_qry.get_ref (ref, m_stmt, &aref, 0))
     499                 :             :     return false;
     500                 :             : 
     501                 :      613960 :   if (aref.offset_in_range (axssize))
     502                 :             :     return false;
     503                 :             : 
     504                 :       10716 :   if (TREE_CODE (aref.ref) == SSA_NAME)
     505                 :             :     {
     506                 :         525 :       gimple *def = SSA_NAME_DEF_STMT (aref.ref);
     507                 :         525 :       if (is_gimple_call (def))
     508                 :             :         {
     509                 :             :           /* Save the allocation call and the low bound on the size.  */
     510                 :         488 :           alloc_stmt = def;
     511                 :         488 :           minbound = aref.sizrng[0];
     512                 :             :         }
     513                 :             :     }
     514                 :             : 
     515                 :             :   /* The range of the byte offset into the reference.  Adjusted below.  */
     516                 :       10716 :   offset_int offrange[2] = { aref.offrng[0], aref.offrng[1] };
     517                 :             : 
     518                 :             :   /* The type of the referenced object.  */
     519                 :       10716 :   tree reftype = TREE_TYPE (aref.ref);
     520                 :             :   /* The size of the referenced array element.  */
     521                 :       10716 :   offset_int eltsize = 1;
     522                 :       10716 :   if (POINTER_TYPE_P (reftype))
     523                 :         546 :     reftype = TREE_TYPE (reftype);
     524                 :             : 
     525                 :       10716 :   if (TREE_CODE (reftype) == FUNCTION_TYPE)
     526                 :             :     /* Restore the original (pointer) type and avoid trying to create
     527                 :             :        an array of functions (done below).  */
     528                 :           9 :     reftype = TREE_TYPE (aref.ref);
     529                 :             :   else
     530                 :             :     {
     531                 :             :       /* The byte size of the array has already been determined above
     532                 :             :          based on a pointer ARG.  Set ELTSIZE to the size of the type
     533                 :             :          it points to and REFTYPE to the array with the size, rounded
     534                 :             :          down as necessary.  */
     535                 :       10707 :       if (TREE_CODE (reftype) == ARRAY_TYPE)
     536                 :        9894 :         reftype = TREE_TYPE (reftype);
     537                 :       10707 :       if (tree refsize = TYPE_SIZE_UNIT (reftype))
     538                 :       10707 :         if (TREE_CODE (refsize) == INTEGER_CST)
     539                 :       10691 :           eltsize = wi::to_offset (refsize);
     540                 :             : 
     541                 :       10707 :       const offset_int nelts = aref.sizrng[1] / eltsize;
     542                 :       10707 :       reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
     543                 :             :     }
     544                 :             : 
     545                 :             :   /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
     546                 :             :      is set (when taking the address of the one-past-last element
     547                 :             :      of an array) but always use the stricter bound in diagnostics. */
     548                 :       10716 :   offset_int ubound = aref.sizrng[1];
     549                 :       10716 :   if (ignore_off_by_one)
     550                 :        9575 :     ubound += eltsize;
     551                 :             : 
     552                 :             :   /* Set if the lower bound of the subscript is out of bounds.  */
     553                 :       10716 :   const bool lboob = (aref.sizrng[1] == 0
     554                 :       10491 :                       || offrange[0] >= ubound
     555                 :       20858 :                       || offrange[1] < 0);
     556                 :             :   /* Set if only the upper bound of the subscript is out of bounds.
     557                 :             :      This can happen when using a bigger type to index into an array
     558                 :             :      of a smaller type, as is common with unsigned char.  */
     559                 :       10716 :   const bool uboob = !lboob && offrange[0] + axssize > ubound;
     560                 :       10716 :   if (lboob || uboob)
     561                 :             :     {
     562                 :             :       /* Treat a reference to a non-array object as one to an array
     563                 :             :          of a single element.  */
     564                 :       10014 :       if (TREE_CODE (reftype) != ARRAY_TYPE)
     565                 :           9 :         reftype = build_printable_array_type (reftype, 1);
     566                 :             : 
     567                 :             :       /* Extract the element type out of MEM_REF and use its size
     568                 :             :          to compute the index to print in the diagnostic; arrays
     569                 :             :          in MEM_REF don't mean anything.  A type with no size like
     570                 :             :          void is as good as having a size of 1.  */
     571                 :       10014 :       tree type = strip_array_types (TREE_TYPE (ref));
     572                 :       10014 :       if (tree size = TYPE_SIZE_UNIT (type))
     573                 :             :         {
     574                 :       10013 :           offrange[0] = offrange[0] / wi::to_offset (size);
     575                 :       10013 :           offrange[1] = offrange[1] / wi::to_offset (size);
     576                 :             :         }
     577                 :             :     }
     578                 :             : 
     579                 :       19962 :   bool warned = false;
     580                 :       10014 :   if (lboob)
     581                 :             :     {
     582                 :         768 :       if (offrange[0] == offrange[1])
     583                 :         654 :         warned = warning_at (location, OPT_Warray_bounds_,
     584                 :             :                              "array subscript %wi is outside array bounds "
     585                 :             :                              "of %qT",
     586                 :             :                              offrange[0].to_shwi (), reftype);
     587                 :             :       else
     588                 :         114 :         warned = warning_at (location, OPT_Warray_bounds_,
     589                 :             :                              "array subscript [%wi, %wi] is outside "
     590                 :             :                              "array bounds of %qT",
     591                 :             :                              offrange[0].to_shwi (),
     592                 :             :                              offrange[1].to_shwi (), reftype);
     593                 :             :     }
     594                 :        9948 :   else if (uboob && !ignore_off_by_one)
     595                 :             :     {
     596                 :         446 :       tree backtype = reftype;
     597                 :         446 :       if (alloc_stmt)
     598                 :             :         /* If the memory was dynamically allocated refer to it as if
     599                 :             :            it were an untyped array of bytes.  */
     600                 :         284 :         backtype = build_array_type_nelts (unsigned_char_type_node,
     601                 :         284 :                                            aref.sizrng[1].to_uhwi ());
     602                 :             : 
     603                 :         446 :       warned = warning_at (location, OPT_Warray_bounds_,
     604                 :             :                            "array subscript %<%T[%wi]%> is partly "
     605                 :             :                            "outside array bounds of %qT",
     606                 :             :                            axstype, offrange[0].to_shwi (), backtype);
     607                 :             :     }
     608                 :             : 
     609                 :        1214 :   if (warned)
     610                 :             :     {
     611                 :             :       /* TODO: Determine the access from the statement and use it.  */
     612                 :        1209 :       aref.inform_access (access_none);
     613                 :        1209 :       suppress_warning (ref, OPT_Warray_bounds_);
     614                 :        1209 :       return true;
     615                 :             :     }
     616                 :             : 
     617                 :        9507 :   if (warn_array_bounds < 2)
     618                 :             :     return false;
     619                 :             : 
     620                 :             :   /* At level 2 check also intermediate offsets.  */
     621                 :          20 :   int i = 0;
     622                 :          20 :   if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound)
     623                 :             :     {
     624                 :           4 :       HOST_WIDE_INT tmpidx = (aref.offmax[i] / eltsize).to_shwi ();
     625                 :             : 
     626                 :           4 :       if (warning_at (location, OPT_Warray_bounds_,
     627                 :             :                       "intermediate array offset %wi is outside array bounds "
     628                 :             :                       "of %qT", tmpidx, reftype))
     629                 :             :         {
     630                 :           3 :           suppress_warning (ref, OPT_Warray_bounds_);
     631                 :           3 :           return true;
     632                 :             :         }
     633                 :             :     }
     634                 :             : 
     635                 :             :   return false;
     636                 :             : }
     637                 :             : 
     638                 :             : /* Searches if the expr T, located at LOCATION computes
     639                 :             :    address of an ARRAY_REF, and call check_array_ref on it.  */
     640                 :             : 
     641                 :             : void
     642                 :      877517 : array_bounds_checker::check_addr_expr (location_t location, tree t,
     643                 :             :                                        gimple *stmt)
     644                 :             : {
     645                 :             :   /* For the most significant subscript only, accept taking the address
     646                 :             :      of the just-past-the-end element.  */
     647                 :      877517 :   bool ignore_off_by_one = true;
     648                 :             : 
     649                 :             :   /* Check each ARRAY_REF and MEM_REF in the reference chain. */
     650                 :     1024936 :   do
     651                 :             :     {
     652                 :     1024936 :       bool warned = false;
     653                 :     1024936 :       if (TREE_CODE (t) == ARRAY_REF)
     654                 :             :         {
     655                 :       14538 :           warned = check_array_ref (location, t, stmt, ignore_off_by_one);
     656                 :       14538 :           ignore_off_by_one = false;
     657                 :             :         }
     658                 :     1010398 :       else if (TREE_CODE (t) == MEM_REF)
     659                 :       57285 :         warned = check_mem_ref (location, t, ignore_off_by_one);
     660                 :             : 
     661                 :       71823 :       if (warned)
     662                 :         181 :         suppress_warning (t, OPT_Warray_bounds_);
     663                 :             : 
     664                 :     1024936 :       t = TREE_OPERAND (t, 0);
     665                 :             :     }
     666                 :     1172355 :   while (handled_component_p (t) || TREE_CODE (t) == MEM_REF);
     667                 :             : 
     668                 :      877517 :   if (TREE_CODE (t) != MEM_REF
     669                 :           0 :       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
     670                 :      877517 :       || warning_suppressed_p (t, OPT_Warray_bounds_))
     671                 :      877517 :     return;
     672                 :             : 
     673                 :           0 :   tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
     674                 :           0 :   tree low_bound, up_bound, el_sz;
     675                 :           0 :   if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
     676                 :           0 :       || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
     677                 :           0 :       || !TYPE_DOMAIN (TREE_TYPE (tem)))
     678                 :             :     return;
     679                 :             : 
     680                 :           0 :   low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
     681                 :           0 :   up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
     682                 :           0 :   el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
     683                 :           0 :   if (!low_bound
     684                 :           0 :       || TREE_CODE (low_bound) != INTEGER_CST
     685                 :           0 :       || !up_bound
     686                 :           0 :       || TREE_CODE (up_bound) != INTEGER_CST
     687                 :           0 :       || !el_sz
     688                 :           0 :       || TREE_CODE (el_sz) != INTEGER_CST)
     689                 :             :     return;
     690                 :             : 
     691                 :           0 :   offset_int idx;
     692                 :           0 :   if (!mem_ref_offset (t).is_constant (&idx))
     693                 :             :     return;
     694                 :             : 
     695                 :           0 :   bool warned = false;
     696                 :           0 :   idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
     697                 :           0 :   if (idx < 0)
     698                 :             :     {
     699                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
     700                 :             :         {
     701                 :           0 :           fprintf (dump_file, "Array bound warning for ");
     702                 :           0 :           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
     703                 :           0 :           fprintf (dump_file, "\n");
     704                 :             :         }
     705                 :           0 :       warned = warning_at (location, OPT_Warray_bounds_,
     706                 :             :                            "array subscript %wi is below "
     707                 :             :                            "array bounds of %qT",
     708                 :           0 :                            idx.to_shwi (), TREE_TYPE (tem));
     709                 :             :     }
     710                 :           0 :   else if (idx > (wi::to_offset (up_bound)
     711                 :           0 :                   - wi::to_offset (low_bound) + 1))
     712                 :             :     {
     713                 :           0 :       if (dump_file && (dump_flags & TDF_DETAILS))
     714                 :             :         {
     715                 :           0 :           fprintf (dump_file, "Array bound warning for ");
     716                 :           0 :           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
     717                 :           0 :           fprintf (dump_file, "\n");
     718                 :             :         }
     719                 :           0 :       warned = warning_at (location, OPT_Warray_bounds_,
     720                 :             :                            "array subscript %wu is above "
     721                 :             :                            "array bounds of %qT",
     722                 :           0 :                            idx.to_uhwi (), TREE_TYPE (tem));
     723                 :             :     }
     724                 :             : 
     725                 :           0 :   if (warned)
     726                 :             :     {
     727                 :           0 :       if (DECL_P (t))
     728                 :           0 :         inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
     729                 :             : 
     730                 :           0 :       suppress_warning (t, OPT_Warray_bounds_);
     731                 :             :     }
     732                 :             : }
     733                 :             : 
     734                 :             : /* Return true if T is a reference to a member of a base class that's within
     735                 :             :    the bounds of the enclosing complete object.  The function "hacks" around
     736                 :             :    problems discussed in pr98266 and pr97595.  */
     737                 :             : 
     738                 :             : static bool
     739                 :    10030238 : inbounds_memaccess_p (tree t, gimple *stmt)
     740                 :             : {
     741                 :    10030238 :   if (TREE_CODE (t) != COMPONENT_REF)
     742                 :             :     return false;
     743                 :             : 
     744                 :      692741 :   tree mref = TREE_OPERAND (t, 0);
     745                 :      692741 :   if (TREE_CODE (mref) != MEM_REF)
     746                 :             :     return false;
     747                 :             : 
     748                 :             :   /* Consider the access if its type is a derived class.  */
     749                 :      399796 :   tree mreftype = TREE_TYPE (mref);
     750                 :      399796 :   if (!RECORD_OR_UNION_TYPE_P (mreftype)
     751                 :      399796 :       || !TYPE_BINFO (mreftype))
     752                 :             :     return false;
     753                 :             : 
     754                 :             :   /* Compute the size of the referenced object (it could be dynamically
     755                 :             :      allocated).  */
     756                 :      190734 :   access_ref aref;   // unused
     757                 :      190734 :   tree refop = TREE_OPERAND (mref, 0);
     758                 :      190734 :   tree refsize = compute_objsize (refop, stmt, 1, &aref);
     759                 :      190734 :   if (!refsize || TREE_CODE (refsize) != INTEGER_CST)
     760                 :             :     return false;
     761                 :             : 
     762                 :             :   /* Compute the byte offset of the member within its enclosing class.  */
     763                 :      190734 :   tree fld = TREE_OPERAND (t, 1);
     764                 :      190734 :   tree fldpos = byte_position (fld);
     765                 :      190734 :   if (TREE_CODE (fldpos) != INTEGER_CST)
     766                 :             :     return false;
     767                 :             : 
     768                 :             :   /* Compute the byte offset of the member with the outermost complete
     769                 :             :      object by adding its offset computed above to the MEM_REF offset.  */
     770                 :      190734 :   tree refoff = TREE_OPERAND (mref, 1);
     771                 :      190734 :   tree fldoff = int_const_binop (PLUS_EXPR, fldpos, refoff);
     772                 :             :   /* Return false if the member offset is greater or equal to the size
     773                 :             :      of the complete object.  */
     774                 :      190734 :   if (!tree_int_cst_lt (fldoff, refsize))
     775                 :             :     return false;
     776                 :             : 
     777                 :      187662 :   tree fldsiz = DECL_SIZE_UNIT (fld);
     778                 :      187662 :   if (!fldsiz || TREE_CODE (fldsiz) != INTEGER_CST)
     779                 :             :     return false;
     780                 :             : 
     781                 :             :   /* Return true if the offset just past the end of the member is less
     782                 :             :      than or equal to the size of the complete object.  */
     783                 :      187506 :   tree fldend = int_const_binop (PLUS_EXPR, fldoff, fldsiz);
     784                 :      187506 :   return tree_int_cst_le (fldend, refsize);
     785                 :             : }
     786                 :             : 
     787                 :             : /* Callback for walk_tree to check a tree for out of bounds array
     788                 :             :    accesses.  The array_bounds_checker class is passed in DATA.  */
     789                 :             : 
     790                 :             : tree
     791                 :    11688436 : array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
     792                 :             :                                           void *data)
     793                 :             : {
     794                 :    11688436 :   tree t = *tp;
     795                 :    11688436 :   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
     796                 :             : 
     797                 :    11688436 :   location_t location;
     798                 :             : 
     799                 :    11688436 :   if (EXPR_HAS_LOCATION (t))
     800                 :     1647489 :     location = EXPR_LOCATION (t);
     801                 :             :   else
     802                 :    10040947 :     location = gimple_location (wi->stmt);
     803                 :             : 
     804                 :    11688436 :   *walk_subtree = true;
     805                 :             : 
     806                 :    11688436 :   bool warned = false;
     807                 :    11688436 :   array_bounds_checker *checker = (array_bounds_checker *) wi->info;
     808                 :    11688436 :   gcc_assert (checker->m_stmt == wi->stmt);
     809                 :             : 
     810                 :    11688436 :   if (TREE_CODE (t) == ARRAY_REF)
     811                 :      223929 :     warned = checker->check_array_ref (location, t, wi->stmt,
     812                 :             :                                        false/*ignore_off_by_one*/);
     813                 :    11464507 :   else if (TREE_CODE (t) == MEM_REF)
     814                 :      556752 :     warned = checker->check_mem_ref (location, t,
     815                 :             :                                      false /*ignore_off_by_one*/);
     816                 :    10907755 :   else if (TREE_CODE (t) == ADDR_EXPR)
     817                 :             :     {
     818                 :      877517 :       checker->check_addr_expr (location, t, wi->stmt);
     819                 :      877517 :       *walk_subtree = false;
     820                 :             :     }
     821                 :    10030238 :   else if (inbounds_memaccess_p (t, wi->stmt))
     822                 :             :     /* Hack: Skip MEM_REF checks in accesses to a member of a base class
     823                 :             :        at an offset that's within the bounds of the enclosing object.
     824                 :             :        See pr98266 and pr97595.  */
     825                 :      187425 :     *walk_subtree = false;
     826                 :             : 
     827                 :             :   /* Propagate the no-warning bit to the outer statement to avoid also
     828                 :             :      issuing -Wstringop-overflow/-overread for the out-of-bounds accesses.  */
     829                 :     1845623 :   if (warned)
     830                 :        2289 :     suppress_warning (wi->stmt, OPT_Warray_bounds_);
     831                 :             : 
     832                 :    11688436 :   return NULL_TREE;
     833                 :             : }
     834                 :             : 
     835                 :             : /* A dom_walker subclass for use by check_all_array_refs, to walk over
     836                 :             :    all statements of all reachable BBs and call check_array_bounds on
     837                 :             :    them.  */
     838                 :             : 
     839                 :             : class check_array_bounds_dom_walker : public dom_walker
     840                 :             : {
     841                 :             : public:
     842                 :      107837 :   check_array_bounds_dom_walker (array_bounds_checker *checker)
     843                 :      107837 :     : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS),
     844                 :      215674 :     checker (checker) { }
     845                 :      215674 :   ~check_array_bounds_dom_walker () {}
     846                 :             : 
     847                 :             :   edge before_dom_children (basic_block) final override;
     848                 :             : 
     849                 :             : private:
     850                 :             :   array_bounds_checker *checker;
     851                 :             : };
     852                 :             : 
     853                 :             : /* Implementation of dom_walker::before_dom_children.
     854                 :             : 
     855                 :             :    Walk over all statements of BB and call check_array_bounds on them,
     856                 :             :    and determine if there's a unique successor edge.  */
     857                 :             : 
     858                 :             : edge
     859                 :     1048918 : check_array_bounds_dom_walker::before_dom_children (basic_block bb)
     860                 :             : {
     861                 :     1048918 :   gimple_stmt_iterator si;
     862                 :    10651009 :   for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
     863                 :             :     {
     864                 :     8553173 :       gimple *stmt = gsi_stmt (si);
     865                 :     8553173 :       if (!gimple_has_location (stmt)
     866                 :     8553173 :           || is_gimple_debug (stmt))
     867                 :     4921123 :         continue;
     868                 :             : 
     869                 :     3632050 :       struct walk_stmt_info wi{ };
     870                 :     3632050 :       wi.info = checker;
     871                 :     3632050 :       checker->m_stmt = stmt;
     872                 :             : 
     873                 :     3632050 :       walk_gimple_op (stmt, array_bounds_checker::check_array_bounds, &wi);
     874                 :             :     }
     875                 :             : 
     876                 :             :   /* Determine if there's a unique successor edge, and if so, return
     877                 :             :      that back to dom_walker, ensuring that we don't visit blocks that
     878                 :             :      became unreachable during the VRP propagation
     879                 :             :      (PR tree-optimization/83312).  */
     880                 :     1048918 :   return find_taken_edge (bb, NULL_TREE);
     881                 :             : }
     882                 :             : 
     883                 :             : void
     884                 :      107837 : array_bounds_checker::check ()
     885                 :             : {
     886                 :      107837 :   check_array_bounds_dom_walker w (this);
     887                 :      107837 :   w.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
     888                 :      107837 : }
     889                 :             : 
     890                 :             : const pass_data pass_data_array_bounds =
     891                 :             : {
     892                 :             :   GIMPLE_PASS, /* type */
     893                 :             :   "bounds", /* name */
     894                 :             :   OPTGROUP_NONE, /* optinfo_flags */
     895                 :             :   TV_TREE_ARRAY_BOUNDS, /* tv_id */
     896                 :             :   PROP_ssa, /* properties_required */
     897                 :             :   0, /* properties_provided */
     898                 :             :   0, /* properties_destroyed */
     899                 :             :   0, /* todo_flags_start */
     900                 :             :   ( 0 ),  /* No TODOs */
     901                 :             : };
     902                 :             : 
     903                 :             : class pass_array_bounds : public gimple_opt_pass
     904                 :             : {
     905                 :             : public:
     906                 :      280114 :   pass_array_bounds (gcc::context *ctxt, const pass_data &data_)
     907                 :      560228 :     : gimple_opt_pass (data_, ctxt), data (data_)
     908                 :             :     { }
     909                 :             : 
     910                 :             :   /* opt_pass methods: */
     911                 :           0 :   opt_pass * clone () final override
     912                 :           0 :     { return new pass_array_bounds (m_ctxt, data); }
     913                 :      996137 :   bool gate (function *) final override
     914                 :             :     {
     915                 :             :       // Gate on the VRP pass to preserve previous behavior.
     916                 :      996137 :       return flag_tree_vrp && (warn_array_bounds || warn_strict_flex_arrays);
     917                 :             :     }
     918                 :      107837 :   unsigned int execute (function *fun) final override
     919                 :             :     {
     920                 :      107837 :       calculate_dominance_info (CDI_DOMINATORS);
     921                 :             :       // Enable ranger as the current range query.
     922                 :      107837 :       enable_ranger (fun, false);
     923                 :      107837 :       array_bounds_checker array_checker (fun);
     924                 :      107837 :       array_checker.check ();
     925                 :      107837 :       disable_ranger (fun);
     926                 :      107837 :       return 0;
     927                 :      107837 :     }
     928                 :             : 
     929                 :             :  private:
     930                 :             :   const pass_data &data;
     931                 :             : }; // class pass_array_bounds
     932                 :             : 
     933                 :             : gimple_opt_pass *
     934                 :      280114 : make_pass_array_bounds (gcc::context *ctxt)
     935                 :             : {
     936                 :      280114 :   return new pass_array_bounds (ctxt, pass_data_array_bounds);
     937                 :             : }
        

Generated by: LCOV version 2.1-beta

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