[LLVMdev] clang/g++ frontend: can __cxa_end_catch throw?

John McCall 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.

John.



More information about the llvm-dev mailing list