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