Revise -mdisable-fpregs option and add new -msoft-mult option
[official-gcc.git] / gcc / gimple-ssa-warn-restrict.c
blobd1df9ca8d4fc1412c4f82777ff00c5959a68c899
1 /* Pass to detect and issue warnings for violations of the restrict
2 qualifier.
3 Copyright (C) 2017-2021 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 *ctxt)
66 : gimple_opt_pass (pass_data_wrestrict, ctxt)
67 { }
69 opt_pass *clone () { return new pass_wrestrict (m_ctxt); }
71 virtual bool gate (function *);
72 virtual unsigned int execute (function *);
75 bool
76 pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
78 return warn_array_bounds || warn_restrict || warn_stringop_overflow;
81 static void check_call (range_query *, gimple *);
83 static void
84 wrestrict_walk (range_query *query, basic_block bb)
86 /* Iterate over statements, looking for function calls. */
87 for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
88 gsi_next (&si))
90 gimple *stmt = gsi_stmt (si);
91 if (!is_gimple_call (stmt))
92 continue;
94 check_call (query, stmt);
98 unsigned
99 pass_wrestrict::execute (function *fun)
101 gimple_ranger ranger;
102 basic_block bb;
103 FOR_EACH_BB_FN (bb, fun)
104 wrestrict_walk (&ranger, bb);
106 return 0;
109 /* Description of a memory reference by a built-in function. This
110 is similar to ao_ref but made especially suitable for -Wrestrict
111 and not for optimization. */
112 class builtin_memref
114 public:
115 /* The original pointer argument to the built-in function. */
116 tree ptr;
117 /* The referenced subobject or NULL if not available, and the base
118 object of the memory reference or NULL. */
119 tree ref;
120 tree base;
122 /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
123 and negative until (possibly lazily) initialized. */
124 offset_int basesize;
125 /* Same for the subobject. */
126 offset_int refsize;
128 /* The non-negative offset of the referenced subobject. Used to avoid
129 warnings for (apparently) possibly but not definitively overlapping
130 accesses to member arrays. Negative when unknown/invalid. */
131 offset_int refoff;
133 /* The offset range relative to the base. */
134 offset_int offrange[2];
135 /* The size range of the access to this reference. */
136 offset_int sizrange[2];
138 /* Cached result of get_max_objsize(). */
139 const offset_int maxobjsize;
141 /* True for "bounded" string functions like strncat, and strncpy
142 and their variants that specify either an exact or upper bound
143 on the size of the accesses they perform. For strncat both
144 the source and destination references are bounded. For strncpy
145 only the destination reference is. */
146 bool strbounded_p;
148 builtin_memref (range_query *, gimple *, tree, tree);
150 tree offset_out_of_bounds (int, offset_int[3]) const;
152 private:
153 /* Call statement to the built-in. */
154 gimple *stmt;
156 range_query *query;
158 /* Ctor helper to set or extend OFFRANGE based on argument. */
159 void extend_offset_range (tree);
161 /* Ctor helper to determine BASE and OFFRANGE from argument. */
162 void set_base_and_offset (tree);
165 /* Description of a memory access by a raw memory or string built-in
166 function involving a pair of builtin_memref's. */
167 class builtin_access
169 public:
170 /* Destination and source memory reference. */
171 builtin_memref* const dstref;
172 builtin_memref* const srcref;
173 /* The size range of the access. It's the greater of the accesses
174 to the two references. */
175 HOST_WIDE_INT sizrange[2];
177 /* The minimum and maximum offset of an overlap of the access
178 (if it does, in fact, overlap), and the size of the overlap. */
179 HOST_WIDE_INT ovloff[2];
180 HOST_WIDE_INT ovlsiz[2];
182 /* True to consider valid only accesses to the smallest subobject
183 and false for raw memory functions. */
184 bool strict () const
186 return (detect_overlap != &builtin_access::generic_overlap
187 && detect_overlap != &builtin_access::no_overlap);
190 builtin_access (range_query *, gimple *, builtin_memref &, builtin_memref &);
192 /* Entry point to determine overlap. */
193 bool overlap ();
195 offset_int write_off (tree) const;
197 void dump (FILE *) const;
199 private:
200 /* Implementation functions used to determine overlap. */
201 bool generic_overlap ();
202 bool strcat_overlap ();
203 bool strcpy_overlap ();
205 bool no_overlap ()
207 return false;
210 offset_int overlap_size (const offset_int [2], const offset_int[2],
211 offset_int [2]);
213 private:
214 /* Temporaries used to compute the final result. */
215 offset_int dstoff[2];
216 offset_int srcoff[2];
217 offset_int dstsiz[2];
218 offset_int srcsiz[2];
220 /* Pointer to a member function to call to determine overlap. */
221 bool (builtin_access::*detect_overlap) ();
224 /* Initialize a memory reference representation from a pointer EXPR and
225 a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed
226 to be unknown. STMT is the statement in which expr appears in. */
228 builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr,
229 tree size)
230 : ptr (expr),
231 ref (),
232 base (),
233 basesize (-1),
234 refsize (-1),
235 refoff (HOST_WIDE_INT_MIN),
236 offrange (),
237 sizrange (),
238 maxobjsize (tree_to_shwi (max_object_size ())),
239 strbounded_p (),
240 stmt (stmt),
241 query (query)
243 /* Unfortunately, wide_int default ctor is a no-op so array members
244 of the type must be set individually. */
245 offrange[0] = offrange[1] = 0;
246 sizrange[0] = sizrange[1] = 0;
248 if (!expr)
249 return;
251 /* Find the BASE object or pointer referenced by EXPR and set
252 the offset range OFFRANGE in the process. */
253 set_base_and_offset (expr);
255 if (size)
257 tree range[2];
258 /* Determine the size range, allowing for the result to be [0, 0]
259 for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */
260 get_size_range (query, size, stmt, range, SR_ALLOW_ZERO);
261 sizrange[0] = wi::to_offset (range[0]);
262 sizrange[1] = wi::to_offset (range[1]);
263 /* get_size_range returns SIZE_MAX for the maximum size.
264 Constrain it to the real maximum of PTRDIFF_MAX. */
265 if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize)
266 sizrange[1] = maxobjsize;
268 else
269 sizrange[1] = maxobjsize;
271 if (!DECL_P (base))
272 return;
274 /* If the offset could be in the range of the referenced object
275 constrain its bounds so neither exceeds those of the object. */
276 if (offrange[0] < 0 && offrange[1] > 0)
277 offrange[0] = 0;
279 offset_int maxoff = maxobjsize;
280 tree basetype = TREE_TYPE (base);
281 if (TREE_CODE (basetype) == ARRAY_TYPE)
283 if (ref && array_at_struct_end_p (ref))
284 ; /* Use the maximum possible offset for last member arrays. */
285 else if (tree basesize = TYPE_SIZE_UNIT (basetype))
286 if (TREE_CODE (basesize) == INTEGER_CST)
287 /* Size could be non-constant for a variable-length type such
288 as a struct with a VLA member (a GCC extension). */
289 maxoff = wi::to_offset (basesize);
292 if (offrange[0] >= 0)
294 if (offrange[1] < 0)
295 offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
296 else if (offrange[0] <= maxoff && offrange[1] > maxoff)
297 offrange[1] = maxoff;
301 /* Based on the initial length of the destination STARTLEN, returns
302 the offset of the first write access from the beginning of
303 the destination. Nonzero only for strcat-type of calls. */
305 offset_int builtin_access::write_off (tree startlen) const
307 if (detect_overlap != &builtin_access::strcat_overlap
308 || !startlen || TREE_CODE (startlen) != INTEGER_CST)
309 return 0;
311 return wi::to_offset (startlen);
314 /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
315 Pointer offsets are represented as unsigned sizetype but must be
316 treated as signed. */
318 void
319 builtin_memref::extend_offset_range (tree offset)
321 if (TREE_CODE (offset) == INTEGER_CST)
323 offset_int off = int_cst_value (offset);
324 if (off != 0)
326 offrange[0] += off;
327 offrange[1] += off;
329 return;
332 if (TREE_CODE (offset) == SSA_NAME)
334 /* A pointer offset is represented as sizetype but treated
335 as signed. */
336 wide_int min, max;
337 value_range_kind rng;
338 value_range vr;
339 if (query && query->range_of_expr (vr, offset, stmt))
341 rng = vr.kind ();
342 if (!vr.undefined_p ())
344 min = wi::to_wide (vr.min ());
345 max = wi::to_wide (vr.max ());
348 else
350 /* There is a global version here because
351 check_bounds_or_overlap may be called from gimple
352 fold during gimple lowering. */
353 get_range_query (cfun)->range_of_expr (vr, offset, stmt);
354 rng = vr.kind ();
355 if (!vr.undefined_p ())
357 min = wi::to_wide (vr.min ());
358 max = wi::to_wide (vr.max ());
361 if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
363 /* Convert an anti-range whose upper bound is less than
364 its lower bound to a signed range. */
365 offrange[0] += offset_int::from (max + 1, SIGNED);
366 offrange[1] += offset_int::from (min - 1, SIGNED);
367 return;
370 if (rng == VR_RANGE
371 && (DECL_P (base) || wi::lts_p (min, max)))
373 /* Preserve the bounds of the range for an offset into
374 a known object (it may be adjusted later relative to
375 a constant offset from its beginning). Otherwise use
376 the bounds only when they are ascending when treated
377 as signed. */
378 offrange[0] += offset_int::from (min, SIGNED);
379 offrange[1] += offset_int::from (max, SIGNED);
380 return;
383 /* Handle an anti-range the same as no range at all. */
384 gimple *stmt = SSA_NAME_DEF_STMT (offset);
385 tree type;
386 if (is_gimple_assign (stmt)
387 && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
388 && INTEGRAL_TYPE_P (type))
390 tree_code code = gimple_assign_rhs_code (stmt);
391 if (code == NOP_EXPR)
393 /* Use the bounds of the type of the NOP_EXPR operand
394 even if it's signed. The result doesn't trigger
395 warnings but makes their output more readable. */
396 offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
397 offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
398 return;
403 const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
404 const offset_int minoff = -maxoff - 1;
406 offrange[0] += minoff;
407 offrange[1] += maxoff;
410 /* Determines the base object or pointer of the reference EXPR
411 and the offset range from the beginning of the base. */
413 void
414 builtin_memref::set_base_and_offset (tree expr)
416 tree offset = NULL_TREE;
418 if (TREE_CODE (expr) == SSA_NAME)
420 /* Try to tease the offset out of the pointer. */
421 gimple *stmt = SSA_NAME_DEF_STMT (expr);
422 if (!base
423 && gimple_assign_single_p (stmt)
424 && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
425 expr = gimple_assign_rhs1 (stmt);
426 else if (is_gimple_assign (stmt))
428 tree_code code = gimple_assign_rhs_code (stmt);
429 if (code == NOP_EXPR)
431 tree rhs = gimple_assign_rhs1 (stmt);
432 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
433 expr = gimple_assign_rhs1 (stmt);
434 else
436 base = expr;
437 return;
440 else if (code == POINTER_PLUS_EXPR)
442 expr = gimple_assign_rhs1 (stmt);
443 offset = gimple_assign_rhs2 (stmt);
445 else
447 base = expr;
448 return;
451 else
453 /* FIXME: Handle PHI nodes in case like:
454 _12 = &MEM[(void *)&a + 2B] + _10;
456 <bb> [local count: 1073741824]:
457 # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
458 memcpy (prephitmp_13, p_7(D), 6); */
459 base = expr;
460 return;
464 if (TREE_CODE (expr) == ADDR_EXPR)
465 expr = TREE_OPERAND (expr, 0);
467 /* Stash the reference for offset validation. */
468 ref = expr;
470 poly_int64 bitsize, bitpos;
471 tree var_off;
472 machine_mode mode;
473 int sign, reverse, vol;
475 /* Determine the base object or pointer of the reference and
476 the constant bit offset from the beginning of the base.
477 If the offset has a non-constant component, it will be in
478 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
479 unused here. */
480 base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
481 &mode, &sign, &reverse, &vol);
483 /* get_inner_reference is not expected to return null. */
484 gcc_assert (base != NULL);
486 if (offset)
487 extend_offset_range (offset);
489 poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
491 /* Convert the poly_int64 offset to offset_int. The offset
492 should be constant but be prepared for it not to be just in
493 case. */
494 offset_int cstoff;
495 if (bytepos.is_constant (&cstoff))
497 offrange[0] += cstoff;
498 offrange[1] += cstoff;
500 /* Besides the reference saved above, also stash the offset
501 for validation. */
502 if (TREE_CODE (expr) == COMPONENT_REF)
503 refoff = cstoff;
505 else
506 offrange[1] += maxobjsize;
508 if (var_off)
510 if (TREE_CODE (var_off) == INTEGER_CST)
512 cstoff = wi::to_offset (var_off);
513 offrange[0] += cstoff;
514 offrange[1] += cstoff;
516 else
517 offrange[1] += maxobjsize;
520 if (TREE_CODE (base) == MEM_REF)
522 tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
523 extend_offset_range (memrefoff);
524 base = TREE_OPERAND (base, 0);
526 if (refoff != HOST_WIDE_INT_MIN
527 && TREE_CODE (expr) == COMPONENT_REF)
529 /* Bump up the offset of the referenced subobject to reflect
530 the offset to the enclosing object. For example, so that
532 struct S { char a, b[3]; } s[2];
533 strcpy (s[1].b, "1234");
534 REFOFF is set to s[1].b - (char*)s. */
535 offset_int off = tree_to_shwi (memrefoff);
536 refoff += off;
539 if (!integer_zerop (memrefoff))
540 /* A non-zero offset into an array of struct with flexible array
541 members implies that the array is empty because there is no
542 way to initialize such a member when it belongs to an array.
543 This must be some sort of a bug. */
544 refsize = 0;
547 if (TREE_CODE (ref) == COMPONENT_REF)
548 if (tree size = component_ref_size (ref))
549 if (TREE_CODE (size) == INTEGER_CST)
550 refsize = wi::to_offset (size);
552 if (TREE_CODE (base) == SSA_NAME)
553 set_base_and_offset (base);
556 /* Return error_mark_node if the signed offset exceeds the bounds
557 of the address space (PTRDIFF_MAX). Otherwise, return either BASE
558 or REF when the offset exceeds the bounds of the BASE or REF object,
559 and set OOBOFF to the past-the-end offset formed by the reference,
560 including its size. OOBOFF is initially setto the range of offsets,
561 and OOBOFF[2] to the offset of the first write access (nonzero for
562 the strcat family). When STRICT is nonzero use REF size, when
563 available, otherwise use BASE size. When STRICT is greater than 1,
564 use the size of the last array member as the bound, otherwise treat
565 such a member as a flexible array member. Return NULL when the offset
566 is in bounds. */
568 tree
569 builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
571 if (!ptr)
572 return NULL_TREE;
574 /* The offset of the first write access or zero. */
575 offset_int wroff = ooboff[2];
577 /* A temporary, possibly adjusted, copy of the offset range. */
578 offset_int offrng[2] = { ooboff[0], ooboff[1] };
580 if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
582 /* Check for offset in an anti-range with a negative lower bound.
583 For such a range, consider only the non-negative subrange. */
584 if (offrng[1] < offrng[0] && offrng[1] < 0)
585 offrng[1] = maxobjsize;
588 /* Conservative offset of the last byte of the referenced object. */
589 offset_int endoff;
591 /* The bounds need not be ordered. Set HIB to use as the index
592 of the larger of the bounds and LOB as the opposite. */
593 bool hib = wi::les_p (offrng[0], offrng[1]);
594 bool lob = !hib;
596 /* Set to the size remaining in the object after subtracting
597 REFOFF. It may become negative as a result of negative indices
598 into the enclosing object, such as in:
599 extern struct S { char a[4], b[3], c[1]; } *p;
600 strcpy (p[-3].b, "123"); */
601 offset_int size = basesize;
602 tree obj = base;
604 const bool decl_p = DECL_P (obj);
606 if (basesize < 0)
608 endoff = offrng[lob] + (sizrange[0] - wroff);
610 /* For a reference through a pointer to an object of unknown size
611 all initial offsets are considered valid, positive as well as
612 negative, since the pointer itself can point past the beginning
613 of the object. However, the sum of the lower bound of the offset
614 and that of the size must be less than or equal than PTRDIFF_MAX. */
615 if (endoff > maxobjsize)
616 return error_mark_node;
618 /* When the referenced subobject is known, the end offset must be
619 within its bounds. Otherwise there is nothing to do. */
620 if (strict
621 && !decl_p
622 && ref
623 && refsize >= 0
624 && TREE_CODE (ref) == COMPONENT_REF)
626 /* If REFOFF is negative, SIZE will become negative here. */
627 size = refoff + refsize;
628 obj = ref;
630 else
631 return NULL_TREE;
634 /* A reference to an object of known size must be within the bounds
635 of either the base object or the subobject (see above for when
636 a subobject can be used). */
637 if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
638 return obj;
640 /* The extent of the reference must also be within the bounds of
641 the base object (if known) or the subobject or the maximum object
642 size otherwise. */
643 endoff = offrng[lob] + sizrange[0];
644 if (endoff > maxobjsize)
645 return error_mark_node;
647 if (strict
648 && decl_p
649 && ref
650 && refsize >= 0
651 && TREE_CODE (ref) == COMPONENT_REF)
653 /* If the reference is to a member subobject of a declared object,
654 the offset must be within the bounds of the subobject. */
655 size = refoff + refsize;
656 obj = ref;
659 if (endoff <= size)
660 return NULL_TREE;
662 /* Set the out-of-bounds offset range to be one greater than
663 that delimited by the reference including its size. */
664 ooboff[lob] = size;
666 if (endoff > ooboff[lob])
667 ooboff[hib] = endoff - 1;
668 else
669 ooboff[hib] = offrng[lob] + sizrange[1];
671 return obj;
674 /* Create an association between the memory references DST and SRC
675 for access by a call EXPR to a memory or string built-in funtion. */
677 builtin_access::builtin_access (range_query *query, gimple *call,
678 builtin_memref &dst,
679 builtin_memref &src)
680 : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
681 dstoff (), srcoff (), dstsiz (), srcsiz ()
683 dstoff[0] = dst.offrange[0];
684 dstoff[1] = dst.offrange[1];
686 /* Zero out since the offset_int ctors invoked above are no-op. */
687 srcoff[0] = srcoff[1] = 0;
688 dstsiz[0] = dstsiz[1] = 0;
689 srcsiz[0] = srcsiz[1] = 0;
691 /* Object Size Type to use to determine the size of the destination
692 and source objects. Overridden below for raw memory functions. */
693 int ostype = 1;
695 /* True when the size of one reference depends on the offset of
696 itself or the other. */
697 bool depends_p = true;
699 /* True when the size of the destination reference DSTREF has been
700 determined from SRCREF and so needs to be adjusted by the latter's
701 offset. Only meaningful for bounded string functions like strncpy. */
702 bool dstadjust_p = false;
704 /* The size argument number (depends on the built-in). */
705 unsigned sizeargno = 2;
707 tree func = gimple_call_fndecl (call);
708 switch (DECL_FUNCTION_CODE (func))
710 case BUILT_IN_MEMCPY:
711 case BUILT_IN_MEMCPY_CHK:
712 case BUILT_IN_MEMPCPY:
713 case BUILT_IN_MEMPCPY_CHK:
714 ostype = 0;
715 depends_p = false;
716 detect_overlap = &builtin_access::generic_overlap;
717 break;
719 case BUILT_IN_MEMMOVE:
720 case BUILT_IN_MEMMOVE_CHK:
721 /* For memmove there is never any overlap to check for. */
722 ostype = 0;
723 depends_p = false;
724 detect_overlap = &builtin_access::no_overlap;
725 break;
727 case BUILT_IN_MEMSET:
728 case BUILT_IN_MEMSET_CHK:
729 /* For memset there is never any overlap to check for. */
730 ostype = 0;
731 depends_p = false;
732 detect_overlap = &builtin_access::no_overlap;
733 break;
735 case BUILT_IN_STPNCPY:
736 case BUILT_IN_STPNCPY_CHK:
737 case BUILT_IN_STRNCPY:
738 case BUILT_IN_STRNCPY_CHK:
739 dstref->strbounded_p = true;
740 detect_overlap = &builtin_access::strcpy_overlap;
741 break;
743 case BUILT_IN_STPCPY:
744 case BUILT_IN_STPCPY_CHK:
745 case BUILT_IN_STRCPY:
746 case BUILT_IN_STRCPY_CHK:
747 detect_overlap = &builtin_access::strcpy_overlap;
748 break;
750 case BUILT_IN_STRCAT:
751 case BUILT_IN_STRCAT_CHK:
752 detect_overlap = &builtin_access::strcat_overlap;
753 break;
755 case BUILT_IN_STRNCAT:
756 case BUILT_IN_STRNCAT_CHK:
757 dstref->strbounded_p = true;
758 srcref->strbounded_p = true;
759 detect_overlap = &builtin_access::strcat_overlap;
760 break;
762 default:
763 /* Handle other string functions here whose access may need
764 to be validated for in-bounds offsets and non-overlapping
765 copies. */
766 return;
769 const offset_int maxobjsize = dst.maxobjsize;
771 /* Try to determine the size of the base object. compute_objsize
772 expects a pointer so create one if BASE is a non-pointer object. */
773 tree addr;
774 if (dst.basesize < 0)
776 addr = dst.base;
777 if (!POINTER_TYPE_P (TREE_TYPE (addr)))
778 addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr);
780 if (tree dstsize = compute_objsize (addr, ostype))
781 dst.basesize = wi::to_offset (dstsize);
782 else if (POINTER_TYPE_P (TREE_TYPE (addr)))
783 dst.basesize = HOST_WIDE_INT_MIN;
784 else
785 dst.basesize = maxobjsize;
788 if (src.base && src.basesize < 0)
790 addr = src.base;
791 if (!POINTER_TYPE_P (TREE_TYPE (addr)))
792 addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr);
794 if (tree srcsize = compute_objsize (addr, ostype))
795 src.basesize = wi::to_offset (srcsize);
796 else if (POINTER_TYPE_P (TREE_TYPE (addr)))
797 src.basesize = HOST_WIDE_INT_MIN;
798 else
799 src.basesize = maxobjsize;
802 /* Make adjustments for references to the same object by string
803 built-in functions to reflect the constraints imposed by
804 the function. */
806 /* For bounded string functions determine the range of the bound
807 on the access. For others, the range stays unbounded. */
808 offset_int bounds[2] = { maxobjsize, maxobjsize };
809 if (dstref->strbounded_p)
811 unsigned nargs = gimple_call_num_args (call);
812 if (nargs <= sizeargno)
813 return;
815 tree size = gimple_call_arg (call, sizeargno);
816 tree range[2];
817 if (get_size_range (query, size, call, range, true))
819 bounds[0] = wi::to_offset (range[0]);
820 bounds[1] = wi::to_offset (range[1]);
823 /* If both references' size ranges are indeterminate use the last
824 (size) argument from the function call as a substitute. This
825 may only be necessary for strncpy (but not for memcpy where
826 the size range would have been already determined this way). */
827 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
828 && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
830 dstref->sizrange[0] = bounds[0];
831 dstref->sizrange[1] = bounds[1];
835 bool dstsize_set = false;
836 /* The size range of one reference involving the same base object
837 can be determined from the size range of the other reference.
838 This makes it possible to compute accurate offsets for warnings
839 involving functions like strcpy where the length of just one of
840 the two arguments is known (determined by tree-ssa-strlen). */
841 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize)
843 /* When the destination size is unknown set it to the size of
844 the source. */
845 dstref->sizrange[0] = srcref->sizrange[0];
846 dstref->sizrange[1] = srcref->sizrange[1];
847 dstsize_set = true;
849 else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
851 /* When the size of the source access is unknown set it to the size
852 of the destination first and adjust it later if necessary. */
853 srcref->sizrange[0] = dstref->sizrange[0];
854 srcref->sizrange[1] = dstref->sizrange[1];
856 if (depends_p)
858 if (dstref->strbounded_p)
860 /* Read access by strncpy is constrained by the third
861 argument but except for a zero bound is at least one. */
862 srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
863 offset_int bound = wi::umin (srcref->basesize, bounds[1]);
864 if (bound < srcref->sizrange[1])
865 srcref->sizrange[1] = bound;
867 /* For string functions, adjust the size range of the source
868 reference by the inverse boundaries of the offset (because
869 the higher the offset into the string the shorter its
870 length). */
871 if (srcref->offrange[1] >= 0
872 && srcref->offrange[1] < srcref->sizrange[0])
873 srcref->sizrange[0] -= srcref->offrange[1];
874 else
875 srcref->sizrange[0] = 1;
877 if (srcref->offrange[0] > 0)
879 if (srcref->offrange[0] < srcref->sizrange[1])
880 srcref->sizrange[1] -= srcref->offrange[0];
881 else
882 srcref->sizrange[1] = 0;
885 dstadjust_p = true;
889 if (detect_overlap == &builtin_access::generic_overlap)
891 if (dstref->strbounded_p)
893 dstref->sizrange[0] = bounds[0];
894 dstref->sizrange[1] = bounds[1];
896 if (dstref->sizrange[0] < srcref->sizrange[0])
897 srcref->sizrange[0] = dstref->sizrange[0];
899 if (dstref->sizrange[1] < srcref->sizrange[1])
900 srcref->sizrange[1] = dstref->sizrange[1];
903 else if (detect_overlap == &builtin_access::strcpy_overlap)
905 if (!dstref->strbounded_p)
907 /* For strcpy, adjust the destination size range to match that
908 of the source computed above. */
909 if (depends_p && dstadjust_p)
911 dstref->sizrange[0] = srcref->sizrange[0];
912 dstref->sizrange[1] = srcref->sizrange[1];
916 else if (!dstsize_set && detect_overlap == &builtin_access::strcat_overlap)
918 dstref->sizrange[0] += srcref->sizrange[0] - 1;
919 dstref->sizrange[1] += srcref->sizrange[1] - 1;
922 if (dstref->strbounded_p)
924 /* For strncpy, adjust the destination size range to match that
925 of the source computed above. */
926 dstref->sizrange[0] = bounds[0];
927 dstref->sizrange[1] = bounds[1];
929 if (bounds[0] < srcref->sizrange[0])
930 srcref->sizrange[0] = bounds[0];
932 if (bounds[1] < srcref->sizrange[1])
933 srcref->sizrange[1] = bounds[1];
937 offset_int
938 builtin_access::overlap_size (const offset_int a[2], const offset_int b[2],
939 offset_int *off)
941 const offset_int *p = a;
942 const offset_int *q = b;
944 /* Point P at the bigger of the two ranges and Q at the smaller. */
945 if (wi::lts_p (a[1] - a[0], b[1] - b[0]))
947 p = b;
948 q = a;
951 if (p[0] < q[0])
953 if (p[1] < q[0])
954 return 0;
956 *off = q[0];
957 return wi::smin (p[1], q[1]) - q[0];
960 if (q[1] < p[0])
961 return 0;
963 off[0] = p[0];
964 return q[1] - p[0];
967 /* Return true if the bounded mempry (memcpy amd similar) or string function
968 access (strncpy and similar) ACS overlaps. */
970 bool
971 builtin_access::generic_overlap ()
973 builtin_access &acs = *this;
974 const builtin_memref *dstref = acs.dstref;
975 const builtin_memref *srcref = acs.srcref;
977 gcc_assert (dstref->base == srcref->base);
979 const offset_int maxobjsize = acs.dstref->maxobjsize;
981 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
983 /* Adjust the larger bounds of the offsets (which may be the first
984 element if the lower bound is larger than the upper bound) to
985 make them valid for the smallest access (if possible) but no smaller
986 than the smaller bounds. */
987 gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));
989 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
990 acs.dstoff[1] = maxsize - acs.dstsiz[0];
991 if (acs.dstoff[1] < acs.dstoff[0])
992 acs.dstoff[1] = acs.dstoff[0];
994 gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1]));
996 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
997 acs.srcoff[1] = maxsize - acs.srcsiz[0];
998 if (acs.srcoff[1] < acs.srcoff[0])
999 acs.srcoff[1] = acs.srcoff[0];
1001 /* Determine the minimum and maximum space for the access given
1002 the offsets. */
1003 offset_int space[2];
1004 space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1005 space[1] = space[0];
1007 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1008 if (acs.srcsiz[0] > 0)
1010 if (d < space[0])
1011 space[0] = d;
1013 if (space[1] < d)
1014 space[1] = d;
1016 else
1017 space[1] = acs.dstsiz[1];
1019 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1020 if (d < space[0])
1021 space[0] = d;
1023 if (space[1] < d)
1024 space[1] = d;
1026 /* Treat raw memory functions both of whose references are bounded
1027 as special and permit uncertain overlaps to go undetected. For
1028 all kinds of constant offset and constant size accesses, if
1029 overlap isn't certain it is not possible. */
1030 bool overlap_possible = space[0] < acs.dstsiz[1];
1031 if (!overlap_possible)
1032 return false;
1034 bool overlap_certain = space[1] < acs.dstsiz[0];
1036 /* True when the size of one reference depends on the offset of
1037 the other. */
1038 bool depends_p = detect_overlap != &builtin_access::generic_overlap;
1040 if (!overlap_certain)
1042 if (!dstref->strbounded_p && !depends_p)
1043 /* Memcpy only considers certain overlap. */
1044 return false;
1046 /* There's no way to distinguish an access to the same member
1047 of a structure from one to two distinct members of the same
1048 structure. Give up to avoid excessive false positives. */
1049 tree basetype = TREE_TYPE (dstref->base);
1051 if (POINTER_TYPE_P (basetype))
1052 basetype = TREE_TYPE (basetype);
1053 else
1054 while (TREE_CODE (basetype) == ARRAY_TYPE)
1055 basetype = TREE_TYPE (basetype);
1057 if (RECORD_OR_UNION_TYPE_P (basetype))
1058 return false;
1061 /* True for stpcpy and strcpy. */
1062 bool stxcpy_p = (!dstref->strbounded_p
1063 && detect_overlap == &builtin_access::strcpy_overlap);
1065 if (dstref->refoff >= 0
1066 && srcref->refoff >= 0
1067 && dstref->refoff != srcref->refoff
1068 && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p))
1069 return false;
1071 offset_int siz[2] = { maxobjsize + 1, 0 };
1073 ovloff[0] = HOST_WIDE_INT_MAX;
1074 ovloff[1] = HOST_WIDE_INT_MIN;
1076 if (stxcpy_p)
1078 /* Iterate over the extreme locations (on the horizontal axis formed
1079 by their offsets) and sizes of two regions and find their smallest
1080 and largest overlap and the corresponding offsets. */
1081 for (unsigned i = 0; i != 2; ++i)
1083 const offset_int a[2] = {
1084 acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i]
1087 const offset_int b[2] = {
1088 acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i]
1091 offset_int off;
1092 offset_int sz = overlap_size (a, b, &off);
1093 if (sz < siz[0])
1094 siz[0] = sz;
1096 if (siz[1] <= sz)
1097 siz[1] = sz;
1099 if (sz != 0)
1101 if (wi::lts_p (off, ovloff[0]))
1102 ovloff[0] = off.to_shwi ();
1103 if (wi::lts_p (ovloff[1], off))
1104 ovloff[1] = off.to_shwi ();
1108 else
1110 /* Iterate over the extreme locations (on the horizontal axis
1111 formed by their offsets) and sizes of the two regions and
1112 find their smallest and largest overlap and the corresponding
1113 offsets. */
1115 for (unsigned io = 0; io != 2; ++io)
1116 for (unsigned is = 0; is != 2; ++is)
1118 const offset_int a[2] = {
1119 acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is]
1122 for (unsigned jo = 0; jo != 2; ++jo)
1123 for (unsigned js = 0; js != 2; ++js)
1125 const offset_int b[2] = {
1126 acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
1129 offset_int off;
1130 offset_int sz = overlap_size (a, b, &off);
1131 if (sz < siz[0])
1132 siz[0] = sz;
1134 if (siz[1] <= sz)
1135 siz[1] = sz;
1137 if (sz != 0)
1139 if (wi::lts_p (off, ovloff[0]))
1140 ovloff[0] = off.to_shwi ();
1141 if (wi::lts_p (ovloff[1], off))
1142 ovloff[1] = off.to_shwi ();
1148 ovlsiz[0] = siz[0].to_shwi ();
1149 ovlsiz[1] = siz[1].to_shwi ();
1151 /* Adjust the overlap offset range to reflect the overlap size range. */
1152 if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
1153 ovloff[1] = ovloff[0] + ovlsiz[1] - 1;
1155 return true;
1158 /* Return true if the strcat-like access overlaps. */
1160 bool
1161 builtin_access::strcat_overlap ()
1163 builtin_access &acs = *this;
1164 const builtin_memref *dstref = acs.dstref;
1165 const builtin_memref *srcref = acs.srcref;
1167 gcc_assert (dstref->base == srcref->base);
1169 const offset_int maxobjsize = acs.dstref->maxobjsize;
1171 gcc_assert (dstref->base && dstref->base == srcref->base);
1173 /* Adjust for strcat-like accesses. */
1175 /* As a special case for strcat, set the DSTREF offsets to the length
1176 of the destination string since the function starts writing over
1177 its terminating nul, and set the destination size to 1 for the length
1178 of the nul. */
1179 acs.dstoff[0] += dstsiz[0] - srcref->sizrange[0];
1180 acs.dstoff[1] += dstsiz[1] - srcref->sizrange[1];
1182 bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0;
1184 /* The lower bound is zero when the size is unknown because then
1185 overlap is not certain. */
1186 acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1;
1187 acs.dstsiz[1] = 1;
1189 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
1191 /* For references to the same base object, determine if there's a pair
1192 of valid offsets into the two references such that access between
1193 them doesn't overlap. Adjust both upper bounds to be valid for
1194 the smaller size (i.e., at most MAXSIZE - SIZE). */
1196 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
1197 acs.dstoff[1] = maxsize - acs.dstsiz[0];
1199 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
1200 acs.srcoff[1] = maxsize - acs.srcsiz[0];
1202 /* Check to see if there's enough space for both accesses without
1203 overlap. Determine the optimistic (maximum) amount of available
1204 space. */
1205 offset_int space;
1206 if (acs.dstoff[0] <= acs.srcoff[0])
1208 if (acs.dstoff[1] < acs.srcoff[1])
1209 space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0];
1210 else
1211 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1213 else
1214 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1216 /* Overlap is certain if the distance between the farthest offsets
1217 of the opposite accesses is less than the sum of the lower bounds
1218 of the sizes of the two accesses. */
1219 bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0];
1221 /* For a constant-offset, constant size access, consider the largest
1222 distance between the offset bounds and the lower bound of the access
1223 size. If the overlap isn't certain return success. */
1224 if (!overlap_certain
1225 && acs.dstoff[0] == acs.dstoff[1]
1226 && acs.srcoff[0] == acs.srcoff[1]
1227 && acs.dstsiz[0] == acs.dstsiz[1]
1228 && acs.srcsiz[0] == acs.srcsiz[1])
1229 return false;
1231 /* Overlap is not certain but may be possible. */
1233 offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0];
1235 /* Determine the conservative (minimum) amount of space. */
1236 space = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1237 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1238 if (d < space)
1239 space = d;
1240 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1241 if (d < space)
1242 space = d;
1244 /* For a strict test (used for strcpy and similar with unknown or
1245 variable bounds or sizes), consider the smallest distance between
1246 the offset bounds and either the upper bound of the access size
1247 if known, or the lower bound otherwise. */
1248 if (access_min <= space && (access_min != 0 || !strfunc_unknown_args))
1249 return false;
1251 /* When strcat overlap is certain it is always a single byte:
1252 the terminating NUL, regardless of offsets and sizes. When
1253 overlap is only possible its range is [0, 1]. */
1254 acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
1255 acs.ovlsiz[1] = 1;
1257 offset_int endoff
1258 = dstref->offrange[0] + (dstref->sizrange[0] - srcref->sizrange[0]);
1259 if (endoff <= srcref->offrange[0])
1260 acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi ();
1261 else
1262 acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi ();
1264 acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1,
1265 srcref->sizrange[0]).to_shwi ();
1266 if (dstref->offrange[0] == dstref->offrange[1])
1268 if (srcref->offrange[0] == srcref->offrange[1])
1269 acs.ovloff[1] = acs.ovloff[0];
1270 else
1271 acs.ovloff[1]
1272 = wi::smin (maxobjsize,
1273 srcref->offrange[1] + srcref->sizrange[1]).to_shwi ();
1275 else
1276 acs.ovloff[1]
1277 = wi::smin (maxobjsize,
1278 dstref->offrange[1] + dstref->sizrange[1]).to_shwi ();
1280 if (acs.sizrange[0] == 0)
1281 acs.sizrange[0] = 1;
1282 acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1283 return true;
1286 /* Return true if the strcpy-like access overlaps. */
1288 bool
1289 builtin_access::strcpy_overlap ()
1291 return generic_overlap ();
1294 /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
1295 if known, or [0, MAXOBJSIZE] otherwise. */
1297 static void
1298 clamp_offset (tree base, offset_int refoff[2], offset_int maxobjsize)
1300 if (!base || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
1301 return;
1303 if (refoff[0] < 0 && refoff[1] >= 0)
1304 refoff[0] = 0;
1306 if (refoff[1] < refoff[0])
1308 offset_int maxsize = maxobjsize;
1309 if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (base)))
1310 maxsize = wi::to_offset (size);
1312 refoff[1] = wi::umin (refoff[1], maxsize);
1316 /* Return true if DSTREF and SRCREF describe accesses that either overlap
1317 one another or that, in order not to overlap, would imply that the size
1318 of the referenced object(s) exceeds the maximum size of an object. Set
1319 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1320 they may overlap in a way that's not apparent from the available data),
1321 return false. */
1323 bool
1324 builtin_access::overlap ()
1326 builtin_access &acs = *this;
1328 const offset_int maxobjsize = dstref->maxobjsize;
1330 acs.sizrange[0] = wi::smax (dstref->sizrange[0],
1331 srcref->sizrange[0]).to_shwi ();
1332 acs.sizrange[1] = wi::smax (dstref->sizrange[1],
1333 srcref->sizrange[1]).to_shwi ();
1335 /* Check to see if the two references refer to regions that are
1336 too large not to overlap in the address space (whose maximum
1337 size is PTRDIFF_MAX). */
1338 offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
1339 if (maxobjsize < size)
1341 acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi ();
1342 acs.ovlsiz[0] = (size - maxobjsize).to_shwi ();
1343 return true;
1346 /* If both base objects aren't known return the maximum possible
1347 offset that would make them not overlap. */
1348 if (!dstref->base || !srcref->base)
1349 return false;
1351 /* If the base object is an array adjust the bounds of the offset
1352 to be non-negative and within the bounds of the array if possible. */
1353 clamp_offset (dstref->base, acs.dstoff, maxobjsize);
1355 acs.srcoff[0] = srcref->offrange[0];
1356 acs.srcoff[1] = srcref->offrange[1];
1358 clamp_offset (srcref->base, acs.srcoff, maxobjsize);
1360 /* When the upper bound of the offset is less than the lower bound
1361 the former is the result of a negative offset being represented
1362 as a large positive value or vice versa. The resulting range is
1363 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1364 a union is not representable using the current data structure
1365 replace it with the full range of offsets. */
1366 if (acs.dstoff[1] < acs.dstoff[0])
1368 acs.dstoff[0] = -maxobjsize - 1;
1369 acs.dstoff[1] = maxobjsize;
1372 /* Validate the offset and size of each reference on its own first.
1373 This is independent of whether or not the base objects are the
1374 same. Normally, this would have already been detected and
1375 diagnosed by -Warray-bounds, unless it has been disabled. */
1376 offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
1377 if (maxobjsize < maxoff)
1379 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1380 acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0];
1381 return true;
1384 /* Repeat the same as above but for the source offsets. */
1385 if (acs.srcoff[1] < acs.srcoff[0])
1387 acs.srcoff[0] = -maxobjsize - 1;
1388 acs.srcoff[1] = maxobjsize;
1391 maxoff = acs.srcoff[0] + srcref->sizrange[0];
1392 if (maxobjsize < maxoff)
1394 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1395 acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1]
1396 - maxobjsize).to_shwi ();
1397 acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0];
1398 return true;
1401 if (dstref->base != srcref->base)
1402 return false;
1404 acs.dstsiz[0] = dstref->sizrange[0];
1405 acs.dstsiz[1] = dstref->sizrange[1];
1407 acs.srcsiz[0] = srcref->sizrange[0];
1408 acs.srcsiz[1] = srcref->sizrange[1];
1410 /* Call the appropriate function to determine the overlap. */
1411 if ((this->*detect_overlap) ())
1413 if (!sizrange[1])
1415 /* Unless the access size range has already been set, do so here. */
1416 sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi ();
1417 sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1419 return true;
1422 return false;
1425 /* Attempt to detect and diagnose an overlapping copy in a call expression
1426 EXPR involving an access ACS to a built-in memory or string function.
1427 Return true when one has been detected, false otherwise. */
1429 static bool
1430 maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
1432 if (!acs.overlap ())
1433 return false;
1435 if (warning_suppressed_p (call, OPT_Wrestrict))
1436 return true;
1438 /* For convenience. */
1439 const builtin_memref &dstref = *acs.dstref;
1440 const builtin_memref &srcref = *acs.srcref;
1442 /* Determine the range of offsets and sizes of the overlap if it
1443 exists and issue diagnostics. */
1444 HOST_WIDE_INT *ovloff = acs.ovloff;
1445 HOST_WIDE_INT *ovlsiz = acs.ovlsiz;
1446 HOST_WIDE_INT *sizrange = acs.sizrange;
1448 tree func = gimple_call_fndecl (call);
1450 /* To avoid a combinatorial explosion of diagnostics format the offsets
1451 or their ranges as strings and use them in the warning calls below. */
1452 char offstr[3][64];
1454 if (dstref.offrange[0] == dstref.offrange[1]
1455 || dstref.offrange[1] > HOST_WIDE_INT_MAX)
1456 sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC,
1457 dstref.offrange[0].to_shwi ());
1458 else
1459 sprintf (offstr[0],
1460 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1461 dstref.offrange[0].to_shwi (),
1462 dstref.offrange[1].to_shwi ());
1464 if (srcref.offrange[0] == srcref.offrange[1]
1465 || srcref.offrange[1] > HOST_WIDE_INT_MAX)
1466 sprintf (offstr[1],
1467 HOST_WIDE_INT_PRINT_DEC,
1468 srcref.offrange[0].to_shwi ());
1469 else
1470 sprintf (offstr[1],
1471 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1472 srcref.offrange[0].to_shwi (),
1473 srcref.offrange[1].to_shwi ());
1475 if (ovloff[0] == ovloff[1] || !ovloff[1])
1476 sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]);
1477 else
1478 sprintf (offstr[2],
1479 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1480 ovloff[0], ovloff[1]);
1482 const offset_int maxobjsize = dstref.maxobjsize;
1483 bool must_overlap = ovlsiz[0] > 0;
1485 if (ovlsiz[1] == 0)
1486 ovlsiz[1] = ovlsiz[0];
1488 if (must_overlap)
1490 /* Issue definitive "overlaps" diagnostic in this block. */
1492 if (sizrange[0] == sizrange[1])
1494 if (ovlsiz[0] == ovlsiz[1])
1495 warning_at (loc, OPT_Wrestrict,
1496 sizrange[0] == 1
1497 ? (ovlsiz[0] == 1
1498 ? G_("%qD accessing %wu byte at offsets %s "
1499 "and %s overlaps %wu byte at offset %s")
1500 : G_("%qD accessing %wu byte at offsets %s "
1501 "and %s overlaps %wu bytes at offset "
1502 "%s"))
1503 : (ovlsiz[0] == 1
1504 ? G_("%qD accessing %wu bytes at offsets %s "
1505 "and %s overlaps %wu byte at offset %s")
1506 : G_("%qD accessing %wu bytes at offsets %s "
1507 "and %s overlaps %wu bytes at offset "
1508 "%s")),
1509 func, sizrange[0],
1510 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1511 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1512 warning_n (loc, OPT_Wrestrict, sizrange[0],
1513 "%qD accessing %wu byte at offsets %s "
1514 "and %s overlaps between %wu and %wu bytes "
1515 "at offset %s",
1516 "%qD accessing %wu bytes at offsets %s "
1517 "and %s overlaps between %wu and %wu bytes "
1518 "at offset %s",
1519 func, sizrange[0], offstr[0], offstr[1],
1520 ovlsiz[0], ovlsiz[1], offstr[2]);
1521 else
1522 warning_n (loc, OPT_Wrestrict, sizrange[0],
1523 "%qD accessing %wu byte at offsets %s and "
1524 "%s overlaps %wu or more bytes at offset %s",
1525 "%qD accessing %wu bytes at offsets %s and "
1526 "%s overlaps %wu or more bytes at offset %s",
1527 func, sizrange[0],
1528 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1529 return true;
1532 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1534 if (ovlsiz[0] == ovlsiz[1])
1535 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
1536 "%qD accessing between %wu and %wu bytes "
1537 "at offsets %s and %s overlaps %wu byte at "
1538 "offset %s",
1539 "%qD accessing between %wu and %wu bytes "
1540 "at offsets %s and %s overlaps %wu bytes "
1541 "at offset %s",
1542 func, sizrange[0], sizrange[1],
1543 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1544 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1545 warning_at (loc, OPT_Wrestrict,
1546 "%qD accessing between %wu and %wu bytes at "
1547 "offsets %s and %s overlaps between %wu and %wu "
1548 "bytes at offset %s",
1549 func, sizrange[0], sizrange[1],
1550 offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
1551 offstr[2]);
1552 else
1553 warning_at (loc, OPT_Wrestrict,
1554 "%qD accessing between %wu and %wu bytes at "
1555 "offsets %s and %s overlaps %wu or more bytes "
1556 "at offset %s",
1557 func, sizrange[0], sizrange[1],
1558 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1559 return true;
1562 if (ovlsiz[0] != ovlsiz[1])
1563 ovlsiz[1] = maxobjsize.to_shwi ();
1565 if (ovlsiz[0] == ovlsiz[1])
1566 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
1567 "%qD accessing %wu or more bytes at offsets "
1568 "%s and %s overlaps %wu byte at offset %s",
1569 "%qD accessing %wu or more bytes at offsets "
1570 "%s and %s overlaps %wu bytes at offset %s",
1571 func, sizrange[0], offstr[0], offstr[1],
1572 ovlsiz[0], offstr[2]);
1573 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1574 warning_at (loc, OPT_Wrestrict,
1575 "%qD accessing %wu or more bytes at offsets %s "
1576 "and %s overlaps between %wu and %wu bytes "
1577 "at offset %s",
1578 func, sizrange[0], offstr[0], offstr[1],
1579 ovlsiz[0], ovlsiz[1], offstr[2]);
1580 else
1581 warning_at (loc, OPT_Wrestrict,
1582 "%qD accessing %wu or more bytes at offsets %s "
1583 "and %s overlaps %wu or more bytes at offset %s",
1584 func, sizrange[0], offstr[0], offstr[1],
1585 ovlsiz[0], offstr[2]);
1586 return true;
1589 /* Use more concise wording when one of the offsets is unbounded
1590 to avoid confusing the user with large and mostly meaningless
1591 numbers. */
1592 bool open_range;
1593 if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
1594 open_range = ((dstref.offrange[0] == 0
1595 && dstref.offrange[1] == maxobjsize)
1596 || (srcref.offrange[0] == 0
1597 && srcref.offrange[1] == maxobjsize));
1598 else
1599 open_range = ((dstref.offrange[0] == -maxobjsize - 1
1600 && dstref.offrange[1] == maxobjsize)
1601 || (srcref.offrange[0] == -maxobjsize - 1
1602 && srcref.offrange[1] == maxobjsize));
1604 if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
1606 if (ovlsiz[1] == 1)
1608 if (open_range)
1609 warning_n (loc, OPT_Wrestrict, sizrange[1],
1610 "%qD accessing %wu byte may overlap "
1611 "%wu byte",
1612 "%qD accessing %wu bytes may overlap "
1613 "%wu byte",
1614 func, sizrange[1], ovlsiz[1]);
1615 else
1616 warning_n (loc, OPT_Wrestrict, sizrange[1],
1617 "%qD accessing %wu byte at offsets %s "
1618 "and %s may overlap %wu byte at offset %s",
1619 "%qD accessing %wu bytes at offsets %s "
1620 "and %s may overlap %wu byte at offset %s",
1621 func, sizrange[1], offstr[0], offstr[1],
1622 ovlsiz[1], offstr[2]);
1623 return true;
1626 if (open_range)
1627 warning_n (loc, OPT_Wrestrict, sizrange[1],
1628 "%qD accessing %wu byte may overlap "
1629 "up to %wu bytes",
1630 "%qD accessing %wu bytes may overlap "
1631 "up to %wu bytes",
1632 func, sizrange[1], ovlsiz[1]);
1633 else
1634 warning_n (loc, OPT_Wrestrict, sizrange[1],
1635 "%qD accessing %wu byte at offsets %s and "
1636 "%s may overlap up to %wu bytes at offset %s",
1637 "%qD accessing %wu bytes at offsets %s and "
1638 "%s may overlap up to %wu bytes at offset %s",
1639 func, sizrange[1], offstr[0], offstr[1],
1640 ovlsiz[1], offstr[2]);
1641 return true;
1644 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1646 if (open_range)
1647 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1648 "%qD accessing between %wu and %wu bytes "
1649 "may overlap %wu byte",
1650 "%qD accessing between %wu and %wu bytes "
1651 "may overlap up to %wu bytes",
1652 func, sizrange[0], sizrange[1], ovlsiz[1]);
1653 else
1654 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1655 "%qD accessing between %wu and %wu bytes "
1656 "at offsets %s and %s may overlap %wu byte "
1657 "at offset %s",
1658 "%qD accessing between %wu and %wu bytes "
1659 "at offsets %s and %s may overlap up to %wu "
1660 "bytes at offset %s",
1661 func, sizrange[0], sizrange[1],
1662 offstr[0], offstr[1], ovlsiz[1], offstr[2]);
1663 return true;
1666 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
1667 "%qD accessing %wu or more bytes at offsets %s "
1668 "and %s may overlap %wu byte at offset %s",
1669 "%qD accessing %wu or more bytes at offsets %s "
1670 "and %s may overlap up to %wu bytes at offset %s",
1671 func, sizrange[0], offstr[0], offstr[1],
1672 ovlsiz[1], offstr[2]);
1674 return true;
1677 /* Validate REF size and offsets in an expression passed as an argument
1678 to a CALL to a built-in function FUNC to make sure they are within
1679 the bounds of the referenced object if its size is known, or
1680 PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1681 be issued, false otherwise.
1682 Both initial values of the offsets and their final value computed
1683 by the function by incrementing the initial value by the size are
1684 validated. Return the warning number if the offsets are not valid
1685 and a diagnostic has been issued, or would have been issued if
1686 DO_WARN had been true, otherwise an invalid warning number. */
1688 static opt_code
1689 maybe_diag_access_bounds (gimple *call, tree func, int strict,
1690 const builtin_memref &ref, offset_int wroff,
1691 bool do_warn)
1693 location_t loc = gimple_location (call);
1694 const offset_int maxobjsize = ref.maxobjsize;
1696 /* Check for excessive size first and regardless of warning options
1697 since the result is used to make codegen decisions. */
1698 if (ref.sizrange[0] > maxobjsize)
1700 const opt_code opt = OPT_Wstringop_overflow_;
1701 /* Return true without issuing a warning. */
1702 if (!do_warn)
1703 return opt;
1705 if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
1706 return no_warning;
1708 bool warned = false;
1709 if (warn_stringop_overflow)
1711 if (ref.sizrange[0] == ref.sizrange[1])
1712 warned = warning_at (loc, opt,
1713 "%qD specified bound %wu "
1714 "exceeds maximum object size %wu",
1715 func, ref.sizrange[0].to_uhwi (),
1716 maxobjsize.to_uhwi ());
1717 else
1718 warned = warning_at (loc, opt,
1719 "%qD specified bound between %wu and %wu "
1720 "exceeds maximum object size %wu",
1721 func, ref.sizrange[0].to_uhwi (),
1722 ref.sizrange[1].to_uhwi (),
1723 maxobjsize.to_uhwi ());
1724 return warned ? opt : no_warning;
1728 /* Check for out-bounds pointers regardless of warning options since
1729 the result is used to make codegen decisions. An excessive WROFF
1730 can only come up as a result of an invalid strncat bound and is
1731 diagnosed separately using a more meaningful warning. */
1732 if (maxobjsize < wroff)
1733 wroff = 0;
1734 offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
1735 tree oobref = ref.offset_out_of_bounds (strict, ooboff);
1736 if (!oobref)
1737 return no_warning;
1739 const opt_code opt = OPT_Warray_bounds;
1740 /* Return true without issuing a warning. */
1741 if (!do_warn)
1742 return opt;
1744 if (!warn_array_bounds)
1745 return no_warning;
1747 if (warning_suppressed_p (ref.ptr, opt)
1748 || (ref.ref && warning_suppressed_p (ref.ref, opt)))
1749 return no_warning;
1751 char rangestr[2][64];
1752 if (ooboff[0] == ooboff[1]
1753 || (ooboff[0] != ref.offrange[0]
1754 && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
1755 sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ());
1756 else
1757 sprintf (rangestr[0], "[%lli, %lli]",
1758 (long long) ooboff[0].to_shwi (),
1759 (long long) ooboff[1].to_shwi ());
1761 bool warned = false;
1763 if (oobref == error_mark_node)
1765 if (ref.sizrange[0] == ref.sizrange[1])
1766 sprintf (rangestr[1], "%llu",
1767 (unsigned long long) ref.sizrange[0].to_shwi ());
1768 else
1769 sprintf (rangestr[1], "[%lli, %lli]",
1770 (unsigned long long) ref.sizrange[0].to_uhwi (),
1771 (unsigned long long) ref.sizrange[1].to_uhwi ());
1773 tree type;
1775 if (DECL_P (ref.base)
1776 && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
1778 auto_diagnostic_group d;
1779 if (warning_at (loc, opt,
1780 "%qD pointer overflow between offset %s "
1781 "and size %s accessing array %qD with type %qT",
1782 func, rangestr[0], rangestr[1], ref.base, type))
1784 inform (DECL_SOURCE_LOCATION (ref.base),
1785 "array %qD declared here", ref.base);
1786 warned = true;
1788 else
1789 warned = warning_at (loc, opt,
1790 "%qD pointer overflow between offset %s "
1791 "and size %s",
1792 func, rangestr[0], rangestr[1]);
1794 else
1795 warned = warning_at (loc, opt,
1796 "%qD pointer overflow between offset %s "
1797 "and size %s",
1798 func, rangestr[0], rangestr[1]);
1800 else if (oobref == ref.base)
1802 /* True when the offset formed by an access to the reference
1803 is out of bounds, rather than the initial offset wich is
1804 in bounds. This implies access past the end. */
1805 bool form = ooboff[0] != ref.offrange[0];
1807 if (DECL_P (ref.base))
1809 auto_diagnostic_group d;
1810 if ((ref.basesize < maxobjsize
1811 && warning_at (loc, opt,
1812 form
1813 ? G_("%qD forming offset %s is out of "
1814 "the bounds [0, %wu] of object %qD with "
1815 "type %qT")
1816 : G_("%qD offset %s is out of the bounds "
1817 "[0, %wu] of object %qD with type %qT"),
1818 func, rangestr[0], ref.basesize.to_uhwi (),
1819 ref.base, TREE_TYPE (ref.base)))
1820 || warning_at (loc, opt,
1821 form
1822 ? G_("%qD forming offset %s is out of "
1823 "the bounds of object %qD with type %qT")
1824 : G_("%qD offset %s is out of the bounds "
1825 "of object %qD with type %qT"),
1826 func, rangestr[0],
1827 ref.base, TREE_TYPE (ref.base)))
1829 inform (DECL_SOURCE_LOCATION (ref.base),
1830 "%qD declared here", ref.base);
1831 warned = true;
1834 else if (ref.basesize < maxobjsize)
1835 warned = warning_at (loc, opt,
1836 form
1837 ? G_("%qD forming offset %s is out "
1838 "of the bounds [0, %wu]")
1839 : G_("%qD offset %s is out "
1840 "of the bounds [0, %wu]"),
1841 func, rangestr[0], ref.basesize.to_uhwi ());
1842 else
1843 warned = warning_at (loc, opt,
1844 form
1845 ? G_("%qD forming offset %s is out of bounds")
1846 : G_("%qD offset %s is out of bounds"),
1847 func, rangestr[0]);
1849 else if (TREE_CODE (ref.ref) == MEM_REF)
1851 tree refop = TREE_OPERAND (ref.ref, 0);
1852 tree type = TREE_TYPE (refop);
1853 if (POINTER_TYPE_P (type))
1854 type = TREE_TYPE (type);
1855 type = TYPE_MAIN_VARIANT (type);
1857 if (warning_at (loc, opt,
1858 "%qD offset %s from the object at %qE is out "
1859 "of the bounds of %qT",
1860 func, rangestr[0], ref.base, type))
1862 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1863 refop = TREE_OPERAND (ref.ref, 1);
1864 if (DECL_P (refop))
1865 inform (DECL_SOURCE_LOCATION (refop),
1866 "subobject %qD declared here", refop);
1867 warned = true;
1870 else
1872 tree refop = TREE_OPERAND (ref.ref, 0);
1873 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
1875 if (warning_at (loc, opt,
1876 "%qD offset %s from the object at %qE is out "
1877 "of the bounds of referenced subobject %qD with "
1878 "type %qT at offset %wi",
1879 func, rangestr[0], ref.base,
1880 TREE_OPERAND (ref.ref, 1), type,
1881 ref.refoff.to_shwi ()))
1883 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1884 refop = TREE_OPERAND (ref.ref, 1);
1885 if (DECL_P (refop))
1886 inform (DECL_SOURCE_LOCATION (refop),
1887 "subobject %qD declared here", refop);
1888 warned = true;
1892 return warned ? opt : no_warning;
1895 /* Check a CALL statement for restrict-violations and issue warnings
1896 if/when appropriate. */
1898 static void
1899 check_call (range_query *query, gimple *call)
1901 /* Avoid checking the call if it has already been diagnosed for
1902 some reason. */
1903 if (warning_suppressed_p (call, OPT_Wrestrict))
1904 return;
1906 tree func = gimple_call_fndecl (call);
1907 if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
1908 return;
1910 /* Argument number to extract from the call (depends on the built-in
1911 and its kind). */
1912 unsigned dst_idx = -1;
1913 unsigned src_idx = -1;
1914 unsigned bnd_idx = -1;
1916 /* Is this CALL to a string function (as opposed to one to a raw
1917 memory function). */
1918 bool strfun = true;
1920 switch (DECL_FUNCTION_CODE (func))
1922 case BUILT_IN_MEMCPY:
1923 case BUILT_IN_MEMCPY_CHK:
1924 case BUILT_IN_MEMPCPY:
1925 case BUILT_IN_MEMPCPY_CHK:
1926 case BUILT_IN_MEMMOVE:
1927 case BUILT_IN_MEMMOVE_CHK:
1928 strfun = false;
1929 /* Fall through. */
1931 case BUILT_IN_STPNCPY:
1932 case BUILT_IN_STPNCPY_CHK:
1933 case BUILT_IN_STRNCAT:
1934 case BUILT_IN_STRNCAT_CHK:
1935 case BUILT_IN_STRNCPY:
1936 case BUILT_IN_STRNCPY_CHK:
1937 dst_idx = 0;
1938 src_idx = 1;
1939 bnd_idx = 2;
1940 break;
1942 case BUILT_IN_MEMSET:
1943 case BUILT_IN_MEMSET_CHK:
1944 dst_idx = 0;
1945 bnd_idx = 2;
1946 break;
1948 case BUILT_IN_STPCPY:
1949 case BUILT_IN_STPCPY_CHK:
1950 case BUILT_IN_STRCPY:
1951 case BUILT_IN_STRCPY_CHK:
1952 case BUILT_IN_STRCAT:
1953 case BUILT_IN_STRCAT_CHK:
1954 dst_idx = 0;
1955 src_idx = 1;
1956 break;
1958 default:
1959 /* Handle other string functions here whose access may need
1960 to be validated for in-bounds offsets and non-overlapping
1961 copies. */
1962 return;
1965 unsigned nargs = gimple_call_num_args (call);
1967 tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
1968 tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
1969 tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE;
1971 /* For string functions with an unspecified or unknown bound,
1972 assume the size of the access is one. */
1973 if (!dstwr && strfun)
1974 dstwr = size_one_node;
1976 /* DST and SRC can be null for a call with an insufficient number
1977 of arguments to a built-in function declared without a protype. */
1978 if (!dst || (src_idx < nargs && !src))
1979 return;
1981 /* DST, SRC, or DSTWR can also have the wrong type in a call to
1982 a function declared without a prototype. Avoid checking such
1983 invalid calls. */
1984 if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
1985 || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
1986 || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
1987 return;
1989 opt_code opt = check_bounds_or_overlap (query, call, dst, src, dstwr,
1990 NULL_TREE);
1991 /* Avoid diagnosing the call again. */
1992 suppress_warning (call, opt);
1995 } /* anonymous namespace */
1997 /* Attempt to detect and diagnose invalid offset bounds and (except for
1998 memmove) overlapping copy in a call expression EXPR from SRC to DST
1999 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
2000 SRCSIZE may be NULL. DO_WARN is false to detect either problem
2001 without issue a warning. Return the OPT_Wxxx constant corresponding
2002 to the warning if one has been detected and zero otherwise. */
2004 opt_code
2005 check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
2006 tree srcsize, bool bounds_only /* = false */,
2007 bool do_warn /* = true */)
2009 return check_bounds_or_overlap (/*range_query=*/NULL,
2010 call, dst, src, dstsize, srcsize,
2011 bounds_only, do_warn);
2014 opt_code
2015 check_bounds_or_overlap (range_query *query,
2016 gimple *call, tree dst, tree src, tree dstsize,
2017 tree srcsize, bool bounds_only /* = false */,
2018 bool do_warn /* = true */)
2020 tree func = gimple_call_fndecl (call);
2022 builtin_memref dstref (query, call, dst, dstsize);
2023 builtin_memref srcref (query, call, src, srcsize);
2025 /* Create a descriptor of the access. This may adjust both DSTREF
2026 and SRCREF based on one another and the kind of the access. */
2027 builtin_access acs (query, call, dstref, srcref);
2029 /* Set STRICT to the value of the -Warray-bounds=N argument for
2030 string functions or when N > 1. */
2031 int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0);
2033 /* The starting offset of the destination write access. Nonzero only
2034 for the strcat family of functions. */
2035 offset_int wroff = acs.write_off (dstsize);
2037 /* Validate offsets to each reference before the access first to make
2038 sure they are within the bounds of the destination object if its
2039 size is known, or PTRDIFF_MAX otherwise. */
2040 opt_code opt
2041 = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
2042 if (opt == no_warning)
2043 opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
2045 if (opt != no_warning)
2047 if (do_warn)
2048 suppress_warning (call, opt);
2049 return opt;
2052 if (!warn_restrict || bounds_only || !src)
2053 return no_warning;
2055 if (!bounds_only)
2057 switch (DECL_FUNCTION_CODE (func))
2059 case BUILT_IN_MEMMOVE:
2060 case BUILT_IN_MEMMOVE_CHK:
2061 case BUILT_IN_MEMSET:
2062 case BUILT_IN_MEMSET_CHK:
2063 return no_warning;
2064 default:
2065 break;
2069 location_t loc = gimple_location (call);
2070 if (operand_equal_p (dst, src, 0))
2072 /* Issue -Wrestrict unless the pointers are null (those do
2073 not point to objects and so do not indicate an overlap;
2074 such calls could be the result of sanitization and jump
2075 threading). */
2076 if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
2078 warning_at (loc, OPT_Wrestrict,
2079 "%qD source argument is the same as destination",
2080 func);
2081 suppress_warning (call, OPT_Wrestrict);
2082 return OPT_Wrestrict;
2085 return no_warning;
2088 /* Return false when overlap has been detected. */
2089 if (maybe_diag_overlap (loc, call, acs))
2091 suppress_warning (call, OPT_Wrestrict);
2092 return OPT_Wrestrict;
2095 return no_warning;
2098 gimple_opt_pass *
2099 make_pass_warn_restrict (gcc::context *ctxt)
2101 return new pass_wrestrict (ctxt);
2104 DEBUG_FUNCTION void
2105 dump_builtin_memref (FILE *fp, const builtin_memref &ref)
2107 fprintf (fp, "\n ptr = ");
2108 print_generic_expr (fp, ref.ptr, TDF_LINENO);
2109 fprintf (fp, "\n ref = ");
2110 if (ref.ref)
2111 print_generic_expr (fp, ref.ref, TDF_LINENO);
2112 else
2113 fputs ("null", fp);
2114 fprintf (fp, "\n base = ");
2115 print_generic_expr (fp, ref.base, TDF_LINENO);
2116 fprintf (fp,
2117 "\n basesize = %lli"
2118 "\n refsize = %lli"
2119 "\n refoff = %lli"
2120 "\n offrange = [%lli, %lli]"
2121 "\n sizrange = [%lli, %lli]"
2122 "\n strbounded_p = %s\n",
2123 (long long)ref.basesize.to_shwi (),
2124 (long long)ref.refsize.to_shwi (),
2125 (long long)ref.refoff.to_shwi (),
2126 (long long)ref.offrange[0].to_shwi (),
2127 (long long)ref.offrange[1].to_shwi (),
2128 (long long)ref.sizrange[0].to_shwi (),
2129 (long long)ref.sizrange[1].to_shwi (),
2130 ref.strbounded_p ? "true" : "false");
2133 void
2134 builtin_access::dump (FILE *fp) const
2136 fprintf (fp, " dstref:");
2137 dump_builtin_memref (fp, *dstref);
2138 fprintf (fp, "\n srcref:");
2139 dump_builtin_memref (fp, *srcref);
2141 fprintf (fp,
2142 " sizrange = [%lli, %lli]\n"
2143 " ovloff = [%lli, %lli]\n"
2144 " ovlsiz = [%lli, %lli]\n"
2145 " dstoff = [%lli, %lli]\n"
2146 " dstsiz = [%lli, %lli]\n"
2147 " srcoff = [%lli, %lli]\n"
2148 " srcsiz = [%lli, %lli]\n",
2149 (long long)sizrange[0], (long long)sizrange[1],
2150 (long long)ovloff[0], (long long)ovloff[1],
2151 (long long)ovlsiz[0], (long long)ovlsiz[1],
2152 (long long)dstoff[0].to_shwi (), (long long)dstoff[1].to_shwi (),
2153 (long long)dstsiz[0].to_shwi (), (long long)dstsiz[1].to_shwi (),
2154 (long long)srcoff[0].to_shwi (), (long long)srcoff[1].to_shwi (),
2155 (long long)srcsiz[0].to_shwi (), (long long)srcsiz[1].to_shwi ());
2158 DEBUG_FUNCTION void
2159 dump_builtin_access (FILE *fp, gimple *stmt, const builtin_access &acs)
2161 if (stmt)
2163 fprintf (fp, "\nDumping builtin_access for ");
2164 print_gimple_expr (fp, stmt, TDF_LINENO);
2165 fputs (":\n", fp);
2168 acs.dump (fp);
2171 DEBUG_FUNCTION void
2172 debug (gimple *stmt, const builtin_access &acs)
2174 dump_builtin_access (stdout, stmt, acs);