Use Object Size Type zero for -Warray-bounds [PR101374].
[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 "builtins.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)
47 {
48   return ranges->get_value_range (op);
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                                        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);
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_CODE (axstype) != UNION_TYPE)
425     if (tree access_size = TYPE_SIZE_UNIT (axstype))
426       if (TREE_CODE (access_size) == INTEGER_CST)
427         axssize = wi::to_offset (access_size);
428
429   access_ref aref;
430   if (!compute_objsize (ref, 0, &aref, ranges))
431     return false;
432
433   if (aref.offset_in_range (axssize))
434     return false;
435
436   if (TREE_CODE (aref.ref) == SSA_NAME)
437     {
438       gimple *def = SSA_NAME_DEF_STMT (aref.ref);
439       if (is_gimple_call (def))
440         {
441           /* Save the allocation call and the low bound on the size.  */
442           alloc_stmt = def;
443           minbound = aref.sizrng[0];
444         }
445     }
446                         
447   /* The range of the byte offset into the reference.  Adjusted below.  */
448   offset_int offrange[2] = { aref.offrng[0], aref.offrng[1] };
449
450   /* The type of the referenced object.  */
451   tree reftype = TREE_TYPE (aref.ref);
452   /* The size of the referenced array element.  */
453   offset_int eltsize = 1;
454   /* The byte size of the array has already been determined above
455      based on a pointer ARG.  Set ELTSIZE to the size of the type
456      it points to and REFTYPE to the array with the size, rounded
457      down as necessary.  */
458   if (POINTER_TYPE_P (reftype))
459     reftype = TREE_TYPE (reftype);
460   if (TREE_CODE (reftype) == ARRAY_TYPE)
461     reftype = TREE_TYPE (reftype);
462   if (tree refsize = TYPE_SIZE_UNIT (reftype))
463     if (TREE_CODE (refsize) == INTEGER_CST)
464       eltsize = wi::to_offset (refsize);
465
466   const offset_int nelts = aref.sizrng[1] / eltsize;
467   reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
468
469   /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
470      is set (when taking the address of the one-past-last element
471      of an array) but always use the stricter bound in diagnostics. */
472   offset_int ubound = aref.sizrng[1];
473   if (ignore_off_by_one)
474     ubound += eltsize;
475
476   /* Set if the lower bound of the subscript is out of bounds.  */
477   const bool lboob = (aref.sizrng[1] == 0
478                       || offrange[0] >= ubound
479                       || offrange[1] < 0);
480   /* Set if only the upper bound of the subscript is out of bounds.
481      This can happen when using a bigger type to index into an array
482      of a smaller type, as is common with unsigned char.  */
483   const bool uboob = !lboob && offrange[0] + axssize > ubound;
484   if (lboob || uboob)
485     {
486       /* Treat a reference to a non-array object as one to an array
487          of a single element.  */
488       if (TREE_CODE (reftype) != ARRAY_TYPE)
489         reftype = build_printable_array_type (reftype, 1);
490
491       /* Extract the element type out of MEM_REF and use its size
492          to compute the index to print in the diagnostic; arrays
493          in MEM_REF don't mean anything.  A type with no size like
494          void is as good as having a size of 1.  */
495       tree type = strip_array_types (TREE_TYPE (ref));
496       if (tree size = TYPE_SIZE_UNIT (type))
497         {
498           offrange[0] = offrange[0] / wi::to_offset (size);
499           offrange[1] = offrange[1] / wi::to_offset (size);
500         }
501     }
502
503   bool warned = false;
504   if (lboob)
505     {
506       if (offrange[0] == offrange[1])
507         warned = warning_at (location, OPT_Warray_bounds,
508                              "array subscript %wi is outside array bounds "
509                              "of %qT",
510                              offrange[0].to_shwi (), reftype);
511       else
512         warned = warning_at (location, OPT_Warray_bounds,
513                              "array subscript [%wi, %wi] is outside "
514                              "array bounds of %qT",
515                              offrange[0].to_shwi (),
516                              offrange[1].to_shwi (), reftype);
517     }
518   else if (uboob && !ignore_off_by_one)
519     {
520       tree backtype = reftype;
521       if (alloc_stmt)
522         /* If the memory was dynamically allocated refer to it as if
523            it were an untyped array of bytes.  */
524         backtype = build_array_type_nelts (unsigned_char_type_node,
525                                            aref.sizrng[1].to_uhwi ());
526
527       warned = warning_at (location, OPT_Warray_bounds,
528                            "array subscript %<%T[%wi]%> is partly "
529                            "outside array bounds of %qT",
530                            axstype, offrange[0].to_shwi (), backtype);
531     }
532
533   if (warned)
534     {
535       /* TODO: Determine the access from the statement and use it.  */
536       aref.inform_access (access_none);
537       suppress_warning (ref, OPT_Warray_bounds);
538       return true;
539     }
540
541   if (warn_array_bounds < 2)
542     return false;
543
544   /* At level 2 check also intermediate offsets.  */
545   int i = 0;
546   if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound)
547     {
548       HOST_WIDE_INT tmpidx = aref.offmax[i].to_shwi () / eltsize.to_shwi ();
549
550       if (warning_at (location, OPT_Warray_bounds,
551                       "intermediate array offset %wi is outside array bounds "
552                       "of %qT", tmpidx, reftype))
553         {
554           suppress_warning (ref, OPT_Warray_bounds);
555           return true;
556         }
557     }
558
559   return false;
560 }
561
562 /* Searches if the expr T, located at LOCATION computes
563    address of an ARRAY_REF, and call check_array_ref on it.  */
564
565 void
566 array_bounds_checker::check_addr_expr (location_t location, tree t)
567 {
568   /* For the most significant subscript only, accept taking the address
569      of the just-past-the-end element.  */
570   bool ignore_off_by_one = true;
571
572   /* Check each ARRAY_REF and MEM_REF in the reference chain. */
573   do
574     {
575       bool warned = false;
576       if (TREE_CODE (t) == ARRAY_REF)
577         {
578           warned = check_array_ref (location, t, ignore_off_by_one);
579           ignore_off_by_one = false;
580         }
581       else if (TREE_CODE (t) == MEM_REF)
582         warned = check_mem_ref (location, t, ignore_off_by_one);
583
584       if (warned)
585         suppress_warning (t, OPT_Warray_bounds);
586
587       t = TREE_OPERAND (t, 0);
588     }
589   while (handled_component_p (t) || TREE_CODE (t) == MEM_REF);
590
591   if (TREE_CODE (t) != MEM_REF
592       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
593       || warning_suppressed_p (t, OPT_Warray_bounds))
594     return;
595
596   tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
597   tree low_bound, up_bound, el_sz;
598   if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
599       || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
600       || !TYPE_DOMAIN (TREE_TYPE (tem)))
601     return;
602
603   low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
604   up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
605   el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
606   if (!low_bound
607       || TREE_CODE (low_bound) != INTEGER_CST
608       || !up_bound
609       || TREE_CODE (up_bound) != INTEGER_CST
610       || !el_sz
611       || TREE_CODE (el_sz) != INTEGER_CST)
612     return;
613
614   offset_int idx;
615   if (!mem_ref_offset (t).is_constant (&idx))
616     return;
617
618   bool warned = false;
619   idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
620   if (idx < 0)
621     {
622       if (dump_file && (dump_flags & TDF_DETAILS))
623         {
624           fprintf (dump_file, "Array bound warning for ");
625           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
626           fprintf (dump_file, "\n");
627         }
628       warned = warning_at (location, OPT_Warray_bounds,
629                            "array subscript %wi is below "
630                            "array bounds of %qT",
631                            idx.to_shwi (), TREE_TYPE (tem));
632     }
633   else if (idx > (wi::to_offset (up_bound)
634                   - wi::to_offset (low_bound) + 1))
635     {
636       if (dump_file && (dump_flags & TDF_DETAILS))
637         {
638           fprintf (dump_file, "Array bound warning for ");
639           dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
640           fprintf (dump_file, "\n");
641         }
642       warned = warning_at (location, OPT_Warray_bounds,
643                            "array subscript %wu is above "
644                            "array bounds of %qT",
645                            idx.to_uhwi (), TREE_TYPE (tem));
646     }
647
648   if (warned)
649     {
650       if (DECL_P (t))
651         inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
652
653       suppress_warning (t, OPT_Warray_bounds);
654     }
655 }
656
657 /* Return true if T is a reference to a member of a base class that's within
658    the bounds of the enclosing complete object.  The function "hacks" around
659    problems discussed in pr98266 and pr97595.  */
660
661 static bool
662 inbounds_memaccess_p (tree t)
663 {
664   if (TREE_CODE (t) != COMPONENT_REF)
665     return false;
666
667   tree mref = TREE_OPERAND (t, 0);
668   if (TREE_CODE (mref) != MEM_REF)
669     return false;
670
671   /* Consider the access if its type is a derived class.  */
672   tree mreftype = TREE_TYPE (mref);
673   if (!RECORD_OR_UNION_TYPE_P (mreftype)
674       || !TYPE_BINFO (mreftype))
675     return false;
676
677   /* Compute the size of the referenced object (it could be dynamically
678      allocated).  */
679   access_ref aref;   // unused
680   tree refop = TREE_OPERAND (mref, 0);
681   tree refsize = compute_objsize (refop, 1, &aref);
682   if (!refsize || TREE_CODE (refsize) != INTEGER_CST)
683     return false;
684
685   /* Compute the byte offset of the member within its enclosing class.  */
686   tree fld = TREE_OPERAND (t, 1);
687   tree fldpos = byte_position (fld);
688   if (TREE_CODE (fldpos) != INTEGER_CST)
689     return false;
690
691   /* Compute the byte offset of the member with the outermost complete
692      object by adding its offset computed above to the MEM_REF offset.  */
693   tree refoff = TREE_OPERAND (mref, 1);
694   tree fldoff = int_const_binop (PLUS_EXPR, fldpos, refoff);
695   /* Return false if the member offset is greater or equal to the size
696      of the complete object.  */
697   if (!tree_int_cst_lt (fldoff, refsize))
698     return false;
699
700   tree fldsiz = DECL_SIZE_UNIT (fld);
701   if (!fldsiz || TREE_CODE (fldsiz) != INTEGER_CST)
702     return false;
703
704   /* Return true if the offset just past the end of the member is less
705      than or equal to the size of the complete object.  */
706   tree fldend = int_const_binop (PLUS_EXPR, fldoff, fldsiz);
707   return tree_int_cst_le (fldend, refsize);
708 }
709
710 /* Callback for walk_tree to check a tree for out of bounds array
711    accesses.  The array_bounds_checker class is passed in DATA.  */
712
713 tree
714 array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
715                                           void *data)
716 {
717   tree t = *tp;
718   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
719   location_t location;
720
721   if (EXPR_HAS_LOCATION (t))
722     location = EXPR_LOCATION (t);
723   else
724     location = gimple_location (wi->stmt);
725
726   *walk_subtree = TRUE;
727
728   bool warned = false;
729   array_bounds_checker *checker = (array_bounds_checker *) wi->info;
730   if (TREE_CODE (t) == ARRAY_REF)
731     warned = checker->check_array_ref (location, t,
732                                        false/*ignore_off_by_one*/);
733   else if (TREE_CODE (t) == MEM_REF)
734     warned = checker->check_mem_ref (location, t,
735                                      false /*ignore_off_by_one*/);
736   else if (TREE_CODE (t) == ADDR_EXPR)
737     {
738       checker->check_addr_expr (location, t);
739       *walk_subtree = false;
740     }
741   else if (inbounds_memaccess_p (t))
742     /* Hack: Skip MEM_REF checks in accesses to a member of a base class
743        at an offset that's within the bounds of the enclosing object.
744        See pr98266 and pr97595.  */
745     *walk_subtree = false;
746
747   /* Propagate the no-warning bit to the outer statement to avoid also
748      issuing -Wstringop-overflow/-overread for the out-of-bounds accesses.  */
749   if (warned)
750     suppress_warning (wi->stmt, OPT_Warray_bounds);
751
752   return NULL_TREE;
753 }
754
755 /* A dom_walker subclass for use by check_all_array_refs, to walk over
756    all statements of all reachable BBs and call check_array_bounds on
757    them.  */
758
759 class check_array_bounds_dom_walker : public dom_walker
760 {
761 public:
762   check_array_bounds_dom_walker (array_bounds_checker *checker)
763     : dom_walker (CDI_DOMINATORS,
764                   /* Discover non-executable edges, preserving EDGE_EXECUTABLE
765                      flags, so that we can merge in information on
766                      non-executable edges from vrp_folder .  */
767                   REACHABLE_BLOCKS_PRESERVING_FLAGS),
768     checker (checker) { }
769   ~check_array_bounds_dom_walker () {}
770
771   edge before_dom_children (basic_block) FINAL OVERRIDE;
772
773 private:
774   array_bounds_checker *checker;
775 };
776
777 /* Implementation of dom_walker::before_dom_children.
778
779    Walk over all statements of BB and call check_array_bounds on them,
780    and determine if there's a unique successor edge.  */
781
782 edge
783 check_array_bounds_dom_walker::before_dom_children (basic_block bb)
784 {
785   gimple_stmt_iterator si;
786   for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
787     {
788       gimple *stmt = gsi_stmt (si);
789       struct walk_stmt_info wi;
790       if (!gimple_has_location (stmt)
791           || is_gimple_debug (stmt))
792         continue;
793
794       memset (&wi, 0, sizeof (wi));
795
796       wi.info = checker;
797
798       walk_gimple_op (stmt, array_bounds_checker::check_array_bounds, &wi);
799     }
800
801   /* Determine if there's a unique successor edge, and if so, return
802      that back to dom_walker, ensuring that we don't visit blocks that
803      became unreachable during the VRP propagation
804      (PR tree-optimization/83312).  */
805   return find_taken_edge (bb, NULL_TREE);
806 }
807
808 void
809 array_bounds_checker::check ()
810 {
811   check_array_bounds_dom_walker w (this);
812   w.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
813 }