1 /* Pass to detect and issue warnings for violations of the restrict
3 Copyright (C) 2017-2019 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"
29 #include "tree-pass.h"
32 #include "gimple-pretty-print.h"
33 #include "gimple-ssa-warn-restrict.h"
34 #include "diagnostic-core.h"
35 #include "fold-const.h"
36 #include "gimple-iterator.h"
41 #include "tree-object-size.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 /* Class to walk the basic blocks of a function in dominator order. */
82 class wrestrict_dom_walker
: public dom_walker
85 wrestrict_dom_walker () : dom_walker (CDI_DOMINATORS
) {}
87 edge
before_dom_children (basic_block
) FINAL OVERRIDE
;
88 bool handle_gimple_call (gimple_stmt_iterator
*);
91 void check_call (gimple
*);
95 wrestrict_dom_walker::before_dom_children (basic_block bb
)
97 /* Iterate over statements, looking for function calls. */
98 for (gimple_stmt_iterator si
= gsi_start_bb (bb
); !gsi_end_p (si
);
101 gimple
*stmt
= gsi_stmt (si
);
102 if (!is_gimple_call (stmt
))
111 /* Execute the pass for function FUN, walking in dominator order. */
114 pass_wrestrict::execute (function
*fun
)
116 calculate_dominance_info (CDI_DOMINATORS
);
118 wrestrict_dom_walker walker
;
119 walker
.walk (ENTRY_BLOCK_PTR_FOR_FN (fun
));
124 /* Description of a memory reference by a built-in function. This
125 is similar to ao_ref but made especially suitable for -Wrestrict
126 and not for optimization. */
130 /* The original pointer argument to the built-in function. */
132 /* The referenced subobject or NULL if not available, and the base
133 object of the memory reference or NULL. */
137 /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
138 and negative until (possibly lazily) initialized. */
140 /* Same for the subobject. */
143 /* The non-negative offset of the referenced subobject. Used to avoid
144 warnings for (apparently) possibly but not definitively overlapping
145 accesses to member arrays. Negative when unknown/invalid. */
148 /* The offset range relative to the base. */
149 offset_int offrange
[2];
150 /* The size range of the access to this reference. */
151 offset_int sizrange
[2];
153 /* Cached result of get_max_objsize(). */
154 const offset_int maxobjsize
;
156 /* True for "bounded" string functions like strncat, and strncpy
157 and their variants that specify either an exact or upper bound
158 on the size of the accesses they perform. For strncat both
159 the source and destination references are bounded. For strncpy
160 only the destination reference is. */
163 builtin_memref (tree
, tree
);
165 tree
offset_out_of_bounds (int, offset_int
[3]) const;
169 /* Ctor helper to set or extend OFFRANGE based on argument. */
170 void extend_offset_range (tree
);
172 /* Ctor helper to determine BASE and OFFRANGE from argument. */
173 void set_base_and_offset (tree
);
176 /* Description of a memory access by a raw memory or string built-in
177 function involving a pair of builtin_memref's. */
181 /* Destination and source memory reference. */
182 builtin_memref
* const dstref
;
183 builtin_memref
* const srcref
;
184 /* The size range of the access. It's the greater of the accesses
185 to the two references. */
186 HOST_WIDE_INT sizrange
[2];
188 /* The minimum and maximum offset of an overlap of the access
189 (if it does, in fact, overlap), and the size of the overlap. */
190 HOST_WIDE_INT ovloff
[2];
191 HOST_WIDE_INT ovlsiz
[2];
193 /* True to consider valid only accesses to the smallest subobject
194 and false for raw memory functions. */
197 return (detect_overlap
!= &builtin_access::generic_overlap
198 && detect_overlap
!= &builtin_access::no_overlap
);
201 builtin_access (gimple
*, builtin_memref
&, builtin_memref
&);
203 /* Entry point to determine overlap. */
206 offset_int
write_off (tree
) const;
208 void dump (FILE *) const;
211 /* Implementation functions used to determine overlap. */
212 bool generic_overlap ();
213 bool strcat_overlap ();
214 bool strcpy_overlap ();
221 offset_int
overlap_size (const offset_int
[2], const offset_int
[2],
225 /* Temporaries used to compute the final result. */
226 offset_int dstoff
[2];
227 offset_int srcoff
[2];
228 offset_int dstsiz
[2];
229 offset_int srcsiz
[2];
231 /* Pointer to a member function to call to determine overlap. */
232 bool (builtin_access::*detect_overlap
) ();
235 /* Initialize a memory reference representation from a pointer EXPR and
236 a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed
239 builtin_memref::builtin_memref (tree expr
, tree size
)
245 refoff (HOST_WIDE_INT_MIN
),
248 maxobjsize (tree_to_shwi (max_object_size ())),
251 /* Unfortunately, wide_int default ctor is a no-op so array members
252 of the type must be set individually. */
253 offrange
[0] = offrange
[1] = 0;
254 sizrange
[0] = sizrange
[1] = 0;
259 /* Find the BASE object or pointer referenced by EXPR and set
260 the offset range OFFRANGE in the process. */
261 set_base_and_offset (expr
);
266 /* Determine the size range, allowing for the result to be [0, 0]
267 for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */
268 get_size_range (size
, range
, true);
269 sizrange
[0] = wi::to_offset (range
[0]);
270 sizrange
[1] = wi::to_offset (range
[1]);
271 /* get_size_range returns SIZE_MAX for the maximum size.
272 Constrain it to the real maximum of PTRDIFF_MAX. */
273 if (sizrange
[0] <= maxobjsize
&& sizrange
[1] > maxobjsize
)
274 sizrange
[1] = maxobjsize
;
277 sizrange
[1] = maxobjsize
;
282 /* If the offset could be in the range of the referenced object
283 constrain its bounds so neither exceeds those of the object. */
284 if (offrange
[0] < 0 && offrange
[1] > 0)
287 offset_int maxoff
= maxobjsize
;
288 tree basetype
= TREE_TYPE (base
);
289 if (TREE_CODE (basetype
) == ARRAY_TYPE
)
291 if (ref
&& array_at_struct_end_p (ref
))
292 ; /* Use the maximum possible offset for last member arrays. */
293 else if (tree basesize
= TYPE_SIZE_UNIT (basetype
))
294 if (TREE_CODE (basesize
) == INTEGER_CST
)
295 /* Size could be non-constant for a variable-length type such
296 as a struct with a VLA member (a GCC extension). */
297 maxoff
= wi::to_offset (basesize
);
300 if (offrange
[0] >= 0)
303 offrange
[1] = offrange
[0] <= maxoff
? maxoff
: maxobjsize
;
304 else if (offrange
[0] <= maxoff
&& offrange
[1] > maxoff
)
305 offrange
[1] = maxoff
;
309 /* Based on the initial length of the destination STARTLEN, returns
310 the offset of the first write access from the beginning of
311 the destination. Nonzero only for strcat-type of calls. */
313 offset_int
builtin_access::write_off (tree startlen
) const
315 if (detect_overlap
!= &builtin_access::strcat_overlap
316 || !startlen
|| TREE_CODE (startlen
) != INTEGER_CST
)
319 return wi::to_offset (startlen
);
322 /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
323 Pointer offsets are represented as unsigned sizetype but must be
324 treated as signed. */
327 builtin_memref::extend_offset_range (tree offset
)
329 if (TREE_CODE (offset
) == INTEGER_CST
)
331 offset_int off
= int_cst_value (offset
);
340 if (TREE_CODE (offset
) == SSA_NAME
)
342 /* A pointer offset is represented as sizetype but treated
345 value_range_kind rng
= get_range_info (offset
, &min
, &max
);
346 if (rng
== VR_ANTI_RANGE
&& wi::lts_p (max
, min
))
348 /* Convert an anti-range whose upper bound is less than
349 its lower bound to a signed range. */
350 offrange
[0] += offset_int::from (max
+ 1, SIGNED
);
351 offrange
[1] += offset_int::from (min
- 1, SIGNED
);
356 && (DECL_P (base
) || wi::lts_p (min
, max
)))
358 /* Preserve the bounds of the range for an offset into
359 a known object (it may be adjusted later relative to
360 a constant offset from its beginning). Otherwise use
361 the bounds only when they are ascending when treated
363 offrange
[0] += offset_int::from (min
, SIGNED
);
364 offrange
[1] += offset_int::from (max
, SIGNED
);
368 /* Handle an anti-range the same as no range at all. */
369 gimple
*stmt
= SSA_NAME_DEF_STMT (offset
);
371 if (is_gimple_assign (stmt
)
372 && (type
= TREE_TYPE (gimple_assign_rhs1 (stmt
)))
373 && INTEGRAL_TYPE_P (type
))
375 tree_code code
= gimple_assign_rhs_code (stmt
);
376 if (code
== NOP_EXPR
)
378 /* Use the bounds of the type of the NOP_EXPR operand
379 even if it's signed. The result doesn't trigger
380 warnings but makes their output more readable. */
381 offrange
[0] += wi::to_offset (TYPE_MIN_VALUE (type
));
382 offrange
[1] += wi::to_offset (TYPE_MAX_VALUE (type
));
388 const offset_int maxoff
= tree_to_shwi (max_object_size ()) >> 1;
389 const offset_int minoff
= -maxoff
- 1;
391 offrange
[0] += minoff
;
392 offrange
[1] += maxoff
;
395 /* Determines the base object or pointer of the reference EXPR
396 and the offset range from the beginning of the base. */
399 builtin_memref::set_base_and_offset (tree expr
)
401 tree offset
= NULL_TREE
;
403 if (TREE_CODE (expr
) == SSA_NAME
)
405 /* Try to tease the offset out of the pointer. */
406 gimple
*stmt
= SSA_NAME_DEF_STMT (expr
);
408 && gimple_assign_single_p (stmt
)
409 && gimple_assign_rhs_code (stmt
) == ADDR_EXPR
)
410 expr
= gimple_assign_rhs1 (stmt
);
411 else if (is_gimple_assign (stmt
))
413 tree_code code
= gimple_assign_rhs_code (stmt
);
414 if (code
== NOP_EXPR
)
416 tree rhs
= gimple_assign_rhs1 (stmt
);
417 if (POINTER_TYPE_P (TREE_TYPE (rhs
)))
418 expr
= gimple_assign_rhs1 (stmt
);
425 else if (code
== POINTER_PLUS_EXPR
)
427 expr
= gimple_assign_rhs1 (stmt
);
428 offset
= gimple_assign_rhs2 (stmt
);
438 /* FIXME: Handle PHI nodes in case like:
439 _12 = &MEM[(void *)&a + 2B] + _10;
441 <bb> [local count: 1073741824]:
442 # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
443 memcpy (prephitmp_13, p_7(D), 6); */
449 if (TREE_CODE (expr
) == ADDR_EXPR
)
450 expr
= TREE_OPERAND (expr
, 0);
452 /* Stash the reference for offset validation. */
455 poly_int64 bitsize
, bitpos
;
458 int sign
, reverse
, vol
;
460 /* Determine the base object or pointer of the reference and
461 the constant bit offset from the beginning of the base.
462 If the offset has a non-constant component, it will be in
463 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
465 base
= get_inner_reference (expr
, &bitsize
, &bitpos
, &var_off
,
466 &mode
, &sign
, &reverse
, &vol
);
468 /* get_inner_reference is not expected to return null. */
469 gcc_assert (base
!= NULL
);
472 extend_offset_range (offset
);
474 poly_int64 bytepos
= exact_div (bitpos
, BITS_PER_UNIT
);
476 /* Convert the poly_int64 offset to offset_int. The offset
477 should be constant but be prepared for it not to be just in
480 if (bytepos
.is_constant (&cstoff
))
482 offrange
[0] += cstoff
;
483 offrange
[1] += cstoff
;
485 /* Besides the reference saved above, also stash the offset
487 if (TREE_CODE (expr
) == COMPONENT_REF
)
491 offrange
[1] += maxobjsize
;
495 if (TREE_CODE (var_off
) == INTEGER_CST
)
497 cstoff
= wi::to_offset (var_off
);
498 offrange
[0] += cstoff
;
499 offrange
[1] += cstoff
;
502 offrange
[1] += maxobjsize
;
505 if (TREE_CODE (base
) == MEM_REF
)
507 tree memrefoff
= fold_convert (ptrdiff_type_node
, TREE_OPERAND (base
, 1));
508 extend_offset_range (memrefoff
);
509 base
= TREE_OPERAND (base
, 0);
511 if (refoff
!= HOST_WIDE_INT_MIN
512 && TREE_CODE (expr
) == COMPONENT_REF
)
514 /* Bump up the offset of the referenced subobject to reflect
515 the offset to the enclosing object. For example, so that
517 struct S { char a, b[3]; } s[2];
518 strcpy (s[1].b, "1234");
519 REFOFF is set to s[1].b - (char*)s. */
520 offset_int off
= tree_to_shwi (memrefoff
);
524 if (!integer_zerop (memrefoff
))
525 /* A non-zero offset into an array of struct with flexible array
526 members implies that the array is empty because there is no
527 way to initialize such a member when it belongs to an array.
528 This must be some sort of a bug. */
532 if (TREE_CODE (ref
) == COMPONENT_REF
)
533 if (tree size
= component_ref_size (ref
))
534 if (TREE_CODE (size
) == INTEGER_CST
)
535 refsize
= wi::to_offset (size
);
537 if (TREE_CODE (base
) == SSA_NAME
)
538 set_base_and_offset (base
);
541 /* Return error_mark_node if the signed offset exceeds the bounds
542 of the address space (PTRDIFF_MAX). Otherwise, return either BASE
543 or REF when the offset exceeds the bounds of the BASE or REF object,
544 and set OOBOFF to the past-the-end offset formed by the reference,
545 including its size. OOBOFF is initially setto the range of offsets,
546 and OOBOFF[2] to the offset of the first write access (nonzero for
547 the strcat family). When STRICT is nonzero use REF size, when
548 available, otherwise use BASE size. When STRICT is greater than 1,
549 use the size of the last array member as the bound, otherwise treat
550 such a member as a flexible array member. Return NULL when the offset
554 builtin_memref::offset_out_of_bounds (int strict
, offset_int ooboff
[3]) const
559 /* The offset of the first write access or zero. */
560 offset_int wroff
= ooboff
[2];
562 /* A temporary, possibly adjusted, copy of the offset range. */
563 offset_int offrng
[2] = { ooboff
[0], ooboff
[1] };
565 if (DECL_P (base
) && TREE_CODE (TREE_TYPE (base
)) == ARRAY_TYPE
)
567 /* Check for offset in an anti-range with a negative lower bound.
568 For such a range, consider only the non-negative subrange. */
569 if (offrng
[1] < offrng
[0] && offrng
[1] < 0)
570 offrng
[1] = maxobjsize
;
573 /* Conservative offset of the last byte of the referenced object. */
576 /* The bounds need not be ordered. Set HIB to use as the index
577 of the larger of the bounds and LOB as the opposite. */
578 bool hib
= wi::les_p (offrng
[0], offrng
[1]);
581 /* Set to the size remaining in the object object after subtracting
582 REFOFF. It may become negative as a result of negative indices
583 into the enclosing object, such as in:
584 extern struct S { char a[4], b[3], c[1]; } *p;
585 strcpy (p[-3].b, "123"); */
586 offset_int size
= basesize
;
589 const bool decl_p
= DECL_P (obj
);
593 endoff
= offrng
[lob
] + (sizrange
[0] - wroff
);
595 /* For a reference through a pointer to an object of unknown size
596 all initial offsets are considered valid, positive as well as
597 negative, since the pointer itself can point past the beginning
598 of the object. However, the sum of the lower bound of the offset
599 and that of the size must be less than or equal than PTRDIFF_MAX. */
600 if (endoff
> maxobjsize
)
601 return error_mark_node
;
603 /* When the referenced subobject is known, the end offset must be
604 within its bounds. Otherwise there is nothing to do. */
609 && TREE_CODE (ref
) == COMPONENT_REF
)
611 /* If REFOFF is negative, SIZE will become negative here. */
612 size
= refoff
+ refsize
;
619 /* A reference to an object of known size must be within the bounds
620 of either the base object or the subobject (see above for when
621 a subobject can be used). */
622 if ((decl_p
&& offrng
[hib
] < 0) || offrng
[lob
] > size
)
625 /* The extent of the reference must also be within the bounds of
626 the base object (if known) or the subobject or the maximum object
628 endoff
= offrng
[lob
] + sizrange
[0];
629 if (endoff
> maxobjsize
)
630 return error_mark_node
;
636 && TREE_CODE (ref
) == COMPONENT_REF
)
638 /* If the reference is to a member subobject of a declared object,
639 the offset must be within the bounds of the subobject. */
640 size
= refoff
+ refsize
;
647 /* Set the out-of-bounds offset range to be one greater than
648 that delimited by the reference including its size. */
651 if (endoff
> ooboff
[lob
])
652 ooboff
[hib
] = endoff
- 1;
654 ooboff
[hib
] = offrng
[lob
] + sizrange
[1];
659 /* Create an association between the memory references DST and SRC
660 for access by a call EXPR to a memory or string built-in funtion. */
662 builtin_access::builtin_access (gimple
*call
, builtin_memref
&dst
,
664 : dstref (&dst
), srcref (&src
), sizrange (), ovloff (), ovlsiz (),
665 dstoff (), srcoff (), dstsiz (), srcsiz ()
667 dstoff
[0] = dst
.offrange
[0];
668 dstoff
[1] = dst
.offrange
[1];
670 /* Zero out since the offset_int ctors invoked above are no-op. */
671 srcoff
[0] = srcoff
[1] = 0;
672 dstsiz
[0] = dstsiz
[1] = 0;
673 srcsiz
[0] = srcsiz
[1] = 0;
675 /* Object Size Type to use to determine the size of the destination
676 and source objects. Overridden below for raw memory functions. */
679 /* True when the size of one reference depends on the offset of
680 itself or the other. */
681 bool depends_p
= true;
683 /* True when the size of the destination reference DSTREF has been
684 determined from SRCREF and so needs to be adjusted by the latter's
685 offset. Only meaningful for bounded string functions like strncpy. */
686 bool dstadjust_p
= false;
688 /* The size argument number (depends on the built-in). */
689 unsigned sizeargno
= 2;
691 tree func
= gimple_call_fndecl (call
);
692 switch (DECL_FUNCTION_CODE (func
))
694 case BUILT_IN_MEMCPY
:
695 case BUILT_IN_MEMCPY_CHK
:
696 case BUILT_IN_MEMPCPY
:
697 case BUILT_IN_MEMPCPY_CHK
:
700 detect_overlap
= &builtin_access::generic_overlap
;
703 case BUILT_IN_MEMMOVE
:
704 case BUILT_IN_MEMMOVE_CHK
:
705 /* For memmove there is never any overlap to check for. */
708 detect_overlap
= &builtin_access::no_overlap
;
711 case BUILT_IN_MEMSET
:
712 case BUILT_IN_MEMSET_CHK
:
713 /* For memset there is never any overlap to check for. */
716 detect_overlap
= &builtin_access::no_overlap
;
719 case BUILT_IN_STPNCPY
:
720 case BUILT_IN_STPNCPY_CHK
:
721 case BUILT_IN_STRNCPY
:
722 case BUILT_IN_STRNCPY_CHK
:
723 dstref
->strbounded_p
= true;
724 detect_overlap
= &builtin_access::strcpy_overlap
;
727 case BUILT_IN_STPCPY
:
728 case BUILT_IN_STPCPY_CHK
:
729 case BUILT_IN_STRCPY
:
730 case BUILT_IN_STRCPY_CHK
:
731 detect_overlap
= &builtin_access::strcpy_overlap
;
734 case BUILT_IN_STRCAT
:
735 case BUILT_IN_STRCAT_CHK
:
736 detect_overlap
= &builtin_access::strcat_overlap
;
739 case BUILT_IN_STRNCAT
:
740 case BUILT_IN_STRNCAT_CHK
:
741 dstref
->strbounded_p
= true;
742 srcref
->strbounded_p
= true;
743 detect_overlap
= &builtin_access::strcat_overlap
;
747 /* Handle other string functions here whose access may need
748 to be validated for in-bounds offsets and non-overlapping
753 const offset_int maxobjsize
= dst
.maxobjsize
;
755 /* Try to determine the size of the base object. compute_objsize
756 expects a pointer so create one if BASE is a non-pointer object. */
758 if (dst
.basesize
< 0)
761 if (!POINTER_TYPE_P (TREE_TYPE (addr
)))
762 addr
= build1 (ADDR_EXPR
, (TREE_TYPE (addr
)), addr
);
764 if (tree dstsize
= compute_objsize (addr
, ostype
))
765 dst
.basesize
= wi::to_offset (dstsize
);
766 else if (POINTER_TYPE_P (TREE_TYPE (addr
)))
767 dst
.basesize
= HOST_WIDE_INT_MIN
;
769 dst
.basesize
= maxobjsize
;
772 if (src
.base
&& src
.basesize
< 0)
775 if (!POINTER_TYPE_P (TREE_TYPE (addr
)))
776 addr
= build1 (ADDR_EXPR
, (TREE_TYPE (addr
)), addr
);
778 if (tree srcsize
= compute_objsize (addr
, ostype
))
779 src
.basesize
= wi::to_offset (srcsize
);
780 else if (POINTER_TYPE_P (TREE_TYPE (addr
)))
781 src
.basesize
= HOST_WIDE_INT_MIN
;
783 src
.basesize
= maxobjsize
;
786 /* Make adjustments for references to the same object by string
787 built-in functions to reflect the constraints imposed by
790 /* For bounded string functions determine the range of the bound
791 on the access. For others, the range stays unbounded. */
792 offset_int bounds
[2] = { maxobjsize
, maxobjsize
};
793 if (dstref
->strbounded_p
)
795 unsigned nargs
= gimple_call_num_args (call
);
796 if (nargs
<= sizeargno
)
799 tree size
= gimple_call_arg (call
, sizeargno
);
801 if (get_size_range (size
, range
, true))
803 bounds
[0] = wi::to_offset (range
[0]);
804 bounds
[1] = wi::to_offset (range
[1]);
807 /* If both references' size ranges are indeterminate use the last
808 (size) argument from the function call as a substitute. This
809 may only be necessary for strncpy (but not for memcpy where
810 the size range would have been already determined this way). */
811 if (dstref
->sizrange
[0] == 0 && dstref
->sizrange
[1] == maxobjsize
812 && srcref
->sizrange
[0] == 0 && srcref
->sizrange
[1] == maxobjsize
)
814 dstref
->sizrange
[0] = bounds
[0];
815 dstref
->sizrange
[1] = bounds
[1];
819 bool dstsize_set
= false;
820 /* The size range of one reference involving the same base object
821 can be determined from the size range of the other reference.
822 This makes it possible to compute accurate offsets for warnings
823 involving functions like strcpy where the length of just one of
824 the two arguments is known (determined by tree-ssa-strlen). */
825 if (dstref
->sizrange
[0] == 0 && dstref
->sizrange
[1] == maxobjsize
)
827 /* When the destination size is unknown set it to the size of
829 dstref
->sizrange
[0] = srcref
->sizrange
[0];
830 dstref
->sizrange
[1] = srcref
->sizrange
[1];
833 else if (srcref
->sizrange
[0] == 0 && srcref
->sizrange
[1] == maxobjsize
)
835 /* When the source size is unknown set it to the size of
837 srcref
->sizrange
[0] = dstref
->sizrange
[0];
838 srcref
->sizrange
[1] = dstref
->sizrange
[1];
842 if (dstref
->strbounded_p
)
844 /* Read access by strncpy is constrained by the third
845 argument but except for a zero bound is at least one. */
846 offset_int size
= wi::umax (srcref
->basesize
, 1);
847 offset_int bound
= wi::umin (size
, bounds
[0]);
848 if (bound
< srcref
->sizrange
[0])
849 srcref
->sizrange
[0] = bound
;
850 bound
= wi::umin (srcref
->basesize
, bounds
[1]);
851 if (bound
< srcref
->sizrange
[1])
852 srcref
->sizrange
[1] = bound
;
855 /* For string functions, adjust the size range of the source
856 reference by the inverse boundaries of the offset (because
857 the higher the offset into the string the shorter its
859 if (srcref
->offrange
[1] >= 0
860 && srcref
->offrange
[1] < srcref
->sizrange
[0])
861 srcref
->sizrange
[0] -= srcref
->offrange
[1];
863 srcref
->sizrange
[0] = 0;
865 if (srcref
->offrange
[0] > 0)
867 if (srcref
->offrange
[0] < srcref
->sizrange
[1])
868 srcref
->sizrange
[1] -= srcref
->offrange
[0];
870 srcref
->sizrange
[1] = 0;
877 if (detect_overlap
== &builtin_access::generic_overlap
)
879 if (dstref
->strbounded_p
)
881 dstref
->sizrange
[0] = bounds
[0];
882 dstref
->sizrange
[1] = bounds
[1];
884 if (dstref
->sizrange
[0] < srcref
->sizrange
[0])
885 srcref
->sizrange
[0] = dstref
->sizrange
[0];
887 if (dstref
->sizrange
[1] < srcref
->sizrange
[1])
888 srcref
->sizrange
[1] = dstref
->sizrange
[1];
891 else if (detect_overlap
== &builtin_access::strcpy_overlap
)
893 if (!dstref
->strbounded_p
)
895 /* For strcpy, adjust the destination size range to match that
896 of the source computed above. */
897 if (depends_p
&& dstadjust_p
)
899 dstref
->sizrange
[0] = srcref
->sizrange
[0];
900 dstref
->sizrange
[1] = srcref
->sizrange
[1];
904 else if (!dstsize_set
&& detect_overlap
== &builtin_access::strcat_overlap
)
906 dstref
->sizrange
[0] += srcref
->sizrange
[0] - 1;
907 dstref
->sizrange
[1] += srcref
->sizrange
[1] - 1;
910 if (dstref
->strbounded_p
)
912 /* For strncpy, adjust the destination size range to match that
913 of the source computed above. */
914 dstref
->sizrange
[0] = bounds
[0];
915 dstref
->sizrange
[1] = bounds
[1];
917 if (bounds
[0] < srcref
->sizrange
[0])
918 srcref
->sizrange
[0] = bounds
[0];
920 if (bounds
[1] < srcref
->sizrange
[1])
921 srcref
->sizrange
[1] = bounds
[1];
926 builtin_access::overlap_size (const offset_int a
[2], const offset_int b
[2],
929 const offset_int
*p
= a
;
930 const offset_int
*q
= b
;
932 /* Point P at the bigger of the two ranges and Q at the smaller. */
933 if (wi::lts_p (a
[1] - a
[0], b
[1] - b
[0]))
945 return wi::smin (p
[1], q
[1]) - q
[0];
955 /* Return true if the bounded mempry (memcpy amd similar) or string function
956 access (strncpy and similar) ACS overlaps. */
959 builtin_access::generic_overlap ()
961 builtin_access
&acs
= *this;
962 const builtin_memref
*dstref
= acs
.dstref
;
963 const builtin_memref
*srcref
= acs
.srcref
;
965 gcc_assert (dstref
->base
== srcref
->base
);
967 const offset_int maxobjsize
= acs
.dstref
->maxobjsize
;
969 offset_int maxsize
= dstref
->basesize
< 0 ? maxobjsize
: dstref
->basesize
;
970 gcc_assert (maxsize
<= maxobjsize
);
972 /* Adjust the larger bounds of the offsets (which may be the first
973 element if the lower bound is larger than the upper bound) to
974 make them valid for the smallest access (if possible) but no smaller
975 than the smaller bounds. */
976 gcc_assert (wi::les_p (acs
.dstoff
[0], acs
.dstoff
[1]));
978 if (maxsize
< acs
.dstoff
[1] + acs
.dstsiz
[0])
979 acs
.dstoff
[1] = maxsize
- acs
.dstsiz
[0];
980 if (acs
.dstoff
[1] < acs
.dstoff
[0])
981 acs
.dstoff
[1] = acs
.dstoff
[0];
983 gcc_assert (wi::les_p (acs
.srcoff
[0], acs
.srcoff
[1]));
985 if (maxsize
< acs
.srcoff
[1] + acs
.srcsiz
[0])
986 acs
.srcoff
[1] = maxsize
- acs
.srcsiz
[0];
987 if (acs
.srcoff
[1] < acs
.srcoff
[0])
988 acs
.srcoff
[1] = acs
.srcoff
[0];
990 /* Determine the minimum and maximum space for the access given
993 space
[0] = wi::abs (acs
.dstoff
[0] - acs
.srcoff
[0]);
996 offset_int d
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[1]);
997 if (acs
.srcsiz
[0] > 0)
1006 space
[1] = acs
.dstsiz
[1];
1008 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
1015 /* Treat raw memory functions both of whose references are bounded
1016 as special and permit uncertain overlaps to go undetected. For
1017 all kinds of constant offset and constant size accesses, if
1018 overlap isn't certain it is not possible. */
1019 bool overlap_possible
= space
[0] < acs
.dstsiz
[1];
1020 if (!overlap_possible
)
1023 bool overlap_certain
= space
[1] < acs
.dstsiz
[0];
1025 /* True when the size of one reference depends on the offset of
1027 bool depends_p
= detect_overlap
!= &builtin_access::generic_overlap
;
1029 if (!overlap_certain
)
1031 if (!dstref
->strbounded_p
&& !depends_p
)
1032 /* Memcpy only considers certain overlap. */
1035 /* There's no way to distinguish an access to the same member
1036 of a structure from one to two distinct members of the same
1037 structure. Give up to avoid excessive false positives. */
1038 tree basetype
= TREE_TYPE (dstref
->base
);
1040 if (POINTER_TYPE_P (basetype
))
1041 basetype
= TREE_TYPE (basetype
);
1043 while (TREE_CODE (basetype
) == ARRAY_TYPE
)
1044 basetype
= TREE_TYPE (basetype
);
1046 if (RECORD_OR_UNION_TYPE_P (basetype
))
1050 /* True for stpcpy and strcpy. */
1051 bool stxcpy_p
= (!dstref
->strbounded_p
1052 && detect_overlap
== &builtin_access::strcpy_overlap
);
1054 if (dstref
->refoff
>= 0
1055 && srcref
->refoff
>= 0
1056 && dstref
->refoff
!= srcref
->refoff
1057 && (stxcpy_p
|| dstref
->strbounded_p
|| srcref
->strbounded_p
))
1060 offset_int siz
[2] = { maxobjsize
+ 1, 0 };
1062 ovloff
[0] = HOST_WIDE_INT_MAX
;
1063 ovloff
[1] = HOST_WIDE_INT_MIN
;
1065 /* Adjustment to the lower bound of the offset of the overlap to
1066 account for a subset of unbounded string calls where the size
1067 of the destination string depends on the length of the source
1068 which in turn depends on the offset into it. */
1073 sub1
= acs
.dstoff
[0] <= acs
.srcoff
[0];
1075 /* Iterate over the extreme locations (on the horizontal axis formed
1076 by their offsets) and sizes of two regions and find their smallest
1077 and largest overlap and the corresponding offsets. */
1078 for (unsigned i
= 0; i
!= 2; ++i
)
1080 const offset_int a
[2] = {
1081 acs
.dstoff
[i
], acs
.dstoff
[i
] + acs
.dstsiz
[!i
]
1084 const offset_int b
[2] = {
1085 acs
.srcoff
[i
], acs
.srcoff
[i
] + acs
.srcsiz
[!i
]
1089 offset_int sz
= overlap_size (a
, b
, &off
);
1098 if (wi::lts_p (off
, ovloff
[0]))
1099 ovloff
[0] = off
.to_shwi ();
1100 if (wi::lts_p (ovloff
[1], off
))
1101 ovloff
[1] = off
.to_shwi ();
1109 /* Iterate over the extreme locations (on the horizontal axis
1110 formed by their offsets) and sizes of two regions and find
1111 their smallest and largest overlap and the corresponding
1114 for (unsigned io
= 0; io
!= 2; ++io
)
1115 for (unsigned is
= 0; is
!= 2; ++is
)
1117 const offset_int a
[2] = {
1118 acs
.dstoff
[io
], acs
.dstoff
[io
] + acs
.dstsiz
[is
]
1121 for (unsigned jo
= 0; jo
!= 2; ++jo
)
1122 for (unsigned js
= 0; js
!= 2; ++js
)
1126 /* For st{p,r}ncpy the size of the source sequence
1127 depends on the offset into it. */
1133 const offset_int b
[2] = {
1134 acs
.srcoff
[jo
], acs
.srcoff
[jo
] + acs
.srcsiz
[js
]
1138 offset_int sz
= overlap_size (a
, b
, &off
);
1147 if (wi::lts_p (off
, ovloff
[0]))
1148 ovloff
[0] = off
.to_shwi ();
1149 if (wi::lts_p (ovloff
[1], off
))
1150 ovloff
[1] = off
.to_shwi ();
1156 ovlsiz
[0] = siz
[0].to_shwi ();
1157 ovlsiz
[1] = siz
[1].to_shwi ();
1159 if (ovlsiz
[0] == 0 && ovlsiz
[1] > 1)
1160 ovloff
[0] = ovloff
[1] + ovlsiz
[1] - 1 - sub1
;
1165 /* Return true if the strcat-like access overlaps. */
1168 builtin_access::strcat_overlap ()
1170 builtin_access
&acs
= *this;
1171 const builtin_memref
*dstref
= acs
.dstref
;
1172 const builtin_memref
*srcref
= acs
.srcref
;
1174 gcc_assert (dstref
->base
== srcref
->base
);
1176 const offset_int maxobjsize
= acs
.dstref
->maxobjsize
;
1178 gcc_assert (dstref
->base
&& dstref
->base
== srcref
->base
);
1180 /* Adjust for strcat-like accesses. */
1182 /* As a special case for strcat, set the DSTREF offsets to the length
1183 of the destination string since the function starts writing over
1184 its terminating nul, and set the destination size to 1 for the length
1186 acs
.dstoff
[0] += dstsiz
[0] - srcref
->sizrange
[0];
1187 acs
.dstoff
[1] += dstsiz
[1] - srcref
->sizrange
[1];
1189 bool strfunc_unknown_args
= acs
.dstsiz
[0] == 0 && acs
.dstsiz
[1] != 0;
1191 /* The lower bound is zero when the size is unknown because then
1192 overlap is not certain. */
1193 acs
.dstsiz
[0] = strfunc_unknown_args
? 0 : 1;
1196 offset_int maxsize
= dstref
->basesize
< 0 ? maxobjsize
: dstref
->basesize
;
1197 gcc_assert (maxsize
<= maxobjsize
);
1199 /* For references to the same base object, determine if there's a pair
1200 of valid offsets into the two references such that access between
1201 them doesn't overlap. Adjust both upper bounds to be valid for
1202 the smaller size (i.e., at most MAXSIZE - SIZE). */
1204 if (maxsize
< acs
.dstoff
[1] + acs
.dstsiz
[0])
1205 acs
.dstoff
[1] = maxsize
- acs
.dstsiz
[0];
1207 if (maxsize
< acs
.srcoff
[1] + acs
.srcsiz
[0])
1208 acs
.srcoff
[1] = maxsize
- acs
.srcsiz
[0];
1210 /* Check to see if there's enough space for both accesses without
1211 overlap. Determine the optimistic (maximum) amount of available
1214 if (acs
.dstoff
[0] <= acs
.srcoff
[0])
1216 if (acs
.dstoff
[1] < acs
.srcoff
[1])
1217 space
= acs
.srcoff
[1] + acs
.srcsiz
[0] - acs
.dstoff
[0];
1219 space
= acs
.dstoff
[1] + acs
.dstsiz
[0] - acs
.srcoff
[0];
1222 space
= acs
.dstoff
[1] + acs
.dstsiz
[0] - acs
.srcoff
[0];
1224 /* Overlap is certain if the distance between the farthest offsets
1225 of the opposite accesses is less than the sum of the lower bounds
1226 of the sizes of the two accesses. */
1227 bool overlap_certain
= space
< acs
.dstsiz
[0] + acs
.srcsiz
[0];
1229 /* For a constant-offset, constant size access, consider the largest
1230 distance between the offset bounds and the lower bound of the access
1231 size. If the overlap isn't certain return success. */
1232 if (!overlap_certain
1233 && acs
.dstoff
[0] == acs
.dstoff
[1]
1234 && acs
.srcoff
[0] == acs
.srcoff
[1]
1235 && acs
.dstsiz
[0] == acs
.dstsiz
[1]
1236 && acs
.srcsiz
[0] == acs
.srcsiz
[1])
1239 /* Overlap is not certain but may be possible. */
1241 offset_int access_min
= acs
.dstsiz
[0] + acs
.srcsiz
[0];
1243 /* Determine the conservative (minimum) amount of space. */
1244 space
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[0]);
1245 offset_int d
= wi::abs (acs
.dstoff
[0] - acs
.srcoff
[1]);
1248 d
= wi::abs (acs
.dstoff
[1] - acs
.srcoff
[0]);
1252 /* For a strict test (used for strcpy and similar with unknown or
1253 variable bounds or sizes), consider the smallest distance between
1254 the offset bounds and either the upper bound of the access size
1255 if known, or the lower bound otherwise. */
1256 if (access_min
<= space
&& (access_min
!= 0 || !strfunc_unknown_args
))
1259 /* When strcat overlap is certain it is always a single byte:
1260 the terminating NUL, regardless of offsets and sizes. When
1261 overlap is only possible its range is [0, 1]. */
1262 acs
.ovlsiz
[0] = dstref
->sizrange
[0] == dstref
->sizrange
[1] ? 1 : 0;
1266 = dstref
->offrange
[0] + (dstref
->sizrange
[0] - srcref
->sizrange
[0]);
1267 if (endoff
<= srcref
->offrange
[0])
1268 acs
.ovloff
[0] = wi::smin (maxobjsize
, srcref
->offrange
[0]).to_shwi ();
1270 acs
.ovloff
[0] = wi::smin (maxobjsize
, endoff
).to_shwi ();
1272 acs
.sizrange
[0] = wi::smax (wi::abs (endoff
- srcref
->offrange
[0]) + 1,
1273 srcref
->sizrange
[0]).to_shwi ();
1274 if (dstref
->offrange
[0] == dstref
->offrange
[1])
1276 if (srcref
->offrange
[0] == srcref
->offrange
[1])
1277 acs
.ovloff
[1] = acs
.ovloff
[0];
1280 = wi::smin (maxobjsize
,
1281 srcref
->offrange
[1] + srcref
->sizrange
[1]).to_shwi ();
1285 = wi::smin (maxobjsize
,
1286 dstref
->offrange
[1] + dstref
->sizrange
[1]).to_shwi ();
1288 if (acs
.sizrange
[0] == 0)
1289 acs
.sizrange
[0] = 1;
1290 acs
.sizrange
[1] = wi::smax (acs
.dstsiz
[1], srcref
->sizrange
[1]).to_shwi ();
1294 /* Return true if the strcpy-like access overlaps. */
1297 builtin_access::strcpy_overlap ()
1299 return generic_overlap ();
1303 /* Return true if DSTREF and SRCREF describe accesses that either overlap
1304 one another or that, in order not to overlap, would imply that the size
1305 of the referenced object(s) exceeds the maximum size of an object. Set
1306 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1307 they may overlap in a way that's not apparent from the available data),
1311 builtin_access::overlap ()
1313 builtin_access
&acs
= *this;
1315 const offset_int maxobjsize
= dstref
->maxobjsize
;
1317 acs
.sizrange
[0] = wi::smax (dstref
->sizrange
[0],
1318 srcref
->sizrange
[0]).to_shwi ();
1319 acs
.sizrange
[1] = wi::smax (dstref
->sizrange
[1],
1320 srcref
->sizrange
[1]).to_shwi ();
1322 /* Check to see if the two references refer to regions that are
1323 too large not to overlap in the address space (whose maximum
1324 size is PTRDIFF_MAX). */
1325 offset_int size
= dstref
->sizrange
[0] + srcref
->sizrange
[0];
1326 if (maxobjsize
< size
)
1328 acs
.ovloff
[0] = (maxobjsize
- dstref
->sizrange
[0]).to_shwi ();
1329 acs
.ovlsiz
[0] = (size
- maxobjsize
).to_shwi ();
1333 /* If both base objects aren't known return the maximum possible
1334 offset that would make them not overlap. */
1335 if (!dstref
->base
|| !srcref
->base
)
1338 /* If the base object is an array adjust the bounds of the offset
1339 to be non-negative and within the bounds of the array if possible. */
1341 && TREE_CODE (TREE_TYPE (dstref
->base
)) == ARRAY_TYPE
)
1343 if (acs
.dstoff
[0] < 0 && acs
.dstoff
[1] >= 0)
1346 if (acs
.dstoff
[1] < acs
.dstoff
[0])
1348 if (tree size
= TYPE_SIZE_UNIT (TREE_TYPE (dstref
->base
)))
1349 acs
.dstoff
[1] = wi::umin (acs
.dstoff
[1], wi::to_offset (size
));
1351 acs
.dstoff
[1] = wi::umin (acs
.dstoff
[1], maxobjsize
);
1355 acs
.srcoff
[0] = srcref
->offrange
[0];
1356 acs
.srcoff
[1] = srcref
->offrange
[1];
1359 && TREE_CODE (TREE_TYPE (srcref
->base
)) == ARRAY_TYPE
)
1361 if (acs
.srcoff
[0] < 0 && acs
.srcoff
[1] >= 0)
1364 if (tree size
= TYPE_SIZE_UNIT (TREE_TYPE (srcref
->base
)))
1365 acs
.srcoff
[1] = wi::umin (acs
.srcoff
[1], wi::to_offset (size
));
1366 else if (acs
.srcoff
[1] < acs
.srcoff
[0])
1367 acs
.srcoff
[1] = wi::umin (acs
.srcoff
[1], maxobjsize
);
1370 /* When the upper bound of the offset is less than the lower bound
1371 the former is the result of a negative offset being represented
1372 as a large positive value or vice versa. The resulting range is
1373 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1374 a union is not representable using the current data structure
1375 replace it with the full range of offsets. */
1376 if (acs
.dstoff
[1] < acs
.dstoff
[0])
1378 acs
.dstoff
[0] = -maxobjsize
- 1;
1379 acs
.dstoff
[1] = maxobjsize
;
1382 /* Validate the offset and size of each reference on its own first.
1383 This is independent of whether or not the base objects are the
1384 same. Normally, this would have already been detected and
1385 diagnosed by -Warray-bounds, unless it has been disabled. */
1386 offset_int maxoff
= acs
.dstoff
[0] + dstref
->sizrange
[0];
1387 if (maxobjsize
< maxoff
)
1389 acs
.ovlsiz
[0] = (maxoff
- maxobjsize
).to_shwi ();
1390 acs
.ovloff
[0] = acs
.dstoff
[0].to_shwi () - acs
.ovlsiz
[0];
1394 /* Repeat the same as above but for the source offsets. */
1395 if (acs
.srcoff
[1] < acs
.srcoff
[0])
1397 acs
.srcoff
[0] = -maxobjsize
- 1;
1398 acs
.srcoff
[1] = maxobjsize
;
1401 maxoff
= acs
.srcoff
[0] + srcref
->sizrange
[0];
1402 if (maxobjsize
< maxoff
)
1404 acs
.ovlsiz
[0] = (maxoff
- maxobjsize
).to_shwi ();
1405 acs
.ovlsiz
[1] = (acs
.srcoff
[0] + srcref
->sizrange
[1]
1406 - maxobjsize
).to_shwi ();
1407 acs
.ovloff
[0] = acs
.srcoff
[0].to_shwi () - acs
.ovlsiz
[0];
1411 if (dstref
->base
!= srcref
->base
)
1414 acs
.dstsiz
[0] = dstref
->sizrange
[0];
1415 acs
.dstsiz
[1] = dstref
->sizrange
[1];
1417 acs
.srcsiz
[0] = srcref
->sizrange
[0];
1418 acs
.srcsiz
[1] = srcref
->sizrange
[1];
1420 /* Call the appropriate function to determine the overlap. */
1421 if ((this->*detect_overlap
) ())
1425 /* Unless the access size range has already been set, do so here. */
1426 sizrange
[0] = wi::smax (acs
.dstsiz
[0], srcref
->sizrange
[0]).to_shwi ();
1427 sizrange
[1] = wi::smax (acs
.dstsiz
[1], srcref
->sizrange
[1]).to_shwi ();
1435 /* Attempt to detect and diagnose an overlapping copy in a call expression
1436 EXPR involving an an access ACS to a built-in memory or string function.
1437 Return true when one has been detected, false otherwise. */
1440 maybe_diag_overlap (location_t loc
, gimple
*call
, builtin_access
&acs
)
1442 if (!acs
.overlap ())
1445 if (gimple_no_warning_p (call
))
1448 /* For convenience. */
1449 const builtin_memref
&dstref
= *acs
.dstref
;
1450 const builtin_memref
&srcref
= *acs
.srcref
;
1452 /* Determine the range of offsets and sizes of the overlap if it
1453 exists and issue diagnostics. */
1454 HOST_WIDE_INT
*ovloff
= acs
.ovloff
;
1455 HOST_WIDE_INT
*ovlsiz
= acs
.ovlsiz
;
1456 HOST_WIDE_INT
*sizrange
= acs
.sizrange
;
1458 tree func
= gimple_call_fndecl (call
);
1460 /* To avoid a combinatorial explosion of diagnostics format the offsets
1461 or their ranges as strings and use them in the warning calls below. */
1464 if (dstref
.offrange
[0] == dstref
.offrange
[1]
1465 || dstref
.offrange
[1] > HOST_WIDE_INT_MAX
)
1466 sprintf (offstr
[0], HOST_WIDE_INT_PRINT_DEC
,
1467 dstref
.offrange
[0].to_shwi ());
1470 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1471 dstref
.offrange
[0].to_shwi (),
1472 dstref
.offrange
[1].to_shwi ());
1474 if (srcref
.offrange
[0] == srcref
.offrange
[1]
1475 || srcref
.offrange
[1] > HOST_WIDE_INT_MAX
)
1477 HOST_WIDE_INT_PRINT_DEC
,
1478 srcref
.offrange
[0].to_shwi ());
1481 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1482 srcref
.offrange
[0].to_shwi (),
1483 srcref
.offrange
[1].to_shwi ());
1485 if (ovloff
[0] == ovloff
[1] || !ovloff
[1])
1486 sprintf (offstr
[2], HOST_WIDE_INT_PRINT_DEC
, ovloff
[0]);
1489 "[" HOST_WIDE_INT_PRINT_DEC
", " HOST_WIDE_INT_PRINT_DEC
"]",
1490 ovloff
[0], ovloff
[1]);
1492 const offset_int maxobjsize
= dstref
.maxobjsize
;
1493 bool must_overlap
= ovlsiz
[0] > 0;
1496 ovlsiz
[1] = ovlsiz
[0];
1500 /* Issue definitive "overlaps" diagnostic in this block. */
1502 if (sizrange
[0] == sizrange
[1])
1504 if (ovlsiz
[0] == ovlsiz
[1])
1505 warning_at (loc
, OPT_Wrestrict
,
1508 ? G_("%G%qD accessing %wu byte at offsets %s "
1509 "and %s overlaps %wu byte at offset %s")
1510 : G_("%G%qD accessing %wu byte at offsets %s "
1511 "and %s overlaps %wu bytes at offset "
1514 ? G_("%G%qD accessing %wu bytes at offsets %s "
1515 "and %s overlaps %wu byte at offset %s")
1516 : G_("%G%qD accessing %wu bytes at offsets %s "
1517 "and %s overlaps %wu bytes at offset "
1519 call
, func
, sizrange
[0],
1520 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1521 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1522 warning_n (loc
, OPT_Wrestrict
, sizrange
[0],
1523 "%G%qD accessing %wu byte at offsets %s "
1524 "and %s overlaps between %wu and %wu bytes "
1526 "%G%qD accessing %wu bytes at offsets %s "
1527 "and %s overlaps between %wu and %wu bytes "
1529 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1530 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
1532 warning_n (loc
, OPT_Wrestrict
, sizrange
[0],
1533 "%G%qD accessing %wu byte at offsets %s and "
1534 "%s overlaps %wu or more bytes at offset %s",
1535 "%G%qD accessing %wu bytes at offsets %s and "
1536 "%s overlaps %wu or more bytes at offset %s",
1537 call
, func
, sizrange
[0],
1538 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1542 if (sizrange
[1] >= 0 && sizrange
[1] < maxobjsize
.to_shwi ())
1544 if (ovlsiz
[0] == ovlsiz
[1])
1545 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[0],
1546 "%G%qD accessing between %wu and %wu bytes "
1547 "at offsets %s and %s overlaps %wu byte at "
1549 "%G%qD accessing between %wu and %wu bytes "
1550 "at offsets %s and %s overlaps %wu bytes "
1552 call
, func
, sizrange
[0], sizrange
[1],
1553 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1554 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1555 warning_at (loc
, OPT_Wrestrict
,
1556 "%G%qD accessing between %wu and %wu bytes at "
1557 "offsets %s and %s overlaps between %wu and %wu "
1558 "bytes at offset %s",
1559 call
, func
, sizrange
[0], sizrange
[1],
1560 offstr
[0], offstr
[1], ovlsiz
[0], ovlsiz
[1],
1563 warning_at (loc
, OPT_Wrestrict
,
1564 "%G%qD accessing between %wu and %wu bytes at "
1565 "offsets %s and %s overlaps %wu or more bytes "
1567 call
, func
, sizrange
[0], sizrange
[1],
1568 offstr
[0], offstr
[1], ovlsiz
[0], offstr
[2]);
1572 if (ovlsiz
[0] != ovlsiz
[1])
1573 ovlsiz
[1] = maxobjsize
.to_shwi ();
1575 if (ovlsiz
[0] == ovlsiz
[1])
1576 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[0],
1577 "%G%qD accessing %wu or more bytes at offsets "
1578 "%s and %s overlaps %wu byte at offset %s",
1579 "%G%qD accessing %wu or more bytes at offsets "
1580 "%s and %s overlaps %wu bytes at offset %s",
1581 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1582 ovlsiz
[0], offstr
[2]);
1583 else if (ovlsiz
[1] >= 0 && ovlsiz
[1] < maxobjsize
.to_shwi ())
1584 warning_at (loc
, OPT_Wrestrict
,
1585 "%G%qD accessing %wu or more bytes at offsets %s "
1586 "and %s overlaps between %wu and %wu bytes "
1588 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1589 ovlsiz
[0], ovlsiz
[1], offstr
[2]);
1591 warning_at (loc
, OPT_Wrestrict
,
1592 "%G%qD accessing %wu or more bytes at offsets %s "
1593 "and %s overlaps %wu or more bytes at offset %s",
1594 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1595 ovlsiz
[0], offstr
[2]);
1599 /* Use more concise wording when one of the offsets is unbounded
1600 to avoid confusing the user with large and mostly meaningless
1603 if (DECL_P (dstref
.base
) && TREE_CODE (TREE_TYPE (dstref
.base
)) == ARRAY_TYPE
)
1604 open_range
= ((dstref
.offrange
[0] == 0
1605 && dstref
.offrange
[1] == maxobjsize
)
1606 || (srcref
.offrange
[0] == 0
1607 && srcref
.offrange
[1] == maxobjsize
));
1609 open_range
= ((dstref
.offrange
[0] == -maxobjsize
- 1
1610 && dstref
.offrange
[1] == maxobjsize
)
1611 || (srcref
.offrange
[0] == -maxobjsize
- 1
1612 && srcref
.offrange
[1] == maxobjsize
));
1614 if (sizrange
[0] == sizrange
[1] || sizrange
[1] == 1)
1619 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1620 "%G%qD accessing %wu byte may overlap "
1622 "%G%qD accessing %wu bytes may overlap "
1624 call
, func
, sizrange
[1], ovlsiz
[1]);
1626 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1627 "%G%qD accessing %wu byte at offsets %s "
1628 "and %s may overlap %wu byte at offset %s",
1629 "%G%qD accessing %wu bytes at offsets %s "
1630 "and %s may overlap %wu byte at offset %s",
1631 call
, func
, sizrange
[1], offstr
[0], offstr
[1],
1632 ovlsiz
[1], offstr
[2]);
1637 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1638 "%G%qD accessing %wu byte may overlap "
1640 "%G%qD accessing %wu bytes may overlap "
1642 call
, func
, sizrange
[1], ovlsiz
[1]);
1644 warning_n (loc
, OPT_Wrestrict
, sizrange
[1],
1645 "%G%qD accessing %wu byte at offsets %s and "
1646 "%s may overlap up to %wu bytes at offset %s",
1647 "%G%qD accessing %wu bytes at offsets %s and "
1648 "%s may overlap up to %wu bytes at offset %s",
1649 call
, func
, sizrange
[1], offstr
[0], offstr
[1],
1650 ovlsiz
[1], offstr
[2]);
1654 if (sizrange
[1] >= 0 && sizrange
[1] < maxobjsize
.to_shwi ())
1657 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1658 "%G%qD accessing between %wu and %wu bytes "
1659 "may overlap %wu byte",
1660 "%G%qD accessing between %wu and %wu bytes "
1661 "may overlap up to %wu bytes",
1662 call
, func
, sizrange
[0], sizrange
[1], ovlsiz
[1]);
1664 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1665 "%G%qD accessing between %wu and %wu bytes "
1666 "at offsets %s and %s may overlap %wu byte "
1668 "%G%qD accessing between %wu and %wu bytes "
1669 "at offsets %s and %s may overlap up to %wu "
1670 "bytes at offset %s",
1671 call
, func
, sizrange
[0], sizrange
[1],
1672 offstr
[0], offstr
[1], ovlsiz
[1], offstr
[2]);
1676 warning_n (loc
, OPT_Wrestrict
, ovlsiz
[1],
1677 "%G%qD accessing %wu or more bytes at offsets %s "
1678 "and %s may overlap %wu byte at offset %s",
1679 "%G%qD accessing %wu or more bytes at offsets %s "
1680 "and %s may overlap up to %wu bytes at offset %s",
1681 call
, func
, sizrange
[0], offstr
[0], offstr
[1],
1682 ovlsiz
[1], offstr
[2]);
1687 /* Validate REF size and offsets in an expression passed as an argument
1688 to a CALL to a built-in function FUNC to make sure they are within
1689 the bounds of the referenced object if its size is known, or
1690 PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1691 be issued, false otherwise.
1692 Both initial values of the offsets and their final value computed
1693 by the function by incrementing the initial value by the size are
1694 validated. Return true if the offsets are not valid and a diagnostic
1695 has been issued, or would have been issued if DO_WARN had been true. */
1698 maybe_diag_access_bounds (location_t loc
, gimple
*call
, tree func
, int strict
,
1699 const builtin_memref
&ref
, offset_int wroff
,
1702 const offset_int maxobjsize
= ref
.maxobjsize
;
1704 /* Check for excessive size first and regardless of warning options
1705 since the result is used to make codegen decisions. */
1706 if (ref
.sizrange
[0] > maxobjsize
)
1708 /* Return true without issuing a warning. */
1712 if (ref
.ref
&& TREE_NO_WARNING (ref
.ref
))
1715 if (warn_stringop_overflow
)
1717 if (EXPR_HAS_LOCATION (ref
.ptr
))
1718 loc
= EXPR_LOCATION (ref
.ptr
);
1720 loc
= expansion_point_location_if_in_system_header (loc
);
1722 if (ref
.sizrange
[0] == ref
.sizrange
[1])
1723 return warning_at (loc
, OPT_Wstringop_overflow_
,
1724 "%G%qD specified bound %wu "
1725 "exceeds maximum object size %wu",
1726 call
, func
, ref
.sizrange
[0].to_uhwi (),
1727 maxobjsize
.to_uhwi ());
1729 return warning_at (loc
, OPT_Wstringop_overflow_
,
1730 "%G%qD specified bound between %wu and %wu "
1731 "exceeds maximum object size %wu",
1732 call
, func
, ref
.sizrange
[0].to_uhwi (),
1733 ref
.sizrange
[1].to_uhwi (),
1734 maxobjsize
.to_uhwi ());
1738 /* Check for out-bounds pointers regardless of warning options since
1739 the result is used to make codegen decisions. An excessive WROFF
1740 can only come up as a result of an invalid strncat bound and is
1741 diagnosed separately using a more meaningful warning. */
1742 if (maxobjsize
< wroff
)
1744 offset_int ooboff
[] = { ref
.offrange
[0], ref
.offrange
[1], wroff
};
1745 tree oobref
= ref
.offset_out_of_bounds (strict
, ooboff
);
1749 /* Return true without issuing a warning. */
1753 if (!warn_array_bounds
)
1756 if (TREE_NO_WARNING (ref
.ptr
)
1757 || (ref
.ref
&& TREE_NO_WARNING (ref
.ref
)))
1760 if (EXPR_HAS_LOCATION (ref
.ptr
))
1761 loc
= EXPR_LOCATION (ref
.ptr
);
1763 loc
= expansion_point_location_if_in_system_header (loc
);
1765 char rangestr
[2][64];
1766 if (ooboff
[0] == ooboff
[1]
1767 || (ooboff
[0] != ref
.offrange
[0]
1768 && ooboff
[0].to_shwi () >= ooboff
[1].to_shwi ()))
1769 sprintf (rangestr
[0], "%lli", (long long) ooboff
[0].to_shwi ());
1771 sprintf (rangestr
[0], "[%lli, %lli]",
1772 (long long) ooboff
[0].to_shwi (),
1773 (long long) ooboff
[1].to_shwi ());
1775 bool warned
= false;
1777 if (oobref
== error_mark_node
)
1779 if (ref
.sizrange
[0] == ref
.sizrange
[1])
1780 sprintf (rangestr
[1], "%llu",
1781 (unsigned long long) ref
.sizrange
[0].to_shwi ());
1783 sprintf (rangestr
[1], "[%lli, %lli]",
1784 (unsigned long long) ref
.sizrange
[0].to_uhwi (),
1785 (unsigned long long) ref
.sizrange
[1].to_uhwi ());
1789 if (DECL_P (ref
.base
)
1790 && TREE_CODE (type
= TREE_TYPE (ref
.base
)) == ARRAY_TYPE
)
1792 auto_diagnostic_group d
;
1793 if (warning_at (loc
, OPT_Warray_bounds
,
1794 "%G%qD pointer overflow between offset %s "
1795 "and size %s accessing array %qD with type %qT",
1796 call
, func
, rangestr
[0], rangestr
[1], ref
.base
, type
))
1798 inform (DECL_SOURCE_LOCATION (ref
.base
),
1799 "array %qD declared here", ref
.base
);
1803 warned
= warning_at (loc
, OPT_Warray_bounds
,
1804 "%G%qD pointer overflow between offset %s "
1806 call
, func
, rangestr
[0], rangestr
[1]);
1809 warned
= warning_at (loc
, OPT_Warray_bounds
,
1810 "%G%qD pointer overflow between offset %s "
1812 call
, func
, rangestr
[0], rangestr
[1]);
1814 else if (oobref
== ref
.base
)
1816 /* True when the offset formed by an access to the reference
1817 is out of bounds, rather than the initial offset wich is
1818 in bounds. This implies access past the end. */
1819 bool form
= ooboff
[0] != ref
.offrange
[0];
1821 if (DECL_P (ref
.base
))
1823 auto_diagnostic_group d
;
1824 if ((ref
.basesize
< maxobjsize
1825 && warning_at (loc
, OPT_Warray_bounds
,
1827 ? G_("%G%qD forming offset %s is out of "
1828 "the bounds [0, %wu] of object %qD with "
1830 : G_("%G%qD offset %s is out of the bounds "
1831 "[0, %wu] of object %qD with type %qT"),
1832 call
, func
, rangestr
[0], ref
.basesize
.to_uhwi (),
1833 ref
.base
, TREE_TYPE (ref
.base
)))
1834 || warning_at (loc
, OPT_Warray_bounds
,
1836 ? G_("%G%qD forming offset %s is out of "
1837 "the bounds of object %qD with type %qT")
1838 : G_("%G%qD offset %s is out of the bounds "
1839 "of object %qD with type %qT"),
1840 call
, func
, rangestr
[0],
1841 ref
.base
, TREE_TYPE (ref
.base
)))
1843 inform (DECL_SOURCE_LOCATION (ref
.base
),
1844 "%qD declared here", ref
.base
);
1848 else if (ref
.basesize
< maxobjsize
)
1849 warned
= warning_at (loc
, OPT_Warray_bounds
,
1851 ? G_("%G%qD forming offset %s is out "
1852 "of the bounds [0, %wu]")
1853 : G_("%G%qD offset %s is out "
1854 "of the bounds [0, %wu]"),
1855 call
, func
, rangestr
[0], ref
.basesize
.to_uhwi ());
1857 warned
= warning_at (loc
, OPT_Warray_bounds
,
1859 ? G_("%G%qD forming offset %s is out of bounds")
1860 : G_("%G%qD offset %s is out of bounds"),
1861 call
, func
, rangestr
[0]);
1863 else if (TREE_CODE (ref
.ref
) == MEM_REF
)
1865 tree refop
= TREE_OPERAND (ref
.ref
, 0);
1866 tree type
= TREE_TYPE (refop
);
1867 if (POINTER_TYPE_P (type
))
1868 type
= TREE_TYPE (type
);
1869 type
= TYPE_MAIN_VARIANT (type
);
1871 if (warning_at (loc
, OPT_Warray_bounds
,
1872 "%G%qD offset %s from the object at %qE is out "
1873 "of the bounds of %qT",
1874 call
, func
, rangestr
[0], ref
.base
, type
))
1876 if (TREE_CODE (ref
.ref
) == COMPONENT_REF
)
1877 refop
= TREE_OPERAND (ref
.ref
, 1);
1879 inform (DECL_SOURCE_LOCATION (refop
),
1880 "subobject %qD declared here", refop
);
1886 tree refop
= TREE_OPERAND (ref
.ref
, 0);
1887 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (ref
.ref
));
1889 if (warning_at (loc
, OPT_Warray_bounds
,
1890 "%G%qD offset %s from the object at %qE is out "
1891 "of the bounds of referenced subobject %qD with "
1892 "type %qT at offset %wi",
1893 call
, func
, rangestr
[0], ref
.base
,
1894 TREE_OPERAND (ref
.ref
, 1), type
,
1895 ref
.refoff
.to_shwi ()))
1897 if (TREE_CODE (ref
.ref
) == COMPONENT_REF
)
1898 refop
= TREE_OPERAND (ref
.ref
, 1);
1900 inform (DECL_SOURCE_LOCATION (refop
),
1901 "subobject %qD declared here", refop
);
1909 /* Check a CALL statement for restrict-violations and issue warnings
1910 if/when appropriate. */
1913 wrestrict_dom_walker::check_call (gimple
*call
)
1915 /* Avoid checking the call if it has already been diagnosed for
1917 if (gimple_no_warning_p (call
))
1920 tree func
= gimple_call_fndecl (call
);
1921 if (!func
|| !fndecl_built_in_p (func
, BUILT_IN_NORMAL
))
1924 /* Argument number to extract from the call (depends on the built-in
1926 unsigned dst_idx
= -1;
1927 unsigned src_idx
= -1;
1928 unsigned bnd_idx
= -1;
1930 /* Is this CALL to a string function (as opposed to one to a raw
1931 memory function). */
1934 switch (DECL_FUNCTION_CODE (func
))
1936 case BUILT_IN_MEMCPY
:
1937 case BUILT_IN_MEMCPY_CHK
:
1938 case BUILT_IN_MEMPCPY
:
1939 case BUILT_IN_MEMPCPY_CHK
:
1940 case BUILT_IN_MEMMOVE
:
1941 case BUILT_IN_MEMMOVE_CHK
:
1945 case BUILT_IN_STPNCPY
:
1946 case BUILT_IN_STPNCPY_CHK
:
1947 case BUILT_IN_STRNCAT
:
1948 case BUILT_IN_STRNCAT_CHK
:
1949 case BUILT_IN_STRNCPY
:
1950 case BUILT_IN_STRNCPY_CHK
:
1956 case BUILT_IN_MEMSET
:
1957 case BUILT_IN_MEMSET_CHK
:
1962 case BUILT_IN_STPCPY
:
1963 case BUILT_IN_STPCPY_CHK
:
1964 case BUILT_IN_STRCPY
:
1965 case BUILT_IN_STRCPY_CHK
:
1966 case BUILT_IN_STRCAT
:
1967 case BUILT_IN_STRCAT_CHK
:
1973 /* Handle other string functions here whose access may need
1974 to be validated for in-bounds offsets and non-overlapping
1979 unsigned nargs
= gimple_call_num_args (call
);
1981 tree dst
= dst_idx
< nargs
? gimple_call_arg (call
, dst_idx
) : NULL_TREE
;
1982 tree src
= src_idx
< nargs
? gimple_call_arg (call
, src_idx
) : NULL_TREE
;
1983 tree dstwr
= bnd_idx
< nargs
? gimple_call_arg (call
, bnd_idx
) : NULL_TREE
;
1985 /* For string functions with an unspecified or unknown bound,
1986 assume the size of the access is one. */
1987 if (!dstwr
&& strfun
)
1988 dstwr
= size_one_node
;
1990 /* DST and SRC can be null for a call with an insufficient number
1991 of arguments to a built-in function declared without a protype. */
1992 if (!dst
|| (src_idx
< nargs
&& !src
))
1995 /* DST, SRC, or DSTWR can also have the wrong type in a call to
1996 a function declared without a prototype. Avoid checking such
1998 if (TREE_CODE (TREE_TYPE (dst
)) != POINTER_TYPE
1999 || (src
&& TREE_CODE (TREE_TYPE (src
)) != POINTER_TYPE
)
2000 || (dstwr
&& !INTEGRAL_TYPE_P (TREE_TYPE (dstwr
))))
2003 if (!check_bounds_or_overlap (call
, dst
, src
, dstwr
, NULL_TREE
))
2006 /* Avoid diagnosing the call again. */
2007 gimple_set_no_warning (call
, true);
2010 } /* anonymous namespace */
2012 /* Attempt to detect and diagnose invalid offset bounds and (except for
2013 memmove) overlapping copy in a call expression EXPR from SRC to DST
2014 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
2015 SRCSIZE may be NULL. DO_WARN is false to detect either problem
2016 without issue a warning. Return the OPT_Wxxx constant corresponding
2017 to the warning if one has been detected and zero otherwise. */
2020 check_bounds_or_overlap (gimple
*call
, tree dst
, tree src
, tree dstsize
,
2021 tree srcsize
, bool bounds_only
/* = false */,
2022 bool do_warn
/* = true */)
2024 location_t loc
= gimple_nonartificial_location (call
);
2025 loc
= expansion_point_location_if_in_system_header (loc
);
2027 tree func
= gimple_call_fndecl (call
);
2029 builtin_memref
dstref (dst
, dstsize
);
2030 builtin_memref
srcref (src
, srcsize
);
2032 /* Create a descriptor of the access. This may adjust both DSTREF
2033 and SRCREF based on one another and the kind of the access. */
2034 builtin_access
acs (call
, dstref
, srcref
);
2036 /* Set STRICT to the value of the -Warray-bounds=N argument for
2037 string functions or when N > 1. */
2038 int strict
= (acs
.strict () || warn_array_bounds
> 1 ? warn_array_bounds
: 0);
2040 /* The starting offset of the destination write access. Nonzero only
2041 for the strcat family of functions. */
2042 offset_int wroff
= acs
.write_off (dstsize
);
2044 /* Validate offsets to each reference before the access first to make
2045 sure they are within the bounds of the destination object if its
2046 size is known, or PTRDIFF_MAX otherwise. */
2047 if (maybe_diag_access_bounds (loc
, call
, func
, strict
, dstref
, wroff
, do_warn
)
2048 || maybe_diag_access_bounds (loc
, call
, func
, strict
, srcref
, 0, do_warn
))
2051 gimple_set_no_warning (call
, true);
2052 return OPT_Warray_bounds
;
2055 if (!warn_restrict
|| bounds_only
|| !src
)
2060 switch (DECL_FUNCTION_CODE (func
))
2062 case BUILT_IN_MEMMOVE
:
2063 case BUILT_IN_MEMMOVE_CHK
:
2064 case BUILT_IN_MEMSET
:
2065 case BUILT_IN_MEMSET_CHK
:
2072 if (operand_equal_p (dst
, src
, 0))
2074 /* Issue -Wrestrict unless the pointers are null (those do
2075 not point to objects and so do not indicate an overlap;
2076 such calls could be the result of sanitization and jump
2078 if (!integer_zerop (dst
) && !gimple_no_warning_p (call
))
2080 warning_at (loc
, OPT_Wrestrict
,
2081 "%G%qD source argument is the same as destination",
2083 gimple_set_no_warning (call
, true);
2084 return OPT_Wrestrict
;
2090 /* Return false when overlap has been detected. */
2091 if (maybe_diag_overlap (loc
, call
, acs
))
2093 gimple_set_no_warning (call
, true);
2094 return OPT_Wrestrict
;
2101 make_pass_warn_restrict (gcc::context
*ctxt
)
2103 return new pass_wrestrict (ctxt
);
2107 dump_builtin_memref (FILE *fp
, const builtin_memref
&ref
)
2109 fprintf (fp
, "\n ptr = ");
2110 print_generic_expr (fp
, ref
.ptr
, TDF_LINENO
);
2111 fprintf (fp
, "\n ref = ");
2113 print_generic_expr (fp
, ref
.ref
, TDF_LINENO
);
2116 fprintf (fp
, "\n base = ");
2117 print_generic_expr (fp
, ref
.base
, TDF_LINENO
);
2119 "\n basesize = %lli"
2122 "\n offrange = [%lli, %lli]"
2123 "\n sizrange = [%lli, %lli]"
2124 "\n strbounded_p = %s\n",
2125 (long long)ref
.basesize
.to_shwi (),
2126 (long long)ref
.refsize
.to_shwi (),
2127 (long long)ref
.refoff
.to_shwi (),
2128 (long long)ref
.offrange
[0].to_shwi (),
2129 (long long)ref
.offrange
[1].to_shwi (),
2130 (long long)ref
.sizrange
[0].to_shwi (),
2131 (long long)ref
.sizrange
[1].to_shwi (),
2132 ref
.strbounded_p
? "true" : "false");
2136 builtin_access::dump (FILE *fp
) const
2138 fprintf (fp
, " dstref:");
2139 dump_builtin_memref (fp
, *dstref
);
2140 fprintf (fp
, "\n srcref:");
2141 dump_builtin_memref (fp
, *srcref
);
2144 " sizrange = [%lli, %lli]\n"
2145 " ovloff = [%lli, %lli]\n"
2146 " ovlsiz = [%lli, %lli]\n"
2147 " dstoff = [%lli, %lli]\n"
2148 " dstsiz = [%lli, %lli]\n"
2149 " srcoff = [%lli, %lli]\n"
2150 " srcsiz = [%lli, %lli]\n",
2151 (long long)sizrange
[0], (long long)sizrange
[1],
2152 (long long)ovloff
[0], (long long)ovloff
[1],
2153 (long long)ovlsiz
[0], (long long)ovlsiz
[1],
2154 (long long)dstoff
[0].to_shwi (), (long long)dstoff
[1].to_shwi (),
2155 (long long)dstsiz
[0].to_shwi (), (long long)dstsiz
[1].to_shwi (),
2156 (long long)srcoff
[0].to_shwi (), (long long)srcoff
[1].to_shwi (),
2157 (long long)srcsiz
[0].to_shwi (), (long long)srcsiz
[1].to_shwi ());
2161 dump_builtin_access (FILE *fp
, gimple
*stmt
, const builtin_access
&acs
)
2165 fprintf (fp
, "\nDumping builtin_access for ");
2166 print_gimple_expr (fp
, stmt
, TDF_LINENO
);
2174 debug (gimple
*stmt
, const builtin_access
&acs
)
2176 dump_builtin_access (stdout
, stmt
, acs
);