syscall, runtime: always call XSI strerror_r
[official-gcc.git] / gcc / gimple-array-bounds.cc
blobeae49ab3910ad57288d772e63af10fd610527a84
1 /* Array bounds checking.
2 Copyright (C) 2005-2022 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
42 array_bounds_checker::array_bounds_checker (struct function *func,
43 range_query *qry)
44 : fun (func), m_ptr_qry (qry)
46 /* No-op. */
49 const value_range *
50 array_bounds_checker::get_value_range (const_tree op, gimple *stmt)
52 return m_ptr_qry.rvals->get_value_range (op, stmt);
55 /* Try to determine the DECL that REF refers to. Return the DECL or
56 the expression closest to it. Used in informational notes pointing
57 to referenced objects or function parameters. */
59 static tree
60 get_base_decl (tree ref)
62 tree base = get_base_address (ref);
63 if (DECL_P (base))
64 return base;
66 if (TREE_CODE (base) == MEM_REF)
67 base = TREE_OPERAND (base, 0);
69 if (TREE_CODE (base) != SSA_NAME)
70 return base;
74 gimple *def = SSA_NAME_DEF_STMT (base);
75 if (gimple_assign_single_p (def))
77 base = gimple_assign_rhs1 (def);
78 return base;
81 if (!gimple_nop_p (def))
82 return base;
84 break;
85 } while (true);
87 tree var = SSA_NAME_VAR (base);
88 if (TREE_CODE (var) != PARM_DECL)
89 return base;
91 return var;
94 /* Return the constant byte size of the object or type referenced by
95 the MEM_REF ARG. On success, set *PREF to the DECL or expression
96 ARG refers to. Otherwise return null. */
98 static tree
99 get_ref_size (tree arg, tree *pref)
101 if (TREE_CODE (arg) != MEM_REF)
102 return NULL_TREE;
104 arg = TREE_OPERAND (arg, 0);
105 tree type = TREE_TYPE (arg);
106 if (!POINTER_TYPE_P (type))
107 return NULL_TREE;
109 type = TREE_TYPE (type);
110 if (TREE_CODE (type) != ARRAY_TYPE)
111 return NULL_TREE;
113 tree nbytes = TYPE_SIZE_UNIT (type);
114 if (!nbytes || TREE_CODE (nbytes) != INTEGER_CST)
115 return NULL_TREE;
117 *pref = get_base_decl (arg);
118 return nbytes;
121 /* Return true if REF is (likely) an ARRAY_REF to a trailing array member
122 of a struct. It refines array_ref_flexible_size_p by detecting a pointer
123 to an array and an array parameter declared using the [N] syntax (as
124 opposed to a pointer) and returning false. Set *PREF to the decl or
125 expression REF refers to. */
127 static bool
128 trailing_array (tree arg, tree *pref)
130 tree ref = arg;
131 tree base = get_base_decl (arg);
132 while (TREE_CODE (ref) == ARRAY_REF || TREE_CODE (ref) == MEM_REF)
133 ref = TREE_OPERAND (ref, 0);
135 if (TREE_CODE (ref) == COMPONENT_REF)
137 *pref = TREE_OPERAND (ref, 1);
138 tree type = TREE_TYPE (*pref);
139 if (TREE_CODE (type) == ARRAY_TYPE)
141 /* A multidimensional trailing array is not considered special
142 no matter what its major bound is. */
143 type = TREE_TYPE (type);
144 if (TREE_CODE (type) == ARRAY_TYPE)
145 return false;
148 else
149 *pref = base;
151 tree basetype = TREE_TYPE (base);
152 if (TREE_CODE (base) == PARM_DECL
153 && POINTER_TYPE_P (basetype))
155 tree ptype = TREE_TYPE (basetype);
156 if (TREE_CODE (ptype) == ARRAY_TYPE)
157 return false;
160 return array_ref_flexible_size_p (arg);
163 /* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible
164 arrays and "struct" hacks. If VRP can determine that the array
165 subscript is a constant, check if it is outside valid range. If
166 the array subscript is a RANGE, warn if it is non-overlapping with
167 valid range. IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside
168 a ADDR_EXPR. Return true if a warning has been issued or if
169 no-warning is set. */
171 bool
172 array_bounds_checker::check_array_ref (location_t location, tree ref,
173 gimple *stmt, bool ignore_off_by_one)
175 if (warning_suppressed_p (ref, OPT_Warray_bounds))
176 /* Return true to have the caller prevent warnings for enclosing
177 refs. */
178 return true;
180 tree low_sub = TREE_OPERAND (ref, 1);
181 tree up_sub = low_sub;
182 tree up_bound = array_ref_up_bound (ref);
184 /* Referenced decl if one can be determined. */
185 tree decl = NULL_TREE;
187 /* Set for accesses to interior zero-length arrays. */
188 special_array_member sam{ };
190 tree up_bound_p1;
192 if (!up_bound
193 || TREE_CODE (up_bound) != INTEGER_CST
194 || (warn_array_bounds < 2 && trailing_array (ref, &decl)))
196 /* Accesses to trailing arrays via pointers may access storage
197 beyond the types array bounds. For such arrays, or for flexible
198 array members, as well as for other arrays of an unknown size,
199 replace the upper bound with a more permissive one that assumes
200 the size of the largest object is PTRDIFF_MAX. */
201 tree eltsize = array_ref_element_size (ref);
203 if (TREE_CODE (eltsize) != INTEGER_CST
204 || integer_zerop (eltsize))
206 up_bound = NULL_TREE;
207 up_bound_p1 = NULL_TREE;
209 else
211 tree ptrdiff_max = TYPE_MAX_VALUE (ptrdiff_type_node);
212 tree maxbound = ptrdiff_max;
213 tree arg = TREE_OPERAND (ref, 0);
215 const bool compref = TREE_CODE (arg) == COMPONENT_REF;
216 if (compref)
218 /* Try to determine the size of the trailing array from
219 its initializer (if it has one). */
220 if (tree refsize = component_ref_size (arg, &sam))
221 if (TREE_CODE (refsize) == INTEGER_CST)
222 maxbound = refsize;
225 if (maxbound == ptrdiff_max)
227 /* Try to determine the size of the base object. Avoid
228 COMPONENT_REF already tried above. Using its DECL_SIZE
229 size wouldn't necessarily be correct if the reference is
230 to its flexible array member initialized in a different
231 translation unit. */
232 poly_int64 off;
233 if (tree base = get_addr_base_and_unit_offset (arg, &off))
235 if (TREE_CODE (base) == MEM_REF)
237 /* Try to determine the size from a pointer to
238 an array if BASE is one. */
239 if (tree size = get_ref_size (base, &decl))
240 maxbound = size;
242 else if (!compref && DECL_P (base))
243 if (tree basesize = DECL_SIZE_UNIT (base))
244 if (TREE_CODE (basesize) == INTEGER_CST)
246 maxbound = basesize;
247 decl = base;
250 if (known_gt (off, 0))
251 maxbound = wide_int_to_tree (sizetype,
252 wi::sub (wi::to_wide (maxbound),
253 off));
256 else
257 maxbound = fold_convert (sizetype, maxbound);
259 up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
261 if (up_bound_p1 != NULL_TREE)
262 up_bound = int_const_binop (MINUS_EXPR, up_bound_p1,
263 build_int_cst (ptrdiff_type_node, 1));
264 else
265 up_bound = NULL_TREE;
268 else
269 up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
270 build_int_cst (TREE_TYPE (up_bound), 1));
272 tree low_bound = array_ref_low_bound (ref);
274 tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
276 bool warned = false;
278 /* Empty array. */
279 if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
280 warned = warning_at (location, OPT_Warray_bounds,
281 "array subscript %E is outside array bounds of %qT",
282 low_sub, artype);
284 const value_range *vr = NULL;
285 if (TREE_CODE (low_sub) == SSA_NAME)
287 vr = get_value_range (low_sub, stmt);
288 if (!vr->undefined_p () && !vr->varying_p ())
290 low_sub = vr->kind () == VR_RANGE ? vr->max () : vr->min ();
291 up_sub = vr->kind () == VR_RANGE ? vr->min () : vr->max ();
295 if (warned)
296 ; /* Do nothing. */
297 else if (vr && vr->kind () == VR_ANTI_RANGE)
299 if (up_bound
300 && TREE_CODE (up_sub) == INTEGER_CST
301 && (ignore_off_by_one
302 ? tree_int_cst_lt (up_bound, up_sub)
303 : tree_int_cst_le (up_bound, up_sub))
304 && TREE_CODE (low_sub) == INTEGER_CST
305 && tree_int_cst_le (low_sub, low_bound))
306 warned = warning_at (location, OPT_Warray_bounds,
307 "array subscript [%E, %E] is outside "
308 "array bounds of %qT",
309 low_sub, up_sub, artype);
311 else if (up_bound
312 && TREE_CODE (up_sub) == INTEGER_CST
313 && (ignore_off_by_one
314 ? !tree_int_cst_le (up_sub, up_bound_p1)
315 : !tree_int_cst_le (up_sub, up_bound)))
316 warned = warning_at (location, OPT_Warray_bounds,
317 "array subscript %E is above array bounds of %qT",
318 up_sub, artype);
319 else if (TREE_CODE (low_sub) == INTEGER_CST
320 && tree_int_cst_lt (low_sub, low_bound))
321 warned = warning_at (location, OPT_Warray_bounds,
322 "array subscript %E is below array bounds of %qT",
323 low_sub, artype);
325 if (!warned && sam == special_array_member::int_0)
326 warned = warning_at (location, OPT_Wzero_length_bounds,
327 (TREE_CODE (low_sub) == INTEGER_CST
328 ? G_("array subscript %E is outside the bounds "
329 "of an interior zero-length array %qT")
330 : G_("array subscript %qE is outside the bounds "
331 "of an interior zero-length array %qT")),
332 low_sub, artype);
334 if (warned)
336 if (dump_file && (dump_flags & TDF_DETAILS))
338 fprintf (dump_file, "Array bound warning for ");
339 dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
340 fprintf (dump_file, "\n");
343 /* Avoid more warnings when checking more significant subscripts
344 of the same expression. */
345 ref = TREE_OPERAND (ref, 0);
346 suppress_warning (ref, OPT_Warray_bounds);
348 if (decl)
349 ref = decl;
351 tree rec = NULL_TREE;
352 if (TREE_CODE (ref) == COMPONENT_REF)
354 /* For a reference to a member of a struct object also mention
355 the object if it's known. It may be defined in a different
356 function than the out-of-bounds access. */
357 rec = TREE_OPERAND (ref, 0);
358 if (!VAR_P (rec))
359 rec = NULL_TREE;
360 ref = TREE_OPERAND (ref, 1);
363 if (DECL_P (ref))
364 inform (DECL_SOURCE_LOCATION (ref), "while referencing %qD", ref);
365 if (rec && DECL_P (rec))
366 inform (DECL_SOURCE_LOCATION (rec), "defined here %qD", rec);
369 return warned;
372 /* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
373 references to string constants. If VRP can determine that the array
374 subscript is a constant, check if it is outside valid range.
375 If the array subscript is a RANGE, warn if it is non-overlapping
376 with valid range.
377 IGNORE_OFF_BY_ONE is true if the MEM_REF is inside an ADDR_EXPR
378 (used to allow one-past-the-end indices for code that takes
379 the address of the just-past-the-end element of an array).
380 Returns true if a warning has been issued. */
382 bool
383 array_bounds_checker::check_mem_ref (location_t location, tree ref,
384 bool ignore_off_by_one)
386 if (warning_suppressed_p (ref, OPT_Warray_bounds))
387 return false;
389 /* The statement used to allocate the array or null. */
390 gimple *alloc_stmt = NULL;
391 /* For an allocation statement, the low bound of the size range. */
392 offset_int minbound = 0;
393 /* The type and size of the access. */
394 tree axstype = TREE_TYPE (ref);
395 offset_int axssize = 0;
396 if (tree access_size = TYPE_SIZE_UNIT (axstype))
397 if (TREE_CODE (access_size) == INTEGER_CST)
398 axssize = wi::to_offset (access_size);
400 access_ref aref;
401 if (!m_ptr_qry.get_ref (ref, m_stmt, &aref, 0))
402 return false;
404 if (aref.offset_in_range (axssize))
405 return false;
407 if (TREE_CODE (aref.ref) == SSA_NAME)
409 gimple *def = SSA_NAME_DEF_STMT (aref.ref);
410 if (is_gimple_call (def))
412 /* Save the allocation call and the low bound on the size. */
413 alloc_stmt = def;
414 minbound = aref.sizrng[0];
418 /* The range of the byte offset into the reference. Adjusted below. */
419 offset_int offrange[2] = { aref.offrng[0], aref.offrng[1] };
421 /* The type of the referenced object. */
422 tree reftype = TREE_TYPE (aref.ref);
423 /* The size of the referenced array element. */
424 offset_int eltsize = 1;
425 if (POINTER_TYPE_P (reftype))
426 reftype = TREE_TYPE (reftype);
428 if (TREE_CODE (reftype) == FUNCTION_TYPE)
429 /* Restore the original (pointer) type and avoid trying to create
430 an array of functions (done below). */
431 reftype = TREE_TYPE (aref.ref);
432 else
434 /* The byte size of the array has already been determined above
435 based on a pointer ARG. Set ELTSIZE to the size of the type
436 it points to and REFTYPE to the array with the size, rounded
437 down as necessary. */
438 if (TREE_CODE (reftype) == ARRAY_TYPE)
439 reftype = TREE_TYPE (reftype);
440 if (tree refsize = TYPE_SIZE_UNIT (reftype))
441 if (TREE_CODE (refsize) == INTEGER_CST)
442 eltsize = wi::to_offset (refsize);
444 const offset_int nelts = aref.sizrng[1] / eltsize;
445 reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
448 /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
449 is set (when taking the address of the one-past-last element
450 of an array) but always use the stricter bound in diagnostics. */
451 offset_int ubound = aref.sizrng[1];
452 if (ignore_off_by_one)
453 ubound += eltsize;
455 /* Set if the lower bound of the subscript is out of bounds. */
456 const bool lboob = (aref.sizrng[1] == 0
457 || offrange[0] >= ubound
458 || offrange[1] < 0);
459 /* Set if only the upper bound of the subscript is out of bounds.
460 This can happen when using a bigger type to index into an array
461 of a smaller type, as is common with unsigned char. */
462 const bool uboob = !lboob && offrange[0] + axssize > ubound;
463 if (lboob || uboob)
465 /* Treat a reference to a non-array object as one to an array
466 of a single element. */
467 if (TREE_CODE (reftype) != ARRAY_TYPE)
468 reftype = build_printable_array_type (reftype, 1);
470 /* Extract the element type out of MEM_REF and use its size
471 to compute the index to print in the diagnostic; arrays
472 in MEM_REF don't mean anything. A type with no size like
473 void is as good as having a size of 1. */
474 tree type = strip_array_types (TREE_TYPE (ref));
475 if (tree size = TYPE_SIZE_UNIT (type))
477 offrange[0] = offrange[0] / wi::to_offset (size);
478 offrange[1] = offrange[1] / wi::to_offset (size);
482 bool warned = false;
483 if (lboob)
485 if (offrange[0] == offrange[1])
486 warned = warning_at (location, OPT_Warray_bounds,
487 "array subscript %wi is outside array bounds "
488 "of %qT",
489 offrange[0].to_shwi (), reftype);
490 else
491 warned = warning_at (location, OPT_Warray_bounds,
492 "array subscript [%wi, %wi] is outside "
493 "array bounds of %qT",
494 offrange[0].to_shwi (),
495 offrange[1].to_shwi (), reftype);
497 else if (uboob && !ignore_off_by_one)
499 tree backtype = reftype;
500 if (alloc_stmt)
501 /* If the memory was dynamically allocated refer to it as if
502 it were an untyped array of bytes. */
503 backtype = build_array_type_nelts (unsigned_char_type_node,
504 aref.sizrng[1].to_uhwi ());
506 warned = warning_at (location, OPT_Warray_bounds,
507 "array subscript %<%T[%wi]%> is partly "
508 "outside array bounds of %qT",
509 axstype, offrange[0].to_shwi (), backtype);
512 if (warned)
514 /* TODO: Determine the access from the statement and use it. */
515 aref.inform_access (access_none);
516 suppress_warning (ref, OPT_Warray_bounds);
517 return true;
520 if (warn_array_bounds < 2)
521 return false;
523 /* At level 2 check also intermediate offsets. */
524 int i = 0;
525 if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound)
527 HOST_WIDE_INT tmpidx = (aref.offmax[i] / eltsize).to_shwi ();
529 if (warning_at (location, OPT_Warray_bounds,
530 "intermediate array offset %wi is outside array bounds "
531 "of %qT", tmpidx, reftype))
533 suppress_warning (ref, OPT_Warray_bounds);
534 return true;
538 return false;
541 /* Searches if the expr T, located at LOCATION computes
542 address of an ARRAY_REF, and call check_array_ref on it. */
544 void
545 array_bounds_checker::check_addr_expr (location_t location, tree t,
546 gimple *stmt)
548 /* For the most significant subscript only, accept taking the address
549 of the just-past-the-end element. */
550 bool ignore_off_by_one = true;
552 /* Check each ARRAY_REF and MEM_REF in the reference chain. */
555 bool warned = false;
556 if (TREE_CODE (t) == ARRAY_REF)
558 warned = check_array_ref (location, t, stmt, ignore_off_by_one);
559 ignore_off_by_one = false;
561 else if (TREE_CODE (t) == MEM_REF)
562 warned = check_mem_ref (location, t, ignore_off_by_one);
564 if (warned)
565 suppress_warning (t, OPT_Warray_bounds);
567 t = TREE_OPERAND (t, 0);
569 while (handled_component_p (t) || TREE_CODE (t) == MEM_REF);
571 if (TREE_CODE (t) != MEM_REF
572 || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
573 || warning_suppressed_p (t, OPT_Warray_bounds))
574 return;
576 tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
577 tree low_bound, up_bound, el_sz;
578 if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
579 || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
580 || !TYPE_DOMAIN (TREE_TYPE (tem)))
581 return;
583 low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
584 up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
585 el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
586 if (!low_bound
587 || TREE_CODE (low_bound) != INTEGER_CST
588 || !up_bound
589 || TREE_CODE (up_bound) != INTEGER_CST
590 || !el_sz
591 || TREE_CODE (el_sz) != INTEGER_CST)
592 return;
594 offset_int idx;
595 if (!mem_ref_offset (t).is_constant (&idx))
596 return;
598 bool warned = false;
599 idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
600 if (idx < 0)
602 if (dump_file && (dump_flags & TDF_DETAILS))
604 fprintf (dump_file, "Array bound warning for ");
605 dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
606 fprintf (dump_file, "\n");
608 warned = warning_at (location, OPT_Warray_bounds,
609 "array subscript %wi is below "
610 "array bounds of %qT",
611 idx.to_shwi (), TREE_TYPE (tem));
613 else if (idx > (wi::to_offset (up_bound)
614 - wi::to_offset (low_bound) + 1))
616 if (dump_file && (dump_flags & TDF_DETAILS))
618 fprintf (dump_file, "Array bound warning for ");
619 dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
620 fprintf (dump_file, "\n");
622 warned = warning_at (location, OPT_Warray_bounds,
623 "array subscript %wu is above "
624 "array bounds of %qT",
625 idx.to_uhwi (), TREE_TYPE (tem));
628 if (warned)
630 if (DECL_P (t))
631 inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
633 suppress_warning (t, OPT_Warray_bounds);
637 /* Return true if T is a reference to a member of a base class that's within
638 the bounds of the enclosing complete object. The function "hacks" around
639 problems discussed in pr98266 and pr97595. */
641 static bool
642 inbounds_memaccess_p (tree t, gimple *stmt)
644 if (TREE_CODE (t) != COMPONENT_REF)
645 return false;
647 tree mref = TREE_OPERAND (t, 0);
648 if (TREE_CODE (mref) != MEM_REF)
649 return false;
651 /* Consider the access if its type is a derived class. */
652 tree mreftype = TREE_TYPE (mref);
653 if (!RECORD_OR_UNION_TYPE_P (mreftype)
654 || !TYPE_BINFO (mreftype))
655 return false;
657 /* Compute the size of the referenced object (it could be dynamically
658 allocated). */
659 access_ref aref; // unused
660 tree refop = TREE_OPERAND (mref, 0);
661 tree refsize = compute_objsize (refop, stmt, 1, &aref);
662 if (!refsize || TREE_CODE (refsize) != INTEGER_CST)
663 return false;
665 /* Compute the byte offset of the member within its enclosing class. */
666 tree fld = TREE_OPERAND (t, 1);
667 tree fldpos = byte_position (fld);
668 if (TREE_CODE (fldpos) != INTEGER_CST)
669 return false;
671 /* Compute the byte offset of the member with the outermost complete
672 object by adding its offset computed above to the MEM_REF offset. */
673 tree refoff = TREE_OPERAND (mref, 1);
674 tree fldoff = int_const_binop (PLUS_EXPR, fldpos, refoff);
675 /* Return false if the member offset is greater or equal to the size
676 of the complete object. */
677 if (!tree_int_cst_lt (fldoff, refsize))
678 return false;
680 tree fldsiz = DECL_SIZE_UNIT (fld);
681 if (!fldsiz || TREE_CODE (fldsiz) != INTEGER_CST)
682 return false;
684 /* Return true if the offset just past the end of the member is less
685 than or equal to the size of the complete object. */
686 tree fldend = int_const_binop (PLUS_EXPR, fldoff, fldsiz);
687 return tree_int_cst_le (fldend, refsize);
690 /* Callback for walk_tree to check a tree for out of bounds array
691 accesses. The array_bounds_checker class is passed in DATA. */
693 tree
694 array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
695 void *data)
697 tree t = *tp;
698 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
700 location_t location;
702 if (EXPR_HAS_LOCATION (t))
703 location = EXPR_LOCATION (t);
704 else
705 location = gimple_location (wi->stmt);
707 *walk_subtree = TRUE;
709 bool warned = false;
710 array_bounds_checker *checker = (array_bounds_checker *) wi->info;
711 gcc_assert (checker->m_stmt == wi->stmt);
713 if (TREE_CODE (t) == ARRAY_REF)
714 warned = checker->check_array_ref (location, t, wi->stmt,
715 false/*ignore_off_by_one*/);
716 else if (TREE_CODE (t) == MEM_REF)
717 warned = checker->check_mem_ref (location, t,
718 false /*ignore_off_by_one*/);
719 else if (TREE_CODE (t) == ADDR_EXPR)
721 checker->check_addr_expr (location, t, wi->stmt);
722 *walk_subtree = false;
724 else if (inbounds_memaccess_p (t, wi->stmt))
725 /* Hack: Skip MEM_REF checks in accesses to a member of a base class
726 at an offset that's within the bounds of the enclosing object.
727 See pr98266 and pr97595. */
728 *walk_subtree = false;
730 /* Propagate the no-warning bit to the outer statement to avoid also
731 issuing -Wstringop-overflow/-overread for the out-of-bounds accesses. */
732 if (warned)
733 suppress_warning (wi->stmt, OPT_Warray_bounds);
735 return NULL_TREE;
738 /* A dom_walker subclass for use by check_all_array_refs, to walk over
739 all statements of all reachable BBs and call check_array_bounds on
740 them. */
742 class check_array_bounds_dom_walker : public dom_walker
744 public:
745 check_array_bounds_dom_walker (array_bounds_checker *checker)
746 : dom_walker (CDI_DOMINATORS,
747 /* Discover non-executable edges, preserving EDGE_EXECUTABLE
748 flags, so that we can merge in information on
749 non-executable edges from vrp_folder . */
750 REACHABLE_BLOCKS_PRESERVING_FLAGS),
751 checker (checker) { }
752 ~check_array_bounds_dom_walker () {}
754 edge before_dom_children (basic_block) final override;
756 private:
757 array_bounds_checker *checker;
760 /* Implementation of dom_walker::before_dom_children.
762 Walk over all statements of BB and call check_array_bounds on them,
763 and determine if there's a unique successor edge. */
765 edge
766 check_array_bounds_dom_walker::before_dom_children (basic_block bb)
768 gimple_stmt_iterator si;
769 for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
771 gimple *stmt = gsi_stmt (si);
772 if (!gimple_has_location (stmt)
773 || is_gimple_debug (stmt))
774 continue;
776 struct walk_stmt_info wi{ };
777 wi.info = checker;
778 checker->m_stmt = stmt;
780 walk_gimple_op (stmt, array_bounds_checker::check_array_bounds, &wi);
783 /* Determine if there's a unique successor edge, and if so, return
784 that back to dom_walker, ensuring that we don't visit blocks that
785 became unreachable during the VRP propagation
786 (PR tree-optimization/83312). */
787 return find_taken_edge (bb, NULL_TREE);
790 void
791 array_bounds_checker::check ()
793 check_array_bounds_dom_walker w (this);
794 w.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));