[cfe-dev] The really scary part of noexcept
Johannes Schaub (litb)
schaub.johannes at googlemail.com
Sun Mar 20 08:17:21 PDT 2011
Sebastian Redl wrote:
> Hi,
>
> There's one small piece of the noexcept specification left to implement.
> It's not only scary, it's also fiendishly difficult to find, being the
> only part of noexcept that isn't within [except]. [class.dtor]p3 says:
>
> "A declaration of a destructor that does not have an
> exception-specification is implicitly considered to have the same
> exception-specification as an implicit declaration."
>
> This means that destructors suddenly grow exception specifications, and
> they may be really, really wrong. Consider this little class, which could
> be used as an RAII guard.
>
> class TransactionGuard {
> DatabaseConnection& m_conn;
> public:
> TransactionGuard(DatabaseConnection& conn) : m_conn(conn) {}
> ~TransactionGuard() {
> if (std::unhandled_exception()) { // if we're being destructed due to
> an exception being thrown
> try { conn.rollback(); } catch(...) {} // rollback and swallow any
> errors, or we terminate
> } else {
> conn.commit(); // otherwise commit, and let exceptions escape
> }
> }
> };
>
> The above destructor would suddenly grow an exception-specification.
> Specifically, because it has no object data members, the
> exception-specification would be empty: it would be noexcept(true). If the
> conn.commit() call throws, the program would immediately terminate instead
> of letting the exception escape.
>
[...]
> So my question is, how should we implement this in Clang? Simply put it
> under C++0x? Have it enabled in C++0x by default, but add a switch to turn
> it off? Add an explicit switch to turn it on?
>
In my opinion, the situation for a program that does not use
std::uncaught_exception() to check whether there currently is an unhandled
exception is not worsened by this, because if the exception is thrown, it
already has the risk of having terminate called.
So I wonder whether the following makes sense:
- Implement it according to the spec, and when you process the body:
- When the destructor does not have an explicit exception specification but
a nonthrowing implicit exception specification, and
- when the body contains a call to std::uncaught_exception
If the two conditions are satisfied, issue a warning that
terminate/unexpected will be called regardless of the return value of
std::uncaught_exception() when an exception escapes the body.
I don't quite understand whether the exception specification will be
"throw()" or "noexcept(true)". It seems to make a difference wrt whether
unexpected() or teminate() is called. Subsection 15.4 hasn't enlighted me:
It just says that the function disallows any exception.
More information about the cfe-dev
mailing list