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