------- Comment #9 from redi at gcc dot gnu dot org  2009-08-27 12:18 -------
(In reply to comment #5)
> I think the problem is that the uncaught_exception() is true as soon as the
> memory for the exception has been allocated, but if the exception's copy
> constructor is elided then happens before entering the exception's 
> constructor.
>  If the exception constructor throws another exception then uncaughtExceptions
> goes to 2, and never goes back to zero.
After re-reading [except.throw] and [except.terminate] I think it is OK to
elide the copy of the thrown object into the exception object here:
   throw e();
This means that uncaught_exception() can be true in the call e::e()

*But* if the copy is elided and e::e() throws then std::terminate() should be
called. This means the OP's testcase and my one in comment #5 should terminate,
rather than exiting normally with std::uncaught_exception()==true

This is because of the following in [except.terminate]/1

"when the exception handling mechanism, after completing evaluation of the
expression to be thrown but before the exception is caught (15.1), calls a
function that exits via an uncaught exception, 141"
"141) For example, if the object being thrown is of a class with a copy
constructor, std::terminate() will be called if that copy constructor exits
with an exception during a throw."

Now, either

(A) e::e() happens before completing evaluation of the expression to be thrown
and uncaught_exception() should be false during e::e()

or

(B) the copy is elided and e::e() happens after evaluating completing
evaluation. In this case, uncaught_exception() should be true during e::e() but
if it exits with an exception then std::terminate() should be called.

GCC elides the copy, but does not call std::terminate() if e::e() exits with an
exception.  I don't think this interpretation will be changed by DR 475


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41174

Reply via email to