libc++ and std::bad_exception

I've observed some unexpected behavior with libc++ and exception specifications. libc++ seems to be calling std::terminate() even in a situation where it should not.

I have a program with a function 'foo' that lists std::bad_exception in its exception specification, and a custom unexpected hander is registered which rethrows an exception. When 'foo' is called it throws a type not listed and so my custom unexpected handler is called. However, if I'm using libc++ then after my handler is called std::terminate() is called.

My understanding is that these circumstances should lead to std::bad_exception being thrown and exception handling continuing normally instead of std::terminate() being called.

Here's the program I'm using:

#include <iostream>
#include <exception>

void custom_unexpected() {
  std::cerr << "custom unexpected handler called\n";
  throw;
}

void foo()
    throw(std::bad_exception)
{
  throw 10;
}

int main (void) {
  std::set_unexpected(custom_unexpected);
  
  try {
    foo();
  } catch (std::exception &e) {
    std::cerr << "caught std::exception: " << e.what() << "\n";
  }
}

Two commands I use to build this program were:

/usr/local/bin/clang++ -std=c++0x -U__STRICT_ANSI__ -Wall -Werror noexcept.cpp

and

/usr/local/bin/clang++ -std=c++0x -stdlib=libc++ -U__STRICT_ANSI__ -Wall -Werror noexcept.cpp

With the first build command the output of the resulting program is:

custom unexpected handler called
caught std::exception: std::bad_exception

The program resulting from the second command (which uses libc++) outputs:

custom unexpected handler called
terminate called throwing an exceptionAbort trap: 6

The result is also independent of whether I use -std=c++0x or not.

version info:

clang version 3.0 (http://llvm.org/git/clang.git 1e5b6f60e2e09addd2f2e915c87d8bd74d40c369)
Target: x86_64-apple-darwin11.0.0
Thread model: posix

and I believe the version of libc++ I'm using is the built in one with Mac OS X Lion 10.7 (11A511)

I'd like to test it out with the latest version of libc++ as well, just to be sure this isn't already fixed. Is there a recommended way to build and use libc++ without replacing the system's version?

I've observed some unexpected behavior with libc++ and exception specifications. libc++ seems to be calling std::terminate() even in a situation where it should not.

I have a program with a function 'foo' that lists std::bad_exception in its exception specification, and a custom unexpected hander is registered which rethrows an exception. When 'foo' is called it throws a type not listed and so my custom unexpected handler is called. However, if I'm using libc++ then after my handler is called std::terminate() is called.

My understanding is that these circumstances should lead to std::bad_exception being thrown and exception handling continuing normally instead of std::terminate() being called.

Your understanding is correct.

Here's the program I'm using:

#include <iostream>
#include <exception>

void custom_unexpected() {
  std::cerr << "custom unexpected handler called\n";
  throw;
}

void foo()
   throw(std::bad_exception)
{
  throw 10;
}

int main (void) {
  std::set_unexpected(custom_unexpected);
  
  try {
    foo();
  } catch (std::exception &e) {
    std::cerr << "caught std::exception: " << e.what() << "\n";
  }
}

Two commands I use to build this program were:

/usr/local/bin/clang++ -std=c++0x -U__STRICT_ANSI__ -Wall -Werror noexcept.cpp

and

/usr/local/bin/clang++ -std=c++0x -stdlib=libc++ -U__STRICT_ANSI__ -Wall -Werror noexcept.cpp

With the first build command the output of the resulting program is:

custom unexpected handler called
caught std::exception: std::bad_exception

The program resulting from the second command (which uses libc++) outputs:

custom unexpected handler called
terminate called throwing an exceptionAbort trap: 6

The result is also independent of whether I use -std=c++0x or not.

version info:

clang version 3.0 (http://llvm.org/git/clang.git 1e5b6f60e2e09addd2f2e915c87d8bd74d40c369)
Target: x86_64-apple-darwin11.0.0
Thread model: posix

and I believe the version of libc++ I'm using is the built in one with Mac OS X Lion 10.7 (11A511)

Please file a bug report (http://llvm.org/bugs/) against libc++abi.

Because dynamic exception specifications have been deprecated, I do not know how much priority this bug will get. But it is an open source project. So if people are excited about getting this right, it will happen.

I'd like to test it out with the latest version of libc++ as well, just to be sure this isn't already fixed. Is there a recommended way to build and use libc++ without replacing the system's version?

To build, I like to cd into lib and type ./buildit. You'll first want to: export TRIPLE=-apple_.

To run, create an environment variable with: export DYLD_LIBRARY_PATH="where ever you put the dylib". Mac OS will look there before it goes to the system places to load the library. And I believe a -I to your test headers (on the command line) will take precedence over the system headers as well.

Howard