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

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.