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"
29 #include "pointer-query.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"
40 #include "tree-object-size.h"
44 #include "gimple-range.h"
48 const pass_data pass_data_wrestrict
= {
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
65 pass_wrestrict (gcc::context
*ctxt
)
66 : gimple_opt_pass (pass_data_wrestrict
, ctxt
)
69 opt_pass
*clone () { return new pass_wrestrict (m_ctxt
); }
71 virtual bool gate (function
*);
72 virtual unsigned int execute (function
*);
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
*);
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
);
90 gimple
*stmt
= gsi_stmt (si
);
91 if (!is_gimple_call (stmt
))
94 check_call (query
, stmt
);
99 pass_wrestrict::execute (function
*fun
)
101 gimple_ranger ranger
;
103 FOR_EACH_BB_FN (bb
, fun
)
104 wrestrict_walk (&ranger
, bb
);
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. */
115 /* The original pointer argument to the built-in function. */
117 /* The referenced subobject or NULL if not available, and the base
118 object of the memory reference or NULL. */
122 /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
123 and negative until (possibly lazily) initialized. */
125 /* Same for the subobject. */
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. */
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. */
148 builtin_memref (range_query
*, gimple
*, tree
, tree
);
150 tree
offset_out_of_bounds (int, offset_int
[3]) const;
153 /* Call statement to the built-in. */
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. */
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. */
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. */
195 offset_int
write_off (tree
) const;
197 void dump (FILE *) const;
200 /* Implementation functions used to determine overlap. */
201 bool generic_overlap ();
202 bool strcat_overlap ();
203 bool strcpy_overlap ();
210 offset_int
overlap_size (const offset_int
[2], const offset_int
[2],
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
,
235 refoff (HOST_WIDE_INT_MIN
),
238 maxobjsize (tree_to_shwi (max_object_size ())),
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;
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
);
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
;
269 sizrange
[1] = maxobjsize
;
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)
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)
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
)
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. */
319 builtin_memref::extend_offset_range (tree offset
)
321 if (TREE_CODE (offset
) == INTEGER_CST
)
323 offset_int off
= int_cst_value (offset
);
332 if (TREE_CODE (offset
) == SSA_NAME
)
334 /* A pointer offset is represented as sizetype but treated
337 value_range_kind rng
;
339 if (query
&& query
->range_of_expr (vr
, offset
, stmt
))
342 if (!vr
.undefined_p ())
344 min
= wi::to_wide (vr
.min ());
345 max
= wi::to_wide (vr
.max ());
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
);
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
);
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
378 offrange
[0] += offset_int::from (min
, SIGNED
);
379 offrange
[1] += offset_int::from (max
, SIGNED
);
383 /* Handle an anti-range the same as no range at all. */
384 gimple
*stmt
= SSA_NAME_DEF_STMT (offset
);
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
));
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. */
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
);
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
);
440 else if (code
== POINTER_PLUS_EXPR
)
442 expr
= gimple_assign_rhs1 (stmt
);
443 offset
= gimple_assign_rhs2 (stmt
);
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); */
464 if (TREE_CODE (expr
) == ADDR_EXPR
)
465 expr
= TREE_OPERAND (expr
, 0);
467 /* Stash the reference for offset validation. */
470 poly_int64 bitsize
, bitpos
;
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
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
);
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
495 if (bytepos
.is_constant (&cstoff
))
497 offrange
[0] += cstoff
;
498 offrange
[1] += cstoff
;
500 /* Besides the reference saved above, also stash the offset
502 if (TREE_CODE (expr
) == COMPONENT_REF
)
506 offrange
[1] += maxobjsize
;
510 if (TREE_CODE (var_off
) == INTEGER_CST
)
512 cstoff
= wi::to_offset (var_off
);
513 offrange
[0] += cstoff
;
514 offrange
[1] += cstoff
;
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
);
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. */
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
569 builtin_memref::offset_out_of_bounds (int strict
, offset_int ooboff
[3]) const
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. */
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]);
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
;
604 const bool decl_p
= DECL_P (obj
);
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. */
624 && TREE_CODE (ref
) == COMPONENT_REF
)
626 /* If REFOFF is negative, SIZE will become negative here. */
627 size
= refoff
+ refsize
;
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
)
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
643 endoff
= offrng
[lob
] + sizrange
[0];
644 if (endoff
> maxobjsize
)
645 return error_mark_node
;
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
;
662 /* Set the out-of-bounds offset range to be one greater than
663 that delimited by the reference including its size. */
666 if (endoff
> ooboff
[lob
])
667 ooboff
[hib
] = endoff
- 1;
669 ooboff
[hib
] = offrng
[lob
] + sizrange
[1];
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
,
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. */
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
:
716 detect_overlap
= &builtin_access::generic_overlap
;
719 case BUILT_IN_MEMMOVE
:
720 case BUILT_IN_MEMMOVE_CHK
:
721 /* For memmove there is never any overlap to check for. */
724 detect_overlap
= &builtin_access::no_overlap
;
727 case BUILT_IN_MEMSET
:
728 case BUILT_IN_MEMSET_CHK
:
729 /* For memset there is never any overlap to check for. */
732 detect_overlap
= &builtin_access::no_overlap
;
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
;
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
;
750 case BUILT_IN_STRCAT
:
751 case BUILT_IN_STRCAT_CHK
:
752 detect_overlap
= &builtin_access::strcat_overlap
;
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
;
763 /* Handle other string functions here whose access may need
764 to be validated for in-bounds offsets and non-overlapping
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. */
774 if (dst
.basesize
< 0)
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
;
785 dst
.basesize
= maxobjsize
;
788 if (src
.base
&& src
.basesize
< 0)
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
;
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
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
)
815 tree size
= gimple_call_arg (call
, sizeargno
);
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
845 dstref
->sizrange
[0] = srcref
->sizrange
[0];
846 dstref
->sizrange
[1] = srcref
->sizrange
[1];
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];
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
871 if (srcref
->offrange
[1] >= 0
872 && srcref
->offrange
[1] < srcref
->sizrange
[0])
873 srcref
->sizrange
[0] -= srcref
->offrange
[1];
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];
882 srcref
->sizrange
[1] = 0;
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];
938 builtin_access::overlap_size (const offset_int a
[2], const offset_int b
[2],
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]))
957 return wi::smin (p
[1], q
[1]) - q
[0];
967 /* Return true if the bounded mempry (memcpy amd similar) or string function
968 access (strncpy and similar) ACS overlaps. */
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
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)
1017 space
[1] = acs
.dstsiz
[1];
1019 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
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
)
1034 bool overlap_certain
= space
[1] < acs
.dstsiz
[0];
1036 /* True when the size of one reference depends on the offset of
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. */
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
);
1054 while (TREE_CODE (basetype
) == ARRAY_TYPE
)
1055 basetype
= TREE_TYPE (basetype
);
1057 if (RECORD_OR_UNION_TYPE_P (basetype
))
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
))
1071 offset_int siz
[2] = { maxobjsize
+ 1, 0 };
1073 ovloff
[0] = HOST_WIDE_INT_MAX
;
1074 ovloff
[1] = HOST_WIDE_INT_MIN
;
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
]
1092 offset_int sz
= overlap_size (a
, b
, &off
);
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 ();
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
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
]
1130 offset_int sz
= overlap_size (a
, b
, &off
);
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;
1158 /* Return true if the strcat-like access overlaps. */
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
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;
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
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];
1211 space
= acs
.dstoff
[1] + acs
.dstsiz
[0] - acs
.srcoff
[0];
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])
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]);
1240 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
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
))
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;
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 ();
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];
1272 = wi::smin (maxobjsize
,
1273 srcref
->offrange
[1] + srcref
->sizrange
[1]).to_shwi ();
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 ();
1286 /* Return true if the strcpy-like access overlaps. */
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. */
1298 clamp_offset (tree base
, offset_int refoff
[2], offset_int maxobjsize
)
1300 if (!base
|| TREE_CODE (TREE_TYPE (base
)) != ARRAY_TYPE
)
1303 if (refoff
[0] < 0 && refoff
[1] >= 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),
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 ();
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
)
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];
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];
1401 if (dstref
->base
!= srcref
->base
)
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
) ())
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 ();
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. */
1430 maybe_diag_overlap (location_t loc
, gimple
*call
, builtin_access
&acs
)
1432 if (!acs
.overlap ())
1435 if (warning_suppressed_p (call
, OPT_Wrestrict
))
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. */
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 ());
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
)
1467 HOST_WIDE_INT_PRINT_DEC
,
1468 srcref
.offrange
[0].to_shwi ());
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]);
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;
1486 ovlsiz
[1] = ovlsiz
[0];
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
,
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 "
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 "
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 "
1516 "%qD accessing %wu bytes at offsets %s "
1517 "and %s overlaps between %wu and %wu bytes "
1519 func
, sizrange
[0], offstr
[0], offstr
[1],
1520 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
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",
1528 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
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 "
1539 "%qD accessing between %wu and %wu bytes "
1540 "at offsets %s and %s overlaps %wu bytes "
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],
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 "
1557 func
, sizrange
[0], sizrange
[1],
1558 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
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 "
1578 func
, sizrange
[0], offstr
[0], offstr
[1],
1579 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
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]);
1589 /* Use more concise wording when one of the offsets is unbounded
1590 to avoid confusing the user with large and mostly meaningless
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
));
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)
1609 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1610 "%qD accessing %wu byte may overlap "
1612 "%qD accessing %wu bytes may overlap "
1614 func
, sizrange
[1], ovlsiz
[1]);
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]);
1627 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1628 "%qD accessing %wu byte may overlap "
1630 "%qD accessing %wu bytes may overlap "
1632 func
, sizrange
[1], ovlsiz
[1]);
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]);
1644 if (sizrange
[1] >= 0 && sizrange
[1] < maxobjsize
.to_shwi ())
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]);
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 "
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]);
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]);
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. */
1689 maybe_diag_access_bounds (gimple
*call
, tree func
, int strict
,
1690 const builtin_memref
&ref
, offset_int wroff
,
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. */
1705 if (ref
.ref
&& warning_suppressed_p (ref
.ref
, OPT_Wstringop_overflow_
))
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 ());
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
)
1734 offset_int ooboff
[] = { ref
.offrange
[0], ref
.offrange
[1], wroff
};
1735 tree oobref
= ref
.offset_out_of_bounds (strict
, ooboff
);
1739 const opt_code opt
= OPT_Warray_bounds
;
1740 /* Return true without issuing a warning. */
1744 if (!warn_array_bounds
)
1747 if (warning_suppressed_p (ref
.ptr
, opt
)
1748 || (ref
.ref
&& warning_suppressed_p (ref
.ref
, opt
)))
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 ());
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 ());
1769 sprintf (rangestr
[1], "[%lli, %lli]",
1770 (unsigned long long) ref
.sizrange
[0].to_uhwi (),
1771 (unsigned long long) ref
.sizrange
[1].to_uhwi ());
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
);
1789 warned
= warning_at (loc
, opt
,
1790 "%qD pointer overflow between offset %s "
1792 func
, rangestr
[0], rangestr
[1]);
1795 warned
= warning_at (loc
, opt
,
1796 "%qD pointer overflow between offset %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
,
1813 ? G_("%qD forming offset %s is out of "
1814 "the bounds [0, %wu] of object %qD with "
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
,
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"),
1827 ref
.base
, TREE_TYPE (ref
.base
)))
1829 inform (DECL_SOURCE_LOCATION (ref
.base
),
1830 "%qD declared here", ref
.base
);
1834 else if (ref
.basesize
< maxobjsize
)
1835 warned
= warning_at (loc
, opt
,
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 ());
1843 warned
= warning_at (loc
, opt
,
1845 ? G_("%qD forming offset %s is out of bounds")
1846 : G_("%qD offset %s is out of bounds"),
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);
1865 inform (DECL_SOURCE_LOCATION (refop
),
1866 "subobject %qD declared here", refop
);
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);
1886 inform (DECL_SOURCE_LOCATION (refop
),
1887 "subobject %qD declared here", refop
);
1892 return warned
? opt
: no_warning
;
1895 /* Check a CALL statement for restrict-violations and issue warnings
1896 if/when appropriate. */
1899 check_call (range_query
*query
, gimple
*call
)
1901 /* Avoid checking the call if it has already been diagnosed for
1903 if (warning_suppressed_p (call
, OPT_Wrestrict
))
1906 tree func
= gimple_call_fndecl (call
);
1907 if (!func
|| !fndecl_built_in_p (func
, BUILT_IN_NORMAL
))
1910 /* Argument number to extract from the call (depends on the built-in
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). */
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
:
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
:
1942 case BUILT_IN_MEMSET
:
1943 case BUILT_IN_MEMSET_CHK
:
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
:
1959 /* Handle other string functions here whose access may need
1960 to be validated for in-bounds offsets and non-overlapping
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
))
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
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
))))
1989 opt_code opt
= check_bounds_or_overlap (query
, call
, dst
, src
, dstwr
,
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. */
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
);
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. */
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
)
2048 suppress_warning (call
, opt
);
2052 if (!warn_restrict
|| bounds_only
|| !src
)
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
:
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
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",
2081 suppress_warning (call
, OPT_Wrestrict
);
2082 return OPT_Wrestrict
;
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
;
2099 make_pass_warn_restrict (gcc::context
*ctxt
)
2101 return new pass_wrestrict (ctxt
);
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 = ");
2111 print_generic_expr (fp
, ref
.ref
, TDF_LINENO
);
2114 fprintf (fp
, "\n base = ");
2115 print_generic_expr (fp
, ref
.base
, TDF_LINENO
);
2117 "\n basesize = %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");
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
);
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 ());
2159 dump_builtin_access (FILE *fp
, gimple
*stmt
, const builtin_access
&acs
)
2163 fprintf (fp
, "\nDumping builtin_access for ");
2164 print_gimple_expr (fp
, stmt
, TDF_LINENO
);
2172 debug (gimple
*stmt
, const builtin_access
&acs
)
2174 dump_builtin_access (stdout
, stmt
, acs
);