This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] Fix EH prev_try handling (PR tree-optimization/30558)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, Diego Novillo <dnovillo at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 24 Apr 2007 13:01:14 -0400
- Subject: [gomp] Fix EH prev_try handling (PR tree-optimization/30558)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
On the attached testcase we have before the eh lowering:
try
{
__comp_ctor (&gD.2573);
.omp_data_o.2D.2651.gD.2648 = &gD.2573;
#pragma omp parallel shared(gD.2573) [child fn: main.omp_fn.0D.2645 (.omp_data_o.2D.2651)]
try
{
.omp_data_iD.2647 = &.omp_data_o.2D.2651;
try
{
#pragma omp for nowait
for (iD.2583 = 0; iD.2583 <= 9; iD.2583 = iD.2583 + 1)
__comp_ctor (&jD.2584, iD.2583);
try
{
...
}
finally
{
__comp_dtor (&jD.2584);
}
OMP_CONTINUE
}
catch
{
<<<eh_filter ()>>>
{
terminate ();
}
}
OMP_RETURN [nowait]
}
catch
{
<<<eh_filter ()>>>
{
terminate ();
}
}
OMP_RETURN
}
catch
{
catch (intD.2)
{
D.2599 = __cxa_begin_catch (<<<exception object>>>);
e.0D.2595 = (intD.2 *) D.2599;
eD.2592 = e.0D.2595;
__cxa_end_catch ();
}
}
Eventhough terminate really won't return, EH lowering creates
abnormal EH edges from __comp_dtor (&jD.2584)'s BB to the BB
containing __cxa_begin_catch, as when the outermost try .. catch
is lowered, prev_try in the state is set to that ERT_TRY region
and nothing ever clears it. This causes various ICEs during omp
expand, as the omp parallel region really is not a single entry
single exit because of that EH edge. Unmodified gcc ICEs in
duplicate_eh_edges, because REMAP (cur->u.cleanup.prev_try);
is not representable with the new EH regions, when I conditionalized
this it ICEd a short while afterwards (because pred edges of
the __cxa_begin_catch containing BB in main referenced a non-existent
BB (one that has been moved into a separate function by
move_sese_region_to_fn). But even in -fno-openmp C++ code I believe
there is no reason to have EH edges from cleanup regions accross
EH_FILTER_MUST_NOT_THROW regions out to some containing try .. catch.
Tested on x86_64-linux, ok for 4.3/4.2?
2007-04-24 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/30558
* tree-eh.c (lower_eh_filter): If EH_FILTER_MUST_NOT_THROW
clear this_state.prev_try.
* g++.dg/gomp/pr30558.C: New test.
--- gcc/tree-eh.c.jj 2007-03-12 17:18:17.000000000 +0100
+++ gcc/tree-eh.c 2007-04-24 17:32:16.000000000 +0200
@@ -1497,6 +1497,10 @@ lower_eh_filter (struct leh_state *state
EH_FILTER_TYPES (inner));
this_state = *state;
this_state.cur_region = this_region;
+ /* For must not throw regions any cleanup regions inside it
+ can't reach outer catch regions. */
+ if (EH_FILTER_MUST_NOT_THROW (inner))
+ this_state.prev_try = NULL;
lower_eh_constructs_1 (&this_state, &TREE_OPERAND (*tp, 0));
--- gcc/testsuite/g++.dg/gomp/pr30558.C.jj 2007-04-24 17:41:47.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr30558.C 2007-04-24 17:42:24.000000000 +0200
@@ -0,0 +1,45 @@
+// PR tree-optimization/30558
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+static int s = 6;
+
+template <typename T> struct F
+{
+ ~F () {}
+ F (T x) {}
+ const T &operator[] (unsigned i) const { return s; }
+};
+
+template <typename T> F<T> foo (const F<T> &x)
+{
+ return F<T> (x[1]);
+}
+
+extern F<int> z;
+
+struct G
+{
+ G () { bar (2); }
+ F<int> &operator () (F<int> x) { return z; }
+ void bar (int);
+};
+
+int
+main ()
+{
+ try
+ {
+ G g;
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ {
+ F<int> j (i);
+ F<int> f = g (j);
+ F<int> h = foo (f);
+ }
+ }
+ catch (int &e)
+ {
+ }
+}
Jakub