re PR middle-end/14535 (exception throwing in virtual function doesn't turn on the...
authorRichard Henderson <rth@redhat.com>
Tue, 16 Mar 2004 00:35:17 +0000 (16:35 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 16 Mar 2004 00:35:17 +0000 (16:35 -0800)
        PR middle-end/14535
        * except.c (collect_one_action_chain): Record action for cleanup
        outer of exception spec.
* g++.dg/eh/spec7.C: New.

From-SVN: r79521

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

index 458ae138e717fd1d51dce8ee7900a4d54a11deee..69a0bcc5f485a8f0e9a39faa0fcaf3db84a9a245 100644 (file)
@@ -1,3 +1,9 @@
+2004-03-15  Richard Henderson  <rth@redhat.com>
+
+       PR middle-end/14535
+       * except.c (collect_one_action_chain): Record action for cleanup
+       outer of exception spec.
+
 2004-03-15  Ian Lance Taylor  <ian@wasabisystems.com>
 
        * config/rs6000/host-darwin.c (darwin_rs6000_gt_pch_use_address):
index 4e38df26db0db7339f823626b152e70594db3ce1..c739650eb9f89e7cd9503f86d68431d8525e73f0 100644 (file)
@@ -3365,8 +3365,18 @@ collect_one_action_chain (htab_t ar_hash, struct eh_region *region)
       /* An exception specification adds its filter to the
         beginning of the chain.  */
       next = collect_one_action_chain (ar_hash, region->outer);
-      return add_action_record (ar_hash, region->u.allowed.filter,
-                               next < 0 ? 0 : next);
+
+      /* If there is no next action, terminate the chain.  */
+      if (next == -1)
+       next = 0;
+      /* If all outer actions are cleanups or must_not_throw,
+        we'll have no action record for it, since we had wanted
+        to encode these states in the call-site record directly.
+        Add a cleanup action to the chain to catch these.  */
+      else if (next <= 0)
+       next = add_action_record (ar_hash, 0, 0);
+      
+      return add_action_record (ar_hash, region->u.allowed.filter, next);
 
     case ERT_MUST_NOT_THROW:
       /* A must-not-throw region with no inner handlers or cleanups
diff --git a/gcc/testsuite/g++.dg/eh/spec7.C b/gcc/testsuite/g++.dg/eh/spec7.C
new file mode 100644 (file)
index 0000000..08586a2
--- /dev/null
@@ -0,0 +1,35 @@
+// PR 14535
+// { dg-do run }
+// { dg-options "-O -finline" }
+//
+// Original test case failure required that Raiser constructor be inlined.
+
+extern "C" void abort(); 
+bool destructor_called = false; 
+struct B { 
+    virtual void Run(){}; 
+}; 
+struct D : public B { 
+    virtual void Run() 
+      { 
+        struct O { 
+            ~O() { destructor_called = true; }; 
+        } o; 
+         
+        struct Raiser { 
+            Raiser()  throw( int ) {throw 1;}; 
+        } raiser; 
+      }; 
+}; 
+int main() { 
+    try { 
+      D d; 
+      static_cast<B&>(d).Run(); 
+    } catch (...) {} 
+    if (!destructor_called) 
+      abort (); 
+}