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

Generated by: LCOV version 2.5.0-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.