[LLVMdev] clang/g++ frontend: can __cxa_end_catch throw?
rjmccall at apple.com
Mon Jul 12 14:03:44 PDT 2010
On Jul 12, 2010, at 1:22 PM, Yuri wrote:
> On 07/12/2010 12:41, John McCall wrote:
>> For your test case, clang++'s code is correct (and better) because
>> __cxa_end_catch won't throw for a caught exception of that type. That said,
> Which type? There are two pending exceptions at the moment when __cxa_end_catch is called, both with invisible destructors: E* and unknown type thrown from mycatching(). __cxa_end_catch attempts to delete E* and proceed to rethrow the unknown one when the other unknown exception is thrown by E::~E(). Isn't this the condition for terminate()?
I think you're confused about the semantics of C++ EH. In C++, the only time you have to call a destructor for an exception is when the exception is of class type. An exception that's caught by A* is never of class type; by definition, it's of *pointer* to class type (specifically, either A or some class derived from A; we can't make assumptions about its destructor from properties of A's destructor). There is no implicit delete of the pointed-to object.
In theory, a program could call _cxa_throw itself, providing an exception of pointer type together with a special "destructor" function which deletes the pointer, but AFAIK that's an accident of the ABI API, not a supported operation; we're allowed to optimize based on an assumption that an exception of pointer type never has a destructor.
If mycatching throws an exception, then we do need to call _cxa_end_catch on the way out of the catch block for the E*. That's done in a landing pad for the invoke, but that landing pad never technically catches this exception, which is to say, that landing pad never calls __cxa_begin_catch. Therefore we shouldn't (and don't) call __cxa_end_catch, and therefore the destructor for that object is not run.
More information about the llvm-dev