This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR50040
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: jason at redhat dot com
- Date: Thu, 11 Aug 2011 14:57:00 +0200 (CEST)
- Subject: [PATCH] Fix PR50040
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" "" } */
}