d: Merge upstream dmd, druntime c8ae4adb2e, phobos 792c8b7c1.
[official-gcc.git] / gcc / gimple-ssa-warn-restrict.cc
blob107ba278798d26ffddff9265b67d5442b5a2707c
1 /* Pass to detect and issue warnings for violations of the restrict
2 qualifier.
3 Copyright (C) 2017-2022 Free Software Foundation, Inc.
4 Contributed by Martin Sebor <msebor@redhat.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "backend.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "tree-pass.h"
29 #include "pointer-query.h"
30 #include "ssa.h"
31 #include "gimple-pretty-print.h"
32 #include "gimple-ssa-warn-access.h"
33 #include "gimple-ssa-warn-restrict.h"
34 #include "diagnostic-core.h"
35 #include "fold-const.h"
36 #include "gimple-iterator.h"
37 #include "tree-dfa.h"
38 #include "tree-ssa.h"
39 #include "tree-cfg.h"
40 #include "tree-object-size.h"
41 #include "calls.h"
42 #include "cfgloop.h"
43 #include "intl.h"
44 #include "gimple-range.h"
46 namespace {
48 const pass_data pass_data_wrestrict = {
49 GIMPLE_PASS,
50 "wrestrict",
51 OPTGROUP_NONE,
52 TV_NONE,
53 PROP_cfg, /* Properties_required. */
54 0, /* properties_provided. */
55 0, /* properties_destroyed. */
56 0, /* properties_start */
57 0, /* properties_finish */
60 /* Pass to detect violations of strict aliasing requirements in calls
61 to built-in string and raw memory functions. */
62 class pass_wrestrict : public gimple_opt_pass
64 public:
65 pass_wrestrict (gcc::context *);
67 bool gate (function *) final override;
68 unsigned int execute (function *) final override;
70 void check_call (gimple *);
72 void check_block (basic_block);
74 /* A pointer_query object to store information about pointers and
75 their targets in. */
76 pointer_query m_ptr_qry;
79 pass_wrestrict::pass_wrestrict (gcc::context *ctxt)
80 : gimple_opt_pass (pass_data_wrestrict, ctxt),
81 m_ptr_qry ()
82 { }
84 bool
85 pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
87 return warn_array_bounds || warn_restrict || warn_stringop_overflow;
90 void
91 pass_wrestrict::check_block (basic_block bb)
93 /* Iterate over statements, looking for function calls. */
94 for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
96 gimple *stmt = gsi_stmt (si);
97 if (!is_gimple_call (stmt))
98 continue;
100 check_call (stmt);
104 unsigned
105 pass_wrestrict::execute (function *fun)
107 /* Create a new ranger instance and associate it with FUN. */
108 m_ptr_qry.rvals = enable_ranger (fun);
110 basic_block bb;
111 FOR_EACH_BB_FN (bb, fun)
112 check_block (bb);
114 m_ptr_qry.flush_cache ();
116 /* Release the ranger instance and replace it with a global ranger.
117 Also reset the pointer since calling disable_ranger() deletes it. */
118 disable_ranger (fun);
119 m_ptr_qry.rvals = NULL;
121 return 0;
124 /* Description of a memory reference by a built-in function. This
125 is similar to ao_ref but made especially suitable for -Wrestrict
126 and not for optimization. */
127 class builtin_memref
129 public:
130 /* The original pointer argument to the built-in function. */
131 tree ptr;
132 /* The referenced subobject or NULL if not available, and the base
133 object of the memory reference or NULL. */
134 tree ref;
135 tree base;
137 /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
138 and negative until (possibly lazily) initialized. */
139 offset_int basesize;
140 /* Same for the subobject. */
141 offset_int refsize;
143 /* The non-negative offset of the referenced subobject. Used to avoid
144 warnings for (apparently) possibly but not definitively overlapping
145 accesses to member arrays. Negative when unknown/invalid. */
146 offset_int refoff;
148 /* The offset range relative to the base. */
149 offset_int offrange[2];
150 /* The size range of the access to this reference. */
151 offset_int sizrange[2];
153 /* Cached result of get_max_objsize(). */
154 const offset_int maxobjsize;
156 /* True for "bounded" string functions like strncat, and strncpy
157 and their variants that specify either an exact or upper bound
158 on the size of the accesses they perform. For strncat both
159 the source and destination references are bounded. For strncpy
160 only the destination reference is. */
161 bool strbounded_p;
163 builtin_memref (pointer_query &, gimple *, tree, tree);
165 tree offset_out_of_bounds (int, offset_int[3]) const;
167 private:
168 /* Call statement to the built-in. */
169 gimple *stmt;
171 pointer_query &m_ptr_qry;
173 /* Ctor helper to set or extend OFFRANGE based on argument. */
174 void extend_offset_range (tree);
176 /* Ctor helper to determine BASE and OFFRANGE from argument. */
177 void set_base_and_offset (tree);
180 /* Description of a memory access by a raw memory or string built-in
181 function involving a pair of builtin_memref's. */
182 class builtin_access
184 public:
185 /* Destination and source memory reference. */
186 builtin_memref* const dstref;
187 builtin_memref* const srcref;
188 /* The size range of the access. It's the greater of the accesses
189 to the two references. */
190 HOST_WIDE_INT sizrange[2];
192 /* The minimum and maximum offset of an overlap of the access
193 (if it does, in fact, overlap), and the size of the overlap. */
194 HOST_WIDE_INT ovloff[2];
195 HOST_WIDE_INT ovlsiz[2];
197 /* True to consider valid only accesses to the smallest subobject
198 and false for raw memory functions. */
199 bool strict () const
201 return (detect_overlap != &builtin_access::generic_overlap
202 && detect_overlap != &builtin_access::no_overlap);
205 builtin_access (pointer_query &, gimple *,
206 builtin_memref &, builtin_memref &);
208 /* Entry point to determine overlap. */
209 bool overlap ();
211 offset_int write_off (tree) const;
213 void dump (FILE *) const;
215 private:
216 /* Implementation functions used to determine overlap. */
217 bool generic_overlap ();
218 bool strcat_overlap ();
219 bool strcpy_overlap ();
221 bool no_overlap ()
223 return false;
226 offset_int overlap_size (const offset_int [2], const offset_int[2],
227 offset_int [2]);
229 private:
230 /* Temporaries used to compute the final result. */
231 offset_int dstoff[2];
232 offset_int srcoff[2];
233 offset_int dstsiz[2];
234 offset_int srcsiz[2];
236 /* Pointer to a member function to call to determine overlap. */
237 bool (builtin_access::*detect_overlap) ();
240 /* Initialize a memory reference representation from a pointer EXPR and
241 a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed
242 to be unknown. STMT is the statement in which expr appears in. */
244 builtin_memref::builtin_memref (pointer_query &ptrqry, gimple *stmt, tree expr,
245 tree size)
246 : ptr (expr),
247 ref (),
248 base (),
249 basesize (-1),
250 refsize (-1),
251 refoff (HOST_WIDE_INT_MIN),
252 offrange (),
253 sizrange (),
254 maxobjsize (tree_to_shwi (max_object_size ())),
255 strbounded_p (),
256 stmt (stmt),
257 m_ptr_qry (ptrqry)
259 /* Unfortunately, wide_int default ctor is a no-op so array members
260 of the type must be set individually. */
261 offrange[0] = offrange[1] = 0;
262 sizrange[0] = sizrange[1] = 0;
264 if (!expr)
265 return;
267 /* Find the BASE object or pointer referenced by EXPR and set
268 the offset range OFFRANGE in the process. */
269 set_base_and_offset (expr);
271 if (size)
273 tree range[2];
274 /* Determine the size range, allowing for the result to be [0, 0]
275 for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */
276 get_size_range (m_ptr_qry.rvals, size, stmt, range, SR_ALLOW_ZERO);
277 sizrange[0] = wi::to_offset (range[0]);
278 sizrange[1] = wi::to_offset (range[1]);
279 /* get_size_range returns SIZE_MAX for the maximum size.
280 Constrain it to the real maximum of PTRDIFF_MAX. */
281 if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize)
282 sizrange[1] = maxobjsize;
284 else
285 sizrange[1] = maxobjsize;
287 if (!DECL_P (base))
288 return;
290 /* If the offset could be in the range of the referenced object
291 constrain its bounds so neither exceeds those of the object. */
292 if (offrange[0] < 0 && offrange[1] > 0)
293 offrange[0] = 0;
295 offset_int maxoff = maxobjsize;
296 tree basetype = TREE_TYPE (base);
297 if (TREE_CODE (basetype) == ARRAY_TYPE)
299 if (ref && array_ref_flexible_size_p (ref))
300 ; /* Use the maximum possible offset for an array that might
301 have flexible size. */
302 else if (tree basesize = TYPE_SIZE_UNIT (basetype))
303 if (TREE_CODE (basesize) == INTEGER_CST)
304 /* Size could be non-constant for a variable-length type such
305 as a struct with a VLA member (a GCC extension). */
306 maxoff = wi::to_offset (basesize);
309 if (offrange[0] >= 0)
311 if (offrange[1] < 0)
312 offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
313 else if (offrange[0] <= maxoff && offrange[1] > maxoff)
314 offrange[1] = maxoff;
318 /* Based on the initial length of the destination STARTLEN, returns
319 the offset of the first write access from the beginning of
320 the destination. Nonzero only for strcat-type of calls. */
322 offset_int builtin_access::write_off (tree startlen) const
324 if (detect_overlap != &builtin_access::strcat_overlap
325 || !startlen || TREE_CODE (startlen) != INTEGER_CST)
326 return 0;
328 return wi::to_offset (startlen);
331 /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
332 Pointer offsets are represented as unsigned sizetype but must be
333 treated as signed. */
335 void
336 builtin_memref::extend_offset_range (tree offset)
338 if (TREE_CODE (offset) == INTEGER_CST)
340 offset_int off = int_cst_value (offset);
341 if (off != 0)
343 offrange[0] += off;
344 offrange[1] += off;
346 return;
349 if (TREE_CODE (offset) == SSA_NAME)
351 /* A pointer offset is represented as sizetype but treated
352 as signed. */
353 wide_int min, max;
354 value_range_kind rng = VR_VARYING;
355 value_range vr;
356 if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt))
358 rng = vr.kind ();
359 if (!vr.undefined_p ())
361 min = wi::to_wide (vr.min ());
362 max = wi::to_wide (vr.max ());
366 if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
368 /* Convert an anti-range whose upper bound is less than
369 its lower bound to a signed range. */
370 offrange[0] += offset_int::from (max + 1, SIGNED);
371 offrange[1] += offset_int::from (min - 1, SIGNED);
372 return;
375 if (rng == VR_RANGE
376 && (DECL_P (base) || wi::lts_p (min, max)))
378 /* Preserve the bounds of the range for an offset into
379 a known object (it may be adjusted later relative to
380 a constant offset from its beginning). Otherwise use
381 the bounds only when they are ascending when treated
382 as signed. */
383 offrange[0] += offset_int::from (min, SIGNED);
384 offrange[1] += offset_int::from (max, SIGNED);
385 return;
388 /* Handle an anti-range the same as no range at all. */
389 gimple *stmt = SSA_NAME_DEF_STMT (offset);
390 tree type;
391 if (is_gimple_assign (stmt)
392 && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
393 && INTEGRAL_TYPE_P (type))
395 tree_code code = gimple_assign_rhs_code (stmt);
396 if (code == NOP_EXPR)
398 /* Use the bounds of the type of the NOP_EXPR operand
399 even if it's signed. The result doesn't trigger
400 warnings but makes their output more readable. */
401 offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
402 offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
403 return;
408 const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
409 const offset_int minoff = -maxoff - 1;
411 offrange[0] += minoff;
412 offrange[1] += maxoff;
415 /* Determines the base object or pointer of the reference EXPR
416 and the offset range from the beginning of the base. */
418 void
419 builtin_memref::set_base_and_offset (tree expr)
421 tree offset = NULL_TREE;
423 if (TREE_CODE (expr) == SSA_NAME)
425 /* Try to tease the offset out of the pointer. */
426 gimple *stmt = SSA_NAME_DEF_STMT (expr);
427 if (!base
428 && gimple_assign_single_p (stmt)
429 && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
430 expr = gimple_assign_rhs1 (stmt);
431 else if (is_gimple_assign (stmt))
433 tree_code code = gimple_assign_rhs_code (stmt);
434 if (CONVERT_EXPR_CODE_P (code))
436 tree rhs = gimple_assign_rhs1 (stmt);
437 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
438 expr = gimple_assign_rhs1 (stmt);
439 else
441 base = expr;
442 return;
445 else if (code == POINTER_PLUS_EXPR)
447 expr = gimple_assign_rhs1 (stmt);
448 offset = gimple_assign_rhs2 (stmt);
450 else
452 base = expr;
453 return;
456 else
458 /* FIXME: Handle PHI nodes in case like:
459 _12 = &MEM[(void *)&a + 2B] + _10;
461 <bb> [local count: 1073741824]:
462 # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
463 memcpy (prephitmp_13, p_7(D), 6); */
464 base = expr;
465 return;
469 if (TREE_CODE (expr) == ADDR_EXPR)
470 expr = TREE_OPERAND (expr, 0);
472 /* Stash the reference for offset validation. */
473 ref = expr;
475 poly_int64 bitsize, bitpos;
476 tree var_off;
477 machine_mode mode;
478 int sign, reverse, vol;
480 /* Determine the base object or pointer of the reference and
481 the constant bit offset from the beginning of the base.
482 If the offset has a non-constant component, it will be in
483 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
484 unused here. */
485 base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
486 &mode, &sign, &reverse, &vol);
488 /* get_inner_reference is not expected to return null. */
489 gcc_assert (base != NULL);
491 if (offset)
492 extend_offset_range (offset);
494 poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
496 /* Convert the poly_int64 offset to offset_int. The offset
497 should be constant but be prepared for it not to be just in
498 case. */
499 offset_int cstoff;
500 if (bytepos.is_constant (&cstoff))
502 offrange[0] += cstoff;
503 offrange[1] += cstoff;
505 /* Besides the reference saved above, also stash the offset
506 for validation. */
507 if (TREE_CODE (expr) == COMPONENT_REF)
508 refoff = cstoff;
510 else
511 offrange[1] += maxobjsize;
513 if (var_off)
515 if (TREE_CODE (var_off) == INTEGER_CST)
517 cstoff = wi::to_offset (var_off);
518 offrange[0] += cstoff;
519 offrange[1] += cstoff;
521 else
522 offrange[1] += maxobjsize;
525 if (TREE_CODE (base) == MEM_REF)
527 tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
528 extend_offset_range (memrefoff);
530 if (refoff != HOST_WIDE_INT_MIN
531 && TREE_CODE (expr) == COMPONENT_REF)
533 /* Bump up the offset of the referenced subobject to reflect
534 the offset to the enclosing object. For example, so that
536 struct S { char a, b[3]; } s[2];
537 strcpy (s[1].b, "1234");
538 REFOFF is set to s[1].b - (char*)s. */
539 offset_int off = tree_to_shwi (memrefoff);
540 refoff += off;
542 if (!integer_zerop (memrefoff)
543 && !COMPLETE_TYPE_P (TREE_TYPE (expr))
544 && multiple_of_p (sizetype, memrefoff,
545 TYPE_SIZE_UNIT (TREE_TYPE (base)), true))
546 /* A non-zero offset into an array of struct with flexible array
547 members implies that the array is empty because there is no
548 way to initialize such a member when it belongs to an array.
549 This must be some sort of a bug. */
550 refsize = 0;
553 base = TREE_OPERAND (base, 0);
556 if (TREE_CODE (ref) == COMPONENT_REF)
557 if (tree size = component_ref_size (ref))
558 if (TREE_CODE (size) == INTEGER_CST)
559 refsize = wi::to_offset (size);
561 if (TREE_CODE (base) == SSA_NAME)
562 set_base_and_offset (base);
565 /* Return error_mark_node if the signed offset exceeds the bounds
566 of the address space (PTRDIFF_MAX). Otherwise, return either BASE
567 or REF when the offset exceeds the bounds of the BASE or REF object,
568 and set OOBOFF to the past-the-end offset formed by the reference,
569 including its size. OOBOFF is initially setto the range of offsets,
570 and OOBOFF[2] to the offset of the first write access (nonzero for
571 the strcat family). When STRICT is nonzero use REF size, when
572 available, otherwise use BASE size. When STRICT is greater than 1,
573 use the size of the last array member as the bound, otherwise treat
574 such a member as a flexible array member. Return NULL when the offset
575 is in bounds. */
577 tree
578 builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
580 if (!ptr)
581 return NULL_TREE;
583 /* The offset of the first write access or zero. */
584 offset_int wroff = ooboff[2];
586 /* A temporary, possibly adjusted, copy of the offset range. */
587 offset_int offrng[2] = { ooboff[0], ooboff[1] };
589 if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
591 /* Check for offset in an anti-range with a negative lower bound.
592 For such a range, consider only the non-negative subrange. */
593 if (offrng[1] < offrng[0] && offrng[1] < 0)
594 offrng[1] = maxobjsize;
597 /* Conservative offset of the last byte of the referenced object. */
598 offset_int endoff;
600 /* The bounds need not be ordered. Set HIB to use as the index
601 of the larger of the bounds and LOB as the opposite. */
602 bool hib = wi::les_p (offrng[0], offrng[1]);
603 bool lob = !hib;
605 /* Set to the size remaining in the object after subtracting
606 REFOFF. It may become negative as a result of negative indices
607 into the enclosing object, such as in:
608 extern struct S { char a[4], b[3], c[1]; } *p;
609 strcpy (p[-3].b, "123"); */
610 offset_int size = basesize;
611 tree obj = base;
613 const bool decl_p = DECL_P (obj);
615 if (basesize < 0)
617 endoff = offrng[lob] + (sizrange[0] - wroff);
619 /* For a reference through a pointer to an object of unknown size
620 all initial offsets are considered valid, positive as well as
621 negative, since the pointer itself can point past the beginning
622 of the object. However, the sum of the lower bound of the offset
623 and that of the size must be less than or equal than PTRDIFF_MAX. */
624 if (endoff > maxobjsize)
625 return error_mark_node;
627 /* When the referenced subobject is known, the end offset must be
628 within its bounds. Otherwise there is nothing to do. */
629 if (strict
630 && !decl_p
631 && ref
632 && refsize >= 0
633 && TREE_CODE (ref) == COMPONENT_REF)
635 /* If REFOFF is negative, SIZE will become negative here. */
636 size = refoff + refsize;
637 obj = ref;
639 else
640 return NULL_TREE;
643 /* A reference to an object of known size must be within the bounds
644 of either the base object or the subobject (see above for when
645 a subobject can be used). */
646 if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
647 return obj;
649 /* The extent of the reference must also be within the bounds of
650 the base object (if known) or the subobject or the maximum object
651 size otherwise. */
652 endoff = offrng[lob] + sizrange[0];
653 if (endoff > maxobjsize)
654 return error_mark_node;
656 if (strict
657 && decl_p
658 && ref
659 && refsize >= 0
660 && TREE_CODE (ref) == COMPONENT_REF)
662 /* If the reference is to a member subobject of a declared object,
663 the offset must be within the bounds of the subobject. */
664 size = refoff + refsize;
665 obj = ref;
668 if (endoff <= size)
669 return NULL_TREE;
671 /* Set the out-of-bounds offset range to be one greater than
672 that delimited by the reference including its size. */
673 ooboff[lob] = size;
675 if (endoff > ooboff[lob])
676 ooboff[hib] = endoff - 1;
677 else
678 ooboff[hib] = offrng[lob] + sizrange[1];
680 return obj;
683 /* Create an association between the memory references DST and SRC
684 for access by a call EXPR to a memory or string built-in funtion. */
686 builtin_access::builtin_access (pointer_query &ptrqry, gimple *call,
687 builtin_memref &dst,
688 builtin_memref &src)
689 : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
690 dstoff (), srcoff (), dstsiz (), srcsiz ()
692 dstoff[0] = dst.offrange[0];
693 dstoff[1] = dst.offrange[1];
695 /* Zero out since the offset_int ctors invoked above are no-op. */
696 srcoff[0] = srcoff[1] = 0;
697 dstsiz[0] = dstsiz[1] = 0;
698 srcsiz[0] = srcsiz[1] = 0;
700 /* Object Size Type to use to determine the size of the destination
701 and source objects. Overridden below for raw memory functions. */
702 int ostype = 1;
704 /* True when the size of one reference depends on the offset of
705 itself or the other. */
706 bool depends_p = true;
708 /* True when the size of the destination reference DSTREF has been
709 determined from SRCREF and so needs to be adjusted by the latter's
710 offset. Only meaningful for bounded string functions like strncpy. */
711 bool dstadjust_p = false;
713 /* The size argument number (depends on the built-in). */
714 unsigned sizeargno = 2;
716 tree func = gimple_call_fndecl (call);
717 switch (DECL_FUNCTION_CODE (func))
719 case BUILT_IN_MEMCPY:
720 case BUILT_IN_MEMCPY_CHK:
721 case BUILT_IN_MEMPCPY:
722 case BUILT_IN_MEMPCPY_CHK:
723 ostype = 0;
724 depends_p = false;
725 detect_overlap = &builtin_access::generic_overlap;
726 break;
728 case BUILT_IN_MEMMOVE:
729 case BUILT_IN_MEMMOVE_CHK:
730 /* For memmove there is never any overlap to check for. */
731 ostype = 0;
732 depends_p = false;
733 detect_overlap = &builtin_access::no_overlap;
734 break;
736 case BUILT_IN_MEMSET:
737 case BUILT_IN_MEMSET_CHK:
738 /* For memset there is never any overlap to check for. */
739 ostype = 0;
740 depends_p = false;
741 detect_overlap = &builtin_access::no_overlap;
742 break;
744 case BUILT_IN_STPNCPY:
745 case BUILT_IN_STPNCPY_CHK:
746 case BUILT_IN_STRNCPY:
747 case BUILT_IN_STRNCPY_CHK:
748 dstref->strbounded_p = true;
749 detect_overlap = &builtin_access::strcpy_overlap;
750 break;
752 case BUILT_IN_STPCPY:
753 case BUILT_IN_STPCPY_CHK:
754 case BUILT_IN_STRCPY:
755 case BUILT_IN_STRCPY_CHK:
756 detect_overlap = &builtin_access::strcpy_overlap;
757 break;
759 case BUILT_IN_STRCAT:
760 case BUILT_IN_STRCAT_CHK:
761 detect_overlap = &builtin_access::strcat_overlap;
762 break;
764 case BUILT_IN_STRNCAT:
765 case BUILT_IN_STRNCAT_CHK:
766 dstref->strbounded_p = true;
767 srcref->strbounded_p = true;
768 detect_overlap = &builtin_access::strcat_overlap;
769 break;
771 default:
772 /* Handle other string functions here whose access may need
773 to be validated for in-bounds offsets and non-overlapping
774 copies. */
775 return;
778 /* Try to determine the size of the base object. compute_objsize
779 expects a pointer so create one if BASE is a non-pointer object. */
780 if (dst.basesize < 0)
782 access_ref aref;
783 if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0)
784 dst.basesize = aref.sizrng[1];
785 else
786 dst.basesize = HOST_WIDE_INT_MIN;
789 if (src.base && src.basesize < 0)
791 access_ref aref;
792 if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0)
793 src.basesize = aref.sizrng[1];
794 else
795 src.basesize = HOST_WIDE_INT_MIN;
798 const offset_int maxobjsize = dst.maxobjsize;
800 /* Make adjustments for references to the same object by string
801 built-in functions to reflect the constraints imposed by
802 the function. */
804 /* For bounded string functions determine the range of the bound
805 on the access. For others, the range stays unbounded. */
806 offset_int bounds[2] = { maxobjsize, maxobjsize };
807 if (dstref->strbounded_p)
809 unsigned nargs = gimple_call_num_args (call);
810 if (nargs <= sizeargno)
811 return;
813 tree size = gimple_call_arg (call, sizeargno);
814 tree range[2];
815 if (get_size_range (ptrqry.rvals, size, call, range, true))
817 bounds[0] = wi::to_offset (range[0]);
818 bounds[1] = wi::to_offset (range[1]);
821 /* If both references' size ranges are indeterminate use the last
822 (size) argument from the function call as a substitute. This
823 may only be necessary for strncpy (but not for memcpy where
824 the size range would have been already determined this way). */
825 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
826 && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
828 dstref->sizrange[0] = bounds[0];
829 dstref->sizrange[1] = bounds[1];
833 bool dstsize_set = false;
834 /* The size range of one reference involving the same base object
835 can be determined from the size range of the other reference.
836 This makes it possible to compute accurate offsets for warnings
837 involving functions like strcpy where the length of just one of
838 the two arguments is known (determined by tree-ssa-strlen). */
839 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize)
841 /* When the destination size is unknown set it to the size of
842 the source. */
843 dstref->sizrange[0] = srcref->sizrange[0];
844 dstref->sizrange[1] = srcref->sizrange[1];
845 dstsize_set = true;
847 else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
849 /* When the size of the source access is unknown set it to the size
850 of the destination first and adjust it later if necessary. */
851 srcref->sizrange[0] = dstref->sizrange[0];
852 srcref->sizrange[1] = dstref->sizrange[1];
854 if (depends_p)
856 if (dstref->strbounded_p)
858 /* Read access by strncpy is constrained by the third
859 argument but except for a zero bound is at least one. */
860 srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
861 offset_int bound = wi::umin (srcref->basesize, bounds[1]);
862 if (bound < srcref->sizrange[1])
863 srcref->sizrange[1] = bound;
865 /* For string functions, adjust the size range of the source
866 reference by the inverse boundaries of the offset (because
867 the higher the offset into the string the shorter its
868 length). */
869 if (srcref->offrange[1] >= 0
870 && srcref->offrange[1] < srcref->sizrange[0])
871 srcref->sizrange[0] -= srcref->offrange[1];
872 else
873 srcref->sizrange[0] = 1;
875 if (srcref->offrange[0] > 0)
877 if (srcref->offrange[0] < srcref->sizrange[1])
878 srcref->sizrange[1] -= srcref->offrange[0];
879 else
880 srcref->sizrange[1] = 0;
883 dstadjust_p = true;
887 if (detect_overlap == &builtin_access::generic_overlap)
889 if (dstref->strbounded_p)
891 dstref->sizrange[0] = bounds[0];
892 dstref->sizrange[1] = bounds[1];
894 if (dstref->sizrange[0] < srcref->sizrange[0])
895 srcref->sizrange[0] = dstref->sizrange[0];
897 if (dstref->sizrange[1] < srcref->sizrange[1])
898 srcref->sizrange[1] = dstref->sizrange[1];
901 else if (detect_overlap == &builtin_access::strcpy_overlap)
903 if (!dstref->strbounded_p)
905 /* For strcpy, adjust the destination size range to match that
906 of the source computed above. */
907 if (depends_p && dstadjust_p)
909 dstref->sizrange[0] = srcref->sizrange[0];
910 dstref->sizrange[1] = srcref->sizrange[1];
914 else if (!dstsize_set && detect_overlap == &builtin_access::strcat_overlap)
916 dstref->sizrange[0] += srcref->sizrange[0] - 1;
917 dstref->sizrange[1] += srcref->sizrange[1] - 1;
920 if (dstref->strbounded_p)
922 /* For strncpy, adjust the destination size range to match that
923 of the source computed above. */
924 dstref->sizrange[0] = bounds[0];
925 dstref->sizrange[1] = bounds[1];
927 if (bounds[0] < srcref->sizrange[0])
928 srcref->sizrange[0] = bounds[0];
930 if (bounds[1] < srcref->sizrange[1])
931 srcref->sizrange[1] = bounds[1];
935 offset_int
936 builtin_access::overlap_size (const offset_int a[2], const offset_int b[2],
937 offset_int *off)
939 const offset_int *p = a;
940 const offset_int *q = b;
942 /* Point P at the bigger of the two ranges and Q at the smaller. */
943 if (wi::lts_p (a[1] - a[0], b[1] - b[0]))
945 p = b;
946 q = a;
949 if (p[0] < q[0])
951 if (p[1] < q[0])
952 return 0;
954 *off = q[0];
955 return wi::smin (p[1], q[1]) - q[0];
958 if (q[1] < p[0])
959 return 0;
961 off[0] = p[0];
962 return q[1] - p[0];
965 /* Return true if the bounded mempry (memcpy amd similar) or string function
966 access (strncpy and similar) ACS overlaps. */
968 bool
969 builtin_access::generic_overlap ()
971 builtin_access &acs = *this;
972 const builtin_memref *dstref = acs.dstref;
973 const builtin_memref *srcref = acs.srcref;
975 gcc_assert (dstref->base == srcref->base);
977 const offset_int maxobjsize = acs.dstref->maxobjsize;
979 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
981 /* Adjust the larger bounds of the offsets (which may be the first
982 element if the lower bound is larger than the upper bound) to
983 make them valid for the smallest access (if possible) but no smaller
984 than the smaller bounds. */
985 gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));
987 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
988 acs.dstoff[1] = maxsize - acs.dstsiz[0];
989 if (acs.dstoff[1] < acs.dstoff[0])
990 acs.dstoff[1] = acs.dstoff[0];
992 gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1]));
994 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
995 acs.srcoff[1] = maxsize - acs.srcsiz[0];
996 if (acs.srcoff[1] < acs.srcoff[0])
997 acs.srcoff[1] = acs.srcoff[0];
999 /* Determine the minimum and maximum space for the access given
1000 the offsets. */
1001 offset_int space[2];
1002 space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1003 space[1] = space[0];
1005 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1006 if (acs.srcsiz[0] > 0)
1008 if (d < space[0])
1009 space[0] = d;
1011 if (space[1] < d)
1012 space[1] = d;
1014 else
1015 space[1] = acs.dstsiz[1];
1017 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1018 if (d < space[0])
1019 space[0] = d;
1021 if (space[1] < d)
1022 space[1] = d;
1024 /* Treat raw memory functions both of whose references are bounded
1025 as special and permit uncertain overlaps to go undetected. For
1026 all kinds of constant offset and constant size accesses, if
1027 overlap isn't certain it is not possible. */
1028 bool overlap_possible = space[0] < acs.dstsiz[1];
1029 if (!overlap_possible)
1030 return false;
1032 bool overlap_certain = space[1] < acs.dstsiz[0];
1034 /* True when the size of one reference depends on the offset of
1035 the other. */
1036 bool depends_p = detect_overlap != &builtin_access::generic_overlap;
1038 if (!overlap_certain)
1040 if (!dstref->strbounded_p && !depends_p)
1041 /* Memcpy only considers certain overlap. */
1042 return false;
1044 /* There's no way to distinguish an access to the same member
1045 of a structure from one to two distinct members of the same
1046 structure. Give up to avoid excessive false positives. */
1047 tree basetype = TREE_TYPE (dstref->base);
1049 if (POINTER_TYPE_P (basetype))
1050 basetype = TREE_TYPE (basetype);
1051 else
1052 while (TREE_CODE (basetype) == ARRAY_TYPE)
1053 basetype = TREE_TYPE (basetype);
1055 if (RECORD_OR_UNION_TYPE_P (basetype))
1056 return false;
1059 /* True for stpcpy and strcpy. */
1060 bool stxcpy_p = (!dstref->strbounded_p
1061 && detect_overlap == &builtin_access::strcpy_overlap);
1063 if (dstref->refoff >= 0
1064 && srcref->refoff >= 0
1065 && dstref->refoff != srcref->refoff
1066 && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p))
1067 return false;
1069 offset_int siz[2] = { maxobjsize + 1, 0 };
1071 ovloff[0] = HOST_WIDE_INT_MAX;
1072 ovloff[1] = HOST_WIDE_INT_MIN;
1074 if (stxcpy_p)
1076 /* Iterate over the extreme locations (on the horizontal axis formed
1077 by their offsets) and sizes of two regions and find their smallest
1078 and largest overlap and the corresponding offsets. */
1079 for (unsigned i = 0; i != 2; ++i)
1081 const offset_int a[2] = {
1082 acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i]
1085 const offset_int b[2] = {
1086 acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i]
1089 offset_int off;
1090 offset_int sz = overlap_size (a, b, &off);
1091 if (sz < siz[0])
1092 siz[0] = sz;
1094 if (siz[1] <= sz)
1095 siz[1] = sz;
1097 if (sz != 0)
1099 if (wi::lts_p (off, ovloff[0]))
1100 ovloff[0] = off.to_shwi ();
1101 if (wi::lts_p (ovloff[1], off))
1102 ovloff[1] = off.to_shwi ();
1106 else
1108 /* Iterate over the extreme locations (on the horizontal axis
1109 formed by their offsets) and sizes of the two regions and
1110 find their smallest and largest overlap and the corresponding
1111 offsets. */
1113 for (unsigned io = 0; io != 2; ++io)
1114 for (unsigned is = 0; is != 2; ++is)
1116 const offset_int a[2] = {
1117 acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is]
1120 for (unsigned jo = 0; jo != 2; ++jo)
1121 for (unsigned js = 0; js != 2; ++js)
1123 const offset_int b[2] = {
1124 acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
1127 offset_int off;
1128 offset_int sz = overlap_size (a, b, &off);
1129 if (sz < siz[0])
1130 siz[0] = sz;
1132 if (siz[1] <= sz)
1133 siz[1] = sz;
1135 if (sz != 0)
1137 if (wi::lts_p (off, ovloff[0]))
1138 ovloff[0] = off.to_shwi ();
1139 if (wi::lts_p (ovloff[1], off))
1140 ovloff[1] = off.to_shwi ();
1146 ovlsiz[0] = siz[0].to_shwi ();
1147 ovlsiz[1] = siz[1].to_shwi ();
1149 /* Adjust the overlap offset range to reflect the overlap size range. */
1150 if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
1151 ovloff[1] = ovloff[0] + ovlsiz[1] - 1;
1153 return true;
1156 /* Return true if the strcat-like access overlaps. */
1158 bool
1159 builtin_access::strcat_overlap ()
1161 builtin_access &acs = *this;
1162 const builtin_memref *dstref = acs.dstref;
1163 const builtin_memref *srcref = acs.srcref;
1165 gcc_assert (dstref->base == srcref->base);
1167 const offset_int maxobjsize = acs.dstref->maxobjsize;
1169 gcc_assert (dstref->base && dstref->base == srcref->base);
1171 /* Adjust for strcat-like accesses. */
1173 /* As a special case for strcat, set the DSTREF offsets to the length
1174 of the destination string since the function starts writing over
1175 its terminating nul, and set the destination size to 1 for the length
1176 of the nul. */
1177 acs.dstoff[0] += dstsiz[0] - srcref->sizrange[0];
1178 acs.dstoff[1] += dstsiz[1] - srcref->sizrange[1];
1180 bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0;
1182 /* The lower bound is zero when the size is unknown because then
1183 overlap is not certain. */
1184 acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1;
1185 acs.dstsiz[1] = 1;
1187 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
1189 /* For references to the same base object, determine if there's a pair
1190 of valid offsets into the two references such that access between
1191 them doesn't overlap. Adjust both upper bounds to be valid for
1192 the smaller size (i.e., at most MAXSIZE - SIZE). */
1194 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
1195 acs.dstoff[1] = maxsize - acs.dstsiz[0];
1197 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
1198 acs.srcoff[1] = maxsize - acs.srcsiz[0];
1200 /* Check to see if there's enough space for both accesses without
1201 overlap. Determine the optimistic (maximum) amount of available
1202 space. */
1203 offset_int space;
1204 if (acs.dstoff[0] <= acs.srcoff[0])
1206 if (acs.dstoff[1] < acs.srcoff[1])
1207 space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0];
1208 else
1209 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1211 else
1212 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1214 /* Overlap is certain if the distance between the farthest offsets
1215 of the opposite accesses is less than the sum of the lower bounds
1216 of the sizes of the two accesses. */
1217 bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0];
1219 /* For a constant-offset, constant size access, consider the largest
1220 distance between the offset bounds and the lower bound of the access
1221 size. If the overlap isn't certain return success. */
1222 if (!overlap_certain
1223 && acs.dstoff[0] == acs.dstoff[1]
1224 && acs.srcoff[0] == acs.srcoff[1]
1225 && acs.dstsiz[0] == acs.dstsiz[1]
1226 && acs.srcsiz[0] == acs.srcsiz[1])
1227 return false;
1229 /* Overlap is not certain but may be possible. */
1231 offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0];
1233 /* Determine the conservative (minimum) amount of space. */
1234 space = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1235 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1236 if (d < space)
1237 space = d;
1238 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1239 if (d < space)
1240 space = d;
1242 /* For a strict test (used for strcpy and similar with unknown or
1243 variable bounds or sizes), consider the smallest distance between
1244 the offset bounds and either the upper bound of the access size
1245 if known, or the lower bound otherwise. */
1246 if (access_min <= space && (access_min != 0 || !strfunc_unknown_args))
1247 return false;
1249 /* When strcat overlap is certain it is always a single byte:
1250 the terminating NUL, regardless of offsets and sizes. When
1251 overlap is only possible its range is [0, 1]. */
1252 acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
1253 acs.ovlsiz[1] = 1;
1255 offset_int endoff
1256 = dstref->offrange[0] + (dstref->sizrange[0] - srcref->sizrange[0]);
1257 if (endoff <= srcref->offrange[0])
1258 acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi ();
1259 else
1260 acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi ();
1262 acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1,
1263 srcref->sizrange[0]).to_shwi ();
1264 if (dstref->offrange[0] == dstref->offrange[1])
1266 if (srcref->offrange[0] == srcref->offrange[1])
1267 acs.ovloff[1] = acs.ovloff[0];
1268 else
1269 acs.ovloff[1]
1270 = wi::smin (maxobjsize,
1271 srcref->offrange[1] + srcref->sizrange[1]).to_shwi ();
1273 else
1274 acs.ovloff[1]
1275 = wi::smin (maxobjsize,
1276 dstref->offrange[1] + dstref->sizrange[1]).to_shwi ();
1278 if (acs.sizrange[0] == 0)
1279 acs.sizrange[0] = 1;
1280 acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1281 return true;
1284 /* Return true if the strcpy-like access overlaps. */
1286 bool
1287 builtin_access::strcpy_overlap ()
1289 return generic_overlap ();
1292 /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
1293 if known, or [0, MAXOBJSIZE] otherwise. */
1295 static void
1296 clamp_offset (tree base, offset_int refoff[2], offset_int maxobjsize)
1298 if (!base || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
1299 return;
1301 if (refoff[0] < 0 && refoff[1] >= 0)
1302 refoff[0] = 0;
1304 if (refoff[1] < refoff[0])
1306 offset_int maxsize = maxobjsize;
1307 if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (base)))
1308 maxsize = wi::to_offset (size);
1310 refoff[1] = wi::umin (refoff[1], maxsize);
1314 /* Return true if DSTREF and SRCREF describe accesses that either overlap
1315 one another or that, in order not to overlap, would imply that the size
1316 of the referenced object(s) exceeds the maximum size of an object. Set
1317 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1318 they may overlap in a way that's not apparent from the available data),
1319 return false. */
1321 bool
1322 builtin_access::overlap ()
1324 builtin_access &acs = *this;
1326 const offset_int maxobjsize = dstref->maxobjsize;
1328 acs.sizrange[0] = wi::smax (dstref->sizrange[0],
1329 srcref->sizrange[0]).to_shwi ();
1330 acs.sizrange[1] = wi::smax (dstref->sizrange[1],
1331 srcref->sizrange[1]).to_shwi ();
1333 /* Check to see if the two references refer to regions that are
1334 too large not to overlap in the address space (whose maximum
1335 size is PTRDIFF_MAX). */
1336 offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
1337 if (maxobjsize < size)
1339 acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi ();
1340 acs.ovlsiz[0] = (size - maxobjsize).to_shwi ();
1341 return true;
1344 /* If both base objects aren't known return the maximum possible
1345 offset that would make them not overlap. */
1346 if (!dstref->base || !srcref->base)
1347 return false;
1349 /* If the base object is an array adjust the bounds of the offset
1350 to be non-negative and within the bounds of the array if possible. */
1351 clamp_offset (dstref->base, acs.dstoff, maxobjsize);
1353 acs.srcoff[0] = srcref->offrange[0];
1354 acs.srcoff[1] = srcref->offrange[1];
1356 clamp_offset (srcref->base, acs.srcoff, maxobjsize);
1358 /* When the upper bound of the offset is less than the lower bound
1359 the former is the result of a negative offset being represented
1360 as a large positive value or vice versa. The resulting range is
1361 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1362 a union is not representable using the current data structure
1363 replace it with the full range of offsets. */
1364 if (acs.dstoff[1] < acs.dstoff[0])
1366 acs.dstoff[0] = -maxobjsize - 1;
1367 acs.dstoff[1] = maxobjsize;
1370 /* Validate the offset and size of each reference on its own first.
1371 This is independent of whether or not the base objects are the
1372 same. Normally, this would have already been detected and
1373 diagnosed by -Warray-bounds, unless it has been disabled. */
1374 offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
1375 if (maxobjsize < maxoff)
1377 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1378 acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0];
1379 return true;
1382 /* Repeat the same as above but for the source offsets. */
1383 if (acs.srcoff[1] < acs.srcoff[0])
1385 acs.srcoff[0] = -maxobjsize - 1;
1386 acs.srcoff[1] = maxobjsize;
1389 maxoff = acs.srcoff[0] + srcref->sizrange[0];
1390 if (maxobjsize < maxoff)
1392 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1393 acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1]
1394 - maxobjsize).to_shwi ();
1395 acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0];
1396 return true;
1399 if (dstref->base != srcref->base)
1400 return false;
1402 acs.dstsiz[0] = dstref->sizrange[0];
1403 acs.dstsiz[1] = dstref->sizrange[1];
1405 acs.srcsiz[0] = srcref->sizrange[0];
1406 acs.srcsiz[1] = srcref->sizrange[1];
1408 /* Call the appropriate function to determine the overlap. */
1409 if ((this->*detect_overlap) ())
1411 if (!sizrange[1])
1413 /* Unless the access size range has already been set, do so here. */
1414 sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi ();
1415 sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1417 return true;
1420 return false;
1423 /* Attempt to detect and diagnose an overlapping copy in a call expression
1424 EXPR involving an access ACS to a built-in memory or string function.
1425 Return true when one has been detected, false otherwise. */
1427 static bool
1428 maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
1430 if (!acs.overlap ())
1431 return false;
1433 if (warning_suppressed_p (call, OPT_Wrestrict))
1434 return true;
1436 /* For convenience. */
1437 const builtin_memref &dstref = *acs.dstref;
1438 const builtin_memref &srcref = *acs.srcref;
1440 /* Determine the range of offsets and sizes of the overlap if it
1441 exists and issue diagnostics. */
1442 HOST_WIDE_INT *ovloff = acs.ovloff;
1443 HOST_WIDE_INT *ovlsiz = acs.ovlsiz;
1444 HOST_WIDE_INT *sizrange = acs.sizrange;
1446 tree func = gimple_call_fndecl (call);
1448 /* To avoid a combinatorial explosion of diagnostics format the offsets
1449 or their ranges as strings and use them in the warning calls below. */
1450 char offstr[3][64];
1452 if (dstref.offrange[0] == dstref.offrange[1]
1453 || dstref.offrange[1] > HOST_WIDE_INT_MAX)
1454 sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC,
1455 dstref.offrange[0].to_shwi ());
1456 else
1457 sprintf (offstr[0],
1458 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1459 dstref.offrange[0].to_shwi (),
1460 dstref.offrange[1].to_shwi ());
1462 if (srcref.offrange[0] == srcref.offrange[1]
1463 || srcref.offrange[1] > HOST_WIDE_INT_MAX)
1464 sprintf (offstr[1],
1465 HOST_WIDE_INT_PRINT_DEC,
1466 srcref.offrange[0].to_shwi ());
1467 else
1468 sprintf (offstr[1],
1469 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1470 srcref.offrange[0].to_shwi (),
1471 srcref.offrange[1].to_shwi ());
1473 if (ovloff[0] == ovloff[1] || !ovloff[1])
1474 sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]);
1475 else
1476 sprintf (offstr[2],
1477 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1478 ovloff[0], ovloff[1]);
1480 const offset_int maxobjsize = dstref.maxobjsize;
1481 bool must_overlap = ovlsiz[0] > 0;
1483 if (ovlsiz[1] == 0)
1484 ovlsiz[1] = ovlsiz[0];
1486 if (must_overlap)
1488 /* Issue definitive "overlaps" diagnostic in this block. */
1490 if (sizrange[0] == sizrange[1])
1492 if (ovlsiz[0] == ovlsiz[1])
1493 warning_at (loc, OPT_Wrestrict,
1494 sizrange[0] == 1
1495 ? (ovlsiz[0] == 1
1496 ? G_("%qD accessing %wu byte at offsets %s "
1497 "and %s overlaps %wu byte at offset %s")
1498 : G_("%qD accessing %wu byte at offsets %s "
1499 "and %s overlaps %wu bytes at offset "
1500 "%s"))
1501 : (ovlsiz[0] == 1
1502 ? G_("%qD accessing %wu bytes at offsets %s "
1503 "and %s overlaps %wu byte at offset %s")
1504 : G_("%qD accessing %wu bytes at offsets %s "
1505 "and %s overlaps %wu bytes at offset "
1506 "%s")),
1507 func, sizrange[0],
1508 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1509 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1510 warning_n (loc, OPT_Wrestrict, sizrange[0],
1511 "%qD accessing %wu byte at offsets %s "
1512 "and %s overlaps between %wu and %wu bytes "
1513 "at offset %s",
1514 "%qD accessing %wu bytes at offsets %s "
1515 "and %s overlaps between %wu and %wu bytes "
1516 "at offset %s",
1517 func, sizrange[0], offstr[0], offstr[1],
1518 ovlsiz[0], ovlsiz[1], offstr[2]);
1519 else
1520 warning_n (loc, OPT_Wrestrict, sizrange[0],
1521 "%qD accessing %wu byte at offsets %s and "
1522 "%s overlaps %wu or more bytes at offset %s",
1523 "%qD accessing %wu bytes at offsets %s and "
1524 "%s overlaps %wu or more bytes at offset %s",
1525 func, sizrange[0],
1526 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1527 return true;
1530 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1532 if (ovlsiz[0] == ovlsiz[1])
1533 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
1534 "%qD accessing between %wu and %wu bytes "
1535 "at offsets %s and %s overlaps %wu byte at "
1536 "offset %s",
1537 "%qD accessing between %wu and %wu bytes "
1538 "at offsets %s and %s overlaps %wu bytes "
1539 "at offset %s",
1540 func, sizrange[0], sizrange[1],
1541 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1542 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1543 warning_at (loc, OPT_Wrestrict,
1544 "%qD accessing between %wu and %wu bytes at "
1545 "offsets %s and %s overlaps between %wu and %wu "
1546 "bytes at offset %s",
1547 func, sizrange[0], sizrange[1],
1548 offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
1549 offstr[2]);
1550 else
1551 warning_at (loc, OPT_Wrestrict,
1552 "%qD accessing between %wu and %wu bytes at "
1553 "offsets %s and %s overlaps %wu or more bytes "
1554 "at offset %s",
1555 func, sizrange[0], sizrange[1],
1556 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1557 return true;
1560 if (ovlsiz[0] != ovlsiz[1])
1561 ovlsiz[1] = maxobjsize.to_shwi ();
1563 if (ovlsiz[0] == ovlsiz[1])
1564 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
1565 "%qD accessing %wu or more bytes at offsets "
1566 "%s and %s overlaps %wu byte at offset %s",
1567 "%qD accessing %wu or more bytes at offsets "
1568 "%s and %s overlaps %wu bytes at offset %s",
1569 func, sizrange[0], offstr[0], offstr[1],
1570 ovlsiz[0], offstr[2]);
1571 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1572 warning_at (loc, OPT_Wrestrict,
1573 "%qD accessing %wu or more bytes at offsets %s "
1574 "and %s overlaps between %wu and %wu bytes "
1575 "at offset %s",
1576 func, sizrange[0], offstr[0], offstr[1],
1577 ovlsiz[0], ovlsiz[1], offstr[2]);
1578 else
1579 warning_at (loc, OPT_Wrestrict,
1580 "%qD accessing %wu or more bytes at offsets %s "
1581 "and %s overlaps %wu or more bytes at offset %s",
1582 func, sizrange[0], offstr[0], offstr[1],
1583 ovlsiz[0], offstr[2]);
1584 return true;
1587 /* Use more concise wording when one of the offsets is unbounded
1588 to avoid confusing the user with large and mostly meaningless
1589 numbers. */
1590 bool open_range;
1591 if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
1592 open_range = ((dstref.offrange[0] == 0
1593 && dstref.offrange[1] == maxobjsize)
1594 || (srcref.offrange[0] == 0
1595 && srcref.offrange[1] == maxobjsize));
1596 else
1597 open_range = ((dstref.offrange[0] == -maxobjsize - 1
1598 && dstref.offrange[1] == maxobjsize)
1599 || (srcref.offrange[0] == -maxobjsize - 1
1600 && srcref.offrange[1] == maxobjsize));
1602 if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
1604 if (ovlsiz[1] == 1)
1606 if (open_range)
1607 warning_n (loc, OPT_Wrestrict, sizrange[1],
1608 "%qD accessing %wu byte may overlap "
1609 "%wu byte",
1610 "%qD accessing %wu bytes may overlap "
1611 "%wu byte",
1612 func, sizrange[1], ovlsiz[1]);
1613 else
1614 warning_n (loc, OPT_Wrestrict, sizrange[1],
1615 "%qD accessing %wu byte at offsets %s "
1616 "and %s may overlap %wu byte at offset %s",
1617 "%qD accessing %wu bytes at offsets %s "
1618 "and %s may overlap %wu byte at offset %s",
1619 func, sizrange[1], offstr[0], offstr[1],
1620 ovlsiz[1], offstr[2]);
1621 return true;
1624 if (open_range)
1625 warning_n (loc, OPT_Wrestrict, sizrange[1],
1626 "%qD accessing %wu byte may overlap "
1627 "up to %wu bytes",
1628 "%qD accessing %wu bytes may overlap "
1629 "up to %wu bytes",
1630 func, sizrange[1], ovlsiz[1]);
1631 else
1632 warning_n (loc, OPT_Wrestrict, sizrange[1],
1633 "%qD accessing %wu byte at offsets %s and "
1634 "%s may overlap up to %wu bytes at offset %s",
1635 "%qD accessing %wu bytes at offsets %s and "
1636 "%s may overlap up to %wu bytes at offset %s",
1637 func, sizrange[1], offstr[0], offstr[1],
1638 ovlsiz[1], offstr[2]);
1639 return true;
1642 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1644 if (open_range)
1645 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1646 "%qD accessing between %wu and %wu bytes "
1647 "may overlap %wu byte",
1648 "%qD accessing between %wu and %wu bytes "
1649 "may overlap up to %wu bytes",
1650 func, sizrange[0], sizrange[1], ovlsiz[1]);
1651 else
1652 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1653 "%qD accessing between %wu and %wu bytes "
1654 "at offsets %s and %s may overlap %wu byte "
1655 "at offset %s",
1656 "%qD accessing between %wu and %wu bytes "
1657 "at offsets %s and %s may overlap up to %wu "
1658 "bytes at offset %s",
1659 func, sizrange[0], sizrange[1],
1660 offstr[0], offstr[1], ovlsiz[1], offstr[2]);
1661 return true;
1664 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1665 "%qD accessing %wu or more bytes at offsets %s "
1666 "and %s may overlap %wu byte at offset %s",
1667 "%qD accessing %wu or more bytes at offsets %s "
1668 "and %s may overlap up to %wu bytes at offset %s",
1669 func, sizrange[0], offstr[0], offstr[1],
1670 ovlsiz[1], offstr[2]);
1672 return true;
1675 /* Validate REF size and offsets in an expression passed as an argument
1676 to a CALL to a built-in function FUNC to make sure they are within
1677 the bounds of the referenced object if its size is known, or
1678 PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1679 be issued, false otherwise.
1680 Both initial values of the offsets and their final value computed
1681 by the function by incrementing the initial value by the size are
1682 validated. Return the warning number if the offsets are not valid
1683 and a diagnostic has been issued, or would have been issued if
1684 DO_WARN had been true, otherwise an invalid warning number. */
1686 static opt_code
1687 maybe_diag_access_bounds (gimple *call, tree func, int strict,
1688 const builtin_memref &ref, offset_int wroff,
1689 bool do_warn)
1691 location_t loc = gimple_location (call);
1692 const offset_int maxobjsize = ref.maxobjsize;
1694 /* Check for excessive size first and regardless of warning options
1695 since the result is used to make codegen decisions. */
1696 if (ref.sizrange[0] > maxobjsize)
1698 const opt_code opt = OPT_Wstringop_overflow_;
1699 /* Return true without issuing a warning. */
1700 if (!do_warn)
1701 return opt;
1703 if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
1704 return no_warning;
1706 bool warned = false;
1707 if (warn_stringop_overflow)
1709 if (ref.sizrange[0] == ref.sizrange[1])
1710 warned = warning_at (loc, opt,
1711 "%qD specified bound %wu "
1712 "exceeds maximum object size %wu",
1713 func, ref.sizrange[0].to_uhwi (),
1714 maxobjsize.to_uhwi ());
1715 else
1716 warned = warning_at (loc, opt,
1717 "%qD specified bound between %wu and %wu "
1718 "exceeds maximum object size %wu",
1719 func, ref.sizrange[0].to_uhwi (),
1720 ref.sizrange[1].to_uhwi (),
1721 maxobjsize.to_uhwi ());
1722 return warned ? opt : no_warning;
1726 /* Check for out-bounds pointers regardless of warning options since
1727 the result is used to make codegen decisions. An excessive WROFF
1728 can only come up as a result of an invalid strncat bound and is
1729 diagnosed separately using a more meaningful warning. */
1730 if (maxobjsize < wroff)
1731 wroff = 0;
1732 offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
1733 tree oobref = ref.offset_out_of_bounds (strict, ooboff);
1734 if (!oobref)
1735 return no_warning;
1737 const opt_code opt = OPT_Warray_bounds_;
1738 /* Return true without issuing a warning. */
1739 if (!do_warn)
1740 return opt;
1742 if (!warn_array_bounds)
1743 return no_warning;
1745 if (warning_suppressed_p (ref.ptr, opt)
1746 || (ref.ref && warning_suppressed_p (ref.ref, opt)))
1747 return no_warning;
1749 char rangestr[2][64];
1750 if (ooboff[0] == ooboff[1]
1751 || (ooboff[0] != ref.offrange[0]
1752 && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
1753 sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ());
1754 else
1755 sprintf (rangestr[0], "[%lli, %lli]",
1756 (long long) ooboff[0].to_shwi (),
1757 (long long) ooboff[1].to_shwi ());
1759 bool warned = false;
1761 if (oobref == error_mark_node)
1763 if (ref.sizrange[0] == ref.sizrange[1])
1764 sprintf (rangestr[1], "%llu",
1765 (unsigned long long) ref.sizrange[0].to_shwi ());
1766 else
1767 sprintf (rangestr[1], "[%lli, %lli]",
1768 (unsigned long long) ref.sizrange[0].to_uhwi (),
1769 (unsigned long long) ref.sizrange[1].to_uhwi ());
1771 tree type;
1773 if (DECL_P (ref.base)
1774 && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
1776 auto_diagnostic_group d;
1777 if (warning_at (loc, opt,
1778 "%qD pointer overflow between offset %s "
1779 "and size %s accessing array %qD with type %qT",
1780 func, rangestr[0], rangestr[1], ref.base, type))
1782 inform (DECL_SOURCE_LOCATION (ref.base),
1783 "array %qD declared here", ref.base);
1784 warned = true;
1786 else
1787 warned = warning_at (loc, opt,
1788 "%qD pointer overflow between offset %s "
1789 "and size %s",
1790 func, rangestr[0], rangestr[1]);
1792 else
1793 warned = warning_at (loc, opt,
1794 "%qD pointer overflow between offset %s "
1795 "and size %s",
1796 func, rangestr[0], rangestr[1]);
1798 else if (oobref == ref.base)
1800 /* True when the offset formed by an access to the reference
1801 is out of bounds, rather than the initial offset wich is
1802 in bounds. This implies access past the end. */
1803 bool form = ooboff[0] != ref.offrange[0];
1805 if (DECL_P (ref.base))
1807 auto_diagnostic_group d;
1808 if ((ref.basesize < maxobjsize
1809 && warning_at (loc, opt,
1810 form
1811 ? G_("%qD forming offset %s is out of "
1812 "the bounds [0, %wu] of object %qD with "
1813 "type %qT")
1814 : G_("%qD offset %s is out of the bounds "
1815 "[0, %wu] of object %qD with type %qT"),
1816 func, rangestr[0], ref.basesize.to_uhwi (),
1817 ref.base, TREE_TYPE (ref.base)))
1818 || warning_at (loc, opt,
1819 form
1820 ? G_("%qD forming offset %s is out of "
1821 "the bounds of object %qD with type %qT")
1822 : G_("%qD offset %s is out of the bounds "
1823 "of object %qD with type %qT"),
1824 func, rangestr[0],
1825 ref.base, TREE_TYPE (ref.base)))
1827 inform (DECL_SOURCE_LOCATION (ref.base),
1828 "%qD declared here", ref.base);
1829 warned = true;
1832 else if (ref.basesize < maxobjsize)
1833 warned = warning_at (loc, opt,
1834 form
1835 ? G_("%qD forming offset %s is out "
1836 "of the bounds [0, %wu]")
1837 : G_("%qD offset %s is out "
1838 "of the bounds [0, %wu]"),
1839 func, rangestr[0], ref.basesize.to_uhwi ());
1840 else
1841 warned = warning_at (loc, opt,
1842 form
1843 ? G_("%qD forming offset %s is out of bounds")
1844 : G_("%qD offset %s is out of bounds"),
1845 func, rangestr[0]);
1847 else if (TREE_CODE (ref.ref) == MEM_REF)
1849 tree refop = TREE_OPERAND (ref.ref, 0);
1850 tree type = TREE_TYPE (refop);
1851 if (POINTER_TYPE_P (type))
1852 type = TREE_TYPE (type);
1853 type = TYPE_MAIN_VARIANT (type);
1855 if (warning_at (loc, opt,
1856 "%qD offset %s from the object at %qE is out "
1857 "of the bounds of %qT",
1858 func, rangestr[0], ref.base, type))
1860 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1861 refop = TREE_OPERAND (ref.ref, 1);
1862 if (DECL_P (refop))
1863 inform (DECL_SOURCE_LOCATION (refop),
1864 "subobject %qD declared here", refop);
1865 warned = true;
1868 else
1870 tree refop = TREE_OPERAND (ref.ref, 0);
1871 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
1873 if (warning_at (loc, opt,
1874 "%qD offset %s from the object at %qE is out "
1875 "of the bounds of referenced subobject %qD with "
1876 "type %qT at offset %wi",
1877 func, rangestr[0], ref.base,
1878 TREE_OPERAND (ref.ref, 1), type,
1879 ref.refoff.to_shwi ()))
1881 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1882 refop = TREE_OPERAND (ref.ref, 1);
1883 if (DECL_P (refop))
1884 inform (DECL_SOURCE_LOCATION (refop),
1885 "subobject %qD declared here", refop);
1886 warned = true;
1890 return warned ? opt : no_warning;
1893 /* Check a CALL statement for restrict-violations and issue warnings
1894 if/when appropriate. */
1896 void
1897 pass_wrestrict::check_call (gimple *call)
1899 /* Avoid checking the call if it has already been diagnosed for
1900 some reason. */
1901 if (warning_suppressed_p (call, OPT_Wrestrict))
1902 return;
1904 tree func = gimple_call_fndecl (call);
1905 if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
1906 return;
1908 /* Argument number to extract from the call (depends on the built-in
1909 and its kind). */
1910 unsigned dst_idx = -1;
1911 unsigned src_idx = -1;
1912 unsigned bnd_idx = -1;
1914 /* Is this CALL to a string function (as opposed to one to a raw
1915 memory function). */
1916 bool strfun = true;
1918 switch (DECL_FUNCTION_CODE (func))
1920 case BUILT_IN_MEMCPY:
1921 case BUILT_IN_MEMCPY_CHK:
1922 case BUILT_IN_MEMPCPY:
1923 case BUILT_IN_MEMPCPY_CHK:
1924 case BUILT_IN_MEMMOVE:
1925 case BUILT_IN_MEMMOVE_CHK:
1926 strfun = false;
1927 /* Fall through. */
1929 case BUILT_IN_STPNCPY:
1930 case BUILT_IN_STPNCPY_CHK:
1931 case BUILT_IN_STRNCAT:
1932 case BUILT_IN_STRNCAT_CHK:
1933 case BUILT_IN_STRNCPY:
1934 case BUILT_IN_STRNCPY_CHK:
1935 dst_idx = 0;
1936 src_idx = 1;
1937 bnd_idx = 2;
1938 break;
1940 case BUILT_IN_MEMSET:
1941 case BUILT_IN_MEMSET_CHK:
1942 dst_idx = 0;
1943 bnd_idx = 2;
1944 break;
1946 case BUILT_IN_STPCPY:
1947 case BUILT_IN_STPCPY_CHK:
1948 case BUILT_IN_STRCPY:
1949 case BUILT_IN_STRCPY_CHK:
1950 case BUILT_IN_STRCAT:
1951 case BUILT_IN_STRCAT_CHK:
1952 dst_idx = 0;
1953 src_idx = 1;
1954 break;
1956 default:
1957 /* Handle other string functions here whose access may need
1958 to be validated for in-bounds offsets and non-overlapping
1959 copies. */
1960 return;
1963 unsigned nargs = gimple_call_num_args (call);
1965 tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
1966 tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
1967 tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE;
1969 /* For string functions with an unspecified or unknown bound,
1970 assume the size of the access is one. */
1971 if (!dstwr && strfun)
1972 dstwr = size_one_node;
1974 /* DST and SRC can be null for a call with an insufficient number
1975 of arguments to a built-in function declared without a protype. */
1976 if (!dst || (src_idx < nargs && !src))
1977 return;
1979 /* DST, SRC, or DSTWR can also have the wrong type in a call to
1980 a function declared without a prototype. Avoid checking such
1981 invalid calls. */
1982 if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
1983 || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
1984 || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
1985 return;
1987 opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr,
1988 NULL_TREE);
1989 /* Avoid diagnosing the call again. */
1990 suppress_warning (call, opt);
1993 } /* anonymous namespace */
1995 /* Attempt to detect and diagnose invalid offset bounds and (except for
1996 memmove) overlapping copy in a call expression EXPR from SRC to DST
1997 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
1998 SRCSIZE may be NULL. DO_WARN is false to detect either problem
1999 without issue a warning. Return the OPT_Wxxx constant corresponding
2000 to the warning if one has been detected and zero otherwise. */
2002 opt_code
2003 check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
2004 tree srcsize, bool bounds_only /* = false */,
2005 bool do_warn /* = true */)
2007 pointer_query ptrqry (get_range_query (cfun));
2008 return check_bounds_or_overlap (ptrqry,
2009 call, dst, src, dstsize, srcsize,
2010 bounds_only, do_warn);
2013 opt_code
2014 check_bounds_or_overlap (pointer_query &ptrqry,
2015 gimple *call, tree dst, tree src, tree dstsize,
2016 tree srcsize, bool bounds_only /* = false */,
2017 bool do_warn /* = true */)
2019 tree func = gimple_call_fndecl (call);
2021 builtin_memref dstref (ptrqry, call, dst, dstsize);
2022 builtin_memref srcref (ptrqry, call, src, srcsize);
2024 /* Create a descriptor of the access. This may adjust both DSTREF
2025 and SRCREF based on one another and the kind of the access. */
2026 builtin_access acs (ptrqry, call, dstref, srcref);
2028 /* Set STRICT to the value of the -Warray-bounds=N argument for
2029 string functions or when N > 1. */
2030 int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0);
2032 /* The starting offset of the destination write access. Nonzero only
2033 for the strcat family of functions. */
2034 offset_int wroff = acs.write_off (dstsize);
2036 /* Validate offsets to each reference before the access first to make
2037 sure they are within the bounds of the destination object if its
2038 size is known, or PTRDIFF_MAX otherwise. */
2039 opt_code opt
2040 = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
2041 if (opt == no_warning)
2042 opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
2044 if (opt != no_warning)
2046 if (do_warn)
2047 suppress_warning (call, opt);
2048 return opt;
2051 if (!warn_restrict || bounds_only || !src)
2052 return no_warning;
2054 if (!bounds_only)
2056 switch (DECL_FUNCTION_CODE (func))
2058 case BUILT_IN_MEMMOVE:
2059 case BUILT_IN_MEMMOVE_CHK:
2060 case BUILT_IN_MEMSET:
2061 case BUILT_IN_MEMSET_CHK:
2062 return no_warning;
2063 default:
2064 break;
2068 location_t loc = gimple_location (call);
2069 if (operand_equal_p (dst, src, 0))
2071 /* Issue -Wrestrict unless the pointers are null (those do
2072 not point to objects and so do not indicate an overlap;
2073 such calls could be the result of sanitization and jump
2074 threading). */
2075 if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
2077 warning_at (loc, OPT_Wrestrict,
2078 "%qD source argument is the same as destination",
2079 func);
2080 suppress_warning (call, OPT_Wrestrict);
2081 return OPT_Wrestrict;
2084 return no_warning;
2087 /* Return false when overlap has been detected. */
2088 if (maybe_diag_overlap (loc, call, acs))
2090 suppress_warning (call, OPT_Wrestrict);
2091 return OPT_Wrestrict;
2094 return no_warning;
2097 gimple_opt_pass *
2098 make_pass_warn_restrict (gcc::context *ctxt)
2100 return new pass_wrestrict (ctxt);
2103 DEBUG_FUNCTION void
2104 dump_builtin_memref (FILE *fp, const builtin_memref &ref)
2106 fprintf (fp, "\n ptr = ");
2107 print_generic_expr (fp, ref.ptr, TDF_LINENO);
2108 fprintf (fp, "\n ref = ");
2109 if (ref.ref)
2110 print_generic_expr (fp, ref.ref, TDF_LINENO);
2111 else
2112 fputs ("null", fp);
2113 fprintf (fp, "\n base = ");
2114 print_generic_expr (fp, ref.base, TDF_LINENO);
2115 fprintf (fp,
2116 "\n basesize = %lli"
2117 "\n refsize = %lli"
2118 "\n refoff = %lli"
2119 "\n offrange = [%lli, %lli]"
2120 "\n sizrange = [%lli, %lli]"
2121 "\n strbounded_p = %s\n",
2122 (long long)ref.basesize.to_shwi (),
2123 (long long)ref.refsize.to_shwi (),
2124 (long long)ref.refoff.to_shwi (),
2125 (long long)ref.offrange[0].to_shwi (),
2126 (long long)ref.offrange[1].to_shwi (),
2127 (long long)ref.sizrange[0].to_shwi (),
2128 (long long)ref.sizrange[1].to_shwi (),
2129 ref.strbounded_p ? "true" : "false");
2132 void
2133 builtin_access::dump (FILE *fp) const
2135 fprintf (fp, " dstref:");
2136 dump_builtin_memref (fp, *dstref);
2137 fprintf (fp, "\n srcref:");
2138 dump_builtin_memref (fp, *srcref);
2140 fprintf (fp,
2141 " sizrange = [%lli, %lli]\n"
2142 " ovloff = [%lli, %lli]\n"
2143 " ovlsiz = [%lli, %lli]\n"
2144 " dstoff = [%lli, %lli]\n"
2145 " dstsiz = [%lli, %lli]\n"
2146 " srcoff = [%lli, %lli]\n"
2147 " srcsiz = [%lli, %lli]\n",
2148 (long long)sizrange[0], (long long)sizrange[1],
2149 (long long)ovloff[0], (long long)ovloff[1],
2150 (long long)ovlsiz[0], (long long)ovlsiz[1],
2151 (long long)dstoff[0].to_shwi (), (long long)dstoff[1].to_shwi (),
2152 (long long)dstsiz[0].to_shwi (), (long long)dstsiz[1].to_shwi (),
2153 (long long)srcoff[0].to_shwi (), (long long)srcoff[1].to_shwi (),
2154 (long long)srcsiz[0].to_shwi (), (long long)srcsiz[1].to_shwi ());
2157 DEBUG_FUNCTION void
2158 dump_builtin_access (FILE *fp, gimple *stmt, const builtin_access &acs)
2160 if (stmt)
2162 fprintf (fp, "\nDumping builtin_access for ");
2163 print_gimple_expr (fp, stmt, TDF_LINENO);
2164 fputs (":\n", fp);
2167 acs.dump (fp);
2170 DEBUG_FUNCTION void
2171 debug (gimple *stmt, const builtin_access &acs)
2173 dump_builtin_access (stdout, stmt, acs);