[cfe-dev] clang, noexcept and terminate

Howard Hinnant hhinnant at apple.com
Mon Jan 30 18:04:49 PST 2012


On Jan 30, 2012, at 4:11 PM, Howard Hinnant wrote:

> Wait, it gets worse.  The compiler can't just do:
> 
>    __cxa_begin_catch(unwind_arg);
>    std::terminate();
> 
> In C++98/03, the terminate_handler that gets used in a call to terminate during exception unwinding is the terminate_handler in effect at the time the exception is thrown, not when the implementation "catches" the exception and calls terminate.  libc++abi-like libraries handle this by storing the terminate_handler and unexpected_handler in the thrown exception object at the time the exception object is created.

I think I've changed my mind on this.  With a modified std::terminate() that detected caught-but-unhandled exceptions, and called the right handler based on that detection,  I tried to write a test case that would get the wrong answer if we just did the above, and I'm having trouble doing so.  The above answer is easy and ABI compatible.

clang just needs to start emitting a call to __cxa_begin_catch prior to calling terminate.  If I'm wrong, and there is a test case where this doesn't work, such code is going to be vanishingly rare, and far rarer than code that is broken by our current state:  not calling __cxa_begin_catch prior to calling terminate.

Here's a test case that I would like to run:

#include <iostream>
#include <stdexcept>
#include <exception>
#include <cstdlib>

void handler1()
{
    std::cout << "handler 1\n";
    std::abort();
}

void handler2()
{
    std::cout << "handler 2\n";
    std::abort();
}

struct A
{
    ~A() {std::set_terminate(handler2);}
};

void f2()
{
    std::set_terminate(handler1);
    throw std::runtime_error("throw in f2");
}

void f1() throw()
{
    A a;
    f2();
}

int main()
{
    f1();
}

Whether f1() has a noexcept or a throw(), the output should be:

handler 1

A wrong output is:

handler 2

(for either noexcept or throw())

I've just checked in a new std::terminate in libc++abi that will make this possible *if* clang calls __cxa_begin_catch prior to calling std::terminate (revision 149329).

I've filed:

http://llvm.org/bugs/show_bug.cgi?id=11893

to track this work.

Howard




More information about the cfe-dev mailing list