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