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

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.