[Ada] Use Is_Generic_Subprogram where possible
[platform/upstream/gcc.git] / gcc / gimple-array-bounds.cc
1 /* Array bounds checking.
2    Copyright (C) 2005-2020 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
40 // This purposely returns a value_range, not a value_range_equiv, to
41 // break the dependency on equivalences for this pass.
42
43 const value_range *
44 array_bounds_checker::get_value_range (const_tree op)
45 {
46   return ranges->get_value_range (op);
47 }
48
49 /* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible
50    arrays and "struct" hacks. If VRP can determine that the array
51    subscript is a constant, check if it is outside valid range.  If
52    the array subscript is a RANGE, warn if it is non-overlapping with
53    valid range.  IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside
54    a ADDR_EXPR.  Returns true if a warning has been issued.  */
55
56 bool
57 array_bounds_checker::check_array_ref (location_t location, tree ref,
58                                        bool ignore_off_by_one)
59 {
60   if (TREE_NO_WARNING (ref))
61     return false;
62
63   tree low_sub = TREE_OPERAND (ref, 1);
64   tree up_sub = low_sub;
65   tree up_bound = array_ref_up_bound (ref);
66
67   /* Referenced decl if one can be determined.  */
68   tree decl = NULL_TREE;
69
70   /* Set for accesses to interior zero-length arrays.  */
71   bool interior_zero_len = false;
72
73   tree up_bound_p1;
74
75   if (!up_bound
76       || TREE_CODE (up_bound) != INTEGER_CST
77       || (warn_array_bounds < 2
78           && array_at_struct_end_p (ref)))
79     {
80       /* Accesses to trailing arrays via pointers may access storage
81          beyond the types array bounds.  For such arrays, or for flexible
82          array members, as well as for other arrays of an unknown size,
83          replace the upper bound with a more permissive one that assumes
84          the size of the largest object is PTRDIFF_MAX.  */
85       tree eltsize = array_ref_element_size (ref);
86
87       if (TREE_CODE (eltsize) != INTEGER_CST
88           || integer_zerop (eltsize))
89         {
90           up_bound = NULL_TREE;
91           up_bound_p1 = NULL_TREE;
92         }
93       else
94         {
95           tree ptrdiff_max = TYPE_MAX_VALUE (ptrdiff_type_node);
96           tree maxbound = ptrdiff_max;
97           tree arg = TREE_OPERAND (ref, 0);
98
99           const bool compref = TREE_CODE (arg) == COMPONENT_REF;
100           if (compref)
101             {
102               /* Try to determine the size of the trailing array from
103                  its initializer (if it has one).  */
104               if (tree refsize = component_ref_size (arg, &interior_zero_len))
105                 if (TREE_CODE (refsize) == INTEGER_CST)
106                   maxbound = refsize;
107             }
108
109           if (maxbound == ptrdiff_max)
110             {
111               /* Try to determine the size of the base object.  Avoid
112                  COMPONENT_REF already tried above.  Using its DECL_SIZE
113                  size wouldn't necessarily be correct if the reference is
114                  to its flexible array member initialized in a different
115                  translation unit.  */
116               poly_int64 off;
117               if (tree base = get_addr_base_and_unit_offset (arg, &off))
118                 {
119                   if (!compref && DECL_P (base))
120                     if (tree basesize = DECL_SIZE_UNIT (base))
121                       if (TREE_CODE (basesize) == INTEGER_CST)
122                         {
123                           maxbound = basesize;
124                           decl = base;
125                         }
126
127                   if (known_gt (off, 0))
128                     maxbound = wide_int_to_tree (sizetype,
129                                                  wi::sub (wi::to_wide (maxbound),
130                                                           off));
131                 }
132             }
133           else
134             maxbound = fold_convert (sizetype, maxbound);
135
136           up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
137
138           if (up_bound_p1 != NULL_TREE)
139             up_bound = int_const_binop (MINUS_EXPR, up_bound_p1,
140                                         build_int_cst (ptrdiff_type_node, 1));
141           else
142             up_bound = NULL_TREE;
143         }
144     }
145   else
146     up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
147                                    build_int_cst (TREE_TYPE (up_bound), 1));
148
149   tree low_bound = array_ref_low_bound (ref);
150
151   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
152
153   bool warned = false;
154
155   /* Empty array.  */
156   if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
157     warned = warning_at (location, OPT_Warray_bounds,
158                          "array subscript %E is outside array bounds of %qT",
159                          low_sub, artype);
160
161   const value_range *vr = NULL;
162   if (TREE_CODE (low_sub) == SSA_NAME)
163     {
164       vr = get_value_range (low_sub);
165       if (!vr->undefined_p () && !vr->varying_p ())
166         {
167           low_sub = vr->kind () == VR_RANGE ? vr->max () : vr->min ();
168           up_sub = vr->kind () == VR_RANGE ? vr->min () : vr->max ();
169         }
170     }
171
172   if (warned)
173     ; /* Do nothing.  */
174   else if (vr && vr->kind () == VR_ANTI_RANGE)
175     {
176       if (up_bound
177           && TREE_CODE (up_sub) == INTEGER_CST
178           && (ignore_off_by_one
179               ? tree_int_cst_lt (up_bound, up_sub)
180               : tree_int_cst_le (up_bound, up_sub))
181           && TREE_CODE (low_sub) == INTEGER_CST
182           && tree_int_cst_le (low_sub, low_bound))
183         warned = warning_at (location, OPT_Warray_bounds,
184                              "array subscript [%E, %E] is outside "
185                              "array bounds of %qT",
186                              low_sub, up_sub, artype);
187     }
188   else if (up_bound
189            && TREE_CODE (up_sub) == INTEGER_CST
190            && (ignore_off_by_one
191                ? !tree_int_cst_le (up_sub, up_bound_p1)
192                : !tree_int_cst_le (up_sub, up_bound)))
193     warned = warning_at (location, OPT_Warray_bounds,
194                          "array subscript %E is above array bounds of %qT",
195                          up_sub, artype);
196   else if (TREE_CODE (low_sub) == INTEGER_CST
197            && tree_int_cst_lt (low_sub, low_bound))
198     warned = warning_at (location, OPT_Warray_bounds,
199                          "array subscript %E is below array bounds of %qT",
200                          low_sub, artype);
201
202   if (!warned && interior_zero_len)
203     warned = warning_at (location, OPT_Wzero_length_bounds,
204                          (TREE_CODE (low_sub) == INTEGER_CST
205                           ? G_("array subscript %E is outside the bounds "
206                                "of an interior zero-length array %qT")
207                           : G_("array subscript %qE is outside the bounds "
208                                "of an interior zero-length array %qT")),
209                          low_sub, artype);
210
211   if (warned)
212     {
213       if (dump_file && (dump_flags & TDF_DETAILS))
214         {
215           fprintf (dump_file, "Array bound warning for ");
216           dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
217           fprintf (dump_file, "\n");
218         }
219
220       ref = decl ? decl : TREE_OPERAND (ref, 0);
221
222       tree rec = NULL_TREE;
223       if (TREE_CODE (ref) == COMPONENT_REF)
224         {
225           /* For a reference to a member of a struct object also mention
226              the object if it's known.  It may be defined in a different
227              function than the out-of-bounds access.  */
228           rec = TREE_OPERAND (ref, 0);
229           if (!VAR_P (rec))
230             rec = NULL_TREE;
231           ref = TREE_OPERAND (ref, 1);
232         }
233
234       if (DECL_P (ref))
235         inform (DECL_SOURCE_LOCATION (ref), "while referencing %qD", ref);
236       if (rec && DECL_P (rec))
237         inform (DECL_SOURCE_LOCATION (rec), "defined here %qD", rec);
238
239       TREE_NO_WARNING (ref) = 1;
240     }
241
242   return warned;
243 }
244
245 /* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
246    references to string constants.  If VRP can determine that the array
247    subscript is a constant, check if it is outside valid range.
248    If the array subscript is a RANGE, warn if it is non-overlapping
249    with valid range.
250    IGNORE_OFF_BY_ONE is true if the MEM_REF is inside an ADDR_EXPR
251    (used to allow one-past-the-end indices for code that takes
252    the address of the just-past-the-end element of an array).
253    Returns true if a warning has been issued.  */
254
255 bool
256 array_bounds_checker::check_mem_ref (location_t location, tree ref,
257                                      bool ignore_off_by_one)
258 {
259   if (TREE_NO_WARNING (ref))
260     return false;
261
262   tree arg = TREE_OPERAND (ref, 0);
263   /* The constant and variable offset of the reference.  */
264   tree cstoff = TREE_OPERAND (ref, 1);
265   tree varoff = NULL_TREE;
266
267   const offset_int maxobjsize = tree_to_shwi (max_object_size ());
268
269   /* The array or string constant bounds in bytes.  Initially set
270      to [-MAXOBJSIZE - 1, MAXOBJSIZE]  until a tighter bound is
271      determined.  */
272   offset_int arrbounds[2] = { -maxobjsize - 1, maxobjsize };
273
274   /* The minimum and maximum intermediate offset.  For a reference
275      to be valid, not only does the final offset/subscript must be
276      in bounds but all intermediate offsets should be as well.
277      GCC may be able to deal gracefully with such out-of-bounds
278      offsets so the checking is only enbaled at -Warray-bounds=2
279      where it may help detect bugs in uses of the intermediate
280      offsets that could otherwise not be detectable.  */
281   offset_int ioff = wi::to_offset (fold_convert (ptrdiff_type_node, cstoff));
282   offset_int extrema[2] = { 0, wi::abs (ioff) };
283
284   /* The range of the byte offset into the reference.  */
285   offset_int offrange[2] = { 0, 0 };
286
287   const value_range *vr = NULL;
288
289   /* Determine the offsets and increment OFFRANGE for the bounds of each.
290      The loop computes the range of the final offset for expressions such
291      as (A + i0 + ... + iN)[CSTOFF] where i0 through iN are SSA_NAMEs in
292      some range.  */
293   const unsigned limit = param_ssa_name_def_chain_limit;
294   for (unsigned n = 0; TREE_CODE (arg) == SSA_NAME && n < limit; ++n)
295     {
296       gimple *def = SSA_NAME_DEF_STMT (arg);
297       if (!is_gimple_assign (def))
298         break;
299
300       tree_code code = gimple_assign_rhs_code (def);
301       if (code == POINTER_PLUS_EXPR)
302         {
303           arg = gimple_assign_rhs1 (def);
304           varoff = gimple_assign_rhs2 (def);
305         }
306       else if (code == ASSERT_EXPR)
307         {
308           arg = TREE_OPERAND (gimple_assign_rhs1 (def), 0);
309           continue;
310         }
311       else
312         return false;
313
314       /* VAROFF should always be a SSA_NAME here (and not even
315          INTEGER_CST) but there's no point in taking chances.  */
316       if (TREE_CODE (varoff) != SSA_NAME)
317         break;
318
319       vr = get_value_range (varoff);
320       if (!vr || vr->undefined_p () || vr->varying_p ())
321         break;
322
323       if (!vr->constant_p ())
324         break;
325
326       if (vr->kind () == VR_RANGE)
327         {
328           offset_int min
329             = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min ()));
330           offset_int max
331             = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max ()));
332           if (min < max)
333             {
334               offrange[0] += min;
335               offrange[1] += max;
336             }
337           else
338             {
339               /* When MIN >= MAX, the offset is effectively in a union
340                  of two ranges: [-MAXOBJSIZE -1, MAX] and [MIN, MAXOBJSIZE].
341                  Since there is no way to represent such a range across
342                  additions, conservatively add [-MAXOBJSIZE -1, MAXOBJSIZE]
343                  to OFFRANGE.  */
344               offrange[0] += arrbounds[0];
345               offrange[1] += arrbounds[1];
346             }
347         }
348       else
349         {
350           /* For an anti-range, analogously to the above, conservatively
351              add [-MAXOBJSIZE -1, MAXOBJSIZE] to OFFRANGE.  */
352           offrange[0] += arrbounds[0];
353           offrange[1] += arrbounds[1];
354         }
355
356       /* Keep track of the minimum and maximum offset.  */
357       if (offrange[1] < 0 && offrange[1] < extrema[0])
358         extrema[0] = offrange[1];
359       if (offrange[0] > 0 && offrange[0] > extrema[1])
360         extrema[1] = offrange[0];
361
362       if (offrange[0] < arrbounds[0])
363         offrange[0] = arrbounds[0];
364
365       if (offrange[1] > arrbounds[1])
366         offrange[1] = arrbounds[1];
367     }
368
369   if (TREE_CODE (arg) == ADDR_EXPR)
370     {
371       arg = TREE_OPERAND (arg, 0);
372       if (TREE_CODE (arg) != STRING_CST
373           && TREE_CODE (arg) != PARM_DECL
374           && TREE_CODE (arg) != VAR_DECL)
375         return false;
376     }
377   else
378     return false;
379
380   /* The type of the object being referred to.  It can be an array,
381      string literal, or a non-array type when the MEM_REF represents
382      a reference/subscript via a pointer to an object that is not
383      an element of an array.  Incomplete types are excluded as well
384      because their size is not known.  */
385   tree reftype = TREE_TYPE (arg);
386   if (POINTER_TYPE_P (reftype)
387       || !COMPLETE_TYPE_P (reftype)
388       || TREE_CODE (TYPE_SIZE_UNIT (reftype)) != INTEGER_CST)
389     return false;
390
391   /* Except in declared objects, references to trailing array members
392      of structs and union objects are excluded because MEM_REF doesn't
393      make it possible to identify the member where the reference
394      originated.  */
395   if (RECORD_OR_UNION_TYPE_P (reftype)
396       && (!VAR_P (arg)
397           || (DECL_EXTERNAL (arg) && array_at_struct_end_p (ref))))
398     return false;
399
400   arrbounds[0] = 0;
401
402   offset_int eltsize;
403   if (TREE_CODE (reftype) == ARRAY_TYPE)
404     {
405       eltsize = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (reftype)));
406       if (tree dom = TYPE_DOMAIN (reftype))
407         {
408           tree bnds[] = { TYPE_MIN_VALUE (dom), TYPE_MAX_VALUE (dom) };
409           if (TREE_CODE (arg) == COMPONENT_REF)
410             {
411               offset_int size = maxobjsize;
412               if (tree fldsize = component_ref_size (arg))
413                 size = wi::to_offset (fldsize);
414               arrbounds[1] = wi::lrshift (size, wi::floor_log2 (eltsize));
415             }
416           else if (array_at_struct_end_p (arg) || !bnds[0] || !bnds[1])
417             arrbounds[1] = wi::lrshift (maxobjsize, wi::floor_log2 (eltsize));
418           else
419             arrbounds[1] = (wi::to_offset (bnds[1]) - wi::to_offset (bnds[0])
420                             + 1) * eltsize;
421         }
422       else
423         arrbounds[1] = wi::lrshift (maxobjsize, wi::floor_log2 (eltsize));
424
425       /* Determine a tighter bound of the non-array element type.  */
426       tree eltype = TREE_TYPE (reftype);
427       while (TREE_CODE (eltype) == ARRAY_TYPE)
428         eltype = TREE_TYPE (eltype);
429       eltsize = wi::to_offset (TYPE_SIZE_UNIT (eltype));
430     }
431   else
432     {
433       eltsize = 1;
434       tree size = TYPE_SIZE_UNIT (reftype);
435       if (VAR_P (arg))
436         if (tree initsize = DECL_SIZE_UNIT (arg))
437           if (tree_int_cst_lt (size, initsize))
438             size = initsize;
439
440       arrbounds[1] = wi::to_offset (size);
441     }
442
443   offrange[0] += ioff;
444   offrange[1] += ioff;
445
446   /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
447      is set (when taking the address of the one-past-last element
448      of an array) but always use the stricter bound in diagnostics. */
449   offset_int ubound = arrbounds[1];
450   if (ignore_off_by_one)
451     ubound += 1;
452
453   if (arrbounds[0] == arrbounds[1]
454       || offrange[0] >= ubound
455       || offrange[1] < arrbounds[0])
456     {
457       /* Treat a reference to a non-array object as one to an array
458          of a single element.  */
459       if (TREE_CODE (reftype) != ARRAY_TYPE)
460         reftype = build_array_type_nelts (reftype, 1);
461
462       /* Extract the element type out of MEM_REF and use its size
463          to compute the index to print in the diagnostic; arrays
464          in MEM_REF don't mean anything.  A type with no size like
465          void is as good as having a size of 1.  */
466       tree type = TREE_TYPE (ref);
467       while (TREE_CODE (type) == ARRAY_TYPE)
468         type = TREE_TYPE (type);
469       if (tree size = TYPE_SIZE_UNIT (type))
470         {
471           offrange[0] = offrange[0] / wi::to_offset (size);
472           offrange[1] = offrange[1] / wi::to_offset (size);
473         }
474
475       bool warned;
476       if (offrange[0] == offrange[1])
477         warned = warning_at (location, OPT_Warray_bounds,
478                              "array subscript %wi is outside array bounds "
479                              "of %qT",
480                              offrange[0].to_shwi (), reftype);
481       else
482         warned = warning_at (location, OPT_Warray_bounds,
483                              "array subscript [%wi, %wi] is outside "
484                              "array bounds of %qT",
485                              offrange[0].to_shwi (),
486                              offrange[1].to_shwi (), reftype);
487       if (warned && DECL_P (arg))
488         inform (DECL_SOURCE_LOCATION (arg), "while referencing %qD", arg);
489
490       if (warned)
491         TREE_NO_WARNING (ref) = 1;
492       return warned;
493     }
494
495   if (warn_array_bounds < 2)
496     return false;
497
498   /* At level 2 check also intermediate offsets.  */
499   int i = 0;
500   if (extrema[i] < -arrbounds[1] || extrema[i = 1] > ubound)
501     {
502       HOST_WIDE_INT tmpidx = extrema[i].to_shwi () / eltsize.to_shwi ();
503
504       if (warning_at (location, OPT_Warray_bounds,
505                       "intermediate array offset %wi is outside array bounds "
506                       "of %qT", tmpidx, reftype))
507         {
508           TREE_NO_WARNING (ref) = 1;
509           return true;
510         }
511     }
512
513   return false;
514 }
515
516 /* Searches if the expr T, located at LOCATION computes
517    address of an ARRAY_REF, and call check_array_ref on it.  */
518
519 void
520 array_bounds_checker::check_addr_expr (location_t location, tree t)
521 {
522   /* Check each ARRAY_REF and MEM_REF in the reference chain. */
523   do
524     {
525       bool warned = false;
526       if (TREE_CODE (t) == ARRAY_REF)
527         warned = check_array_ref (location, t, true /*ignore_off_by_one*/);
528       else if (TREE_CODE (t) == MEM_REF)
529         warned = check_mem_ref (location, t, true /*ignore_off_by_one*/);
530
531       if (warned)
532         TREE_NO_WARNING (t) = true;
533
534       t = TREE_OPERAND (t, 0);
535     }
536   while (handled_component_p (t) || TREE_CODE (t) == MEM_REF);
537
538   if (TREE_CODE (t) != MEM_REF
539       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
540       || TREE_NO_WARNING (t))
541     return;
542
543   tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
544   tree low_bound, up_bound, el_sz;
545   if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
546       || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
547       || !TYPE_DOMAIN (TREE_TYPE (tem)))
548     return;
549
550   low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
551   up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
552   el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
553   if (!low_bound
554       || TREE_CODE (low_bound) != INTEGER_CST
555       || !up_bound
556       || TREE_CODE (up_bound) != INTEGER_CST
557       || !el_sz
558       || TREE_CODE (el_sz) != INTEGER_CST)
559     return;
560
561   offset_int idx;
562   if (!mem_ref_offset (t).is_constant (&idx))
563     return;
564
565   bool warned = false;
566   idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
567   if (idx < 0)
568     {
569       if (dump_file && (dump_flags & TDF_DETAILS))
570         {
571           fprintf (dump_file, "Array bound warning for ");
572           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
573           fprintf (dump_file, "\n");
574         }
575       warned = warning_at (location, OPT_Warray_bounds,
576                            "array subscript %wi is below "
577                            "array bounds of %qT",
578                            idx.to_shwi (), TREE_TYPE (tem));
579     }
580   else if (idx > (wi::to_offset (up_bound)
581                   - wi::to_offset (low_bound) + 1))
582     {
583       if (dump_file && (dump_flags & TDF_DETAILS))
584         {
585           fprintf (dump_file, "Array bound warning for ");
586           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
587           fprintf (dump_file, "\n");
588         }
589       warned = warning_at (location, OPT_Warray_bounds,
590                            "array subscript %wu is above "
591                            "array bounds of %qT",
592                            idx.to_uhwi (), TREE_TYPE (tem));
593     }
594
595   if (warned)
596     {
597       if (DECL_P (t))
598         inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
599
600       TREE_NO_WARNING (t) = 1;
601     }
602 }
603
604 /* Callback for walk_tree to check a tree for out of bounds array
605    accesses.  The array_bounds_checker class is passed in DATA.  */
606
607 tree
608 array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
609                                           void *data)
610 {
611   tree t = *tp;
612   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
613   location_t location;
614
615   if (EXPR_HAS_LOCATION (t))
616     location = EXPR_LOCATION (t);
617   else
618     location = gimple_location (wi->stmt);
619
620   *walk_subtree = TRUE;
621
622   bool warned = false;
623   array_bounds_checker *checker = (array_bounds_checker *) wi->info;
624   if (TREE_CODE (t) == ARRAY_REF)
625     warned = checker->check_array_ref (location, t,
626                                        false/*ignore_off_by_one*/);
627   else if (TREE_CODE (t) == MEM_REF)
628     warned = checker->check_mem_ref (location, t,
629                                      false /*ignore_off_by_one*/);
630   else if (TREE_CODE (t) == ADDR_EXPR)
631     {
632       checker->check_addr_expr (location, t);
633       *walk_subtree = FALSE;
634     }
635   /* Propagate the no-warning bit to the outer expression.  */
636   if (warned)
637     TREE_NO_WARNING (t) = true;
638
639   return NULL_TREE;
640 }
641
642 /* A dom_walker subclass for use by check_all_array_refs, to walk over
643    all statements of all reachable BBs and call check_array_bounds on
644    them.  */
645
646 class check_array_bounds_dom_walker : public dom_walker
647 {
648 public:
649   check_array_bounds_dom_walker (array_bounds_checker *checker)
650     : dom_walker (CDI_DOMINATORS,
651                   /* Discover non-executable edges, preserving EDGE_EXECUTABLE
652                      flags, so that we can merge in information on
653                      non-executable edges from vrp_folder .  */
654                   REACHABLE_BLOCKS_PRESERVING_FLAGS),
655     checker (checker) { }
656   ~check_array_bounds_dom_walker () {}
657
658   edge before_dom_children (basic_block) FINAL OVERRIDE;
659
660 private:
661   array_bounds_checker *checker;
662 };
663
664 /* Implementation of dom_walker::before_dom_children.
665
666    Walk over all statements of BB and call check_array_bounds on them,
667    and determine if there's a unique successor edge.  */
668
669 edge
670 check_array_bounds_dom_walker::before_dom_children (basic_block bb)
671 {
672   gimple_stmt_iterator si;
673   for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
674     {
675       gimple *stmt = gsi_stmt (si);
676       struct walk_stmt_info wi;
677       if (!gimple_has_location (stmt)
678           || is_gimple_debug (stmt))
679         continue;
680
681       memset (&wi, 0, sizeof (wi));
682
683       wi.info = checker;
684
685       walk_gimple_op (stmt, array_bounds_checker::check_array_bounds, &wi);
686     }
687
688   /* Determine if there's a unique successor edge, and if so, return
689      that back to dom_walker, ensuring that we don't visit blocks that
690      became unreachable during the VRP propagation
691      (PR tree-optimization/83312).  */
692   return find_taken_edge (bb, NULL_TREE);
693 }
694
695 void
696 array_bounds_checker::check ()
697 {
698   check_array_bounds_dom_walker w (this);
699   w.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
700 }