[PATCH] Fix PR39246: -Wuninitialized for partially initialized complex
Thomas Preud'homme
thomas.preudhomme@arm.com
Sun May 4 08:32:00 GMT 2014
Warning for use of a partially initialized complex is displayed on the wrong line (the one where the partial initialization is done) and is not consistent between target (or even within a given target, for instance between hardfloat and softfloat on arm-none-eabi target). This patch correctly retains the line location when expanding a complex move, stop warning when a COMPLEX_EXPR is constructed but instead warn when it is used, and for cases where a branch is involved, get the line location from the phi argument involved as a fallback. This fixes PR39246.
The ChangeLog are as follows:
*** gcc/ChangeLog ***
2014-05-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR middle-end/39246
* tree-complex.c (expand_complex_move): Keep line info when expanding
complex move.
* tree-ssa-uninit.c (warn_uninit): New argument. Ignore assignment of
complex expression. Use new argument to display correct location for
values coming from phi statement.
(warn_uninitialized_vars): Adapt to new signature of warn_uninit.
(warn_uninitialized_phi): Pass location of phi argument to warn_uninit.
* tree-ssa.c (ssa_undefined_value_p): For SSA_NAME initialized by a
COMPLEX_EXPR, recurse on each part of the COMPLEX_EXPR.
*** gcc/testsuite/ChangeLog ***
2014-05-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.dg/uninit-13.c: Move warning on the actual source line where the
uninitialized complex is used.
* gcc.dg/uninit-17.c: New test to check partial initialization of
complex with branches.
* gcc.dg/uninit-17-O0.c: Likewise.
Bootstrapped on x86_64-linux-gnu with no regression in the testsuite. Also tested a cross-build of gcc for arm-none-eabi target and run the regression testsuite in qemu for cortex-m3 without any regression and the uninit-13.c test fixed.
Ok for stage1? Patch with proper formatting in attachment.
diff --git a/gcc/testsuite/gcc.dg/uninit-13.c b/gcc/testsuite/gcc.dg/uninit-13.c
index 631e8de..5e88a8a 100644
--- a/gcc/testsuite/gcc.dg/uninit-13.c
+++ b/gcc/testsuite/gcc.dg/uninit-13.c
@@ -5,6 +5,6 @@ typedef _Complex float C;
C foo()
{
C f;
- __imag__ f = 0; /* { dg-warning "is used" "unconditional" } */
- return f;
+ __imag__ f = 0;
+ return f; /* { dg-warning "is used" "unconditional" } */
}
diff --git a/gcc/testsuite/gcc.dg/uninit-17-O0.c b/gcc/testsuite/gcc.dg/uninit-17-O0.c
new file mode 100644
index 0000000..0eaef05
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-17-O0.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized" } */
+
+typedef _Complex float C;
+C foo(int cond)
+{
+ C f;
+ __imag__ f = 0;
+ if (cond)
+ {
+ __real__ f = 1;
+ return f;
+ }
+ return f;
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-17.c b/gcc/testsuite/gcc.dg/uninit-17.c
new file mode 100644
index 0000000..8a95f15
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-17.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized" } */
+
+typedef _Complex float C;
+C foo(int cond)
+{
+ C f;
+ __imag__ f = 0;
+ if (cond)
+ {
+ __real__ f = 1;
+ return f;
+ }
+ return f; /* { dg-warning "may be used" "unconditional" } */
+}
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index a97aaf9..2286e2e 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -831,12 +831,15 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
{
tree x;
gimple t;
+ location_t loc;
+ loc = gimple_location (stmt);
r = extract_component (gsi, rhs, 0, false);
i = extract_component (gsi, rhs, 1, false);
x = build1 (REALPART_EXPR, inner_type, unshare_expr (lhs));
t = gimple_build_assign (x, r);
+ gimple_set_location (t, loc);
gsi_insert_before (gsi, t, GSI_SAME_STMT);
if (stmt == gsi_stmt (*gsi))
@@ -849,6 +852,7 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
{
x = build1 (IMAGPART_EXPR, inner_type, unshare_expr (lhs));
t = gimple_build_assign (x, i);
+ gimple_set_location (t, loc);
gsi_insert_before (gsi, t, GSI_SAME_STMT);
stmt = gsi_stmt (*gsi);
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index ae251cc..4310e7e 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -123,17 +123,25 @@ uninit_undefined_value_p (tree t) {
/* 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. */
+ warning text is in MSGID and DATA is the gimple stmt with info about
+ the location in source code. When DATA is a GIMPLE_PHI, PHIARG_IDX
+ gives which argument of the phi node to take the location from. WC
+ is the warning code. */
static void
-warn_uninit (enum opt_code wc, tree t,
- tree expr, tree var, const char *gmsgid, void *data)
+warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
+ const char *gmsgid, void *data, location_t phiarg_loc)
{
gimple context = (gimple) data;
location_t location, cfun_loc;
expanded_location xloc, floc;
+ /* Ignore COMPLEX_EXPR as initializing only a part of a complex
+ turns in a COMPLEX_EXPR with the not initialized part being
+ set to its previous (undefined) value. */
+ if (is_gimple_assign (context)
+ && gimple_assign_rhs_code (context) == COMPLEX_EXPR)
+ return;
if (!has_undefined_value_p (t))
return;
@@ -146,9 +154,12 @@ warn_uninit (enum opt_code wc, tree t,
|| TREE_NO_WARNING (expr))
return;
- location = (context != NULL && gimple_has_location (context))
- ? gimple_location (context)
- : DECL_SOURCE_LOCATION (var);
+ if (context != NULL && gimple_has_location (context))
+ location = gimple_location (context);
+ else if (phiarg_loc != UNKNOWN_LOCATION)
+ location = phiarg_loc;
+ else
+ location = DECL_SOURCE_LOCATION (var);
location = linemap_resolve_location (line_table, location,
LRK_SPELLING_LOCATION,
NULL);
@@ -200,12 +211,12 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized)
warn_uninit (OPT_Wuninitialized, use,
SSA_NAME_VAR (use), SSA_NAME_VAR (use),
"%qD is used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
else if (warn_possibly_uninitialized)
warn_uninit (OPT_Wmaybe_uninitialized, use,
SSA_NAME_VAR (use), SSA_NAME_VAR (use),
"%qD may be used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
}
/* For memory the only cheap thing we can do is see if we
@@ -236,12 +247,12 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized)
warn_uninit (OPT_Wuninitialized, use,
gimple_assign_rhs1 (stmt), base,
"%qE is used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
else if (warn_possibly_uninitialized)
warn_uninit (OPT_Wmaybe_uninitialized, use,
gimple_assign_rhs1 (stmt), base,
"%qE may be used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
}
}
}
@@ -2247,6 +2258,8 @@ warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
unsigned uninit_opnds;
gimple uninit_use_stmt = 0;
tree uninit_op;
+ int phiarg_index;
+ location_t loc;
/* Don't look at virtual operands. */
if (virtual_operand_p (gimple_phi_result (phi)))
@@ -2271,13 +2284,18 @@ warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
if (!uninit_use_stmt)
return;
- uninit_op = gimple_phi_arg_def (phi, MASK_FIRST_SET_BIT (uninit_opnds));
+ phiarg_index = MASK_FIRST_SET_BIT (uninit_opnds);
+ uninit_op = gimple_phi_arg_def (phi, phiarg_index);
if (SSA_NAME_VAR (uninit_op) == NULL_TREE)
return;
+ if (gimple_phi_arg_has_location (phi, phiarg_index))
+ loc = gimple_phi_arg_location (phi, phiarg_index);
+ else
+ loc = UNKNOWN_LOCATION;
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);
+ uninit_use_stmt, loc);
}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 1ea639d..499bd06 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1246,6 +1246,7 @@ tree_ssa_strip_useless_type_conversions (tree exp)
bool
ssa_undefined_value_p (tree t)
{
+ gimple def_stmt;
tree var = SSA_NAME_VAR (t);
if (!var)
@@ -1262,7 +1263,22 @@ ssa_undefined_value_p (tree t)
return false;
/* The value is undefined iff its definition statement is empty. */
- return gimple_nop_p (SSA_NAME_DEF_STMT (t));
+ def_stmt = SSA_NAME_DEF_STMT (t);
+ if (gimple_nop_p (def_stmt))
+ return true;
+
+ /* Check if the complex was not only partially defined. */
+ if (is_gimple_assign (def_stmt)
+ && gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR)
+ {
+ tree rhs1, rhs2;
+
+ rhs1 = gimple_assign_rhs1 (def_stmt);
+ rhs2 = gimple_assign_rhs2 (def_stmt);
+ return (TREE_CODE (rhs1) == SSA_NAME && ssa_undefined_value_p (rhs1))
+ || (TREE_CODE (rhs2) == SSA_NAME && ssa_undefined_value_p (rhs2));
+ }
+ return false;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gcc32rm-91.1.1.diff
Type: application/octet-stream
Size: 7466 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20140504/172f5fc0/attachment.obj>
More information about the Gcc-patches
mailing list