c++: ICE with alias in pack expansion [PR103769]
[official-gcc.git] / gcc / gimple-ssa-warn-restrict.cc
blobb678e806da373a109d1e24765970bb4112c5feef
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 virtual bool gate (function *);
68 virtual unsigned int execute (function *);
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_at_struct_end_p (ref))
300 ; /* Use the maximum possible offset for last member arrays. */
301 else if (tree basesize = TYPE_SIZE_UNIT (basetype))
302 if (TREE_CODE (basesize) == INTEGER_CST)
303 /* Size could be non-constant for a variable-length type such
304 as a struct with a VLA member (a GCC extension). */
305 maxoff = wi::to_offset (basesize);
308 if (offrange[0] >= 0)
310 if (offrange[1] < 0)
311 offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
312 else if (offrange[0] <= maxoff && offrange[1] > maxoff)
313 offrange[1] = maxoff;
317 /* Based on the initial length of the destination STARTLEN, returns
318 the offset of the first write access from the beginning of
319 the destination. Nonzero only for strcat-type of calls. */
321 offset_int builtin_access::write_off (tree startlen) const
323 if (detect_overlap != &builtin_access::strcat_overlap
324 || !startlen || TREE_CODE (startlen) != INTEGER_CST)
325 return 0;
327 return wi::to_offset (startlen);
330 /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
331 Pointer offsets are represented as unsigned sizetype but must be
332 treated as signed. */
334 void
335 builtin_memref::extend_offset_range (tree offset)
337 if (TREE_CODE (offset) == INTEGER_CST)
339 offset_int off = int_cst_value (offset);
340 if (off != 0)
342 offrange[0] += off;
343 offrange[1] += off;
345 return;
348 if (TREE_CODE (offset) == SSA_NAME)
350 /* A pointer offset is represented as sizetype but treated
351 as signed. */
352 wide_int min, max;
353 value_range_kind rng = VR_VARYING;
354 value_range vr;
355 if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt))
357 rng = vr.kind ();
358 if (!vr.undefined_p ())
360 min = wi::to_wide (vr.min ());
361 max = wi::to_wide (vr.max ());
365 if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
367 /* Convert an anti-range whose upper bound is less than
368 its lower bound to a signed range. */
369 offrange[0] += offset_int::from (max + 1, SIGNED);
370 offrange[1] += offset_int::from (min - 1, SIGNED);
371 return;
374 if (rng == VR_RANGE
375 && (DECL_P (base) || wi::lts_p (min, max)))
377 /* Preserve the bounds of the range for an offset into
378 a known object (it may be adjusted later relative to
379 a constant offset from its beginning). Otherwise use
380 the bounds only when they are ascending when treated
381 as signed. */
382 offrange[0] += offset_int::from (min, SIGNED);
383 offrange[1] += offset_int::from (max, SIGNED);
384 return;
387 /* Handle an anti-range the same as no range at all. */
388 gimple *stmt = SSA_NAME_DEF_STMT (offset);
389 tree type;
390 if (is_gimple_assign (stmt)
391 && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
392 && INTEGRAL_TYPE_P (type))
394 tree_code code = gimple_assign_rhs_code (stmt);
395 if (code == NOP_EXPR)
397 /* Use the bounds of the type of the NOP_EXPR operand
398 even if it's signed. The result doesn't trigger
399 warnings but makes their output more readable. */
400 offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
401 offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
402 return;
407 const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
408 const offset_int minoff = -maxoff - 1;
410 offrange[0] += minoff;
411 offrange[1] += maxoff;
414 /* Determines the base object or pointer of the reference EXPR
415 and the offset range from the beginning of the base. */
417 void
418 builtin_memref::set_base_and_offset (tree expr)
420 tree offset = NULL_TREE;
422 if (TREE_CODE (expr) == SSA_NAME)
424 /* Try to tease the offset out of the pointer. */
425 gimple *stmt = SSA_NAME_DEF_STMT (expr);
426 if (!base
427 && gimple_assign_single_p (stmt)
428 && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
429 expr = gimple_assign_rhs1 (stmt);
430 else if (is_gimple_assign (stmt))
432 tree_code code = gimple_assign_rhs_code (stmt);
433 if (code == NOP_EXPR)
435 tree rhs = gimple_assign_rhs1 (stmt);
436 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
437 expr = gimple_assign_rhs1 (stmt);
438 else
440 base = expr;
441 return;
444 else if (code == POINTER_PLUS_EXPR)
446 expr = gimple_assign_rhs1 (stmt);
447 offset = gimple_assign_rhs2 (stmt);
449 else
451 base = expr;
452 return;
455 else
457 /* FIXME: Handle PHI nodes in case like:
458 _12 = &MEM[(void *)&a + 2B] + _10;
460 <bb> [local count: 1073741824]:
461 # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
462 memcpy (prephitmp_13, p_7(D), 6); */
463 base = expr;
464 return;
468 if (TREE_CODE (expr) == ADDR_EXPR)
469 expr = TREE_OPERAND (expr, 0);
471 /* Stash the reference for offset validation. */
472 ref = expr;
474 poly_int64 bitsize, bitpos;
475 tree var_off;
476 machine_mode mode;
477 int sign, reverse, vol;
479 /* Determine the base object or pointer of the reference and
480 the constant bit offset from the beginning of the base.
481 If the offset has a non-constant component, it will be in
482 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
483 unused here. */
484 base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
485 &mode, &sign, &reverse, &vol);
487 /* get_inner_reference is not expected to return null. */
488 gcc_assert (base != NULL);
490 if (offset)
491 extend_offset_range (offset);
493 poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
495 /* Convert the poly_int64 offset to offset_int. The offset
496 should be constant but be prepared for it not to be just in
497 case. */
498 offset_int cstoff;
499 if (bytepos.is_constant (&cstoff))
501 offrange[0] += cstoff;
502 offrange[1] += cstoff;
504 /* Besides the reference saved above, also stash the offset
505 for validation. */
506 if (TREE_CODE (expr) == COMPONENT_REF)
507 refoff = cstoff;
509 else
510 offrange[1] += maxobjsize;
512 if (var_off)
514 if (TREE_CODE (var_off) == INTEGER_CST)
516 cstoff = wi::to_offset (var_off);
517 offrange[0] += cstoff;
518 offrange[1] += cstoff;
520 else
521 offrange[1] += maxobjsize;
524 if (TREE_CODE (base) == MEM_REF)
526 tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
527 extend_offset_range (memrefoff);
528 base = TREE_OPERAND (base, 0);
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;
543 if (!integer_zerop (memrefoff))
544 /* A non-zero offset into an array of struct with flexible array
545 members implies that the array is empty because there is no
546 way to initialize such a member when it belongs to an array.
547 This must be some sort of a bug. */
548 refsize = 0;
551 if (TREE_CODE (ref) == COMPONENT_REF)
552 if (tree size = component_ref_size (ref))
553 if (TREE_CODE (size) == INTEGER_CST)
554 refsize = wi::to_offset (size);
556 if (TREE_CODE (base) == SSA_NAME)
557 set_base_and_offset (base);
560 /* Return error_mark_node if the signed offset exceeds the bounds
561 of the address space (PTRDIFF_MAX). Otherwise, return either BASE
562 or REF when the offset exceeds the bounds of the BASE or REF object,
563 and set OOBOFF to the past-the-end offset formed by the reference,
564 including its size. OOBOFF is initially setto the range of offsets,
565 and OOBOFF[2] to the offset of the first write access (nonzero for
566 the strcat family). When STRICT is nonzero use REF size, when
567 available, otherwise use BASE size. When STRICT is greater than 1,
568 use the size of the last array member as the bound, otherwise treat
569 such a member as a flexible array member. Return NULL when the offset
570 is in bounds. */
572 tree
573 builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
575 if (!ptr)
576 return NULL_TREE;
578 /* The offset of the first write access or zero. */
579 offset_int wroff = ooboff[2];
581 /* A temporary, possibly adjusted, copy of the offset range. */
582 offset_int offrng[2] = { ooboff[0], ooboff[1] };
584 if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
586 /* Check for offset in an anti-range with a negative lower bound.
587 For such a range, consider only the non-negative subrange. */
588 if (offrng[1] < offrng[0] && offrng[1] < 0)
589 offrng[1] = maxobjsize;
592 /* Conservative offset of the last byte of the referenced object. */
593 offset_int endoff;
595 /* The bounds need not be ordered. Set HIB to use as the index
596 of the larger of the bounds and LOB as the opposite. */
597 bool hib = wi::les_p (offrng[0], offrng[1]);
598 bool lob = !hib;
600 /* Set to the size remaining in the object after subtracting
601 REFOFF. It may become negative as a result of negative indices
602 into the enclosing object, such as in:
603 extern struct S { char a[4], b[3], c[1]; } *p;
604 strcpy (p[-3].b, "123"); */
605 offset_int size = basesize;
606 tree obj = base;
608 const bool decl_p = DECL_P (obj);
610 if (basesize < 0)
612 endoff = offrng[lob] + (sizrange[0] - wroff);
614 /* For a reference through a pointer to an object of unknown size
615 all initial offsets are considered valid, positive as well as
616 negative, since the pointer itself can point past the beginning
617 of the object. However, the sum of the lower bound of the offset
618 and that of the size must be less than or equal than PTRDIFF_MAX. */
619 if (endoff > maxobjsize)
620 return error_mark_node;
622 /* When the referenced subobject is known, the end offset must be
623 within its bounds. Otherwise there is nothing to do. */
624 if (strict
625 && !decl_p
626 && ref
627 && refsize >= 0
628 && TREE_CODE (ref) == COMPONENT_REF)
630 /* If REFOFF is negative, SIZE will become negative here. */
631 size = refoff + refsize;
632 obj = ref;
634 else
635 return NULL_TREE;
638 /* A reference to an object of known size must be within the bounds
639 of either the base object or the subobject (see above for when
640 a subobject can be used). */
641 if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
642 return obj;
644 /* The extent of the reference must also be within the bounds of
645 the base object (if known) or the subobject or the maximum object
646 size otherwise. */
647 endoff = offrng[lob] + sizrange[0];
648 if (endoff > maxobjsize)
649 return error_mark_node;
651 if (strict
652 && decl_p
653 && ref
654 && refsize >= 0
655 && TREE_CODE (ref) == COMPONENT_REF)
657 /* If the reference is to a member subobject of a declared object,
658 the offset must be within the bounds of the subobject. */
659 size = refoff + refsize;
660 obj = ref;
663 if (endoff <= size)
664 return NULL_TREE;
666 /* Set the out-of-bounds offset range to be one greater than
667 that delimited by the reference including its size. */
668 ooboff[lob] = size;
670 if (endoff > ooboff[lob])
671 ooboff[hib] = endoff - 1;
672 else
673 ooboff[hib] = offrng[lob] + sizrange[1];
675 return obj;
678 /* Create an association between the memory references DST and SRC
679 for access by a call EXPR to a memory or string built-in funtion. */
681 builtin_access::builtin_access (pointer_query &ptrqry, gimple *call,
682 builtin_memref &dst,
683 builtin_memref &src)
684 : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
685 dstoff (), srcoff (), dstsiz (), srcsiz ()
687 dstoff[0] = dst.offrange[0];
688 dstoff[1] = dst.offrange[1];
690 /* Zero out since the offset_int ctors invoked above are no-op. */
691 srcoff[0] = srcoff[1] = 0;
692 dstsiz[0] = dstsiz[1] = 0;
693 srcsiz[0] = srcsiz[1] = 0;
695 /* Object Size Type to use to determine the size of the destination
696 and source objects. Overridden below for raw memory functions. */
697 int ostype = 1;
699 /* True when the size of one reference depends on the offset of
700 itself or the other. */
701 bool depends_p = true;
703 /* True when the size of the destination reference DSTREF has been
704 determined from SRCREF and so needs to be adjusted by the latter's
705 offset. Only meaningful for bounded string functions like strncpy. */
706 bool dstadjust_p = false;
708 /* The size argument number (depends on the built-in). */
709 unsigned sizeargno = 2;
711 tree func = gimple_call_fndecl (call);
712 switch (DECL_FUNCTION_CODE (func))
714 case BUILT_IN_MEMCPY:
715 case BUILT_IN_MEMCPY_CHK:
716 case BUILT_IN_MEMPCPY:
717 case BUILT_IN_MEMPCPY_CHK:
718 ostype = 0;
719 depends_p = false;
720 detect_overlap = &builtin_access::generic_overlap;
721 break;
723 case BUILT_IN_MEMMOVE:
724 case BUILT_IN_MEMMOVE_CHK:
725 /* For memmove there is never any overlap to check for. */
726 ostype = 0;
727 depends_p = false;
728 detect_overlap = &builtin_access::no_overlap;
729 break;
731 case BUILT_IN_MEMSET:
732 case BUILT_IN_MEMSET_CHK:
733 /* For memset there is never any overlap to check for. */
734 ostype = 0;
735 depends_p = false;
736 detect_overlap = &builtin_access::no_overlap;
737 break;
739 case BUILT_IN_STPNCPY:
740 case BUILT_IN_STPNCPY_CHK:
741 case BUILT_IN_STRNCPY:
742 case BUILT_IN_STRNCPY_CHK:
743 dstref->strbounded_p = true;
744 detect_overlap = &builtin_access::strcpy_overlap;
745 break;
747 case BUILT_IN_STPCPY:
748 case BUILT_IN_STPCPY_CHK:
749 case BUILT_IN_STRCPY:
750 case BUILT_IN_STRCPY_CHK:
751 detect_overlap = &builtin_access::strcpy_overlap;
752 break;
754 case BUILT_IN_STRCAT:
755 case BUILT_IN_STRCAT_CHK:
756 detect_overlap = &builtin_access::strcat_overlap;
757 break;
759 case BUILT_IN_STRNCAT:
760 case BUILT_IN_STRNCAT_CHK:
761 dstref->strbounded_p = true;
762 srcref->strbounded_p = true;
763 detect_overlap = &builtin_access::strcat_overlap;
764 break;
766 default:
767 /* Handle other string functions here whose access may need
768 to be validated for in-bounds offsets and non-overlapping
769 copies. */
770 return;
773 /* Try to determine the size of the base object. compute_objsize
774 expects a pointer so create one if BASE is a non-pointer object. */
775 if (dst.basesize < 0)
777 access_ref aref;
778 if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0)
779 dst.basesize = aref.sizrng[1];
780 else
781 dst.basesize = HOST_WIDE_INT_MIN;
784 if (src.base && src.basesize < 0)
786 access_ref aref;
787 if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0)
788 src.basesize = aref.sizrng[1];
789 else
790 src.basesize = HOST_WIDE_INT_MIN;
793 const offset_int maxobjsize = dst.maxobjsize;
795 /* Make adjustments for references to the same object by string
796 built-in functions to reflect the constraints imposed by
797 the function. */
799 /* For bounded string functions determine the range of the bound
800 on the access. For others, the range stays unbounded. */
801 offset_int bounds[2] = { maxobjsize, maxobjsize };
802 if (dstref->strbounded_p)
804 unsigned nargs = gimple_call_num_args (call);
805 if (nargs <= sizeargno)
806 return;
808 tree size = gimple_call_arg (call, sizeargno);
809 tree range[2];
810 if (get_size_range (ptrqry.rvals, size, call, range, true))
812 bounds[0] = wi::to_offset (range[0]);
813 bounds[1] = wi::to_offset (range[1]);
816 /* If both references' size ranges are indeterminate use the last
817 (size) argument from the function call as a substitute. This
818 may only be necessary for strncpy (but not for memcpy where
819 the size range would have been already determined this way). */
820 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
821 && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
823 dstref->sizrange[0] = bounds[0];
824 dstref->sizrange[1] = bounds[1];
828 bool dstsize_set = false;
829 /* The size range of one reference involving the same base object
830 can be determined from the size range of the other reference.
831 This makes it possible to compute accurate offsets for warnings
832 involving functions like strcpy where the length of just one of
833 the two arguments is known (determined by tree-ssa-strlen). */
834 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize)
836 /* When the destination size is unknown set it to the size of
837 the source. */
838 dstref->sizrange[0] = srcref->sizrange[0];
839 dstref->sizrange[1] = srcref->sizrange[1];
840 dstsize_set = true;
842 else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
844 /* When the size of the source access is unknown set it to the size
845 of the destination first and adjust it later if necessary. */
846 srcref->sizrange[0] = dstref->sizrange[0];
847 srcref->sizrange[1] = dstref->sizrange[1];
849 if (depends_p)
851 if (dstref->strbounded_p)
853 /* Read access by strncpy is constrained by the third
854 argument but except for a zero bound is at least one. */
855 srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
856 offset_int bound = wi::umin (srcref->basesize, bounds[1]);
857 if (bound < srcref->sizrange[1])
858 srcref->sizrange[1] = bound;
860 /* For string functions, adjust the size range of the source
861 reference by the inverse boundaries of the offset (because
862 the higher the offset into the string the shorter its
863 length). */
864 if (srcref->offrange[1] >= 0
865 && srcref->offrange[1] < srcref->sizrange[0])
866 srcref->sizrange[0] -= srcref->offrange[1];
867 else
868 srcref->sizrange[0] = 1;
870 if (srcref->offrange[0] > 0)
872 if (srcref->offrange[0] < srcref->sizrange[1])
873 srcref->sizrange[1] -= srcref->offrange[0];
874 else
875 srcref->sizrange[1] = 0;
878 dstadjust_p = true;
882 if (detect_overlap == &builtin_access::generic_overlap)
884 if (dstref->strbounded_p)
886 dstref->sizrange[0] = bounds[0];
887 dstref->sizrange[1] = bounds[1];
889 if (dstref->sizrange[0] < srcref->sizrange[0])
890 srcref->sizrange[0] = dstref->sizrange[0];
892 if (dstref->sizrange[1] < srcref->sizrange[1])
893 srcref->sizrange[1] = dstref->sizrange[1];
896 else if (detect_overlap == &builtin_access::strcpy_overlap)
898 if (!dstref->strbounded_p)
900 /* For strcpy, adjust the destination size range to match that
901 of the source computed above. */
902 if (depends_p && dstadjust_p)
904 dstref->sizrange[0] = srcref->sizrange[0];
905 dstref->sizrange[1] = srcref->sizrange[1];
909 else if (!dstsize_set && detect_overlap == &builtin_access::strcat_overlap)
911 dstref->sizrange[0] += srcref->sizrange[0] - 1;
912 dstref->sizrange[1] += srcref->sizrange[1] - 1;
915 if (dstref->strbounded_p)
917 /* For strncpy, adjust the destination size range to match that
918 of the source computed above. */
919 dstref->sizrange[0] = bounds[0];
920 dstref->sizrange[1] = bounds[1];
922 if (bounds[0] < srcref->sizrange[0])
923 srcref->sizrange[0] = bounds[0];
925 if (bounds[1] < srcref->sizrange[1])
926 srcref->sizrange[1] = bounds[1];
930 offset_int
931 builtin_access::overlap_size (const offset_int a[2], const offset_int b[2],
932 offset_int *off)
934 const offset_int *p = a;
935 const offset_int *q = b;
937 /* Point P at the bigger of the two ranges and Q at the smaller. */
938 if (wi::lts_p (a[1] - a[0], b[1] - b[0]))
940 p = b;
941 q = a;
944 if (p[0] < q[0])
946 if (p[1] < q[0])
947 return 0;
949 *off = q[0];
950 return wi::smin (p[1], q[1]) - q[0];
953 if (q[1] < p[0])
954 return 0;
956 off[0] = p[0];
957 return q[1] - p[0];
960 /* Return true if the bounded mempry (memcpy amd similar) or string function
961 access (strncpy and similar) ACS overlaps. */
963 bool
964 builtin_access::generic_overlap ()
966 builtin_access &acs = *this;
967 const builtin_memref *dstref = acs.dstref;
968 const builtin_memref *srcref = acs.srcref;
970 gcc_assert (dstref->base == srcref->base);
972 const offset_int maxobjsize = acs.dstref->maxobjsize;
974 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
976 /* Adjust the larger bounds of the offsets (which may be the first
977 element if the lower bound is larger than the upper bound) to
978 make them valid for the smallest access (if possible) but no smaller
979 than the smaller bounds. */
980 gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));
982 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
983 acs.dstoff[1] = maxsize - acs.dstsiz[0];
984 if (acs.dstoff[1] < acs.dstoff[0])
985 acs.dstoff[1] = acs.dstoff[0];
987 gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1]));
989 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
990 acs.srcoff[1] = maxsize - acs.srcsiz[0];
991 if (acs.srcoff[1] < acs.srcoff[0])
992 acs.srcoff[1] = acs.srcoff[0];
994 /* Determine the minimum and maximum space for the access given
995 the offsets. */
996 offset_int space[2];
997 space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
998 space[1] = space[0];
1000 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1001 if (acs.srcsiz[0] > 0)
1003 if (d < space[0])
1004 space[0] = d;
1006 if (space[1] < d)
1007 space[1] = d;
1009 else
1010 space[1] = acs.dstsiz[1];
1012 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1013 if (d < space[0])
1014 space[0] = d;
1016 if (space[1] < d)
1017 space[1] = d;
1019 /* Treat raw memory functions both of whose references are bounded
1020 as special and permit uncertain overlaps to go undetected. For
1021 all kinds of constant offset and constant size accesses, if
1022 overlap isn't certain it is not possible. */
1023 bool overlap_possible = space[0] < acs.dstsiz[1];
1024 if (!overlap_possible)
1025 return false;
1027 bool overlap_certain = space[1] < acs.dstsiz[0];
1029 /* True when the size of one reference depends on the offset of
1030 the other. */
1031 bool depends_p = detect_overlap != &builtin_access::generic_overlap;
1033 if (!overlap_certain)
1035 if (!dstref->strbounded_p && !depends_p)
1036 /* Memcpy only considers certain overlap. */
1037 return false;
1039 /* There's no way to distinguish an access to the same member
1040 of a structure from one to two distinct members of the same
1041 structure. Give up to avoid excessive false positives. */
1042 tree basetype = TREE_TYPE (dstref->base);
1044 if (POINTER_TYPE_P (basetype))
1045 basetype = TREE_TYPE (basetype);
1046 else
1047 while (TREE_CODE (basetype) == ARRAY_TYPE)
1048 basetype = TREE_TYPE (basetype);
1050 if (RECORD_OR_UNION_TYPE_P (basetype))
1051 return false;
1054 /* True for stpcpy and strcpy. */
1055 bool stxcpy_p = (!dstref->strbounded_p
1056 && detect_overlap == &builtin_access::strcpy_overlap);
1058 if (dstref->refoff >= 0
1059 && srcref->refoff >= 0
1060 && dstref->refoff != srcref->refoff
1061 && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p))
1062 return false;
1064 offset_int siz[2] = { maxobjsize + 1, 0 };
1066 ovloff[0] = HOST_WIDE_INT_MAX;
1067 ovloff[1] = HOST_WIDE_INT_MIN;
1069 if (stxcpy_p)
1071 /* Iterate over the extreme locations (on the horizontal axis formed
1072 by their offsets) and sizes of two regions and find their smallest
1073 and largest overlap and the corresponding offsets. */
1074 for (unsigned i = 0; i != 2; ++i)
1076 const offset_int a[2] = {
1077 acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i]
1080 const offset_int b[2] = {
1081 acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i]
1084 offset_int off;
1085 offset_int sz = overlap_size (a, b, &off);
1086 if (sz < siz[0])
1087 siz[0] = sz;
1089 if (siz[1] <= sz)
1090 siz[1] = sz;
1092 if (sz != 0)
1094 if (wi::lts_p (off, ovloff[0]))
1095 ovloff[0] = off.to_shwi ();
1096 if (wi::lts_p (ovloff[1], off))
1097 ovloff[1] = off.to_shwi ();
1101 else
1103 /* Iterate over the extreme locations (on the horizontal axis
1104 formed by their offsets) and sizes of the two regions and
1105 find their smallest and largest overlap and the corresponding
1106 offsets. */
1108 for (unsigned io = 0; io != 2; ++io)
1109 for (unsigned is = 0; is != 2; ++is)
1111 const offset_int a[2] = {
1112 acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is]
1115 for (unsigned jo = 0; jo != 2; ++jo)
1116 for (unsigned js = 0; js != 2; ++js)
1118 const offset_int b[2] = {
1119 acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
1122 offset_int off;
1123 offset_int sz = overlap_size (a, b, &off);
1124 if (sz < siz[0])
1125 siz[0] = sz;
1127 if (siz[1] <= sz)
1128 siz[1] = sz;
1130 if (sz != 0)
1132 if (wi::lts_p (off, ovloff[0]))
1133 ovloff[0] = off.to_shwi ();
1134 if (wi::lts_p (ovloff[1], off))
1135 ovloff[1] = off.to_shwi ();
1141 ovlsiz[0] = siz[0].to_shwi ();
1142 ovlsiz[1] = siz[1].to_shwi ();
1144 /* Adjust the overlap offset range to reflect the overlap size range. */
1145 if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
1146 ovloff[1] = ovloff[0] + ovlsiz[1] - 1;
1148 return true;
1151 /* Return true if the strcat-like access overlaps. */
1153 bool
1154 builtin_access::strcat_overlap ()
1156 builtin_access &acs = *this;
1157 const builtin_memref *dstref = acs.dstref;
1158 const builtin_memref *srcref = acs.srcref;
1160 gcc_assert (dstref->base == srcref->base);
1162 const offset_int maxobjsize = acs.dstref->maxobjsize;
1164 gcc_assert (dstref->base && dstref->base == srcref->base);
1166 /* Adjust for strcat-like accesses. */
1168 /* As a special case for strcat, set the DSTREF offsets to the length
1169 of the destination string since the function starts writing over
1170 its terminating nul, and set the destination size to 1 for the length
1171 of the nul. */
1172 acs.dstoff[0] += dstsiz[0] - srcref->sizrange[0];
1173 acs.dstoff[1] += dstsiz[1] - srcref->sizrange[1];
1175 bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0;
1177 /* The lower bound is zero when the size is unknown because then
1178 overlap is not certain. */
1179 acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1;
1180 acs.dstsiz[1] = 1;
1182 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
1184 /* For references to the same base object, determine if there's a pair
1185 of valid offsets into the two references such that access between
1186 them doesn't overlap. Adjust both upper bounds to be valid for
1187 the smaller size (i.e., at most MAXSIZE - SIZE). */
1189 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
1190 acs.dstoff[1] = maxsize - acs.dstsiz[0];
1192 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
1193 acs.srcoff[1] = maxsize - acs.srcsiz[0];
1195 /* Check to see if there's enough space for both accesses without
1196 overlap. Determine the optimistic (maximum) amount of available
1197 space. */
1198 offset_int space;
1199 if (acs.dstoff[0] <= acs.srcoff[0])
1201 if (acs.dstoff[1] < acs.srcoff[1])
1202 space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0];
1203 else
1204 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1206 else
1207 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1209 /* Overlap is certain if the distance between the farthest offsets
1210 of the opposite accesses is less than the sum of the lower bounds
1211 of the sizes of the two accesses. */
1212 bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0];
1214 /* For a constant-offset, constant size access, consider the largest
1215 distance between the offset bounds and the lower bound of the access
1216 size. If the overlap isn't certain return success. */
1217 if (!overlap_certain
1218 && acs.dstoff[0] == acs.dstoff[1]
1219 && acs.srcoff[0] == acs.srcoff[1]
1220 && acs.dstsiz[0] == acs.dstsiz[1]
1221 && acs.srcsiz[0] == acs.srcsiz[1])
1222 return false;
1224 /* Overlap is not certain but may be possible. */
1226 offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0];
1228 /* Determine the conservative (minimum) amount of space. */
1229 space = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1230 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1231 if (d < space)
1232 space = d;
1233 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1234 if (d < space)
1235 space = d;
1237 /* For a strict test (used for strcpy and similar with unknown or
1238 variable bounds or sizes), consider the smallest distance between
1239 the offset bounds and either the upper bound of the access size
1240 if known, or the lower bound otherwise. */
1241 if (access_min <= space && (access_min != 0 || !strfunc_unknown_args))
1242 return false;
1244 /* When strcat overlap is certain it is always a single byte:
1245 the terminating NUL, regardless of offsets and sizes. When
1246 overlap is only possible its range is [0, 1]. */
1247 acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
1248 acs.ovlsiz[1] = 1;
1250 offset_int endoff
1251 = dstref->offrange[0] + (dstref->sizrange[0] - srcref->sizrange[0]);
1252 if (endoff <= srcref->offrange[0])
1253 acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi ();
1254 else
1255 acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi ();
1257 acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1,
1258 srcref->sizrange[0]).to_shwi ();
1259 if (dstref->offrange[0] == dstref->offrange[1])
1261 if (srcref->offrange[0] == srcref->offrange[1])
1262 acs.ovloff[1] = acs.ovloff[0];
1263 else
1264 acs.ovloff[1]
1265 = wi::smin (maxobjsize,
1266 srcref->offrange[1] + srcref->sizrange[1]).to_shwi ();
1268 else
1269 acs.ovloff[1]
1270 = wi::smin (maxobjsize,
1271 dstref->offrange[1] + dstref->sizrange[1]).to_shwi ();
1273 if (acs.sizrange[0] == 0)
1274 acs.sizrange[0] = 1;
1275 acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1276 return true;
1279 /* Return true if the strcpy-like access overlaps. */
1281 bool
1282 builtin_access::strcpy_overlap ()
1284 return generic_overlap ();
1287 /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
1288 if known, or [0, MAXOBJSIZE] otherwise. */
1290 static void
1291 clamp_offset (tree base, offset_int refoff[2], offset_int maxobjsize)
1293 if (!base || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
1294 return;
1296 if (refoff[0] < 0 && refoff[1] >= 0)
1297 refoff[0] = 0;
1299 if (refoff[1] < refoff[0])
1301 offset_int maxsize = maxobjsize;
1302 if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (base)))
1303 maxsize = wi::to_offset (size);
1305 refoff[1] = wi::umin (refoff[1], maxsize);
1309 /* Return true if DSTREF and SRCREF describe accesses that either overlap
1310 one another or that, in order not to overlap, would imply that the size
1311 of the referenced object(s) exceeds the maximum size of an object. Set
1312 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1313 they may overlap in a way that's not apparent from the available data),
1314 return false. */
1316 bool
1317 builtin_access::overlap ()
1319 builtin_access &acs = *this;
1321 const offset_int maxobjsize = dstref->maxobjsize;
1323 acs.sizrange[0] = wi::smax (dstref->sizrange[0],
1324 srcref->sizrange[0]).to_shwi ();
1325 acs.sizrange[1] = wi::smax (dstref->sizrange[1],
1326 srcref->sizrange[1]).to_shwi ();
1328 /* Check to see if the two references refer to regions that are
1329 too large not to overlap in the address space (whose maximum
1330 size is PTRDIFF_MAX). */
1331 offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
1332 if (maxobjsize < size)
1334 acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi ();
1335 acs.ovlsiz[0] = (size - maxobjsize).to_shwi ();
1336 return true;
1339 /* If both base objects aren't known return the maximum possible
1340 offset that would make them not overlap. */
1341 if (!dstref->base || !srcref->base)
1342 return false;
1344 /* If the base object is an array adjust the bounds of the offset
1345 to be non-negative and within the bounds of the array if possible. */
1346 clamp_offset (dstref->base, acs.dstoff, maxobjsize);
1348 acs.srcoff[0] = srcref->offrange[0];
1349 acs.srcoff[1] = srcref->offrange[1];
1351 clamp_offset (srcref->base, acs.srcoff, maxobjsize);
1353 /* When the upper bound of the offset is less than the lower bound
1354 the former is the result of a negative offset being represented
1355 as a large positive value or vice versa. The resulting range is
1356 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1357 a union is not representable using the current data structure
1358 replace it with the full range of offsets. */
1359 if (acs.dstoff[1] < acs.dstoff[0])
1361 acs.dstoff[0] = -maxobjsize - 1;
1362 acs.dstoff[1] = maxobjsize;
1365 /* Validate the offset and size of each reference on its own first.
1366 This is independent of whether or not the base objects are the
1367 same. Normally, this would have already been detected and
1368 diagnosed by -Warray-bounds, unless it has been disabled. */
1369 offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
1370 if (maxobjsize < maxoff)
1372 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1373 acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0];
1374 return true;
1377 /* Repeat the same as above but for the source offsets. */
1378 if (acs.srcoff[1] < acs.srcoff[0])
1380 acs.srcoff[0] = -maxobjsize - 1;
1381 acs.srcoff[1] = maxobjsize;
1384 maxoff = acs.srcoff[0] + srcref->sizrange[0];
1385 if (maxobjsize < maxoff)
1387 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1388 acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1]
1389 - maxobjsize).to_shwi ();
1390 acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0];
1391 return true;
1394 if (dstref->base != srcref->base)
1395 return false;
1397 acs.dstsiz[0] = dstref->sizrange[0];
1398 acs.dstsiz[1] = dstref->sizrange[1];
1400 acs.srcsiz[0] = srcref->sizrange[0];
1401 acs.srcsiz[1] = srcref->sizrange[1];
1403 /* Call the appropriate function to determine the overlap. */
1404 if ((this->*detect_overlap) ())
1406 if (!sizrange[1])
1408 /* Unless the access size range has already been set, do so here. */
1409 sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi ();
1410 sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1412 return true;
1415 return false;
1418 /* Attempt to detect and diagnose an overlapping copy in a call expression
1419 EXPR involving an access ACS to a built-in memory or string function.
1420 Return true when one has been detected, false otherwise. */
1422 static bool
1423 maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
1425 if (!acs.overlap ())
1426 return false;
1428 if (warning_suppressed_p (call, OPT_Wrestrict))
1429 return true;
1431 /* For convenience. */
1432 const builtin_memref &dstref = *acs.dstref;
1433 const builtin_memref &srcref = *acs.srcref;
1435 /* Determine the range of offsets and sizes of the overlap if it
1436 exists and issue diagnostics. */
1437 HOST_WIDE_INT *ovloff = acs.ovloff;
1438 HOST_WIDE_INT *ovlsiz = acs.ovlsiz;
1439 HOST_WIDE_INT *sizrange = acs.sizrange;
1441 tree func = gimple_call_fndecl (call);
1443 /* To avoid a combinatorial explosion of diagnostics format the offsets
1444 or their ranges as strings and use them in the warning calls below. */
1445 char offstr[3][64];
1447 if (dstref.offrange[0] == dstref.offrange[1]
1448 || dstref.offrange[1] > HOST_WIDE_INT_MAX)
1449 sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC,
1450 dstref.offrange[0].to_shwi ());
1451 else
1452 sprintf (offstr[0],
1453 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1454 dstref.offrange[0].to_shwi (),
1455 dstref.offrange[1].to_shwi ());
1457 if (srcref.offrange[0] == srcref.offrange[1]
1458 || srcref.offrange[1] > HOST_WIDE_INT_MAX)
1459 sprintf (offstr[1],
1460 HOST_WIDE_INT_PRINT_DEC,
1461 srcref.offrange[0].to_shwi ());
1462 else
1463 sprintf (offstr[1],
1464 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1465 srcref.offrange[0].to_shwi (),
1466 srcref.offrange[1].to_shwi ());
1468 if (ovloff[0] == ovloff[1] || !ovloff[1])
1469 sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]);
1470 else
1471 sprintf (offstr[2],
1472 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1473 ovloff[0], ovloff[1]);
1475 const offset_int maxobjsize = dstref.maxobjsize;
1476 bool must_overlap = ovlsiz[0] > 0;
1478 if (ovlsiz[1] == 0)
1479 ovlsiz[1] = ovlsiz[0];
1481 if (must_overlap)
1483 /* Issue definitive "overlaps" diagnostic in this block. */
1485 if (sizrange[0] == sizrange[1])
1487 if (ovlsiz[0] == ovlsiz[1])
1488 warning_at (loc, OPT_Wrestrict,
1489 sizrange[0] == 1
1490 ? (ovlsiz[0] == 1
1491 ? G_("%qD accessing %wu byte at offsets %s "
1492 "and %s overlaps %wu byte at offset %s")
1493 : G_("%qD accessing %wu byte at offsets %s "
1494 "and %s overlaps %wu bytes at offset "
1495 "%s"))
1496 : (ovlsiz[0] == 1
1497 ? G_("%qD accessing %wu bytes at offsets %s "
1498 "and %s overlaps %wu byte at offset %s")
1499 : G_("%qD accessing %wu bytes at offsets %s "
1500 "and %s overlaps %wu bytes at offset "
1501 "%s")),
1502 func, sizrange[0],
1503 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1504 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1505 warning_n (loc, OPT_Wrestrict, sizrange[0],
1506 "%qD accessing %wu byte at offsets %s "
1507 "and %s overlaps between %wu and %wu bytes "
1508 "at offset %s",
1509 "%qD accessing %wu bytes at offsets %s "
1510 "and %s overlaps between %wu and %wu bytes "
1511 "at offset %s",
1512 func, sizrange[0], offstr[0], offstr[1],
1513 ovlsiz[0], ovlsiz[1], offstr[2]);
1514 else
1515 warning_n (loc, OPT_Wrestrict, sizrange[0],
1516 "%qD accessing %wu byte at offsets %s and "
1517 "%s overlaps %wu or more bytes at offset %s",
1518 "%qD accessing %wu bytes at offsets %s and "
1519 "%s overlaps %wu or more bytes at offset %s",
1520 func, sizrange[0],
1521 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1522 return true;
1525 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1527 if (ovlsiz[0] == ovlsiz[1])
1528 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
1529 "%qD accessing between %wu and %wu bytes "
1530 "at offsets %s and %s overlaps %wu byte at "
1531 "offset %s",
1532 "%qD accessing between %wu and %wu bytes "
1533 "at offsets %s and %s overlaps %wu bytes "
1534 "at offset %s",
1535 func, sizrange[0], sizrange[1],
1536 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1537 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1538 warning_at (loc, OPT_Wrestrict,
1539 "%qD accessing between %wu and %wu bytes at "
1540 "offsets %s and %s overlaps between %wu and %wu "
1541 "bytes at offset %s",
1542 func, sizrange[0], sizrange[1],
1543 offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
1544 offstr[2]);
1545 else
1546 warning_at (loc, OPT_Wrestrict,
1547 "%qD accessing between %wu and %wu bytes at "
1548 "offsets %s and %s overlaps %wu or more bytes "
1549 "at offset %s",
1550 func, sizrange[0], sizrange[1],
1551 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1552 return true;
1555 if (ovlsiz[0] != ovlsiz[1])
1556 ovlsiz[1] = maxobjsize.to_shwi ();
1558 if (ovlsiz[0] == ovlsiz[1])
1559 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
1560 "%qD accessing %wu or more bytes at offsets "
1561 "%s and %s overlaps %wu byte at offset %s",
1562 "%qD accessing %wu or more bytes at offsets "
1563 "%s and %s overlaps %wu bytes at offset %s",
1564 func, sizrange[0], offstr[0], offstr[1],
1565 ovlsiz[0], offstr[2]);
1566 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1567 warning_at (loc, OPT_Wrestrict,
1568 "%qD accessing %wu or more bytes at offsets %s "
1569 "and %s overlaps between %wu and %wu bytes "
1570 "at offset %s",
1571 func, sizrange[0], offstr[0], offstr[1],
1572 ovlsiz[0], ovlsiz[1], offstr[2]);
1573 else
1574 warning_at (loc, OPT_Wrestrict,
1575 "%qD accessing %wu or more bytes at offsets %s "
1576 "and %s overlaps %wu or more bytes at offset %s",
1577 func, sizrange[0], offstr[0], offstr[1],
1578 ovlsiz[0], offstr[2]);
1579 return true;
1582 /* Use more concise wording when one of the offsets is unbounded
1583 to avoid confusing the user with large and mostly meaningless
1584 numbers. */
1585 bool open_range;
1586 if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
1587 open_range = ((dstref.offrange[0] == 0
1588 && dstref.offrange[1] == maxobjsize)
1589 || (srcref.offrange[0] == 0
1590 && srcref.offrange[1] == maxobjsize));
1591 else
1592 open_range = ((dstref.offrange[0] == -maxobjsize - 1
1593 && dstref.offrange[1] == maxobjsize)
1594 || (srcref.offrange[0] == -maxobjsize - 1
1595 && srcref.offrange[1] == maxobjsize));
1597 if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
1599 if (ovlsiz[1] == 1)
1601 if (open_range)
1602 warning_n (loc, OPT_Wrestrict, sizrange[1],
1603 "%qD accessing %wu byte may overlap "
1604 "%wu byte",
1605 "%qD accessing %wu bytes may overlap "
1606 "%wu byte",
1607 func, sizrange[1], ovlsiz[1]);
1608 else
1609 warning_n (loc, OPT_Wrestrict, sizrange[1],
1610 "%qD accessing %wu byte at offsets %s "
1611 "and %s may overlap %wu byte at offset %s",
1612 "%qD accessing %wu bytes at offsets %s "
1613 "and %s may overlap %wu byte at offset %s",
1614 func, sizrange[1], offstr[0], offstr[1],
1615 ovlsiz[1], offstr[2]);
1616 return true;
1619 if (open_range)
1620 warning_n (loc, OPT_Wrestrict, sizrange[1],
1621 "%qD accessing %wu byte may overlap "
1622 "up to %wu bytes",
1623 "%qD accessing %wu bytes may overlap "
1624 "up to %wu bytes",
1625 func, sizrange[1], ovlsiz[1]);
1626 else
1627 warning_n (loc, OPT_Wrestrict, sizrange[1],
1628 "%qD accessing %wu byte at offsets %s and "
1629 "%s may overlap up to %wu bytes at offset %s",
1630 "%qD accessing %wu bytes at offsets %s and "
1631 "%s may overlap up to %wu bytes at offset %s",
1632 func, sizrange[1], offstr[0], offstr[1],
1633 ovlsiz[1], offstr[2]);
1634 return true;
1637 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1639 if (open_range)
1640 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1641 "%qD accessing between %wu and %wu bytes "
1642 "may overlap %wu byte",
1643 "%qD accessing between %wu and %wu bytes "
1644 "may overlap up to %wu bytes",
1645 func, sizrange[0], sizrange[1], ovlsiz[1]);
1646 else
1647 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1648 "%qD accessing between %wu and %wu bytes "
1649 "at offsets %s and %s may overlap %wu byte "
1650 "at offset %s",
1651 "%qD accessing between %wu and %wu bytes "
1652 "at offsets %s and %s may overlap up to %wu "
1653 "bytes at offset %s",
1654 func, sizrange[0], sizrange[1],
1655 offstr[0], offstr[1], ovlsiz[1], offstr[2]);
1656 return true;
1659 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1660 "%qD accessing %wu or more bytes at offsets %s "
1661 "and %s may overlap %wu byte at offset %s",
1662 "%qD accessing %wu or more bytes at offsets %s "
1663 "and %s may overlap up to %wu bytes at offset %s",
1664 func, sizrange[0], offstr[0], offstr[1],
1665 ovlsiz[1], offstr[2]);
1667 return true;
1670 /* Validate REF size and offsets in an expression passed as an argument
1671 to a CALL to a built-in function FUNC to make sure they are within
1672 the bounds of the referenced object if its size is known, or
1673 PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1674 be issued, false otherwise.
1675 Both initial values of the offsets and their final value computed
1676 by the function by incrementing the initial value by the size are
1677 validated. Return the warning number if the offsets are not valid
1678 and a diagnostic has been issued, or would have been issued if
1679 DO_WARN had been true, otherwise an invalid warning number. */
1681 static opt_code
1682 maybe_diag_access_bounds (gimple *call, tree func, int strict,
1683 const builtin_memref &ref, offset_int wroff,
1684 bool do_warn)
1686 location_t loc = gimple_location (call);
1687 const offset_int maxobjsize = ref.maxobjsize;
1689 /* Check for excessive size first and regardless of warning options
1690 since the result is used to make codegen decisions. */
1691 if (ref.sizrange[0] > maxobjsize)
1693 const opt_code opt = OPT_Wstringop_overflow_;
1694 /* Return true without issuing a warning. */
1695 if (!do_warn)
1696 return opt;
1698 if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
1699 return no_warning;
1701 bool warned = false;
1702 if (warn_stringop_overflow)
1704 if (ref.sizrange[0] == ref.sizrange[1])
1705 warned = warning_at (loc, opt,
1706 "%qD specified bound %wu "
1707 "exceeds maximum object size %wu",
1708 func, ref.sizrange[0].to_uhwi (),
1709 maxobjsize.to_uhwi ());
1710 else
1711 warned = warning_at (loc, opt,
1712 "%qD specified bound between %wu and %wu "
1713 "exceeds maximum object size %wu",
1714 func, ref.sizrange[0].to_uhwi (),
1715 ref.sizrange[1].to_uhwi (),
1716 maxobjsize.to_uhwi ());
1717 return warned ? opt : no_warning;
1721 /* Check for out-bounds pointers regardless of warning options since
1722 the result is used to make codegen decisions. An excessive WROFF
1723 can only come up as a result of an invalid strncat bound and is
1724 diagnosed separately using a more meaningful warning. */
1725 if (maxobjsize < wroff)
1726 wroff = 0;
1727 offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
1728 tree oobref = ref.offset_out_of_bounds (strict, ooboff);
1729 if (!oobref)
1730 return no_warning;
1732 const opt_code opt = OPT_Warray_bounds;
1733 /* Return true without issuing a warning. */
1734 if (!do_warn)
1735 return opt;
1737 if (!warn_array_bounds)
1738 return no_warning;
1740 if (warning_suppressed_p (ref.ptr, opt)
1741 || (ref.ref && warning_suppressed_p (ref.ref, opt)))
1742 return no_warning;
1744 char rangestr[2][64];
1745 if (ooboff[0] == ooboff[1]
1746 || (ooboff[0] != ref.offrange[0]
1747 && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
1748 sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ());
1749 else
1750 sprintf (rangestr[0], "[%lli, %lli]",
1751 (long long) ooboff[0].to_shwi (),
1752 (long long) ooboff[1].to_shwi ());
1754 bool warned = false;
1756 if (oobref == error_mark_node)
1758 if (ref.sizrange[0] == ref.sizrange[1])
1759 sprintf (rangestr[1], "%llu",
1760 (unsigned long long) ref.sizrange[0].to_shwi ());
1761 else
1762 sprintf (rangestr[1], "[%lli, %lli]",
1763 (unsigned long long) ref.sizrange[0].to_uhwi (),
1764 (unsigned long long) ref.sizrange[1].to_uhwi ());
1766 tree type;
1768 if (DECL_P (ref.base)
1769 && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
1771 auto_diagnostic_group d;
1772 if (warning_at (loc, opt,
1773 "%qD pointer overflow between offset %s "
1774 "and size %s accessing array %qD with type %qT",
1775 func, rangestr[0], rangestr[1], ref.base, type))
1777 inform (DECL_SOURCE_LOCATION (ref.base),
1778 "array %qD declared here", ref.base);
1779 warned = true;
1781 else
1782 warned = warning_at (loc, opt,
1783 "%qD pointer overflow between offset %s "
1784 "and size %s",
1785 func, rangestr[0], rangestr[1]);
1787 else
1788 warned = warning_at (loc, opt,
1789 "%qD pointer overflow between offset %s "
1790 "and size %s",
1791 func, rangestr[0], rangestr[1]);
1793 else if (oobref == ref.base)
1795 /* True when the offset formed by an access to the reference
1796 is out of bounds, rather than the initial offset wich is
1797 in bounds. This implies access past the end. */
1798 bool form = ooboff[0] != ref.offrange[0];
1800 if (DECL_P (ref.base))
1802 auto_diagnostic_group d;
1803 if ((ref.basesize < maxobjsize
1804 && warning_at (loc, opt,
1805 form
1806 ? G_("%qD forming offset %s is out of "
1807 "the bounds [0, %wu] of object %qD with "
1808 "type %qT")
1809 : G_("%qD offset %s is out of the bounds "
1810 "[0, %wu] of object %qD with type %qT"),
1811 func, rangestr[0], ref.basesize.to_uhwi (),
1812 ref.base, TREE_TYPE (ref.base)))
1813 || warning_at (loc, opt,
1814 form
1815 ? G_("%qD forming offset %s is out of "
1816 "the bounds of object %qD with type %qT")
1817 : G_("%qD offset %s is out of the bounds "
1818 "of object %qD with type %qT"),
1819 func, rangestr[0],
1820 ref.base, TREE_TYPE (ref.base)))
1822 inform (DECL_SOURCE_LOCATION (ref.base),
1823 "%qD declared here", ref.base);
1824 warned = true;
1827 else if (ref.basesize < maxobjsize)
1828 warned = warning_at (loc, opt,
1829 form
1830 ? G_("%qD forming offset %s is out "
1831 "of the bounds [0, %wu]")
1832 : G_("%qD offset %s is out "
1833 "of the bounds [0, %wu]"),
1834 func, rangestr[0], ref.basesize.to_uhwi ());
1835 else
1836 warned = warning_at (loc, opt,
1837 form
1838 ? G_("%qD forming offset %s is out of bounds")
1839 : G_("%qD offset %s is out of bounds"),
1840 func, rangestr[0]);
1842 else if (TREE_CODE (ref.ref) == MEM_REF)
1844 tree refop = TREE_OPERAND (ref.ref, 0);
1845 tree type = TREE_TYPE (refop);
1846 if (POINTER_TYPE_P (type))
1847 type = TREE_TYPE (type);
1848 type = TYPE_MAIN_VARIANT (type);
1850 if (warning_at (loc, opt,
1851 "%qD offset %s from the object at %qE is out "
1852 "of the bounds of %qT",
1853 func, rangestr[0], ref.base, type))
1855 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1856 refop = TREE_OPERAND (ref.ref, 1);
1857 if (DECL_P (refop))
1858 inform (DECL_SOURCE_LOCATION (refop),
1859 "subobject %qD declared here", refop);
1860 warned = true;
1863 else
1865 tree refop = TREE_OPERAND (ref.ref, 0);
1866 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
1868 if (warning_at (loc, opt,
1869 "%qD offset %s from the object at %qE is out "
1870 "of the bounds of referenced subobject %qD with "
1871 "type %qT at offset %wi",
1872 func, rangestr[0], ref.base,
1873 TREE_OPERAND (ref.ref, 1), type,
1874 ref.refoff.to_shwi ()))
1876 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1877 refop = TREE_OPERAND (ref.ref, 1);
1878 if (DECL_P (refop))
1879 inform (DECL_SOURCE_LOCATION (refop),
1880 "subobject %qD declared here", refop);
1881 warned = true;
1885 return warned ? opt : no_warning;
1888 /* Check a CALL statement for restrict-violations and issue warnings
1889 if/when appropriate. */
1891 void
1892 pass_wrestrict::check_call (gimple *call)
1894 /* Avoid checking the call if it has already been diagnosed for
1895 some reason. */
1896 if (warning_suppressed_p (call, OPT_Wrestrict))
1897 return;
1899 tree func = gimple_call_fndecl (call);
1900 if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
1901 return;
1903 /* Argument number to extract from the call (depends on the built-in
1904 and its kind). */
1905 unsigned dst_idx = -1;
1906 unsigned src_idx = -1;
1907 unsigned bnd_idx = -1;
1909 /* Is this CALL to a string function (as opposed to one to a raw
1910 memory function). */
1911 bool strfun = true;
1913 switch (DECL_FUNCTION_CODE (func))
1915 case BUILT_IN_MEMCPY:
1916 case BUILT_IN_MEMCPY_CHK:
1917 case BUILT_IN_MEMPCPY:
1918 case BUILT_IN_MEMPCPY_CHK:
1919 case BUILT_IN_MEMMOVE:
1920 case BUILT_IN_MEMMOVE_CHK:
1921 strfun = false;
1922 /* Fall through. */
1924 case BUILT_IN_STPNCPY:
1925 case BUILT_IN_STPNCPY_CHK:
1926 case BUILT_IN_STRNCAT:
1927 case BUILT_IN_STRNCAT_CHK:
1928 case BUILT_IN_STRNCPY:
1929 case BUILT_IN_STRNCPY_CHK:
1930 dst_idx = 0;
1931 src_idx = 1;
1932 bnd_idx = 2;
1933 break;
1935 case BUILT_IN_MEMSET:
1936 case BUILT_IN_MEMSET_CHK:
1937 dst_idx = 0;
1938 bnd_idx = 2;
1939 break;
1941 case BUILT_IN_STPCPY:
1942 case BUILT_IN_STPCPY_CHK:
1943 case BUILT_IN_STRCPY:
1944 case BUILT_IN_STRCPY_CHK:
1945 case BUILT_IN_STRCAT:
1946 case BUILT_IN_STRCAT_CHK:
1947 dst_idx = 0;
1948 src_idx = 1;
1949 break;
1951 default:
1952 /* Handle other string functions here whose access may need
1953 to be validated for in-bounds offsets and non-overlapping
1954 copies. */
1955 return;
1958 unsigned nargs = gimple_call_num_args (call);
1960 tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
1961 tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
1962 tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE;
1964 /* For string functions with an unspecified or unknown bound,
1965 assume the size of the access is one. */
1966 if (!dstwr && strfun)
1967 dstwr = size_one_node;
1969 /* DST and SRC can be null for a call with an insufficient number
1970 of arguments to a built-in function declared without a protype. */
1971 if (!dst || (src_idx < nargs && !src))
1972 return;
1974 /* DST, SRC, or DSTWR can also have the wrong type in a call to
1975 a function declared without a prototype. Avoid checking such
1976 invalid calls. */
1977 if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
1978 || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
1979 || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
1980 return;
1982 opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr,
1983 NULL_TREE);
1984 /* Avoid diagnosing the call again. */
1985 suppress_warning (call, opt);
1988 } /* anonymous namespace */
1990 /* Attempt to detect and diagnose invalid offset bounds and (except for
1991 memmove) overlapping copy in a call expression EXPR from SRC to DST
1992 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
1993 SRCSIZE may be NULL. DO_WARN is false to detect either problem
1994 without issue a warning. Return the OPT_Wxxx constant corresponding
1995 to the warning if one has been detected and zero otherwise. */
1997 opt_code
1998 check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
1999 tree srcsize, bool bounds_only /* = false */,
2000 bool do_warn /* = true */)
2002 pointer_query ptrqry (get_range_query (cfun));
2003 return check_bounds_or_overlap (ptrqry,
2004 call, dst, src, dstsize, srcsize,
2005 bounds_only, do_warn);
2008 opt_code
2009 check_bounds_or_overlap (pointer_query &ptrqry,
2010 gimple *call, tree dst, tree src, tree dstsize,
2011 tree srcsize, bool bounds_only /* = false */,
2012 bool do_warn /* = true */)
2014 tree func = gimple_call_fndecl (call);
2016 builtin_memref dstref (ptrqry, call, dst, dstsize);
2017 builtin_memref srcref (ptrqry, call, src, srcsize);
2019 /* Create a descriptor of the access. This may adjust both DSTREF
2020 and SRCREF based on one another and the kind of the access. */
2021 builtin_access acs (ptrqry, call, dstref, srcref);
2023 /* Set STRICT to the value of the -Warray-bounds=N argument for
2024 string functions or when N > 1. */
2025 int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0);
2027 /* The starting offset of the destination write access. Nonzero only
2028 for the strcat family of functions. */
2029 offset_int wroff = acs.write_off (dstsize);
2031 /* Validate offsets to each reference before the access first to make
2032 sure they are within the bounds of the destination object if its
2033 size is known, or PTRDIFF_MAX otherwise. */
2034 opt_code opt
2035 = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
2036 if (opt == no_warning)
2037 opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
2039 if (opt != no_warning)
2041 if (do_warn)
2042 suppress_warning (call, opt);
2043 return opt;
2046 if (!warn_restrict || bounds_only || !src)
2047 return no_warning;
2049 if (!bounds_only)
2051 switch (DECL_FUNCTION_CODE (func))
2053 case BUILT_IN_MEMMOVE:
2054 case BUILT_IN_MEMMOVE_CHK:
2055 case BUILT_IN_MEMSET:
2056 case BUILT_IN_MEMSET_CHK:
2057 return no_warning;
2058 default:
2059 break;
2063 location_t loc = gimple_location (call);
2064 if (operand_equal_p (dst, src, 0))
2066 /* Issue -Wrestrict unless the pointers are null (those do
2067 not point to objects and so do not indicate an overlap;
2068 such calls could be the result of sanitization and jump
2069 threading). */
2070 if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
2072 warning_at (loc, OPT_Wrestrict,
2073 "%qD source argument is the same as destination",
2074 func);
2075 suppress_warning (call, OPT_Wrestrict);
2076 return OPT_Wrestrict;
2079 return no_warning;
2082 /* Return false when overlap has been detected. */
2083 if (maybe_diag_overlap (loc, call, acs))
2085 suppress_warning (call, OPT_Wrestrict);
2086 return OPT_Wrestrict;
2089 return no_warning;
2092 gimple_opt_pass *
2093 make_pass_warn_restrict (gcc::context *ctxt)
2095 return new pass_wrestrict (ctxt);
2098 DEBUG_FUNCTION void
2099 dump_builtin_memref (FILE *fp, const builtin_memref &ref)
2101 fprintf (fp, "\n ptr = ");
2102 print_generic_expr (fp, ref.ptr, TDF_LINENO);
2103 fprintf (fp, "\n ref = ");
2104 if (ref.ref)
2105 print_generic_expr (fp, ref.ref, TDF_LINENO);
2106 else
2107 fputs ("null", fp);
2108 fprintf (fp, "\n base = ");
2109 print_generic_expr (fp, ref.base, TDF_LINENO);
2110 fprintf (fp,
2111 "\n basesize = %lli"
2112 "\n refsize = %lli"
2113 "\n refoff = %lli"
2114 "\n offrange = [%lli, %lli]"
2115 "\n sizrange = [%lli, %lli]"
2116 "\n strbounded_p = %s\n",
2117 (long long)ref.basesize.to_shwi (),
2118 (long long)ref.refsize.to_shwi (),
2119 (long long)ref.refoff.to_shwi (),
2120 (long long)ref.offrange[0].to_shwi (),
2121 (long long)ref.offrange[1].to_shwi (),
2122 (long long)ref.sizrange[0].to_shwi (),
2123 (long long)ref.sizrange[1].to_shwi (),
2124 ref.strbounded_p ? "true" : "false");
2127 void
2128 builtin_access::dump (FILE *fp) const
2130 fprintf (fp, " dstref:");
2131 dump_builtin_memref (fp, *dstref);
2132 fprintf (fp, "\n srcref:");
2133 dump_builtin_memref (fp, *srcref);
2135 fprintf (fp,
2136 " sizrange = [%lli, %lli]\n"
2137 " ovloff = [%lli, %lli]\n"
2138 " ovlsiz = [%lli, %lli]\n"
2139 " dstoff = [%lli, %lli]\n"
2140 " dstsiz = [%lli, %lli]\n"
2141 " srcoff = [%lli, %lli]\n"
2142 " srcsiz = [%lli, %lli]\n",
2143 (long long)sizrange[0], (long long)sizrange[1],
2144 (long long)ovloff[0], (long long)ovloff[1],
2145 (long long)ovlsiz[0], (long long)ovlsiz[1],
2146 (long long)dstoff[0].to_shwi (), (long long)dstoff[1].to_shwi (),
2147 (long long)dstsiz[0].to_shwi (), (long long)dstsiz[1].to_shwi (),
2148 (long long)srcoff[0].to_shwi (), (long long)srcoff[1].to_shwi (),
2149 (long long)srcsiz[0].to_shwi (), (long long)srcsiz[1].to_shwi ());
2152 DEBUG_FUNCTION void
2153 dump_builtin_access (FILE *fp, gimple *stmt, const builtin_access &acs)
2155 if (stmt)
2157 fprintf (fp, "\nDumping builtin_access for ");
2158 print_gimple_expr (fp, stmt, TDF_LINENO);
2159 fputs (":\n", fp);
2162 acs.dump (fp);
2165 DEBUG_FUNCTION void
2166 debug (gimple *stmt, const builtin_access &acs)
2168 dump_builtin_access (stdout, stmt, acs);