]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-ssa-strlen.c
PR tree-optimization/83444
[thirdparty/gcc.git] / gcc / tree-ssa-strlen.c
1 /* String length optimization
2 Copyright (C) 2011-2017 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "alloc-pool.h"
29 #include "tree-pass.h"
30 #include "ssa.h"
31 #include "cgraph.h"
32 #include "gimple-pretty-print.h"
33 #include "gimple-ssa-warn-restrict.h"
34 #include "fold-const.h"
35 #include "stor-layout.h"
36 #include "gimple-fold.h"
37 #include "tree-eh.h"
38 #include "gimplify.h"
39 #include "gimple-iterator.h"
40 #include "gimplify-me.h"
41 #include "expr.h"
42 #include "tree-dfa.h"
43 #include "domwalk.h"
44 #include "tree-ssa-alias.h"
45 #include "tree-ssa-propagate.h"
46 #include "params.h"
47 #include "ipa-chkp.h"
48 #include "tree-hash-traits.h"
49 #include "builtins.h"
50 #include "target.h"
51 #include "diagnostic-core.h"
52 #include "diagnostic.h"
53 #include "intl.h"
54 #include "attribs.h"
55 #include "calls.h"
56
57 /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
58 is an index into strinfo vector, negative value stands for
59 string length of a string literal (~strlen). */
60 static vec<int> ssa_ver_to_stridx;
61
62 /* Number of currently active string indexes plus one. */
63 static int max_stridx;
64
65 /* String information record. */
66 struct strinfo
67 {
68 /* Number of leading characters that are known to be nonzero. This is
69 also the length of the string if FULL_STRING_P.
70
71 The values in a list of related string pointers must be consistent;
72 that is, if strinfo B comes X bytes after strinfo A, it must be
73 the case that A->nonzero_chars == X + B->nonzero_chars. */
74 tree nonzero_chars;
75 /* Any of the corresponding pointers for querying alias oracle. */
76 tree ptr;
77 /* This is used for two things:
78
79 - To record the statement that should be used for delayed length
80 computations. We maintain the invariant that all related strinfos
81 have delayed lengths or none do.
82
83 - To record the malloc or calloc call that produced this result. */
84 gimple *stmt;
85 /* Pointer to '\0' if known, if NULL, it can be computed as
86 ptr + length. */
87 tree endptr;
88 /* Reference count. Any changes to strinfo entry possibly shared
89 with dominating basic blocks need unshare_strinfo first, except
90 for dont_invalidate which affects only the immediately next
91 maybe_invalidate. */
92 int refcount;
93 /* Copy of index. get_strinfo (si->idx) should return si; */
94 int idx;
95 /* These 3 fields are for chaining related string pointers together.
96 E.g. for
97 bl = strlen (b); dl = strlen (d); strcpy (a, b); c = a + bl;
98 strcpy (c, d); e = c + dl;
99 strinfo(a) -> strinfo(c) -> strinfo(e)
100 All have ->first field equal to strinfo(a)->idx and are doubly
101 chained through prev/next fields. The later strinfos are required
102 to point into the same string with zero or more bytes after
103 the previous pointer and all bytes in between the two pointers
104 must be non-zero. Functions like strcpy or memcpy are supposed
105 to adjust all previous strinfo lengths, but not following strinfo
106 lengths (those are uncertain, usually invalidated during
107 maybe_invalidate, except when the alias oracle knows better).
108 Functions like strcat on the other side adjust the whole
109 related strinfo chain.
110 They are updated lazily, so to use the chain the same first fields
111 and si->prev->next == si->idx needs to be verified. */
112 int first;
113 int next;
114 int prev;
115 /* A flag whether the string is known to be written in the current
116 function. */
117 bool writable;
118 /* A flag for the next maybe_invalidate that this strinfo shouldn't
119 be invalidated. Always cleared by maybe_invalidate. */
120 bool dont_invalidate;
121 /* True if the string is known to be nul-terminated after NONZERO_CHARS
122 characters. False is useful when detecting strings that are built
123 up via successive memcpys. */
124 bool full_string_p;
125 };
126
127 /* Pool for allocating strinfo_struct entries. */
128 static object_allocator<strinfo> strinfo_pool ("strinfo pool");
129
130 /* Vector mapping positive string indexes to strinfo, for the
131 current basic block. The first pointer in the vector is special,
132 it is either NULL, meaning the vector isn't shared, or it is
133 a basic block pointer to the owner basic_block if shared.
134 If some other bb wants to modify the vector, the vector needs
135 to be unshared first, and only the owner bb is supposed to free it. */
136 static vec<strinfo *, va_heap, vl_embed> *stridx_to_strinfo;
137
138 /* One OFFSET->IDX mapping. */
139 struct stridxlist
140 {
141 struct stridxlist *next;
142 HOST_WIDE_INT offset;
143 int idx;
144 };
145
146 /* Hash table entry, mapping a DECL to a chain of OFFSET->IDX mappings. */
147 struct decl_stridxlist_map
148 {
149 struct tree_map_base base;
150 struct stridxlist list;
151 };
152
153 /* Hash table for mapping decls to a chained list of offset -> idx
154 mappings. */
155 static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
156
157 /* Hash table mapping strlen calls to stridx instances describing
158 the calls' arguments. Non-null only when warn_stringop_truncation
159 is non-zero. */
160 typedef std::pair<int, location_t> stridx_strlenloc;
161 static hash_map<tree, stridx_strlenloc> *strlen_to_stridx;
162
163 /* Obstack for struct stridxlist and struct decl_stridxlist_map. */
164 static struct obstack stridx_obstack;
165
166 /* Last memcpy statement if it could be adjusted if the trailing
167 '\0' written is immediately overwritten, or
168 *x = '\0' store that could be removed if it is immediately overwritten. */
169 struct laststmt_struct
170 {
171 gimple *stmt;
172 tree len;
173 int stridx;
174 } laststmt;
175
176 static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
177 static void handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *);
178
179 /* Return:
180
181 - 1 if SI is known to start with more than OFF nonzero characters.
182
183 - 0 if SI is known to start with OFF nonzero characters,
184 but is not known to start with more.
185
186 - -1 if SI might not start with OFF nonzero characters. */
187
188 static inline int
189 compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off)
190 {
191 if (si->nonzero_chars
192 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
193 return compare_tree_int (si->nonzero_chars, off);
194 else
195 return -1;
196 }
197
198 /* Return true if SI is known to be a zero-length string. */
199
200 static inline bool
201 zero_length_string_p (strinfo *si)
202 {
203 return si->full_string_p && integer_zerop (si->nonzero_chars);
204 }
205
206 /* Return strinfo vector entry IDX. */
207
208 static inline strinfo *
209 get_strinfo (int idx)
210 {
211 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
212 return NULL;
213 return (*stridx_to_strinfo)[idx];
214 }
215
216 /* Get the next strinfo in the chain after SI, or null if none. */
217
218 static inline strinfo *
219 get_next_strinfo (strinfo *si)
220 {
221 if (si->next == 0)
222 return NULL;
223 strinfo *nextsi = get_strinfo (si->next);
224 if (nextsi == NULL || nextsi->first != si->first || nextsi->prev != si->idx)
225 return NULL;
226 return nextsi;
227 }
228
229 /* Helper function for get_stridx. Return the strinfo index of the address
230 of EXP, which is available in PTR if nonnull. If OFFSET_OUT, it is
231 OK to return the index for some X <= &EXP and store &EXP - X in
232 *OFFSET_OUT. */
233
234 static int
235 get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
236 {
237 HOST_WIDE_INT off;
238 struct stridxlist *list, *last = NULL;
239 tree base;
240
241 if (!decl_to_stridxlist_htab)
242 return 0;
243
244 base = get_addr_base_and_unit_offset (exp, &off);
245 if (base == NULL || !DECL_P (base))
246 return 0;
247
248 list = decl_to_stridxlist_htab->get (base);
249 if (list == NULL)
250 return 0;
251
252 do
253 {
254 if (list->offset == off)
255 {
256 if (offset_out)
257 *offset_out = 0;
258 return list->idx;
259 }
260 if (list->offset > off)
261 return 0;
262 last = list;
263 list = list->next;
264 }
265 while (list);
266
267 if ((offset_out || ptr) && last && last->idx > 0)
268 {
269 unsigned HOST_WIDE_INT rel_off
270 = (unsigned HOST_WIDE_INT) off - last->offset;
271 strinfo *si = get_strinfo (last->idx);
272 if (si && compare_nonzero_chars (si, rel_off) >= 0)
273 {
274 if (offset_out)
275 {
276 *offset_out = rel_off;
277 return last->idx;
278 }
279 else
280 return get_stridx_plus_constant (si, rel_off, ptr);
281 }
282 }
283 return 0;
284 }
285
286 /* Return string index for EXP. */
287
288 static int
289 get_stridx (tree exp)
290 {
291 tree s, o;
292
293 if (TREE_CODE (exp) == SSA_NAME)
294 {
295 if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
296 return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
297 int i;
298 tree e = exp;
299 HOST_WIDE_INT off = 0;
300 for (i = 0; i < 5; i++)
301 {
302 gimple *def_stmt = SSA_NAME_DEF_STMT (e);
303 if (!is_gimple_assign (def_stmt)
304 || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
305 return 0;
306 tree rhs1 = gimple_assign_rhs1 (def_stmt);
307 tree rhs2 = gimple_assign_rhs2 (def_stmt);
308 if (TREE_CODE (rhs1) != SSA_NAME
309 || !tree_fits_shwi_p (rhs2))
310 return 0;
311 HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
312 if (this_off < 0)
313 return 0;
314 off = (unsigned HOST_WIDE_INT) off + this_off;
315 if (off < 0)
316 return 0;
317 if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
318 {
319 strinfo *si
320 = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
321 if (si && compare_nonzero_chars (si, off) >= 0)
322 return get_stridx_plus_constant (si, off, exp);
323 }
324 e = rhs1;
325 }
326 return 0;
327 }
328
329 if (TREE_CODE (exp) == ADDR_EXPR)
330 {
331 int idx = get_addr_stridx (TREE_OPERAND (exp, 0), exp, NULL);
332 if (idx != 0)
333 return idx;
334 }
335
336 s = string_constant (exp, &o);
337 if (s != NULL_TREE
338 && (o == NULL_TREE || tree_fits_shwi_p (o))
339 && TREE_STRING_LENGTH (s) > 0)
340 {
341 HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
342 const char *p = TREE_STRING_POINTER (s);
343 int max = TREE_STRING_LENGTH (s) - 1;
344
345 if (p[max] == '\0' && offset >= 0 && offset <= max)
346 return ~(int) strlen (p + offset);
347 }
348 return 0;
349 }
350
351 /* Return true if strinfo vector is shared with the immediate dominator. */
352
353 static inline bool
354 strinfo_shared (void)
355 {
356 return vec_safe_length (stridx_to_strinfo)
357 && (*stridx_to_strinfo)[0] != NULL;
358 }
359
360 /* Unshare strinfo vector that is shared with the immediate dominator. */
361
362 static void
363 unshare_strinfo_vec (void)
364 {
365 strinfo *si;
366 unsigned int i = 0;
367
368 gcc_assert (strinfo_shared ());
369 stridx_to_strinfo = vec_safe_copy (stridx_to_strinfo);
370 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
371 if (si != NULL)
372 si->refcount++;
373 (*stridx_to_strinfo)[0] = NULL;
374 }
375
376 /* Attempt to create a string index for exp, ADDR_EXPR's operand.
377 Return a pointer to the location where the string index can
378 be stored (if 0) or is stored, or NULL if this can't be tracked. */
379
380 static int *
381 addr_stridxptr (tree exp)
382 {
383 HOST_WIDE_INT off;
384
385 tree base = get_addr_base_and_unit_offset (exp, &off);
386 if (base == NULL_TREE || !DECL_P (base))
387 return NULL;
388
389 if (!decl_to_stridxlist_htab)
390 {
391 decl_to_stridxlist_htab
392 = new hash_map<tree_decl_hash, stridxlist> (64);
393 gcc_obstack_init (&stridx_obstack);
394 }
395
396 bool existed;
397 stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, &existed);
398 if (existed)
399 {
400 int i;
401 stridxlist *before = NULL;
402 for (i = 0; i < 32; i++)
403 {
404 if (list->offset == off)
405 return &list->idx;
406 if (list->offset > off && before == NULL)
407 before = list;
408 if (list->next == NULL)
409 break;
410 list = list->next;
411 }
412 if (i == 32)
413 return NULL;
414 if (before)
415 {
416 list = before;
417 before = XOBNEW (&stridx_obstack, struct stridxlist);
418 *before = *list;
419 list->next = before;
420 list->offset = off;
421 list->idx = 0;
422 return &list->idx;
423 }
424 list->next = XOBNEW (&stridx_obstack, struct stridxlist);
425 list = list->next;
426 }
427
428 list->next = NULL;
429 list->offset = off;
430 list->idx = 0;
431 return &list->idx;
432 }
433
434 /* Create a new string index, or return 0 if reached limit. */
435
436 static int
437 new_stridx (tree exp)
438 {
439 int idx;
440 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
441 return 0;
442 if (TREE_CODE (exp) == SSA_NAME)
443 {
444 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp))
445 return 0;
446 idx = max_stridx++;
447 ssa_ver_to_stridx[SSA_NAME_VERSION (exp)] = idx;
448 return idx;
449 }
450 if (TREE_CODE (exp) == ADDR_EXPR)
451 {
452 int *pidx = addr_stridxptr (TREE_OPERAND (exp, 0));
453 if (pidx != NULL)
454 {
455 gcc_assert (*pidx == 0);
456 *pidx = max_stridx++;
457 return *pidx;
458 }
459 }
460 return 0;
461 }
462
463 /* Like new_stridx, but for ADDR_EXPR's operand instead. */
464
465 static int
466 new_addr_stridx (tree exp)
467 {
468 int *pidx;
469 if (max_stridx >= PARAM_VALUE (PARAM_MAX_TRACKED_STRLENS))
470 return 0;
471 pidx = addr_stridxptr (exp);
472 if (pidx != NULL)
473 {
474 gcc_assert (*pidx == 0);
475 *pidx = max_stridx++;
476 return *pidx;
477 }
478 return 0;
479 }
480
481 /* Create a new strinfo. */
482
483 static strinfo *
484 new_strinfo (tree ptr, int idx, tree nonzero_chars, bool full_string_p)
485 {
486 strinfo *si = strinfo_pool.allocate ();
487 si->nonzero_chars = nonzero_chars;
488 si->ptr = ptr;
489 si->stmt = NULL;
490 si->endptr = NULL_TREE;
491 si->refcount = 1;
492 si->idx = idx;
493 si->first = 0;
494 si->prev = 0;
495 si->next = 0;
496 si->writable = false;
497 si->dont_invalidate = false;
498 si->full_string_p = full_string_p;
499 return si;
500 }
501
502 /* Decrease strinfo refcount and free it if not referenced anymore. */
503
504 static inline void
505 free_strinfo (strinfo *si)
506 {
507 if (si && --si->refcount == 0)
508 strinfo_pool.remove (si);
509 }
510
511 /* Set strinfo in the vector entry IDX to SI. */
512
513 static inline void
514 set_strinfo (int idx, strinfo *si)
515 {
516 if (vec_safe_length (stridx_to_strinfo) && (*stridx_to_strinfo)[0])
517 unshare_strinfo_vec ();
518 if (vec_safe_length (stridx_to_strinfo) <= (unsigned int) idx)
519 vec_safe_grow_cleared (stridx_to_strinfo, idx + 1);
520 (*stridx_to_strinfo)[idx] = si;
521 }
522
523 /* Return the first strinfo in the related strinfo chain
524 if all strinfos in between belong to the chain, otherwise NULL. */
525
526 static strinfo *
527 verify_related_strinfos (strinfo *origsi)
528 {
529 strinfo *si = origsi, *psi;
530
531 if (origsi->first == 0)
532 return NULL;
533 for (; si->prev; si = psi)
534 {
535 if (si->first != origsi->first)
536 return NULL;
537 psi = get_strinfo (si->prev);
538 if (psi == NULL)
539 return NULL;
540 if (psi->next != si->idx)
541 return NULL;
542 }
543 if (si->idx != si->first)
544 return NULL;
545 return si;
546 }
547
548 /* Set SI's endptr to ENDPTR and compute its length based on SI->ptr.
549 Use LOC for folding. */
550
551 static void
552 set_endptr_and_length (location_t loc, strinfo *si, tree endptr)
553 {
554 si->endptr = endptr;
555 si->stmt = NULL;
556 tree start_as_size = fold_convert_loc (loc, size_type_node, si->ptr);
557 tree end_as_size = fold_convert_loc (loc, size_type_node, endptr);
558 si->nonzero_chars = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
559 end_as_size, start_as_size);
560 si->full_string_p = true;
561 }
562
563 /* Return string length, or NULL if it can't be computed. */
564
565 static tree
566 get_string_length (strinfo *si)
567 {
568 if (si->nonzero_chars)
569 return si->full_string_p ? si->nonzero_chars : NULL;
570
571 if (si->stmt)
572 {
573 gimple *stmt = si->stmt, *lenstmt;
574 bool with_bounds = gimple_call_with_bounds_p (stmt);
575 tree callee, lhs, fn, tem;
576 location_t loc;
577 gimple_stmt_iterator gsi;
578
579 gcc_assert (is_gimple_call (stmt));
580 callee = gimple_call_fndecl (stmt);
581 gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
582 lhs = gimple_call_lhs (stmt);
583 /* unshare_strinfo is intentionally not called here. The (delayed)
584 transformation of strcpy or strcat into stpcpy is done at the place
585 of the former strcpy/strcat call and so can affect all the strinfos
586 with the same stmt. If they were unshared before and transformation
587 has been already done, the handling of BUILT_IN_STPCPY{,_CHK} should
588 just compute the right length. */
589 switch (DECL_FUNCTION_CODE (callee))
590 {
591 case BUILT_IN_STRCAT:
592 case BUILT_IN_STRCAT_CHK:
593 case BUILT_IN_STRCAT_CHKP:
594 case BUILT_IN_STRCAT_CHK_CHKP:
595 gsi = gsi_for_stmt (stmt);
596 fn = builtin_decl_implicit (BUILT_IN_STRLEN);
597 gcc_assert (lhs == NULL_TREE);
598 tem = unshare_expr (gimple_call_arg (stmt, 0));
599 if (with_bounds)
600 {
601 lenstmt = gimple_build_call (chkp_maybe_create_clone (fn)->decl,
602 2, tem, gimple_call_arg (stmt, 1));
603 gimple_call_set_with_bounds (lenstmt, true);
604 }
605 else
606 lenstmt = gimple_build_call (fn, 1, tem);
607 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
608 gimple_call_set_lhs (lenstmt, lhs);
609 gimple_set_vuse (lenstmt, gimple_vuse (stmt));
610 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
611 tem = gimple_call_arg (stmt, 0);
612 if (!ptrofftype_p (TREE_TYPE (lhs)))
613 {
614 lhs = convert_to_ptrofftype (lhs);
615 lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
616 true, GSI_SAME_STMT);
617 }
618 lenstmt = gimple_build_assign
619 (make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0))),
620 POINTER_PLUS_EXPR,tem, lhs);
621 gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
622 gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
623 lhs = NULL_TREE;
624 /* FALLTHRU */
625 case BUILT_IN_STRCPY:
626 case BUILT_IN_STRCPY_CHK:
627 case BUILT_IN_STRCPY_CHKP:
628 case BUILT_IN_STRCPY_CHK_CHKP:
629 gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
630 if (gimple_call_num_args (stmt) == (with_bounds ? 4 : 2))
631 fn = builtin_decl_implicit (BUILT_IN_STPCPY);
632 else
633 fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
634 if (with_bounds)
635 fn = chkp_maybe_create_clone (fn)->decl;
636 gcc_assert (lhs == NULL_TREE);
637 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
638 {
639 fprintf (dump_file, "Optimizing: ");
640 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
641 }
642 gimple_call_set_fndecl (stmt, fn);
643 lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
644 gimple_call_set_lhs (stmt, lhs);
645 update_stmt (stmt);
646 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
647 {
648 fprintf (dump_file, "into: ");
649 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
650 }
651 /* FALLTHRU */
652 case BUILT_IN_STPCPY:
653 case BUILT_IN_STPCPY_CHK:
654 case BUILT_IN_STPCPY_CHKP:
655 case BUILT_IN_STPCPY_CHK_CHKP:
656 gcc_assert (lhs != NULL_TREE);
657 loc = gimple_location (stmt);
658 set_endptr_and_length (loc, si, lhs);
659 for (strinfo *chainsi = verify_related_strinfos (si);
660 chainsi != NULL;
661 chainsi = get_next_strinfo (chainsi))
662 if (chainsi->nonzero_chars == NULL)
663 set_endptr_and_length (loc, chainsi, lhs);
664 break;
665 case BUILT_IN_MALLOC:
666 break;
667 /* BUILT_IN_CALLOC always has si->nonzero_chars set. */
668 default:
669 gcc_unreachable ();
670 break;
671 }
672 }
673
674 return si->nonzero_chars;
675 }
676
677 /* Invalidate string length information for strings whose length
678 might change due to stores in stmt. */
679
680 static bool
681 maybe_invalidate (gimple *stmt)
682 {
683 strinfo *si;
684 unsigned int i;
685 bool nonempty = false;
686
687 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
688 if (si != NULL)
689 {
690 if (!si->dont_invalidate)
691 {
692 ao_ref r;
693 /* Do not use si->nonzero_chars. */
694 ao_ref_init_from_ptr_and_size (&r, si->ptr, NULL_TREE);
695 if (stmt_may_clobber_ref_p_1 (stmt, &r))
696 {
697 set_strinfo (i, NULL);
698 free_strinfo (si);
699 continue;
700 }
701 }
702 si->dont_invalidate = false;
703 nonempty = true;
704 }
705 return nonempty;
706 }
707
708 /* Unshare strinfo record SI, if it has refcount > 1 or
709 if stridx_to_strinfo vector is shared with some other
710 bbs. */
711
712 static strinfo *
713 unshare_strinfo (strinfo *si)
714 {
715 strinfo *nsi;
716
717 if (si->refcount == 1 && !strinfo_shared ())
718 return si;
719
720 nsi = new_strinfo (si->ptr, si->idx, si->nonzero_chars, si->full_string_p);
721 nsi->stmt = si->stmt;
722 nsi->endptr = si->endptr;
723 nsi->first = si->first;
724 nsi->prev = si->prev;
725 nsi->next = si->next;
726 nsi->writable = si->writable;
727 set_strinfo (si->idx, nsi);
728 free_strinfo (si);
729 return nsi;
730 }
731
732 /* Attempt to create a new strinfo for BASESI + OFF, or find existing
733 strinfo if there is any. Return it's idx, or 0 if no strinfo has
734 been created. */
735
736 static int
737 get_stridx_plus_constant (strinfo *basesi, unsigned HOST_WIDE_INT off,
738 tree ptr)
739 {
740 if (TREE_CODE (ptr) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
741 return 0;
742
743 if (compare_nonzero_chars (basesi, off) < 0
744 || !tree_fits_uhwi_p (basesi->nonzero_chars))
745 return 0;
746
747 unsigned HOST_WIDE_INT nonzero_chars
748 = tree_to_uhwi (basesi->nonzero_chars) - off;
749 strinfo *si = basesi, *chainsi;
750 if (si->first || si->prev || si->next)
751 si = verify_related_strinfos (basesi);
752 if (si == NULL
753 || si->nonzero_chars == NULL_TREE
754 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
755 return 0;
756
757 if (TREE_CODE (ptr) == SSA_NAME
758 && ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
759 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
760
761 gcc_checking_assert (compare_tree_int (si->nonzero_chars, off) != -1);
762 for (chainsi = si; chainsi->next; chainsi = si)
763 {
764 si = get_next_strinfo (chainsi);
765 if (si == NULL
766 || si->nonzero_chars == NULL_TREE
767 || TREE_CODE (si->nonzero_chars) != INTEGER_CST)
768 break;
769 int r = compare_tree_int (si->nonzero_chars, nonzero_chars);
770 if (r != 1)
771 {
772 if (r == 0)
773 {
774 if (TREE_CODE (ptr) == SSA_NAME)
775 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = si->idx;
776 else
777 {
778 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
779 if (pidx != NULL && *pidx == 0)
780 *pidx = si->idx;
781 }
782 return si->idx;
783 }
784 break;
785 }
786 }
787
788 int idx = new_stridx (ptr);
789 if (idx == 0)
790 return 0;
791 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
792 basesi->full_string_p);
793 set_strinfo (idx, si);
794 if (chainsi->next)
795 {
796 strinfo *nextsi = unshare_strinfo (get_strinfo (chainsi->next));
797 si->next = nextsi->idx;
798 nextsi->prev = idx;
799 }
800 chainsi = unshare_strinfo (chainsi);
801 if (chainsi->first == 0)
802 chainsi->first = chainsi->idx;
803 chainsi->next = idx;
804 if (chainsi->endptr == NULL_TREE && zero_length_string_p (si))
805 chainsi->endptr = ptr;
806 si->endptr = chainsi->endptr;
807 si->prev = chainsi->idx;
808 si->first = chainsi->first;
809 si->writable = chainsi->writable;
810 return si->idx;
811 }
812
813 /* Note that PTR, a pointer SSA_NAME initialized in the current stmt, points
814 to a zero-length string and if possible chain it to a related strinfo
815 chain whose part is or might be CHAINSI. */
816
817 static strinfo *
818 zero_length_string (tree ptr, strinfo *chainsi)
819 {
820 strinfo *si;
821 int idx;
822 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
823 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
824 gcc_checking_assert (TREE_CODE (ptr) == SSA_NAME
825 && ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] == 0);
826
827 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr))
828 return NULL;
829 if (chainsi != NULL)
830 {
831 si = verify_related_strinfos (chainsi);
832 if (si)
833 {
834 do
835 {
836 /* We shouldn't mix delayed and non-delayed lengths. */
837 gcc_assert (si->full_string_p);
838 if (si->endptr == NULL_TREE)
839 {
840 si = unshare_strinfo (si);
841 si->endptr = ptr;
842 }
843 chainsi = si;
844 si = get_next_strinfo (si);
845 }
846 while (si != NULL);
847 if (zero_length_string_p (chainsi))
848 {
849 if (chainsi->next)
850 {
851 chainsi = unshare_strinfo (chainsi);
852 chainsi->next = 0;
853 }
854 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = chainsi->idx;
855 return chainsi;
856 }
857 }
858 else
859 {
860 /* We shouldn't mix delayed and non-delayed lengths. */
861 gcc_assert (chainsi->full_string_p);
862 if (chainsi->first || chainsi->prev || chainsi->next)
863 {
864 chainsi = unshare_strinfo (chainsi);
865 chainsi->first = 0;
866 chainsi->prev = 0;
867 chainsi->next = 0;
868 }
869 }
870 }
871 idx = new_stridx (ptr);
872 if (idx == 0)
873 return NULL;
874 si = new_strinfo (ptr, idx, build_int_cst (size_type_node, 0), true);
875 set_strinfo (idx, si);
876 si->endptr = ptr;
877 if (chainsi != NULL)
878 {
879 chainsi = unshare_strinfo (chainsi);
880 if (chainsi->first == 0)
881 chainsi->first = chainsi->idx;
882 chainsi->next = idx;
883 if (chainsi->endptr == NULL_TREE)
884 chainsi->endptr = ptr;
885 si->prev = chainsi->idx;
886 si->first = chainsi->first;
887 si->writable = chainsi->writable;
888 }
889 return si;
890 }
891
892 /* For strinfo ORIGSI whose length has been just updated, adjust other
893 related strinfos so that they match the new ORIGSI. This involves:
894
895 - adding ADJ to the nonzero_chars fields
896 - copying full_string_p from the new ORIGSI. */
897
898 static void
899 adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
900 {
901 strinfo *si = verify_related_strinfos (origsi);
902
903 if (si == NULL)
904 return;
905
906 while (1)
907 {
908 strinfo *nsi;
909
910 if (si != origsi)
911 {
912 tree tem;
913
914 si = unshare_strinfo (si);
915 /* We shouldn't see delayed lengths here; the caller must have
916 calculated the old length in order to calculate the
917 adjustment. */
918 gcc_assert (si->nonzero_chars);
919 tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
920 si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
921 TREE_TYPE (si->nonzero_chars),
922 si->nonzero_chars, tem);
923 si->full_string_p = origsi->full_string_p;
924
925 si->endptr = NULL_TREE;
926 si->dont_invalidate = true;
927 }
928 nsi = get_next_strinfo (si);
929 if (nsi == NULL)
930 return;
931 si = nsi;
932 }
933 }
934
935 /* Find if there are other SSA_NAME pointers equal to PTR
936 for which we don't track their string lengths yet. If so, use
937 IDX for them. */
938
939 static void
940 find_equal_ptrs (tree ptr, int idx)
941 {
942 if (TREE_CODE (ptr) != SSA_NAME)
943 return;
944 while (1)
945 {
946 gimple *stmt = SSA_NAME_DEF_STMT (ptr);
947 if (!is_gimple_assign (stmt))
948 return;
949 ptr = gimple_assign_rhs1 (stmt);
950 switch (gimple_assign_rhs_code (stmt))
951 {
952 case SSA_NAME:
953 break;
954 CASE_CONVERT:
955 if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
956 return;
957 if (TREE_CODE (ptr) == SSA_NAME)
958 break;
959 if (TREE_CODE (ptr) != ADDR_EXPR)
960 return;
961 /* FALLTHRU */
962 case ADDR_EXPR:
963 {
964 int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
965 if (pidx != NULL && *pidx == 0)
966 *pidx = idx;
967 return;
968 }
969 default:
970 return;
971 }
972
973 /* We might find an endptr created in this pass. Grow the
974 vector in that case. */
975 if (ssa_ver_to_stridx.length () <= SSA_NAME_VERSION (ptr))
976 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
977
978 if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] != 0)
979 return;
980 ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)] = idx;
981 }
982 }
983
984 /* Return true if STMT is a call to a builtin function with the right
985 arguments and attributes that should be considered for optimization
986 by this pass. */
987
988 static bool
989 valid_builtin_call (gimple *stmt)
990 {
991 if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
992 return false;
993
994 tree callee = gimple_call_fndecl (stmt);
995 switch (DECL_FUNCTION_CODE (callee))
996 {
997 case BUILT_IN_MEMCMP:
998 case BUILT_IN_MEMCMP_EQ:
999 case BUILT_IN_STRCHR:
1000 case BUILT_IN_STRCHR_CHKP:
1001 case BUILT_IN_STRLEN:
1002 case BUILT_IN_STRLEN_CHKP:
1003 /* The above functions should be pure. Punt if they aren't. */
1004 if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
1005 return false;
1006 break;
1007
1008 case BUILT_IN_CALLOC:
1009 case BUILT_IN_MALLOC:
1010 case BUILT_IN_MEMCPY:
1011 case BUILT_IN_MEMCPY_CHK:
1012 case BUILT_IN_MEMCPY_CHKP:
1013 case BUILT_IN_MEMCPY_CHK_CHKP:
1014 case BUILT_IN_MEMPCPY:
1015 case BUILT_IN_MEMPCPY_CHK:
1016 case BUILT_IN_MEMPCPY_CHKP:
1017 case BUILT_IN_MEMPCPY_CHK_CHKP:
1018 case BUILT_IN_MEMSET:
1019 case BUILT_IN_STPCPY:
1020 case BUILT_IN_STPCPY_CHK:
1021 case BUILT_IN_STPCPY_CHKP:
1022 case BUILT_IN_STPCPY_CHK_CHKP:
1023 case BUILT_IN_STRCAT:
1024 case BUILT_IN_STRCAT_CHK:
1025 case BUILT_IN_STRCAT_CHKP:
1026 case BUILT_IN_STRCAT_CHK_CHKP:
1027 case BUILT_IN_STRCPY:
1028 case BUILT_IN_STRCPY_CHK:
1029 case BUILT_IN_STRCPY_CHKP:
1030 case BUILT_IN_STRCPY_CHK_CHKP:
1031 /* The above functions should be neither const nor pure. Punt if they
1032 aren't. */
1033 if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
1034 return false;
1035 break;
1036
1037 default:
1038 break;
1039 }
1040
1041 return true;
1042 }
1043
1044 /* If the last .MEM setter statement before STMT is
1045 memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
1046 and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
1047 just memcpy (x, y, strlen (y)). SI must be the zero length
1048 strinfo. */
1049
1050 static void
1051 adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
1052 {
1053 tree vuse, callee, len;
1054 struct laststmt_struct last = laststmt;
1055 strinfo *lastsi, *firstsi;
1056 unsigned len_arg_no = 2;
1057
1058 laststmt.stmt = NULL;
1059 laststmt.len = NULL_TREE;
1060 laststmt.stridx = 0;
1061
1062 if (last.stmt == NULL)
1063 return;
1064
1065 vuse = gimple_vuse (stmt);
1066 if (vuse == NULL_TREE
1067 || SSA_NAME_DEF_STMT (vuse) != last.stmt
1068 || !has_single_use (vuse))
1069 return;
1070
1071 gcc_assert (last.stridx > 0);
1072 lastsi = get_strinfo (last.stridx);
1073 if (lastsi == NULL)
1074 return;
1075
1076 if (lastsi != si)
1077 {
1078 if (lastsi->first == 0 || lastsi->first != si->first)
1079 return;
1080
1081 firstsi = verify_related_strinfos (si);
1082 if (firstsi == NULL)
1083 return;
1084 while (firstsi != lastsi)
1085 {
1086 firstsi = get_next_strinfo (firstsi);
1087 if (firstsi == NULL)
1088 return;
1089 }
1090 }
1091
1092 if (!is_strcat && !zero_length_string_p (si))
1093 return;
1094
1095 if (is_gimple_assign (last.stmt))
1096 {
1097 gimple_stmt_iterator gsi;
1098
1099 if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
1100 return;
1101 if (stmt_could_throw_p (last.stmt))
1102 return;
1103 gsi = gsi_for_stmt (last.stmt);
1104 unlink_stmt_vdef (last.stmt);
1105 release_defs (last.stmt);
1106 gsi_remove (&gsi, true);
1107 return;
1108 }
1109
1110 if (!valid_builtin_call (last.stmt))
1111 return;
1112
1113 callee = gimple_call_fndecl (last.stmt);
1114 switch (DECL_FUNCTION_CODE (callee))
1115 {
1116 case BUILT_IN_MEMCPY:
1117 case BUILT_IN_MEMCPY_CHK:
1118 break;
1119 case BUILT_IN_MEMCPY_CHKP:
1120 case BUILT_IN_MEMCPY_CHK_CHKP:
1121 len_arg_no = 4;
1122 break;
1123 default:
1124 return;
1125 }
1126
1127 len = gimple_call_arg (last.stmt, len_arg_no);
1128 if (tree_fits_uhwi_p (len))
1129 {
1130 if (!tree_fits_uhwi_p (last.len)
1131 || integer_zerop (len)
1132 || tree_to_uhwi (len) != tree_to_uhwi (last.len) + 1)
1133 return;
1134 /* Don't adjust the length if it is divisible by 4, it is more efficient
1135 to store the extra '\0' in that case. */
1136 if ((tree_to_uhwi (len) & 3) == 0)
1137 return;
1138 }
1139 else if (TREE_CODE (len) == SSA_NAME)
1140 {
1141 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1142 if (!is_gimple_assign (def_stmt)
1143 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
1144 || gimple_assign_rhs1 (def_stmt) != last.len
1145 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
1146 return;
1147 }
1148 else
1149 return;
1150
1151 gimple_call_set_arg (last.stmt, len_arg_no, last.len);
1152 update_stmt (last.stmt);
1153 }
1154
1155 /* For an LHS that is an SSA_NAME and for strlen() argument SRC, set
1156 LHS range info to [0, N] if SRC refers to a character array A[N]
1157 with unknown length bounded by N. */
1158
1159 static void
1160 maybe_set_strlen_range (tree lhs, tree src)
1161 {
1162 if (TREE_CODE (lhs) != SSA_NAME)
1163 return;
1164
1165 if (TREE_CODE (src) == SSA_NAME)
1166 {
1167 gimple *def = SSA_NAME_DEF_STMT (src);
1168 if (is_gimple_assign (def)
1169 && gimple_assign_rhs_code (def) == ADDR_EXPR)
1170 src = gimple_assign_rhs1 (def);
1171 }
1172
1173 if (TREE_CODE (src) != ADDR_EXPR)
1174 return;
1175
1176 /* The last array member of a struct can be bigger than its size
1177 suggests if it's treated as a poor-man's flexible array member. */
1178 src = TREE_OPERAND (src, 0);
1179 if (TREE_CODE (TREE_TYPE (src)) != ARRAY_TYPE
1180 || array_at_struct_end_p (src))
1181 return;
1182
1183 tree type = TREE_TYPE (src);
1184 if (tree dom = TYPE_DOMAIN (type))
1185 if (tree maxval = TYPE_MAX_VALUE (dom))
1186 {
1187 wide_int max = wi::to_wide (maxval);
1188 wide_int min = wi::zero (max.get_precision ());
1189 set_range_info (lhs, VR_RANGE, min, max);
1190 }
1191 }
1192
1193 /* Handle a strlen call. If strlen of the argument is known, replace
1194 the strlen call with the known value, otherwise remember that strlen
1195 of the argument is stored in the lhs SSA_NAME. */
1196
1197 static void
1198 handle_builtin_strlen (gimple_stmt_iterator *gsi)
1199 {
1200 int idx;
1201 tree src;
1202 gimple *stmt = gsi_stmt (*gsi);
1203 tree lhs = gimple_call_lhs (stmt);
1204
1205 if (lhs == NULL_TREE)
1206 return;
1207
1208 src = gimple_call_arg (stmt, 0);
1209 idx = get_stridx (src);
1210 if (idx)
1211 {
1212 strinfo *si = NULL;
1213 tree rhs;
1214
1215 if (idx < 0)
1216 rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
1217 else
1218 {
1219 rhs = NULL_TREE;
1220 si = get_strinfo (idx);
1221 if (si != NULL)
1222 rhs = get_string_length (si);
1223 }
1224 if (rhs != NULL_TREE)
1225 {
1226 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1227 {
1228 fprintf (dump_file, "Optimizing: ");
1229 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1230 }
1231 rhs = unshare_expr (rhs);
1232 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
1233 rhs = fold_convert_loc (gimple_location (stmt),
1234 TREE_TYPE (lhs), rhs);
1235 if (!update_call_from_tree (gsi, rhs))
1236 gimplify_and_update_call_from_tree (gsi, rhs);
1237 stmt = gsi_stmt (*gsi);
1238 update_stmt (stmt);
1239 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1240 {
1241 fprintf (dump_file, "into: ");
1242 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1243 }
1244 if (si != NULL
1245 && TREE_CODE (si->nonzero_chars) != SSA_NAME
1246 && TREE_CODE (si->nonzero_chars) != INTEGER_CST
1247 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1248 {
1249 si = unshare_strinfo (si);
1250 si->nonzero_chars = lhs;
1251 gcc_assert (si->full_string_p);
1252 }
1253
1254 if (strlen_to_stridx)
1255 {
1256 location_t loc = gimple_location (stmt);
1257 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1258 }
1259 return;
1260 }
1261 }
1262 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1263 return;
1264 if (idx == 0)
1265 idx = new_stridx (src);
1266 else
1267 {
1268 strinfo *si = get_strinfo (idx);
1269 if (si != NULL)
1270 {
1271 if (!si->full_string_p && !si->stmt)
1272 {
1273 /* Until now we only had a lower bound on the string length.
1274 Install LHS as the actual length. */
1275 si = unshare_strinfo (si);
1276 tree old = si->nonzero_chars;
1277 si->nonzero_chars = lhs;
1278 si->full_string_p = true;
1279 if (TREE_CODE (old) == INTEGER_CST)
1280 {
1281 location_t loc = gimple_location (stmt);
1282 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
1283 tree adj = fold_build2_loc (loc, MINUS_EXPR,
1284 TREE_TYPE (lhs), lhs, old);
1285 adjust_related_strinfos (loc, si, adj);
1286 }
1287 else
1288 {
1289 si->first = 0;
1290 si->prev = 0;
1291 si->next = 0;
1292 }
1293 }
1294 return;
1295 }
1296 }
1297 if (idx)
1298 {
1299 strinfo *si = new_strinfo (src, idx, lhs, true);
1300 set_strinfo (idx, si);
1301 find_equal_ptrs (src, idx);
1302
1303 /* For SRC that is an array of N elements, set LHS's range
1304 to [0, N]. */
1305 maybe_set_strlen_range (lhs, src);
1306
1307 if (strlen_to_stridx)
1308 {
1309 location_t loc = gimple_location (stmt);
1310 strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
1311 }
1312 }
1313 }
1314
1315 /* Handle a strchr call. If strlen of the first argument is known, replace
1316 the strchr (x, 0) call with the endptr or x + strlen, otherwise remember
1317 that lhs of the call is endptr and strlen of the argument is endptr - x. */
1318
1319 static void
1320 handle_builtin_strchr (gimple_stmt_iterator *gsi)
1321 {
1322 int idx;
1323 tree src;
1324 gimple *stmt = gsi_stmt (*gsi);
1325 tree lhs = gimple_call_lhs (stmt);
1326 bool with_bounds = gimple_call_with_bounds_p (stmt);
1327
1328 if (lhs == NULL_TREE)
1329 return;
1330
1331 if (!integer_zerop (gimple_call_arg (stmt, with_bounds ? 2 : 1)))
1332 return;
1333
1334 src = gimple_call_arg (stmt, 0);
1335 idx = get_stridx (src);
1336 if (idx)
1337 {
1338 strinfo *si = NULL;
1339 tree rhs;
1340
1341 if (idx < 0)
1342 rhs = build_int_cst (size_type_node, ~idx);
1343 else
1344 {
1345 rhs = NULL_TREE;
1346 si = get_strinfo (idx);
1347 if (si != NULL)
1348 rhs = get_string_length (si);
1349 }
1350 if (rhs != NULL_TREE)
1351 {
1352 location_t loc = gimple_location (stmt);
1353
1354 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1355 {
1356 fprintf (dump_file, "Optimizing: ");
1357 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1358 }
1359 if (si != NULL && si->endptr != NULL_TREE)
1360 {
1361 rhs = unshare_expr (si->endptr);
1362 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1363 TREE_TYPE (rhs)))
1364 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1365 }
1366 else
1367 {
1368 rhs = fold_convert_loc (loc, sizetype, unshare_expr (rhs));
1369 rhs = fold_build2_loc (loc, POINTER_PLUS_EXPR,
1370 TREE_TYPE (src), src, rhs);
1371 if (!useless_type_conversion_p (TREE_TYPE (lhs),
1372 TREE_TYPE (rhs)))
1373 rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
1374 }
1375 if (!update_call_from_tree (gsi, rhs))
1376 gimplify_and_update_call_from_tree (gsi, rhs);
1377 stmt = gsi_stmt (*gsi);
1378 update_stmt (stmt);
1379 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1380 {
1381 fprintf (dump_file, "into: ");
1382 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1383 }
1384 if (si != NULL
1385 && si->endptr == NULL_TREE
1386 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1387 {
1388 si = unshare_strinfo (si);
1389 si->endptr = lhs;
1390 }
1391 zero_length_string (lhs, si);
1392 return;
1393 }
1394 }
1395 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
1396 return;
1397 if (TREE_CODE (src) != SSA_NAME || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (src))
1398 {
1399 if (idx == 0)
1400 idx = new_stridx (src);
1401 else if (get_strinfo (idx) != NULL)
1402 {
1403 zero_length_string (lhs, NULL);
1404 return;
1405 }
1406 if (idx)
1407 {
1408 location_t loc = gimple_location (stmt);
1409 tree lhsu = fold_convert_loc (loc, size_type_node, lhs);
1410 tree srcu = fold_convert_loc (loc, size_type_node, src);
1411 tree length = fold_build2_loc (loc, MINUS_EXPR,
1412 size_type_node, lhsu, srcu);
1413 strinfo *si = new_strinfo (src, idx, length, true);
1414 si->endptr = lhs;
1415 set_strinfo (idx, si);
1416 find_equal_ptrs (src, idx);
1417 zero_length_string (lhs, si);
1418 }
1419 }
1420 else
1421 zero_length_string (lhs, NULL);
1422 }
1423
1424 /* Handle a strcpy-like ({st{r,p}cpy,__st{r,p}cpy_chk}) call.
1425 If strlen of the second argument is known, strlen of the first argument
1426 is the same after this call. Furthermore, attempt to convert it to
1427 memcpy. */
1428
1429 static void
1430 handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
1431 {
1432 int idx, didx;
1433 tree src, dst, srclen, len, lhs, type, fn, oldlen;
1434 bool success;
1435 gimple *stmt = gsi_stmt (*gsi);
1436 strinfo *si, *dsi, *olddsi, *zsi;
1437 location_t loc;
1438 bool with_bounds = gimple_call_with_bounds_p (stmt);
1439
1440 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
1441 dst = gimple_call_arg (stmt, 0);
1442 lhs = gimple_call_lhs (stmt);
1443 idx = get_stridx (src);
1444 si = NULL;
1445 if (idx > 0)
1446 si = get_strinfo (idx);
1447
1448 didx = get_stridx (dst);
1449 olddsi = NULL;
1450 oldlen = NULL_TREE;
1451 if (didx > 0)
1452 olddsi = get_strinfo (didx);
1453 else if (didx < 0)
1454 return;
1455
1456 if (olddsi != NULL)
1457 adjust_last_stmt (olddsi, stmt, false);
1458
1459 srclen = NULL_TREE;
1460 if (si != NULL)
1461 srclen = get_string_length (si);
1462 else if (idx < 0)
1463 srclen = build_int_cst (size_type_node, ~idx);
1464
1465 loc = gimple_location (stmt);
1466 if (srclen == NULL_TREE)
1467 switch (bcode)
1468 {
1469 case BUILT_IN_STRCPY:
1470 case BUILT_IN_STRCPY_CHK:
1471 case BUILT_IN_STRCPY_CHKP:
1472 case BUILT_IN_STRCPY_CHK_CHKP:
1473 if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
1474 return;
1475 break;
1476 case BUILT_IN_STPCPY:
1477 case BUILT_IN_STPCPY_CHK:
1478 case BUILT_IN_STPCPY_CHKP:
1479 case BUILT_IN_STPCPY_CHK_CHKP:
1480 if (lhs == NULL_TREE)
1481 return;
1482 else
1483 {
1484 tree lhsuint = fold_convert_loc (loc, size_type_node, lhs);
1485 srclen = fold_convert_loc (loc, size_type_node, dst);
1486 srclen = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
1487 lhsuint, srclen);
1488 }
1489 break;
1490 default:
1491 gcc_unreachable ();
1492 }
1493
1494 if (didx == 0)
1495 {
1496 didx = new_stridx (dst);
1497 if (didx == 0)
1498 return;
1499 }
1500 if (olddsi != NULL)
1501 {
1502 oldlen = olddsi->nonzero_chars;
1503 dsi = unshare_strinfo (olddsi);
1504 dsi->nonzero_chars = srclen;
1505 dsi->full_string_p = (srclen != NULL_TREE);
1506 /* Break the chain, so adjust_related_strinfo on later pointers in
1507 the chain won't adjust this one anymore. */
1508 dsi->next = 0;
1509 dsi->stmt = NULL;
1510 dsi->endptr = NULL_TREE;
1511 }
1512 else
1513 {
1514 dsi = new_strinfo (dst, didx, srclen, srclen != NULL_TREE);
1515 set_strinfo (didx, dsi);
1516 find_equal_ptrs (dst, didx);
1517 }
1518 dsi->writable = true;
1519 dsi->dont_invalidate = true;
1520
1521 if (dsi->nonzero_chars == NULL_TREE)
1522 {
1523 strinfo *chainsi;
1524
1525 /* If string length of src is unknown, use delayed length
1526 computation. If string lenth of dst will be needed, it
1527 can be computed by transforming this strcpy call into
1528 stpcpy and subtracting dst from the return value. */
1529
1530 /* Look for earlier strings whose length could be determined if
1531 this strcpy is turned into an stpcpy. */
1532
1533 if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
1534 {
1535 for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
1536 {
1537 /* When setting a stmt for delayed length computation
1538 prevent all strinfos through dsi from being
1539 invalidated. */
1540 chainsi = unshare_strinfo (chainsi);
1541 chainsi->stmt = stmt;
1542 chainsi->nonzero_chars = NULL_TREE;
1543 chainsi->full_string_p = false;
1544 chainsi->endptr = NULL_TREE;
1545 chainsi->dont_invalidate = true;
1546 }
1547 }
1548 dsi->stmt = stmt;
1549
1550 /* Try to detect overlap before returning. This catches cases
1551 like strcpy (d, d + n) where n is non-constant whose range
1552 is such that (n <= strlen (d) holds).
1553
1554 OLDDSI->NONZERO_chars may have been reset by this point with
1555 oldlen holding it original value. */
1556 if (olddsi && oldlen)
1557 {
1558 /* Add 1 for the terminating NUL. */
1559 tree type = TREE_TYPE (oldlen);
1560 oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
1561 build_int_cst (type, 1));
1562 check_bounds_or_overlap (as_a <gcall *>(stmt), olddsi->ptr, src,
1563 oldlen, NULL_TREE);
1564 }
1565
1566 return;
1567 }
1568
1569 if (olddsi != NULL)
1570 {
1571 tree adj = NULL_TREE;
1572 if (oldlen == NULL_TREE)
1573 ;
1574 else if (integer_zerop (oldlen))
1575 adj = srclen;
1576 else if (TREE_CODE (oldlen) == INTEGER_CST
1577 || TREE_CODE (srclen) == INTEGER_CST)
1578 adj = fold_build2_loc (loc, MINUS_EXPR,
1579 TREE_TYPE (srclen), srclen,
1580 fold_convert_loc (loc, TREE_TYPE (srclen),
1581 oldlen));
1582 if (adj != NULL_TREE)
1583 adjust_related_strinfos (loc, dsi, adj);
1584 else
1585 dsi->prev = 0;
1586 }
1587 /* strcpy src may not overlap dst, so src doesn't need to be
1588 invalidated either. */
1589 if (si != NULL)
1590 si->dont_invalidate = true;
1591
1592 fn = NULL_TREE;
1593 zsi = NULL;
1594 switch (bcode)
1595 {
1596 case BUILT_IN_STRCPY:
1597 case BUILT_IN_STRCPY_CHKP:
1598 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
1599 if (lhs)
1600 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1601 break;
1602 case BUILT_IN_STRCPY_CHK:
1603 case BUILT_IN_STRCPY_CHK_CHKP:
1604 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
1605 if (lhs)
1606 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
1607 break;
1608 case BUILT_IN_STPCPY:
1609 case BUILT_IN_STPCPY_CHKP:
1610 /* This would need adjustment of the lhs (subtract one),
1611 or detection that the trailing '\0' doesn't need to be
1612 written, if it will be immediately overwritten.
1613 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
1614 if (lhs)
1615 {
1616 dsi->endptr = lhs;
1617 zsi = zero_length_string (lhs, dsi);
1618 }
1619 break;
1620 case BUILT_IN_STPCPY_CHK:
1621 case BUILT_IN_STPCPY_CHK_CHKP:
1622 /* This would need adjustment of the lhs (subtract one),
1623 or detection that the trailing '\0' doesn't need to be
1624 written, if it will be immediately overwritten.
1625 fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
1626 if (lhs)
1627 {
1628 dsi->endptr = lhs;
1629 zsi = zero_length_string (lhs, dsi);
1630 }
1631 break;
1632 default:
1633 gcc_unreachable ();
1634 }
1635 if (zsi != NULL)
1636 zsi->dont_invalidate = true;
1637
1638 if (fn)
1639 {
1640 tree args = TYPE_ARG_TYPES (TREE_TYPE (fn));
1641 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
1642 }
1643 else
1644 type = size_type_node;
1645
1646 len = fold_convert_loc (loc, type, unshare_expr (srclen));
1647 len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
1648
1649 /* Set the no-warning bit on the transformed statement? */
1650 bool set_no_warning = false;
1651
1652 if (const strinfo *chksi = olddsi ? olddsi : dsi)
1653 if (si
1654 && !check_bounds_or_overlap (as_a <gcall *>(stmt), chksi->ptr, si->ptr,
1655 NULL_TREE, len))
1656 {
1657 gimple_set_no_warning (stmt, true);
1658 set_no_warning = true;
1659 }
1660
1661 if (fn == NULL_TREE)
1662 return;
1663
1664 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
1665 GSI_SAME_STMT);
1666 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1667 {
1668 fprintf (dump_file, "Optimizing: ");
1669 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1670 }
1671 if (with_bounds)
1672 {
1673 fn = chkp_maybe_create_clone (fn)->decl;
1674 if (gimple_call_num_args (stmt) == 4)
1675 success = update_gimple_call (gsi, fn, 5, dst,
1676 gimple_call_arg (stmt, 1),
1677 src,
1678 gimple_call_arg (stmt, 3),
1679 len);
1680 else
1681 success = update_gimple_call (gsi, fn, 6, dst,
1682 gimple_call_arg (stmt, 1),
1683 src,
1684 gimple_call_arg (stmt, 3),
1685 len,
1686 gimple_call_arg (stmt, 4));
1687 }
1688 else
1689 if (gimple_call_num_args (stmt) == 2)
1690 success = update_gimple_call (gsi, fn, 3, dst, src, len);
1691 else
1692 success = update_gimple_call (gsi, fn, 4, dst, src, len,
1693 gimple_call_arg (stmt, 2));
1694 if (success)
1695 {
1696 stmt = gsi_stmt (*gsi);
1697 gimple_call_set_with_bounds (stmt, with_bounds);
1698 update_stmt (stmt);
1699 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1700 {
1701 fprintf (dump_file, "into: ");
1702 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1703 }
1704 /* Allow adjust_last_stmt to decrease this memcpy's size. */
1705 laststmt.stmt = stmt;
1706 laststmt.len = srclen;
1707 laststmt.stridx = dsi->idx;
1708 }
1709 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
1710 fprintf (dump_file, "not possible.\n");
1711
1712 if (set_no_warning)
1713 gimple_set_no_warning (stmt, true);
1714 }
1715
1716 /* Check the size argument to the built-in forms of stpncpy and strncpy
1717 for out-of-bounds offsets or overlapping access, and to see if the
1718 size argument is derived from a call to strlen() on the source argument,
1719 and if so, issue an appropriate warning. */
1720
1721 static void
1722 handle_builtin_strncat (built_in_function bcode, gimple_stmt_iterator *gsi)
1723 {
1724 /* Same as stxncpy(). */
1725 handle_builtin_stxncpy (bcode, gsi);
1726 }
1727
1728 /* Return true if LEN depends on a call to strlen(SRC) in an interesting
1729 way. LEN can either be an integer expression, or a pointer (to char).
1730 When it is the latter (such as in recursive calls to self) is is
1731 assumed to be the argument in some call to strlen() whose relationship
1732 to SRC is being ascertained. */
1733
1734 static bool
1735 is_strlen_related_p (tree src, tree len)
1736 {
1737 if (TREE_CODE (TREE_TYPE (len)) == POINTER_TYPE
1738 && operand_equal_p (src, len, 0))
1739 return true;
1740
1741 if (TREE_CODE (len) != SSA_NAME)
1742 return false;
1743
1744 gimple *def_stmt = SSA_NAME_DEF_STMT (len);
1745 if (!def_stmt)
1746 return false;
1747
1748 if (is_gimple_call (def_stmt))
1749 {
1750 tree func = gimple_call_fndecl (def_stmt);
1751 if (!valid_builtin_call (def_stmt)
1752 || DECL_FUNCTION_CODE (func) != BUILT_IN_STRLEN)
1753 return false;
1754
1755 tree arg = gimple_call_arg (def_stmt, 0);
1756 return is_strlen_related_p (src, arg);
1757 }
1758
1759 if (!is_gimple_assign (def_stmt))
1760 return false;
1761
1762 tree_code code = gimple_assign_rhs_code (def_stmt);
1763 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1764 tree rhstype = TREE_TYPE (rhs1);
1765
1766 if ((TREE_CODE (rhstype) == POINTER_TYPE && code == POINTER_PLUS_EXPR)
1767 || (INTEGRAL_TYPE_P (rhstype)
1768 && (code == BIT_AND_EXPR
1769 || code == NOP_EXPR)))
1770 {
1771 /* Pointer plus (an integer) and integer cast or truncation are
1772 considered among the (potentially) related expressions to strlen.
1773 Others are not. */
1774 return is_strlen_related_p (src, rhs1);
1775 }
1776
1777 return false;
1778 }
1779
1780 /* A helper of handle_builtin_stxncpy. Check to see if the specified
1781 bound is a) equal to the size of the destination DST and if so, b)
1782 if it's immediately followed by DST[CNT - 1] = '\0'. If a) holds
1783 and b) does not, warn. Otherwise, do nothing. Return true if
1784 diagnostic has been issued.
1785
1786 The purpose is to diagnose calls to strncpy and stpncpy that do
1787 not nul-terminate the copy while allowing for the idiom where
1788 such a call is immediately followed by setting the last element
1789 to nul, as in:
1790 char a[32];
1791 strncpy (a, s, sizeof a);
1792 a[sizeof a - 1] = '\0';
1793 */
1794
1795 static bool
1796 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
1797 {
1798 gimple *stmt = gsi_stmt (gsi);
1799
1800 wide_int cntrange[2];
1801
1802 if (TREE_CODE (cnt) == INTEGER_CST)
1803 cntrange[0] = cntrange[1] = wi::to_wide (cnt);
1804 else if (TREE_CODE (cnt) == SSA_NAME)
1805 {
1806 enum value_range_type rng = get_range_info (cnt, cntrange, cntrange + 1);
1807 if (rng == VR_RANGE)
1808 ;
1809 else if (rng == VR_ANTI_RANGE)
1810 {
1811 wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
1812
1813 if (wi::ltu_p (cntrange[1], maxobjsize))
1814 {
1815 cntrange[0] = cntrange[1] + 1;
1816 cntrange[1] = maxobjsize;
1817 }
1818 else
1819 {
1820 cntrange[1] = cntrange[0] - 1;
1821 cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
1822 }
1823 }
1824 else
1825 return false;
1826 }
1827 else
1828 return false;
1829
1830 /* Negative value is the constant string length. If it's less than
1831 the lower bound there is no truncation. */
1832 int sidx = get_stridx (src);
1833 if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
1834 return false;
1835
1836 tree dst = gimple_call_arg (stmt, 0);
1837 tree dstdecl = dst;
1838 if (TREE_CODE (dstdecl) == ADDR_EXPR)
1839 dstdecl = TREE_OPERAND (dstdecl, 0);
1840
1841 /* If the destination refers to a an array/pointer declared nonstring
1842 return early. */
1843 tree ref = NULL_TREE;
1844 if (get_attr_nonstring_decl (dstdecl, &ref))
1845 return false;
1846
1847 /* Look for dst[i] = '\0'; after the stxncpy() call and if found
1848 avoid the truncation warning. */
1849 gsi_next (&gsi);
1850 gimple *next_stmt = gsi_stmt (gsi);
1851
1852 if (!gsi_end_p (gsi) && is_gimple_assign (next_stmt))
1853 {
1854 tree lhs = gimple_assign_lhs (next_stmt);
1855 tree_code code = TREE_CODE (lhs);
1856 if (code == ARRAY_REF || code == MEM_REF)
1857 lhs = TREE_OPERAND (lhs, 0);
1858
1859 tree func = gimple_call_fndecl (stmt);
1860 if (DECL_FUNCTION_CODE (func) == BUILT_IN_STPNCPY)
1861 {
1862 tree ret = gimple_call_lhs (stmt);
1863 if (ret && operand_equal_p (ret, lhs, 0))
1864 return false;
1865 }
1866
1867 /* Determine the base address and offset of the reference,
1868 ignoring the innermost array index. */
1869 if (TREE_CODE (ref) == ARRAY_REF)
1870 ref = TREE_OPERAND (ref, 0);
1871
1872 HOST_WIDE_INT dstoff;
1873 tree dstbase = get_addr_base_and_unit_offset (ref, &dstoff);
1874
1875 HOST_WIDE_INT lhsoff;
1876 tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
1877 if (lhsbase
1878 && dstoff == lhsoff
1879 && operand_equal_p (dstbase, lhsbase, 0))
1880 return false;
1881 }
1882
1883 int prec = TYPE_PRECISION (TREE_TYPE (cnt));
1884 wide_int lenrange[2];
1885 if (strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL)
1886 {
1887 lenrange[0] = (sisrc->nonzero_chars
1888 && TREE_CODE (sisrc->nonzero_chars) == INTEGER_CST
1889 ? wi::to_wide (sisrc->nonzero_chars)
1890 : wi::zero (prec));
1891 lenrange[1] = lenrange[0];
1892 }
1893 else if (sidx < 0)
1894 lenrange[0] = lenrange[1] = wi::shwi (~sidx, prec);
1895 else
1896 {
1897 tree range[2];
1898 get_range_strlen (src, range);
1899 if (range[0])
1900 {
1901 lenrange[0] = wi::to_wide (range[0], prec);
1902 lenrange[1] = wi::to_wide (range[1], prec);
1903 }
1904 else
1905 {
1906 lenrange[0] = wi::shwi (0, prec);
1907 lenrange[1] = wi::shwi (-1, prec);
1908 }
1909 }
1910
1911 location_t callloc = gimple_location (stmt);
1912 tree func = gimple_call_fndecl (stmt);
1913
1914 if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
1915 {
1916 /* If the longest source string is shorter than the lower bound
1917 of the specified count the copy is definitely nul-terminated. */
1918 if (wi::ltu_p (lenrange[1], cntrange[0]))
1919 return false;
1920
1921 if (wi::neg_p (lenrange[1]))
1922 {
1923 /* The length of one of the strings is unknown but at least
1924 one has non-zero length and that length is stored in
1925 LENRANGE[1]. Swap the bounds to force a "may be truncated"
1926 warning below. */
1927 lenrange[1] = lenrange[0];
1928 lenrange[0] = wi::shwi (0, prec);
1929 }
1930
1931 if (wi::geu_p (lenrange[0], cntrange[1]))
1932 {
1933 /* The shortest string is longer than the upper bound of
1934 the count so the truncation is certain. */
1935 if (cntrange[0] == cntrange[1])
1936 return warning_at (callloc, OPT_Wstringop_truncation,
1937 integer_onep (cnt)
1938 ? G_("%qD output truncated copying %E byte "
1939 "from a string of length %wu")
1940 : G_("%qD output truncated copying %E bytes "
1941 "from a string of length %wu"),
1942 func, cnt, lenrange[0].to_uhwi ());
1943
1944 return warning_at (callloc, OPT_Wstringop_truncation,
1945 "%qD output truncated copying between %wu "
1946 "and %wu bytes from a string of length %wu",
1947 func, cntrange[0].to_uhwi (),
1948 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1949 }
1950 else if (wi::geu_p (lenrange[1], cntrange[1]))
1951 {
1952 /* The longest string is longer than the upper bound of
1953 the count so the truncation is possible. */
1954 if (cntrange[0] == cntrange[1])
1955 return warning_at (callloc, OPT_Wstringop_truncation,
1956 integer_onep (cnt)
1957 ? G_("%qD output may be truncated copying %E "
1958 "byte from a string of length %wu")
1959 : G_("%qD output may be truncated copying %E "
1960 "bytes from a string of length %wu"),
1961 func, cnt, lenrange[1].to_uhwi ());
1962
1963 return warning_at (callloc, OPT_Wstringop_truncation,
1964 "%qD output may be truncated copying between %wu "
1965 "and %wu bytes from a string of length %wu",
1966 func, cntrange[0].to_uhwi (),
1967 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
1968 }
1969
1970 if (cntrange[0] != cntrange[1]
1971 && wi::leu_p (cntrange[0], lenrange[0])
1972 && wi::leu_p (cntrange[1], lenrange[0] + 1))
1973 {
1974 /* If the source (including the terminating nul) is longer than
1975 the lower bound of the specified count but shorter than the
1976 upper bound the copy may (but need not) be truncated. */
1977 return warning_at (callloc, OPT_Wstringop_truncation,
1978 "%qD output may be truncated copying between %wu "
1979 "and %wu bytes from a string of length %wu",
1980 func, cntrange[0].to_uhwi (),
1981 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
1982 }
1983 }
1984
1985 if (tree dstsize = compute_objsize (dst, 1))
1986 {
1987 /* The source length is uknown. Try to determine the destination
1988 size and see if it matches the specified bound. If not, bail.
1989 Otherwise go on to see if it should be diagnosed for possible
1990 truncation. */
1991 if (!dstsize)
1992 return false;
1993
1994 if (wi::to_wide (dstsize) != cntrange[1])
1995 return false;
1996
1997 if (cntrange[0] == cntrange[1])
1998 return warning_at (callloc, OPT_Wstringop_truncation,
1999 "%qD specified bound %E equals destination size",
2000 func, cnt);
2001 }
2002
2003 return false;
2004 }
2005
2006 /* Check the arguments to the built-in forms of stpncpy and strncpy for
2007 out-of-bounds offsets or overlapping access, and to see if the size
2008 is derived from calling strlen() on the source argument, and if so,
2009 issue the appropriate warning. */
2010
2011 static void
2012 handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
2013 {
2014 if (!strlen_to_stridx)
2015 return;
2016
2017 gimple *stmt = gsi_stmt (*gsi);
2018
2019 bool with_bounds = gimple_call_with_bounds_p (stmt);
2020
2021 tree dst = gimple_call_arg (stmt, with_bounds ? 1 : 0);
2022 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2023 tree len = gimple_call_arg (stmt, with_bounds ? 3 : 2);
2024 tree dstsize = NULL_TREE, srcsize = NULL_TREE;
2025
2026 int didx = get_stridx (dst);
2027 if (strinfo *sidst = didx > 0 ? get_strinfo (didx) : NULL)
2028 {
2029 /* Compute the size of the destination string including the NUL. */
2030 if (sidst->nonzero_chars)
2031 {
2032 tree type = TREE_TYPE (sidst->nonzero_chars);
2033 dstsize = fold_build2 (PLUS_EXPR, type, sidst->nonzero_chars,
2034 build_int_cst (type, 1));
2035 }
2036 dst = sidst->ptr;
2037 }
2038
2039 int sidx = get_stridx (src);
2040 strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
2041 if (sisrc)
2042 {
2043 /* strncat() and strncpy() can modify the source string by writing
2044 over the terminating nul so SISRC->DONT_INVALIDATE must be left
2045 clear. */
2046
2047 /* Compute the size of the source string including the NUL. */
2048 if (sisrc->nonzero_chars)
2049 {
2050 tree type = TREE_TYPE (sisrc->nonzero_chars);
2051 srcsize = fold_build2 (PLUS_EXPR, type, sisrc->nonzero_chars,
2052 build_int_cst (type, 1));
2053 }
2054
2055 src = sisrc->ptr;
2056 }
2057 else
2058 srcsize = NULL_TREE;
2059
2060 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, src,
2061 dstsize, srcsize))
2062 {
2063 gimple_set_no_warning (stmt, true);
2064 return;
2065 }
2066
2067 /* If the length argument was computed from strlen(S) for some string
2068 S retrieve the strinfo index for the string (PSS->FIRST) alonng with
2069 the location of the strlen() call (PSS->SECOND). */
2070 stridx_strlenloc *pss = strlen_to_stridx->get (len);
2071 if (!pss || pss->first <= 0)
2072 {
2073 if (maybe_diag_stxncpy_trunc (*gsi, src, len))
2074 gimple_set_no_warning (stmt, true);
2075
2076 return;
2077 }
2078
2079 /* Retrieve the strinfo data for the string S that LEN was computed
2080 from as some function F of strlen (S) (i.e., LEN need not be equal
2081 to strlen(S)). */
2082 strinfo *silen = get_strinfo (pss->first);
2083
2084 location_t callloc = gimple_location (stmt);
2085
2086 tree func = gimple_call_fndecl (stmt);
2087
2088 bool warned = false;
2089
2090 /* When -Wstringop-truncation is set, try to determine truncation
2091 before diagnosing possible overflow. Truncation is implied by
2092 the LEN argument being equal to strlen(SRC), regardless of
2093 whether its value is known. Otherwise, issue the more generic
2094 -Wstringop-overflow which triggers for LEN arguments that in
2095 any meaningful way depend on strlen(SRC). */
2096 if (sisrc == silen
2097 && is_strlen_related_p (src, len)
2098 && warning_at (callloc, OPT_Wstringop_truncation,
2099 "%qD output truncated before terminating nul "
2100 "copying as many bytes from a string as its length",
2101 func))
2102 warned = true;
2103 else if (silen && is_strlen_related_p (src, silen->ptr))
2104 warned = warning_at (callloc, OPT_Wstringop_overflow_,
2105 "%qD specified bound depends on the length "
2106 "of the source argument", func);
2107 if (warned)
2108 {
2109 location_t strlenloc = pss->second;
2110 if (strlenloc != UNKNOWN_LOCATION && strlenloc != callloc)
2111 inform (strlenloc, "length computed here");
2112 }
2113 }
2114
2115 /* Handle a memcpy-like ({mem{,p}cpy,__mem{,p}cpy_chk}) call.
2116 If strlen of the second argument is known and length of the third argument
2117 is that plus one, strlen of the first argument is the same after this
2118 call. */
2119
2120 static void
2121 handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2122 {
2123 int idx, didx;
2124 tree src, dst, len, lhs, oldlen, newlen;
2125 gimple *stmt = gsi_stmt (*gsi);
2126 strinfo *si, *dsi, *olddsi;
2127 bool with_bounds = gimple_call_with_bounds_p (stmt);
2128
2129 len = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2130 src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2131 dst = gimple_call_arg (stmt, 0);
2132 idx = get_stridx (src);
2133 if (idx == 0)
2134 return;
2135
2136 didx = get_stridx (dst);
2137 olddsi = NULL;
2138 if (didx > 0)
2139 olddsi = get_strinfo (didx);
2140 else if (didx < 0)
2141 return;
2142
2143 if (olddsi != NULL
2144 && tree_fits_uhwi_p (len)
2145 && !integer_zerop (len))
2146 adjust_last_stmt (olddsi, stmt, false);
2147
2148 bool full_string_p;
2149 if (idx > 0)
2150 {
2151 gimple *def_stmt;
2152
2153 /* Handle memcpy (x, y, l) where l's relationship with strlen (y)
2154 is known. */
2155 si = get_strinfo (idx);
2156 if (si == NULL || si->nonzero_chars == NULL_TREE)
2157 return;
2158 if (TREE_CODE (len) == INTEGER_CST
2159 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
2160 {
2161 if (tree_int_cst_le (len, si->nonzero_chars))
2162 {
2163 /* Copying LEN nonzero characters, where LEN is constant. */
2164 newlen = len;
2165 full_string_p = false;
2166 }
2167 else
2168 {
2169 /* Copying the whole of the analyzed part of SI. */
2170 newlen = si->nonzero_chars;
2171 full_string_p = si->full_string_p;
2172 }
2173 }
2174 else
2175 {
2176 if (!si->full_string_p)
2177 return;
2178 if (TREE_CODE (len) != SSA_NAME)
2179 return;
2180 def_stmt = SSA_NAME_DEF_STMT (len);
2181 if (!is_gimple_assign (def_stmt)
2182 || gimple_assign_rhs_code (def_stmt) != PLUS_EXPR
2183 || gimple_assign_rhs1 (def_stmt) != si->nonzero_chars
2184 || !integer_onep (gimple_assign_rhs2 (def_stmt)))
2185 return;
2186 /* Copying variable-length string SI (and no more). */
2187 newlen = si->nonzero_chars;
2188 full_string_p = true;
2189 }
2190 }
2191 else
2192 {
2193 si = NULL;
2194 /* Handle memcpy (x, "abcd", 5) or
2195 memcpy (x, "abc\0uvw", 7). */
2196 if (!tree_fits_uhwi_p (len))
2197 return;
2198
2199 unsigned HOST_WIDE_INT clen = tree_to_uhwi (len);
2200 unsigned HOST_WIDE_INT nonzero_chars = ~idx;
2201 newlen = build_int_cst (size_type_node, MIN (nonzero_chars, clen));
2202 full_string_p = clen > nonzero_chars;
2203 }
2204
2205 if (olddsi != NULL && TREE_CODE (len) == SSA_NAME)
2206 adjust_last_stmt (olddsi, stmt, false);
2207
2208 if (didx == 0)
2209 {
2210 didx = new_stridx (dst);
2211 if (didx == 0)
2212 return;
2213 }
2214 oldlen = NULL_TREE;
2215 if (olddsi != NULL)
2216 {
2217 dsi = unshare_strinfo (olddsi);
2218 oldlen = olddsi->nonzero_chars;
2219 dsi->nonzero_chars = newlen;
2220 dsi->full_string_p = full_string_p;
2221 /* Break the chain, so adjust_related_strinfo on later pointers in
2222 the chain won't adjust this one anymore. */
2223 dsi->next = 0;
2224 dsi->stmt = NULL;
2225 dsi->endptr = NULL_TREE;
2226 }
2227 else
2228 {
2229 dsi = new_strinfo (dst, didx, newlen, full_string_p);
2230 set_strinfo (didx, dsi);
2231 find_equal_ptrs (dst, didx);
2232 }
2233 dsi->writable = true;
2234 dsi->dont_invalidate = true;
2235 if (olddsi != NULL)
2236 {
2237 tree adj = NULL_TREE;
2238 location_t loc = gimple_location (stmt);
2239 if (oldlen == NULL_TREE)
2240 ;
2241 else if (integer_zerop (oldlen))
2242 adj = newlen;
2243 else if (TREE_CODE (oldlen) == INTEGER_CST
2244 || TREE_CODE (newlen) == INTEGER_CST)
2245 adj = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (newlen), newlen,
2246 fold_convert_loc (loc, TREE_TYPE (newlen),
2247 oldlen));
2248 if (adj != NULL_TREE)
2249 adjust_related_strinfos (loc, dsi, adj);
2250 else
2251 dsi->prev = 0;
2252 }
2253 /* memcpy src may not overlap dst, so src doesn't need to be
2254 invalidated either. */
2255 if (si != NULL)
2256 si->dont_invalidate = true;
2257
2258 if (full_string_p)
2259 {
2260 lhs = gimple_call_lhs (stmt);
2261 switch (bcode)
2262 {
2263 case BUILT_IN_MEMCPY:
2264 case BUILT_IN_MEMCPY_CHK:
2265 case BUILT_IN_MEMCPY_CHKP:
2266 case BUILT_IN_MEMCPY_CHK_CHKP:
2267 /* Allow adjust_last_stmt to decrease this memcpy's size. */
2268 laststmt.stmt = stmt;
2269 laststmt.len = dsi->nonzero_chars;
2270 laststmt.stridx = dsi->idx;
2271 if (lhs)
2272 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx;
2273 break;
2274 case BUILT_IN_MEMPCPY:
2275 case BUILT_IN_MEMPCPY_CHK:
2276 case BUILT_IN_MEMPCPY_CHKP:
2277 case BUILT_IN_MEMPCPY_CHK_CHKP:
2278 break;
2279 default:
2280 gcc_unreachable ();
2281 }
2282 }
2283 }
2284
2285 /* Handle a strcat-like ({strcat,__strcat_chk}) call.
2286 If strlen of the second argument is known, strlen of the first argument
2287 is increased by the length of the second argument. Furthermore, attempt
2288 to convert it to memcpy/strcpy if the length of the first argument
2289 is known. */
2290
2291 static void
2292 handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2293 {
2294 int idx, didx;
2295 tree srclen, args, type, fn, objsz, endptr;
2296 bool success;
2297 gimple *stmt = gsi_stmt (*gsi);
2298 strinfo *si, *dsi;
2299 location_t loc = gimple_location (stmt);
2300 bool with_bounds = gimple_call_with_bounds_p (stmt);
2301
2302 tree src = gimple_call_arg (stmt, with_bounds ? 2 : 1);
2303 tree dst = gimple_call_arg (stmt, 0);
2304
2305 /* Bail if the source is the same as destination. It will be diagnosed
2306 elsewhere. */
2307 if (operand_equal_p (src, dst, 0))
2308 return;
2309
2310 tree lhs = gimple_call_lhs (stmt);
2311
2312 didx = get_stridx (dst);
2313 if (didx < 0)
2314 return;
2315
2316 dsi = NULL;
2317 if (didx > 0)
2318 dsi = get_strinfo (didx);
2319
2320 srclen = NULL_TREE;
2321 si = NULL;
2322 idx = get_stridx (src);
2323 if (idx < 0)
2324 srclen = build_int_cst (size_type_node, ~idx);
2325 else if (idx > 0)
2326 {
2327 si = get_strinfo (idx);
2328 if (si != NULL)
2329 srclen = get_string_length (si);
2330 }
2331
2332 /* Set the no-warning bit on the transformed statement? */
2333 bool set_no_warning = false;
2334
2335 if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
2336 {
2337 {
2338 /* The concatenation always involves copying at least one byte
2339 (the terminating nul), even if the source string is empty.
2340 If the source is unknown assume it's one character long and
2341 used that as both sizes. */
2342 tree slen = srclen;
2343 if (slen)
2344 {
2345 tree type = TREE_TYPE (slen);
2346 slen = fold_build2 (PLUS_EXPR, type, slen, build_int_cst (type, 1));
2347 }
2348
2349 tree sptr = si && si->ptr ? si->ptr : src;
2350
2351 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2352 NULL_TREE, slen))
2353 {
2354 gimple_set_no_warning (stmt, true);
2355 set_no_warning = true;
2356 }
2357 }
2358
2359 /* strcat (p, q) can be transformed into
2360 tmp = p + strlen (p); endptr = stpcpy (tmp, q);
2361 with length endptr - p if we need to compute the length
2362 later on. Don't do this transformation if we don't need
2363 it. */
2364 if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
2365 {
2366 if (didx == 0)
2367 {
2368 didx = new_stridx (dst);
2369 if (didx == 0)
2370 return;
2371 }
2372 if (dsi == NULL)
2373 {
2374 dsi = new_strinfo (dst, didx, NULL_TREE, false);
2375 set_strinfo (didx, dsi);
2376 find_equal_ptrs (dst, didx);
2377 }
2378 else
2379 {
2380 dsi = unshare_strinfo (dsi);
2381 dsi->nonzero_chars = NULL_TREE;
2382 dsi->full_string_p = false;
2383 dsi->next = 0;
2384 dsi->endptr = NULL_TREE;
2385 }
2386 dsi->writable = true;
2387 dsi->stmt = stmt;
2388 dsi->dont_invalidate = true;
2389 }
2390 return;
2391 }
2392
2393 tree dstlen = dsi->nonzero_chars;
2394 endptr = dsi->endptr;
2395
2396 dsi = unshare_strinfo (dsi);
2397 dsi->endptr = NULL_TREE;
2398 dsi->stmt = NULL;
2399 dsi->writable = true;
2400
2401 if (srclen != NULL_TREE)
2402 {
2403 dsi->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
2404 TREE_TYPE (dsi->nonzero_chars),
2405 dsi->nonzero_chars, srclen);
2406 gcc_assert (dsi->full_string_p);
2407 adjust_related_strinfos (loc, dsi, srclen);
2408 dsi->dont_invalidate = true;
2409 }
2410 else
2411 {
2412 dsi->nonzero_chars = NULL;
2413 dsi->full_string_p = false;
2414 if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
2415 dsi->dont_invalidate = true;
2416 }
2417
2418 if (si != NULL)
2419 /* strcat src may not overlap dst, so src doesn't need to be
2420 invalidated either. */
2421 si->dont_invalidate = true;
2422
2423 /* For now. Could remove the lhs from the call and add
2424 lhs = dst; afterwards. */
2425 if (lhs)
2426 return;
2427
2428 fn = NULL_TREE;
2429 objsz = NULL_TREE;
2430 switch (bcode)
2431 {
2432 case BUILT_IN_STRCAT:
2433 case BUILT_IN_STRCAT_CHKP:
2434 if (srclen != NULL_TREE)
2435 fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
2436 else
2437 fn = builtin_decl_implicit (BUILT_IN_STRCPY);
2438 break;
2439 case BUILT_IN_STRCAT_CHK:
2440 case BUILT_IN_STRCAT_CHK_CHKP:
2441 if (srclen != NULL_TREE)
2442 fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
2443 else
2444 fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
2445 objsz = gimple_call_arg (stmt, with_bounds ? 4 : 2);
2446 break;
2447 default:
2448 gcc_unreachable ();
2449 }
2450
2451 if (fn == NULL_TREE)
2452 return;
2453
2454 if (dsi && dstlen)
2455 {
2456 tree type = TREE_TYPE (dstlen);
2457
2458 /* Compute the size of the source sequence, including the nul. */
2459 tree srcsize = srclen ? srclen : size_zero_node;
2460 srcsize = fold_build2 (PLUS_EXPR, type, srcsize, build_int_cst (type, 1));
2461
2462 tree sptr = si && si->ptr ? si->ptr : src;
2463
2464 if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
2465 dstlen, srcsize))
2466 {
2467 gimple_set_no_warning (stmt, true);
2468 set_no_warning = true;
2469 }
2470 }
2471
2472 tree len = NULL_TREE;
2473 if (srclen != NULL_TREE)
2474 {
2475 args = TYPE_ARG_TYPES (TREE_TYPE (fn));
2476 type = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
2477
2478 len = fold_convert_loc (loc, type, unshare_expr (srclen));
2479 len = fold_build2_loc (loc, PLUS_EXPR, type, len,
2480 build_int_cst (type, 1));
2481 len = force_gimple_operand_gsi (gsi, len, true, NULL_TREE, true,
2482 GSI_SAME_STMT);
2483 }
2484 if (endptr)
2485 dst = fold_convert_loc (loc, TREE_TYPE (dst), unshare_expr (endptr));
2486 else
2487 dst = fold_build2_loc (loc, POINTER_PLUS_EXPR,
2488 TREE_TYPE (dst), unshare_expr (dst),
2489 fold_convert_loc (loc, sizetype,
2490 unshare_expr (dstlen)));
2491 dst = force_gimple_operand_gsi (gsi, dst, true, NULL_TREE, true,
2492 GSI_SAME_STMT);
2493 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2494 {
2495 fprintf (dump_file, "Optimizing: ");
2496 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2497 }
2498 if (with_bounds)
2499 {
2500 fn = chkp_maybe_create_clone (fn)->decl;
2501 if (srclen != NULL_TREE)
2502 success = update_gimple_call (gsi, fn, 5 + (objsz != NULL_TREE),
2503 dst,
2504 gimple_call_arg (stmt, 1),
2505 src,
2506 gimple_call_arg (stmt, 3),
2507 len, objsz);
2508 else
2509 success = update_gimple_call (gsi, fn, 4 + (objsz != NULL_TREE),
2510 dst,
2511 gimple_call_arg (stmt, 1),
2512 src,
2513 gimple_call_arg (stmt, 3),
2514 objsz);
2515 }
2516 else
2517 if (srclen != NULL_TREE)
2518 success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE),
2519 dst, src, len, objsz);
2520 else
2521 success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE),
2522 dst, src, objsz);
2523 if (success)
2524 {
2525 stmt = gsi_stmt (*gsi);
2526 gimple_call_set_with_bounds (stmt, with_bounds);
2527 update_stmt (stmt);
2528 if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2529 {
2530 fprintf (dump_file, "into: ");
2531 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2532 }
2533 /* If srclen == NULL, note that current string length can be
2534 computed by transforming this strcpy into stpcpy. */
2535 if (srclen == NULL_TREE && dsi->dont_invalidate)
2536 dsi->stmt = stmt;
2537 adjust_last_stmt (dsi, stmt, true);
2538 if (srclen != NULL_TREE)
2539 {
2540 laststmt.stmt = stmt;
2541 laststmt.len = srclen;
2542 laststmt.stridx = dsi->idx;
2543 }
2544 }
2545 else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
2546 fprintf (dump_file, "not possible.\n");
2547
2548 if (set_no_warning)
2549 gimple_set_no_warning (stmt, true);
2550 }
2551
2552 /* Handle a call to malloc or calloc. */
2553
2554 static void
2555 handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
2556 {
2557 gimple *stmt = gsi_stmt (*gsi);
2558 tree lhs = gimple_call_lhs (stmt);
2559 if (lhs == NULL_TREE)
2560 return;
2561
2562 gcc_assert (get_stridx (lhs) == 0);
2563 int idx = new_stridx (lhs);
2564 tree length = NULL_TREE;
2565 if (bcode == BUILT_IN_CALLOC)
2566 length = build_int_cst (size_type_node, 0);
2567 strinfo *si = new_strinfo (lhs, idx, length, length != NULL_TREE);
2568 if (bcode == BUILT_IN_CALLOC)
2569 si->endptr = lhs;
2570 set_strinfo (idx, si);
2571 si->writable = true;
2572 si->stmt = stmt;
2573 si->dont_invalidate = true;
2574 }
2575
2576 /* Handle a call to memset.
2577 After a call to calloc, memset(,0,) is unnecessary.
2578 memset(malloc(n),0,n) is calloc(n,1). */
2579
2580 static bool
2581 handle_builtin_memset (gimple_stmt_iterator *gsi)
2582 {
2583 gimple *stmt2 = gsi_stmt (*gsi);
2584 if (!integer_zerop (gimple_call_arg (stmt2, 1)))
2585 return true;
2586 tree ptr = gimple_call_arg (stmt2, 0);
2587 int idx1 = get_stridx (ptr);
2588 if (idx1 <= 0)
2589 return true;
2590 strinfo *si1 = get_strinfo (idx1);
2591 if (!si1)
2592 return true;
2593 gimple *stmt1 = si1->stmt;
2594 if (!stmt1 || !is_gimple_call (stmt1))
2595 return true;
2596 tree callee1 = gimple_call_fndecl (stmt1);
2597 if (!valid_builtin_call (stmt1))
2598 return true;
2599 enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
2600 tree size = gimple_call_arg (stmt2, 2);
2601 if (code1 == BUILT_IN_CALLOC)
2602 /* Not touching stmt1 */ ;
2603 else if (code1 == BUILT_IN_MALLOC
2604 && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
2605 {
2606 gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
2607 update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
2608 size, build_one_cst (size_type_node));
2609 si1->nonzero_chars = build_int_cst (size_type_node, 0);
2610 si1->full_string_p = true;
2611 si1->stmt = gsi_stmt (gsi1);
2612 }
2613 else
2614 return true;
2615 tree lhs = gimple_call_lhs (stmt2);
2616 unlink_stmt_vdef (stmt2);
2617 if (lhs)
2618 {
2619 gimple *assign = gimple_build_assign (lhs, ptr);
2620 gsi_replace (gsi, assign, false);
2621 }
2622 else
2623 {
2624 gsi_remove (gsi, true);
2625 release_defs (stmt2);
2626 }
2627
2628 return false;
2629 }
2630
2631 /* Handle a call to memcmp. We try to handle small comparisons by
2632 converting them to load and compare, and replacing the call to memcmp
2633 with a __builtin_memcmp_eq call where possible. */
2634
2635 static bool
2636 handle_builtin_memcmp (gimple_stmt_iterator *gsi)
2637 {
2638 gcall *stmt2 = as_a <gcall *> (gsi_stmt (*gsi));
2639 tree res = gimple_call_lhs (stmt2);
2640 tree arg1 = gimple_call_arg (stmt2, 0);
2641 tree arg2 = gimple_call_arg (stmt2, 1);
2642 tree len = gimple_call_arg (stmt2, 2);
2643 unsigned HOST_WIDE_INT leni;
2644 use_operand_p use_p;
2645 imm_use_iterator iter;
2646
2647 if (!res)
2648 return true;
2649
2650 FOR_EACH_IMM_USE_FAST (use_p, iter, res)
2651 {
2652 gimple *ustmt = USE_STMT (use_p);
2653
2654 if (is_gimple_debug (ustmt))
2655 continue;
2656 if (gimple_code (ustmt) == GIMPLE_ASSIGN)
2657 {
2658 gassign *asgn = as_a <gassign *> (ustmt);
2659 tree_code code = gimple_assign_rhs_code (asgn);
2660 if ((code != EQ_EXPR && code != NE_EXPR)
2661 || !integer_zerop (gimple_assign_rhs2 (asgn)))
2662 return true;
2663 }
2664 else if (gimple_code (ustmt) == GIMPLE_COND)
2665 {
2666 tree_code code = gimple_cond_code (ustmt);
2667 if ((code != EQ_EXPR && code != NE_EXPR)
2668 || !integer_zerop (gimple_cond_rhs (ustmt)))
2669 return true;
2670 }
2671 else
2672 return true;
2673 }
2674
2675 if (tree_fits_uhwi_p (len)
2676 && (leni = tree_to_uhwi (len)) <= GET_MODE_SIZE (word_mode)
2677 && pow2p_hwi (leni))
2678 {
2679 leni *= CHAR_TYPE_SIZE;
2680 unsigned align1 = get_pointer_alignment (arg1);
2681 unsigned align2 = get_pointer_alignment (arg2);
2682 unsigned align = MIN (align1, align2);
2683 scalar_int_mode mode;
2684 if (int_mode_for_size (leni, 1).exists (&mode)
2685 && (align >= leni || !targetm.slow_unaligned_access (mode, align)))
2686 {
2687 location_t loc = gimple_location (stmt2);
2688 tree type, off;
2689 type = build_nonstandard_integer_type (leni, 1);
2690 gcc_assert (GET_MODE_BITSIZE (TYPE_MODE (type)) == leni);
2691 tree ptrtype = build_pointer_type_for_mode (char_type_node,
2692 ptr_mode, true);
2693 off = build_int_cst (ptrtype, 0);
2694 arg1 = build2_loc (loc, MEM_REF, type, arg1, off);
2695 arg2 = build2_loc (loc, MEM_REF, type, arg2, off);
2696 tree tem1 = fold_const_aggregate_ref (arg1);
2697 if (tem1)
2698 arg1 = tem1;
2699 tree tem2 = fold_const_aggregate_ref (arg2);
2700 if (tem2)
2701 arg2 = tem2;
2702 res = fold_convert_loc (loc, TREE_TYPE (res),
2703 fold_build2_loc (loc, NE_EXPR,
2704 boolean_type_node,
2705 arg1, arg2));
2706 gimplify_and_update_call_from_tree (gsi, res);
2707 return false;
2708 }
2709 }
2710
2711 gimple_call_set_fndecl (stmt2, builtin_decl_explicit (BUILT_IN_MEMCMP_EQ));
2712 return false;
2713 }
2714
2715 /* Handle a POINTER_PLUS_EXPR statement.
2716 For p = "abcd" + 2; compute associated length, or if
2717 p = q + off is pointing to a '\0' character of a string, call
2718 zero_length_string on it. */
2719
2720 static void
2721 handle_pointer_plus (gimple_stmt_iterator *gsi)
2722 {
2723 gimple *stmt = gsi_stmt (*gsi);
2724 tree lhs = gimple_assign_lhs (stmt), off;
2725 int idx = get_stridx (gimple_assign_rhs1 (stmt));
2726 strinfo *si, *zsi;
2727
2728 if (idx == 0)
2729 return;
2730
2731 if (idx < 0)
2732 {
2733 tree off = gimple_assign_rhs2 (stmt);
2734 if (tree_fits_uhwi_p (off)
2735 && tree_to_uhwi (off) <= (unsigned HOST_WIDE_INT) ~idx)
2736 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)]
2737 = ~(~idx - (int) tree_to_uhwi (off));
2738 return;
2739 }
2740
2741 si = get_strinfo (idx);
2742 if (si == NULL || si->nonzero_chars == NULL_TREE)
2743 return;
2744
2745 off = gimple_assign_rhs2 (stmt);
2746 zsi = NULL;
2747 if (si->full_string_p && operand_equal_p (si->nonzero_chars, off, 0))
2748 zsi = zero_length_string (lhs, si);
2749 else if (TREE_CODE (off) == SSA_NAME)
2750 {
2751 gimple *def_stmt = SSA_NAME_DEF_STMT (off);
2752 if (gimple_assign_single_p (def_stmt)
2753 && si->full_string_p
2754 && operand_equal_p (si->nonzero_chars,
2755 gimple_assign_rhs1 (def_stmt), 0))
2756 zsi = zero_length_string (lhs, si);
2757 }
2758 if (zsi != NULL
2759 && si->endptr != NULL_TREE
2760 && si->endptr != lhs
2761 && TREE_CODE (si->endptr) == SSA_NAME)
2762 {
2763 enum tree_code rhs_code
2764 = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr))
2765 ? SSA_NAME : NOP_EXPR;
2766 gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr);
2767 gcc_assert (gsi_stmt (*gsi) == stmt);
2768 update_stmt (stmt);
2769 }
2770 }
2771
2772 /* Handle a single character store. */
2773
2774 static bool
2775 handle_char_store (gimple_stmt_iterator *gsi)
2776 {
2777 int idx = -1;
2778 strinfo *si = NULL;
2779 gimple *stmt = gsi_stmt (*gsi);
2780 tree ssaname = NULL_TREE, lhs = gimple_assign_lhs (stmt);
2781 tree rhs = gimple_assign_rhs1 (stmt);
2782 unsigned HOST_WIDE_INT offset = 0;
2783
2784 if (TREE_CODE (lhs) == MEM_REF
2785 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
2786 {
2787 tree mem_offset = TREE_OPERAND (lhs, 1);
2788 if (tree_fits_uhwi_p (mem_offset))
2789 {
2790 /* Get the strinfo for the base, and use it if it starts with at
2791 least OFFSET nonzero characters. This is trivially true if
2792 OFFSET is zero. */
2793 offset = tree_to_uhwi (mem_offset);
2794 idx = get_stridx (TREE_OPERAND (lhs, 0));
2795 if (idx > 0)
2796 si = get_strinfo (idx);
2797 if (offset == 0)
2798 ssaname = TREE_OPERAND (lhs, 0);
2799 else if (si == NULL || compare_nonzero_chars (si, offset) < 0)
2800 return true;
2801 }
2802 }
2803 else
2804 {
2805 idx = get_addr_stridx (lhs, NULL_TREE, &offset);
2806 if (idx > 0)
2807 si = get_strinfo (idx);
2808 }
2809
2810 bool storing_zero_p = initializer_zerop (rhs);
2811 bool storing_nonzero_p = (!storing_zero_p
2812 && TREE_CODE (rhs) == INTEGER_CST
2813 && integer_nonzerop (rhs));
2814
2815 if (si != NULL)
2816 {
2817 int cmp = compare_nonzero_chars (si, offset);
2818 gcc_assert (offset == 0 || cmp >= 0);
2819 if (storing_zero_p && cmp == 0 && si->full_string_p)
2820 {
2821 /* When overwriting a '\0' with a '\0', the store can be removed
2822 if we know it has been stored in the current function. */
2823 if (!stmt_could_throw_p (stmt) && si->writable)
2824 {
2825 unlink_stmt_vdef (stmt);
2826 release_defs (stmt);
2827 gsi_remove (gsi, true);
2828 return false;
2829 }
2830 else
2831 {
2832 si->writable = true;
2833 gsi_next (gsi);
2834 return false;
2835 }
2836 }
2837 /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0',
2838 and if we aren't storing '\0', we know that the length of the
2839 string and any other zero terminated string in memory remains
2840 the same. In that case we move to the next gimple statement and
2841 return to signal the caller that it shouldn't invalidate anything.
2842
2843 This is benefical for cases like:
2844
2845 char p[20];
2846 void foo (char *q)
2847 {
2848 strcpy (p, "foobar");
2849 size_t len = strlen (p); // This can be optimized into 6
2850 size_t len2 = strlen (q); // This has to be computed
2851 p[0] = 'X';
2852 size_t len3 = strlen (p); // This can be optimized into 6
2853 size_t len4 = strlen (q); // This can be optimized into len2
2854 bar (len, len2, len3, len4);
2855 }
2856 */
2857 else if (storing_nonzero_p && cmp > 0)
2858 {
2859 gsi_next (gsi);
2860 return false;
2861 }
2862 else if (storing_zero_p || storing_nonzero_p || (offset != 0 && cmp > 0))
2863 {
2864 /* When storing_nonzero_p, we know that the string now starts
2865 with OFFSET + 1 nonzero characters, but don't know whether
2866 there's a following nul terminator.
2867
2868 When storing_zero_p, we know that the string is now OFFSET
2869 characters long.
2870
2871 Otherwise, we're storing an unknown value at offset OFFSET,
2872 so need to clip the nonzero_chars to OFFSET. */
2873 location_t loc = gimple_location (stmt);
2874 tree oldlen = si->nonzero_chars;
2875 if (cmp == 0 && si->full_string_p)
2876 /* We're overwriting the nul terminator with a nonzero or
2877 unknown character. If the previous stmt was a memcpy,
2878 its length may be decreased. */
2879 adjust_last_stmt (si, stmt, false);
2880 si = unshare_strinfo (si);
2881 if (storing_nonzero_p)
2882 si->nonzero_chars = build_int_cst (size_type_node, offset + 1);
2883 else
2884 si->nonzero_chars = build_int_cst (size_type_node, offset);
2885 si->full_string_p = storing_zero_p;
2886 if (storing_zero_p
2887 && ssaname
2888 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2889 si->endptr = ssaname;
2890 else
2891 si->endptr = NULL;
2892 si->next = 0;
2893 si->stmt = NULL;
2894 si->writable = true;
2895 si->dont_invalidate = true;
2896 if (oldlen)
2897 {
2898 tree adj = fold_build2_loc (loc, MINUS_EXPR, size_type_node,
2899 si->nonzero_chars, oldlen);
2900 adjust_related_strinfos (loc, si, adj);
2901 }
2902 else
2903 si->prev = 0;
2904 }
2905 }
2906 else if (idx == 0 && (storing_zero_p || storing_nonzero_p))
2907 {
2908 if (ssaname)
2909 idx = new_stridx (ssaname);
2910 else
2911 idx = new_addr_stridx (lhs);
2912 if (idx != 0)
2913 {
2914 tree ptr = (ssaname ? ssaname : build_fold_addr_expr (lhs));
2915 tree len = storing_nonzero_p ? size_one_node : size_zero_node;
2916 si = new_strinfo (ptr, idx, len, storing_zero_p);
2917 set_strinfo (idx, si);
2918 if (storing_zero_p
2919 && ssaname
2920 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssaname))
2921 si->endptr = ssaname;
2922 si->dont_invalidate = true;
2923 si->writable = true;
2924 }
2925 }
2926 else if (idx == 0
2927 && TREE_CODE (gimple_assign_rhs1 (stmt)) == STRING_CST
2928 && ssaname == NULL_TREE
2929 && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
2930 {
2931 size_t l = strlen (TREE_STRING_POINTER (gimple_assign_rhs1 (stmt)));
2932 HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
2933 if (a > 0 && (unsigned HOST_WIDE_INT) a > l)
2934 {
2935 int idx = new_addr_stridx (lhs);
2936 if (idx != 0)
2937 {
2938 si = new_strinfo (build_fold_addr_expr (lhs), idx,
2939 build_int_cst (size_type_node, l), true);
2940 set_strinfo (idx, si);
2941 si->dont_invalidate = true;
2942 }
2943 }
2944 }
2945
2946 if (si != NULL && offset == 0 && storing_zero_p)
2947 {
2948 /* Allow adjust_last_stmt to remove it if the stored '\0'
2949 is immediately overwritten. */
2950 laststmt.stmt = stmt;
2951 laststmt.len = build_int_cst (size_type_node, 1);
2952 laststmt.stridx = si->idx;
2953 }
2954 return true;
2955 }
2956
2957 /* Try to fold strstr (s, t) eq/ne s to strncmp (s, t, strlen (t)) eq/ne 0. */
2958
2959 static void
2960 fold_strstr_to_strncmp (tree rhs1, tree rhs2, gimple *stmt)
2961 {
2962 if (TREE_CODE (rhs1) != SSA_NAME
2963 || TREE_CODE (rhs2) != SSA_NAME)
2964 return;
2965
2966 gimple *call_stmt = NULL;
2967 for (int pass = 0; pass < 2; pass++)
2968 {
2969 gimple *g = SSA_NAME_DEF_STMT (rhs1);
2970 if (gimple_call_builtin_p (g, BUILT_IN_STRSTR)
2971 && has_single_use (rhs1)
2972 && gimple_call_arg (g, 0) == rhs2)
2973 {
2974 call_stmt = g;
2975 break;
2976 }
2977 std::swap (rhs1, rhs2);
2978 }
2979
2980 if (call_stmt)
2981 {
2982 tree arg0 = gimple_call_arg (call_stmt, 0);
2983
2984 if (arg0 == rhs2)
2985 {
2986 tree arg1 = gimple_call_arg (call_stmt, 1);
2987 tree arg1_len = NULL_TREE;
2988 int idx = get_stridx (arg1);
2989
2990 if (idx)
2991 {
2992 if (idx < 0)
2993 arg1_len = build_int_cst (size_type_node, ~idx);
2994 else
2995 {
2996 strinfo *si = get_strinfo (idx);
2997 if (si)
2998 arg1_len = get_string_length (si);
2999 }
3000 }
3001
3002 if (arg1_len != NULL_TREE)
3003 {
3004 gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
3005 tree strncmp_decl = builtin_decl_explicit (BUILT_IN_STRNCMP);
3006 gcall *strncmp_call = gimple_build_call (strncmp_decl, 3,
3007 arg0, arg1, arg1_len);
3008 tree strncmp_lhs = make_ssa_name (integer_type_node);
3009 gimple_set_vuse (strncmp_call, gimple_vuse (call_stmt));
3010 gimple_call_set_lhs (strncmp_call, strncmp_lhs);
3011 gsi_remove (&gsi, true);
3012 gsi_insert_before (&gsi, strncmp_call, GSI_SAME_STMT);
3013 tree zero = build_zero_cst (TREE_TYPE (strncmp_lhs));
3014
3015 if (is_gimple_assign (stmt))
3016 {
3017 if (gimple_assign_rhs_code (stmt) == COND_EXPR)
3018 {
3019 tree cond = gimple_assign_rhs1 (stmt);
3020 TREE_OPERAND (cond, 0) = strncmp_lhs;
3021 TREE_OPERAND (cond, 1) = zero;
3022 }
3023 else
3024 {
3025 gimple_assign_set_rhs1 (stmt, strncmp_lhs);
3026 gimple_assign_set_rhs2 (stmt, zero);
3027 }
3028 }
3029 else
3030 {
3031 gcond *cond = as_a<gcond *> (stmt);
3032 gimple_cond_set_lhs (cond, strncmp_lhs);
3033 gimple_cond_set_rhs (cond, zero);
3034 }
3035 update_stmt (stmt);
3036 }
3037 }
3038 }
3039 }
3040
3041 /* Attempt to check for validity of the performed access a single statement
3042 at *GSI using string length knowledge, and to optimize it. */
3043
3044 static bool
3045 strlen_check_and_optimize_stmt (gimple_stmt_iterator *gsi)
3046 {
3047 gimple *stmt = gsi_stmt (*gsi);
3048
3049 if (is_gimple_call (stmt))
3050 {
3051 tree callee = gimple_call_fndecl (stmt);
3052 if (valid_builtin_call (stmt))
3053 switch (DECL_FUNCTION_CODE (callee))
3054 {
3055 case BUILT_IN_STRLEN:
3056 case BUILT_IN_STRLEN_CHKP:
3057 handle_builtin_strlen (gsi);
3058 break;
3059 case BUILT_IN_STRCHR:
3060 case BUILT_IN_STRCHR_CHKP:
3061 handle_builtin_strchr (gsi);
3062 break;
3063 case BUILT_IN_STRCPY:
3064 case BUILT_IN_STRCPY_CHK:
3065 case BUILT_IN_STPCPY:
3066 case BUILT_IN_STPCPY_CHK:
3067 case BUILT_IN_STRCPY_CHKP:
3068 case BUILT_IN_STRCPY_CHK_CHKP:
3069 case BUILT_IN_STPCPY_CHKP:
3070 case BUILT_IN_STPCPY_CHK_CHKP:
3071 handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi);
3072 break;
3073
3074 case BUILT_IN_STRNCAT:
3075 case BUILT_IN_STRNCAT_CHK:
3076 handle_builtin_strncat (DECL_FUNCTION_CODE (callee), gsi);
3077 break;
3078
3079 case BUILT_IN_STPNCPY:
3080 case BUILT_IN_STPNCPY_CHK:
3081 case BUILT_IN_STRNCPY:
3082 case BUILT_IN_STRNCPY_CHK:
3083 handle_builtin_stxncpy (DECL_FUNCTION_CODE (callee), gsi);
3084 break;
3085
3086 case BUILT_IN_MEMCPY:
3087 case BUILT_IN_MEMCPY_CHK:
3088 case BUILT_IN_MEMPCPY:
3089 case BUILT_IN_MEMPCPY_CHK:
3090 case BUILT_IN_MEMCPY_CHKP:
3091 case BUILT_IN_MEMCPY_CHK_CHKP:
3092 case BUILT_IN_MEMPCPY_CHKP:
3093 case BUILT_IN_MEMPCPY_CHK_CHKP:
3094 handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi);
3095 break;
3096 case BUILT_IN_STRCAT:
3097 case BUILT_IN_STRCAT_CHK:
3098 case BUILT_IN_STRCAT_CHKP:
3099 case BUILT_IN_STRCAT_CHK_CHKP:
3100 handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi);
3101 break;
3102 case BUILT_IN_MALLOC:
3103 case BUILT_IN_CALLOC:
3104 handle_builtin_malloc (DECL_FUNCTION_CODE (callee), gsi);
3105 break;
3106 case BUILT_IN_MEMSET:
3107 if (!handle_builtin_memset (gsi))
3108 return false;
3109 break;
3110 case BUILT_IN_MEMCMP:
3111 if (!handle_builtin_memcmp (gsi))
3112 return false;
3113 break;
3114 default:
3115 break;
3116 }
3117 }
3118 else if (is_gimple_assign (stmt) && !gimple_clobber_p (stmt))
3119 {
3120 tree lhs = gimple_assign_lhs (stmt);
3121
3122 if (TREE_CODE (lhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (lhs)))
3123 {
3124 if (gimple_assign_single_p (stmt)
3125 || (gimple_assign_cast_p (stmt)
3126 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
3127 {
3128 int idx = get_stridx (gimple_assign_rhs1 (stmt));
3129 ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = idx;
3130 }
3131 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
3132 handle_pointer_plus (gsi);
3133 }
3134 else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
3135 {
3136 enum tree_code code = gimple_assign_rhs_code (stmt);
3137 if (code == COND_EXPR)
3138 {
3139 tree cond = gimple_assign_rhs1 (stmt);
3140 enum tree_code cond_code = TREE_CODE (cond);
3141
3142 if (cond_code == EQ_EXPR || cond_code == NE_EXPR)
3143 fold_strstr_to_strncmp (TREE_OPERAND (cond, 0),
3144 TREE_OPERAND (cond, 1), stmt);
3145 }
3146 else if (code == EQ_EXPR || code == NE_EXPR)
3147 fold_strstr_to_strncmp (gimple_assign_rhs1 (stmt),
3148 gimple_assign_rhs2 (stmt), stmt);
3149 else if (gimple_assign_load_p (stmt)
3150 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
3151 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (char_type_node)
3152 && (TYPE_PRECISION (TREE_TYPE (lhs))
3153 == TYPE_PRECISION (char_type_node))
3154 && !gimple_has_volatile_ops (stmt))
3155 {
3156 tree off = integer_zero_node;
3157 unsigned HOST_WIDE_INT coff = 0;
3158 int idx = -1;
3159 tree rhs1 = gimple_assign_rhs1 (stmt);
3160 if (code == MEM_REF)
3161 {
3162 idx = get_stridx (TREE_OPERAND (rhs1, 0));
3163 off = TREE_OPERAND (rhs1, 1);
3164 }
3165 else
3166 idx = get_addr_stridx (rhs1, NULL_TREE, &coff);
3167 if (idx > 0)
3168 {
3169 strinfo *si = get_strinfo (idx);
3170 if (si
3171 && si->nonzero_chars
3172 && TREE_CODE (si->nonzero_chars) == INTEGER_CST)
3173 {
3174 widest_int w1 = wi::to_widest (si->nonzero_chars);
3175 widest_int w2 = wi::to_widest (off) + coff;
3176 if (w1 == w2
3177 && si->full_string_p)
3178 {
3179 /* Reading the final '\0' character. */
3180 tree zero = build_int_cst (TREE_TYPE (lhs), 0);
3181 gimple_set_vuse (stmt, NULL_TREE);
3182 gimple_assign_set_rhs_from_tree (gsi, zero);
3183 update_stmt (gsi_stmt (*gsi));
3184 }
3185 else if (w1 > w2)
3186 {
3187 /* Reading a character before the final '\0'
3188 character. Just set the value range to ~[0, 0]
3189 if we don't have anything better. */
3190 wide_int min, max;
3191 tree type = TREE_TYPE (lhs);
3192 enum value_range_type vr
3193 = get_range_info (lhs, &min, &max);
3194 if (vr == VR_VARYING
3195 || (vr == VR_RANGE
3196 && min == wi::min_value (TYPE_PRECISION (type),
3197 TYPE_SIGN (type))
3198 && max == wi::max_value (TYPE_PRECISION (type),
3199 TYPE_SIGN (type))))
3200 set_range_info (lhs, VR_ANTI_RANGE,
3201 wi::zero (TYPE_PRECISION (type)),
3202 wi::zero (TYPE_PRECISION (type)));
3203 }
3204 }
3205 }
3206 }
3207
3208 if (strlen_to_stridx)
3209 {
3210 tree rhs1 = gimple_assign_rhs1 (stmt);
3211 if (stridx_strlenloc *ps = strlen_to_stridx->get (rhs1))
3212 strlen_to_stridx->put (lhs, stridx_strlenloc (*ps));
3213 }
3214 }
3215 else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
3216 {
3217 tree type = TREE_TYPE (lhs);
3218 if (TREE_CODE (type) == ARRAY_TYPE)
3219 type = TREE_TYPE (type);
3220 if (TREE_CODE (type) == INTEGER_TYPE
3221 && TYPE_MODE (type) == TYPE_MODE (char_type_node)
3222 && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
3223 {
3224 if (! handle_char_store (gsi))
3225 return false;
3226 }
3227 }
3228 }
3229 else if (gcond *cond = dyn_cast<gcond *> (stmt))
3230 {
3231 enum tree_code code = gimple_cond_code (cond);
3232 if (code == EQ_EXPR || code == NE_EXPR)
3233 fold_strstr_to_strncmp (gimple_cond_lhs (stmt),
3234 gimple_cond_rhs (stmt), stmt);
3235 }
3236
3237 if (gimple_vdef (stmt))
3238 maybe_invalidate (stmt);
3239 return true;
3240 }
3241
3242 /* Recursively call maybe_invalidate on stmts that might be executed
3243 in between dombb and current bb and that contain a vdef. Stop when
3244 *count stmts are inspected, or if the whole strinfo vector has
3245 been invalidated. */
3246
3247 static void
3248 do_invalidate (basic_block dombb, gimple *phi, bitmap visited, int *count)
3249 {
3250 unsigned int i, n = gimple_phi_num_args (phi);
3251
3252 for (i = 0; i < n; i++)
3253 {
3254 tree vuse = gimple_phi_arg_def (phi, i);
3255 gimple *stmt = SSA_NAME_DEF_STMT (vuse);
3256 basic_block bb = gimple_bb (stmt);
3257 if (bb == NULL
3258 || bb == dombb
3259 || !bitmap_set_bit (visited, bb->index)
3260 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3261 continue;
3262 while (1)
3263 {
3264 if (gimple_code (stmt) == GIMPLE_PHI)
3265 {
3266 do_invalidate (dombb, stmt, visited, count);
3267 if (*count == 0)
3268 return;
3269 break;
3270 }
3271 if (--*count == 0)
3272 return;
3273 if (!maybe_invalidate (stmt))
3274 {
3275 *count = 0;
3276 return;
3277 }
3278 vuse = gimple_vuse (stmt);
3279 stmt = SSA_NAME_DEF_STMT (vuse);
3280 if (gimple_bb (stmt) != bb)
3281 {
3282 bb = gimple_bb (stmt);
3283 if (bb == NULL
3284 || bb == dombb
3285 || !bitmap_set_bit (visited, bb->index)
3286 || !dominated_by_p (CDI_DOMINATORS, bb, dombb))
3287 break;
3288 }
3289 }
3290 }
3291 }
3292
3293 class strlen_dom_walker : public dom_walker
3294 {
3295 public:
3296 strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
3297
3298 virtual edge before_dom_children (basic_block);
3299 virtual void after_dom_children (basic_block);
3300 };
3301
3302 /* Callback for walk_dominator_tree. Attempt to optimize various
3303 string ops by remembering string lengths pointed by pointer SSA_NAMEs. */
3304
3305 edge
3306 strlen_dom_walker::before_dom_children (basic_block bb)
3307 {
3308 basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
3309
3310 if (dombb == NULL)
3311 stridx_to_strinfo = NULL;
3312 else
3313 {
3314 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) dombb->aux);
3315 if (stridx_to_strinfo)
3316 {
3317 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3318 gsi_next (&gsi))
3319 {
3320 gphi *phi = gsi.phi ();
3321 if (virtual_operand_p (gimple_phi_result (phi)))
3322 {
3323 bitmap visited = BITMAP_ALLOC (NULL);
3324 int count_vdef = 100;
3325 do_invalidate (dombb, phi, visited, &count_vdef);
3326 BITMAP_FREE (visited);
3327 if (count_vdef == 0)
3328 {
3329 /* If there were too many vdefs in between immediate
3330 dominator and current bb, invalidate everything.
3331 If stridx_to_strinfo has been unshared, we need
3332 to free it, otherwise just set it to NULL. */
3333 if (!strinfo_shared ())
3334 {
3335 unsigned int i;
3336 strinfo *si;
3337
3338 for (i = 1;
3339 vec_safe_iterate (stridx_to_strinfo, i, &si);
3340 ++i)
3341 {
3342 free_strinfo (si);
3343 (*stridx_to_strinfo)[i] = NULL;
3344 }
3345 }
3346 else
3347 stridx_to_strinfo = NULL;
3348 }
3349 break;
3350 }
3351 }
3352 }
3353 }
3354
3355 /* If all PHI arguments have the same string index, the PHI result
3356 has it as well. */
3357 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
3358 gsi_next (&gsi))
3359 {
3360 gphi *phi = gsi.phi ();
3361 tree result = gimple_phi_result (phi);
3362 if (!virtual_operand_p (result) && POINTER_TYPE_P (TREE_TYPE (result)))
3363 {
3364 int idx = get_stridx (gimple_phi_arg_def (phi, 0));
3365 if (idx != 0)
3366 {
3367 unsigned int i, n = gimple_phi_num_args (phi);
3368 for (i = 1; i < n; i++)
3369 if (idx != get_stridx (gimple_phi_arg_def (phi, i)))
3370 break;
3371 if (i == n)
3372 ssa_ver_to_stridx[SSA_NAME_VERSION (result)] = idx;
3373 }
3374 }
3375 }
3376
3377 /* Attempt to optimize individual statements. */
3378 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
3379 if (strlen_check_and_optimize_stmt (&gsi))
3380 gsi_next (&gsi);
3381
3382 bb->aux = stridx_to_strinfo;
3383 if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
3384 (*stridx_to_strinfo)[0] = (strinfo *) bb;
3385 return NULL;
3386 }
3387
3388 /* Callback for walk_dominator_tree. Free strinfo vector if it is
3389 owned by the current bb, clear bb->aux. */
3390
3391 void
3392 strlen_dom_walker::after_dom_children (basic_block bb)
3393 {
3394 if (bb->aux)
3395 {
3396 stridx_to_strinfo = ((vec<strinfo *, va_heap, vl_embed> *) bb->aux);
3397 if (vec_safe_length (stridx_to_strinfo)
3398 && (*stridx_to_strinfo)[0] == (strinfo *) bb)
3399 {
3400 unsigned int i;
3401 strinfo *si;
3402
3403 for (i = 1; vec_safe_iterate (stridx_to_strinfo, i, &si); ++i)
3404 free_strinfo (si);
3405 vec_free (stridx_to_strinfo);
3406 }
3407 bb->aux = NULL;
3408 }
3409 }
3410
3411 /* Main entry point. */
3412
3413 namespace {
3414
3415 const pass_data pass_data_strlen =
3416 {
3417 GIMPLE_PASS, /* type */
3418 "strlen", /* name */
3419 OPTGROUP_NONE, /* optinfo_flags */
3420 TV_TREE_STRLEN, /* tv_id */
3421 ( PROP_cfg | PROP_ssa ), /* properties_required */
3422 0, /* properties_provided */
3423 0, /* properties_destroyed */
3424 0, /* todo_flags_start */
3425 0, /* todo_flags_finish */
3426 };
3427
3428 class pass_strlen : public gimple_opt_pass
3429 {
3430 public:
3431 pass_strlen (gcc::context *ctxt)
3432 : gimple_opt_pass (pass_data_strlen, ctxt)
3433 {}
3434
3435 /* opt_pass methods: */
3436 virtual bool gate (function *) { return flag_optimize_strlen != 0; }
3437 virtual unsigned int execute (function *);
3438
3439 }; // class pass_strlen
3440
3441 unsigned int
3442 pass_strlen::execute (function *fun)
3443 {
3444 gcc_assert (!strlen_to_stridx);
3445 if (warn_stringop_overflow || warn_stringop_truncation)
3446 strlen_to_stridx = new hash_map<tree, stridx_strlenloc> ();
3447
3448 ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
3449 max_stridx = 1;
3450
3451 calculate_dominance_info (CDI_DOMINATORS);
3452
3453 /* String length optimization is implemented as a walk of the dominator
3454 tree and a forward walk of statements within each block. */
3455 strlen_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
3456
3457 ssa_ver_to_stridx.release ();
3458 strinfo_pool.release ();
3459 if (decl_to_stridxlist_htab)
3460 {
3461 obstack_free (&stridx_obstack, NULL);
3462 delete decl_to_stridxlist_htab;
3463 decl_to_stridxlist_htab = NULL;
3464 }
3465 laststmt.stmt = NULL;
3466 laststmt.len = NULL_TREE;
3467 laststmt.stridx = 0;
3468
3469 if (strlen_to_stridx)
3470 {
3471 strlen_to_stridx->empty ();
3472 delete strlen_to_stridx;
3473 strlen_to_stridx = NULL;
3474 }
3475
3476 return 0;
3477 }
3478
3479 } // anon namespace
3480
3481 gimple_opt_pass *
3482 make_pass_strlen (gcc::context *ctxt)
3483 {
3484 return new pass_strlen (ctxt);
3485 }