This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

fix c++/3757


Hopefully the commentary describes the bug well enough, since
at the moment I can't think of any other words to use.

The test case from the PR has been distilled as filter1.C.

There was a similar problem in which we failed to call std::terminate
in case a destructor-in-cleanup threw.  That is the subject of filter2.C.

The following is for mainline; I'll fix the branch in a moment.


r~


        * except.c (collect_one_action_chain): Add an explicit cleanup
        action if regions surrounding a catch were encoded entirely
        within the call-site entry.

        * g++.dg/eh/filter1.C, g++.dg/eh/filter2.C: New tests.

Index: except.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/except.c,v
retrieving revision 1.179
diff -c -p -d -r1.179 except.c
*** except.c	2001/08/01 22:47:09	1.179
--- except.c	2001/08/03 23:10:12
*************** expand_eh_return ()
*** 3020,3025 ****
--- 3020,3036 ----
    emit_label (around_label);
  }
  
+ /* In the following functions, we represent entries in the action table
+    as 1-based indicies.  Special cases are:
+ 
+ 	 0:	null action record, non-null landing pad; implies cleanups
+ 	-1:	null action record, null landing pad; implies no action
+ 	-2:	no call-site entry; implies must_not_throw
+ 	-3:	we have yet to process outer regions
+ 
+    Further, no special cases apply to the "next" field of the record.
+    For next, 0 means end of list.  */
+ 
  struct action_record
  {
    int offset;
*************** collect_one_action_chain (ar_hash, regio
*** 3123,3130 ****
  	      if (next == -3)
  		{
  		  next = collect_one_action_chain (ar_hash, region->outer);
! 		  if (next < 0)
  		    next = 0;
  		}
  	      next = add_action_record (ar_hash, c->u.catch.filter, next);
  	    }
--- 3134,3149 ----
  	      if (next == -3)
  		{
  		  next = collect_one_action_chain (ar_hash, region->outer);
! 
! 		  /* 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);
  		}
  	      next = add_action_record (ar_hash, c->u.catch.filter, next);
  	    }
Index: testsuite/g++.dg/eh/filter1.C
===================================================================
RCS file: filter1.C
diff -N filter1.C
*** /dev/null	Tue May  5 13:32:27 1998
--- filter1.C	Fri Aug  3 16:10:12 2001
***************
*** 0 ****
--- 1,43 ----
+ // Test that cleanups get run when a catch filter fails to match.
+ // { dg-do run }
+ 
+ extern "C" void exit(int);
+ extern "C" void abort();
+ 
+ struct a
+ {
+   a();
+   ~a();
+ };
+ 
+ struct e1 {};
+ struct e2 {};
+ 
+ void
+ ex_test ()
+ {
+   a aa;
+   try
+     {
+       throw e1 ();
+     }
+   catch (e2 &)
+     {
+     }
+ }
+ 
+ int
+ main ()
+ {
+   try
+     {
+       ex_test ();
+     }
+   catch (...)
+     {
+     }
+   abort ();
+ }
+ 
+ a::a() { }
+ a::~a() { exit (0); }
Index: testsuite/g++.dg/eh/filter2.C
===================================================================
RCS file: filter2.C
diff -N filter2.C
*** /dev/null	Tue May  5 13:32:27 1998
--- filter2.C	Fri Aug  3 16:10:12 2001
***************
*** 0 ****
--- 1,59 ----
+ // Test that terminate gets run when a catch filter fails to match while
+ // running destructors.  Original bug depended on a::~a being inlined.
+ // { dg-do run }
+ // { dg-options -O }
+ 
+ #include <exception>
+ #include <cstdlib>
+ 
+ struct e1 {};
+ struct e2 {};
+ 
+ struct a
+ {
+   a () { }
+ 
+   ~a ()
+     {
+       try
+ 	{
+ 	  throw e1();
+ 	}
+       catch (e2 &)
+ 	{
+         }
+     }
+ };
+ 
+ void
+ ex_test ()
+ {
+   a aa;
+   try
+     {
+       throw e1 ();
+     }
+   catch (e2 &)
+     {
+     }
+ }
+ 
+ void my_terminate ()
+ {
+   std::exit (0);
+ }
+ 
+ int
+ main ()
+ {
+   std::set_terminate (my_terminate);
+ 
+   try
+     {
+       ex_test ();
+     }
+   catch (...)
+     {
+     }
+   abort ();
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]