Overlap/clash between libc++ and libsupc++

[This message got lost in the shuffle during the mail outage back in August, so I'm resending it.]

In trying to use libc++ on Linux, I attempted to go the simple route of using libsupc++ to provide the ABI support, but in addition to a crash in std::uncaught_exception() (see http://llvm.org/bugs/show_bug.cgi?id=13669), I've noticed that the following functions are defined in *both* libsupc++ and libc++. Note that these are in std::, *not* std::__1:: so these are genuine duplicate definitions.

  operator delete(void*, std::nothrow_t const&)
  operator delete(void*, std::nothrow_t const&)
  operator new(unsigned long, std::nothrow_t const&)
  operator new(unsigned long, std::nothrow_t const&)
  std::bad_alloc::what() const
  std::bad_alloc::~bad_alloc()
  std::bad_cast::what() const
  std::bad_cast::~bad_cast()
  std::bad_exception::what() const
  std::bad_exception::~bad_exception()
  std::bad_typeid::what() const
  std::bad_typeid::~bad_typeid()
  std::current_exception()
  std::exception::what() const
  std::exception::~exception()
  std::nested_exception::~nested_exception()
  std::set_new_handler(void (*)())
  std::set_terminate(void (*)())
  std::set_unexpected(void (*)())
  std::terminate()
  std::uncaught_exception()
  std::unexpected()

In addition to the duplication (which may be problematic by itself?), libc++ doesn't currently provide good implementations for some of these functions (for example, on Linux, libc++'s version of std::uncaught_exception() actually just calls abort, causing the crash I mentioned earlier), it would seem like the best thing to do on Linux would be to not provide them at all.

Thoughts?

One thought I had was to just #ifdef out the code in src/new.cpp and src/exception.cpp but that fails because libc++ relies on (at least)

  std::exception_ptr::~exception_ptr()
  std::bad_alloc::bad_alloc()
  std::exception_ptr::exception_ptr(std::exception_ptr const&)
  std::exception_ptr::operator=(std::exception_ptr const&)
  std::rethrow_exception(std::exception_ptr)

which are defined by libc++, but not defined by libsupc++.

In general, as others have said multiple times on this mailing list, it would be really nice if there was a simple way for people to use clang with libc++ on Linux and have it "just work". I don't really mind *how* that is accomplished. I don't even care about compatibility with code compiled by GCC. It still amazes me that there isn't an *easy* recipe to follow for this.

   M.E.O.

P.S. Also of interest, libc++ (only) provides the following functions.

  std::__throw_bad_alloc()
  std::bad_alloc::bad_alloc()
  std::bad_array_new_length::bad_array_new_length()
  std::bad_array_new_length::what() const
  std::bad_array_new_length::~bad_array_new_length()
  std::bad_cast::bad_cast()
  std::bad_typeid::bad_typeid()
  std::domain_error::~domain_error()
  std::exception_ptr::exception_ptr(std::exception_ptr const&)
  std::exception_ptr::operator=(std::exception_ptr const&)
  std::exception_ptr::~exception_ptr()
  std::get_new_handler()
  std::get_terminate()
  std::get_unexpected()
  std::invalid_argument::~invalid_argument()
  std::length_error::~length_error()
  std::logic_error::logic_error(char const*)
  std::logic_error::logic_error(std::logic_error const&)
  std::logic_error::operator=(std::logic_error const&)
  std::logic_error::what() const
  std::logic_error::~logic_error()
  std::nested_exception::nested_exception()
  std::nested_exception::rethrow_nested() const
  std::out_of_range::~out_of_range()
  std::overflow_error::~overflow_error()
  std::range_error::~range_error()
  std::rethrow_exception(std::exception_ptr)
  std::runtime_error::operator=(std::runtime_error const&)
  std::runtime_error::runtime_error(char const*)
  std::runtime_error::runtime_error(std::runtime_error const&)
  std::runtime_error::what() const
  std::runtime_error::~runtime_error()
  std::underflow_error::~underflow_error()

From: "M.E. O'Neill" <oneill@cs.hmc.edu>
To: "CFE Dev" <cfe-dev@cs.uiuc.edu>
Sent: Tuesday, November 6, 2012 2:44:09 AM
Subject: [cfe-dev] Overlap/clash between libc++ and libsupc++

[This message got lost in the shuffle during the mail outage back in
August, so I'm resending it.]

In trying to use libc++ on Linux, I attempted to go the simple route
of using libsupc++ to provide the ABI support, but in addition to a
crash in std::uncaught_exception() (see
http://llvm.org/bugs/show_bug.cgi?id=13669), I've noticed that the
following functions are defined in *both* libsupc++ and libc++.
Note that these are in std::, *not* std::__1:: so these are genuine
duplicate definitions.

  operator delete(void*, std::nothrow_t const&)
  operator delete(void*, std::nothrow_t const&)
  operator new(unsigned long, std::nothrow_t const&)
  operator new(unsigned long, std::nothrow_t const&)
  std::bad_alloc::what() const
  std::bad_alloc::~bad_alloc()
  std::bad_cast::what() const
  std::bad_cast::~bad_cast()
  std::bad_exception::what() const
  std::bad_exception::~bad_exception()
  std::bad_typeid::what() const
  std::bad_typeid::~bad_typeid()
  std::current_exception()
  std::exception::what() const
  std::exception::~exception()
  std::nested_exception::~nested_exception()
  std::set_new_handler(void (*)())
  std::set_terminate(void (*)())
  std::set_unexpected(void (*)())
  std::terminate()
  std::uncaught_exception()
  std::unexpected()

At least for some of this, I think this depends on how libc++ is compiled. The definitions in src/exception.cpp are guarded by !defined(__GLIBCXX__) -- the assumption seems to be that __GLIBCXX__ will be defined if cxxabi.h is included; this was not always true, but that's another matter -- when I compile on Linux I add -D__GLIBCXX__ to the command line arguments and everything seems to work correctly.

-Hal

There now is a simplish way. The CMake build now has support for
properly handling libc++ on Linux with libsupc++ ABI. The interface
could be much nicer, but it does work.

1) Configure libc++ with CMAKE_INSTALL_PREFIX=/usr (clang only looks
for libc++ here on Linux)
2) Set LIBCXX_CXX_ABI to libsupc++ and reconfigure.
3) Set LIBCXX_LIBSUPCXX_INCLUDE_PATHS to a ; separated list of paths
to the libsupc++ headers. On my linux machine this is
"usr/include/c++/4.6;/usr/include/c++/4.6/x86_64-linux-gnu"
4) Reconfigure
5) Generate, build, install

- Michael Spencer