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]
Other format: [Raw text]

Re: [3.3] Followup to C++ forced unwinding


On Wed, Apr 30, 2003 at 11:39:41AM -0700, Mark Mitchell wrote:
> (4) Some other black magic in except.c that I couldn't get my head
> around on the first try.  What do these bits do?

I presume you're talking about

	(RNL_ALWAYS_CAUGHT): New.
	(reachable_next_level): Return RNL_ALWAYS_CAUGHT for empty filter
	spec and must_not_throw shadowing other catch handlers.
	(reachable_handlers): With forced unwinding, only mark cleanups
	live after catch(...), not throw().
	(can_throw_external): Similarly wrt exceptions escaping the function.

Well, the existing code had bits to notice that must_not_throw
(the wrapper around destructor during cleanup that calls terminate)
was different from catch(...), but didn't distinguish between
throw() and catch(...).  This makes that distinction, because...

> One key question that I'm not sure got resolved on the thread was what
> happens in this case:
> 
>    try { 
>      // Something that might:
>      // (a) result in cancellation.
>      // (b) result in a foreign exception being thrown.
>      // (c) result in longjmp_unwind being called.
>    } catch (...) {
>      // There is no "throw;" here to rethrow.
>    }
> 
> Presumably (a) is the same as either (b) or (c).  Which one?

... I thought (a) was similar to (c) and that the catch 
handler here is *not* invoked in either case.

So continuing with the first question, we want to note that with
-fforced-unwind-exceptions that while cleanups after catch(...)
are live, cleanups after throw() are not.

Oops, I've missed a case:

	void foo() throw()
	{
	  read(...)
	}

will (properly) abort, but

	void bar() throw()
	{
	  try {
	    read(...)
	  } catch (...) {
	  }
	}

won't.  I'll fix that and update the patch.

> And, if which of these cases are we implicitly rethrowing from the
> catch, even though the user didn't write "throw;"?  

We don't implicitly rethrow, because we don't allow the catch.
I've thought about this a bit, and have reservations because...

> The reason I ask is that:
> 
>   f = fopen(...);
>   try {
>   } catch (...) {
>   }
>   fclose (f);
> 
> looks to a C++ programmer to be a perfectly safe piece of code, modulo
> longjmp.

... of this.  It *isn't* safe unless you know that nothing in the
catch handler can throw.  If we can get folks to write this as

	struct closer {
	  FILE *f;
	  closer(FILE *x) : f(x) { }
	  ~closer() { if (f) fclose (f); }
	};
	
	f = fopen(...);
	{
	  closer c(f);
	  try {
	  } catch (...) {
	  }
	}

I'd be much happier.  Or, heaven forfend, use iostreams and
auto_ptr, which are a bit more prepared for this sort of thing
without having to define your own local classes.

> Does the IA-64 ABI specify this?

No.  It says things can work either way, which is a bit unsatisfying.

> But, I'd be unhappy if foreign exceptions and/or thread cancellation did
> an implicit rethrow.

Ok, good, we're on the same page.


r~


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