Branch data Line data Source code
1 : : /* Pass to detect and issue warnings for violations of the restrict
2 : : qualifier.
3 : : Copyright (C) 2017-2025 Free Software Foundation, Inc.
4 : : Contributed by Martin Sebor <msebor@redhat.com>.
5 : :
6 : : This file is part of GCC.
7 : :
8 : : GCC is free software; you can redistribute it and/or modify it under
9 : : the terms of the GNU General Public License as published by the Free
10 : : Software Foundation; either version 3, or (at your option) any later
11 : : version.
12 : :
13 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : : for more details.
17 : :
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/>. */
21 : :
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "backend.h"
26 : : #include "tree.h"
27 : : #include "gimple.h"
28 : : #include "tree-pass.h"
29 : : #include "pointer-query.h"
30 : : #include "ssa.h"
31 : : #include "gimple-pretty-print.h"
32 : : #include "gimple-ssa-warn-access.h"
33 : : #include "gimple-ssa-warn-restrict.h"
34 : : #include "diagnostic-core.h"
35 : : #include "fold-const.h"
36 : : #include "gimple-iterator.h"
37 : : #include "tree-dfa.h"
38 : : #include "tree-ssa.h"
39 : : #include "tree-cfg.h"
40 : : #include "tree-object-size.h"
41 : : #include "calls.h"
42 : : #include "cfgloop.h"
43 : : #include "diagnostic-context-rich-location.h"
44 : : #include "intl.h"
45 : : #include "gimple-range.h"
46 : :
47 : : namespace {
48 : :
49 : : const pass_data pass_data_wrestrict = {
50 : : GIMPLE_PASS,
51 : : "wrestrict",
52 : : OPTGROUP_NONE,
53 : : TV_NONE,
54 : : PROP_cfg, /* Properties_required. */
55 : : 0, /* properties_provided. */
56 : : 0, /* properties_destroyed. */
57 : : 0, /* properties_start */
58 : : 0, /* properties_finish */
59 : : };
60 : :
61 : : /* Pass to detect violations of strict aliasing requirements in calls
62 : : to built-in string and raw memory functions. */
63 : : class pass_wrestrict : public gimple_opt_pass
64 : : {
65 : : public:
66 : : pass_wrestrict (gcc::context *);
67 : :
68 : : bool gate (function *) final override;
69 : : unsigned int execute (function *) final override;
70 : :
71 : : void check_call (gimple *);
72 : :
73 : : void check_block (basic_block);
74 : :
75 : : /* A pointer_query object to store information about pointers and
76 : : their targets in. */
77 : : pointer_query m_ptr_qry;
78 : : };
79 : :
80 : 285689 : pass_wrestrict::pass_wrestrict (gcc::context *ctxt)
81 : : : gimple_opt_pass (pass_data_wrestrict, ctxt),
82 : 285689 : m_ptr_qry ()
83 : 285689 : { }
84 : :
85 : : bool
86 : 1042778 : pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
87 : : {
88 : 1042778 : return warn_array_bounds || warn_restrict || warn_stringop_overflow;
89 : : }
90 : :
91 : : void
92 : 10309668 : pass_wrestrict::check_block (basic_block bb)
93 : : {
94 : : /* Iterate over statements, looking for function calls. */
95 : 110196292 : for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
96 : : {
97 : 89576956 : gimple *stmt = gsi_stmt (si);
98 : 89576956 : if (!is_gimple_call (stmt))
99 : 84441257 : continue;
100 : :
101 : 5135699 : check_call (stmt);
102 : : }
103 : 10309668 : }
104 : :
105 : : unsigned
106 : 1042597 : pass_wrestrict::execute (function *fun)
107 : : {
108 : : /* Create a new ranger instance and associate it with FUN. */
109 : 1042597 : m_ptr_qry.rvals = enable_ranger (fun);
110 : 1042597 : bool new_dominance_for_diagnostics = false;
111 : :
112 : 1042597 : if (flag_diagnostics_show_context
113 : 1042597 : && !dom_info_available_p (fun, CDI_DOMINATORS))
114 : : {
115 : 23 : calculate_dominance_info (CDI_DOMINATORS);
116 : 23 : new_dominance_for_diagnostics = true;
117 : : }
118 : :
119 : 1042597 : basic_block bb;
120 : 11352265 : FOR_EACH_BB_FN (bb, fun)
121 : 10309668 : check_block (bb);
122 : :
123 : 1042597 : if (new_dominance_for_diagnostics
124 : 1042597 : && dom_info_available_p (fun, CDI_DOMINATORS))
125 : 23 : free_dominance_info (fun, CDI_DOMINATORS);
126 : :
127 : 1042597 : m_ptr_qry.flush_cache ();
128 : :
129 : : /* Release the ranger instance and replace it with a global ranger.
130 : : Also reset the pointer since calling disable_ranger() deletes it. */
131 : 1042597 : disable_ranger (fun);
132 : 1042597 : m_ptr_qry.rvals = NULL;
133 : :
134 : 1042597 : return 0;
135 : : }
136 : :
137 : : /* Description of a memory reference by a built-in function. This
138 : : is similar to ao_ref but made especially suitable for -Wrestrict
139 : : and not for optimization. */
140 : : class builtin_memref
141 : : {
142 : : public:
143 : : /* The original pointer argument to the built-in function. */
144 : : tree ptr;
145 : : /* The referenced subobject or NULL if not available, and the base
146 : : object of the memory reference or NULL. */
147 : : tree ref;
148 : : tree base;
149 : :
150 : : /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
151 : : and negative until (possibly lazily) initialized. */
152 : : offset_int basesize;
153 : : /* Same for the subobject. */
154 : : offset_int refsize;
155 : :
156 : : /* The non-negative offset of the referenced subobject. Used to avoid
157 : : warnings for (apparently) possibly but not definitively overlapping
158 : : accesses to member arrays. Negative when unknown/invalid. */
159 : : offset_int refoff;
160 : :
161 : : /* The offset range relative to the base. */
162 : : offset_int offrange[2];
163 : : /* The size range of the access to this reference. */
164 : : offset_int sizrange[2];
165 : :
166 : : /* Cached result of get_max_objsize(). */
167 : : const offset_int maxobjsize;
168 : :
169 : : /* True for "bounded" string functions like strncat, and strncpy
170 : : and their variants that specify either an exact or upper bound
171 : : on the size of the accesses they perform. For strncat both
172 : : the source and destination references are bounded. For strncpy
173 : : only the destination reference is. */
174 : : bool strbounded_p;
175 : :
176 : : builtin_memref (pointer_query &, gimple *, tree, tree);
177 : :
178 : : tree offset_out_of_bounds (int, offset_int[3]) const;
179 : :
180 : : private:
181 : : /* Call statement to the built-in. */
182 : : gimple *stmt;
183 : :
184 : : pointer_query &m_ptr_qry;
185 : :
186 : : /* Ctor helper to set or extend OFFRANGE based on argument. */
187 : : void extend_offset_range (tree);
188 : :
189 : : /* Ctor helper to determine BASE and OFFRANGE from argument. */
190 : : void set_base_and_offset (tree);
191 : : };
192 : :
193 : : /* Description of a memory access by a raw memory or string built-in
194 : : function involving a pair of builtin_memref's. */
195 : : class builtin_access
196 : : {
197 : : public:
198 : : /* Destination and source memory reference. */
199 : : builtin_memref* const dstref;
200 : : builtin_memref* const srcref;
201 : : /* The size range of the access. It's the greater of the accesses
202 : : to the two references. */
203 : : HOST_WIDE_INT sizrange[2];
204 : :
205 : : /* The minimum and maximum offset of an overlap of the access
206 : : (if it does, in fact, overlap), and the size of the overlap. */
207 : : HOST_WIDE_INT ovloff[2];
208 : : HOST_WIDE_INT ovlsiz[2];
209 : :
210 : : /* True to consider valid only accesses to the smallest subobject
211 : : and false for raw memory functions. */
212 : 185301 : bool strict () const
213 : : {
214 : 185301 : return (detect_overlap != &builtin_access::generic_overlap
215 : 62003 : && detect_overlap != &builtin_access::no_overlap);
216 : : }
217 : :
218 : : builtin_access (pointer_query &, gimple *,
219 : : builtin_memref &, builtin_memref &);
220 : :
221 : : /* Entry point to determine overlap. */
222 : : bool overlap ();
223 : :
224 : : offset_int write_off (tree) const;
225 : :
226 : : void dump (FILE *) const;
227 : :
228 : : private:
229 : : /* Implementation functions used to determine overlap. */
230 : : bool generic_overlap ();
231 : : bool strcat_overlap ();
232 : : bool strcpy_overlap ();
233 : :
234 : 0 : bool no_overlap ()
235 : : {
236 : 0 : return false;
237 : : }
238 : :
239 : : offset_int overlap_size (const offset_int [2], const offset_int[2],
240 : : offset_int [2]);
241 : :
242 : : private:
243 : : /* Temporaries used to compute the final result. */
244 : : offset_int dstoff[2];
245 : : offset_int srcoff[2];
246 : : offset_int dstsiz[2];
247 : : offset_int srcsiz[2];
248 : :
249 : : /* Pointer to a member function to call to determine overlap. */
250 : : bool (builtin_access::*detect_overlap) ();
251 : : };
252 : :
253 : : /* Initialize a memory reference representation from a pointer EXPR and
254 : : a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed
255 : : to be unknown. STMT is the statement in which expr appears in. */
256 : :
257 : 370602 : builtin_memref::builtin_memref (pointer_query &ptrqry, gimple *stmt, tree expr,
258 : 370602 : tree size)
259 : 370602 : : ptr (expr),
260 : 370602 : ref (),
261 : 370602 : base (),
262 : 370602 : basesize (-1),
263 : 370602 : refsize (-1),
264 : 370602 : refoff (HOST_WIDE_INT_MIN),
265 : 370602 : offrange (),
266 : 370602 : sizrange (),
267 : 370602 : maxobjsize (tree_to_shwi (max_object_size ())),
268 : 370602 : strbounded_p (),
269 : 370602 : stmt (stmt),
270 : 370602 : m_ptr_qry (ptrqry)
271 : : {
272 : : /* Unfortunately, wide_int default ctor is a no-op so array members
273 : : of the type must be set individually. */
274 : 370602 : offrange[0] = offrange[1] = 0;
275 : 370602 : sizrange[0] = sizrange[1] = 0;
276 : :
277 : 370602 : if (!expr)
278 : 245235 : return;
279 : :
280 : : /* Find the BASE object or pointer referenced by EXPR and set
281 : : the offset range OFFRANGE in the process. */
282 : 338712 : set_base_and_offset (expr);
283 : :
284 : 338712 : if (size)
285 : : {
286 : 224918 : tree range[2];
287 : : /* Determine the size range, allowing for the result to be [0, 0]
288 : : for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */
289 : 224918 : get_size_range (m_ptr_qry.rvals, size, stmt, range, SR_ALLOW_ZERO);
290 : 224918 : sizrange[0] = wi::to_offset (range[0]);
291 : 224918 : sizrange[1] = wi::to_offset (range[1]);
292 : : /* get_size_range returns SIZE_MAX for the maximum size.
293 : : Constrain it to the real maximum of PTRDIFF_MAX. */
294 : 224918 : if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize)
295 : 26919 : sizrange[1] = maxobjsize;
296 : : }
297 : : else
298 : 113794 : sizrange[1] = maxobjsize;
299 : :
300 : 338712 : if (!DECL_P (base))
301 : : return;
302 : :
303 : : /* If the offset could be in the range of the referenced object
304 : : constrain its bounds so neither exceeds those of the object. */
305 : 125367 : if (offrange[0] < 0 && offrange[1] > 0)
306 : 1448 : offrange[0] = 0;
307 : :
308 : 125367 : offset_int maxoff = maxobjsize;
309 : 125367 : tree basetype = TREE_TYPE (base);
310 : 125367 : if (TREE_CODE (basetype) == ARRAY_TYPE)
311 : : {
312 : 71930 : if (ref && array_ref_flexible_size_p (ref))
313 : : ; /* Use the maximum possible offset for an array that might
314 : : have flexible size. */
315 : 69349 : else if (tree basesize = TYPE_SIZE_UNIT (basetype))
316 : 67697 : if (TREE_CODE (basesize) == INTEGER_CST)
317 : : /* Size could be non-constant for a variable-length type such
318 : : as a struct with a VLA member (a GCC extension). */
319 : 67697 : maxoff = wi::to_offset (basesize);
320 : : }
321 : :
322 : 125367 : if (offrange[0] >= 0)
323 : : {
324 : 125232 : if (offrange[1] < 0)
325 : 519 : offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
326 : 124713 : else if (offrange[0] <= maxoff && offrange[1] > maxoff)
327 : 1427 : offrange[1] = maxoff;
328 : : }
329 : : }
330 : :
331 : : /* Based on the initial length of the destination STARTLEN, returns
332 : : the offset of the first write access from the beginning of
333 : : the destination. Nonzero only for strcat-type of calls. */
334 : :
335 : 185301 : offset_int builtin_access::write_off (tree startlen) const
336 : : {
337 : 185301 : if (detect_overlap != &builtin_access::strcat_overlap
338 : 2856 : || !startlen || TREE_CODE (startlen) != INTEGER_CST)
339 : 184170 : return 0;
340 : :
341 : 1131 : return wi::to_offset (startlen);
342 : : }
343 : :
344 : : /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
345 : : Pointer offsets are represented as unsigned sizetype but must be
346 : : treated as signed. */
347 : :
348 : : void
349 : 43203 : builtin_memref::extend_offset_range (tree offset)
350 : : {
351 : 43203 : if (TREE_CODE (offset) == INTEGER_CST)
352 : : {
353 : 15728 : offset_int off = int_cst_value (offset);
354 : 15728 : if (off != 0)
355 : : {
356 : 7993 : offrange[0] += off;
357 : 7993 : offrange[1] += off;
358 : : }
359 : 15728 : return;
360 : : }
361 : :
362 : 27475 : if (TREE_CODE (offset) == SSA_NAME)
363 : : {
364 : : /* A pointer offset is represented as sizetype but treated
365 : : as signed. */
366 : 27401 : wide_int min, max;
367 : 27401 : value_range_kind rng = VR_VARYING;
368 : 27401 : int_range_max vr;
369 : 27401 : if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt))
370 : : {
371 : 27401 : tree vr_min, vr_max;
372 : 27401 : rng = get_legacy_range (vr, vr_min, vr_max);
373 : 27401 : if (!vr.undefined_p ())
374 : : {
375 : 27401 : min = wi::to_wide (vr_min);
376 : 27401 : max = wi::to_wide (vr_max);
377 : : }
378 : : }
379 : :
380 : 27401 : if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
381 : : {
382 : : /* Convert an anti-range whose upper bound is less than
383 : : its lower bound to a signed range. */
384 : 915 : offrange[0] += offset_int::from (max + 1, SIGNED);
385 : 915 : offrange[1] += offset_int::from (min - 1, SIGNED);
386 : 915 : return;
387 : : }
388 : :
389 : 26486 : if (rng == VR_RANGE
390 : 26486 : && (DECL_P (base) || wi::lts_p (min, max)))
391 : : {
392 : : /* Preserve the bounds of the range for an offset into
393 : : a known object (it may be adjusted later relative to
394 : : a constant offset from its beginning). Otherwise use
395 : : the bounds only when they are ascending when treated
396 : : as signed. */
397 : 10208 : offrange[0] += offset_int::from (min, SIGNED);
398 : 10208 : offrange[1] += offset_int::from (max, SIGNED);
399 : 10208 : return;
400 : : }
401 : :
402 : : /* Handle an anti-range the same as no range at all. */
403 : 16278 : gimple *stmt = SSA_NAME_DEF_STMT (offset);
404 : 16278 : tree type;
405 : 16278 : if (is_gimple_assign (stmt)
406 : 10840 : && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
407 : 10840 : && INTEGRAL_TYPE_P (type)
408 : 27118 : && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (offset)))
409 : : {
410 : 10839 : tree_code code = gimple_assign_rhs_code (stmt);
411 : 10839 : if (code == NOP_EXPR)
412 : : {
413 : : /* Use the bounds of the type of the NOP_EXPR operand
414 : : even if it's signed. The result doesn't trigger
415 : : warnings but makes their output more readable. */
416 : 4392 : offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
417 : 4392 : offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
418 : 4392 : return;
419 : : }
420 : : }
421 : 27401 : }
422 : :
423 : 11960 : const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
424 : 11960 : const offset_int minoff = -maxoff - 1;
425 : :
426 : 11960 : offrange[0] += minoff;
427 : 11960 : offrange[1] += maxoff;
428 : : }
429 : :
430 : : /* Determines the base object or pointer of the reference EXPR
431 : : and the offset range from the beginning of the base. */
432 : :
433 : : void
434 : 375636 : builtin_memref::set_base_and_offset (tree expr)
435 : : {
436 : 375636 : tree offset = NULL_TREE;
437 : :
438 : 375636 : if (TREE_CODE (expr) == SSA_NAME)
439 : : {
440 : : /* Try to tease the offset out of the pointer. */
441 : 220022 : gimple *stmt = SSA_NAME_DEF_STMT (expr);
442 : 220022 : if (!base
443 : 183098 : && gimple_assign_single_p (stmt)
444 : 271591 : && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
445 : 9863 : expr = gimple_assign_rhs1 (stmt);
446 : 210159 : else if (is_gimple_assign (stmt))
447 : : {
448 : 104460 : tree_code code = gimple_assign_rhs_code (stmt);
449 : 104460 : if (CONVERT_EXPR_CODE_P (code))
450 : : {
451 : 16418 : tree rhs = gimple_assign_rhs1 (stmt);
452 : 16418 : if (POINTER_TYPE_P (TREE_TYPE (rhs)))
453 : : expr = gimple_assign_rhs1 (stmt);
454 : : else
455 : : {
456 : 16418 : base = expr;
457 : 176176 : return;
458 : : }
459 : : }
460 : 88042 : else if (code == POINTER_PLUS_EXPR)
461 : : {
462 : 33983 : expr = gimple_assign_rhs1 (stmt);
463 : 33983 : offset = gimple_assign_rhs2 (stmt);
464 : : }
465 : : else
466 : : {
467 : 54059 : base = expr;
468 : 54059 : return;
469 : : }
470 : : }
471 : : else
472 : : {
473 : : /* FIXME: Handle PHI nodes in case like:
474 : : _12 = &MEM[(void *)&a + 2B] + _10;
475 : :
476 : : <bb> [local count: 1073741824]:
477 : : # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
478 : : memcpy (prephitmp_13, p_7(D), 6); */
479 : 105699 : base = expr;
480 : 105699 : return;
481 : : }
482 : : }
483 : :
484 : 199460 : if (TREE_CODE (expr) == ADDR_EXPR)
485 : 158863 : expr = TREE_OPERAND (expr, 0);
486 : :
487 : : /* Stash the reference for offset validation. */
488 : 199460 : ref = expr;
489 : :
490 : 199460 : poly_int64 bitsize, bitpos;
491 : 199460 : tree var_off;
492 : 199460 : machine_mode mode;
493 : 199460 : int sign, reverse, vol;
494 : :
495 : : /* Determine the base object or pointer of the reference and
496 : : the constant bit offset from the beginning of the base.
497 : : If the offset has a non-constant component, it will be in
498 : : VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
499 : : unused here. */
500 : 199460 : base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
501 : : &mode, &sign, &reverse, &vol);
502 : :
503 : : /* get_inner_reference is not expected to return null. */
504 : 199460 : gcc_assert (base != NULL);
505 : :
506 : 199460 : if (offset)
507 : 33983 : extend_offset_range (offset);
508 : :
509 : 199460 : poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
510 : :
511 : : /* Convert the poly_int64 offset to offset_int. The offset
512 : : should be constant but be prepared for it not to be just in
513 : : case. */
514 : 199460 : offset_int cstoff;
515 : 199460 : if (bytepos.is_constant (&cstoff))
516 : : {
517 : 199460 : offrange[0] += cstoff;
518 : 199460 : offrange[1] += cstoff;
519 : :
520 : : /* Besides the reference saved above, also stash the offset
521 : : for validation. */
522 : 199460 : if (TREE_CODE (expr) == COMPONENT_REF)
523 : 28160 : refoff = cstoff;
524 : : }
525 : : else
526 : : offrange[1] += maxobjsize;
527 : :
528 : 199460 : if (var_off)
529 : : {
530 : 1788 : if (TREE_CODE (var_off) == INTEGER_CST)
531 : : {
532 : 20 : cstoff = wi::to_offset (var_off);
533 : 20 : offrange[0] += cstoff;
534 : 20 : offrange[1] += cstoff;
535 : : }
536 : : else
537 : 1768 : offrange[1] += maxobjsize;
538 : : }
539 : :
540 : 199460 : if (TREE_CODE (base) == MEM_REF)
541 : : {
542 : 9220 : tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
543 : 9220 : extend_offset_range (memrefoff);
544 : :
545 : 12504 : if (refoff != HOST_WIDE_INT_MIN
546 : 9220 : && TREE_CODE (expr) == COMPONENT_REF)
547 : : {
548 : : /* Bump up the offset of the referenced subobject to reflect
549 : : the offset to the enclosing object. For example, so that
550 : : in
551 : : struct S { char a, b[3]; } s[2];
552 : : strcpy (s[1].b, "1234");
553 : : REFOFF is set to s[1].b - (char*)s. */
554 : 5936 : offset_int off = tree_to_shwi (memrefoff);
555 : 5936 : refoff += off;
556 : :
557 : 5936 : if (!integer_zerop (memrefoff)
558 : 1370 : && !COMPLETE_TYPE_P (TREE_TYPE (expr))
559 : 5943 : && multiple_of_p (sizetype, memrefoff,
560 : 7 : TYPE_SIZE_UNIT (TREE_TYPE (base)), true))
561 : : /* A non-zero offset into an array of struct with flexible array
562 : : members implies that the array is empty because there is no
563 : : way to initialize such a member when it belongs to an array.
564 : : This must be some sort of a bug. */
565 : 7 : refsize = 0;
566 : : }
567 : :
568 : 9220 : base = TREE_OPERAND (base, 0);
569 : : }
570 : :
571 : 199460 : if (TREE_CODE (ref) == COMPONENT_REF)
572 : 28160 : if (tree size = component_ref_size (ref))
573 : 27964 : if (TREE_CODE (size) == INTEGER_CST)
574 : 27946 : refsize = wi::to_offset (size);
575 : :
576 : 199460 : if (TREE_CODE (base) == SSA_NAME)
577 : 36924 : set_base_and_offset (base);
578 : : }
579 : :
580 : : /* Return error_mark_node if the signed offset exceeds the bounds
581 : : of the address space (PTRDIFF_MAX). Otherwise, return either BASE
582 : : or REF when the offset exceeds the bounds of the BASE or REF object,
583 : : and set OOBOFF to the past-the-end offset formed by the reference,
584 : : including its size. OOBOFF is initially setto the range of offsets,
585 : : and OOBOFF[2] to the offset of the first write access (nonzero for
586 : : the strcat family). When STRICT is nonzero use REF size, when
587 : : available, otherwise use BASE size. When STRICT is greater than 1,
588 : : use the size of the last array member as the bound, otherwise treat
589 : : such a member as a flexible array member. Return NULL when the offset
590 : : is in bounds. */
591 : :
592 : : tree
593 : 369578 : builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
594 : : {
595 : 369578 : if (!ptr)
596 : : return NULL_TREE;
597 : :
598 : : /* The offset of the first write access or zero. */
599 : 337735 : offset_int wroff = ooboff[2];
600 : :
601 : : /* A temporary, possibly adjusted, copy of the offset range. */
602 : 337735 : offset_int offrng[2] = { ooboff[0], ooboff[1] };
603 : :
604 : 337735 : if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
605 : : {
606 : : /* Check for offset in an anti-range with a negative lower bound.
607 : : For such a range, consider only the non-negative subrange. */
608 : 71653 : if (offrng[1] < offrng[0] && offrng[1] < 0)
609 : 0 : offrng[1] = maxobjsize;
610 : : }
611 : :
612 : : /* Conservative offset of the last byte of the referenced object. */
613 : 337735 : offset_int endoff;
614 : :
615 : : /* The bounds need not be ordered. Set HIB to use as the index
616 : : of the larger of the bounds and LOB as the opposite. */
617 : 337735 : bool hib = wi::les_p (offrng[0], offrng[1]);
618 : 337735 : bool lob = !hib;
619 : :
620 : : /* Set to the size remaining in the object after subtracting
621 : : REFOFF. It may become negative as a result of negative indices
622 : : into the enclosing object, such as in:
623 : : extern struct S { char a[4], b[3], c[1]; } *p;
624 : : strcpy (p[-3].b, "123"); */
625 : 337735 : offset_int size = basesize;
626 : 337735 : tree obj = base;
627 : :
628 : 337735 : const bool decl_p = DECL_P (obj);
629 : :
630 : 337735 : if (basesize < 0)
631 : : {
632 : 171706 : endoff = offrng[lob] + (sizrange[0] - wroff);
633 : :
634 : : /* For a reference through a pointer to an object of unknown size
635 : : all initial offsets are considered valid, positive as well as
636 : : negative, since the pointer itself can point past the beginning
637 : : of the object. However, the sum of the lower bound of the offset
638 : : and that of the size must be less than or equal than PTRDIFF_MAX. */
639 : 171706 : if (endoff > maxobjsize)
640 : 73 : return error_mark_node;
641 : :
642 : : /* When the referenced subobject is known, the end offset must be
643 : : within its bounds. Otherwise there is nothing to do. */
644 : 171633 : if (strict
645 : 171633 : && !decl_p
646 : 1692 : && ref
647 : 818 : && refsize >= 0
648 : 172321 : && TREE_CODE (ref) == COMPONENT_REF)
649 : : {
650 : : /* If REFOFF is negative, SIZE will become negative here. */
651 : 634 : size = refoff + refsize;
652 : 634 : obj = ref;
653 : : }
654 : : else
655 : 170999 : return NULL_TREE;
656 : : }
657 : :
658 : : /* A reference to an object of known size must be within the bounds
659 : : of either the base object or the subobject (see above for when
660 : : a subobject can be used). */
661 : 166663 : if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
662 : 240 : return obj;
663 : :
664 : : /* The extent of the reference must also be within the bounds of
665 : : the base object (if known) or the subobject or the maximum object
666 : : size otherwise. */
667 : 166423 : endoff = offrng[lob] + sizrange[0];
668 : 166423 : if (endoff > maxobjsize)
669 : 21 : return error_mark_node;
670 : :
671 : 166402 : if (strict
672 : 166402 : && decl_p
673 : 3454 : && ref
674 : 166428 : && refsize >= 0
675 : 167010 : && TREE_CODE (ref) == COMPONENT_REF)
676 : : {
677 : : /* If the reference is to a member subobject of a declared object,
678 : : the offset must be within the bounds of the subobject. */
679 : 582 : size = refoff + refsize;
680 : 582 : obj = ref;
681 : : }
682 : :
683 : 166402 : if (endoff <= size)
684 : : return NULL_TREE;
685 : :
686 : : /* Set the out-of-bounds offset range to be one greater than
687 : : that delimited by the reference including its size. */
688 : 2239 : ooboff[lob] = size;
689 : :
690 : 2239 : if (endoff > ooboff[lob])
691 : 2239 : ooboff[hib] = endoff - 1;
692 : : else
693 : 0 : ooboff[hib] = offrng[lob] + sizrange[1];
694 : :
695 : : return obj;
696 : : }
697 : :
698 : : /* Create an association between the memory references DST and SRC
699 : : for access by a call EXPR to a memory or string built-in funtion. */
700 : :
701 : 185301 : builtin_access::builtin_access (pointer_query &ptrqry, gimple *call,
702 : : builtin_memref &dst,
703 : 185301 : builtin_memref &src)
704 : 185301 : : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
705 : 185301 : dstoff (), srcoff (), dstsiz (), srcsiz ()
706 : : {
707 : 185301 : dstoff[0] = dst.offrange[0];
708 : 185301 : dstoff[1] = dst.offrange[1];
709 : :
710 : : /* Zero out since the offset_int ctors invoked above are no-op. */
711 : 185301 : srcoff[0] = srcoff[1] = 0;
712 : 185301 : dstsiz[0] = dstsiz[1] = 0;
713 : 185301 : srcsiz[0] = srcsiz[1] = 0;
714 : :
715 : : /* Object Size Type to use to determine the size of the destination
716 : : and source objects. Overridden below for raw memory functions. */
717 : 185301 : int ostype = 1;
718 : :
719 : : /* True when the size of one reference depends on the offset of
720 : : itself or the other. */
721 : 185301 : bool depends_p = true;
722 : :
723 : : /* True when the size of the destination reference DSTREF has been
724 : : determined from SRCREF and so needs to be adjusted by the latter's
725 : : offset. Only meaningful for bounded string functions like strncpy. */
726 : 185301 : bool dstadjust_p = false;
727 : :
728 : : /* The size argument number (depends on the built-in). */
729 : 185301 : unsigned sizeargno = 2;
730 : :
731 : 185301 : tree func = gimple_call_fndecl (call);
732 : 185301 : switch (DECL_FUNCTION_CODE (func))
733 : : {
734 : 123298 : case BUILT_IN_MEMCPY:
735 : 123298 : case BUILT_IN_MEMCPY_CHK:
736 : 123298 : case BUILT_IN_MEMPCPY:
737 : 123298 : case BUILT_IN_MEMPCPY_CHK:
738 : 123298 : ostype = 0;
739 : 123298 : depends_p = false;
740 : 123298 : detect_overlap = &builtin_access::generic_overlap;
741 : 123298 : break;
742 : :
743 : 18650 : case BUILT_IN_MEMMOVE:
744 : 18650 : case BUILT_IN_MEMMOVE_CHK:
745 : : /* For memmove there is never any overlap to check for. */
746 : 18650 : ostype = 0;
747 : 18650 : depends_p = false;
748 : 18650 : detect_overlap = &builtin_access::no_overlap;
749 : 18650 : break;
750 : :
751 : 31883 : case BUILT_IN_MEMSET:
752 : 31883 : case BUILT_IN_MEMSET_CHK:
753 : : /* For memset there is never any overlap to check for. */
754 : 31883 : ostype = 0;
755 : 31883 : depends_p = false;
756 : 31883 : detect_overlap = &builtin_access::no_overlap;
757 : 31883 : break;
758 : :
759 : 4696 : case BUILT_IN_STPNCPY:
760 : 4696 : case BUILT_IN_STPNCPY_CHK:
761 : 4696 : case BUILT_IN_STRNCPY:
762 : 4696 : case BUILT_IN_STRNCPY_CHK:
763 : 4696 : dstref->strbounded_p = true;
764 : 4696 : detect_overlap = &builtin_access::strcpy_overlap;
765 : 4696 : break;
766 : :
767 : 3918 : case BUILT_IN_STPCPY:
768 : 3918 : case BUILT_IN_STPCPY_CHK:
769 : 3918 : case BUILT_IN_STRCPY:
770 : 3918 : case BUILT_IN_STRCPY_CHK:
771 : 3918 : detect_overlap = &builtin_access::strcpy_overlap;
772 : 3918 : break;
773 : :
774 : 1348 : case BUILT_IN_STRCAT:
775 : 1348 : case BUILT_IN_STRCAT_CHK:
776 : 1348 : detect_overlap = &builtin_access::strcat_overlap;
777 : 1348 : break;
778 : :
779 : 1508 : case BUILT_IN_STRNCAT:
780 : 1508 : case BUILT_IN_STRNCAT_CHK:
781 : 1508 : dstref->strbounded_p = true;
782 : 1508 : srcref->strbounded_p = true;
783 : 1508 : detect_overlap = &builtin_access::strcat_overlap;
784 : 1508 : break;
785 : :
786 : : default:
787 : : /* Handle other string functions here whose access may need
788 : : to be validated for in-bounds offsets and non-overlapping
789 : : copies. */
790 : 4 : return;
791 : : }
792 : :
793 : : /* Try to determine the size of the base object. compute_objsize
794 : : expects a pointer so create one if BASE is a non-pointer object. */
795 : 185301 : if (dst.basesize < 0)
796 : : {
797 : 185301 : access_ref aref;
798 : 185301 : if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0)
799 : 89293 : dst.basesize = aref.sizrng[1];
800 : : else
801 : 96008 : dst.basesize = HOST_WIDE_INT_MIN;
802 : : }
803 : :
804 : 185301 : if (src.base && src.basesize < 0)
805 : : {
806 : 153411 : access_ref aref;
807 : 153411 : if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0)
808 : 77136 : src.basesize = aref.sizrng[1];
809 : : else
810 : 76275 : src.basesize = HOST_WIDE_INT_MIN;
811 : : }
812 : :
813 : 185301 : const offset_int maxobjsize = dst.maxobjsize;
814 : :
815 : : /* Make adjustments for references to the same object by string
816 : : built-in functions to reflect the constraints imposed by
817 : : the function. */
818 : :
819 : : /* For bounded string functions determine the range of the bound
820 : : on the access. For others, the range stays unbounded. */
821 : 185301 : offset_int bounds[2] = { maxobjsize, maxobjsize };
822 : 185301 : if (dstref->strbounded_p)
823 : : {
824 : 6204 : unsigned nargs = gimple_call_num_args (call);
825 : 6204 : if (nargs <= sizeargno)
826 : 4 : return;
827 : :
828 : 6200 : tree size = gimple_call_arg (call, sizeargno);
829 : 6200 : tree range[2];
830 : 6200 : if (get_size_range (ptrqry.rvals, size, call, range, true))
831 : : {
832 : 6200 : bounds[0] = wi::to_offset (range[0]);
833 : 6200 : bounds[1] = wi::to_offset (range[1]);
834 : : }
835 : :
836 : : /* If both references' size ranges are indeterminate use the last
837 : : (size) argument from the function call as a substitute. This
838 : : may only be necessary for strncpy (but not for memcpy where
839 : : the size range would have been already determined this way). */
840 : 10482 : if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
841 : 10482 : && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
842 : : {
843 : 3352 : dstref->sizrange[0] = bounds[0];
844 : 3352 : dstref->sizrange[1] = bounds[1];
845 : : }
846 : : }
847 : :
848 : 185297 : bool dstsize_set = false;
849 : : /* The size range of one reference involving the same base object
850 : : can be determined from the size range of the other reference.
851 : : This makes it possible to compute accurate offsets for warnings
852 : : involving functions like strcpy where the length of just one of
853 : : the two arguments is known (determined by tree-ssa-strlen). */
854 : 185297 : if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize)
855 : : {
856 : : /* When the destination size is unknown set it to the size of
857 : : the source. */
858 : 16559 : dstref->sizrange[0] = srcref->sizrange[0];
859 : 16559 : dstref->sizrange[1] = srcref->sizrange[1];
860 : 16559 : dstsize_set = true;
861 : : }
862 : 168738 : else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
863 : : {
864 : : /* When the size of the source access is unknown set it to the size
865 : : of the destination first and adjust it later if necessary. */
866 : 96889 : srcref->sizrange[0] = dstref->sizrange[0];
867 : 96889 : srcref->sizrange[1] = dstref->sizrange[1];
868 : :
869 : 96889 : if (depends_p)
870 : : {
871 : 8861 : if (dstref->strbounded_p)
872 : : {
873 : : /* Read access by strncpy is constrained by the third
874 : : argument but except for a zero bound is at least one. */
875 : 5923 : srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
876 : 5859 : offset_int bound = wi::umin (srcref->basesize, bounds[1]);
877 : 5859 : if (bound < srcref->sizrange[1])
878 : 1213 : srcref->sizrange[1] = bound;
879 : : }
880 : : /* For string functions, adjust the size range of the source
881 : : reference by the inverse boundaries of the offset (because
882 : : the higher the offset into the string the shorter its
883 : : length). */
884 : 8861 : if (srcref->offrange[1] >= 0
885 : 8861 : && srcref->offrange[1] < srcref->sizrange[0])
886 : 6000 : srcref->sizrange[0] -= srcref->offrange[1];
887 : : else
888 : 2861 : srcref->sizrange[0] = 1;
889 : :
890 : 8861 : if (srcref->offrange[0] > 0)
891 : : {
892 : 2544 : if (srcref->offrange[0] < srcref->sizrange[1])
893 : 746 : srcref->sizrange[1] -= srcref->offrange[0];
894 : : else
895 : 1798 : srcref->sizrange[1] = 0;
896 : : }
897 : :
898 : : dstadjust_p = true;
899 : : }
900 : : }
901 : :
902 : 185297 : if (detect_overlap == &builtin_access::generic_overlap)
903 : : {
904 : 123298 : if (dstref->strbounded_p)
905 : : {
906 : 0 : dstref->sizrange[0] = bounds[0];
907 : 0 : dstref->sizrange[1] = bounds[1];
908 : :
909 : 0 : if (dstref->sizrange[0] < srcref->sizrange[0])
910 : 0 : srcref->sizrange[0] = dstref->sizrange[0];
911 : :
912 : 0 : if (dstref->sizrange[1] < srcref->sizrange[1])
913 : 0 : srcref->sizrange[1] = dstref->sizrange[1];
914 : : }
915 : : }
916 : 61999 : else if (detect_overlap == &builtin_access::strcpy_overlap)
917 : : {
918 : 8612 : if (!dstref->strbounded_p)
919 : : {
920 : : /* For strcpy, adjust the destination size range to match that
921 : : of the source computed above. */
922 : 3918 : if (depends_p && dstadjust_p)
923 : : {
924 : 2307 : dstref->sizrange[0] = srcref->sizrange[0];
925 : 2307 : dstref->sizrange[1] = srcref->sizrange[1];
926 : : }
927 : : }
928 : : }
929 : 53387 : else if (!dstsize_set && detect_overlap == &builtin_access::strcat_overlap)
930 : : {
931 : 2286 : dstref->sizrange[0] += srcref->sizrange[0] - 1;
932 : 2286 : dstref->sizrange[1] += srcref->sizrange[1] - 1;
933 : : }
934 : :
935 : 185297 : if (dstref->strbounded_p)
936 : : {
937 : : /* For strncpy, adjust the destination size range to match that
938 : : of the source computed above. */
939 : 6200 : dstref->sizrange[0] = bounds[0];
940 : 6200 : dstref->sizrange[1] = bounds[1];
941 : :
942 : 6200 : if (bounds[0] < srcref->sizrange[0])
943 : 2586 : srcref->sizrange[0] = bounds[0];
944 : :
945 : 6200 : if (bounds[1] < srcref->sizrange[1])
946 : 192 : srcref->sizrange[1] = bounds[1];
947 : : }
948 : : }
949 : :
950 : : offset_int
951 : 6424 : builtin_access::overlap_size (const offset_int a[2], const offset_int b[2],
952 : : offset_int *off)
953 : : {
954 : 6424 : const offset_int *p = a;
955 : 6424 : const offset_int *q = b;
956 : :
957 : : /* Point P at the bigger of the two ranges and Q at the smaller. */
958 : 6424 : if (wi::lts_p (a[1] - a[0], b[1] - b[0]))
959 : : {
960 : 328 : p = b;
961 : 328 : q = a;
962 : : }
963 : :
964 : 6424 : if (p[0] < q[0])
965 : : {
966 : 3802 : if (p[1] < q[0])
967 : 248 : return 0;
968 : :
969 : 3554 : *off = q[0];
970 : 3554 : return wi::smin (p[1], q[1]) - q[0];
971 : : }
972 : :
973 : 2622 : if (q[1] < p[0])
974 : 14 : return 0;
975 : :
976 : 2608 : off[0] = p[0];
977 : 2608 : return q[1] - p[0];
978 : : }
979 : :
980 : : /* Return true if the bounded mempry (memcpy amd similar) or string function
981 : : access (strncpy and similar) ACS overlaps. */
982 : :
983 : : bool
984 : 2091 : builtin_access::generic_overlap ()
985 : : {
986 : 2091 : builtin_access &acs = *this;
987 : 2091 : const builtin_memref *dstref = acs.dstref;
988 : 2091 : const builtin_memref *srcref = acs.srcref;
989 : :
990 : 2091 : gcc_assert (dstref->base == srcref->base);
991 : :
992 : 2091 : const offset_int maxobjsize = acs.dstref->maxobjsize;
993 : :
994 : 2091 : offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
995 : :
996 : : /* Adjust the larger bounds of the offsets (which may be the first
997 : : element if the lower bound is larger than the upper bound) to
998 : : make them valid for the smallest access (if possible) but no smaller
999 : : than the smaller bounds. */
1000 : 2091 : gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));
1001 : :
1002 : 2091 : if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
1003 : 338 : acs.dstoff[1] = maxsize - acs.dstsiz[0];
1004 : 2091 : if (acs.dstoff[1] < acs.dstoff[0])
1005 : 11 : acs.dstoff[1] = acs.dstoff[0];
1006 : :
1007 : 2091 : gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1]));
1008 : :
1009 : 2091 : if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
1010 : 182 : acs.srcoff[1] = maxsize - acs.srcsiz[0];
1011 : 2091 : if (acs.srcoff[1] < acs.srcoff[0])
1012 : 11 : acs.srcoff[1] = acs.srcoff[0];
1013 : :
1014 : : /* Determine the minimum and maximum space for the access given
1015 : : the offsets. */
1016 : 2091 : offset_int space[2];
1017 : 2091 : space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1018 : 2091 : space[1] = space[0];
1019 : :
1020 : 2091 : offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1021 : 2091 : if (acs.srcsiz[0] > 0)
1022 : : {
1023 : 2009 : if (d < space[0])
1024 : 102 : space[0] = d;
1025 : :
1026 : 2009 : if (space[1] < d)
1027 : 382 : space[1] = d;
1028 : : }
1029 : : else
1030 : 82 : space[1] = acs.dstsiz[1];
1031 : :
1032 : 2091 : d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1033 : 2091 : if (d < space[0])
1034 : 61 : space[0] = d;
1035 : :
1036 : 2091 : if (space[1] < d)
1037 : 333 : space[1] = d;
1038 : :
1039 : : /* Treat raw memory functions both of whose references are bounded
1040 : : as special and permit uncertain overlaps to go undetected. For
1041 : : all kinds of constant offset and constant size accesses, if
1042 : : overlap isn't certain it is not possible. */
1043 : 2091 : bool overlap_possible = space[0] < acs.dstsiz[1];
1044 : 2091 : if (!overlap_possible)
1045 : : return false;
1046 : :
1047 : 811 : bool overlap_certain = space[1] < acs.dstsiz[0];
1048 : :
1049 : : /* True when the size of one reference depends on the offset of
1050 : : the other. */
1051 : 811 : bool depends_p = detect_overlap != &builtin_access::generic_overlap;
1052 : :
1053 : 811 : if (!overlap_certain)
1054 : : {
1055 : 420 : if (!dstref->strbounded_p && !depends_p)
1056 : : /* Memcpy only considers certain overlap. */
1057 : : return false;
1058 : :
1059 : : /* There's no way to distinguish an access to the same member
1060 : : of a structure from one to two distinct members of the same
1061 : : structure. Give up to avoid excessive false positives. */
1062 : 149 : tree basetype = TREE_TYPE (dstref->base);
1063 : :
1064 : 149 : if (POINTER_TYPE_P (basetype))
1065 : 16 : basetype = TREE_TYPE (basetype);
1066 : : else
1067 : 274 : while (TREE_CODE (basetype) == ARRAY_TYPE)
1068 : 141 : basetype = TREE_TYPE (basetype);
1069 : :
1070 : 149 : if (RECORD_OR_UNION_TYPE_P (basetype))
1071 : : return false;
1072 : : }
1073 : :
1074 : : /* True for stpcpy and strcpy. */
1075 : 996 : bool stxcpy_p = (!dstref->strbounded_p
1076 : 498 : && detect_overlap == &builtin_access::strcpy_overlap);
1077 : :
1078 : 498 : if (dstref->refoff >= 0
1079 : 13 : && srcref->refoff >= 0
1080 : 5 : && dstref->refoff != srcref->refoff
1081 : 500 : && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p))
1082 : 2 : return false;
1083 : :
1084 : 496 : offset_int siz[2] = { maxobjsize + 1, 0 };
1085 : :
1086 : 496 : ovloff[0] = HOST_WIDE_INT_MAX;
1087 : 496 : ovloff[1] = HOST_WIDE_INT_MIN;
1088 : :
1089 : 496 : if (stxcpy_p)
1090 : : {
1091 : : /* Iterate over the extreme locations (on the horizontal axis formed
1092 : : by their offsets) and sizes of two regions and find their smallest
1093 : : and largest overlap and the corresponding offsets. */
1094 : 324 : for (unsigned i = 0; i != 2; ++i)
1095 : : {
1096 : 216 : const offset_int a[2] = {
1097 : 432 : acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i]
1098 : 216 : };
1099 : :
1100 : 216 : const offset_int b[2] = {
1101 : 432 : acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i]
1102 : 216 : };
1103 : :
1104 : 216 : offset_int off;
1105 : 216 : offset_int sz = overlap_size (a, b, &off);
1106 : 216 : if (sz < siz[0])
1107 : 182 : siz[0] = sz;
1108 : :
1109 : 216 : if (siz[1] <= sz)
1110 : 142 : siz[1] = sz;
1111 : :
1112 : 216 : if (sz != 0)
1113 : : {
1114 : 162 : if (wi::lts_p (off, ovloff[0]))
1115 : 108 : ovloff[0] = off.to_shwi ();
1116 : 162 : if (wi::lts_p (ovloff[1], off))
1117 : 128 : ovloff[1] = off.to_shwi ();
1118 : : }
1119 : : }
1120 : : }
1121 : : else
1122 : : {
1123 : : /* Iterate over the extreme locations (on the horizontal axis
1124 : : formed by their offsets) and sizes of the two regions and
1125 : : find their smallest and largest overlap and the corresponding
1126 : : offsets. */
1127 : :
1128 : 1164 : for (unsigned io = 0; io != 2; ++io)
1129 : 2328 : for (unsigned is = 0; is != 2; ++is)
1130 : : {
1131 : 1552 : const offset_int a[2] = {
1132 : 1552 : acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is]
1133 : 1552 : };
1134 : :
1135 : 4656 : for (unsigned jo = 0; jo != 2; ++jo)
1136 : 9312 : for (unsigned js = 0; js != 2; ++js)
1137 : : {
1138 : 6208 : const offset_int b[2] = {
1139 : 12416 : acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
1140 : 6208 : };
1141 : :
1142 : 6208 : offset_int off;
1143 : 6208 : offset_int sz = overlap_size (a, b, &off);
1144 : 6208 : if (sz < siz[0])
1145 : 515 : siz[0] = sz;
1146 : :
1147 : 6208 : if (siz[1] <= sz)
1148 : 4467 : siz[1] = sz;
1149 : :
1150 : 6208 : if (sz != 0)
1151 : : {
1152 : 5752 : if (wi::lts_p (off, ovloff[0]))
1153 : 388 : ovloff[0] = off.to_shwi ();
1154 : 5752 : if (wi::lts_p (ovloff[1], off))
1155 : 500 : ovloff[1] = off.to_shwi ();
1156 : : }
1157 : : }
1158 : : }
1159 : : }
1160 : :
1161 : 496 : ovlsiz[0] = siz[0].to_shwi ();
1162 : 496 : ovlsiz[1] = siz[1].to_shwi ();
1163 : :
1164 : : /* Adjust the overlap offset range to reflect the overlap size range. */
1165 : 496 : if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
1166 : 62 : ovloff[1] = ovloff[0] + ovlsiz[1] - 1;
1167 : :
1168 : : return true;
1169 : : }
1170 : :
1171 : : /* Return true if the strcat-like access overlaps. */
1172 : :
1173 : : bool
1174 : 133 : builtin_access::strcat_overlap ()
1175 : : {
1176 : 133 : builtin_access &acs = *this;
1177 : 133 : const builtin_memref *dstref = acs.dstref;
1178 : 133 : const builtin_memref *srcref = acs.srcref;
1179 : :
1180 : 133 : gcc_assert (dstref->base == srcref->base);
1181 : :
1182 : 133 : const offset_int maxobjsize = acs.dstref->maxobjsize;
1183 : :
1184 : 133 : gcc_assert (dstref->base && dstref->base == srcref->base);
1185 : :
1186 : : /* Adjust for strcat-like accesses. */
1187 : :
1188 : : /* As a special case for strcat, set the DSTREF offsets to the length
1189 : : of the destination string since the function starts writing over
1190 : : its terminating nul, and set the destination size to 1 for the length
1191 : : of the nul. */
1192 : 133 : acs.dstoff[0] += dstsiz[0] - srcref->sizrange[0];
1193 : 133 : acs.dstoff[1] += dstsiz[1] - srcref->sizrange[1];
1194 : :
1195 : 133 : bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0;
1196 : :
1197 : : /* The lower bound is zero when the size is unknown because then
1198 : : overlap is not certain. */
1199 : 133 : acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1;
1200 : 133 : acs.dstsiz[1] = 1;
1201 : :
1202 : 133 : offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
1203 : :
1204 : : /* For references to the same base object, determine if there's a pair
1205 : : of valid offsets into the two references such that access between
1206 : : them doesn't overlap. Adjust both upper bounds to be valid for
1207 : : the smaller size (i.e., at most MAXSIZE - SIZE). */
1208 : :
1209 : 133 : if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
1210 : 5 : acs.dstoff[1] = maxsize - acs.dstsiz[0];
1211 : :
1212 : 133 : if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
1213 : 2 : acs.srcoff[1] = maxsize - acs.srcsiz[0];
1214 : :
1215 : : /* Check to see if there's enough space for both accesses without
1216 : : overlap. Determine the optimistic (maximum) amount of available
1217 : : space. */
1218 : 133 : offset_int space;
1219 : 133 : if (acs.dstoff[0] <= acs.srcoff[0])
1220 : : {
1221 : 54 : if (acs.dstoff[1] < acs.srcoff[1])
1222 : 40 : space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0];
1223 : : else
1224 : 14 : space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1225 : : }
1226 : : else
1227 : 79 : space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
1228 : :
1229 : : /* Overlap is certain if the distance between the farthest offsets
1230 : : of the opposite accesses is less than the sum of the lower bounds
1231 : : of the sizes of the two accesses. */
1232 : 133 : bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0];
1233 : :
1234 : : /* For a constant-offset, constant size access, consider the largest
1235 : : distance between the offset bounds and the lower bound of the access
1236 : : size. If the overlap isn't certain return success. */
1237 : 133 : if (!overlap_certain
1238 : 97 : && acs.dstoff[0] == acs.dstoff[1]
1239 : 86 : && acs.srcoff[0] == acs.srcoff[1]
1240 : 77 : && acs.dstsiz[0] == acs.dstsiz[1]
1241 : 185 : && acs.srcsiz[0] == acs.srcsiz[1])
1242 : : return false;
1243 : :
1244 : : /* Overlap is not certain but may be possible. */
1245 : :
1246 : 81 : offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0];
1247 : :
1248 : : /* Determine the conservative (minimum) amount of space. */
1249 : 81 : space = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
1250 : 81 : offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
1251 : 81 : if (d < space)
1252 : 6 : space = d;
1253 : 81 : d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
1254 : 81 : if (d < space)
1255 : 2 : space = d;
1256 : :
1257 : : /* For a strict test (used for strcpy and similar with unknown or
1258 : : variable bounds or sizes), consider the smallest distance between
1259 : : the offset bounds and either the upper bound of the access size
1260 : : if known, or the lower bound otherwise. */
1261 : 81 : if (access_min <= space && (access_min != 0 || !strfunc_unknown_args))
1262 : 0 : return false;
1263 : :
1264 : : /* When strcat overlap is certain it is always a single byte:
1265 : : the terminating NUL, regardless of offsets and sizes. When
1266 : : overlap is only possible its range is [0, 1]. */
1267 : 81 : acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
1268 : 81 : acs.ovlsiz[1] = 1;
1269 : :
1270 : 81 : offset_int endoff
1271 : 81 : = dstref->offrange[0] + (dstref->sizrange[0] - srcref->sizrange[0]);
1272 : 81 : if (endoff <= srcref->offrange[0])
1273 : 34 : acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi ();
1274 : : else
1275 : 47 : acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi ();
1276 : :
1277 : 81 : acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1,
1278 : 81 : srcref->sizrange[0]).to_shwi ();
1279 : 81 : if (dstref->offrange[0] == dstref->offrange[1])
1280 : : {
1281 : 73 : if (srcref->offrange[0] == srcref->offrange[1])
1282 : 63 : acs.ovloff[1] = acs.ovloff[0];
1283 : : else
1284 : 10 : acs.ovloff[1]
1285 : 10 : = wi::smin (maxobjsize,
1286 : 10 : srcref->offrange[1] + srcref->sizrange[1]).to_shwi ();
1287 : : }
1288 : : else
1289 : 8 : acs.ovloff[1]
1290 : 8 : = wi::smin (maxobjsize,
1291 : 8 : dstref->offrange[1] + dstref->sizrange[1]).to_shwi ();
1292 : :
1293 : 81 : if (acs.sizrange[0] == 0)
1294 : 0 : acs.sizrange[0] = 1;
1295 : 81 : acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1296 : 81 : return true;
1297 : : }
1298 : :
1299 : : /* Return true if the strcpy-like access overlaps. */
1300 : :
1301 : : bool
1302 : 1311 : builtin_access::strcpy_overlap ()
1303 : : {
1304 : 1311 : return generic_overlap ();
1305 : : }
1306 : :
1307 : : /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
1308 : : if known, or [0, MAXOBJSIZE] otherwise. */
1309 : :
1310 : : static void
1311 : 24082 : clamp_offset (tree base, offset_int refoff[2], offset_int maxobjsize)
1312 : : {
1313 : 24082 : if (!base || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
1314 : : return;
1315 : :
1316 : 10056 : if (refoff[0] < 0 && refoff[1] >= 0)
1317 : 0 : refoff[0] = 0;
1318 : :
1319 : 10056 : if (refoff[1] < refoff[0])
1320 : : {
1321 : 5 : offset_int maxsize = maxobjsize;
1322 : 5 : if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (base)))
1323 : 5 : maxsize = wi::to_offset (size);
1324 : :
1325 : 5 : refoff[1] = wi::umin (refoff[1], maxsize);
1326 : : }
1327 : : }
1328 : :
1329 : : /* Return true if DSTREF and SRCREF describe accesses that either overlap
1330 : : one another or that, in order not to overlap, would imply that the size
1331 : : of the referenced object(s) exceeds the maximum size of an object. Set
1332 : : Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
1333 : : they may overlap in a way that's not apparent from the available data),
1334 : : return false. */
1335 : :
1336 : : bool
1337 : 12069 : builtin_access::overlap ()
1338 : : {
1339 : 12069 : builtin_access &acs = *this;
1340 : :
1341 : 12069 : const offset_int maxobjsize = dstref->maxobjsize;
1342 : :
1343 : 12069 : acs.sizrange[0] = wi::smax (dstref->sizrange[0],
1344 : 12069 : srcref->sizrange[0]).to_shwi ();
1345 : 12069 : acs.sizrange[1] = wi::smax (dstref->sizrange[1],
1346 : 12069 : srcref->sizrange[1]).to_shwi ();
1347 : :
1348 : : /* Check to see if the two references refer to regions that are
1349 : : too large not to overlap in the address space (whose maximum
1350 : : size is PTRDIFF_MAX). */
1351 : 12069 : offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
1352 : 12069 : if (maxobjsize < size)
1353 : : {
1354 : 28 : acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi ();
1355 : 28 : acs.ovlsiz[0] = (size - maxobjsize).to_shwi ();
1356 : 28 : return true;
1357 : : }
1358 : :
1359 : : /* If both base objects aren't known return the maximum possible
1360 : : offset that would make them not overlap. */
1361 : 12041 : if (!dstref->base || !srcref->base)
1362 : : return false;
1363 : :
1364 : : /* If the base object is an array adjust the bounds of the offset
1365 : : to be non-negative and within the bounds of the array if possible. */
1366 : 12041 : clamp_offset (dstref->base, acs.dstoff, maxobjsize);
1367 : :
1368 : 12041 : acs.srcoff[0] = srcref->offrange[0];
1369 : 12041 : acs.srcoff[1] = srcref->offrange[1];
1370 : :
1371 : 12041 : clamp_offset (srcref->base, acs.srcoff, maxobjsize);
1372 : :
1373 : : /* When the upper bound of the offset is less than the lower bound
1374 : : the former is the result of a negative offset being represented
1375 : : as a large positive value or vice versa. The resulting range is
1376 : : a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
1377 : : a union is not representable using the current data structure
1378 : : replace it with the full range of offsets. */
1379 : 12041 : if (acs.dstoff[1] < acs.dstoff[0])
1380 : : {
1381 : 5 : acs.dstoff[0] = -maxobjsize - 1;
1382 : 5 : acs.dstoff[1] = maxobjsize;
1383 : : }
1384 : :
1385 : : /* Validate the offset and size of each reference on its own first.
1386 : : This is independent of whether or not the base objects are the
1387 : : same. Normally, this would have already been detected and
1388 : : diagnosed by -Warray-bounds, unless it has been disabled. */
1389 : 12041 : offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
1390 : 12041 : if (maxobjsize < maxoff)
1391 : : {
1392 : 29 : acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1393 : 29 : acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0];
1394 : 29 : return true;
1395 : : }
1396 : :
1397 : : /* Repeat the same as above but for the source offsets. */
1398 : 12012 : if (acs.srcoff[1] < acs.srcoff[0])
1399 : : {
1400 : 0 : acs.srcoff[0] = -maxobjsize - 1;
1401 : 0 : acs.srcoff[1] = maxobjsize;
1402 : : }
1403 : :
1404 : 12012 : maxoff = acs.srcoff[0] + srcref->sizrange[0];
1405 : 12012 : if (maxobjsize < maxoff)
1406 : : {
1407 : 28 : acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
1408 : 28 : acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1]
1409 : 28 : - maxobjsize).to_shwi ();
1410 : 28 : acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0];
1411 : 28 : return true;
1412 : : }
1413 : :
1414 : 11984 : if (dstref->base != srcref->base)
1415 : : return false;
1416 : :
1417 : 2224 : acs.dstsiz[0] = dstref->sizrange[0];
1418 : 2224 : acs.dstsiz[1] = dstref->sizrange[1];
1419 : :
1420 : 2224 : acs.srcsiz[0] = srcref->sizrange[0];
1421 : 2224 : acs.srcsiz[1] = srcref->sizrange[1];
1422 : :
1423 : : /* Call the appropriate function to determine the overlap. */
1424 : 2224 : if ((this->*detect_overlap) ())
1425 : : {
1426 : 577 : if (!sizrange[1])
1427 : : {
1428 : : /* Unless the access size range has already been set, do so here. */
1429 : 0 : sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi ();
1430 : 0 : sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
1431 : : }
1432 : 577 : return true;
1433 : : }
1434 : :
1435 : : return false;
1436 : : }
1437 : :
1438 : : /* Attempt to detect and diagnose an overlapping copy in a call expression
1439 : : EXPR involving an access ACS to a built-in memory or string function.
1440 : : Return true when one has been detected, false otherwise. */
1441 : :
1442 : : static bool
1443 : 12069 : maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
1444 : : {
1445 : 12069 : if (!acs.overlap ())
1446 : : return false;
1447 : :
1448 : 662 : if (warning_suppressed_p (call, OPT_Wrestrict))
1449 : : return true;
1450 : :
1451 : : /* For convenience. */
1452 : 618 : const builtin_memref &dstref = *acs.dstref;
1453 : 618 : const builtin_memref &srcref = *acs.srcref;
1454 : :
1455 : : /* Determine the range of offsets and sizes of the overlap if it
1456 : : exists and issue diagnostics. */
1457 : 618 : HOST_WIDE_INT *ovloff = acs.ovloff;
1458 : 618 : HOST_WIDE_INT *ovlsiz = acs.ovlsiz;
1459 : 618 : HOST_WIDE_INT *sizrange = acs.sizrange;
1460 : :
1461 : 618 : tree func = gimple_call_fndecl (call);
1462 : :
1463 : 618 : rich_location_with_details richloc (loc, call);
1464 : :
1465 : : /* To avoid a combinatorial explosion of diagnostics format the offsets
1466 : : or their ranges as strings and use them in the warning calls below. */
1467 : 618 : char offstr[3][64];
1468 : :
1469 : 618 : if (dstref.offrange[0] == dstref.offrange[1]
1470 : 618 : || dstref.offrange[1] > HOST_WIDE_INT_MAX)
1471 : 451 : sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC,
1472 : : dstref.offrange[0].to_shwi ());
1473 : : else
1474 : 167 : sprintf (offstr[0],
1475 : : "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1476 : : dstref.offrange[0].to_shwi (),
1477 : : dstref.offrange[1].to_shwi ());
1478 : :
1479 : 618 : if (srcref.offrange[0] == srcref.offrange[1]
1480 : 618 : || srcref.offrange[1] > HOST_WIDE_INT_MAX)
1481 : 397 : sprintf (offstr[1],
1482 : : HOST_WIDE_INT_PRINT_DEC,
1483 : : srcref.offrange[0].to_shwi ());
1484 : : else
1485 : 221 : sprintf (offstr[1],
1486 : : "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1487 : : srcref.offrange[0].to_shwi (),
1488 : : srcref.offrange[1].to_shwi ());
1489 : :
1490 : 618 : if (ovloff[0] == ovloff[1] || !ovloff[1])
1491 : 418 : sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]);
1492 : : else
1493 : 200 : sprintf (offstr[2],
1494 : : "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
1495 : : ovloff[0], ovloff[1]);
1496 : :
1497 : 618 : const offset_int maxobjsize = dstref.maxobjsize;
1498 : 618 : bool must_overlap = ovlsiz[0] > 0;
1499 : :
1500 : 618 : if (ovlsiz[1] == 0)
1501 : 53 : ovlsiz[1] = ovlsiz[0];
1502 : :
1503 : 618 : if (must_overlap)
1504 : : {
1505 : : /* Issue definitive "overlaps" diagnostic in this block. */
1506 : :
1507 : 462 : if (sizrange[0] == sizrange[1])
1508 : : {
1509 : 368 : if (ovlsiz[0] == ovlsiz[1])
1510 : 576 : warning_at (&richloc, OPT_Wrestrict,
1511 : : sizrange[0] == 1
1512 : : ? (ovlsiz[0] == 1
1513 : 6 : ? G_("%qD accessing %wu byte at offsets %s "
1514 : : "and %s overlaps %wu byte at offset %s")
1515 : : : G_("%qD accessing %wu byte at offsets %s "
1516 : : "and %s overlaps %wu bytes at offset "
1517 : : "%s"))
1518 : : : (ovlsiz[0] == 1
1519 : 282 : ? G_("%qD accessing %wu bytes at offsets %s "
1520 : : "and %s overlaps %wu byte at offset %s")
1521 : : : G_("%qD accessing %wu bytes at offsets %s "
1522 : : "and %s overlaps %wu bytes at offset "
1523 : : "%s")),
1524 : : func, sizrange[0],
1525 : : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1526 : 80 : else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1527 : 80 : warning_n (&richloc, OPT_Wrestrict, sizrange[0],
1528 : : "%qD accessing %wu byte at offsets %s "
1529 : : "and %s overlaps between %wu and %wu bytes "
1530 : : "at offset %s",
1531 : : "%qD accessing %wu bytes at offsets %s "
1532 : : "and %s overlaps between %wu and %wu bytes "
1533 : : "at offset %s",
1534 : : func, sizrange[0], offstr[0], offstr[1],
1535 : : ovlsiz[0], ovlsiz[1], offstr[2]);
1536 : : else
1537 : 0 : warning_n (&richloc, OPT_Wrestrict, sizrange[0],
1538 : : "%qD accessing %wu byte at offsets %s and "
1539 : : "%s overlaps %wu or more bytes at offset %s",
1540 : : "%qD accessing %wu bytes at offsets %s and "
1541 : : "%s overlaps %wu or more bytes at offset %s",
1542 : : func, sizrange[0],
1543 : : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1544 : 368 : return true;
1545 : : }
1546 : :
1547 : 94 : if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1548 : : {
1549 : 53 : if (ovlsiz[0] == ovlsiz[1])
1550 : 1 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[0],
1551 : : "%qD accessing between %wu and %wu bytes "
1552 : : "at offsets %s and %s overlaps %wu byte at "
1553 : : "offset %s",
1554 : : "%qD accessing between %wu and %wu bytes "
1555 : : "at offsets %s and %s overlaps %wu bytes "
1556 : : "at offset %s",
1557 : : func, sizrange[0], sizrange[1],
1558 : : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1559 : 52 : else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1560 : 52 : warning_at (&richloc, OPT_Wrestrict,
1561 : : "%qD accessing between %wu and %wu bytes at "
1562 : : "offsets %s and %s overlaps between %wu and %wu "
1563 : : "bytes at offset %s",
1564 : : func, sizrange[0], sizrange[1],
1565 : : offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
1566 : : offstr[2]);
1567 : : else
1568 : 0 : warning_at (&richloc, OPT_Wrestrict,
1569 : : "%qD accessing between %wu and %wu bytes at "
1570 : : "offsets %s and %s overlaps %wu or more bytes "
1571 : : "at offset %s",
1572 : : func, sizrange[0], sizrange[1],
1573 : : offstr[0], offstr[1], ovlsiz[0], offstr[2]);
1574 : 53 : return true;
1575 : : }
1576 : :
1577 : 41 : if (ovlsiz[0] != ovlsiz[1])
1578 : 37 : ovlsiz[1] = maxobjsize.to_shwi ();
1579 : :
1580 : 41 : if (ovlsiz[0] == ovlsiz[1])
1581 : 4 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[0],
1582 : : "%qD accessing %wu or more bytes at offsets "
1583 : : "%s and %s overlaps %wu byte at offset %s",
1584 : : "%qD accessing %wu or more bytes at offsets "
1585 : : "%s and %s overlaps %wu bytes at offset %s",
1586 : : func, sizrange[0], offstr[0], offstr[1],
1587 : : ovlsiz[0], offstr[2]);
1588 : 37 : else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
1589 : 0 : warning_at (&richloc, OPT_Wrestrict,
1590 : : "%qD accessing %wu or more bytes at offsets %s "
1591 : : "and %s overlaps between %wu and %wu bytes "
1592 : : "at offset %s",
1593 : : func, sizrange[0], offstr[0], offstr[1],
1594 : : ovlsiz[0], ovlsiz[1], offstr[2]);
1595 : : else
1596 : 37 : warning_at (&richloc, OPT_Wrestrict,
1597 : : "%qD accessing %wu or more bytes at offsets %s "
1598 : : "and %s overlaps %wu or more bytes at offset %s",
1599 : : func, sizrange[0], offstr[0], offstr[1],
1600 : : ovlsiz[0], offstr[2]);
1601 : 41 : return true;
1602 : : }
1603 : :
1604 : : /* Use more concise wording when one of the offsets is unbounded
1605 : : to avoid confusing the user with large and mostly meaningless
1606 : : numbers. */
1607 : 156 : bool open_range;
1608 : 156 : if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
1609 : 113 : open_range = ((dstref.offrange[0] == 0
1610 : 89 : && dstref.offrange[1] == maxobjsize)
1611 : 255 : || (srcref.offrange[0] == 0
1612 : 53 : && srcref.offrange[1] == maxobjsize));
1613 : : else
1614 : 43 : open_range = ((dstref.offrange[0] == -maxobjsize - 1
1615 : 0 : && dstref.offrange[1] == maxobjsize)
1616 : 43 : || (srcref.offrange[0] == -maxobjsize - 1
1617 : 0 : && srcref.offrange[1] == maxobjsize));
1618 : :
1619 : 156 : if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
1620 : : {
1621 : 86 : if (ovlsiz[1] == 1)
1622 : : {
1623 : 46 : if (open_range)
1624 : 0 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1625 : : "%qD accessing %wu byte may overlap "
1626 : : "%wu byte",
1627 : : "%qD accessing %wu bytes may overlap "
1628 : : "%wu byte",
1629 : : func, sizrange[1], ovlsiz[1]);
1630 : : else
1631 : 46 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1632 : : "%qD accessing %wu byte at offsets %s "
1633 : : "and %s may overlap %wu byte at offset %s",
1634 : : "%qD accessing %wu bytes at offsets %s "
1635 : : "and %s may overlap %wu byte at offset %s",
1636 : : func, sizrange[1], offstr[0], offstr[1],
1637 : : ovlsiz[1], offstr[2]);
1638 : 46 : return true;
1639 : : }
1640 : :
1641 : 40 : if (open_range)
1642 : 0 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1643 : : "%qD accessing %wu byte may overlap "
1644 : : "up to %wu bytes",
1645 : : "%qD accessing %wu bytes may overlap "
1646 : : "up to %wu bytes",
1647 : : func, sizrange[1], ovlsiz[1]);
1648 : : else
1649 : 40 : warning_n (&richloc, OPT_Wrestrict, sizrange[1],
1650 : : "%qD accessing %wu byte at offsets %s and "
1651 : : "%s may overlap up to %wu bytes at offset %s",
1652 : : "%qD accessing %wu bytes at offsets %s and "
1653 : : "%s may overlap up to %wu bytes at offset %s",
1654 : : func, sizrange[1], offstr[0], offstr[1],
1655 : : ovlsiz[1], offstr[2]);
1656 : 40 : return true;
1657 : : }
1658 : :
1659 : 70 : if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
1660 : : {
1661 : 28 : if (open_range)
1662 : 0 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
1663 : : "%qD accessing between %wu and %wu bytes "
1664 : : "may overlap %wu byte",
1665 : : "%qD accessing between %wu and %wu bytes "
1666 : : "may overlap up to %wu bytes",
1667 : : func, sizrange[0], sizrange[1], ovlsiz[1]);
1668 : : else
1669 : 28 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
1670 : : "%qD accessing between %wu and %wu bytes "
1671 : : "at offsets %s and %s may overlap %wu byte "
1672 : : "at offset %s",
1673 : : "%qD accessing between %wu and %wu bytes "
1674 : : "at offsets %s and %s may overlap up to %wu "
1675 : : "bytes at offset %s",
1676 : : func, sizrange[0], sizrange[1],
1677 : : offstr[0], offstr[1], ovlsiz[1], offstr[2]);
1678 : 28 : return true;
1679 : : }
1680 : :
1681 : 42 : warning_n (&richloc, OPT_Wrestrict, ovlsiz[1],
1682 : : "%qD accessing %wu or more bytes at offsets %s "
1683 : : "and %s may overlap %wu byte at offset %s",
1684 : : "%qD accessing %wu or more bytes at offsets %s "
1685 : : "and %s may overlap up to %wu bytes at offset %s",
1686 : : func, sizrange[0], offstr[0], offstr[1],
1687 : : ovlsiz[1], offstr[2]);
1688 : :
1689 : 42 : return true;
1690 : 618 : }
1691 : :
1692 : : /* Validate REF size and offsets in an expression passed as an argument
1693 : : to a CALL to a built-in function FUNC to make sure they are within
1694 : : the bounds of the referenced object if its size is known, or
1695 : : PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1696 : : be issued, false otherwise.
1697 : : Both initial values of the offsets and their final value computed
1698 : : by the function by incrementing the initial value by the size are
1699 : : validated. Return the warning number if the offsets are not valid
1700 : : and a diagnostic has been issued, or would have been issued if
1701 : : DO_WARN had been true, otherwise an invalid warning number. */
1702 : :
1703 : : static opt_code
1704 : 369681 : maybe_diag_access_bounds (gimple *call, tree func, int strict,
1705 : : const builtin_memref &ref, offset_int wroff,
1706 : : bool do_warn)
1707 : : {
1708 : 369681 : location_t loc = gimple_location (call);
1709 : 369681 : const offset_int maxobjsize = ref.maxobjsize;
1710 : :
1711 : 369681 : rich_location_with_details richloc (loc, call);
1712 : :
1713 : : /* Check for excessive size first and regardless of warning options
1714 : : since the result is used to make codegen decisions. */
1715 : 369681 : if (ref.sizrange[0] > maxobjsize)
1716 : : {
1717 : 109 : const opt_code opt = OPT_Wstringop_overflow_;
1718 : : /* Return true without issuing a warning. */
1719 : 109 : if (!do_warn)
1720 : : return opt;
1721 : :
1722 : 109 : if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
1723 : : return no_warning;
1724 : :
1725 : 109 : bool warned = false;
1726 : 109 : if (warn_stringop_overflow)
1727 : : {
1728 : 103 : if (ref.sizrange[0] == ref.sizrange[1])
1729 : 85 : warned = warning_at (&richloc, opt,
1730 : : "%qD specified bound %wu "
1731 : : "exceeds maximum object size %wu",
1732 : : func, ref.sizrange[0].to_uhwi (),
1733 : : maxobjsize.to_uhwi ());
1734 : : else
1735 : 18 : warned = warning_at (&richloc, opt,
1736 : : "%qD specified bound between %wu and %wu "
1737 : : "exceeds maximum object size %wu",
1738 : : func, ref.sizrange[0].to_uhwi (),
1739 : : ref.sizrange[1].to_uhwi (),
1740 : : maxobjsize.to_uhwi ());
1741 : 169 : return warned ? opt : no_warning;
1742 : : }
1743 : : }
1744 : :
1745 : : /* Check for out-bounds pointers regardless of warning options since
1746 : : the result is used to make codegen decisions. An excessive WROFF
1747 : : can only come up as a result of an invalid strncat bound and is
1748 : : diagnosed separately using a more meaningful warning. */
1749 : 369578 : if (maxobjsize < wroff)
1750 : 0 : wroff = 0;
1751 : 369578 : offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
1752 : 369578 : tree oobref = ref.offset_out_of_bounds (strict, ooboff);
1753 : 369578 : if (!oobref)
1754 : : return no_warning;
1755 : :
1756 : 2573 : const opt_code opt = OPT_Warray_bounds_;
1757 : : /* Return true without issuing a warning. */
1758 : 2573 : if (!do_warn)
1759 : : return opt;
1760 : :
1761 : 1440 : if (!warn_array_bounds)
1762 : : return no_warning;
1763 : :
1764 : 531 : if (warning_suppressed_p (ref.ptr, opt)
1765 : 531 : || (ref.ref && warning_suppressed_p (ref.ref, opt)))
1766 : 18 : return no_warning;
1767 : :
1768 : 513 : char rangestr[2][64];
1769 : 513 : if (ooboff[0] == ooboff[1]
1770 : 513 : || (ooboff[0] != ref.offrange[0]
1771 : 172 : && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
1772 : 222 : sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ());
1773 : : else
1774 : 291 : sprintf (rangestr[0], "[%lli, %lli]",
1775 : 291 : (long long) ooboff[0].to_shwi (),
1776 : 291 : (long long) ooboff[1].to_shwi ());
1777 : :
1778 : 513 : bool warned = false;
1779 : :
1780 : 513 : if (oobref == error_mark_node)
1781 : : {
1782 : 22 : if (ref.sizrange[0] == ref.sizrange[1])
1783 : 18 : sprintf (rangestr[1], "%llu",
1784 : 18 : (unsigned long long) ref.sizrange[0].to_shwi ());
1785 : : else
1786 : 4 : sprintf (rangestr[1], "[%lli, %lli]",
1787 : 4 : (unsigned long long) ref.sizrange[0].to_uhwi (),
1788 : 4 : (unsigned long long) ref.sizrange[1].to_uhwi ());
1789 : :
1790 : 22 : tree type;
1791 : :
1792 : 22 : if (DECL_P (ref.base)
1793 : 22 : && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
1794 : : {
1795 : 8 : auto_diagnostic_group d;
1796 : 8 : if (warning_at (&richloc, opt,
1797 : : "%qD pointer overflow between offset %s "
1798 : : "and size %s accessing array %qD with type %qT",
1799 : 8 : func, rangestr[0], rangestr[1], ref.base, type))
1800 : : {
1801 : 16 : inform (DECL_SOURCE_LOCATION (ref.base),
1802 : 8 : "array %qD declared here", ref.base);
1803 : 8 : warned = true;
1804 : : }
1805 : : else
1806 : 0 : warned = warning_at (&richloc, opt,
1807 : : "%qD pointer overflow between offset %s "
1808 : : "and size %s",
1809 : : func, rangestr[0], rangestr[1]);
1810 : 8 : }
1811 : : else
1812 : 14 : warned = warning_at (&richloc, opt,
1813 : : "%qD pointer overflow between offset %s "
1814 : : "and size %s",
1815 : : func, rangestr[0], rangestr[1]);
1816 : : }
1817 : 491 : else if (oobref == ref.base)
1818 : : {
1819 : : /* True when the offset formed by an access to the reference
1820 : : is out of bounds, rather than the initial offset wich is
1821 : : in bounds. This implies access past the end. */
1822 : 300 : bool form = ooboff[0] != ref.offrange[0];
1823 : :
1824 : 300 : if (DECL_P (ref.base))
1825 : : {
1826 : 279 : auto_diagnostic_group d;
1827 : 279 : if ((ref.basesize < maxobjsize
1828 : 422 : && warning_at (&richloc, opt,
1829 : : form
1830 : : ? G_("%qD forming offset %s is out of "
1831 : : "the bounds [0, %wu] of object %qD with "
1832 : : "type %qT")
1833 : : : G_("%qD offset %s is out of the bounds "
1834 : : "[0, %wu] of object %qD with type %qT"),
1835 : : func, rangestr[0], ref.basesize.to_uhwi (),
1836 : 263 : ref.base, TREE_TYPE (ref.base)))
1837 : 313 : || warning_at (&richloc, opt,
1838 : : form
1839 : : ? G_("%qD forming offset %s is out of "
1840 : : "the bounds of object %qD with type %qT")
1841 : : : G_("%qD offset %s is out of the bounds "
1842 : : "of object %qD with type %qT"),
1843 : : func, rangestr[0],
1844 : 18 : ref.base, TREE_TYPE (ref.base)))
1845 : : {
1846 : 554 : inform (DECL_SOURCE_LOCATION (ref.base),
1847 : 277 : "%qD declared here", ref.base);
1848 : 277 : warned = true;
1849 : : }
1850 : 279 : }
1851 : 21 : else if (ref.basesize < maxobjsize)
1852 : 25 : warned = warning_at (&richloc, opt,
1853 : : form
1854 : : ? G_("%qD forming offset %s is out "
1855 : : "of the bounds [0, %wu]")
1856 : : : G_("%qD offset %s is out "
1857 : : "of the bounds [0, %wu]"),
1858 : : func, rangestr[0], ref.basesize.to_uhwi ());
1859 : : else
1860 : 0 : warned = warning_at (&richloc, opt,
1861 : : form
1862 : : ? G_("%qD forming offset %s is out of bounds")
1863 : : : G_("%qD offset %s is out of bounds"),
1864 : : func, rangestr[0]);
1865 : : }
1866 : 191 : else if (TREE_CODE (ref.ref) == MEM_REF)
1867 : : {
1868 : 0 : tree refop = TREE_OPERAND (ref.ref, 0);
1869 : 0 : tree type = TREE_TYPE (refop);
1870 : 0 : if (POINTER_TYPE_P (type))
1871 : 0 : type = TREE_TYPE (type);
1872 : 0 : type = TYPE_MAIN_VARIANT (type);
1873 : :
1874 : 0 : if (warning_at (&richloc, opt,
1875 : : "%qD offset %s from the object at %qE is out "
1876 : : "of the bounds of %qT",
1877 : 0 : func, rangestr[0], ref.base, type))
1878 : : {
1879 : 0 : if (TREE_CODE (ref.ref) == COMPONENT_REF)
1880 : 0 : refop = TREE_OPERAND (ref.ref, 1);
1881 : 0 : if (DECL_P (refop))
1882 : 0 : inform (DECL_SOURCE_LOCATION (refop),
1883 : : "subobject %qD declared here", refop);
1884 : : warned = true;
1885 : : }
1886 : : }
1887 : : else
1888 : : {
1889 : 191 : tree refop = TREE_OPERAND (ref.ref, 0);
1890 : 191 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
1891 : :
1892 : 382 : if (warning_at (&richloc, opt,
1893 : : "%qD offset %s from the object at %qE is out "
1894 : : "of the bounds of referenced subobject %qD with "
1895 : : "type %qT at offset %wi",
1896 : 191 : func, rangestr[0], ref.base,
1897 : 191 : TREE_OPERAND (ref.ref, 1), type,
1898 : : ref.refoff.to_shwi ()))
1899 : : {
1900 : 191 : if (TREE_CODE (ref.ref) == COMPONENT_REF)
1901 : 191 : refop = TREE_OPERAND (ref.ref, 1);
1902 : 191 : if (DECL_P (refop))
1903 : 191 : inform (DECL_SOURCE_LOCATION (refop),
1904 : : "subobject %qD declared here", refop);
1905 : : warned = true;
1906 : : }
1907 : : }
1908 : :
1909 : 322 : return warned ? opt : no_warning;
1910 : 369681 : }
1911 : :
1912 : : /* Check a CALL statement for restrict-violations and issue warnings
1913 : : if/when appropriate. */
1914 : :
1915 : : void
1916 : 5135699 : pass_wrestrict::check_call (gimple *call)
1917 : : {
1918 : : /* Avoid checking the call if it has already been diagnosed for
1919 : : some reason. */
1920 : 5135699 : if (warning_suppressed_p (call, OPT_Wrestrict))
1921 : : return;
1922 : :
1923 : 5126719 : tree func = gimple_call_fndecl (call);
1924 : 5126719 : if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
1925 : : return;
1926 : :
1927 : : /* Argument number to extract from the call (depends on the built-in
1928 : : and its kind). */
1929 : 1168489 : unsigned dst_idx = -1;
1930 : 1168489 : unsigned src_idx = -1;
1931 : 1168489 : unsigned bnd_idx = -1;
1932 : :
1933 : : /* Is this CALL to a string function (as opposed to one to a raw
1934 : : memory function). */
1935 : 1168489 : bool strfun = true;
1936 : :
1937 : 1168489 : switch (DECL_FUNCTION_CODE (func))
1938 : : {
1939 : 102311 : case BUILT_IN_MEMCPY:
1940 : 102311 : case BUILT_IN_MEMCPY_CHK:
1941 : 102311 : case BUILT_IN_MEMPCPY:
1942 : 102311 : case BUILT_IN_MEMPCPY_CHK:
1943 : 102311 : case BUILT_IN_MEMMOVE:
1944 : 102311 : case BUILT_IN_MEMMOVE_CHK:
1945 : 102311 : strfun = false;
1946 : : /* Fall through. */
1947 : :
1948 : : case BUILT_IN_STPNCPY:
1949 : : case BUILT_IN_STPNCPY_CHK:
1950 : : case BUILT_IN_STRNCAT:
1951 : : case BUILT_IN_STRNCAT_CHK:
1952 : : case BUILT_IN_STRNCPY:
1953 : : case BUILT_IN_STRNCPY_CHK:
1954 : : dst_idx = 0;
1955 : : src_idx = 1;
1956 : : bnd_idx = 2;
1957 : : break;
1958 : :
1959 : : case BUILT_IN_MEMSET:
1960 : : case BUILT_IN_MEMSET_CHK:
1961 : : dst_idx = 0;
1962 : : bnd_idx = 2;
1963 : : break;
1964 : :
1965 : 2917 : case BUILT_IN_STPCPY:
1966 : 2917 : case BUILT_IN_STPCPY_CHK:
1967 : 2917 : case BUILT_IN_STRCPY:
1968 : 2917 : case BUILT_IN_STRCPY_CHK:
1969 : 2917 : case BUILT_IN_STRCAT:
1970 : 2917 : case BUILT_IN_STRCAT_CHK:
1971 : 2917 : dst_idx = 0;
1972 : 2917 : src_idx = 1;
1973 : 2917 : break;
1974 : :
1975 : : default:
1976 : : /* Handle other string functions here whose access may need
1977 : : to be validated for in-bounds offsets and non-overlapping
1978 : : copies. */
1979 : : return;
1980 : : }
1981 : :
1982 : 140256 : unsigned nargs = gimple_call_num_args (call);
1983 : :
1984 : 140256 : tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
1985 : 140244 : tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
1986 : 140256 : tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE;
1987 : :
1988 : : /* For string functions with an unspecified or unknown bound,
1989 : : assume the size of the access is one. */
1990 : 140256 : if (!dstwr && strfun)
1991 : 2923 : dstwr = size_one_node;
1992 : :
1993 : : /* DST and SRC can be null for a call with an insufficient number
1994 : : of arguments to a built-in function declared without a protype. */
1995 : 140256 : if (!dst || (src_idx < nargs && !src))
1996 : : return;
1997 : :
1998 : : /* DST, SRC, or DSTWR can also have the wrong type in a call to
1999 : : a function declared without a prototype. Avoid checking such
2000 : : invalid calls. */
2001 : 140244 : if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
2002 : 138030 : || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
2003 : 277590 : || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
2004 : : return;
2005 : :
2006 : 137344 : opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr,
2007 : : NULL_TREE);
2008 : : /* Avoid diagnosing the call again. */
2009 : 137344 : suppress_warning (call, opt);
2010 : : }
2011 : :
2012 : : } /* anonymous namespace */
2013 : :
2014 : : /* Attempt to detect and diagnose invalid offset bounds and (except for
2015 : : memmove) overlapping copy in a call expression EXPR from SRC to DST
2016 : : and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
2017 : : SRCSIZE may be NULL. DO_WARN is false to detect either problem
2018 : : without issue a warning. Return the OPT_Wxxx constant corresponding
2019 : : to the warning if one has been detected and zero otherwise. */
2020 : :
2021 : : opt_code
2022 : 47957 : check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
2023 : : tree srcsize, bool bounds_only /* = false */,
2024 : : bool do_warn /* = true */)
2025 : : {
2026 : 95914 : pointer_query ptrqry (get_range_query (cfun));
2027 : 47957 : return check_bounds_or_overlap (ptrqry,
2028 : : call, dst, src, dstsize, srcsize,
2029 : 47957 : bounds_only, do_warn);
2030 : 47957 : }
2031 : :
2032 : : opt_code
2033 : 185301 : check_bounds_or_overlap (pointer_query &ptrqry,
2034 : : gimple *call, tree dst, tree src, tree dstsize,
2035 : : tree srcsize, bool bounds_only /* = false */,
2036 : : bool do_warn /* = true */)
2037 : : {
2038 : 185301 : tree func = gimple_call_fndecl (call);
2039 : :
2040 : 185301 : builtin_memref dstref (ptrqry, call, dst, dstsize);
2041 : 185301 : builtin_memref srcref (ptrqry, call, src, srcsize);
2042 : :
2043 : : /* Create a descriptor of the access. This may adjust both DSTREF
2044 : : and SRCREF based on one another and the kind of the access. */
2045 : 185301 : builtin_access acs (ptrqry, call, dstref, srcref);
2046 : :
2047 : : /* Set STRICT to the value of the -Warray-bounds=N argument for
2048 : : string functions or when N > 1. */
2049 : 185301 : int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0);
2050 : :
2051 : : /* The starting offset of the destination write access. Nonzero only
2052 : : for the strcat family of functions. */
2053 : 185301 : offset_int wroff = acs.write_off (dstsize);
2054 : :
2055 : : /* Validate offsets to each reference before the access first to make
2056 : : sure they are within the bounds of the destination object if its
2057 : : size is known, or PTRDIFF_MAX otherwise. */
2058 : 185301 : opt_code opt
2059 : 185301 : = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
2060 : 185301 : if (opt == no_warning)
2061 : 184380 : opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
2062 : :
2063 : 184380 : if (opt != no_warning)
2064 : : {
2065 : 1681 : if (do_warn)
2066 : 548 : suppress_warning (call, opt);
2067 : 1681 : return opt;
2068 : : }
2069 : :
2070 : 183620 : if (!warn_restrict || bounds_only || !src)
2071 : : return no_warning;
2072 : :
2073 : 13080 : if (!bounds_only)
2074 : : {
2075 : 13080 : switch (DECL_FUNCTION_CODE (func))
2076 : : {
2077 : : case BUILT_IN_MEMMOVE:
2078 : : case BUILT_IN_MEMMOVE_CHK:
2079 : : case BUILT_IN_MEMSET:
2080 : : case BUILT_IN_MEMSET_CHK:
2081 : : return no_warning;
2082 : : default:
2083 : : break;
2084 : : }
2085 : : }
2086 : :
2087 : 12137 : location_t loc = gimple_location (call);
2088 : 12137 : if (operand_equal_p (dst, src, 0))
2089 : : {
2090 : : /* Issue -Wrestrict unless the pointers are null (those do
2091 : : not point to objects and so do not indicate an overlap;
2092 : : such calls could be the result of sanitization and jump
2093 : : threading). */
2094 : 68 : if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
2095 : : {
2096 : 50 : warning_at (loc, OPT_Wrestrict,
2097 : : "%qD source argument is the same as destination",
2098 : : func);
2099 : 50 : suppress_warning (call, OPT_Wrestrict);
2100 : 50 : return OPT_Wrestrict;
2101 : : }
2102 : :
2103 : 18 : return no_warning;
2104 : : }
2105 : :
2106 : : /* Return false when overlap has been detected. */
2107 : 12069 : if (maybe_diag_overlap (loc, call, acs))
2108 : : {
2109 : 662 : suppress_warning (call, OPT_Wrestrict);
2110 : 662 : return OPT_Wrestrict;
2111 : : }
2112 : :
2113 : : return no_warning;
2114 : : }
2115 : :
2116 : : gimple_opt_pass *
2117 : 285689 : make_pass_warn_restrict (gcc::context *ctxt)
2118 : : {
2119 : 285689 : return new pass_wrestrict (ctxt);
2120 : : }
2121 : :
2122 : : DEBUG_FUNCTION void
2123 : 0 : dump_builtin_memref (FILE *fp, const builtin_memref &ref)
2124 : : {
2125 : 0 : fprintf (fp, "\n ptr = ");
2126 : 0 : print_generic_expr (fp, ref.ptr, TDF_LINENO);
2127 : 0 : fprintf (fp, "\n ref = ");
2128 : 0 : if (ref.ref)
2129 : 0 : print_generic_expr (fp, ref.ref, TDF_LINENO);
2130 : : else
2131 : 0 : fputs ("null", fp);
2132 : 0 : fprintf (fp, "\n base = ");
2133 : 0 : print_generic_expr (fp, ref.base, TDF_LINENO);
2134 : 0 : fprintf (fp,
2135 : : "\n basesize = %lli"
2136 : : "\n refsize = %lli"
2137 : : "\n refoff = %lli"
2138 : : "\n offrange = [%lli, %lli]"
2139 : : "\n sizrange = [%lli, %lli]"
2140 : : "\n strbounded_p = %s\n",
2141 : 0 : (long long)ref.basesize.to_shwi (),
2142 : 0 : (long long)ref.refsize.to_shwi (),
2143 : 0 : (long long)ref.refoff.to_shwi (),
2144 : 0 : (long long)ref.offrange[0].to_shwi (),
2145 : 0 : (long long)ref.offrange[1].to_shwi (),
2146 : 0 : (long long)ref.sizrange[0].to_shwi (),
2147 : 0 : (long long)ref.sizrange[1].to_shwi (),
2148 : 0 : ref.strbounded_p ? "true" : "false");
2149 : 0 : }
2150 : :
2151 : : void
2152 : 0 : builtin_access::dump (FILE *fp) const
2153 : : {
2154 : 0 : fprintf (fp, " dstref:");
2155 : 0 : dump_builtin_memref (fp, *dstref);
2156 : 0 : fprintf (fp, "\n srcref:");
2157 : 0 : dump_builtin_memref (fp, *srcref);
2158 : :
2159 : 0 : fprintf (fp,
2160 : : " sizrange = [%lli, %lli]\n"
2161 : : " ovloff = [%lli, %lli]\n"
2162 : : " ovlsiz = [%lli, %lli]\n"
2163 : : " dstoff = [%lli, %lli]\n"
2164 : : " dstsiz = [%lli, %lli]\n"
2165 : : " srcoff = [%lli, %lli]\n"
2166 : : " srcsiz = [%lli, %lli]\n",
2167 : 0 : (long long)sizrange[0], (long long)sizrange[1],
2168 : 0 : (long long)ovloff[0], (long long)ovloff[1],
2169 : 0 : (long long)ovlsiz[0], (long long)ovlsiz[1],
2170 : 0 : (long long)dstoff[0].to_shwi (), (long long)dstoff[1].to_shwi (),
2171 : 0 : (long long)dstsiz[0].to_shwi (), (long long)dstsiz[1].to_shwi (),
2172 : 0 : (long long)srcoff[0].to_shwi (), (long long)srcoff[1].to_shwi (),
2173 : 0 : (long long)srcsiz[0].to_shwi (), (long long)srcsiz[1].to_shwi ());
2174 : 0 : }
2175 : :
2176 : : DEBUG_FUNCTION void
2177 : 0 : dump_builtin_access (FILE *fp, gimple *stmt, const builtin_access &acs)
2178 : : {
2179 : 0 : if (stmt)
2180 : : {
2181 : 0 : fprintf (fp, "\nDumping builtin_access for ");
2182 : 0 : print_gimple_expr (fp, stmt, TDF_LINENO);
2183 : 0 : fputs (":\n", fp);
2184 : : }
2185 : :
2186 : 0 : acs.dump (fp);
2187 : 0 : }
2188 : :
2189 : : DEBUG_FUNCTION void
2190 : 0 : debug (gimple *stmt, const builtin_access &acs)
2191 : : {
2192 : 0 : dump_builtin_access (stdout, stmt, acs);
2193 : 0 : }
|