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

source code of gcc/tree-ssa-uninit.cc