xref: /netbsd-src/external/gpl3/gcc/dist/gcc/tree-ssa-uninit.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Predicate aware uninitialized variable warning.
2    Copyright (C) 2001-2022 Free Software Foundation, Inc.
3    Contributed by Xinliang David Li <davidxl@google.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 #define INCLUDE_STRING
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "backend.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "tree-pass.h"
29 #include "ssa.h"
30 #include "gimple-pretty-print.h"
31 #include "diagnostic-core.h"
32 #include "fold-const.h"
33 #include "gimple-iterator.h"
34 #include "tree-ssa.h"
35 #include "tree-cfg.h"
36 #include "cfghooks.h"
37 #include "attribs.h"
38 #include "builtins.h"
39 #include "calls.h"
40 #include "gimple-range.h"
41 #include "gimple-predicate-analysis.h"
42 #include "domwalk.h"
43 #include "tree-ssa-sccvn.h"
44 #include "cfganal.h"
45 
46 /* This implements the pass that does predicate aware warning on uses of
47    possibly uninitialized variables.  The pass first collects the set of
48    possibly uninitialized SSA names.  For each such name, it walks through
49    all its immediate uses.  For each immediate use, it rebuilds the condition
50    expression (the predicate) that guards the use.  The predicate is then
51    examined to see if the variable is always defined under that same condition.
52    This is done either by pruning the unrealizable paths that lead to the
53    default definitions or by checking if the predicate set that guards the
54    defining paths is a superset of the use predicate.  */
55 
56 /* Pointer set of potentially undefined ssa names, i.e.,
57    ssa names that are defined by phi with operands that
58    are not defined or potentially undefined.  */
59 static hash_set<tree> *possibly_undefined_names = 0;
60 
61 /* Returns the first bit position (starting from LSB)
62    in mask that is non zero.  Returns -1 if the mask is empty.  */
63 static int
get_mask_first_set_bit(unsigned mask)64 get_mask_first_set_bit (unsigned mask)
65 {
66   int pos = 0;
67   if (mask == 0)
68     return -1;
69 
70   while ((mask & (1 << pos)) == 0)
71     pos++;
72 
73   return pos;
74 }
75 #define MASK_FIRST_SET_BIT(mask) get_mask_first_set_bit (mask)
76 
77 /* Return true if T, an SSA_NAME, has an undefined value.  */
78 static bool
has_undefined_value_p(tree t)79 has_undefined_value_p (tree t)
80 {
81   return (ssa_undefined_value_p (t)
82 	  || (possibly_undefined_names
83 	      && possibly_undefined_names->contains (t)));
84 }
85 
86 /* Return true if EXPR should suppress either uninitialized warning.  */
87 
88 static inline bool
get_no_uninit_warning(tree expr)89 get_no_uninit_warning (tree expr)
90 {
91   return warning_suppressed_p (expr, OPT_Wuninitialized);
92 }
93 
94 /* Suppress both uninitialized warnings for EXPR.  */
95 
96 static inline void
set_no_uninit_warning(tree expr)97 set_no_uninit_warning (tree expr)
98 {
99   suppress_warning (expr, OPT_Wuninitialized);
100 }
101 
102 /* Like has_undefined_value_p, but don't return true if the no-warning
103    bit is set on SSA_NAME_VAR for either uninit warning.  */
104 
105 static inline bool
uninit_undefined_value_p(tree t)106 uninit_undefined_value_p (tree t)
107 {
108   if (!has_undefined_value_p (t))
109     return false;
110   if (!SSA_NAME_VAR (t))
111     return true;
112   return !get_no_uninit_warning (SSA_NAME_VAR (t));
113 }
114 
115 /* Emit warnings for uninitialized variables.  This is done in two passes.
116 
117    The first pass notices real uses of SSA names with undefined values.
118    Such uses are unconditionally uninitialized, and we can be certain that
119    such a use is a mistake.  This pass is run before most optimizations,
120    so that we catch as many as we can.
121 
122    The second pass follows PHI nodes to find uses that are potentially
123    uninitialized.  In this case we can't necessarily prove that the use
124    is really uninitialized.  This pass is run after most optimizations,
125    so that we thread as many jumps and possible, and delete as much dead
126    code as possible, in order to reduce false positives.  We also look
127    again for plain uninitialized variables, since optimization may have
128    changed conditionally uninitialized to unconditionally uninitialized.  */
129 
130 /* Emit warning OPT for variable VAR at the point in the program where
131    the SSA_NAME T is being used uninitialized.  The warning text is in
132    MSGID and STMT is the statement that does the uninitialized read.
133    PHI_ARG_LOC is the location of the PHI argument if T and VAR are one,
134    or UNKNOWN_LOCATION otherwise.  */
135 
136 static void
warn_uninit(opt_code opt,tree t,tree var,gimple * context,location_t phi_arg_loc=UNKNOWN_LOCATION)137 warn_uninit (opt_code opt, tree t, tree var, gimple *context,
138 	     location_t phi_arg_loc = UNKNOWN_LOCATION)
139 {
140   /* Bail if the value isn't provably uninitialized.  */
141   if (!has_undefined_value_p (t))
142     return;
143 
144   /* Ignore COMPLEX_EXPR as initializing only a part of a complex
145      turns in a COMPLEX_EXPR with the not initialized part being
146      set to its previous (undefined) value.  */
147   if (is_gimple_assign (context)
148       && gimple_assign_rhs_code (context) == COMPLEX_EXPR)
149     return;
150 
151   /* Ignore REALPART_EXPR or IMAGPART_EXPR if its operand is a call to
152      .DEFERRED_INIT.  This is for handling the following case correctly:
153 
154   1 typedef _Complex float C;
155   2 C foo (int cond)
156   3 {
157   4   C f;
158   5   __imag__ f = 0;
159   6   if (cond)
160   7     {
161   8       __real__ f = 1;
162   9       return f;
163  10     }
164  11   return f;
165  12 }
166 
167     with -ftrivial-auto-var-init, compiler will insert the following
168     artificial initialization at line 4:
169   f = .DEFERRED_INIT (f, 2);
170   _1 = REALPART_EXPR <f>;
171 
172     without the following special handling, _1 = REALPART_EXPR <f> will
173     be treated as the uninitialized use point, which is incorrect. (the
174     real uninitialized use point is at line 11).  */
175   if (is_gimple_assign (context)
176       && (gimple_assign_rhs_code (context) == REALPART_EXPR
177 	  || gimple_assign_rhs_code (context) == IMAGPART_EXPR))
178     {
179       tree v = gimple_assign_rhs1 (context);
180       if (TREE_CODE (TREE_OPERAND (v, 0)) == SSA_NAME
181 	  && gimple_call_internal_p (SSA_NAME_DEF_STMT (TREE_OPERAND (v, 0)),
182 				     IFN_DEFERRED_INIT))
183 	return;
184     }
185 
186   /* Anonymous SSA_NAMEs shouldn't be uninitialized, but ssa_undefined_value_p
187      can return true if the def stmt of an anonymous SSA_NAME is
188      1. A COMPLEX_EXPR created for conversion from scalar to complex.  Use the
189      underlying var of the COMPLEX_EXPRs real part in that case.  See PR71581.
190 
191      Or
192 
193      2. A call to .DEFERRED_INIT internal function. Since the original variable
194      has been eliminated by optimziation, we need to get the variable name,
195      and variable declaration location from this call.  We recorded variable
196      name into VAR_NAME_STR, and will get location info and record warning
197      suppressed info to VAR_DEF_STMT, which is the .DEFERRED_INIT call.  */
198 
199   const char *var_name_str = NULL;
200   gimple *var_def_stmt = NULL;
201 
202   if (!var && !SSA_NAME_VAR (t))
203     {
204       var_def_stmt = SSA_NAME_DEF_STMT (t);
205 
206       if (is_gimple_assign (var_def_stmt)
207 	  && gimple_assign_rhs_code (var_def_stmt) == COMPLEX_EXPR)
208 	{
209 	  tree v = gimple_assign_rhs1 (var_def_stmt);
210 	  if (TREE_CODE (v) == SSA_NAME
211 	      && has_undefined_value_p (v)
212 	      && zerop (gimple_assign_rhs2 (var_def_stmt)))
213 	    var = SSA_NAME_VAR (v);
214 	}
215 
216       if (gimple_call_internal_p (var_def_stmt, IFN_DEFERRED_INIT))
217 	{
218 	  /* Ignore the call to .DEFERRED_INIT that define the original
219 	     var itself as the following case:
220 		temp = .DEFERRED_INIT (4, 2, “alt_reloc");
221 		alt_reloc = temp;
222 	     In order to avoid generating warning for the fake usage
223 	     at alt_reloc = temp.
224 	  */
225 	  tree lhs_var = NULL_TREE;
226 	  tree lhs_var_name = NULL_TREE;
227 	  const char *lhs_var_name_str = NULL;
228 
229 	  /* Get the variable name from the 3rd argument of call.  */
230 	  tree var_name = gimple_call_arg (var_def_stmt, 2);
231 	  var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0);
232 	  var_name_str = TREE_STRING_POINTER (var_name);
233 
234 	  if (is_gimple_assign (context))
235 	    {
236 	      if (TREE_CODE (gimple_assign_lhs (context)) == VAR_DECL)
237 		lhs_var = gimple_assign_lhs (context);
238 	      else if (TREE_CODE (gimple_assign_lhs (context)) == SSA_NAME)
239 		lhs_var = SSA_NAME_VAR (gimple_assign_lhs (context));
240 	    }
241 	  if (lhs_var
242 	      && (lhs_var_name = DECL_NAME (lhs_var))
243 	      && (lhs_var_name_str = IDENTIFIER_POINTER (lhs_var_name))
244 	      && (strcmp (lhs_var_name_str, var_name_str) == 0))
245 	    return;
246 	  gcc_assert (var_name_str && var_def_stmt);
247 	}
248     }
249 
250   if (var == NULL_TREE && var_name_str == NULL)
251     return;
252 
253   /* Avoid warning if we've already done so or if the warning has been
254      suppressed.  */
255   if (((warning_suppressed_p (context, OPT_Wuninitialized)
256 	|| (gimple_assign_single_p (context)
257 	    && get_no_uninit_warning (gimple_assign_rhs1 (context)))))
258       || (var && get_no_uninit_warning (var))
259       || (var_name_str
260 	  && warning_suppressed_p (var_def_stmt, OPT_Wuninitialized)))
261     return;
262 
263   /* Use either the location of the read statement or that of the PHI
264      argument, or that of the uninitialized variable, in that order,
265      whichever is valid.  */
266   location_t location = UNKNOWN_LOCATION;
267   if (gimple_has_location (context))
268     location = gimple_location (context);
269   else if (phi_arg_loc != UNKNOWN_LOCATION)
270     location = phi_arg_loc;
271   else if (var)
272     location = DECL_SOURCE_LOCATION (var);
273   else if (var_name_str)
274     location = gimple_location (var_def_stmt);
275 
276   location = linemap_resolve_location (line_table, location,
277 				       LRK_SPELLING_LOCATION, NULL);
278 
279   auto_diagnostic_group d;
280   gcc_assert (opt == OPT_Wuninitialized || opt == OPT_Wmaybe_uninitialized);
281   if (var)
282     {
283       if ((opt == OPT_Wuninitialized
284 	   && !warning_at (location, opt, "%qD is used uninitialized", var))
285 	  || (opt == OPT_Wmaybe_uninitialized
286 	      && !warning_at (location, opt, "%qD may be used uninitialized",
287 			      var)))
288       return;
289     }
290   else if (var_name_str)
291     {
292       if ((opt == OPT_Wuninitialized
293 	   && !warning_at (location, opt, "%qs is used uninitialized",
294 			   var_name_str))
295 	  || (opt == OPT_Wmaybe_uninitialized
296 	      && !warning_at (location, opt, "%qs may be used uninitialized",
297 			      var_name_str)))
298       return;
299     }
300 
301   /* Avoid subsequent warnings for reads of the same variable again.  */
302   if (var)
303     suppress_warning (var, opt);
304   else if (var_name_str)
305     suppress_warning (var_def_stmt, opt);
306 
307   /* Issue a note pointing to the read variable unless the warning
308      is at the same location.  */
309   location_t var_loc = var ? DECL_SOURCE_LOCATION (var)
310 			: gimple_location (var_def_stmt);
311   if (location == var_loc)
312     return;
313 
314   if (var)
315     inform (var_loc, "%qD was declared here", var);
316   else if (var_name_str)
317     inform (var_loc, "%qs was declared here", var_name_str);
318 }
319 
320 struct check_defs_data
321 {
322   /* If we found any may-defs besides must-def clobbers.  */
323   bool found_may_defs;
324 };
325 
326 /* Return true if STMT is a call to built-in function all of whose
327    by-reference arguments are const-qualified (i.e., the function can
328    be assumed not to modify them).  */
329 
330 static bool
builtin_call_nomodifying_p(gimple * stmt)331 builtin_call_nomodifying_p (gimple *stmt)
332 {
333   if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
334     return false;
335 
336   tree fndecl = gimple_call_fndecl (stmt);
337   if (!fndecl)
338     return false;
339 
340   tree fntype = TREE_TYPE (fndecl);
341   if (!fntype)
342     return false;
343 
344   /* Check the called function's signature for non-constc pointers.
345      If one is found, return false.  */
346   unsigned argno = 0;
347   tree argtype;
348   function_args_iterator it;
349   FOREACH_FUNCTION_ARGS (fntype, argtype, it)
350     {
351       if (VOID_TYPE_P (argtype))
352 	return true;
353 
354       ++argno;
355 
356       if (!POINTER_TYPE_P (argtype))
357 	continue;
358 
359       if (TYPE_READONLY (TREE_TYPE (argtype)))
360 	continue;
361 
362       return false;
363     }
364 
365   /* If the number of actual arguments to the call is less than or
366      equal to the number of parameters, return false.  */
367   unsigned nargs = gimple_call_num_args (stmt);
368   if (nargs <= argno)
369     return false;
370 
371   /* Check arguments passed through the ellipsis in calls to variadic
372      functions for pointers.  If one is found that's a non-constant
373      pointer, return false.  */
374   for (; argno < nargs; ++argno)
375     {
376       tree arg = gimple_call_arg (stmt, argno);
377       argtype = TREE_TYPE (arg);
378       if (!POINTER_TYPE_P (argtype))
379 	continue;
380 
381       if (TYPE_READONLY (TREE_TYPE (argtype)))
382 	continue;
383 
384       return false;
385     }
386 
387   return true;
388 }
389 
390 /* If ARG is a FNDECL parameter declared with attribute access none or
391    write_only issue a warning for its read access via PTR.  */
392 
393 static void
maybe_warn_read_write_only(tree fndecl,gimple * stmt,tree arg,tree ptr)394 maybe_warn_read_write_only (tree fndecl, gimple *stmt, tree arg, tree ptr)
395 {
396   if (!fndecl)
397     return;
398 
399   if (get_no_uninit_warning (arg))
400     return;
401 
402   tree fntype = TREE_TYPE (fndecl);
403   if (!fntype)
404     return;
405 
406   /* Initialize a map of attribute access specifications for arguments
407      to the function call.  */
408   rdwr_map rdwr_idx;
409   init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype));
410 
411   unsigned argno = 0;
412   tree parms = DECL_ARGUMENTS (fndecl);
413   for (tree parm = parms; parm; parm = TREE_CHAIN (parm), ++argno)
414     {
415       if (parm != arg)
416 	continue;
417 
418       const attr_access* access = rdwr_idx.get (argno);
419       if (!access)
420 	break;
421 
422       if (access->mode != access_none
423 	  && access->mode != access_write_only)
424 	continue;
425 
426       location_t stmtloc
427 	= linemap_resolve_location (line_table, gimple_location (stmt),
428 				    LRK_SPELLING_LOCATION, NULL);
429 
430       if (!warning_at (stmtloc, OPT_Wmaybe_uninitialized,
431 		       "%qE may be used uninitialized", ptr))
432 	break;
433 
434       suppress_warning (arg, OPT_Wmaybe_uninitialized);
435 
436       const char* const access_str =
437 	TREE_STRING_POINTER (access->to_external_string ());
438 
439       location_t parmloc = DECL_SOURCE_LOCATION (parm);
440       inform (parmloc, "accessing argument %u of a function declared with "
441 	      "attribute %<%s%>",
442 	      argno + 1, access_str);
443 
444       break;
445     }
446 }
447 
448 /* Callback for walk_aliased_vdefs.  */
449 
450 static bool
check_defs(ao_ref * ref,tree vdef,void * data_)451 check_defs (ao_ref *ref, tree vdef, void *data_)
452 {
453   check_defs_data *data = (check_defs_data *)data_;
454   gimple *def_stmt = SSA_NAME_DEF_STMT (vdef);
455 
456   /* Ignore the vdef if the definition statement is a call
457      to .DEFERRED_INIT function.  */
458   if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
459     return false;
460 
461   /* For address taken variable, a temporary variable is added between
462      the variable and the call to .DEFERRED_INIT function as:
463       _1 = .DEFERRED_INIT (4, 2, &"i1"[0]);
464       i1 = _1;
465      Ignore this vdef as well.  */
466   if (is_gimple_assign (def_stmt)
467       && gimple_assign_rhs_code (def_stmt) == SSA_NAME)
468     {
469       tree tmp_var = gimple_assign_rhs1 (def_stmt);
470       if (gimple_call_internal_p (SSA_NAME_DEF_STMT (tmp_var),
471 				  IFN_DEFERRED_INIT))
472 	return false;
473     }
474 
475   /* The ASAN_MARK intrinsic doesn't modify the variable.  */
476   if (is_gimple_call (def_stmt))
477     {
478       /* The ASAN_MARK intrinsic doesn't modify the variable.  */
479       if (gimple_call_internal_p (def_stmt)
480 	  && gimple_call_internal_fn (def_stmt) == IFN_ASAN_MARK)
481 	return false;
482 
483       if (tree fndecl = gimple_call_fndecl (def_stmt))
484 	{
485 	  /* Some sanitizer calls pass integer arguments to built-ins
486 	     that expect pointets. Avoid using gimple_call_builtin_p()
487 	     which fails for such calls.  */
488 	  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
489 	    {
490 	      built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
491 	      if (fncode > BEGIN_SANITIZER_BUILTINS
492 		  && fncode < END_SANITIZER_BUILTINS)
493 		return false;
494 	    }
495 	}
496     }
497 
498   /* End of VLA scope is not a kill.  */
499   if (gimple_call_builtin_p (def_stmt, BUILT_IN_STACK_RESTORE))
500     return false;
501 
502   /* If this is a clobber then if it is not a kill walk past it.  */
503   if (gimple_clobber_p (def_stmt))
504     {
505       if (stmt_kills_ref_p (def_stmt, ref))
506 	return true;
507       return false;
508     }
509 
510   if (builtin_call_nomodifying_p (def_stmt))
511     return false;
512 
513   /* Found a may-def on this path.  */
514   data->found_may_defs = true;
515   return true;
516 }
517 
518 /* Counters and limits controlling the depth of analysis and
519    strictness of the warning.  */
520 struct wlimits
521 {
522   /* Number of VDEFs encountered.  */
523   unsigned int vdef_cnt;
524   /* Number of statements examined by walk_aliased_vdefs.  */
525   unsigned int oracle_cnt;
526   /* Limit on the number of statements visited by walk_aliased_vdefs.  */
527   unsigned limit;
528   /* Set when basic block with statement is executed unconditionally.  */
529   bool always_executed;
530   /* Set to issue -Wmaybe-uninitialized.  */
531   bool wmaybe_uninit;
532 };
533 
534 /* Determine if REF references an uninitialized operand and diagnose
535    it if so.  STMS is the referencing statement.  LHS is the result
536    of the access and may be null.  RHS is the variable referenced by
537    the access; it may not be null.  */
538 
539 static tree
maybe_warn_operand(ao_ref & ref,gimple * stmt,tree lhs,tree rhs,wlimits & wlims)540 maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
541 		    wlimits &wlims)
542 {
543   bool has_bit_insert = false;
544   use_operand_p luse_p;
545   imm_use_iterator liter;
546 
547   if (get_no_uninit_warning (rhs))
548     return NULL_TREE;
549 
550   /* Do not warn if the base was marked so or this is a
551      hard register var.  */
552   tree base = ao_ref_base (&ref);
553   if ((VAR_P (base)
554        && DECL_HARD_REGISTER (base))
555       || get_no_uninit_warning (base))
556     return NULL_TREE;
557 
558   /* Do not warn if the access is zero size or if it's fully outside
559      the object.  */
560   poly_int64 decl_size;
561   if (known_size_p (ref.size)
562       && known_eq (ref.max_size, ref.size)
563       && (known_eq (ref.size, 0)
564 	  || known_le (ref.offset + ref.size, 0)))
565     return NULL_TREE;
566 
567   if (DECL_P (base)
568       && known_ge (ref.offset, 0)
569       && DECL_SIZE (base)
570       && poly_int_tree_p (DECL_SIZE (base), &decl_size)
571       && known_le (decl_size, ref.offset))
572     return NULL_TREE;
573 
574   /* Do not warn if the result of the access is then used for
575      a BIT_INSERT_EXPR. */
576   if (lhs && TREE_CODE (lhs) == SSA_NAME)
577     FOR_EACH_IMM_USE_FAST (luse_p, liter, lhs)
578       {
579 	gimple *use_stmt = USE_STMT (luse_p);
580 	/* BIT_INSERT_EXPR first operand should not be considered
581 	   a use for the purpose of uninit warnings.  */
582 	if (gassign *ass = dyn_cast <gassign *> (use_stmt))
583 	  {
584 	    if (gimple_assign_rhs_code (ass) == BIT_INSERT_EXPR
585 		&& luse_p->use == gimple_assign_rhs1_ptr (ass))
586 	      {
587 		has_bit_insert = true;
588 		break;
589 	      }
590 	  }
591       }
592 
593   if (has_bit_insert)
594     return NULL_TREE;
595 
596   /* Limit the walking to a constant number of stmts after
597      we overcommit quadratic behavior for small functions
598      and O(n) behavior.  */
599   if (wlims.oracle_cnt > 128 * 128
600       && wlims.oracle_cnt > wlims.vdef_cnt * 2)
601     wlims.limit = 32;
602 
603   check_defs_data data;
604   bool fentry_reached = false;
605   data.found_may_defs = false;
606   tree use = gimple_vuse (stmt);
607   if (!use)
608     return NULL_TREE;
609   int res = walk_aliased_vdefs (&ref, use,
610 				check_defs, &data, NULL,
611 				&fentry_reached, wlims.limit);
612   if (res == -1)
613     {
614       wlims.oracle_cnt += wlims.limit;
615       return NULL_TREE;
616     }
617 
618   wlims.oracle_cnt += res;
619   if (data.found_may_defs)
620     return NULL_TREE;
621 
622   bool found_alloc = false;
623 
624   if (fentry_reached)
625     {
626       if (TREE_CODE (base) == MEM_REF)
627 	base = TREE_OPERAND (base, 0);
628 
629       /* Follow the chain of SSA_NAME assignments looking for an alloca
630 	 call (or VLA) or malloc/realloc, or for decls.  If any is found
631 	 (and in the latter case, the operand is a local variable) issue
632 	 a warning.  */
633       while (TREE_CODE (base) == SSA_NAME)
634 	{
635 	  gimple *def_stmt = SSA_NAME_DEF_STMT (base);
636 
637 	  if (is_gimple_call (def_stmt)
638 	      && gimple_call_builtin_p (def_stmt))
639 	    {
640 	      /* Detect uses of uninitialized alloca/VLAs.  */
641 	      tree fndecl = gimple_call_fndecl (def_stmt);
642 	      const built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
643 	      if (fncode == BUILT_IN_ALLOCA
644 		  || fncode  == BUILT_IN_ALLOCA_WITH_ALIGN
645 		  || fncode  == BUILT_IN_MALLOC)
646 		found_alloc = true;
647 	      break;
648 	    }
649 
650 	  if (!is_gimple_assign (def_stmt))
651 	    break;
652 
653 	  tree_code code = gimple_assign_rhs_code (def_stmt);
654 	  if (code != ADDR_EXPR && code != POINTER_PLUS_EXPR)
655 	    break;
656 
657 	  base = gimple_assign_rhs1 (def_stmt);
658 	  if (TREE_CODE (base) == ADDR_EXPR)
659 	    base = TREE_OPERAND (base, 0);
660 
661 	  if (DECL_P (base)
662 	      || TREE_CODE (base) == COMPONENT_REF)
663 	    rhs = base;
664 
665 	  if (TREE_CODE (base) == MEM_REF)
666 	    base = TREE_OPERAND (base, 0);
667 
668 	  if (tree ba = get_base_address (base))
669 	    base = ba;
670 	}
671 
672       /* Replace the RHS expression with BASE so that it
673 	 refers to it in the diagnostic (instead of to
674 	 '<unknown>').  */
675       if (DECL_P (base)
676 	  && EXPR_P (rhs)
677 	  && TREE_CODE (rhs) != COMPONENT_REF)
678 	rhs = base;
679     }
680 
681   /* Do not warn if it can be initialized outside this function.
682      If we did not reach function entry then we found killing
683      clobbers on all paths to entry.  */
684   if (!found_alloc && fentry_reached)
685     {
686       if (TREE_CODE (base) == SSA_NAME)
687 	{
688 	  tree var = SSA_NAME_VAR (base);
689 	  if (var && TREE_CODE (var) == PARM_DECL)
690 	    {
691 	      maybe_warn_read_write_only (cfun->decl, stmt, var, rhs);
692 	      return NULL_TREE;
693 	    }
694 	}
695 
696       if (!VAR_P (base)
697 	  || is_global_var (base))
698 	/* ???  We'd like to use ref_may_alias_global_p but that
699 	   excludes global readonly memory and thus we get bogus
700 	   warnings from p = cond ? "a" : "b" for example.  */
701 	return NULL_TREE;
702     }
703 
704   /* Strip the address-of expression from arrays passed to functions. */
705   if (TREE_CODE (rhs) == ADDR_EXPR)
706     rhs = TREE_OPERAND (rhs, 0);
707 
708   /* Check again since RHS may have changed above.  */
709   if (get_no_uninit_warning (rhs))
710     return NULL_TREE;
711 
712   /* Avoid warning about empty types such as structs with no members.
713      The first_field() test is important for C++ where the predicate
714      alone isn't always sufficient.  */
715   tree rhstype = TREE_TYPE (rhs);
716   if (POINTER_TYPE_P (rhstype))
717     rhstype = TREE_TYPE (rhstype);
718   if (is_empty_type (rhstype))
719     return NULL_TREE;
720 
721   bool warned = false;
722   /* We didn't find any may-defs so on all paths either
723      reached function entry or a killing clobber.  */
724   location_t location
725     = linemap_resolve_location (line_table, gimple_location (stmt),
726 				LRK_SPELLING_LOCATION, NULL);
727   if (wlims.always_executed)
728     {
729       if (warning_at (location, OPT_Wuninitialized,
730 		      "%qE is used uninitialized", rhs))
731 	{
732 	  /* ???  This is only effective for decls as in
733 	     gcc.dg/uninit-B-O0.c.  Avoid doing this for maybe-uninit
734 	     uses or accesses by functions as it may hide important
735 	     locations.  */
736 	  if (lhs)
737 	    set_no_uninit_warning (rhs);
738 	  warned = true;
739 	}
740     }
741   else if (wlims.wmaybe_uninit)
742     warned = warning_at (location, OPT_Wmaybe_uninitialized,
743 			 "%qE may be used uninitialized", rhs);
744 
745   return warned ? base : NULL_TREE;
746 }
747 
748 
749 /* Diagnose passing addresses of uninitialized objects to either const
750    pointer arguments to functions, or to functions declared with attribute
751    access implying read access to those objects.  */
752 
753 static void
maybe_warn_pass_by_reference(gcall * stmt,wlimits & wlims)754 maybe_warn_pass_by_reference (gcall *stmt, wlimits &wlims)
755 {
756   if (!wlims.wmaybe_uninit)
757     return;
758 
759   unsigned nargs = gimple_call_num_args (stmt);
760   if (!nargs)
761     return;
762 
763   tree fndecl = gimple_call_fndecl (stmt);
764   tree fntype = gimple_call_fntype (stmt);
765   if (!fntype)
766     return;
767 
768   /* Const function do not read their arguments.  */
769   if (gimple_call_flags (stmt) & ECF_CONST)
770     return;
771 
772   const built_in_function fncode
773     = (fndecl && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
774        ? DECL_FUNCTION_CODE (fndecl) : (built_in_function)BUILT_IN_LAST);
775 
776   if (fncode == BUILT_IN_MEMCPY || fncode == BUILT_IN_MEMMOVE)
777     /* Avoid diagnosing calls to raw memory functions (this is overly
778        permissive; consider tightening it up).  */
779     return;
780 
781   /* Save the current warning setting and replace it either a "maybe"
782      when passing addresses of uninitialized variables to const-qualified
783      pointers or arguments declared with attribute read_write, or with
784      a "certain" when passing them to arguments declared with attribute
785      read_only.  */
786   const bool save_always_executed = wlims.always_executed;
787 
788   /* Initialize a map of attribute access specifications for arguments
789      to the function call.  */
790   rdwr_map rdwr_idx;
791   init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype));
792 
793   tree argtype;
794   unsigned argno = 0;
795   function_args_iterator it;
796 
797   FOREACH_FUNCTION_ARGS (fntype, argtype, it)
798     {
799       ++argno;
800 
801       if (argno > nargs)
802 	break;
803 
804       if (!POINTER_TYPE_P (argtype))
805 	continue;
806 
807       tree access_size = NULL_TREE;
808       const attr_access* access = rdwr_idx.get (argno - 1);
809       if (access)
810 	{
811 	  if (access->mode == access_none
812 	      || access->mode == access_write_only)
813 	    continue;
814 
815 	  if (access->mode == access_deferred
816 	      && !TYPE_READONLY (TREE_TYPE (argtype)))
817 	    continue;
818 
819 	  if (save_always_executed && access->mode == access_read_only)
820 	    /* Attribute read_only arguments imply read access.  */
821 	    wlims.always_executed = true;
822 	  else
823 	    /* Attribute read_write arguments are documented as requiring
824 	       initialized objects but it's expected that aggregates may
825 	       be only partially initialized regardless.  */
826 	    wlims.always_executed = false;
827 
828 	  if (access->sizarg < nargs)
829 	    access_size = gimple_call_arg (stmt, access->sizarg);
830 	}
831       else if (!TYPE_READONLY (TREE_TYPE (argtype)))
832 	continue;
833       else if (save_always_executed && fncode != BUILT_IN_LAST)
834 	/* Const-qualified arguments to built-ins imply read access.  */
835 	wlims.always_executed = true;
836       else
837 	/* Const-qualified arguments to ordinary functions imply a likely
838 	   (but not definitive) read access.  */
839 	wlims.always_executed = false;
840 
841       /* Ignore args we are not going to read from.  */
842       if (gimple_call_arg_flags (stmt, argno - 1)
843 	  & (EAF_UNUSED | EAF_NO_DIRECT_READ))
844 	continue;
845 
846       tree arg = gimple_call_arg (stmt, argno - 1);
847       if (!POINTER_TYPE_P (TREE_TYPE (arg)))
848 	/* Avoid actual arguments with invalid types.  */
849 	continue;
850 
851       ao_ref ref;
852       ao_ref_init_from_ptr_and_size (&ref, arg, access_size);
853       tree argbase = maybe_warn_operand (ref, stmt, NULL_TREE, arg, wlims);
854       if (!argbase)
855 	continue;
856 
857       if (access && access->mode != access_deferred)
858 	{
859 	  const char* const access_str =
860 	    TREE_STRING_POINTER (access->to_external_string ());
861 
862 	  if (fndecl)
863 	    {
864 	      location_t loc = DECL_SOURCE_LOCATION (fndecl);
865 	      inform (loc, "in a call to %qD declared with "
866 		      "attribute %<%s%> here", fndecl, access_str);
867 	    }
868 	  else
869 	    {
870 	      /* Handle calls through function pointers.  */
871 	      location_t loc = gimple_location (stmt);
872 	      inform (loc, "in a call to %qT declared with "
873 		      "attribute %<%s%>", fntype, access_str);
874 	    }
875 	}
876       else
877 	{
878 	  /* For a declaration with no relevant attribute access create
879 	     a dummy object and use the formatting function to avoid
880 	     having to complicate things here.  */
881 	  attr_access ptr_access = { };
882 	  if (!access)
883 	    access = &ptr_access;
884 	  const std::string argtypestr = access->array_as_string (argtype);
885 	  if (fndecl)
886 	    {
887 	      location_t loc (DECL_SOURCE_LOCATION (fndecl));
888 	      inform (loc, "by argument %u of type %s to %qD "
889 		      "declared here",
890 		      argno, argtypestr.c_str (), fndecl);
891 	    }
892 	  else
893 	    {
894 	      /* Handle calls through function pointers.  */
895 	      location_t loc (gimple_location (stmt));
896 	      inform (loc, "by argument %u of type %s to %qT",
897 		      argno, argtypestr.c_str (), fntype);
898 	    }
899 	}
900 
901       if (DECL_P (argbase))
902 	{
903 	  location_t loc = DECL_SOURCE_LOCATION (argbase);
904 	  inform (loc, "%qD declared here", argbase);
905 	}
906     }
907 
908   wlims.always_executed = save_always_executed;
909 }
910 
911 /* Warn about an uninitialized PHI argument on the fallthru path to
912    an always executed block BB.  */
913 
914 static void
warn_uninit_phi_uses(basic_block bb)915 warn_uninit_phi_uses (basic_block bb)
916 {
917   edge_iterator ei;
918   edge e, found = NULL, found_back = NULL;
919   /* Look for a fallthru and possibly a single backedge.  */
920   FOR_EACH_EDGE (e, ei, bb->preds)
921     {
922       /* Ignore backedges.  */
923       if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
924 	{
925 	  if (found_back)
926 	    {
927 	      found = NULL;
928 	      break;
929 	    }
930 	  found_back = e;
931 	  continue;
932 	}
933       if (found)
934 	{
935 	  found = NULL;
936 	  break;
937 	}
938       found = e;
939     }
940   if (!found)
941     return;
942 
943   basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
944   for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
945        gsi_next (&si))
946     {
947       gphi *phi = si.phi ();
948       tree def = PHI_ARG_DEF_FROM_EDGE (phi, found);
949       if (TREE_CODE (def) != SSA_NAME
950 	  || !SSA_NAME_IS_DEFAULT_DEF (def)
951 	  || virtual_operand_p (def))
952 	continue;
953       /* If there's a default def on the fallthru edge PHI
954 	 value and there's a use that post-dominates entry
955 	 then that use is uninitialized and we can warn.  */
956       imm_use_iterator iter;
957       use_operand_p use_p;
958       gimple *use_stmt = NULL;
959       FOR_EACH_IMM_USE_FAST (use_p, iter, gimple_phi_result (phi))
960 	{
961 	  use_stmt = USE_STMT (use_p);
962 	  if (gimple_location (use_stmt) != UNKNOWN_LOCATION
963 	      && dominated_by_p (CDI_POST_DOMINATORS, succ,
964 				 gimple_bb (use_stmt))
965 	      /* If we found a non-fallthru edge make sure the
966 		 use is inside the loop, otherwise the backedge
967 		 can serve as initialization.  */
968 	      && (!found_back
969 		  || dominated_by_p (CDI_DOMINATORS, found_back->src,
970 				     gimple_bb (use_stmt))))
971 	    break;
972 	  use_stmt = NULL;
973 	}
974       if (use_stmt)
975 	warn_uninit (OPT_Wuninitialized, def,
976 		     SSA_NAME_VAR (def), use_stmt);
977     }
978 }
979 
980 /* Issue warnings about reads of uninitialized variables.  WMAYBE_UNINIT
981    is true to issue -Wmaybe-uninitialized, otherwise -Wuninitialized.  */
982 
983 static void
warn_uninitialized_vars(bool wmaybe_uninit)984 warn_uninitialized_vars (bool wmaybe_uninit)
985 {
986   /* Counters and limits controlling the depth of the warning.  */
987   wlimits wlims = { };
988   wlims.wmaybe_uninit = wmaybe_uninit;
989 
990   gimple_stmt_iterator gsi;
991   basic_block bb;
992   FOR_EACH_BB_FN (bb, cfun)
993     {
994       edge_iterator ei;
995       edge e;
996       FOR_EACH_EDGE (e, ei, bb->preds)
997 	if (e->flags & EDGE_EXECUTABLE)
998 	  break;
999       /* Skip unreachable blocks.  For early analysis we use VN to
1000 	 determine edge executability when wmaybe_uninit.  */
1001       if (!e)
1002 	continue;
1003 
1004       basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
1005       /* ???  This could be improved when we use a greedy walk and have
1006 	 some edges marked as not executable.  */
1007       wlims.always_executed = dominated_by_p (CDI_POST_DOMINATORS, succ, bb);
1008 
1009       if (wlims.always_executed)
1010 	warn_uninit_phi_uses (bb);
1011 
1012       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1013 	{
1014 	  gimple *stmt = gsi_stmt (gsi);
1015 
1016 	  /* The call is an artificial use, will not provide meaningful
1017 	     error message.  If the result of the call is used somewhere
1018 	     else, we warn there instead.  */
1019 	  if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
1020 	    continue;
1021 
1022 	  if (is_gimple_debug (stmt))
1023 	    continue;
1024 
1025 	  /* We only do data flow with SSA_NAMEs, so that's all we
1026 	     can warn about.  */
1027 	  use_operand_p use_p;
1028 	  ssa_op_iter op_iter;
1029 	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, op_iter, SSA_OP_USE)
1030 	    {
1031 	      /* BIT_INSERT_EXPR first operand should not be considered
1032 	         a use for the purpose of uninit warnings.  */
1033 	      if (gassign *ass = dyn_cast <gassign *> (stmt))
1034 		{
1035 		  if (gimple_assign_rhs_code (ass) == BIT_INSERT_EXPR
1036 		      && use_p->use == gimple_assign_rhs1_ptr (ass))
1037 		    continue;
1038 		}
1039 	      tree use = USE_FROM_PTR (use_p);
1040 	      if (wlims.always_executed)
1041 		warn_uninit (OPT_Wuninitialized, use,
1042 			     SSA_NAME_VAR (use), stmt);
1043 	      else if (wmaybe_uninit)
1044 		warn_uninit (OPT_Wmaybe_uninitialized, use,
1045 			     SSA_NAME_VAR (use), stmt);
1046 	    }
1047 
1048 	  /* For limiting the alias walk below we count all
1049 	     vdefs in the function.  */
1050 	  if (gimple_vdef (stmt))
1051 	    wlims.vdef_cnt++;
1052 
1053 	  if (gcall *call = dyn_cast <gcall *> (stmt))
1054 	    maybe_warn_pass_by_reference (call, wlims);
1055 	  else if (gimple_assign_load_p (stmt)
1056 		   && gimple_has_location (stmt))
1057 	    {
1058 	      tree rhs = gimple_assign_rhs1 (stmt);
1059 	      tree lhs = gimple_assign_lhs (stmt);
1060 
1061 	      ao_ref ref;
1062 	      ao_ref_init (&ref, rhs);
1063 	      tree var = maybe_warn_operand (ref, stmt, lhs, rhs, wlims);
1064 	      if (!var)
1065 		continue;
1066 
1067 	      if (DECL_P (var))
1068 		{
1069 		  location_t loc = DECL_SOURCE_LOCATION (var);
1070 		  inform (loc, "%qD declared here", var);
1071 		}
1072 	    }
1073 	}
1074     }
1075 }
1076 
1077 /* Checks if the operand OPND of PHI is defined by
1078    another phi with one operand defined by this PHI,
1079    but the rest operands are all defined.  If yes,
1080    returns true to skip this operand as being
1081    redundant.  Can be enhanced to be more general.  */
1082 
1083 static bool
can_skip_redundant_opnd(tree opnd,gimple * phi)1084 can_skip_redundant_opnd (tree opnd, gimple *phi)
1085 {
1086   tree phi_def = gimple_phi_result (phi);
1087   gimple *op_def = SSA_NAME_DEF_STMT (opnd);
1088   if (gimple_code (op_def) != GIMPLE_PHI)
1089     return false;
1090 
1091   unsigned n = gimple_phi_num_args (op_def);
1092   for (unsigned i = 0; i < n; ++i)
1093     {
1094       tree op = gimple_phi_arg_def (op_def, i);
1095       if (TREE_CODE (op) != SSA_NAME)
1096 	continue;
1097       if (op != phi_def && uninit_undefined_value_p (op))
1098 	return false;
1099     }
1100 
1101   return true;
1102 }
1103 
1104 /* Return a bitset holding the positions of arguments in PHI with empty
1105    (or possibly empty) definitions.  */
1106 
1107 static unsigned
compute_uninit_opnds_pos(gphi * phi)1108 compute_uninit_opnds_pos (gphi *phi)
1109 {
1110   unsigned uninit_opnds = 0;
1111 
1112   unsigned n = gimple_phi_num_args (phi);
1113   /* Bail out for phi with too many args.  */
1114   if (n > predicate::func_t::max_phi_args)
1115     return 0;
1116 
1117   for (unsigned i = 0; i < n; ++i)
1118     {
1119       tree op = gimple_phi_arg_def (phi, i);
1120       if (TREE_CODE (op) == SSA_NAME
1121 	  && uninit_undefined_value_p (op)
1122 	  && !can_skip_redundant_opnd (op, phi))
1123 	{
1124 	  if (cfun->has_nonlocal_label || cfun->calls_setjmp)
1125 	    {
1126 	      /* Ignore SSA_NAMEs that appear on abnormal edges
1127 		 somewhere.  */
1128 	      if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
1129 		continue;
1130 	    }
1131 	  MASK_SET_BIT (uninit_opnds, i);
1132 	}
1133     }
1134   return uninit_opnds;
1135 }
1136 
1137 /* Function object type used to determine whether an expression
1138    is of interest to the predicate analyzer.  */
1139 
1140 struct uninit_undef_val_t: public predicate::func_t
1141 {
1142   virtual bool operator()(tree) override;
1143   virtual unsigned phi_arg_set (gphi *) override;
1144 };
1145 
1146 /* Return true if the argument is an expression of interest.  */
1147 
1148 bool
operator ()(tree val)1149 uninit_undef_val_t::operator()(tree val)
1150 {
1151   if (TREE_CODE (val) == SSA_NAME)
1152     return uninit_undefined_value_p (val);
1153 
1154   return false;
1155 }
1156 
1157 /* Return a bitset of PHI arguments of interest.  */
1158 
1159 unsigned
phi_arg_set(gphi * phi)1160 uninit_undef_val_t::phi_arg_set (gphi *phi)
1161 {
1162   return compute_uninit_opnds_pos (phi);
1163 }
1164 
1165 /* Searches through all uses of a potentially
1166    uninitialized variable defined by PHI and returns a use
1167    statement if the use is not properly guarded.  It returns
1168    NULL if all uses are guarded.  UNINIT_OPNDS is a bitvector
1169    holding the position(s) of uninit PHI operands.  WORKLIST
1170    is the vector of candidate phis that may be updated by this
1171    function.  ADDED_TO_WORKLIST is the pointer set tracking
1172    if the new phi is already in the worklist.  */
1173 
1174 static gimple *
find_uninit_use(gphi * phi,unsigned uninit_opnds,vec<gphi * > * worklist,hash_set<gphi * > * added_to_worklist)1175 find_uninit_use (gphi *phi, unsigned uninit_opnds,
1176 		 vec<gphi *> *worklist, hash_set<gphi *> *added_to_worklist)
1177 {
1178   /* The Boolean predicate guarding the PHI definition.  Initialized
1179      lazily from PHI in the first call to is_use_guarded() and cached
1180      for subsequent iterations.  */
1181   uninit_undef_val_t eval;
1182   predicate def_preds (eval);
1183 
1184   use_operand_p use_p;
1185   imm_use_iterator iter;
1186   tree phi_result = gimple_phi_result (phi);
1187   FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
1188     {
1189       gimple *use_stmt = USE_STMT (use_p);
1190       if (is_gimple_debug (use_stmt))
1191 	continue;
1192 
1193       basic_block use_bb;
1194       if (gphi *use_phi = dyn_cast<gphi *> (use_stmt))
1195 	{
1196 	  edge e = gimple_phi_arg_edge (use_phi,
1197 					PHI_ARG_INDEX_FROM_USE (use_p));
1198 	  use_bb = e->src;
1199 	  /* Do not look for uses in the next iteration of a loop, predicate
1200 	     analysis will not use the appropriate predicates to prove
1201 	     reachability.  */
1202 	  if (e->flags & EDGE_DFS_BACK)
1203 	    continue;
1204 	}
1205       else
1206 	use_bb = gimple_bb (use_stmt);
1207 
1208       if (def_preds.is_use_guarded (use_stmt, use_bb, phi, uninit_opnds))
1209 	continue;
1210 
1211       if (dump_file && (dump_flags & TDF_DETAILS))
1212 	{
1213 	  fprintf (dump_file, "Found unguarded use in bb %u: ",
1214 		   use_bb->index);
1215 	  print_gimple_stmt (dump_file, use_stmt, 0);
1216 	}
1217       /* Found one real use, return.  */
1218       if (gimple_code (use_stmt) != GIMPLE_PHI)
1219 	return use_stmt;
1220 
1221       /* Found a phi use that is not guarded,
1222 	 add the phi to the worklist.  */
1223       if (!added_to_worklist->add (as_a<gphi *> (use_stmt)))
1224 	{
1225 	  if (dump_file && (dump_flags & TDF_DETAILS))
1226 	    {
1227 	      fprintf (dump_file, "[WORKLIST]: Update worklist with phi: ");
1228 	      print_gimple_stmt (dump_file, use_stmt, 0);
1229 	    }
1230 
1231 	  worklist->safe_push (as_a<gphi *> (use_stmt));
1232 	  possibly_undefined_names->add (phi_result);
1233 	}
1234     }
1235 
1236   return NULL;
1237 }
1238 
1239 /* Look for inputs to PHI that are SSA_NAMEs that have empty definitions
1240    and gives warning if there exists a runtime path from the entry to a
1241    use of the PHI def that does not contain a definition.  In other words,
1242    the warning is on the real use.  The more dead paths that can be pruned
1243    by the compiler, the fewer false positives the warning is.  WORKLIST
1244    is a vector of candidate phis to be examined.  ADDED_TO_WORKLIST is
1245    a pointer set tracking if the new phi is added to the worklist or not.  */
1246 
1247 static void
warn_uninitialized_phi(gphi * phi,vec<gphi * > * worklist,hash_set<gphi * > * added_to_worklist)1248 warn_uninitialized_phi (gphi *phi, vec<gphi *> *worklist,
1249 			hash_set<gphi *> *added_to_worklist)
1250 {
1251   /* Don't look at virtual operands.  */
1252   if (virtual_operand_p (gimple_phi_result (phi)))
1253     return;
1254 
1255   unsigned uninit_opnds = compute_uninit_opnds_pos (phi);
1256   if (MASK_EMPTY (uninit_opnds))
1257     return;
1258 
1259   if (dump_file && (dump_flags & TDF_DETAILS))
1260     {
1261       fprintf (dump_file, "Examining phi: ");
1262       print_gimple_stmt (dump_file, phi, 0);
1263     }
1264 
1265   gimple *uninit_use_stmt = find_uninit_use (phi, uninit_opnds,
1266 					     worklist, added_to_worklist);
1267 
1268   /* All uses are properly guarded but a new PHI may have been added
1269      to WORKLIST.  */
1270   if (!uninit_use_stmt)
1271     return;
1272 
1273   unsigned phiarg_index = MASK_FIRST_SET_BIT (uninit_opnds);
1274   tree uninit_op = gimple_phi_arg_def (phi, phiarg_index);
1275   if (SSA_NAME_VAR (uninit_op) == NULL_TREE)
1276     return;
1277 
1278   location_t loc = UNKNOWN_LOCATION;
1279   if (gimple_phi_arg_has_location (phi, phiarg_index))
1280     loc = gimple_phi_arg_location (phi, phiarg_index);
1281   else
1282     {
1283       tree arg_def = gimple_phi_arg_def (phi, phiarg_index);
1284       if (TREE_CODE (arg_def) == SSA_NAME)
1285 	{
1286 	  gimple *def_stmt = SSA_NAME_DEF_STMT (arg_def);
1287 	  if (gphi *arg_phi = dyn_cast<gphi *> (def_stmt))
1288 	    {
1289 	      unsigned uop = compute_uninit_opnds_pos (arg_phi);
1290 	      unsigned idx = MASK_FIRST_SET_BIT (uop);
1291 	      if (idx < gimple_phi_num_args (arg_phi)
1292 		  && gimple_phi_arg_has_location (arg_phi, idx))
1293 		loc = gimple_phi_arg_location (arg_phi, idx);
1294 	    }
1295 	}
1296     }
1297 
1298   warn_uninit (OPT_Wmaybe_uninitialized, uninit_op,
1299 	       SSA_NAME_VAR (uninit_op),
1300 	       uninit_use_stmt, loc);
1301 }
1302 
1303 static bool
gate_warn_uninitialized(void)1304 gate_warn_uninitialized (void)
1305 {
1306   return warn_uninitialized || warn_maybe_uninitialized;
1307 }
1308 
1309 namespace {
1310 
1311 const pass_data pass_data_late_warn_uninitialized =
1312 {
1313   GIMPLE_PASS, /* type */
1314   "uninit", /* name */
1315   OPTGROUP_NONE, /* optinfo_flags */
1316   TV_NONE, /* tv_id */
1317   PROP_ssa, /* properties_required */
1318   0, /* properties_provided */
1319   0, /* properties_destroyed */
1320   0, /* todo_flags_start */
1321   0, /* todo_flags_finish */
1322 };
1323 
1324 class pass_late_warn_uninitialized : public gimple_opt_pass
1325 {
1326 public:
pass_late_warn_uninitialized(gcc::context * ctxt)1327   pass_late_warn_uninitialized (gcc::context *ctxt)
1328     : gimple_opt_pass (pass_data_late_warn_uninitialized, ctxt)
1329   {}
1330 
1331   /* opt_pass methods: */
clone()1332   opt_pass *clone () { return new pass_late_warn_uninitialized (m_ctxt); }
gate(function *)1333   virtual bool gate (function *) { return gate_warn_uninitialized (); }
1334   virtual unsigned int execute (function *);
1335 
1336 }; // class pass_late_warn_uninitialized
1337 
1338 static void
execute_late_warn_uninitialized(function * fun)1339 execute_late_warn_uninitialized (function *fun)
1340 {
1341   basic_block bb;
1342   gphi_iterator gsi;
1343   vec<gphi *> worklist = vNULL;
1344 
1345   calculate_dominance_info (CDI_DOMINATORS);
1346   calculate_dominance_info (CDI_POST_DOMINATORS);
1347 
1348   /* Mark all edges executable, warn_uninitialized_vars will skip
1349      unreachable blocks.  */
1350   set_all_edges_as_executable (fun);
1351   mark_dfs_back_edges (fun);
1352 
1353   /* Re-do the plain uninitialized variable check, as optimization may have
1354      straightened control flow.  Do this first so that we don't accidentally
1355      get a "may be" warning when we'd have seen an "is" warning later.  */
1356   warn_uninitialized_vars (/*warn_maybe_uninitialized=*/1);
1357 
1358   timevar_push (TV_TREE_UNINIT);
1359 
1360   possibly_undefined_names = new hash_set<tree>;
1361   hash_set<gphi *> added_to_worklist;
1362 
1363   /* Initialize worklist  */
1364   FOR_EACH_BB_FN (bb, fun)
1365     for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1366       {
1367 	gphi *phi = gsi.phi ();
1368 
1369 	/* Don't look at virtual operands.  */
1370 	if (virtual_operand_p (gimple_phi_result (phi)))
1371 	  continue;
1372 
1373 	unsigned n = gimple_phi_num_args (phi);
1374 	for (unsigned i = 0; i < n; ++i)
1375 	  {
1376 	    tree op = gimple_phi_arg_def (phi, i);
1377 	    if (TREE_CODE (op) == SSA_NAME && uninit_undefined_value_p (op))
1378 	      {
1379 		worklist.safe_push (phi);
1380 		added_to_worklist.add (phi);
1381 		if (dump_file && (dump_flags & TDF_DETAILS))
1382 		  {
1383 		    fprintf (dump_file, "[WORKLIST]: add to initial list "
1384 			     "for operand %u of: ", i);
1385 		    print_gimple_stmt (dump_file, phi, 0);
1386 		  }
1387 		break;
1388 	      }
1389 	  }
1390       }
1391 
1392   while (worklist.length () != 0)
1393     {
1394       gphi *cur_phi = 0;
1395       cur_phi = worklist.pop ();
1396       warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
1397     }
1398 
1399   worklist.release ();
1400   delete possibly_undefined_names;
1401   possibly_undefined_names = NULL;
1402   free_dominance_info (CDI_POST_DOMINATORS);
1403   timevar_pop (TV_TREE_UNINIT);
1404 }
1405 
1406 unsigned int
execute(function * fun)1407 pass_late_warn_uninitialized::execute (function *fun)
1408 {
1409   execute_late_warn_uninitialized (fun);
1410   return 0;
1411 }
1412 
1413 } // anon namespace
1414 
1415 gimple_opt_pass *
make_pass_late_warn_uninitialized(gcc::context * ctxt)1416 make_pass_late_warn_uninitialized (gcc::context *ctxt)
1417 {
1418   return new pass_late_warn_uninitialized (ctxt);
1419 }
1420 
1421 static unsigned int
execute_early_warn_uninitialized(struct function * fun)1422 execute_early_warn_uninitialized (struct function *fun)
1423 {
1424   /* Currently, this pass runs always but
1425      execute_late_warn_uninitialized only runs with optimization.  With
1426      optimization we want to warn about possible uninitialized as late
1427      as possible, thus don't do it here.  However, without
1428      optimization we need to warn here about "may be uninitialized".  */
1429   calculate_dominance_info (CDI_DOMINATORS);
1430   calculate_dominance_info (CDI_POST_DOMINATORS);
1431 
1432   /* Use VN in its cheapest incarnation and without doing any
1433      elimination to compute edge reachability.  Don't bother when
1434      we only warn for unconditionally executed code though.  */
1435   if (!optimize)
1436     {
1437       do_rpo_vn (fun, NULL, NULL, false, false, VN_NOWALK);
1438       free_rpo_vn ();
1439     }
1440   else
1441     set_all_edges_as_executable (fun);
1442 
1443   warn_uninitialized_vars (/*warn_maybe_uninitialized=*/!optimize);
1444 
1445   /* Post-dominator information cannot be reliably updated.  Free it
1446      after the use.  */
1447 
1448   free_dominance_info (CDI_POST_DOMINATORS);
1449   return 0;
1450 }
1451 
1452 namespace {
1453 
1454 const pass_data pass_data_early_warn_uninitialized =
1455 {
1456   GIMPLE_PASS, /* type */
1457   "early_uninit", /* name */
1458   OPTGROUP_NONE, /* optinfo_flags */
1459   TV_TREE_UNINIT, /* tv_id */
1460   PROP_ssa, /* properties_required */
1461   0, /* properties_provided */
1462   0, /* properties_destroyed */
1463   0, /* todo_flags_start */
1464   0, /* todo_flags_finish */
1465 };
1466 
1467 class pass_early_warn_uninitialized : public gimple_opt_pass
1468 {
1469 public:
pass_early_warn_uninitialized(gcc::context * ctxt)1470   pass_early_warn_uninitialized (gcc::context *ctxt)
1471     : gimple_opt_pass (pass_data_early_warn_uninitialized, ctxt)
1472   {}
1473 
1474   /* opt_pass methods: */
gate(function *)1475   virtual bool gate (function *) { return gate_warn_uninitialized (); }
execute(function * fun)1476   virtual unsigned int execute (function *fun)
1477   {
1478     return execute_early_warn_uninitialized (fun);
1479   }
1480 
1481 }; // class pass_early_warn_uninitialized
1482 
1483 } // anon namespace
1484 
1485 gimple_opt_pass *
make_pass_early_warn_uninitialized(gcc::context * ctxt)1486 make_pass_early_warn_uninitialized (gcc::context *ctxt)
1487 {
1488   return new pass_early_warn_uninitialized (ctxt);
1489 }
1490