1 /* Pass to detect and issue warnings for violations of the restrict
3 Copyright (C) 2017-2020 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 rng
= get_range_info (offset
, &min
, &max
);
354 if (rng
== VR_ANTI_RANGE
&& wi::lts_p (max
, min
))
356 /* Convert an anti-range whose upper bound is less than
357 its lower bound to a signed range. */
358 offrange
[0] += offset_int::from (max
+ 1, SIGNED
);
359 offrange
[1] += offset_int::from (min
- 1, SIGNED
);
364 && (DECL_P (base
) || wi::lts_p (min
, max
)))
366 /* Preserve the bounds of the range for an offset into
367 a known object (it may be adjusted later relative to
368 a constant offset from its beginning). Otherwise use
369 the bounds only when they are ascending when treated
371 offrange
[0] += offset_int::from (min
, SIGNED
);
372 offrange
[1] += offset_int::from (max
, SIGNED
);
376 /* Handle an anti-range the same as no range at all. */
377 gimple
*stmt
= SSA_NAME_DEF_STMT (offset
);
379 if (is_gimple_assign (stmt
)
380 && (type
= TREE_TYPE (gimple_assign_rhs1 (stmt
)))
381 && INTEGRAL_TYPE_P (type
))
383 tree_code code
= gimple_assign_rhs_code (stmt
);
384 if (code
== NOP_EXPR
)
386 /* Use the bounds of the type of the NOP_EXPR operand
387 even if it's signed. The result doesn't trigger
388 warnings but makes their output more readable. */
389 offrange
[0] += wi::to_offset (TYPE_MIN_VALUE (type
));
390 offrange
[1] += wi::to_offset (TYPE_MAX_VALUE (type
));
396 const offset_int maxoff
= tree_to_shwi (max_object_size ()) >> 1;
397 const offset_int minoff
= -maxoff
- 1;
399 offrange
[0] += minoff
;
400 offrange
[1] += maxoff
;
403 /* Determines the base object or pointer of the reference EXPR
404 and the offset range from the beginning of the base. */
407 builtin_memref::set_base_and_offset (tree expr
)
409 tree offset
= NULL_TREE
;
411 if (TREE_CODE (expr
) == SSA_NAME
)
413 /* Try to tease the offset out of the pointer. */
414 gimple
*stmt
= SSA_NAME_DEF_STMT (expr
);
416 && gimple_assign_single_p (stmt
)
417 && gimple_assign_rhs_code (stmt
) == ADDR_EXPR
)
418 expr
= gimple_assign_rhs1 (stmt
);
419 else if (is_gimple_assign (stmt
))
421 tree_code code
= gimple_assign_rhs_code (stmt
);
422 if (code
== NOP_EXPR
)
424 tree rhs
= gimple_assign_rhs1 (stmt
);
425 if (POINTER_TYPE_P (TREE_TYPE (rhs
)))
426 expr
= gimple_assign_rhs1 (stmt
);
433 else if (code
== POINTER_PLUS_EXPR
)
435 expr
= gimple_assign_rhs1 (stmt
);
436 offset
= gimple_assign_rhs2 (stmt
);
446 /* FIXME: Handle PHI nodes in case like:
447 _12 = &MEM[(void *)&a + 2B] + _10;
449 <bb> [local count: 1073741824]:
450 # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
451 memcpy (prephitmp_13, p_7(D), 6); */
457 if (TREE_CODE (expr
) == ADDR_EXPR
)
458 expr
= TREE_OPERAND (expr
, 0);
460 /* Stash the reference for offset validation. */
463 poly_int64 bitsize
, bitpos
;
466 int sign
, reverse
, vol
;
468 /* Determine the base object or pointer of the reference and
469 the constant bit offset from the beginning of the base.
470 If the offset has a non-constant component, it will be in
471 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
473 base
= get_inner_reference (expr
, &bitsize
, &bitpos
, &var_off
,
474 &mode
, &sign
, &reverse
, &vol
);
476 /* get_inner_reference is not expected to return null. */
477 gcc_assert (base
!= NULL
);
480 extend_offset_range (offset
);
482 poly_int64 bytepos
= exact_div (bitpos
, BITS_PER_UNIT
);
484 /* Convert the poly_int64 offset to offset_int. The offset
485 should be constant but be prepared for it not to be just in
488 if (bytepos
.is_constant (&cstoff
))
490 offrange
[0] += cstoff
;
491 offrange
[1] += cstoff
;
493 /* Besides the reference saved above, also stash the offset
495 if (TREE_CODE (expr
) == COMPONENT_REF
)
499 offrange
[1] += maxobjsize
;
503 if (TREE_CODE (var_off
) == INTEGER_CST
)
505 cstoff
= wi::to_offset (var_off
);
506 offrange
[0] += cstoff
;
507 offrange
[1] += cstoff
;
510 offrange
[1] += maxobjsize
;
513 if (TREE_CODE (base
) == MEM_REF
)
515 tree memrefoff
= fold_convert (ptrdiff_type_node
, TREE_OPERAND (base
, 1));
516 extend_offset_range (memrefoff
);
517 base
= TREE_OPERAND (base
, 0);
519 if (refoff
!= HOST_WIDE_INT_MIN
520 && TREE_CODE (expr
) == COMPONENT_REF
)
522 /* Bump up the offset of the referenced subobject to reflect
523 the offset to the enclosing object. For example, so that
525 struct S { char a, b[3]; } s[2];
526 strcpy (s[1].b, "1234");
527 REFOFF is set to s[1].b - (char*)s. */
528 offset_int off
= tree_to_shwi (memrefoff
);
532 if (!integer_zerop (memrefoff
))
533 /* A non-zero offset into an array of struct with flexible array
534 members implies that the array is empty because there is no
535 way to initialize such a member when it belongs to an array.
536 This must be some sort of a bug. */
540 if (TREE_CODE (ref
) == COMPONENT_REF
)
541 if (tree size
= component_ref_size (ref
))
542 if (TREE_CODE (size
) == INTEGER_CST
)
543 refsize
= wi::to_offset (size
);
545 if (TREE_CODE (base
) == SSA_NAME
)
546 set_base_and_offset (base
);
549 /* Return error_mark_node if the signed offset exceeds the bounds
550 of the address space (PTRDIFF_MAX). Otherwise, return either BASE
551 or REF when the offset exceeds the bounds of the BASE or REF object,
552 and set OOBOFF to the past-the-end offset formed by the reference,
553 including its size. OOBOFF is initially setto the range of offsets,
554 and OOBOFF[2] to the offset of the first write access (nonzero for
555 the strcat family). When STRICT is nonzero use REF size, when
556 available, otherwise use BASE size. When STRICT is greater than 1,
557 use the size of the last array member as the bound, otherwise treat
558 such a member as a flexible array member. Return NULL when the offset
562 builtin_memref::offset_out_of_bounds (int strict
, offset_int ooboff
[3]) const
567 /* The offset of the first write access or zero. */
568 offset_int wroff
= ooboff
[2];
570 /* A temporary, possibly adjusted, copy of the offset range. */
571 offset_int offrng
[2] = { ooboff
[0], ooboff
[1] };
573 if (DECL_P (base
) && TREE_CODE (TREE_TYPE (base
)) == ARRAY_TYPE
)
575 /* Check for offset in an anti-range with a negative lower bound.
576 For such a range, consider only the non-negative subrange. */
577 if (offrng
[1] < offrng
[0] && offrng
[1] < 0)
578 offrng
[1] = maxobjsize
;
581 /* Conservative offset of the last byte of the referenced object. */
584 /* The bounds need not be ordered. Set HIB to use as the index
585 of the larger of the bounds and LOB as the opposite. */
586 bool hib
= wi::les_p (offrng
[0], offrng
[1]);
589 /* Set to the size remaining in the object after subtracting
590 REFOFF. It may become negative as a result of negative indices
591 into the enclosing object, such as in:
592 extern struct S { char a[4], b[3], c[1]; } *p;
593 strcpy (p[-3].b, "123"); */
594 offset_int size
= basesize
;
597 const bool decl_p
= DECL_P (obj
);
601 endoff
= offrng
[lob
] + (sizrange
[0] - wroff
);
603 /* For a reference through a pointer to an object of unknown size
604 all initial offsets are considered valid, positive as well as
605 negative, since the pointer itself can point past the beginning
606 of the object. However, the sum of the lower bound of the offset
607 and that of the size must be less than or equal than PTRDIFF_MAX. */
608 if (endoff
> maxobjsize
)
609 return error_mark_node
;
611 /* When the referenced subobject is known, the end offset must be
612 within its bounds. Otherwise there is nothing to do. */
617 && TREE_CODE (ref
) == COMPONENT_REF
)
619 /* If REFOFF is negative, SIZE will become negative here. */
620 size
= refoff
+ refsize
;
627 /* A reference to an object of known size must be within the bounds
628 of either the base object or the subobject (see above for when
629 a subobject can be used). */
630 if ((decl_p
&& offrng
[hib
] < 0) || offrng
[lob
] > size
)
633 /* The extent of the reference must also be within the bounds of
634 the base object (if known) or the subobject or the maximum object
636 endoff
= offrng
[lob
] + sizrange
[0];
637 if (endoff
> maxobjsize
)
638 return error_mark_node
;
644 && TREE_CODE (ref
) == COMPONENT_REF
)
646 /* If the reference is to a member subobject of a declared object,
647 the offset must be within the bounds of the subobject. */
648 size
= refoff
+ refsize
;
655 /* Set the out-of-bounds offset range to be one greater than
656 that delimited by the reference including its size. */
659 if (endoff
> ooboff
[lob
])
660 ooboff
[hib
] = endoff
- 1;
662 ooboff
[hib
] = offrng
[lob
] + sizrange
[1];
667 /* Create an association between the memory references DST and SRC
668 for access by a call EXPR to a memory or string built-in funtion. */
670 builtin_access::builtin_access (range_query
*query
, gimple
*call
,
673 : dstref (&dst
), srcref (&src
), sizrange (), ovloff (), ovlsiz (),
674 dstoff (), srcoff (), dstsiz (), srcsiz ()
676 dstoff
[0] = dst
.offrange
[0];
677 dstoff
[1] = dst
.offrange
[1];
679 /* Zero out since the offset_int ctors invoked above are no-op. */
680 srcoff
[0] = srcoff
[1] = 0;
681 dstsiz
[0] = dstsiz
[1] = 0;
682 srcsiz
[0] = srcsiz
[1] = 0;
684 /* Object Size Type to use to determine the size of the destination
685 and source objects. Overridden below for raw memory functions. */
688 /* True when the size of one reference depends on the offset of
689 itself or the other. */
690 bool depends_p
= true;
692 /* True when the size of the destination reference DSTREF has been
693 determined from SRCREF and so needs to be adjusted by the latter's
694 offset. Only meaningful for bounded string functions like strncpy. */
695 bool dstadjust_p
= false;
697 /* The size argument number (depends on the built-in). */
698 unsigned sizeargno
= 2;
700 tree func
= gimple_call_fndecl (call
);
701 switch (DECL_FUNCTION_CODE (func
))
703 case BUILT_IN_MEMCPY
:
704 case BUILT_IN_MEMCPY_CHK
:
705 case BUILT_IN_MEMPCPY
:
706 case BUILT_IN_MEMPCPY_CHK
:
709 detect_overlap
= &builtin_access::generic_overlap
;
712 case BUILT_IN_MEMMOVE
:
713 case BUILT_IN_MEMMOVE_CHK
:
714 /* For memmove there is never any overlap to check for. */
717 detect_overlap
= &builtin_access::no_overlap
;
720 case BUILT_IN_MEMSET
:
721 case BUILT_IN_MEMSET_CHK
:
722 /* For memset there is never any overlap to check for. */
725 detect_overlap
= &builtin_access::no_overlap
;
728 case BUILT_IN_STPNCPY
:
729 case BUILT_IN_STPNCPY_CHK
:
730 case BUILT_IN_STRNCPY
:
731 case BUILT_IN_STRNCPY_CHK
:
732 dstref
->strbounded_p
= true;
733 detect_overlap
= &builtin_access::strcpy_overlap
;
736 case BUILT_IN_STPCPY
:
737 case BUILT_IN_STPCPY_CHK
:
738 case BUILT_IN_STRCPY
:
739 case BUILT_IN_STRCPY_CHK
:
740 detect_overlap
= &builtin_access::strcpy_overlap
;
743 case BUILT_IN_STRCAT
:
744 case BUILT_IN_STRCAT_CHK
:
745 detect_overlap
= &builtin_access::strcat_overlap
;
748 case BUILT_IN_STRNCAT
:
749 case BUILT_IN_STRNCAT_CHK
:
750 dstref
->strbounded_p
= true;
751 srcref
->strbounded_p
= true;
752 detect_overlap
= &builtin_access::strcat_overlap
;
756 /* Handle other string functions here whose access may need
757 to be validated for in-bounds offsets and non-overlapping
762 const offset_int maxobjsize
= dst
.maxobjsize
;
764 /* Try to determine the size of the base object. compute_objsize
765 expects a pointer so create one if BASE is a non-pointer object. */
767 if (dst
.basesize
< 0)
770 if (!POINTER_TYPE_P (TREE_TYPE (addr
)))
771 addr
= build1 (ADDR_EXPR
, (TREE_TYPE (addr
)), addr
);
773 if (tree dstsize
= compute_objsize (addr
, ostype
))
774 dst
.basesize
= wi::to_offset (dstsize
);
775 else if (POINTER_TYPE_P (TREE_TYPE (addr
)))
776 dst
.basesize
= HOST_WIDE_INT_MIN
;
778 dst
.basesize
= maxobjsize
;
781 if (src
.base
&& src
.basesize
< 0)
784 if (!POINTER_TYPE_P (TREE_TYPE (addr
)))
785 addr
= build1 (ADDR_EXPR
, (TREE_TYPE (addr
)), addr
);
787 if (tree srcsize
= compute_objsize (addr
, ostype
))
788 src
.basesize
= wi::to_offset (srcsize
);
789 else if (POINTER_TYPE_P (TREE_TYPE (addr
)))
790 src
.basesize
= HOST_WIDE_INT_MIN
;
792 src
.basesize
= maxobjsize
;
795 /* Make adjustments for references to the same object by string
796 built-in functions to reflect the constraints imposed by
799 /* For bounded string functions determine the range of the bound
800 on the access. For others, the range stays unbounded. */
801 offset_int bounds
[2] = { maxobjsize
, maxobjsize
};
802 if (dstref
->strbounded_p
)
804 unsigned nargs
= gimple_call_num_args (call
);
805 if (nargs
<= sizeargno
)
808 tree size
= gimple_call_arg (call
, sizeargno
);
810 if (get_size_range (query
, size
, call
, range
, true))
812 bounds
[0] = wi::to_offset (range
[0]);
813 bounds
[1] = wi::to_offset (range
[1]);
816 /* If both references' size ranges are indeterminate use the last
817 (size) argument from the function call as a substitute. This
818 may only be necessary for strncpy (but not for memcpy where
819 the size range would have been already determined this way). */
820 if (dstref
->sizrange
[0] == 0 && dstref
->sizrange
[1] == maxobjsize
821 && srcref
->sizrange
[0] == 0 && srcref
->sizrange
[1] == maxobjsize
)
823 dstref
->sizrange
[0] = bounds
[0];
824 dstref
->sizrange
[1] = bounds
[1];
828 bool dstsize_set
= false;
829 /* The size range of one reference involving the same base object
830 can be determined from the size range of the other reference.
831 This makes it possible to compute accurate offsets for warnings
832 involving functions like strcpy where the length of just one of
833 the two arguments is known (determined by tree-ssa-strlen). */
834 if (dstref
->sizrange
[0] == 0 && dstref
->sizrange
[1] == maxobjsize
)
836 /* When the destination size is unknown set it to the size of
838 dstref
->sizrange
[0] = srcref
->sizrange
[0];
839 dstref
->sizrange
[1] = srcref
->sizrange
[1];
842 else if (srcref
->sizrange
[0] == 0 && srcref
->sizrange
[1] == maxobjsize
)
844 /* When the size of the source access is unknown set it to the size
845 of the destination first and adjust it later if necessary. */
846 srcref
->sizrange
[0] = dstref
->sizrange
[0];
847 srcref
->sizrange
[1] = dstref
->sizrange
[1];
851 if (dstref
->strbounded_p
)
853 /* Read access by strncpy is constrained by the third
854 argument but except for a zero bound is at least one. */
855 srcref
->sizrange
[0] = bounds
[1] > 0 ? 1 : 0;
856 offset_int bound
= wi::umin (srcref
->basesize
, bounds
[1]);
857 if (bound
< srcref
->sizrange
[1])
858 srcref
->sizrange
[1] = bound
;
860 /* For string functions, adjust the size range of the source
861 reference by the inverse boundaries of the offset (because
862 the higher the offset into the string the shorter its
864 if (srcref
->offrange
[1] >= 0
865 && srcref
->offrange
[1] < srcref
->sizrange
[0])
866 srcref
->sizrange
[0] -= srcref
->offrange
[1];
868 srcref
->sizrange
[0] = 1;
870 if (srcref
->offrange
[0] > 0)
872 if (srcref
->offrange
[0] < srcref
->sizrange
[1])
873 srcref
->sizrange
[1] -= srcref
->offrange
[0];
875 srcref
->sizrange
[1] = 0;
882 if (detect_overlap
== &builtin_access::generic_overlap
)
884 if (dstref
->strbounded_p
)
886 dstref
->sizrange
[0] = bounds
[0];
887 dstref
->sizrange
[1] = bounds
[1];
889 if (dstref
->sizrange
[0] < srcref
->sizrange
[0])
890 srcref
->sizrange
[0] = dstref
->sizrange
[0];
892 if (dstref
->sizrange
[1] < srcref
->sizrange
[1])
893 srcref
->sizrange
[1] = dstref
->sizrange
[1];
896 else if (detect_overlap
== &builtin_access::strcpy_overlap
)
898 if (!dstref
->strbounded_p
)
900 /* For strcpy, adjust the destination size range to match that
901 of the source computed above. */
902 if (depends_p
&& dstadjust_p
)
904 dstref
->sizrange
[0] = srcref
->sizrange
[0];
905 dstref
->sizrange
[1] = srcref
->sizrange
[1];
909 else if (!dstsize_set
&& detect_overlap
== &builtin_access::strcat_overlap
)
911 dstref
->sizrange
[0] += srcref
->sizrange
[0] - 1;
912 dstref
->sizrange
[1] += srcref
->sizrange
[1] - 1;
915 if (dstref
->strbounded_p
)
917 /* For strncpy, adjust the destination size range to match that
918 of the source computed above. */
919 dstref
->sizrange
[0] = bounds
[0];
920 dstref
->sizrange
[1] = bounds
[1];
922 if (bounds
[0] < srcref
->sizrange
[0])
923 srcref
->sizrange
[0] = bounds
[0];
925 if (bounds
[1] < srcref
->sizrange
[1])
926 srcref
->sizrange
[1] = bounds
[1];
931 builtin_access::overlap_size (const offset_int a
[2], const offset_int b
[2],
934 const offset_int
*p
= a
;
935 const offset_int
*q
= b
;
937 /* Point P at the bigger of the two ranges and Q at the smaller. */
938 if (wi::lts_p (a
[1] - a
[0], b
[1] - b
[0]))
950 return wi::smin (p
[1], q
[1]) - q
[0];
960 /* Return true if the bounded mempry (memcpy amd similar) or string function
961 access (strncpy and similar) ACS overlaps. */
964 builtin_access::generic_overlap ()
966 builtin_access
&acs
= *this;
967 const builtin_memref
*dstref
= acs
.dstref
;
968 const builtin_memref
*srcref
= acs
.srcref
;
970 gcc_assert (dstref
->base
== srcref
->base
);
972 const offset_int maxobjsize
= acs
.dstref
->maxobjsize
;
974 offset_int maxsize
= dstref
->basesize
< 0 ? maxobjsize
: dstref
->basesize
;
976 /* Adjust the larger bounds of the offsets (which may be the first
977 element if the lower bound is larger than the upper bound) to
978 make them valid for the smallest access (if possible) but no smaller
979 than the smaller bounds. */
980 gcc_assert (wi::les_p (acs
.dstoff
[0], acs
.dstoff
[1]));
982 if (maxsize
< acs
.dstoff
[1] + acs
.dstsiz
[0])
983 acs
.dstoff
[1] = maxsize
- acs
.dstsiz
[0];
984 if (acs
.dstoff
[1] < acs
.dstoff
[0])
985 acs
.dstoff
[1] = acs
.dstoff
[0];
987 gcc_assert (wi::les_p (acs
.srcoff
[0], acs
.srcoff
[1]));
989 if (maxsize
< acs
.srcoff
[1] + acs
.srcsiz
[0])
990 acs
.srcoff
[1] = maxsize
- acs
.srcsiz
[0];
991 if (acs
.srcoff
[1] < acs
.srcoff
[0])
992 acs
.srcoff
[1] = acs
.srcoff
[0];
994 /* Determine the minimum and maximum space for the access given
997 space
[0] = wi::abs (acs
.dstoff
[0] - acs
.srcoff
[0]);
1000 offset_int d
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[1]);
1001 if (acs
.srcsiz
[0] > 0)
1010 space
[1] = acs
.dstsiz
[1];
1012 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
1019 /* Treat raw memory functions both of whose references are bounded
1020 as special and permit uncertain overlaps to go undetected. For
1021 all kinds of constant offset and constant size accesses, if
1022 overlap isn't certain it is not possible. */
1023 bool overlap_possible
= space
[0] < acs
.dstsiz
[1];
1024 if (!overlap_possible
)
1027 bool overlap_certain
= space
[1] < acs
.dstsiz
[0];
1029 /* True when the size of one reference depends on the offset of
1031 bool depends_p
= detect_overlap
!= &builtin_access::generic_overlap
;
1033 if (!overlap_certain
)
1035 if (!dstref
->strbounded_p
&& !depends_p
)
1036 /* Memcpy only considers certain overlap. */
1039 /* There's no way to distinguish an access to the same member
1040 of a structure from one to two distinct members of the same
1041 structure. Give up to avoid excessive false positives. */
1042 tree basetype
= TREE_TYPE (dstref
->base
);
1044 if (POINTER_TYPE_P (basetype
))
1045 basetype
= TREE_TYPE (basetype
);
1047 while (TREE_CODE (basetype
) == ARRAY_TYPE
)
1048 basetype
= TREE_TYPE (basetype
);
1050 if (RECORD_OR_UNION_TYPE_P (basetype
))
1054 /* True for stpcpy and strcpy. */
1055 bool stxcpy_p
= (!dstref
->strbounded_p
1056 && detect_overlap
== &builtin_access::strcpy_overlap
);
1058 if (dstref
->refoff
>= 0
1059 && srcref
->refoff
>= 0
1060 && dstref
->refoff
!= srcref
->refoff
1061 && (stxcpy_p
|| dstref
->strbounded_p
|| srcref
->strbounded_p
))
1064 offset_int siz
[2] = { maxobjsize
+ 1, 0 };
1066 ovloff
[0] = HOST_WIDE_INT_MAX
;
1067 ovloff
[1] = HOST_WIDE_INT_MIN
;
1071 /* Iterate over the extreme locations (on the horizontal axis formed
1072 by their offsets) and sizes of two regions and find their smallest
1073 and largest overlap and the corresponding offsets. */
1074 for (unsigned i
= 0; i
!= 2; ++i
)
1076 const offset_int a
[2] = {
1077 acs
.dstoff
[i
], acs
.dstoff
[i
] + acs
.dstsiz
[!i
]
1080 const offset_int b
[2] = {
1081 acs
.srcoff
[i
], acs
.srcoff
[i
] + acs
.srcsiz
[!i
]
1085 offset_int sz
= overlap_size (a
, b
, &off
);
1094 if (wi::lts_p (off
, ovloff
[0]))
1095 ovloff
[0] = off
.to_shwi ();
1096 if (wi::lts_p (ovloff
[1], off
))
1097 ovloff
[1] = off
.to_shwi ();
1103 /* Iterate over the extreme locations (on the horizontal axis
1104 formed by their offsets) and sizes of the two regions and
1105 find their smallest and largest overlap and the corresponding
1108 for (unsigned io
= 0; io
!= 2; ++io
)
1109 for (unsigned is
= 0; is
!= 2; ++is
)
1111 const offset_int a
[2] = {
1112 acs
.dstoff
[io
], acs
.dstoff
[io
] + acs
.dstsiz
[is
]
1115 for (unsigned jo
= 0; jo
!= 2; ++jo
)
1116 for (unsigned js
= 0; js
!= 2; ++js
)
1118 const offset_int b
[2] = {
1119 acs
.srcoff
[jo
], acs
.srcoff
[jo
] + acs
.srcsiz
[js
]
1123 offset_int sz
= overlap_size (a
, b
, &off
);
1132 if (wi::lts_p (off
, ovloff
[0]))
1133 ovloff
[0] = off
.to_shwi ();
1134 if (wi::lts_p (ovloff
[1], off
))
1135 ovloff
[1] = off
.to_shwi ();
1141 ovlsiz
[0] = siz
[0].to_shwi ();
1142 ovlsiz
[1] = siz
[1].to_shwi ();
1144 /* Adjust the overlap offset range to reflect the overlap size range. */
1145 if (ovlsiz
[0] == 0 && ovlsiz
[1] > 1)
1146 ovloff
[1] = ovloff
[0] + ovlsiz
[1] - 1;
1151 /* Return true if the strcat-like access overlaps. */
1154 builtin_access::strcat_overlap ()
1156 builtin_access
&acs
= *this;
1157 const builtin_memref
*dstref
= acs
.dstref
;
1158 const builtin_memref
*srcref
= acs
.srcref
;
1160 gcc_assert (dstref
->base
== srcref
->base
);
1162 const offset_int maxobjsize
= acs
.dstref
->maxobjsize
;
1164 gcc_assert (dstref
->base
&& dstref
->base
== srcref
->base
);
1166 /* Adjust for strcat-like accesses. */
1168 /* As a special case for strcat, set the DSTREF offsets to the length
1169 of the destination string since the function starts writing over
1170 its terminating nul, and set the destination size to 1 for the length
1172 acs
.dstoff
[0] += dstsiz
[0] - srcref
->sizrange
[0];
1173 acs
.dstoff
[1] += dstsiz
[1] - srcref
->sizrange
[1];
1175 bool strfunc_unknown_args
= acs
.dstsiz
[0] == 0 && acs
.dstsiz
[1] != 0;
1177 /* The lower bound is zero when the size is unknown because then
1178 overlap is not certain. */
1179 acs
.dstsiz
[0] = strfunc_unknown_args
? 0 : 1;
1182 offset_int maxsize
= dstref
->basesize
< 0 ? maxobjsize
: dstref
->basesize
;
1184 /* For references to the same base object, determine if there's a pair
1185 of valid offsets into the two references such that access between
1186 them doesn't overlap. Adjust both upper bounds to be valid for
1187 the smaller size (i.e., at most MAXSIZE - SIZE). */
1189 if (maxsize
< acs
.dstoff
[1] + acs
.dstsiz
[0])
1190 acs
.dstoff
[1] = maxsize
- acs
.dstsiz
[0];
1192 if (maxsize
< acs
.srcoff
[1] + acs
.srcsiz
[0])
1193 acs
.srcoff
[1] = maxsize
- acs
.srcsiz
[0];
1195 /* Check to see if there's enough space for both accesses without
1196 overlap. Determine the optimistic (maximum) amount of available
1199 if (acs
.dstoff
[0] <= acs
.srcoff
[0])
1201 if (acs
.dstoff
[1] < acs
.srcoff
[1])
1202 space
= acs
.srcoff
[1] + acs
.srcsiz
[0] - acs
.dstoff
[0];
1204 space
= acs
.dstoff
[1] + acs
.dstsiz
[0] - acs
.srcoff
[0];
1207 space
= acs
.dstoff
[1] + acs
.dstsiz
[0] - acs
.srcoff
[0];
1209 /* Overlap is certain if the distance between the farthest offsets
1210 of the opposite accesses is less than the sum of the lower bounds
1211 of the sizes of the two accesses. */
1212 bool overlap_certain
= space
< acs
.dstsiz
[0] + acs
.srcsiz
[0];
1214 /* For a constant-offset, constant size access, consider the largest
1215 distance between the offset bounds and the lower bound of the access
1216 size. If the overlap isn't certain return success. */
1217 if (!overlap_certain
1218 && acs
.dstoff
[0] == acs
.dstoff
[1]
1219 && acs
.srcoff
[0] == acs
.srcoff
[1]
1220 && acs
.dstsiz
[0] == acs
.dstsiz
[1]
1221 && acs
.srcsiz
[0] == acs
.srcsiz
[1])
1224 /* Overlap is not certain but may be possible. */
1226 offset_int access_min
= acs
.dstsiz
[0] + acs
.srcsiz
[0];
1228 /* Determine the conservative (minimum) amount of space. */
1229 space
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[0]);
1230 offset_int d
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[1]);
1233 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
1237 /* For a strict test (used for strcpy and similar with unknown or
1238 variable bounds or sizes), consider the smallest distance between
1239 the offset bounds and either the upper bound of the access size
1240 if known, or the lower bound otherwise. */
1241 if (access_min
<= space
&& (access_min
!= 0 || !strfunc_unknown_args
))
1244 /* When strcat overlap is certain it is always a single byte:
1245 the terminating NUL, regardless of offsets and sizes. When
1246 overlap is only possible its range is [0, 1]. */
1247 acs
.ovlsiz
[0] = dstref
->sizrange
[0] == dstref
->sizrange
[1] ? 1 : 0;
1251 = dstref
->offrange
[0] + (dstref
->sizrange
[0] - srcref
->sizrange
[0]);
1252 if (endoff
<= srcref
->offrange
[0])
1253 acs
.ovloff
[0] = wi::smin (maxobjsize
, srcref
->offrange
[0]).to_shwi ();
1255 acs
.ovloff
[0] = wi::smin (maxobjsize
, endoff
).to_shwi ();
1257 acs
.sizrange
[0] = wi::smax (wi::abs (endoff
- srcref
->offrange
[0]) + 1,
1258 srcref
->sizrange
[0]).to_shwi ();
1259 if (dstref
->offrange
[0] == dstref
->offrange
[1])
1261 if (srcref
->offrange
[0] == srcref
->offrange
[1])
1262 acs
.ovloff
[1] = acs
.ovloff
[0];
1265 = wi::smin (maxobjsize
,
1266 srcref
->offrange
[1] + srcref
->sizrange
[1]).to_shwi ();
1270 = wi::smin (maxobjsize
,
1271 dstref
->offrange
[1] + dstref
->sizrange
[1]).to_shwi ();
1273 if (acs
.sizrange
[0] == 0)
1274 acs
.sizrange
[0] = 1;
1275 acs
.sizrange
[1] = wi::smax (acs
.dstsiz
[1], srcref
->sizrange
[1]).to_shwi ();
1279 /* Return true if the strcpy-like access overlaps. */
1282 builtin_access::strcpy_overlap ()
1284 return generic_overlap ();
1287 /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
1288 if known, or [0, MAXOBJSIZE] otherwise. */
1291 clamp_offset (tree base
, offset_int refoff
[2], offset_int maxobjsize
)
1293 if (!base
|| TREE_CODE (TREE_TYPE (base
)) != ARRAY_TYPE
)
1296 if (refoff
[0] < 0 && refoff
[1] >= 0)
1299 if (refoff
[1] < refoff
[0])
1301 offset_int maxsize
= maxobjsize
;
1302 if (tree size
= TYPE_SIZE_UNIT (TREE_TYPE (base
)))
1303 maxsize
= wi::to_offset (size
);
1305 refoff
[1] = wi::umin (refoff
[1], maxsize
);
1309 /* Return true if DSTREF and SRCREF describe accesses that either overlap
1310 one another or that, in order not to overlap, would imply that the size
1311 of the referenced object(s) exceeds the maximum size of an object. Set
1312 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1313 they may overlap in a way that's not apparent from the available data),
1317 builtin_access::overlap ()
1319 builtin_access
&acs
= *this;
1321 const offset_int maxobjsize
= dstref
->maxobjsize
;
1323 acs
.sizrange
[0] = wi::smax (dstref
->sizrange
[0],
1324 srcref
->sizrange
[0]).to_shwi ();
1325 acs
.sizrange
[1] = wi::smax (dstref
->sizrange
[1],
1326 srcref
->sizrange
[1]).to_shwi ();
1328 /* Check to see if the two references refer to regions that are
1329 too large not to overlap in the address space (whose maximum
1330 size is PTRDIFF_MAX). */
1331 offset_int size
= dstref
->sizrange
[0] + srcref
->sizrange
[0];
1332 if (maxobjsize
< size
)
1334 acs
.ovloff
[0] = (maxobjsize
- dstref
->sizrange
[0]).to_shwi ();
1335 acs
.ovlsiz
[0] = (size
- maxobjsize
).to_shwi ();
1339 /* If both base objects aren't known return the maximum possible
1340 offset that would make them not overlap. */
1341 if (!dstref
->base
|| !srcref
->base
)
1344 /* If the base object is an array adjust the bounds of the offset
1345 to be non-negative and within the bounds of the array if possible. */
1346 clamp_offset (dstref
->base
, acs
.dstoff
, maxobjsize
);
1348 acs
.srcoff
[0] = srcref
->offrange
[0];
1349 acs
.srcoff
[1] = srcref
->offrange
[1];
1351 clamp_offset (srcref
->base
, acs
.srcoff
, maxobjsize
);
1353 /* When the upper bound of the offset is less than the lower bound
1354 the former is the result of a negative offset being represented
1355 as a large positive value or vice versa. The resulting range is
1356 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1357 a union is not representable using the current data structure
1358 replace it with the full range of offsets. */
1359 if (acs
.dstoff
[1] < acs
.dstoff
[0])
1361 acs
.dstoff
[0] = -maxobjsize
- 1;
1362 acs
.dstoff
[1] = maxobjsize
;
1365 /* Validate the offset and size of each reference on its own first.
1366 This is independent of whether or not the base objects are the
1367 same. Normally, this would have already been detected and
1368 diagnosed by -Warray-bounds, unless it has been disabled. */
1369 offset_int maxoff
= acs
.dstoff
[0] + dstref
->sizrange
[0];
1370 if (maxobjsize
< maxoff
)
1372 acs
.ovlsiz
[0] = (maxoff
- maxobjsize
).to_shwi ();
1373 acs
.ovloff
[0] = acs
.dstoff
[0].to_shwi () - acs
.ovlsiz
[0];
1377 /* Repeat the same as above but for the source offsets. */
1378 if (acs
.srcoff
[1] < acs
.srcoff
[0])
1380 acs
.srcoff
[0] = -maxobjsize
- 1;
1381 acs
.srcoff
[1] = maxobjsize
;
1384 maxoff
= acs
.srcoff
[0] + srcref
->sizrange
[0];
1385 if (maxobjsize
< maxoff
)
1387 acs
.ovlsiz
[0] = (maxoff
- maxobjsize
).to_shwi ();
1388 acs
.ovlsiz
[1] = (acs
.srcoff
[0] + srcref
->sizrange
[1]
1389 - maxobjsize
).to_shwi ();
1390 acs
.ovloff
[0] = acs
.srcoff
[0].to_shwi () - acs
.ovlsiz
[0];
1394 if (dstref
->base
!= srcref
->base
)
1397 acs
.dstsiz
[0] = dstref
->sizrange
[0];
1398 acs
.dstsiz
[1] = dstref
->sizrange
[1];
1400 acs
.srcsiz
[0] = srcref
->sizrange
[0];
1401 acs
.srcsiz
[1] = srcref
->sizrange
[1];
1403 /* Call the appropriate function to determine the overlap. */
1404 if ((this->*detect_overlap
) ())
1408 /* Unless the access size range has already been set, do so here. */
1409 sizrange
[0] = wi::smax (acs
.dstsiz
[0], srcref
->sizrange
[0]).to_shwi ();
1410 sizrange
[1] = wi::smax (acs
.dstsiz
[1], srcref
->sizrange
[1]).to_shwi ();
1418 /* Attempt to detect and diagnose an overlapping copy in a call expression
1419 EXPR involving an access ACS to a built-in memory or string function.
1420 Return true when one has been detected, false otherwise. */
1423 maybe_diag_overlap (location_t loc
, gimple
*call
, builtin_access
&acs
)
1425 if (!acs
.overlap ())
1428 if (gimple_no_warning_p (call
))
1431 /* For convenience. */
1432 const builtin_memref
&dstref
= *acs
.dstref
;
1433 const builtin_memref
&srcref
= *acs
.srcref
;
1435 /* Determine the range of offsets and sizes of the overlap if it
1436 exists and issue diagnostics. */
1437 HOST_WIDE_INT
*ovloff
= acs
.ovloff
;
1438 HOST_WIDE_INT
*ovlsiz
= acs
.ovlsiz
;
1439 HOST_WIDE_INT
*sizrange
= acs
.sizrange
;
1441 tree func
= gimple_call_fndecl (call
);
1443 /* To avoid a combinatorial explosion of diagnostics format the offsets
1444 or their ranges as strings and use them in the warning calls below. */
1447 if (dstref
.offrange
[0] == dstref
.offrange
[1]
1448 || dstref
.offrange
[1] > HOST_WIDE_INT_MAX
)
1449 sprintf (offstr
[0], HOST_WIDE_INT_PRINT_DEC
,
1450 dstref
.offrange
[0].to_shwi ());
1453 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1454 dstref
.offrange
[0].to_shwi (),
1455 dstref
.offrange
[1].to_shwi ());
1457 if (srcref
.offrange
[0] == srcref
.offrange
[1]
1458 || srcref
.offrange
[1] > HOST_WIDE_INT_MAX
)
1460 HOST_WIDE_INT_PRINT_DEC
,
1461 srcref
.offrange
[0].to_shwi ());
1464 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1465 srcref
.offrange
[0].to_shwi (),
1466 srcref
.offrange
[1].to_shwi ());
1468 if (ovloff
[0] == ovloff
[1] || !ovloff
[1])
1469 sprintf (offstr
[2], HOST_WIDE_INT_PRINT_DEC
, ovloff
[0]);
1472 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1473 ovloff
[0], ovloff
[1]);
1475 const offset_int maxobjsize
= dstref
.maxobjsize
;
1476 bool must_overlap
= ovlsiz
[0] > 0;
1479 ovlsiz
[1] = ovlsiz
[0];
1483 /* Issue definitive "overlaps" diagnostic in this block. */
1485 if (sizrange
[0] == sizrange
[1])
1487 if (ovlsiz
[0] == ovlsiz
[1])
1488 warning_at (loc
, OPT_Wrestrict
,
1491 ? G_("%G%qD accessing %wu byte at offsets %s "
1492 "and %s overlaps %wu byte at offset %s")
1493 : G_("%G%qD accessing %wu byte at offsets %s "
1494 "and %s overlaps %wu bytes at offset "
1497 ? G_("%G%qD accessing %wu bytes at offsets %s "
1498 "and %s overlaps %wu byte at offset %s")
1499 : G_("%G%qD accessing %wu bytes at offsets %s "
1500 "and %s overlaps %wu bytes at offset "
1502 call
, func
, sizrange
[0],
1503 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1504 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1505 warning_n (loc
, OPT_Wrestrict
, sizrange
[0],
1506 "%G%qD accessing %wu byte at offsets %s "
1507 "and %s overlaps between %wu and %wu bytes "
1509 "%G%qD accessing %wu bytes at offsets %s "
1510 "and %s overlaps between %wu and %wu bytes "
1512 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1513 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
1515 warning_n (loc
, OPT_Wrestrict
, sizrange
[0],
1516 "%G%qD accessing %wu byte at offsets %s and "
1517 "%s overlaps %wu or more bytes at offset %s",
1518 "%G%qD accessing %wu bytes at offsets %s and "
1519 "%s overlaps %wu or more bytes at offset %s",
1520 call
, func
, sizrange
[0],
1521 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1525 if (sizrange
[1] >= 0 && sizrange
[1] < maxobjsize
.to_shwi ())
1527 if (ovlsiz
[0] == ovlsiz
[1])
1528 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[0],
1529 "%G%qD accessing between %wu and %wu bytes "
1530 "at offsets %s and %s overlaps %wu byte at "
1532 "%G%qD accessing between %wu and %wu bytes "
1533 "at offsets %s and %s overlaps %wu bytes "
1535 call
, func
, sizrange
[0], sizrange
[1],
1536 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1537 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1538 warning_at (loc
, OPT_Wrestrict
,
1539 "%G%qD accessing between %wu and %wu bytes at "
1540 "offsets %s and %s overlaps between %wu and %wu "
1541 "bytes at offset %s",
1542 call
, func
, sizrange
[0], sizrange
[1],
1543 offstr
[0], offstr
[1], ovlsiz
[0], ovlsiz
[1],
1546 warning_at (loc
, OPT_Wrestrict
,
1547 "%G%qD accessing between %wu and %wu bytes at "
1548 "offsets %s and %s overlaps %wu or more bytes "
1550 call
, func
, sizrange
[0], sizrange
[1],
1551 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1555 if (ovlsiz
[0] != ovlsiz
[1])
1556 ovlsiz
[1] = maxobjsize
.to_shwi ();
1558 if (ovlsiz
[0] == ovlsiz
[1])
1559 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[0],
1560 "%G%qD accessing %wu or more bytes at offsets "
1561 "%s and %s overlaps %wu byte at offset %s",
1562 "%G%qD accessing %wu or more bytes at offsets "
1563 "%s and %s overlaps %wu bytes at offset %s",
1564 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1565 ovlsiz
[0], offstr
[2]);
1566 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1567 warning_at (loc
, OPT_Wrestrict
,
1568 "%G%qD accessing %wu or more bytes at offsets %s "
1569 "and %s overlaps between %wu and %wu bytes "
1571 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1572 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
1574 warning_at (loc
, OPT_Wrestrict
,
1575 "%G%qD accessing %wu or more bytes at offsets %s "
1576 "and %s overlaps %wu or more bytes at offset %s",
1577 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1578 ovlsiz
[0], offstr
[2]);
1582 /* Use more concise wording when one of the offsets is unbounded
1583 to avoid confusing the user with large and mostly meaningless
1586 if (DECL_P (dstref
.base
) && TREE_CODE (TREE_TYPE (dstref
.base
)) == ARRAY_TYPE
)
1587 open_range
= ((dstref
.offrange
[0] == 0
1588 && dstref
.offrange
[1] == maxobjsize
)
1589 || (srcref
.offrange
[0] == 0
1590 && srcref
.offrange
[1] == maxobjsize
));
1592 open_range
= ((dstref
.offrange
[0] == -maxobjsize
- 1
1593 && dstref
.offrange
[1] == maxobjsize
)
1594 || (srcref
.offrange
[0] == -maxobjsize
- 1
1595 && srcref
.offrange
[1] == maxobjsize
));
1597 if (sizrange
[0] == sizrange
[1] || sizrange
[1] == 1)
1602 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1603 "%G%qD accessing %wu byte may overlap "
1605 "%G%qD accessing %wu bytes may overlap "
1607 call
, func
, sizrange
[1], ovlsiz
[1]);
1609 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1610 "%G%qD accessing %wu byte at offsets %s "
1611 "and %s may overlap %wu byte at offset %s",
1612 "%G%qD accessing %wu bytes at offsets %s "
1613 "and %s may overlap %wu byte at offset %s",
1614 call
, func
, sizrange
[1], offstr
[0], offstr
[1],
1615 ovlsiz
[1], offstr
[2]);
1620 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1621 "%G%qD accessing %wu byte may overlap "
1623 "%G%qD accessing %wu bytes may overlap "
1625 call
, func
, sizrange
[1], ovlsiz
[1]);
1627 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1628 "%G%qD accessing %wu byte at offsets %s and "
1629 "%s may overlap up to %wu bytes at offset %s",
1630 "%G%qD accessing %wu bytes at offsets %s and "
1631 "%s may overlap up to %wu bytes at offset %s",
1632 call
, func
, sizrange
[1], offstr
[0], offstr
[1],
1633 ovlsiz
[1], offstr
[2]);
1637 if (sizrange
[1] >= 0 && sizrange
[1] < maxobjsize
.to_shwi ())
1640 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1641 "%G%qD accessing between %wu and %wu bytes "
1642 "may overlap %wu byte",
1643 "%G%qD accessing between %wu and %wu bytes "
1644 "may overlap up to %wu bytes",
1645 call
, func
, sizrange
[0], sizrange
[1], ovlsiz
[1]);
1647 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1648 "%G%qD accessing between %wu and %wu bytes "
1649 "at offsets %s and %s may overlap %wu byte "
1651 "%G%qD accessing between %wu and %wu bytes "
1652 "at offsets %s and %s may overlap up to %wu "
1653 "bytes at offset %s",
1654 call
, func
, sizrange
[0], sizrange
[1],
1655 offstr
[0], offstr
[1], ovlsiz
[1], offstr
[2]);
1659 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1660 "%G%qD accessing %wu or more bytes at offsets %s "
1661 "and %s may overlap %wu byte at offset %s",
1662 "%G%qD accessing %wu or more bytes at offsets %s "
1663 "and %s may overlap up to %wu bytes at offset %s",
1664 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1665 ovlsiz
[1], offstr
[2]);
1670 /* Validate REF size and offsets in an expression passed as an argument
1671 to a CALL to a built-in function FUNC to make sure they are within
1672 the bounds of the referenced object if its size is known, or
1673 PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1674 be issued, false otherwise.
1675 Both initial values of the offsets and their final value computed
1676 by the function by incrementing the initial value by the size are
1677 validated. Return true if the offsets are not valid and a diagnostic
1678 has been issued, or would have been issued if DO_WARN had been true. */
1681 maybe_diag_access_bounds (gimple
*call
, tree func
, int strict
,
1682 const builtin_memref
&ref
, offset_int wroff
,
1685 location_t loc
= gimple_or_expr_nonartificial_location (call
, ref
.ptr
);
1686 const offset_int maxobjsize
= ref
.maxobjsize
;
1688 /* Check for excessive size first and regardless of warning options
1689 since the result is used to make codegen decisions. */
1690 if (ref
.sizrange
[0] > maxobjsize
)
1692 /* Return true without issuing a warning. */
1696 if (ref
.ref
&& TREE_NO_WARNING (ref
.ref
))
1699 if (warn_stringop_overflow
)
1701 if (ref
.sizrange
[0] == ref
.sizrange
[1])
1702 return warning_at (loc
, OPT_Wstringop_overflow_
,
1703 "%G%qD specified bound %wu "
1704 "exceeds maximum object size %wu",
1705 call
, func
, ref
.sizrange
[0].to_uhwi (),
1706 maxobjsize
.to_uhwi ());
1708 return warning_at (loc
, OPT_Wstringop_overflow_
,
1709 "%G%qD specified bound between %wu and %wu "
1710 "exceeds maximum object size %wu",
1711 call
, func
, ref
.sizrange
[0].to_uhwi (),
1712 ref
.sizrange
[1].to_uhwi (),
1713 maxobjsize
.to_uhwi ());
1717 /* Check for out-bounds pointers regardless of warning options since
1718 the result is used to make codegen decisions. An excessive WROFF
1719 can only come up as a result of an invalid strncat bound and is
1720 diagnosed separately using a more meaningful warning. */
1721 if (maxobjsize
< wroff
)
1723 offset_int ooboff
[] = { ref
.offrange
[0], ref
.offrange
[1], wroff
};
1724 tree oobref
= ref
.offset_out_of_bounds (strict
, ooboff
);
1728 /* Return true without issuing a warning. */
1732 if (!warn_array_bounds
)
1735 if (TREE_NO_WARNING (ref
.ptr
)
1736 || (ref
.ref
&& TREE_NO_WARNING (ref
.ref
)))
1739 char rangestr
[2][64];
1740 if (ooboff
[0] == ooboff
[1]
1741 || (ooboff
[0] != ref
.offrange
[0]
1742 && ooboff
[0].to_shwi () >= ooboff
[1].to_shwi ()))
1743 sprintf (rangestr
[0], "%lli", (long long) ooboff
[0].to_shwi ());
1745 sprintf (rangestr
[0], "[%lli, %lli]",
1746 (long long) ooboff
[0].to_shwi (),
1747 (long long) ooboff
[1].to_shwi ());
1749 bool warned
= false;
1751 if (oobref
== error_mark_node
)
1753 if (ref
.sizrange
[0] == ref
.sizrange
[1])
1754 sprintf (rangestr
[1], "%llu",
1755 (unsigned long long) ref
.sizrange
[0].to_shwi ());
1757 sprintf (rangestr
[1], "[%lli, %lli]",
1758 (unsigned long long) ref
.sizrange
[0].to_uhwi (),
1759 (unsigned long long) ref
.sizrange
[1].to_uhwi ());
1763 if (DECL_P (ref
.base
)
1764 && TREE_CODE (type
= TREE_TYPE (ref
.base
)) == ARRAY_TYPE
)
1766 auto_diagnostic_group d
;
1767 if (warning_at (loc
, OPT_Warray_bounds
,
1768 "%G%qD pointer overflow between offset %s "
1769 "and size %s accessing array %qD with type %qT",
1770 call
, func
, rangestr
[0], rangestr
[1], ref
.base
, type
))
1772 inform (DECL_SOURCE_LOCATION (ref
.base
),
1773 "array %qD declared here", ref
.base
);
1777 warned
= warning_at (loc
, OPT_Warray_bounds
,
1778 "%G%qD pointer overflow between offset %s "
1780 call
, func
, rangestr
[0], rangestr
[1]);
1783 warned
= warning_at (loc
, OPT_Warray_bounds
,
1784 "%G%qD pointer overflow between offset %s "
1786 call
, func
, rangestr
[0], rangestr
[1]);
1788 else if (oobref
== ref
.base
)
1790 /* True when the offset formed by an access to the reference
1791 is out of bounds, rather than the initial offset wich is
1792 in bounds. This implies access past the end. */
1793 bool form
= ooboff
[0] != ref
.offrange
[0];
1795 if (DECL_P (ref
.base
))
1797 auto_diagnostic_group d
;
1798 if ((ref
.basesize
< maxobjsize
1799 && warning_at (loc
, OPT_Warray_bounds
,
1801 ? G_("%G%qD forming offset %s is out of "
1802 "the bounds [0, %wu] of object %qD with "
1804 : G_("%G%qD offset %s is out of the bounds "
1805 "[0, %wu] of object %qD with type %qT"),
1806 call
, func
, rangestr
[0], ref
.basesize
.to_uhwi (),
1807 ref
.base
, TREE_TYPE (ref
.base
)))
1808 || warning_at (loc
, OPT_Warray_bounds
,
1810 ? G_("%G%qD forming offset %s is out of "
1811 "the bounds of object %qD with type %qT")
1812 : G_("%G%qD offset %s is out of the bounds "
1813 "of object %qD with type %qT"),
1814 call
, func
, rangestr
[0],
1815 ref
.base
, TREE_TYPE (ref
.base
)))
1817 inform (DECL_SOURCE_LOCATION (ref
.base
),
1818 "%qD declared here", ref
.base
);
1822 else if (ref
.basesize
< maxobjsize
)
1823 warned
= warning_at (loc
, OPT_Warray_bounds
,
1825 ? G_("%G%qD forming offset %s is out "
1826 "of the bounds [0, %wu]")
1827 : G_("%G%qD offset %s is out "
1828 "of the bounds [0, %wu]"),
1829 call
, func
, rangestr
[0], ref
.basesize
.to_uhwi ());
1831 warned
= warning_at (loc
, OPT_Warray_bounds
,
1833 ? G_("%G%qD forming offset %s is out of bounds")
1834 : G_("%G%qD offset %s is out of bounds"),
1835 call
, func
, rangestr
[0]);
1837 else if (TREE_CODE (ref
.ref
) == MEM_REF
)
1839 tree refop
= TREE_OPERAND (ref
.ref
, 0);
1840 tree type
= TREE_TYPE (refop
);
1841 if (POINTER_TYPE_P (type
))
1842 type
= TREE_TYPE (type
);
1843 type
= TYPE_MAIN_VARIANT (type
);
1845 if (warning_at (loc
, OPT_Warray_bounds
,
1846 "%G%qD offset %s from the object at %qE is out "
1847 "of the bounds of %qT",
1848 call
, func
, rangestr
[0], ref
.base
, type
))
1850 if (TREE_CODE (ref
.ref
) == COMPONENT_REF
)
1851 refop
= TREE_OPERAND (ref
.ref
, 1);
1853 inform (DECL_SOURCE_LOCATION (refop
),
1854 "subobject %qD declared here", refop
);
1860 tree refop
= TREE_OPERAND (ref
.ref
, 0);
1861 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (ref
.ref
));
1863 if (warning_at (loc
, OPT_Warray_bounds
,
1864 "%G%qD offset %s from the object at %qE is out "
1865 "of the bounds of referenced subobject %qD with "
1866 "type %qT at offset %wi",
1867 call
, func
, rangestr
[0], ref
.base
,
1868 TREE_OPERAND (ref
.ref
, 1), type
,
1869 ref
.refoff
.to_shwi ()))
1871 if (TREE_CODE (ref
.ref
) == COMPONENT_REF
)
1872 refop
= TREE_OPERAND (ref
.ref
, 1);
1874 inform (DECL_SOURCE_LOCATION (refop
),
1875 "subobject %qD declared here", refop
);
1883 /* Check a CALL statement for restrict-violations and issue warnings
1884 if/when appropriate. */
1887 check_call (range_query
*query
, gimple
*call
)
1889 /* Avoid checking the call if it has already been diagnosed for
1891 if (gimple_no_warning_p (call
))
1894 tree func
= gimple_call_fndecl (call
);
1895 if (!func
|| !fndecl_built_in_p (func
, BUILT_IN_NORMAL
))
1898 /* Argument number to extract from the call (depends on the built-in
1900 unsigned dst_idx
= -1;
1901 unsigned src_idx
= -1;
1902 unsigned bnd_idx
= -1;
1904 /* Is this CALL to a string function (as opposed to one to a raw
1905 memory function). */
1908 switch (DECL_FUNCTION_CODE (func
))
1910 case BUILT_IN_MEMCPY
:
1911 case BUILT_IN_MEMCPY_CHK
:
1912 case BUILT_IN_MEMPCPY
:
1913 case BUILT_IN_MEMPCPY_CHK
:
1914 case BUILT_IN_MEMMOVE
:
1915 case BUILT_IN_MEMMOVE_CHK
:
1919 case BUILT_IN_STPNCPY
:
1920 case BUILT_IN_STPNCPY_CHK
:
1921 case BUILT_IN_STRNCAT
:
1922 case BUILT_IN_STRNCAT_CHK
:
1923 case BUILT_IN_STRNCPY
:
1924 case BUILT_IN_STRNCPY_CHK
:
1930 case BUILT_IN_MEMSET
:
1931 case BUILT_IN_MEMSET_CHK
:
1936 case BUILT_IN_STPCPY
:
1937 case BUILT_IN_STPCPY_CHK
:
1938 case BUILT_IN_STRCPY
:
1939 case BUILT_IN_STRCPY_CHK
:
1940 case BUILT_IN_STRCAT
:
1941 case BUILT_IN_STRCAT_CHK
:
1947 /* Handle other string functions here whose access may need
1948 to be validated for in-bounds offsets and non-overlapping
1953 unsigned nargs
= gimple_call_num_args (call
);
1955 tree dst
= dst_idx
< nargs
? gimple_call_arg (call
, dst_idx
) : NULL_TREE
;
1956 tree src
= src_idx
< nargs
? gimple_call_arg (call
, src_idx
) : NULL_TREE
;
1957 tree dstwr
= bnd_idx
< nargs
? gimple_call_arg (call
, bnd_idx
) : NULL_TREE
;
1959 /* For string functions with an unspecified or unknown bound,
1960 assume the size of the access is one. */
1961 if (!dstwr
&& strfun
)
1962 dstwr
= size_one_node
;
1964 /* DST and SRC can be null for a call with an insufficient number
1965 of arguments to a built-in function declared without a protype. */
1966 if (!dst
|| (src_idx
< nargs
&& !src
))
1969 /* DST, SRC, or DSTWR can also have the wrong type in a call to
1970 a function declared without a prototype. Avoid checking such
1972 if (TREE_CODE (TREE_TYPE (dst
)) != POINTER_TYPE
1973 || (src
&& TREE_CODE (TREE_TYPE (src
)) != POINTER_TYPE
)
1974 || (dstwr
&& !INTEGRAL_TYPE_P (TREE_TYPE (dstwr
))))
1977 if (!check_bounds_or_overlap (query
, call
, dst
, src
, dstwr
, NULL_TREE
))
1980 /* Avoid diagnosing the call again. */
1981 gimple_set_no_warning (call
, true);
1984 } /* anonymous namespace */
1986 /* Attempt to detect and diagnose invalid offset bounds and (except for
1987 memmove) overlapping copy in a call expression EXPR from SRC to DST
1988 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
1989 SRCSIZE may be NULL. DO_WARN is false to detect either problem
1990 without issue a warning. Return the OPT_Wxxx constant corresponding
1991 to the warning if one has been detected and zero otherwise. */
1994 check_bounds_or_overlap (gimple
*call
, tree dst
, tree src
, tree dstsize
,
1995 tree srcsize
, bool bounds_only
/* = false */,
1996 bool do_warn
/* = true */)
1998 return check_bounds_or_overlap (/*range_query=*/NULL
,
1999 call
, dst
, src
, dstsize
, srcsize
,
2000 bounds_only
, do_warn
);
2004 check_bounds_or_overlap (range_query
*query
,
2005 gimple
*call
, tree dst
, tree src
, tree dstsize
,
2006 tree srcsize
, bool bounds_only
/* = false */,
2007 bool do_warn
/* = true */)
2009 tree func
= gimple_call_fndecl (call
);
2011 builtin_memref
dstref (query
, call
, dst
, dstsize
);
2012 builtin_memref
srcref (query
, call
, src
, srcsize
);
2014 /* Create a descriptor of the access. This may adjust both DSTREF
2015 and SRCREF based on one another and the kind of the access. */
2016 builtin_access
acs (query
, call
, dstref
, srcref
);
2018 /* Set STRICT to the value of the -Warray-bounds=N argument for
2019 string functions or when N > 1. */
2020 int strict
= (acs
.strict () || warn_array_bounds
> 1 ? warn_array_bounds
: 0);
2022 /* The starting offset of the destination write access. Nonzero only
2023 for the strcat family of functions. */
2024 offset_int wroff
= acs
.write_off (dstsize
);
2026 /* Validate offsets to each reference before the access first to make
2027 sure they are within the bounds of the destination object if its
2028 size is known, or PTRDIFF_MAX otherwise. */
2029 if (maybe_diag_access_bounds (call
, func
, strict
, dstref
, wroff
, do_warn
)
2030 || maybe_diag_access_bounds (call
, func
, strict
, srcref
, 0, do_warn
))
2033 gimple_set_no_warning (call
, true);
2034 return OPT_Warray_bounds
;
2037 if (!warn_restrict
|| bounds_only
|| !src
)
2042 switch (DECL_FUNCTION_CODE (func
))
2044 case BUILT_IN_MEMMOVE
:
2045 case BUILT_IN_MEMMOVE_CHK
:
2046 case BUILT_IN_MEMSET
:
2047 case BUILT_IN_MEMSET_CHK
:
2054 location_t loc
= gimple_or_expr_nonartificial_location (call
, dst
);
2055 if (operand_equal_p (dst
, src
, 0))
2057 /* Issue -Wrestrict unless the pointers are null (those do
2058 not point to objects and so do not indicate an overlap;
2059 such calls could be the result of sanitization and jump
2061 if (!integer_zerop (dst
) && !gimple_no_warning_p (call
))
2063 warning_at (loc
, OPT_Wrestrict
,
2064 "%G%qD source argument is the same as destination",
2066 gimple_set_no_warning (call
, true);
2067 return OPT_Wrestrict
;
2073 /* Return false when overlap has been detected. */
2074 if (maybe_diag_overlap (loc
, call
, acs
))
2076 gimple_set_no_warning (call
, true);
2077 return OPT_Wrestrict
;
2084 make_pass_warn_restrict (gcc::context
*ctxt
)
2086 return new pass_wrestrict (ctxt
);
2090 dump_builtin_memref (FILE *fp
, const builtin_memref
&ref
)
2092 fprintf (fp
, "\n ptr = ");
2093 print_generic_expr (fp
, ref
.ptr
, TDF_LINENO
);
2094 fprintf (fp
, "\n ref = ");
2096 print_generic_expr (fp
, ref
.ref
, TDF_LINENO
);
2099 fprintf (fp
, "\n base = ");
2100 print_generic_expr (fp
, ref
.base
, TDF_LINENO
);
2102 "\n basesize = %lli"
2105 "\n offrange = [%lli, %lli]"
2106 "\n sizrange = [%lli, %lli]"
2107 "\n strbounded_p = %s\n",
2108 (long long)ref
.basesize
.to_shwi (),
2109 (long long)ref
.refsize
.to_shwi (),
2110 (long long)ref
.refoff
.to_shwi (),
2111 (long long)ref
.offrange
[0].to_shwi (),
2112 (long long)ref
.offrange
[1].to_shwi (),
2113 (long long)ref
.sizrange
[0].to_shwi (),
2114 (long long)ref
.sizrange
[1].to_shwi (),
2115 ref
.strbounded_p
? "true" : "false");
2119 builtin_access::dump (FILE *fp
) const
2121 fprintf (fp
, " dstref:");
2122 dump_builtin_memref (fp
, *dstref
);
2123 fprintf (fp
, "\n srcref:");
2124 dump_builtin_memref (fp
, *srcref
);
2127 " sizrange = [%lli, %lli]\n"
2128 " ovloff = [%lli, %lli]\n"
2129 " ovlsiz = [%lli, %lli]\n"
2130 " dstoff = [%lli, %lli]\n"
2131 " dstsiz = [%lli, %lli]\n"
2132 " srcoff = [%lli, %lli]\n"
2133 " srcsiz = [%lli, %lli]\n",
2134 (long long)sizrange
[0], (long long)sizrange
[1],
2135 (long long)ovloff
[0], (long long)ovloff
[1],
2136 (long long)ovlsiz
[0], (long long)ovlsiz
[1],
2137 (long long)dstoff
[0].to_shwi (), (long long)dstoff
[1].to_shwi (),
2138 (long long)dstsiz
[0].to_shwi (), (long long)dstsiz
[1].to_shwi (),
2139 (long long)srcoff
[0].to_shwi (), (long long)srcoff
[1].to_shwi (),
2140 (long long)srcsiz
[0].to_shwi (), (long long)srcsiz
[1].to_shwi ());
2144 dump_builtin_access (FILE *fp
, gimple
*stmt
, const builtin_access
&acs
)
2148 fprintf (fp
, "\nDumping builtin_access for ");
2149 print_gimple_expr (fp
, stmt
, TDF_LINENO
);
2157 debug (gimple
*stmt
, const builtin_access
&acs
)
2159 dump_builtin_access (stdout
, stmt
, acs
);