re PR target/12301 (corruption in exception path, exception in returned expression)
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 21 Sep 2003 08:17:48 +0000 (08:17 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 21 Sep 2003 08:17:48 +0000 (08:17 +0000)
PR target/12301
* reorg.c (stop_search_p): Return 1 for insns that can
throw internally.

From-SVN: r71620

gcc/ChangeLog
gcc/reorg.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/delayslot1.C [new file with mode: 0644]

index 35f2fba3a617401b034c1001a668702da6354988..ca9c54098ea5980b35aee37077c341e9a9467b67 100644 (file)
@@ -1,3 +1,9 @@
+2003-09-21  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR target/12301
+       * reorg.c (stop_search_p): Return 1 for insns that can
+       throw internally.
+
 2003-09-20  Richard Henderson  <rth@redhat.com>
 
        * c-format.c (gcc_diag_char_table): Add %J.
index 3d7159daa7c9d7be62366c33f26765dff46acc0b..6a13fe0634b320752202c8360bc19d4fa86b99d7 100644 (file)
@@ -235,6 +235,12 @@ stop_search_p (rtx insn, int labels_p)
   if (insn == 0)
     return 1;
 
+  /* If the insn can throw an exception that is caught within the function,
+     it may effectively perform a jump from the viewpoint of the function.
+     Therefore act like for a jump.  */
+  if (can_throw_internal (insn))
+    return 1;
+
   switch (GET_CODE (insn))
     {
     case NOTE:
index a65e623fd40f95ceee7ea439b9015b013fe97aae..11c7cff5343072a2745fb603af4f3fac50c7ec3e 100644 (file)
@@ -1,3 +1,7 @@
+2003-09-21  Christian Ehrhardt  <ehrhardt@mathematik.uni-ulm.de>
+
+       * g++.dg/eh/delayslot1.C: New test.
+
 2003-09-20  Richard Henderson  <rth@redhat.com>
 
        * gcc.dg/format/gcc_diag-1.c: Add tests for %J.
diff --git a/gcc/testsuite/g++.dg/eh/delayslot1.C b/gcc/testsuite/g++.dg/eh/delayslot1.C
new file mode 100644 (file)
index 0000000..ddc960e
--- /dev/null
@@ -0,0 +1,47 @@
+// PR target/12301
+// Origin: Colin Hirsch <gcc@cohi.at>
+// Testcase by Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
+
+// This used to fail on SPARC because the reorg pass moved an insn
+// across a function call that can throw internally, in order to put
+// it in a delay slot.
+
+// { dg-do run }
+// { dg-options "-O" }
+
+struct S{
+  char *c;
+  char data[100];
+  S () : c (data) {};
+  S (const S& s) {
+    c = data;
+    data[0] = s.c[0];
+  }
+};
+
+S real_cast ()
+{
+  throw 3;  
+}
+
+S cast_helper(S& debug)
+{
+  try {
+    return real_cast();
+  }
+  catch (int e) {
+    throw debug;
+  }
+}
+
+int main()
+{
+  S tmp;
+
+  try {
+    cast_helper (tmp);
+  }                                        
+  catch (S& e) {}
+
+  return 0;
+}