------- 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