LCOV - code coverage report
Current view: top level - gcc - tree-ssa-uninit.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.1 % 652 633
Test Date: 2026-07-11 15:47:05 Functions: 100.0 % 27 27
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.