This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix segfault in try_forward_edges
- From: Jakub Jelinek <jakub at redhat dot com>
- To: rth at redhat dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 9 Jan 2002 16:36:30 +0100
- Subject: [PATCH] Fix segfault in try_forward_edges
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following testcase segfaults the compiler on IA-32 with -O+.
The problem is that if 2 b successor edges are successfully
forwarded, threaded_edges[0] still contains threaded edge from the first
loop.
So when the function later does:
n = 0;
...
if (n >= nthreaded_edges)
abort ();
t = threaded_edges [n++];
it will walk through edge from the first loop and not from the second as it
expects.
Fixed below, bootstrap succeeded on i386-redhat-linux, regression testing
pending. Ok to commit?
2002-01-09 Jakub Jelinek <jakub@redhat.com>
* cfgcleanup.c (try_forward_edges): Reset nthreaded_edges for
each B successor attempted.
* gcc.c-torture/compile/20020109-1.c: New test.
--- gcc/testsuite/gcc.c-torture/compile/20020109-1.c.jj Wed Jan 9 16:51:36 2002
+++ gcc/testsuite/gcc.c-torture/compile/20020109-1.c Wed Jan 9 16:52:53 2002
@@ -0,0 +1,23 @@
+/* This testcase ICEd when 2 different successors of a basic block
+ were successfully threaded and try_forward_edges was not expecting
+ that. */
+
+typedef struct A
+{
+ struct A *s, *t;
+ unsigned int u;
+} A;
+
+void bar (A *);
+
+void
+foo (A *x, A *y, A *z)
+{
+ while (y
+ && (((y && y->t && y->t->u) ? y : z)->t
+ == ((x && x->t && x->t->u) ? x : z)->t))
+ y = y->s;
+
+ if (y)
+ bar (y);
+}
--- gcc/cfgcleanup.c.jj Mon Jan 7 14:57:23 2002
+++ gcc/cfgcleanup.c Wed Jan 9 16:47:49 2002
@@ -370,7 +370,7 @@ try_forward_edges (mode, b)
{
bool changed = false;
edge e, next, *threaded_edges = NULL;
- int nthreaded_edges = 0;
+ int nthreaded_edges;
for (e = b->succ; e; e = next)
{
@@ -390,6 +390,7 @@ try_forward_edges (mode, b)
target = first = e->dest;
counter = 0;
+ nthreaded_edges = 0;
while (counter < n_basic_blocks)
{
@@ -412,7 +413,7 @@ try_forward_edges (mode, b)
edge t = thread_jump (mode, e, target);
if (t)
{
- if (!nthreaded_edges)
+ if (threaded_edges == NULL)
threaded_edges = xmalloc (sizeof (*threaded_edges)
* n_basic_blocks);
else
Jakub