[PATCH] Fix PR50040

Richard Guenther rguenther@suse.de
Thu Aug 11 13:32:00 GMT 2011


This restores some of the uninitialized warnings for memory and
applies some TLC to the machinery.

Any idea why the C++ FE prints that funny setbuf.a::mode instead
of simply setbuf.mode for g++.dg/warn/unit-1.C!?  The latter is
what debug_generic_expr dumps.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Thanks,
Richard.

2011-08-11  Richard Guenther  <rguenther@suse.de>

	PR middle-end/50040
	* gimplify.c (gimplify_modify_expr_complex_part): Mark the
	load of the other piece with TREE_NO_WARNING.
	* tree-flow.h (warn_uninit): Adjust prototype.
	* tree-ssa.c (warn_uninit): Take uninitialized SSA name,
	the base variable and the expression that is used separately.
	Properly query all TREE_NO_WARNING flags.
	(struct walk_data): Remove.
	(warn_uninitialized_var): Likewise.
	(warn_uninitialized_vars): Do not walk gimple pieces but simply
	look at all SSA uses of the statement.  Handle unused memory
	separately.
	* tree-ssa-uninit.c (warn_uninitialized_phi): Adjust.

	* g++.dg/warn/unit-1.C: Un-XFAIL.
	* gcc.dg/uninit-I.c: Likewise.

Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 177649)
--- gcc/gimplify.c	(working copy)
*************** gimplify_modify_expr_complex_part (tree
*** 4483,4488 ****
--- 4483,4489 ----
  
    ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
    other = build1 (ocode, TREE_TYPE (rhs), lhs);
+   TREE_NO_WARNING (other) = 1;
    other = get_formal_tmp_var (other, pre_p);
  
    realpart = code == REALPART_EXPR ? rhs : other;
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h	(revision 177649)
--- gcc/tree-flow.h	(working copy)
*************** extern void flush_pending_stmts (edge);
*** 542,548 ****
  extern void verify_ssa (bool);
  extern void delete_tree_ssa (void);
  extern bool ssa_undefined_value_p (tree);
! extern void warn_uninit (enum opt_code, tree, const char *, void *);
  extern unsigned int warn_uninitialized_vars (bool);
  extern void execute_update_addresses_taken (void);
  
--- 542,548 ----
  extern void verify_ssa (bool);
  extern void delete_tree_ssa (void);
  extern bool ssa_undefined_value_p (tree);
! extern void warn_uninit (enum opt_code, tree, tree, tree, const char *, void *);
  extern unsigned int warn_uninitialized_vars (bool);
  extern void execute_update_addresses_taken (void);
  
Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c	(revision 177649)
--- gcc/tree-ssa.c	(working copy)
*************** walk_use_def_chains (tree var, walk_use_
*** 1652,1665 ****
     again for plain uninitialized variables, since optimization may have
     changed conditionally uninitialized to unconditionally uninitialized.  */
  
! /* Emit a warning for T, an SSA_NAME, being uninitialized.  The exact
     warning text is in MSGID and LOCUS may contain a location or be null.
     WC is the warning code.  */
  
  void
! warn_uninit (enum opt_code wc, tree t, const char *gmsgid, void *data)
  {
-   tree var = SSA_NAME_VAR (t);
    gimple context = (gimple) data;
    location_t location;
    expanded_location xloc, floc;
--- 1652,1666 ----
     again for plain uninitialized variables, since optimization may have
     changed conditionally uninitialized to unconditionally uninitialized.  */
  
! /* Emit a warning for EXPR based on variable VAR at the point in the
!    program T, an SSA_NAME, is used being uninitialized.  The exact
     warning text is in MSGID and LOCUS may contain a location or be null.
     WC is the warning code.  */
  
  void
! warn_uninit (enum opt_code wc, tree t,
! 	     tree expr, tree var, const char *gmsgid, void *data)
  {
    gimple context = (gimple) data;
    location_t location;
    expanded_location xloc, floc;
*************** warn_uninit (enum opt_code wc, tree t, c
*** 1669,1679 ****
  
    /* TREE_NO_WARNING either means we already warned, or the front end
       wishes to suppress the warning.  */
!   if (TREE_NO_WARNING (var))
!     return;
! 
!   /* Do not warn if it can be initialized outside this module.  */
!   if (is_global_var (var))
      return;
  
    location = (context != NULL && gimple_has_location (context))
--- 1670,1680 ----
  
    /* TREE_NO_WARNING either means we already warned, or the front end
       wishes to suppress the warning.  */
!   if ((context
!        && (gimple_no_warning_p (context)
! 	   || (gimple_assign_single_p (context)
! 	       && TREE_NO_WARNING (gimple_assign_rhs1 (context)))))
!       || TREE_NO_WARNING (expr))
      return;
  
    location = (context != NULL && gimple_has_location (context))
*************** warn_uninit (enum opt_code wc, tree t, c
*** 1681,1689 ****
  	     : DECL_SOURCE_LOCATION (var);
    xloc = expand_location (location);
    floc = expand_location (DECL_SOURCE_LOCATION (cfun->decl));
!   if (warning_at (location, wc, gmsgid, var))
      {
!       TREE_NO_WARNING (var) = 1;
  
        if (location == DECL_SOURCE_LOCATION (var))
  	return;
--- 1682,1690 ----
  	     : DECL_SOURCE_LOCATION (var);
    xloc = expand_location (location);
    floc = expand_location (DECL_SOURCE_LOCATION (cfun->decl));
!   if (warning_at (location, wc, gmsgid, expr))
      {
!       TREE_NO_WARNING (expr) = 1;
  
        if (location == DECL_SOURCE_LOCATION (var))
  	return;
*************** warn_uninit (enum opt_code wc, tree t, c
*** 1694,1819 ****
      }
  }
  
- struct walk_data {
-   gimple stmt;
-   bool always_executed;
-   bool warn_possibly_uninitialized;
- };
- 
- /* Called via walk_tree, look for SSA_NAMEs that have empty definitions
-    and warn about them.  */
- 
- static tree
- warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_)
- {
-   struct walk_stmt_info *wi = (struct walk_stmt_info *) data_;
-   struct walk_data *data = (struct walk_data *) wi->info;
-   tree t = *tp;
- 
-   /* We do not care about LHS.  */
-   if (wi->is_lhs)
-     {
-       /* Except for operands of dereferences.  */
-       if (!INDIRECT_REF_P (t)
- 	  && TREE_CODE (t) != MEM_REF)
- 	return NULL_TREE;
-       t = TREE_OPERAND (t, 0);
-     }
- 
-   switch (TREE_CODE (t))
-     {
-     case ADDR_EXPR:
-       /* Taking the address of an uninitialized variable does not
- 	 count as using it.  */
-       *walk_subtrees = 0;
-       break;
- 
-     case VAR_DECL:
-       {
- 	/* A VAR_DECL in the RHS of a gimple statement may mean that
- 	   this variable is loaded from memory.  */
- 	use_operand_p vuse;
- 	tree op;
- 
- 	/* If there is not gimple stmt,
- 	   or alias information has not been computed,
- 	   then we cannot check VUSE ops.  */
- 	if (data->stmt == NULL)
- 	  return NULL_TREE;
- 
- 	/* If the load happens as part of a call do not warn about it.  */
- 	if (is_gimple_call (data->stmt))
- 	  return NULL_TREE;
- 
- 	vuse = gimple_vuse_op (data->stmt);
- 	if (vuse == NULL_USE_OPERAND_P)
- 	  return NULL_TREE;
- 
- 	op = USE_FROM_PTR (vuse);
- 	if (t != SSA_NAME_VAR (op)
- 	    || !SSA_NAME_IS_DEFAULT_DEF (op))
- 	  return NULL_TREE;
- 	/* If this is a VUSE of t and it is the default definition,
- 	   then warn about op.  */
- 	t = op;
- 	/* Fall through into SSA_NAME.  */
-       }
- 
-     case SSA_NAME:
-       /* We only do data flow with SSA_NAMEs, so that's all we
- 	 can warn about.  */
-       if (data->always_executed)
-         warn_uninit (OPT_Wuninitialized,
- 	             t, "%qD is used uninitialized in this function",
- 		     data->stmt);
-       else if (data->warn_possibly_uninitialized)
-         warn_uninit (OPT_Wuninitialized,
- 	             t, "%qD may be used uninitialized in this function",
- 		     data->stmt);
-       *walk_subtrees = 0;
-       break;
- 
-     case REALPART_EXPR:
-     case IMAGPART_EXPR:
-       /* The total store transformation performed during gimplification
- 	 creates uninitialized variable uses.  If all is well, these will
- 	 be optimized away, so don't warn now.  */
-       if (TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME)
- 	*walk_subtrees = 0;
-       break;
- 
-     default:
-       if (IS_TYPE_OR_DECL_P (t))
- 	*walk_subtrees = 0;
-       break;
-     }
- 
-   return NULL_TREE;
- }
- 
  unsigned int
  warn_uninitialized_vars (bool warn_possibly_uninitialized)
  {
    gimple_stmt_iterator gsi;
    basic_block bb;
-   struct walk_data data;
- 
-   data.warn_possibly_uninitialized = warn_possibly_uninitialized;
- 
  
    FOR_EACH_BB (bb)
      {
!       data.always_executed = dominated_by_p (CDI_POST_DOMINATORS,
  					     single_succ (ENTRY_BLOCK_PTR), bb);
        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
  	{
! 	  struct walk_stmt_info wi;
! 	  data.stmt = gsi_stmt (gsi);
! 	  if (is_gimple_debug (data.stmt))
  	    continue;
! 	  memset (&wi, 0, sizeof (wi));
! 	  wi.info = &data;
! 	  walk_gimple_op (gsi_stmt (gsi), warn_uninitialized_var, &wi);
  	}
      }
  
--- 1695,1773 ----
      }
  }
  
  unsigned int
  warn_uninitialized_vars (bool warn_possibly_uninitialized)
  {
    gimple_stmt_iterator gsi;
    basic_block bb;
  
    FOR_EACH_BB (bb)
      {
!       bool always_executed = dominated_by_p (CDI_POST_DOMINATORS,
  					     single_succ (ENTRY_BLOCK_PTR), bb);
        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
  	{
! 	  gimple stmt = gsi_stmt (gsi);
! 	  use_operand_p use_p;
! 	  ssa_op_iter op_iter;
! 	  tree use;
! 
! 	  if (is_gimple_debug (stmt))
  	    continue;
! 
! 	  /* We only do data flow with SSA_NAMEs, so that's all we
! 	     can warn about.  */
! 	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, op_iter, SSA_OP_USE)
! 	    {
! 	      use = USE_FROM_PTR (use_p);
! 	      if (always_executed)
! 		warn_uninit (OPT_Wuninitialized, use,
! 			     SSA_NAME_VAR (use), SSA_NAME_VAR (use),
! 			     "%qD is used uninitialized in this function",
! 			     stmt);
! 	      else if (warn_possibly_uninitialized)
! 		warn_uninit (OPT_Wuninitialized, use,
! 			     SSA_NAME_VAR (use), SSA_NAME_VAR (use),
! 			     "%qD may be used uninitialized in this function",
! 			     stmt);
! 	    }
! 
! 	  /* For memory the only cheap thing we can do is see if we
! 	     have a use of the default def of the virtual operand.
! 	     ???  Note that at -O0 we do not have virtual operands.
! 	     ???  Not so cheap would be to use the alias oracle via
! 	     walk_aliased_vdefs, if we don't find any aliasing vdef
! 	     warn as is-used-uninitialized, if we don't find an aliasing
! 	     vdef that kills our use (stmt_kills_ref_p), warn as
! 	     may-be-used-uninitialized.  But this walk is quadratic and
! 	     so must be limited which means we would miss warning
! 	     opportunities.  */
! 	  use = gimple_vuse (stmt);
! 	  if (use
! 	      && gimple_assign_single_p (stmt)
! 	      && !gimple_vdef (stmt)
! 	      && SSA_NAME_IS_DEFAULT_DEF (use))
! 	    {
! 	      tree rhs = gimple_assign_rhs1 (stmt);
! 	      tree base = get_base_address (rhs);
! 
! 	      /* Do not warn if it can be initialized outside this function.  */
! 	      if (TREE_CODE (base) != VAR_DECL
! 		  || DECL_HARD_REGISTER (base)
! 		  || is_global_var (base))
! 		continue;
! 
! 	      if (always_executed)
! 		warn_uninit (OPT_Wuninitialized, use, gimple_assign_rhs1 (stmt),
! 			     base,
! 			     "%qE is used uninitialized in this function",
! 			     stmt);
! 	      else if (warn_possibly_uninitialized)
! 		warn_uninit (OPT_Wuninitialized, use, gimple_assign_rhs1 (stmt),
! 			     base,
! 			     "%qE may be used uninitialized in this function",
! 			     stmt);
! 	    }
  	}
      }
  
Index: gcc/tree-ssa-uninit.c
===================================================================
*** gcc/tree-ssa-uninit.c	(revision 177649)
--- gcc/tree-ssa-uninit.c	(working copy)
*************** warn_uninitialized_phi (gimple phi, VEC(
*** 1953,1959 ****
      return;
  
    uninit_op = gimple_phi_arg_def (phi, MASK_FIRST_SET_BIT (uninit_opnds));
!   warn_uninit (OPT_Wmaybe_uninitialized, uninit_op,
                 "%qD may be used uninitialized in this function",
                 uninit_use_stmt);
  
--- 1953,1960 ----
      return;
  
    uninit_op = gimple_phi_arg_def (phi, MASK_FIRST_SET_BIT (uninit_opnds));
!   warn_uninit (OPT_Wmaybe_uninitialized, uninit_op, SSA_NAME_VAR (uninit_op),
! 	       SSA_NAME_VAR (uninit_op),
                 "%qD may be used uninitialized in this function",
                 uninit_use_stmt);
  
Index: gcc/testsuite/g++.dg/warn/unit-1.C
===================================================================
*** gcc/testsuite/g++.dg/warn/unit-1.C	(revision 177649)
--- gcc/testsuite/g++.dg/warn/unit-1.C	(working copy)
***************
*** 4,10 ****
  struct a { int mode; };
  int sys_msgctl (void)
  {
!   struct a setbuf;  /* { dg-warning "'setbuf.mode' is used" "" { xfail *-*-* } } */
!   return setbuf.mode;
  }
  
--- 4,10 ----
  struct a { int mode; };
  int sys_msgctl (void)
  {
!   struct a setbuf;
!   return setbuf.mode;  /* { dg-warning "'setbuf.a::mode' is used" "" } */
  }
  
Index: gcc/testsuite/gcc.dg/uninit-I.c
===================================================================
*** gcc/testsuite/gcc.dg/uninit-I.c	(revision 177649)
--- gcc/testsuite/gcc.dg/uninit-I.c	(working copy)
***************
*** 3,8 ****
  
  int sys_msgctl (void)
  {
!   struct { int mode; } setbuf;  /* { dg-warning "'setbuf\.mode' is used" "" { xfail *-*-* } } */
!   return setbuf.mode;
  }
--- 3,8 ----
  
  int sys_msgctl (void)
  {
!   struct { int mode; } setbuf;
!   return setbuf.mode;  /* { dg-warning "'setbuf\.mode' is used" "" } */
  }



More information about the Gcc-patches mailing list