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