1 /* Pass to detect and issue warnings for violations of the restrict
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
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
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/>. */
24 #include "coretypes.h"
28 #include "tree-pass.h"
31 #include "gimple-pretty-print.h"
32 #include "gimple-ssa-warn-restrict.h"
33 #include "diagnostic-core.h"
34 #include "fold-const.h"
35 #include "gimple-iterator.h"
39 #include "tree-object-size.h"
43 #include "gimple-range.h"
47 const pass_data pass_data_wrestrict
= {
52 PROP_cfg
, /* Properties_required. */
53 0, /* properties_provided. */
54 0, /* properties_destroyed. */
55 0, /* properties_start */
56 0, /* properties_finish */
59 /* Pass to detect violations of strict aliasing requirements in calls
60 to built-in string and raw memory functions. */
61 class pass_wrestrict
: public gimple_opt_pass
64 pass_wrestrict (gcc::context
*ctxt
)
65 : gimple_opt_pass (pass_data_wrestrict
, ctxt
)
68 opt_pass
*clone () { return new pass_wrestrict (m_ctxt
); }
70 virtual bool gate (function
*);
71 virtual unsigned int execute (function
*);
75 pass_wrestrict::gate (function
*fun ATTRIBUTE_UNUSED
)
77 return warn_array_bounds
|| warn_restrict
|| warn_stringop_overflow
;
80 static void check_call (range_query
*, gimple
*);
83 wrestrict_walk (range_query
*query
, basic_block bb
)
85 /* Iterate over statements, looking for function calls. */
86 for (gimple_stmt_iterator si
= gsi_start_bb (bb
); !gsi_end_p (si
);
89 gimple
*stmt
= gsi_stmt (si
);
90 if (!is_gimple_call (stmt
))
93 check_call (query
, stmt
);
98 pass_wrestrict::execute (function
*fun
)
100 gimple_ranger ranger
;
102 FOR_EACH_BB_FN (bb
, fun
)
103 wrestrict_walk (&ranger
, bb
);
108 /* Description of a memory reference by a built-in function. This
109 is similar to ao_ref but made especially suitable for -Wrestrict
110 and not for optimization. */
114 /* The original pointer argument to the built-in function. */
116 /* The referenced subobject or NULL if not available, and the base
117 object of the memory reference or NULL. */
121 /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
122 and negative until (possibly lazily) initialized. */
124 /* Same for the subobject. */
127 /* The non-negative offset of the referenced subobject. Used to avoid
128 warnings for (apparently) possibly but not definitively overlapping
129 accesses to member arrays. Negative when unknown/invalid. */
132 /* The offset range relative to the base. */
133 offset_int offrange
[2];
134 /* The size range of the access to this reference. */
135 offset_int sizrange
[2];
137 /* Cached result of get_max_objsize(). */
138 const offset_int maxobjsize
;
140 /* True for "bounded" string functions like strncat, and strncpy
141 and their variants that specify either an exact or upper bound
142 on the size of the accesses they perform. For strncat both
143 the source and destination references are bounded. For strncpy
144 only the destination reference is. */
147 builtin_memref (range_query
*, gimple
*, tree
, tree
);
149 tree
offset_out_of_bounds (int, offset_int
[3]) const;
152 /* Call statement to the built-in. */
157 /* Ctor helper to set or extend OFFRANGE based on argument. */
158 void extend_offset_range (tree
);
160 /* Ctor helper to determine BASE and OFFRANGE from argument. */
161 void set_base_and_offset (tree
);
164 /* Description of a memory access by a raw memory or string built-in
165 function involving a pair of builtin_memref's. */
169 /* Destination and source memory reference. */
170 builtin_memref
* const dstref
;
171 builtin_memref
* const srcref
;
172 /* The size range of the access. It's the greater of the accesses
173 to the two references. */
174 HOST_WIDE_INT sizrange
[2];
176 /* The minimum and maximum offset of an overlap of the access
177 (if it does, in fact, overlap), and the size of the overlap. */
178 HOST_WIDE_INT ovloff
[2];
179 HOST_WIDE_INT ovlsiz
[2];
181 /* True to consider valid only accesses to the smallest subobject
182 and false for raw memory functions. */
185 return (detect_overlap
!= &builtin_access::generic_overlap
186 && detect_overlap
!= &builtin_access::no_overlap
);
189 builtin_access (range_query
*, gimple
*, builtin_memref
&, builtin_memref
&);
191 /* Entry point to determine overlap. */
194 offset_int
write_off (tree
) const;
196 void dump (FILE *) const;
199 /* Implementation functions used to determine overlap. */
200 bool generic_overlap ();
201 bool strcat_overlap ();
202 bool strcpy_overlap ();
209 offset_int
overlap_size (const offset_int
[2], const offset_int
[2],
213 /* Temporaries used to compute the final result. */
214 offset_int dstoff
[2];
215 offset_int srcoff
[2];
216 offset_int dstsiz
[2];
217 offset_int srcsiz
[2];
219 /* Pointer to a member function to call to determine overlap. */
220 bool (builtin_access::*detect_overlap
) ();
223 /* Initialize a memory reference representation from a pointer EXPR and
224 a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed
225 to be unknown. STMT is the statement in which expr appears in. */
227 builtin_memref::builtin_memref (range_query
*query
, gimple
*stmt
, tree expr
,
234 refoff (HOST_WIDE_INT_MIN
),
237 maxobjsize (tree_to_shwi (max_object_size ())),
242 /* Unfortunately, wide_int default ctor is a no-op so array members
243 of the type must be set individually. */
244 offrange
[0] = offrange
[1] = 0;
245 sizrange
[0] = sizrange
[1] = 0;
250 /* Find the BASE object or pointer referenced by EXPR and set
251 the offset range OFFRANGE in the process. */
252 set_base_and_offset (expr
);
257 /* Determine the size range, allowing for the result to be [0, 0]
258 for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */
259 get_size_range (query
, size
, stmt
, range
, SR_ALLOW_ZERO
);
260 sizrange
[0] = wi::to_offset (range
[0]);
261 sizrange
[1] = wi::to_offset (range
[1]);
262 /* get_size_range returns SIZE_MAX for the maximum size.
263 Constrain it to the real maximum of PTRDIFF_MAX. */
264 if (sizrange
[0] <= maxobjsize
&& sizrange
[1] > maxobjsize
)
265 sizrange
[1] = maxobjsize
;
268 sizrange
[1] = maxobjsize
;
273 /* If the offset could be in the range of the referenced object
274 constrain its bounds so neither exceeds those of the object. */
275 if (offrange
[0] < 0 && offrange
[1] > 0)
278 offset_int maxoff
= maxobjsize
;
279 tree basetype
= TREE_TYPE (base
);
280 if (TREE_CODE (basetype
) == ARRAY_TYPE
)
282 if (ref
&& array_at_struct_end_p (ref
))
283 ; /* Use the maximum possible offset for last member arrays. */
284 else if (tree basesize
= TYPE_SIZE_UNIT (basetype
))
285 if (TREE_CODE (basesize
) == INTEGER_CST
)
286 /* Size could be non-constant for a variable-length type such
287 as a struct with a VLA member (a GCC extension). */
288 maxoff
= wi::to_offset (basesize
);
291 if (offrange
[0] >= 0)
294 offrange
[1] = offrange
[0] <= maxoff
? maxoff
: maxobjsize
;
295 else if (offrange
[0] <= maxoff
&& offrange
[1] > maxoff
)
296 offrange
[1] = maxoff
;
300 /* Based on the initial length of the destination STARTLEN, returns
301 the offset of the first write access from the beginning of
302 the destination. Nonzero only for strcat-type of calls. */
304 offset_int
builtin_access::write_off (tree startlen
) const
306 if (detect_overlap
!= &builtin_access::strcat_overlap
307 || !startlen
|| TREE_CODE (startlen
) != INTEGER_CST
)
310 return wi::to_offset (startlen
);
313 /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
314 Pointer offsets are represented as unsigned sizetype but must be
315 treated as signed. */
318 builtin_memref::extend_offset_range (tree offset
)
320 if (TREE_CODE (offset
) == INTEGER_CST
)
322 offset_int off
= int_cst_value (offset
);
331 if (TREE_CODE (offset
) == SSA_NAME
)
333 /* A pointer offset is represented as sizetype but treated
336 value_range_kind rng
;
338 if (query
&& query
->range_of_expr (vr
, offset
, stmt
))
341 if (!vr
.undefined_p ())
343 min
= wi::to_wide (vr
.min ());
344 max
= wi::to_wide (vr
.max ());
349 /* There is a global version here because
350 check_bounds_or_overlap may be called from gimple
351 fold during gimple lowering. */
352 get_range_query (cfun
)->range_of_expr (vr
, offset
, stmt
);
354 if (!vr
.undefined_p ())
356 min
= wi::to_wide (vr
.min ());
357 max
= wi::to_wide (vr
.max ());
360 if (rng
== VR_ANTI_RANGE
&& wi::lts_p (max
, min
))
362 /* Convert an anti-range whose upper bound is less than
363 its lower bound to a signed range. */
364 offrange
[0] += offset_int::from (max
+ 1, SIGNED
);
365 offrange
[1] += offset_int::from (min
- 1, SIGNED
);
370 && (DECL_P (base
) || wi::lts_p (min
, max
)))
372 /* Preserve the bounds of the range for an offset into
373 a known object (it may be adjusted later relative to
374 a constant offset from its beginning). Otherwise use
375 the bounds only when they are ascending when treated
377 offrange
[0] += offset_int::from (min
, SIGNED
);
378 offrange
[1] += offset_int::from (max
, SIGNED
);
382 /* Handle an anti-range the same as no range at all. */
383 gimple
*stmt
= SSA_NAME_DEF_STMT (offset
);
385 if (is_gimple_assign (stmt
)
386 && (type
= TREE_TYPE (gimple_assign_rhs1 (stmt
)))
387 && INTEGRAL_TYPE_P (type
))
389 tree_code code
= gimple_assign_rhs_code (stmt
);
390 if (code
== NOP_EXPR
)
392 /* Use the bounds of the type of the NOP_EXPR operand
393 even if it's signed. The result doesn't trigger
394 warnings but makes their output more readable. */
395 offrange
[0] += wi::to_offset (TYPE_MIN_VALUE (type
));
396 offrange
[1] += wi::to_offset (TYPE_MAX_VALUE (type
));
402 const offset_int maxoff
= tree_to_shwi (max_object_size ()) >> 1;
403 const offset_int minoff
= -maxoff
- 1;
405 offrange
[0] += minoff
;
406 offrange
[1] += maxoff
;
409 /* Determines the base object or pointer of the reference EXPR
410 and the offset range from the beginning of the base. */
413 builtin_memref::set_base_and_offset (tree expr
)
415 tree offset
= NULL_TREE
;
417 if (TREE_CODE (expr
) == SSA_NAME
)
419 /* Try to tease the offset out of the pointer. */
420 gimple
*stmt
= SSA_NAME_DEF_STMT (expr
);
422 && gimple_assign_single_p (stmt
)
423 && gimple_assign_rhs_code (stmt
) == ADDR_EXPR
)
424 expr
= gimple_assign_rhs1 (stmt
);
425 else if (is_gimple_assign (stmt
))
427 tree_code code
= gimple_assign_rhs_code (stmt
);
428 if (code
== NOP_EXPR
)
430 tree rhs
= gimple_assign_rhs1 (stmt
);
431 if (POINTER_TYPE_P (TREE_TYPE (rhs
)))
432 expr
= gimple_assign_rhs1 (stmt
);
439 else if (code
== POINTER_PLUS_EXPR
)
441 expr
= gimple_assign_rhs1 (stmt
);
442 offset
= gimple_assign_rhs2 (stmt
);
452 /* FIXME: Handle PHI nodes in case like:
453 _12 = &MEM[(void *)&a + 2B] + _10;
455 <bb> [local count: 1073741824]:
456 # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
457 memcpy (prephitmp_13, p_7(D), 6); */
463 if (TREE_CODE (expr
) == ADDR_EXPR
)
464 expr
= TREE_OPERAND (expr
, 0);
466 /* Stash the reference for offset validation. */
469 poly_int64 bitsize
, bitpos
;
472 int sign
, reverse
, vol
;
474 /* Determine the base object or pointer of the reference and
475 the constant bit offset from the beginning of the base.
476 If the offset has a non-constant component, it will be in
477 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
479 base
= get_inner_reference (expr
, &bitsize
, &bitpos
, &var_off
,
480 &mode
, &sign
, &reverse
, &vol
);
482 /* get_inner_reference is not expected to return null. */
483 gcc_assert (base
!= NULL
);
486 extend_offset_range (offset
);
488 poly_int64 bytepos
= exact_div (bitpos
, BITS_PER_UNIT
);
490 /* Convert the poly_int64 offset to offset_int. The offset
491 should be constant but be prepared for it not to be just in
494 if (bytepos
.is_constant (&cstoff
))
496 offrange
[0] += cstoff
;
497 offrange
[1] += cstoff
;
499 /* Besides the reference saved above, also stash the offset
501 if (TREE_CODE (expr
) == COMPONENT_REF
)
505 offrange
[1] += maxobjsize
;
509 if (TREE_CODE (var_off
) == INTEGER_CST
)
511 cstoff
= wi::to_offset (var_off
);
512 offrange
[0] += cstoff
;
513 offrange
[1] += cstoff
;
516 offrange
[1] += maxobjsize
;
519 if (TREE_CODE (base
) == MEM_REF
)
521 tree memrefoff
= fold_convert (ptrdiff_type_node
, TREE_OPERAND (base
, 1));
522 extend_offset_range (memrefoff
);
523 base
= TREE_OPERAND (base
, 0);
525 if (refoff
!= HOST_WIDE_INT_MIN
526 && TREE_CODE (expr
) == COMPONENT_REF
)
528 /* Bump up the offset of the referenced subobject to reflect
529 the offset to the enclosing object. For example, so that
531 struct S { char a, b[3]; } s[2];
532 strcpy (s[1].b, "1234");
533 REFOFF is set to s[1].b - (char*)s. */
534 offset_int off
= tree_to_shwi (memrefoff
);
538 if (!integer_zerop (memrefoff
))
539 /* A non-zero offset into an array of struct with flexible array
540 members implies that the array is empty because there is no
541 way to initialize such a member when it belongs to an array.
542 This must be some sort of a bug. */
546 if (TREE_CODE (ref
) == COMPONENT_REF
)
547 if (tree size
= component_ref_size (ref
))
548 if (TREE_CODE (size
) == INTEGER_CST
)
549 refsize
= wi::to_offset (size
);
551 if (TREE_CODE (base
) == SSA_NAME
)
552 set_base_and_offset (base
);
555 /* Return error_mark_node if the signed offset exceeds the bounds
556 of the address space (PTRDIFF_MAX). Otherwise, return either BASE
557 or REF when the offset exceeds the bounds of the BASE or REF object,
558 and set OOBOFF to the past-the-end offset formed by the reference,
559 including its size. OOBOFF is initially setto the range of offsets,
560 and OOBOFF[2] to the offset of the first write access (nonzero for
561 the strcat family). When STRICT is nonzero use REF size, when
562 available, otherwise use BASE size. When STRICT is greater than 1,
563 use the size of the last array member as the bound, otherwise treat
564 such a member as a flexible array member. Return NULL when the offset
568 builtin_memref::offset_out_of_bounds (int strict
, offset_int ooboff
[3]) const
573 /* The offset of the first write access or zero. */
574 offset_int wroff
= ooboff
[2];
576 /* A temporary, possibly adjusted, copy of the offset range. */
577 offset_int offrng
[2] = { ooboff
[0], ooboff
[1] };
579 if (DECL_P (base
) && TREE_CODE (TREE_TYPE (base
)) == ARRAY_TYPE
)
581 /* Check for offset in an anti-range with a negative lower bound.
582 For such a range, consider only the non-negative subrange. */
583 if (offrng
[1] < offrng
[0] && offrng
[1] < 0)
584 offrng
[1] = maxobjsize
;
587 /* Conservative offset of the last byte of the referenced object. */
590 /* The bounds need not be ordered. Set HIB to use as the index
591 of the larger of the bounds and LOB as the opposite. */
592 bool hib
= wi::les_p (offrng
[0], offrng
[1]);
595 /* Set to the size remaining in the object after subtracting
596 REFOFF. It may become negative as a result of negative indices
597 into the enclosing object, such as in:
598 extern struct S { char a[4], b[3], c[1]; } *p;
599 strcpy (p[-3].b, "123"); */
600 offset_int size
= basesize
;
603 const bool decl_p
= DECL_P (obj
);
607 endoff
= offrng
[lob
] + (sizrange
[0] - wroff
);
609 /* For a reference through a pointer to an object of unknown size
610 all initial offsets are considered valid, positive as well as
611 negative, since the pointer itself can point past the beginning
612 of the object. However, the sum of the lower bound of the offset
613 and that of the size must be less than or equal than PTRDIFF_MAX. */
614 if (endoff
> maxobjsize
)
615 return error_mark_node
;
617 /* When the referenced subobject is known, the end offset must be
618 within its bounds. Otherwise there is nothing to do. */
623 && TREE_CODE (ref
) == COMPONENT_REF
)
625 /* If REFOFF is negative, SIZE will become negative here. */
626 size
= refoff
+ refsize
;
633 /* A reference to an object of known size must be within the bounds
634 of either the base object or the subobject (see above for when
635 a subobject can be used). */
636 if ((decl_p
&& offrng
[hib
] < 0) || offrng
[lob
] > size
)
639 /* The extent of the reference must also be within the bounds of
640 the base object (if known) or the subobject or the maximum object
642 endoff
= offrng
[lob
] + sizrange
[0];
643 if (endoff
> maxobjsize
)
644 return error_mark_node
;
650 && TREE_CODE (ref
) == COMPONENT_REF
)
652 /* If the reference is to a member subobject of a declared object,
653 the offset must be within the bounds of the subobject. */
654 size
= refoff
+ refsize
;
661 /* Set the out-of-bounds offset range to be one greater than
662 that delimited by the reference including its size. */
665 if (endoff
> ooboff
[lob
])
666 ooboff
[hib
] = endoff
- 1;
668 ooboff
[hib
] = offrng
[lob
] + sizrange
[1];
673 /* Create an association between the memory references DST and SRC
674 for access by a call EXPR to a memory or string built-in funtion. */
676 builtin_access::builtin_access (range_query
*query
, gimple
*call
,
679 : dstref (&dst
), srcref (&src
), sizrange (), ovloff (), ovlsiz (),
680 dstoff (), srcoff (), dstsiz (), srcsiz ()
682 dstoff
[0] = dst
.offrange
[0];
683 dstoff
[1] = dst
.offrange
[1];
685 /* Zero out since the offset_int ctors invoked above are no-op. */
686 srcoff
[0] = srcoff
[1] = 0;
687 dstsiz
[0] = dstsiz
[1] = 0;
688 srcsiz
[0] = srcsiz
[1] = 0;
690 /* Object Size Type to use to determine the size of the destination
691 and source objects. Overridden below for raw memory functions. */
694 /* True when the size of one reference depends on the offset of
695 itself or the other. */
696 bool depends_p
= true;
698 /* True when the size of the destination reference DSTREF has been
699 determined from SRCREF and so needs to be adjusted by the latter's
700 offset. Only meaningful for bounded string functions like strncpy. */
701 bool dstadjust_p
= false;
703 /* The size argument number (depends on the built-in). */
704 unsigned sizeargno
= 2;
706 tree func
= gimple_call_fndecl (call
);
707 switch (DECL_FUNCTION_CODE (func
))
709 case BUILT_IN_MEMCPY
:
710 case BUILT_IN_MEMCPY_CHK
:
711 case BUILT_IN_MEMPCPY
:
712 case BUILT_IN_MEMPCPY_CHK
:
715 detect_overlap
= &builtin_access::generic_overlap
;
718 case BUILT_IN_MEMMOVE
:
719 case BUILT_IN_MEMMOVE_CHK
:
720 /* For memmove there is never any overlap to check for. */
723 detect_overlap
= &builtin_access::no_overlap
;
726 case BUILT_IN_MEMSET
:
727 case BUILT_IN_MEMSET_CHK
:
728 /* For memset there is never any overlap to check for. */
731 detect_overlap
= &builtin_access::no_overlap
;
734 case BUILT_IN_STPNCPY
:
735 case BUILT_IN_STPNCPY_CHK
:
736 case BUILT_IN_STRNCPY
:
737 case BUILT_IN_STRNCPY_CHK
:
738 dstref
->strbounded_p
= true;
739 detect_overlap
= &builtin_access::strcpy_overlap
;
742 case BUILT_IN_STPCPY
:
743 case BUILT_IN_STPCPY_CHK
:
744 case BUILT_IN_STRCPY
:
745 case BUILT_IN_STRCPY_CHK
:
746 detect_overlap
= &builtin_access::strcpy_overlap
;
749 case BUILT_IN_STRCAT
:
750 case BUILT_IN_STRCAT_CHK
:
751 detect_overlap
= &builtin_access::strcat_overlap
;
754 case BUILT_IN_STRNCAT
:
755 case BUILT_IN_STRNCAT_CHK
:
756 dstref
->strbounded_p
= true;
757 srcref
->strbounded_p
= true;
758 detect_overlap
= &builtin_access::strcat_overlap
;
762 /* Handle other string functions here whose access may need
763 to be validated for in-bounds offsets and non-overlapping
768 const offset_int maxobjsize
= dst
.maxobjsize
;
770 /* Try to determine the size of the base object. compute_objsize
771 expects a pointer so create one if BASE is a non-pointer object. */
773 if (dst
.basesize
< 0)
776 if (!POINTER_TYPE_P (TREE_TYPE (addr
)))
777 addr
= build1 (ADDR_EXPR
, (TREE_TYPE (addr
)), addr
);
779 if (tree dstsize
= compute_objsize (addr
, ostype
))
780 dst
.basesize
= wi::to_offset (dstsize
);
781 else if (POINTER_TYPE_P (TREE_TYPE (addr
)))
782 dst
.basesize
= HOST_WIDE_INT_MIN
;
784 dst
.basesize
= maxobjsize
;
787 if (src
.base
&& src
.basesize
< 0)
790 if (!POINTER_TYPE_P (TREE_TYPE (addr
)))
791 addr
= build1 (ADDR_EXPR
, (TREE_TYPE (addr
)), addr
);
793 if (tree srcsize
= compute_objsize (addr
, ostype
))
794 src
.basesize
= wi::to_offset (srcsize
);
795 else if (POINTER_TYPE_P (TREE_TYPE (addr
)))
796 src
.basesize
= HOST_WIDE_INT_MIN
;
798 src
.basesize
= maxobjsize
;
801 /* Make adjustments for references to the same object by string
802 built-in functions to reflect the constraints imposed by
805 /* For bounded string functions determine the range of the bound
806 on the access. For others, the range stays unbounded. */
807 offset_int bounds
[2] = { maxobjsize
, maxobjsize
};
808 if (dstref
->strbounded_p
)
810 unsigned nargs
= gimple_call_num_args (call
);
811 if (nargs
<= sizeargno
)
814 tree size
= gimple_call_arg (call
, sizeargno
);
816 if (get_size_range (query
, size
, call
, range
, true))
818 bounds
[0] = wi::to_offset (range
[0]);
819 bounds
[1] = wi::to_offset (range
[1]);
822 /* If both references' size ranges are indeterminate use the last
823 (size) argument from the function call as a substitute. This
824 may only be necessary for strncpy (but not for memcpy where
825 the size range would have been already determined this way). */
826 if (dstref
->sizrange
[0] == 0 && dstref
->sizrange
[1] == maxobjsize
827 && srcref
->sizrange
[0] == 0 && srcref
->sizrange
[1] == maxobjsize
)
829 dstref
->sizrange
[0] = bounds
[0];
830 dstref
->sizrange
[1] = bounds
[1];
834 bool dstsize_set
= false;
835 /* The size range of one reference involving the same base object
836 can be determined from the size range of the other reference.
837 This makes it possible to compute accurate offsets for warnings
838 involving functions like strcpy where the length of just one of
839 the two arguments is known (determined by tree-ssa-strlen). */
840 if (dstref
->sizrange
[0] == 0 && dstref
->sizrange
[1] == maxobjsize
)
842 /* When the destination size is unknown set it to the size of
844 dstref
->sizrange
[0] = srcref
->sizrange
[0];
845 dstref
->sizrange
[1] = srcref
->sizrange
[1];
848 else if (srcref
->sizrange
[0] == 0 && srcref
->sizrange
[1] == maxobjsize
)
850 /* When the size of the source access is unknown set it to the size
851 of the destination first and adjust it later if necessary. */
852 srcref
->sizrange
[0] = dstref
->sizrange
[0];
853 srcref
->sizrange
[1] = dstref
->sizrange
[1];
857 if (dstref
->strbounded_p
)
859 /* Read access by strncpy is constrained by the third
860 argument but except for a zero bound is at least one. */
861 srcref
->sizrange
[0] = bounds
[1] > 0 ? 1 : 0;
862 offset_int bound
= wi::umin (srcref
->basesize
, bounds
[1]);
863 if (bound
< srcref
->sizrange
[1])
864 srcref
->sizrange
[1] = bound
;
866 /* For string functions, adjust the size range of the source
867 reference by the inverse boundaries of the offset (because
868 the higher the offset into the string the shorter its
870 if (srcref
->offrange
[1] >= 0
871 && srcref
->offrange
[1] < srcref
->sizrange
[0])
872 srcref
->sizrange
[0] -= srcref
->offrange
[1];
874 srcref
->sizrange
[0] = 1;
876 if (srcref
->offrange
[0] > 0)
878 if (srcref
->offrange
[0] < srcref
->sizrange
[1])
879 srcref
->sizrange
[1] -= srcref
->offrange
[0];
881 srcref
->sizrange
[1] = 0;
888 if (detect_overlap
== &builtin_access::generic_overlap
)
890 if (dstref
->strbounded_p
)
892 dstref
->sizrange
[0] = bounds
[0];
893 dstref
->sizrange
[1] = bounds
[1];
895 if (dstref
->sizrange
[0] < srcref
->sizrange
[0])
896 srcref
->sizrange
[0] = dstref
->sizrange
[0];
898 if (dstref
->sizrange
[1] < srcref
->sizrange
[1])
899 srcref
->sizrange
[1] = dstref
->sizrange
[1];
902 else if (detect_overlap
== &builtin_access::strcpy_overlap
)
904 if (!dstref
->strbounded_p
)
906 /* For strcpy, adjust the destination size range to match that
907 of the source computed above. */
908 if (depends_p
&& dstadjust_p
)
910 dstref
->sizrange
[0] = srcref
->sizrange
[0];
911 dstref
->sizrange
[1] = srcref
->sizrange
[1];
915 else if (!dstsize_set
&& detect_overlap
== &builtin_access::strcat_overlap
)
917 dstref
->sizrange
[0] += srcref
->sizrange
[0] - 1;
918 dstref
->sizrange
[1] += srcref
->sizrange
[1] - 1;
921 if (dstref
->strbounded_p
)
923 /* For strncpy, adjust the destination size range to match that
924 of the source computed above. */
925 dstref
->sizrange
[0] = bounds
[0];
926 dstref
->sizrange
[1] = bounds
[1];
928 if (bounds
[0] < srcref
->sizrange
[0])
929 srcref
->sizrange
[0] = bounds
[0];
931 if (bounds
[1] < srcref
->sizrange
[1])
932 srcref
->sizrange
[1] = bounds
[1];
937 builtin_access::overlap_size (const offset_int a
[2], const offset_int b
[2],
940 const offset_int
*p
= a
;
941 const offset_int
*q
= b
;
943 /* Point P at the bigger of the two ranges and Q at the smaller. */
944 if (wi::lts_p (a
[1] - a
[0], b
[1] - b
[0]))
956 return wi::smin (p
[1], q
[1]) - q
[0];
966 /* Return true if the bounded mempry (memcpy amd similar) or string function
967 access (strncpy and similar) ACS overlaps. */
970 builtin_access::generic_overlap ()
972 builtin_access
&acs
= *this;
973 const builtin_memref
*dstref
= acs
.dstref
;
974 const builtin_memref
*srcref
= acs
.srcref
;
976 gcc_assert (dstref
->base
== srcref
->base
);
978 const offset_int maxobjsize
= acs
.dstref
->maxobjsize
;
980 offset_int maxsize
= dstref
->basesize
< 0 ? maxobjsize
: dstref
->basesize
;
982 /* Adjust the larger bounds of the offsets (which may be the first
983 element if the lower bound is larger than the upper bound) to
984 make them valid for the smallest access (if possible) but no smaller
985 than the smaller bounds. */
986 gcc_assert (wi::les_p (acs
.dstoff
[0], acs
.dstoff
[1]));
988 if (maxsize
< acs
.dstoff
[1] + acs
.dstsiz
[0])
989 acs
.dstoff
[1] = maxsize
- acs
.dstsiz
[0];
990 if (acs
.dstoff
[1] < acs
.dstoff
[0])
991 acs
.dstoff
[1] = acs
.dstoff
[0];
993 gcc_assert (wi::les_p (acs
.srcoff
[0], acs
.srcoff
[1]));
995 if (maxsize
< acs
.srcoff
[1] + acs
.srcsiz
[0])
996 acs
.srcoff
[1] = maxsize
- acs
.srcsiz
[0];
997 if (acs
.srcoff
[1] < acs
.srcoff
[0])
998 acs
.srcoff
[1] = acs
.srcoff
[0];
1000 /* Determine the minimum and maximum space for the access given
1002 offset_int space
[2];
1003 space
[0] = wi::abs (acs
.dstoff
[0] - acs
.srcoff
[0]);
1004 space
[1] = space
[0];
1006 offset_int d
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[1]);
1007 if (acs
.srcsiz
[0] > 0)
1016 space
[1] = acs
.dstsiz
[1];
1018 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
1025 /* Treat raw memory functions both of whose references are bounded
1026 as special and permit uncertain overlaps to go undetected. For
1027 all kinds of constant offset and constant size accesses, if
1028 overlap isn't certain it is not possible. */
1029 bool overlap_possible
= space
[0] < acs
.dstsiz
[1];
1030 if (!overlap_possible
)
1033 bool overlap_certain
= space
[1] < acs
.dstsiz
[0];
1035 /* True when the size of one reference depends on the offset of
1037 bool depends_p
= detect_overlap
!= &builtin_access::generic_overlap
;
1039 if (!overlap_certain
)
1041 if (!dstref
->strbounded_p
&& !depends_p
)
1042 /* Memcpy only considers certain overlap. */
1045 /* There's no way to distinguish an access to the same member
1046 of a structure from one to two distinct members of the same
1047 structure. Give up to avoid excessive false positives. */
1048 tree basetype
= TREE_TYPE (dstref
->base
);
1050 if (POINTER_TYPE_P (basetype
))
1051 basetype
= TREE_TYPE (basetype
);
1053 while (TREE_CODE (basetype
) == ARRAY_TYPE
)
1054 basetype
= TREE_TYPE (basetype
);
1056 if (RECORD_OR_UNION_TYPE_P (basetype
))
1060 /* True for stpcpy and strcpy. */
1061 bool stxcpy_p
= (!dstref
->strbounded_p
1062 && detect_overlap
== &builtin_access::strcpy_overlap
);
1064 if (dstref
->refoff
>= 0
1065 && srcref
->refoff
>= 0
1066 && dstref
->refoff
!= srcref
->refoff
1067 && (stxcpy_p
|| dstref
->strbounded_p
|| srcref
->strbounded_p
))
1070 offset_int siz
[2] = { maxobjsize
+ 1, 0 };
1072 ovloff
[0] = HOST_WIDE_INT_MAX
;
1073 ovloff
[1] = HOST_WIDE_INT_MIN
;
1077 /* Iterate over the extreme locations (on the horizontal axis formed
1078 by their offsets) and sizes of two regions and find their smallest
1079 and largest overlap and the corresponding offsets. */
1080 for (unsigned i
= 0; i
!= 2; ++i
)
1082 const offset_int a
[2] = {
1083 acs
.dstoff
[i
], acs
.dstoff
[i
] + acs
.dstsiz
[!i
]
1086 const offset_int b
[2] = {
1087 acs
.srcoff
[i
], acs
.srcoff
[i
] + acs
.srcsiz
[!i
]
1091 offset_int sz
= overlap_size (a
, b
, &off
);
1100 if (wi::lts_p (off
, ovloff
[0]))
1101 ovloff
[0] = off
.to_shwi ();
1102 if (wi::lts_p (ovloff
[1], off
))
1103 ovloff
[1] = off
.to_shwi ();
1109 /* Iterate over the extreme locations (on the horizontal axis
1110 formed by their offsets) and sizes of the two regions and
1111 find their smallest and largest overlap and the corresponding
1114 for (unsigned io
= 0; io
!= 2; ++io
)
1115 for (unsigned is
= 0; is
!= 2; ++is
)
1117 const offset_int a
[2] = {
1118 acs
.dstoff
[io
], acs
.dstoff
[io
] + acs
.dstsiz
[is
]
1121 for (unsigned jo
= 0; jo
!= 2; ++jo
)
1122 for (unsigned js
= 0; js
!= 2; ++js
)
1124 const offset_int b
[2] = {
1125 acs
.srcoff
[jo
], acs
.srcoff
[jo
] + acs
.srcsiz
[js
]
1129 offset_int sz
= overlap_size (a
, b
, &off
);
1138 if (wi::lts_p (off
, ovloff
[0]))
1139 ovloff
[0] = off
.to_shwi ();
1140 if (wi::lts_p (ovloff
[1], off
))
1141 ovloff
[1] = off
.to_shwi ();
1147 ovlsiz
[0] = siz
[0].to_shwi ();
1148 ovlsiz
[1] = siz
[1].to_shwi ();
1150 /* Adjust the overlap offset range to reflect the overlap size range. */
1151 if (ovlsiz
[0] == 0 && ovlsiz
[1] > 1)
1152 ovloff
[1] = ovloff
[0] + ovlsiz
[1] - 1;
1157 /* Return true if the strcat-like access overlaps. */
1160 builtin_access::strcat_overlap ()
1162 builtin_access
&acs
= *this;
1163 const builtin_memref
*dstref
= acs
.dstref
;
1164 const builtin_memref
*srcref
= acs
.srcref
;
1166 gcc_assert (dstref
->base
== srcref
->base
);
1168 const offset_int maxobjsize
= acs
.dstref
->maxobjsize
;
1170 gcc_assert (dstref
->base
&& dstref
->base
== srcref
->base
);
1172 /* Adjust for strcat-like accesses. */
1174 /* As a special case for strcat, set the DSTREF offsets to the length
1175 of the destination string since the function starts writing over
1176 its terminating nul, and set the destination size to 1 for the length
1178 acs
.dstoff
[0] += dstsiz
[0] - srcref
->sizrange
[0];
1179 acs
.dstoff
[1] += dstsiz
[1] - srcref
->sizrange
[1];
1181 bool strfunc_unknown_args
= acs
.dstsiz
[0] == 0 && acs
.dstsiz
[1] != 0;
1183 /* The lower bound is zero when the size is unknown because then
1184 overlap is not certain. */
1185 acs
.dstsiz
[0] = strfunc_unknown_args
? 0 : 1;
1188 offset_int maxsize
= dstref
->basesize
< 0 ? maxobjsize
: dstref
->basesize
;
1190 /* For references to the same base object, determine if there's a pair
1191 of valid offsets into the two references such that access between
1192 them doesn't overlap. Adjust both upper bounds to be valid for
1193 the smaller size (i.e., at most MAXSIZE - SIZE). */
1195 if (maxsize
< acs
.dstoff
[1] + acs
.dstsiz
[0])
1196 acs
.dstoff
[1] = maxsize
- acs
.dstsiz
[0];
1198 if (maxsize
< acs
.srcoff
[1] + acs
.srcsiz
[0])
1199 acs
.srcoff
[1] = maxsize
- acs
.srcsiz
[0];
1201 /* Check to see if there's enough space for both accesses without
1202 overlap. Determine the optimistic (maximum) amount of available
1205 if (acs
.dstoff
[0] <= acs
.srcoff
[0])
1207 if (acs
.dstoff
[1] < acs
.srcoff
[1])
1208 space
= acs
.srcoff
[1] + acs
.srcsiz
[0] - acs
.dstoff
[0];
1210 space
= acs
.dstoff
[1] + acs
.dstsiz
[0] - acs
.srcoff
[0];
1213 space
= acs
.dstoff
[1] + acs
.dstsiz
[0] - acs
.srcoff
[0];
1215 /* Overlap is certain if the distance between the farthest offsets
1216 of the opposite accesses is less than the sum of the lower bounds
1217 of the sizes of the two accesses. */
1218 bool overlap_certain
= space
< acs
.dstsiz
[0] + acs
.srcsiz
[0];
1220 /* For a constant-offset, constant size access, consider the largest
1221 distance between the offset bounds and the lower bound of the access
1222 size. If the overlap isn't certain return success. */
1223 if (!overlap_certain
1224 && acs
.dstoff
[0] == acs
.dstoff
[1]
1225 && acs
.srcoff
[0] == acs
.srcoff
[1]
1226 && acs
.dstsiz
[0] == acs
.dstsiz
[1]
1227 && acs
.srcsiz
[0] == acs
.srcsiz
[1])
1230 /* Overlap is not certain but may be possible. */
1232 offset_int access_min
= acs
.dstsiz
[0] + acs
.srcsiz
[0];
1234 /* Determine the conservative (minimum) amount of space. */
1235 space
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[0]);
1236 offset_int d
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[1]);
1239 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
1243 /* For a strict test (used for strcpy and similar with unknown or
1244 variable bounds or sizes), consider the smallest distance between
1245 the offset bounds and either the upper bound of the access size
1246 if known, or the lower bound otherwise. */
1247 if (access_min
<= space
&& (access_min
!= 0 || !strfunc_unknown_args
))
1250 /* When strcat overlap is certain it is always a single byte:
1251 the terminating NUL, regardless of offsets and sizes. When
1252 overlap is only possible its range is [0, 1]. */
1253 acs
.ovlsiz
[0] = dstref
->sizrange
[0] == dstref
->sizrange
[1] ? 1 : 0;
1257 = dstref
->offrange
[0] + (dstref
->sizrange
[0] - srcref
->sizrange
[0]);
1258 if (endoff
<= srcref
->offrange
[0])
1259 acs
.ovloff
[0] = wi::smin (maxobjsize
, srcref
->offrange
[0]).to_shwi ();
1261 acs
.ovloff
[0] = wi::smin (maxobjsize
, endoff
).to_shwi ();
1263 acs
.sizrange
[0] = wi::smax (wi::abs (endoff
- srcref
->offrange
[0]) + 1,
1264 srcref
->sizrange
[0]).to_shwi ();
1265 if (dstref
->offrange
[0] == dstref
->offrange
[1])
1267 if (srcref
->offrange
[0] == srcref
->offrange
[1])
1268 acs
.ovloff
[1] = acs
.ovloff
[0];
1271 = wi::smin (maxobjsize
,
1272 srcref
->offrange
[1] + srcref
->sizrange
[1]).to_shwi ();
1276 = wi::smin (maxobjsize
,
1277 dstref
->offrange
[1] + dstref
->sizrange
[1]).to_shwi ();
1279 if (acs
.sizrange
[0] == 0)
1280 acs
.sizrange
[0] = 1;
1281 acs
.sizrange
[1] = wi::smax (acs
.dstsiz
[1], srcref
->sizrange
[1]).to_shwi ();
1285 /* Return true if the strcpy-like access overlaps. */
1288 builtin_access::strcpy_overlap ()
1290 return generic_overlap ();
1293 /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
1294 if known, or [0, MAXOBJSIZE] otherwise. */
1297 clamp_offset (tree base
, offset_int refoff
[2], offset_int maxobjsize
)
1299 if (!base
|| TREE_CODE (TREE_TYPE (base
)) != ARRAY_TYPE
)
1302 if (refoff
[0] < 0 && refoff
[1] >= 0)
1305 if (refoff
[1] < refoff
[0])
1307 offset_int maxsize
= maxobjsize
;
1308 if (tree size
= TYPE_SIZE_UNIT (TREE_TYPE (base
)))
1309 maxsize
= wi::to_offset (size
);
1311 refoff
[1] = wi::umin (refoff
[1], maxsize
);
1315 /* Return true if DSTREF and SRCREF describe accesses that either overlap
1316 one another or that, in order not to overlap, would imply that the size
1317 of the referenced object(s) exceeds the maximum size of an object. Set
1318 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1319 they may overlap in a way that's not apparent from the available data),
1323 builtin_access::overlap ()
1325 builtin_access
&acs
= *this;
1327 const offset_int maxobjsize
= dstref
->maxobjsize
;
1329 acs
.sizrange
[0] = wi::smax (dstref
->sizrange
[0],
1330 srcref
->sizrange
[0]).to_shwi ();
1331 acs
.sizrange
[1] = wi::smax (dstref
->sizrange
[1],
1332 srcref
->sizrange
[1]).to_shwi ();
1334 /* Check to see if the two references refer to regions that are
1335 too large not to overlap in the address space (whose maximum
1336 size is PTRDIFF_MAX). */
1337 offset_int size
= dstref
->sizrange
[0] + srcref
->sizrange
[0];
1338 if (maxobjsize
< size
)
1340 acs
.ovloff
[0] = (maxobjsize
- dstref
->sizrange
[0]).to_shwi ();
1341 acs
.ovlsiz
[0] = (size
- maxobjsize
).to_shwi ();
1345 /* If both base objects aren't known return the maximum possible
1346 offset that would make them not overlap. */
1347 if (!dstref
->base
|| !srcref
->base
)
1350 /* If the base object is an array adjust the bounds of the offset
1351 to be non-negative and within the bounds of the array if possible. */
1352 clamp_offset (dstref
->base
, acs
.dstoff
, maxobjsize
);
1354 acs
.srcoff
[0] = srcref
->offrange
[0];
1355 acs
.srcoff
[1] = srcref
->offrange
[1];
1357 clamp_offset (srcref
->base
, acs
.srcoff
, maxobjsize
);
1359 /* When the upper bound of the offset is less than the lower bound
1360 the former is the result of a negative offset being represented
1361 as a large positive value or vice versa. The resulting range is
1362 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1363 a union is not representable using the current data structure
1364 replace it with the full range of offsets. */
1365 if (acs
.dstoff
[1] < acs
.dstoff
[0])
1367 acs
.dstoff
[0] = -maxobjsize
- 1;
1368 acs
.dstoff
[1] = maxobjsize
;
1371 /* Validate the offset and size of each reference on its own first.
1372 This is independent of whether or not the base objects are the
1373 same. Normally, this would have already been detected and
1374 diagnosed by -Warray-bounds, unless it has been disabled. */
1375 offset_int maxoff
= acs
.dstoff
[0] + dstref
->sizrange
[0];
1376 if (maxobjsize
< maxoff
)
1378 acs
.ovlsiz
[0] = (maxoff
- maxobjsize
).to_shwi ();
1379 acs
.ovloff
[0] = acs
.dstoff
[0].to_shwi () - acs
.ovlsiz
[0];
1383 /* Repeat the same as above but for the source offsets. */
1384 if (acs
.srcoff
[1] < acs
.srcoff
[0])
1386 acs
.srcoff
[0] = -maxobjsize
- 1;
1387 acs
.srcoff
[1] = maxobjsize
;
1390 maxoff
= acs
.srcoff
[0] + srcref
->sizrange
[0];
1391 if (maxobjsize
< maxoff
)
1393 acs
.ovlsiz
[0] = (maxoff
- maxobjsize
).to_shwi ();
1394 acs
.ovlsiz
[1] = (acs
.srcoff
[0] + srcref
->sizrange
[1]
1395 - maxobjsize
).to_shwi ();
1396 acs
.ovloff
[0] = acs
.srcoff
[0].to_shwi () - acs
.ovlsiz
[0];
1400 if (dstref
->base
!= srcref
->base
)
1403 acs
.dstsiz
[0] = dstref
->sizrange
[0];
1404 acs
.dstsiz
[1] = dstref
->sizrange
[1];
1406 acs
.srcsiz
[0] = srcref
->sizrange
[0];
1407 acs
.srcsiz
[1] = srcref
->sizrange
[1];
1409 /* Call the appropriate function to determine the overlap. */
1410 if ((this->*detect_overlap
) ())
1414 /* Unless the access size range has already been set, do so here. */
1415 sizrange
[0] = wi::smax (acs
.dstsiz
[0], srcref
->sizrange
[0]).to_shwi ();
1416 sizrange
[1] = wi::smax (acs
.dstsiz
[1], srcref
->sizrange
[1]).to_shwi ();
1424 /* Attempt to detect and diagnose an overlapping copy in a call expression
1425 EXPR involving an access ACS to a built-in memory or string function.
1426 Return true when one has been detected, false otherwise. */
1429 maybe_diag_overlap (location_t loc
, gimple
*call
, builtin_access
&acs
)
1431 if (!acs
.overlap ())
1434 if (warning_suppressed_p (call
, OPT_Wrestrict
))
1437 /* For convenience. */
1438 const builtin_memref
&dstref
= *acs
.dstref
;
1439 const builtin_memref
&srcref
= *acs
.srcref
;
1441 /* Determine the range of offsets and sizes of the overlap if it
1442 exists and issue diagnostics. */
1443 HOST_WIDE_INT
*ovloff
= acs
.ovloff
;
1444 HOST_WIDE_INT
*ovlsiz
= acs
.ovlsiz
;
1445 HOST_WIDE_INT
*sizrange
= acs
.sizrange
;
1447 tree func
= gimple_call_fndecl (call
);
1449 /* To avoid a combinatorial explosion of diagnostics format the offsets
1450 or their ranges as strings and use them in the warning calls below. */
1453 if (dstref
.offrange
[0] == dstref
.offrange
[1]
1454 || dstref
.offrange
[1] > HOST_WIDE_INT_MAX
)
1455 sprintf (offstr
[0], HOST_WIDE_INT_PRINT_DEC
,
1456 dstref
.offrange
[0].to_shwi ());
1459 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1460 dstref
.offrange
[0].to_shwi (),
1461 dstref
.offrange
[1].to_shwi ());
1463 if (srcref
.offrange
[0] == srcref
.offrange
[1]
1464 || srcref
.offrange
[1] > HOST_WIDE_INT_MAX
)
1466 HOST_WIDE_INT_PRINT_DEC
,
1467 srcref
.offrange
[0].to_shwi ());
1470 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1471 srcref
.offrange
[0].to_shwi (),
1472 srcref
.offrange
[1].to_shwi ());
1474 if (ovloff
[0] == ovloff
[1] || !ovloff
[1])
1475 sprintf (offstr
[2], HOST_WIDE_INT_PRINT_DEC
, ovloff
[0]);
1478 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1479 ovloff
[0], ovloff
[1]);
1481 const offset_int maxobjsize
= dstref
.maxobjsize
;
1482 bool must_overlap
= ovlsiz
[0] > 0;
1485 ovlsiz
[1] = ovlsiz
[0];
1489 /* Issue definitive "overlaps" diagnostic in this block. */
1491 if (sizrange
[0] == sizrange
[1])
1493 if (ovlsiz
[0] == ovlsiz
[1])
1494 warning_at (loc
, OPT_Wrestrict
,
1497 ? G_("%qD accessing %wu byte at offsets %s "
1498 "and %s overlaps %wu byte at offset %s")
1499 : G_("%qD accessing %wu byte at offsets %s "
1500 "and %s overlaps %wu bytes at offset "
1503 ? G_("%qD accessing %wu bytes at offsets %s "
1504 "and %s overlaps %wu byte at offset %s")
1505 : G_("%qD accessing %wu bytes at offsets %s "
1506 "and %s overlaps %wu bytes at offset "
1509 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1510 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1511 warning_n (loc
, OPT_Wrestrict
, sizrange
[0],
1512 "%qD accessing %wu byte at offsets %s "
1513 "and %s overlaps between %wu and %wu bytes "
1515 "%qD accessing %wu bytes at offsets %s "
1516 "and %s overlaps between %wu and %wu bytes "
1518 func
, sizrange
[0], offstr
[0], offstr
[1],
1519 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
1521 warning_n (loc
, OPT_Wrestrict
, sizrange
[0],
1522 "%qD accessing %wu byte at offsets %s and "
1523 "%s overlaps %wu or more bytes at offset %s",
1524 "%qD accessing %wu bytes at offsets %s and "
1525 "%s overlaps %wu or more bytes at offset %s",
1527 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1531 if (sizrange
[1] >= 0 && sizrange
[1] < maxobjsize
.to_shwi ())
1533 if (ovlsiz
[0] == ovlsiz
[1])
1534 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[0],
1535 "%qD accessing between %wu and %wu bytes "
1536 "at offsets %s and %s overlaps %wu byte at "
1538 "%qD accessing between %wu and %wu bytes "
1539 "at offsets %s and %s overlaps %wu bytes "
1541 func
, sizrange
[0], sizrange
[1],
1542 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1543 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1544 warning_at (loc
, OPT_Wrestrict
,
1545 "%qD accessing between %wu and %wu bytes at "
1546 "offsets %s and %s overlaps between %wu and %wu "
1547 "bytes at offset %s",
1548 func
, sizrange
[0], sizrange
[1],
1549 offstr
[0], offstr
[1], ovlsiz
[0], ovlsiz
[1],
1552 warning_at (loc
, OPT_Wrestrict
,
1553 "%qD accessing between %wu and %wu bytes at "
1554 "offsets %s and %s overlaps %wu or more bytes "
1556 func
, sizrange
[0], sizrange
[1],
1557 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1561 if (ovlsiz
[0] != ovlsiz
[1])
1562 ovlsiz
[1] = maxobjsize
.to_shwi ();
1564 if (ovlsiz
[0] == ovlsiz
[1])
1565 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[0],
1566 "%qD accessing %wu or more bytes at offsets "
1567 "%s and %s overlaps %wu byte at offset %s",
1568 "%qD accessing %wu or more bytes at offsets "
1569 "%s and %s overlaps %wu bytes at offset %s",
1570 func
, sizrange
[0], offstr
[0], offstr
[1],
1571 ovlsiz
[0], offstr
[2]);
1572 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1573 warning_at (loc
, OPT_Wrestrict
,
1574 "%qD accessing %wu or more bytes at offsets %s "
1575 "and %s overlaps between %wu and %wu bytes "
1577 func
, sizrange
[0], offstr
[0], offstr
[1],
1578 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
1580 warning_at (loc
, OPT_Wrestrict
,
1581 "%qD accessing %wu or more bytes at offsets %s "
1582 "and %s overlaps %wu or more bytes at offset %s",
1583 func
, sizrange
[0], offstr
[0], offstr
[1],
1584 ovlsiz
[0], offstr
[2]);
1588 /* Use more concise wording when one of the offsets is unbounded
1589 to avoid confusing the user with large and mostly meaningless
1592 if (DECL_P (dstref
.base
) && TREE_CODE (TREE_TYPE (dstref
.base
)) == ARRAY_TYPE
)
1593 open_range
= ((dstref
.offrange
[0] == 0
1594 && dstref
.offrange
[1] == maxobjsize
)
1595 || (srcref
.offrange
[0] == 0
1596 && srcref
.offrange
[1] == maxobjsize
));
1598 open_range
= ((dstref
.offrange
[0] == -maxobjsize
- 1
1599 && dstref
.offrange
[1] == maxobjsize
)
1600 || (srcref
.offrange
[0] == -maxobjsize
- 1
1601 && srcref
.offrange
[1] == maxobjsize
));
1603 if (sizrange
[0] == sizrange
[1] || sizrange
[1] == 1)
1608 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1609 "%qD accessing %wu byte may overlap "
1611 "%qD accessing %wu bytes may overlap "
1613 func
, sizrange
[1], ovlsiz
[1]);
1615 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1616 "%qD accessing %wu byte at offsets %s "
1617 "and %s may overlap %wu byte at offset %s",
1618 "%qD accessing %wu bytes at offsets %s "
1619 "and %s may overlap %wu byte at offset %s",
1620 func
, sizrange
[1], offstr
[0], offstr
[1],
1621 ovlsiz
[1], offstr
[2]);
1626 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1627 "%qD accessing %wu byte may overlap "
1629 "%qD accessing %wu bytes may overlap "
1631 func
, sizrange
[1], ovlsiz
[1]);
1633 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1634 "%qD accessing %wu byte at offsets %s and "
1635 "%s may overlap up to %wu bytes at offset %s",
1636 "%qD accessing %wu bytes at offsets %s and "
1637 "%s may overlap up to %wu bytes at offset %s",
1638 func
, sizrange
[1], offstr
[0], offstr
[1],
1639 ovlsiz
[1], offstr
[2]);
1643 if (sizrange
[1] >= 0 && sizrange
[1] < maxobjsize
.to_shwi ())
1646 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1647 "%qD accessing between %wu and %wu bytes "
1648 "may overlap %wu byte",
1649 "%qD accessing between %wu and %wu bytes "
1650 "may overlap up to %wu bytes",
1651 func
, sizrange
[0], sizrange
[1], ovlsiz
[1]);
1653 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1654 "%qD accessing between %wu and %wu bytes "
1655 "at offsets %s and %s may overlap %wu byte "
1657 "%qD accessing between %wu and %wu bytes "
1658 "at offsets %s and %s may overlap up to %wu "
1659 "bytes at offset %s",
1660 func
, sizrange
[0], sizrange
[1],
1661 offstr
[0], offstr
[1], ovlsiz
[1], offstr
[2]);
1665 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1666 "%qD accessing %wu or more bytes at offsets %s "
1667 "and %s may overlap %wu byte at offset %s",
1668 "%qD accessing %wu or more bytes at offsets %s "
1669 "and %s may overlap up to %wu bytes at offset %s",
1670 func
, sizrange
[0], offstr
[0], offstr
[1],
1671 ovlsiz
[1], offstr
[2]);
1676 /* Validate REF size and offsets in an expression passed as an argument
1677 to a CALL to a built-in function FUNC to make sure they are within
1678 the bounds of the referenced object if its size is known, or
1679 PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1680 be issued, false otherwise.
1681 Both initial values of the offsets and their final value computed
1682 by the function by incrementing the initial value by the size are
1683 validated. Return the warning number if the offsets are not valid
1684 and a diagnostic has been issued, or would have been issued if
1685 DO_WARN had been true, otherwise an invalid warning number. */
1688 maybe_diag_access_bounds (gimple
*call
, tree func
, int strict
,
1689 const builtin_memref
&ref
, offset_int wroff
,
1692 location_t loc
= gimple_location (call
);
1693 const offset_int maxobjsize
= ref
.maxobjsize
;
1695 /* Check for excessive size first and regardless of warning options
1696 since the result is used to make codegen decisions. */
1697 if (ref
.sizrange
[0] > maxobjsize
)
1699 const opt_code opt
= OPT_Wstringop_overflow_
;
1700 /* Return true without issuing a warning. */
1704 if (ref
.ref
&& warning_suppressed_p (ref
.ref
, OPT_Wstringop_overflow_
))
1707 bool warned
= false;
1708 if (warn_stringop_overflow
)
1710 if (ref
.sizrange
[0] == ref
.sizrange
[1])
1711 warned
= warning_at (loc
, opt
,
1712 "%qD specified bound %wu "
1713 "exceeds maximum object size %wu",
1714 func
, ref
.sizrange
[0].to_uhwi (),
1715 maxobjsize
.to_uhwi ());
1717 warned
= warning_at (loc
, opt
,
1718 "%qD specified bound between %wu and %wu "
1719 "exceeds maximum object size %wu",
1720 func
, ref
.sizrange
[0].to_uhwi (),
1721 ref
.sizrange
[1].to_uhwi (),
1722 maxobjsize
.to_uhwi ());
1723 return warned
? opt
: no_warning
;
1727 /* Check for out-bounds pointers regardless of warning options since
1728 the result is used to make codegen decisions. An excessive WROFF
1729 can only come up as a result of an invalid strncat bound and is
1730 diagnosed separately using a more meaningful warning. */
1731 if (maxobjsize
< wroff
)
1733 offset_int ooboff
[] = { ref
.offrange
[0], ref
.offrange
[1], wroff
};
1734 tree oobref
= ref
.offset_out_of_bounds (strict
, ooboff
);
1738 const opt_code opt
= OPT_Warray_bounds
;
1739 /* Return true without issuing a warning. */
1743 if (!warn_array_bounds
)
1746 if (warning_suppressed_p (ref
.ptr
, opt
)
1747 || (ref
.ref
&& warning_suppressed_p (ref
.ref
, opt
)))
1750 char rangestr
[2][64];
1751 if (ooboff
[0] == ooboff
[1]
1752 || (ooboff
[0] != ref
.offrange
[0]
1753 && ooboff
[0].to_shwi () >= ooboff
[1].to_shwi ()))
1754 sprintf (rangestr
[0], "%lli", (long long) ooboff
[0].to_shwi ());
1756 sprintf (rangestr
[0], "[%lli, %lli]",
1757 (long long) ooboff
[0].to_shwi (),
1758 (long long) ooboff
[1].to_shwi ());
1760 bool warned
= false;
1762 if (oobref
== error_mark_node
)
1764 if (ref
.sizrange
[0] == ref
.sizrange
[1])
1765 sprintf (rangestr
[1], "%llu",
1766 (unsigned long long) ref
.sizrange
[0].to_shwi ());
1768 sprintf (rangestr
[1], "[%lli, %lli]",
1769 (unsigned long long) ref
.sizrange
[0].to_uhwi (),
1770 (unsigned long long) ref
.sizrange
[1].to_uhwi ());
1774 if (DECL_P (ref
.base
)
1775 && TREE_CODE (type
= TREE_TYPE (ref
.base
)) == ARRAY_TYPE
)
1777 auto_diagnostic_group d
;
1778 if (warning_at (loc
, opt
,
1779 "%qD pointer overflow between offset %s "
1780 "and size %s accessing array %qD with type %qT",
1781 func
, rangestr
[0], rangestr
[1], ref
.base
, type
))
1783 inform (DECL_SOURCE_LOCATION (ref
.base
),
1784 "array %qD declared here", ref
.base
);
1788 warned
= warning_at (loc
, opt
,
1789 "%qD pointer overflow between offset %s "
1791 func
, rangestr
[0], rangestr
[1]);
1794 warned
= warning_at (loc
, opt
,
1795 "%qD pointer overflow between offset %s "
1797 func
, rangestr
[0], rangestr
[1]);
1799 else if (oobref
== ref
.base
)
1801 /* True when the offset formed by an access to the reference
1802 is out of bounds, rather than the initial offset wich is
1803 in bounds. This implies access past the end. */
1804 bool form
= ooboff
[0] != ref
.offrange
[0];
1806 if (DECL_P (ref
.base
))
1808 auto_diagnostic_group d
;
1809 if ((ref
.basesize
< maxobjsize
1810 && warning_at (loc
, opt
,
1812 ? G_("%qD forming offset %s is out of "
1813 "the bounds [0, %wu] of object %qD with "
1815 : G_("%qD offset %s is out of the bounds "
1816 "[0, %wu] of object %qD with type %qT"),
1817 func
, rangestr
[0], ref
.basesize
.to_uhwi (),
1818 ref
.base
, TREE_TYPE (ref
.base
)))
1819 || warning_at (loc
, opt
,
1821 ? G_("%qD forming offset %s is out of "
1822 "the bounds of object %qD with type %qT")
1823 : G_("%qD offset %s is out of the bounds "
1824 "of object %qD with type %qT"),
1826 ref
.base
, TREE_TYPE (ref
.base
)))
1828 inform (DECL_SOURCE_LOCATION (ref
.base
),
1829 "%qD declared here", ref
.base
);
1833 else if (ref
.basesize
< maxobjsize
)
1834 warned
= warning_at (loc
, opt
,
1836 ? G_("%qD forming offset %s is out "
1837 "of the bounds [0, %wu]")
1838 : G_("%qD offset %s is out "
1839 "of the bounds [0, %wu]"),
1840 func
, rangestr
[0], ref
.basesize
.to_uhwi ());
1842 warned
= warning_at (loc
, opt
,
1844 ? G_("%qD forming offset %s is out of bounds")
1845 : G_("%qD offset %s is out of bounds"),
1848 else if (TREE_CODE (ref
.ref
) == MEM_REF
)
1850 tree refop
= TREE_OPERAND (ref
.ref
, 0);
1851 tree type
= TREE_TYPE (refop
);
1852 if (POINTER_TYPE_P (type
))
1853 type
= TREE_TYPE (type
);
1854 type
= TYPE_MAIN_VARIANT (type
);
1856 if (warning_at (loc
, opt
,
1857 "%qD offset %s from the object at %qE is out "
1858 "of the bounds of %qT",
1859 func
, rangestr
[0], ref
.base
, type
))
1861 if (TREE_CODE (ref
.ref
) == COMPONENT_REF
)
1862 refop
= TREE_OPERAND (ref
.ref
, 1);
1864 inform (DECL_SOURCE_LOCATION (refop
),
1865 "subobject %qD declared here", refop
);
1871 tree refop
= TREE_OPERAND (ref
.ref
, 0);
1872 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (ref
.ref
));
1874 if (warning_at (loc
, opt
,
1875 "%qD offset %s from the object at %qE is out "
1876 "of the bounds of referenced subobject %qD with "
1877 "type %qT at offset %wi",
1878 func
, rangestr
[0], ref
.base
,
1879 TREE_OPERAND (ref
.ref
, 1), type
,
1880 ref
.refoff
.to_shwi ()))
1882 if (TREE_CODE (ref
.ref
) == COMPONENT_REF
)
1883 refop
= TREE_OPERAND (ref
.ref
, 1);
1885 inform (DECL_SOURCE_LOCATION (refop
),
1886 "subobject %qD declared here", refop
);
1891 return warned
? opt
: no_warning
;
1894 /* Check a CALL statement for restrict-violations and issue warnings
1895 if/when appropriate. */
1898 check_call (range_query
*query
, gimple
*call
)
1900 /* Avoid checking the call if it has already been diagnosed for
1902 if (warning_suppressed_p (call
, OPT_Wrestrict
))
1905 tree func
= gimple_call_fndecl (call
);
1906 if (!func
|| !fndecl_built_in_p (func
, BUILT_IN_NORMAL
))
1909 /* Argument number to extract from the call (depends on the built-in
1911 unsigned dst_idx
= -1;
1912 unsigned src_idx
= -1;
1913 unsigned bnd_idx
= -1;
1915 /* Is this CALL to a string function (as opposed to one to a raw
1916 memory function). */
1919 switch (DECL_FUNCTION_CODE (func
))
1921 case BUILT_IN_MEMCPY
:
1922 case BUILT_IN_MEMCPY_CHK
:
1923 case BUILT_IN_MEMPCPY
:
1924 case BUILT_IN_MEMPCPY_CHK
:
1925 case BUILT_IN_MEMMOVE
:
1926 case BUILT_IN_MEMMOVE_CHK
:
1930 case BUILT_IN_STPNCPY
:
1931 case BUILT_IN_STPNCPY_CHK
:
1932 case BUILT_IN_STRNCAT
:
1933 case BUILT_IN_STRNCAT_CHK
:
1934 case BUILT_IN_STRNCPY
:
1935 case BUILT_IN_STRNCPY_CHK
:
1941 case BUILT_IN_MEMSET
:
1942 case BUILT_IN_MEMSET_CHK
:
1947 case BUILT_IN_STPCPY
:
1948 case BUILT_IN_STPCPY_CHK
:
1949 case BUILT_IN_STRCPY
:
1950 case BUILT_IN_STRCPY_CHK
:
1951 case BUILT_IN_STRCAT
:
1952 case BUILT_IN_STRCAT_CHK
:
1958 /* Handle other string functions here whose access may need
1959 to be validated for in-bounds offsets and non-overlapping
1964 unsigned nargs
= gimple_call_num_args (call
);
1966 tree dst
= dst_idx
< nargs
? gimple_call_arg (call
, dst_idx
) : NULL_TREE
;
1967 tree src
= src_idx
< nargs
? gimple_call_arg (call
, src_idx
) : NULL_TREE
;
1968 tree dstwr
= bnd_idx
< nargs
? gimple_call_arg (call
, bnd_idx
) : NULL_TREE
;
1970 /* For string functions with an unspecified or unknown bound,
1971 assume the size of the access is one. */
1972 if (!dstwr
&& strfun
)
1973 dstwr
= size_one_node
;
1975 /* DST and SRC can be null for a call with an insufficient number
1976 of arguments to a built-in function declared without a protype. */
1977 if (!dst
|| (src_idx
< nargs
&& !src
))
1980 /* DST, SRC, or DSTWR can also have the wrong type in a call to
1981 a function declared without a prototype. Avoid checking such
1983 if (TREE_CODE (TREE_TYPE (dst
)) != POINTER_TYPE
1984 || (src
&& TREE_CODE (TREE_TYPE (src
)) != POINTER_TYPE
)
1985 || (dstwr
&& !INTEGRAL_TYPE_P (TREE_TYPE (dstwr
))))
1988 opt_code opt
= check_bounds_or_overlap (query
, call
, dst
, src
, dstwr
,
1990 /* Avoid diagnosing the call again. */
1991 suppress_warning (call
, opt
);
1994 } /* anonymous namespace */
1996 /* Attempt to detect and diagnose invalid offset bounds and (except for
1997 memmove) overlapping copy in a call expression EXPR from SRC to DST
1998 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
1999 SRCSIZE may be NULL. DO_WARN is false to detect either problem
2000 without issue a warning. Return the OPT_Wxxx constant corresponding
2001 to the warning if one has been detected and zero otherwise. */
2004 check_bounds_or_overlap (gimple
*call
, tree dst
, tree src
, tree dstsize
,
2005 tree srcsize
, bool bounds_only
/* = false */,
2006 bool do_warn
/* = true */)
2008 return check_bounds_or_overlap (/*range_query=*/NULL
,
2009 call
, dst
, src
, dstsize
, srcsize
,
2010 bounds_only
, do_warn
);
2014 check_bounds_or_overlap (range_query
*query
,
2015 gimple
*call
, tree dst
, tree src
, tree dstsize
,
2016 tree srcsize
, bool bounds_only
/* = false */,
2017 bool do_warn
/* = true */)
2019 tree func
= gimple_call_fndecl (call
);
2021 builtin_memref
dstref (query
, call
, dst
, dstsize
);
2022 builtin_memref
srcref (query
, call
, src
, srcsize
);
2024 /* Create a descriptor of the access. This may adjust both DSTREF
2025 and SRCREF based on one another and the kind of the access. */
2026 builtin_access
acs (query
, call
, dstref
, srcref
);
2028 /* Set STRICT to the value of the -Warray-bounds=N argument for
2029 string functions or when N > 1. */
2030 int strict
= (acs
.strict () || warn_array_bounds
> 1 ? warn_array_bounds
: 0);
2032 /* The starting offset of the destination write access. Nonzero only
2033 for the strcat family of functions. */
2034 offset_int wroff
= acs
.write_off (dstsize
);
2036 /* Validate offsets to each reference before the access first to make
2037 sure they are within the bounds of the destination object if its
2038 size is known, or PTRDIFF_MAX otherwise. */
2040 = maybe_diag_access_bounds (call
, func
, strict
, dstref
, wroff
, do_warn
);
2041 if (opt
== no_warning
)
2042 opt
= maybe_diag_access_bounds (call
, func
, strict
, srcref
, 0, do_warn
);
2044 if (opt
!= no_warning
)
2047 suppress_warning (call
, opt
);
2051 if (!warn_restrict
|| bounds_only
|| !src
)
2056 switch (DECL_FUNCTION_CODE (func
))
2058 case BUILT_IN_MEMMOVE
:
2059 case BUILT_IN_MEMMOVE_CHK
:
2060 case BUILT_IN_MEMSET
:
2061 case BUILT_IN_MEMSET_CHK
:
2068 location_t loc
= gimple_location (call
);
2069 if (operand_equal_p (dst
, src
, 0))
2071 /* Issue -Wrestrict unless the pointers are null (those do
2072 not point to objects and so do not indicate an overlap;
2073 such calls could be the result of sanitization and jump
2075 if (!integer_zerop (dst
) && !warning_suppressed_p (call
, OPT_Wrestrict
))
2077 warning_at (loc
, OPT_Wrestrict
,
2078 "%qD source argument is the same as destination",
2080 suppress_warning (call
, OPT_Wrestrict
);
2081 return OPT_Wrestrict
;
2087 /* Return false when overlap has been detected. */
2088 if (maybe_diag_overlap (loc
, call
, acs
))
2090 suppress_warning (call
, OPT_Wrestrict
);
2091 return OPT_Wrestrict
;
2098 make_pass_warn_restrict (gcc::context
*ctxt
)
2100 return new pass_wrestrict (ctxt
);
2104 dump_builtin_memref (FILE *fp
, const builtin_memref
&ref
)
2106 fprintf (fp
, "\n ptr = ");
2107 print_generic_expr (fp
, ref
.ptr
, TDF_LINENO
);
2108 fprintf (fp
, "\n ref = ");
2110 print_generic_expr (fp
, ref
.ref
, TDF_LINENO
);
2113 fprintf (fp
, "\n base = ");
2114 print_generic_expr (fp
, ref
.base
, TDF_LINENO
);
2116 "\n basesize = %lli"
2119 "\n offrange = [%lli, %lli]"
2120 "\n sizrange = [%lli, %lli]"
2121 "\n strbounded_p = %s\n",
2122 (long long)ref
.basesize
.to_shwi (),
2123 (long long)ref
.refsize
.to_shwi (),
2124 (long long)ref
.refoff
.to_shwi (),
2125 (long long)ref
.offrange
[0].to_shwi (),
2126 (long long)ref
.offrange
[1].to_shwi (),
2127 (long long)ref
.sizrange
[0].to_shwi (),
2128 (long long)ref
.sizrange
[1].to_shwi (),
2129 ref
.strbounded_p
? "true" : "false");
2133 builtin_access::dump (FILE *fp
) const
2135 fprintf (fp
, " dstref:");
2136 dump_builtin_memref (fp
, *dstref
);
2137 fprintf (fp
, "\n srcref:");
2138 dump_builtin_memref (fp
, *srcref
);
2141 " sizrange = [%lli, %lli]\n"
2142 " ovloff = [%lli, %lli]\n"
2143 " ovlsiz = [%lli, %lli]\n"
2144 " dstoff = [%lli, %lli]\n"
2145 " dstsiz = [%lli, %lli]\n"
2146 " srcoff = [%lli, %lli]\n"
2147 " srcsiz = [%lli, %lli]\n",
2148 (long long)sizrange
[0], (long long)sizrange
[1],
2149 (long long)ovloff
[0], (long long)ovloff
[1],
2150 (long long)ovlsiz
[0], (long long)ovlsiz
[1],
2151 (long long)dstoff
[0].to_shwi (), (long long)dstoff
[1].to_shwi (),
2152 (long long)dstsiz
[0].to_shwi (), (long long)dstsiz
[1].to_shwi (),
2153 (long long)srcoff
[0].to_shwi (), (long long)srcoff
[1].to_shwi (),
2154 (long long)srcsiz
[0].to_shwi (), (long long)srcsiz
[1].to_shwi ());
2158 dump_builtin_access (FILE *fp
, gimple
*stmt
, const builtin_access
&acs
)
2162 fprintf (fp
, "\nDumping builtin_access for ");
2163 print_gimple_expr (fp
, stmt
, TDF_LINENO
);
2171 debug (gimple
*stmt
, const builtin_access
&acs
)
2173 dump_builtin_access (stdout
, stmt
, acs
);