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

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