From 57e446dafafe4609d25395c05ee3c26b05499903 Mon Sep 17 00:00:00 2001 From: Asiri Rathnayake Date: Tue, 31 May 2016 12:01:32 +0000 Subject: [PATCH] [libcxxabi] Introduce a -fno-exceptions libc++abi libary variant Currently there is only support for a -fno-exceptions libc++ build. This is problematic for functions such as std::terminate() which are defined in libc++abi and using any of those functions throws away most of the benefits of using -fno-exceptions (code-size). This patch introduces a -fno-exceptions libc++abi build to address this issue. This new variant of libc++abi cannot be linked against any with-exceptions code as some symbols necessary for handling exceptions are missing in this library. Differential revision: http://reviews.llvm.org/D20677 Reviewers: EricWF, mclow.lists, bcraig llvm-svn: 271267 --- libcxxabi/CMakeLists.txt | 18 ++++-- libcxxabi/src/CMakeLists.txt | 9 ++- libcxxabi/src/cxa_aux_runtime.cpp | 12 ++++ libcxxabi/src/cxa_handlers.cpp | 8 +-- libcxxabi/src/cxa_new_delete.cpp | 12 ++++ libcxxabi/src/cxa_noexception.cpp | 60 +++++++++++++++++++ libcxxabi/test/CMakeLists.txt | 1 + libcxxabi/test/backtrace_test.pass.cpp | 3 + libcxxabi/test/catch_array_01.pass.cpp | 2 +- libcxxabi/test/catch_array_02.pass.cpp | 1 + libcxxabi/test/catch_class_01.pass.cpp | 2 + libcxxabi/test/catch_class_02.pass.cpp | 2 + libcxxabi/test/catch_class_03.pass.cpp | 2 + libcxxabi/test/catch_class_04.pass.cpp | 2 + .../test/catch_const_pointer_nullptr.pass.cpp | 2 + libcxxabi/test/catch_function_01.pass.cpp | 1 + libcxxabi/test/catch_function_02.pass.cpp | 1 + libcxxabi/test/catch_in_noexcept.pass.cpp | 2 +- .../catch_member_data_pointer_01.pass.cpp | 2 + .../catch_member_function_pointer_01.pass.cpp | 1 + .../catch_member_pointer_nullptr.pass.cpp | 2 + .../test/catch_multi_level_pointer.pass.cpp | 2 + libcxxabi/test/catch_pointer_nullptr.pass.cpp | 2 +- .../test/catch_pointer_reference.pass.cpp | 2 + libcxxabi/test/catch_ptr.pass.cpp | 2 + libcxxabi/test/catch_ptr_02.pass.cpp | 2 + libcxxabi/test/cxa_bad_cast.pass.cpp | 55 +++++++++++++++++ libcxxabi/test/cxa_bad_typeid.pass.cpp | 55 +++++++++++++++++ libcxxabi/test/incomplete_type.sh.cpp | 2 + libcxxabi/test/inherited_exception.pass.cpp | 2 + libcxxabi/test/libcxxabi/test/config.py | 7 ++- libcxxabi/test/lit.site.cfg.in | 1 + libcxxabi/test/noexception1.pass.cpp | 38 ++++++++++++ libcxxabi/test/noexception2.pass.cpp | 38 ++++++++++++ libcxxabi/test/noexception3.pass.cpp | 38 ++++++++++++ libcxxabi/test/noexception4.pass.cpp | 29 +++++++++ libcxxabi/test/test_aux_runtime.pass.cpp | 2 + .../test_aux_runtime_op_array_new.pass.cpp | 2 + libcxxabi/test/test_guard.pass.cpp | 4 ++ libcxxabi/test/test_vector1.pass.cpp | 21 ++++++- libcxxabi/test/test_vector2.pass.cpp | 2 + libcxxabi/test/test_vector3.pass.cpp | 2 + libcxxabi/test/uncaught_exceptions.pass.cpp | 2 + libcxxabi/test/unwind_01.pass.cpp | 2 + libcxxabi/test/unwind_02.pass.cpp | 2 + libcxxabi/test/unwind_03.pass.cpp | 2 + libcxxabi/test/unwind_04.pass.cpp | 2 + libcxxabi/test/unwind_05.pass.cpp | 2 + libcxxabi/test/unwind_06.pass.cpp | 2 + 49 files changed, 450 insertions(+), 17 deletions(-) create mode 100644 libcxxabi/src/cxa_noexception.cpp create mode 100644 libcxxabi/test/cxa_bad_cast.pass.cpp create mode 100644 libcxxabi/test/cxa_bad_typeid.pass.cpp create mode 100644 libcxxabi/test/noexception1.pass.cpp create mode 100644 libcxxabi/test/noexception2.pass.cpp create mode 100644 libcxxabi/test/noexception3.pass.cpp create mode 100644 libcxxabi/test/noexception4.pass.cpp diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index 85aa893e04b4..fb52a5ab0cd6 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -108,6 +108,7 @@ endif() #=============================================================================== # Define options. +option(LIBCXXABI_ENABLE_EXCEPTIONS "Use exceptions." ON) option(LIBCXXABI_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON) option(LIBCXXABI_ENABLE_PEDANTIC "Compile with pedantic enabled." ON) option(LIBCXXABI_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) @@ -242,13 +243,20 @@ if (LIBCXXABI_ENABLE_PEDANTIC) endif() # Get feature flags. -# Exceptions -# Catches C++ exceptions only and tells the compiler to assume that extern C -# functions never throw a C++ exception. append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_FSTRICT_ALIASING_FLAG -fstrict-aliasing) -append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_EHSC_FLAG -EHsc) -append_if(LIBCXXABI_C_FLAGS LIBCXXABI_HAS_FUNWIND_TABLES -funwind-tables) +# Exceptions +if (LIBCXXABI_ENABLE_EXCEPTIONS) + # Catches C++ exceptions only and tells the compiler to assume that extern C + # functions never throw a C++ exception. + append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_EHSC_FLAG -EHsc) + append_if(LIBCXXABI_C_FLAGS LIBCXXABI_HAS_FUNWIND_TABLES -funwind-tables) +else() + add_definitions(-D_LIBCXXABI_NO_EXCEPTIONS) + append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_NO_EXCEPTIONS_FLAG -fno-exceptions) + append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_NO_EHS_FLAG -EHs-) + append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_NO_EHA_FLAG -EHa-) +endif() append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden) diff --git a/libcxxabi/src/CMakeLists.txt b/libcxxabi/src/CMakeLists.txt index 502e08367d1c..b851b4ac777a 100644 --- a/libcxxabi/src/CMakeLists.txt +++ b/libcxxabi/src/CMakeLists.txt @@ -4,12 +4,10 @@ set(LIBCXXABI_SOURCES cxa_aux_runtime.cpp cxa_default_handlers.cpp cxa_demangle.cpp - cxa_exception.cpp cxa_exception_storage.cpp cxa_guard.cpp cxa_handlers.cpp cxa_new_delete.cpp - cxa_personality.cpp cxa_unexpected.cpp cxa_vector.cpp cxa_virtual.cpp @@ -19,6 +17,13 @@ set(LIBCXXABI_SOURCES typeinfo.cpp ) +if (LIBCXXABI_ENABLE_EXCEPTIONS) + list(APPEND LIBCXXABI_SOURCES cxa_exception.cpp) + list(APPEND LIBCXXABI_SOURCES cxa_personality.cpp) +else() + list(APPEND LIBCXXABI_SOURCES cxa_noexception.cpp) +endif() + if (UNIX AND NOT (APPLE OR CYGWIN)) list(APPEND LIBCXXABI_SOURCES cxa_thread_atexit.cpp) endif() diff --git a/libcxxabi/src/cxa_aux_runtime.cpp b/libcxxabi/src/cxa_aux_runtime.cpp index a455fad6219e..bb7c9f1255c0 100644 --- a/libcxxabi/src/cxa_aux_runtime.cpp +++ b/libcxxabi/src/cxa_aux_runtime.cpp @@ -17,16 +17,28 @@ namespace __cxxabiv1 { extern "C" { _LIBCXXABI_FUNC_VIS LIBCXXABI_NORETURN void __cxa_bad_cast(void) { +#ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_cast(); +#else + std::terminate(); +#endif } _LIBCXXABI_FUNC_VIS LIBCXXABI_NORETURN void __cxa_bad_typeid(void) { +#ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_typeid(); +#else + std::terminate(); +#endif } _LIBCXXABI_FUNC_VIS LIBCXXABI_NORETURN void __cxa_throw_bad_array_new_length(void) { +#ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_array_new_length(); +#else + std::terminate(); +#endif } } // extern "C" } // abi diff --git a/libcxxabi/src/cxa_handlers.cpp b/libcxxabi/src/cxa_handlers.cpp index c231b5a3ecb7..3f781313df87 100644 --- a/libcxxabi/src/cxa_handlers.cpp +++ b/libcxxabi/src/cxa_handlers.cpp @@ -61,21 +61,21 @@ __attribute__((visibility("hidden"), noreturn)) void __terminate(terminate_handler func) _NOEXCEPT { -#if __has_feature(cxx_exceptions) +#ifndef _LIBCXXABI_NO_EXCEPTIONS try { -#endif // __has_feature(cxx_exceptions) +#endif // _LIBCXXABI_NO_EXCEPTIONS func(); // handler should not return abort_message("terminate_handler unexpectedly returned"); -#if __has_feature(cxx_exceptions) +#ifndef _LIBCXXABI_NO_EXCEPTIONS } catch (...) { // handler should not throw exception abort_message("terminate_handler unexpectedly threw an exception"); } -#endif // #if __has_feature(cxx_exceptions) +#endif // _LIBCXXABI_NO_EXCEPTIONS } __attribute__((noreturn)) diff --git a/libcxxabi/src/cxa_new_delete.cpp b/libcxxabi/src/cxa_new_delete.cpp index 25a5454e05ee..7a2c864c3115 100644 --- a/libcxxabi/src/cxa_new_delete.cpp +++ b/libcxxabi/src/cxa_new_delete.cpp @@ -47,7 +47,11 @@ operator new(std::size_t size) if (nh) nh(); else +#ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_alloc(); +#else + break; +#endif } return p; } @@ -74,13 +78,17 @@ operator new(size_t size, const std::nothrow_t&) #endif { void* p = 0; +#ifndef _LIBCXXABI_NO_EXCEPTIONS try { +#endif p = ::operator new(size); +#ifndef _LIBCXXABI_NO_EXCEPTIONS } catch (...) { } +#endif return p; } @@ -115,13 +123,17 @@ operator new[](size_t size, const std::nothrow_t&) #endif { void* p = 0; +#ifndef _LIBCXXABI_NO_EXCEPTIONS try { +#endif p = ::operator new[](size); +#ifndef _LIBCXXABI_NO_EXCEPTIONS } catch (...) { } +#endif return p; } diff --git a/libcxxabi/src/cxa_noexception.cpp b/libcxxabi/src/cxa_noexception.cpp new file mode 100644 index 000000000000..e45ceff0165e --- /dev/null +++ b/libcxxabi/src/cxa_noexception.cpp @@ -0,0 +1,60 @@ +//===------------------------- cxa_exception.cpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// This file implements the "Exception Handling APIs" +// http://mentorembedded.github.io/cxx-abi/abi-eh.html +// +//===----------------------------------------------------------------------===// + +// Support functions for the no-exceptions libc++ library + +#include "config.h" +#include "cxxabi.h" + +#include // for std::terminate +#include "cxa_exception.hpp" +#include "cxa_handlers.hpp" + +namespace __cxxabiv1 { + +#pragma GCC visibility push(default) + +extern "C" { + +void +__cxa_increment_exception_refcount(void *thrown_object) throw() { + if (thrown_object != nullptr) + std::terminate(); +} + +void +__cxa_decrement_exception_refcount(void *thrown_object) throw() { + if (thrown_object != nullptr) + std::terminate(); +} + + +void *__cxa_current_primary_exception() throw() { return nullptr; } + +void +__cxa_rethrow_primary_exception(void* thrown_object) { + if (thrown_object != nullptr) + std::terminate(); +} + +bool +__cxa_uncaught_exception() throw() { return false; } + +unsigned int +__cxa_uncaught_exceptions() throw() { return 0; } + +} // extern "C" + +#pragma GCC visibility pop + +} // abi diff --git a/libcxxabi/test/CMakeLists.txt b/libcxxabi/test/CMakeLists.txt index aee9ffa4c8ef..a3de1b3d6d7a 100644 --- a/libcxxabi/test/CMakeLists.txt +++ b/libcxxabi/test/CMakeLists.txt @@ -14,6 +14,7 @@ pythonize_bool(LLVM_BUILD_32_BITS) pythonize_bool(LIBCXX_ENABLE_SHARED) pythonize_bool(LIBCXXABI_ENABLE_SHARED) pythonize_bool(LIBCXXABI_ENABLE_THREADS) +pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS) pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER) pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING diff --git a/libcxxabi/test/backtrace_test.pass.cpp b/libcxxabi/test/backtrace_test.pass.cpp index df291c969693..9954e8b7afae 100644 --- a/libcxxabi/test/backtrace_test.pass.cpp +++ b/libcxxabi/test/backtrace_test.pass.cpp @@ -6,6 +6,9 @@ // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// + +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_array_01.pass.cpp b/libcxxabi/test/catch_array_01.pass.cpp index 933e4b28f603..a927e8f9a6b3 100644 --- a/libcxxabi/test/catch_array_01.pass.cpp +++ b/libcxxabi/test/catch_array_01.pass.cpp @@ -9,10 +9,10 @@ // Can you have a catch clause of array type that catches anything? - // GCC incorrectly allows array types to be caught by reference. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69372 // XFAIL: gcc +// UNSUPPORTED: libcxxabi-no-exceptions #include diff --git a/libcxxabi/test/catch_array_02.pass.cpp b/libcxxabi/test/catch_array_02.pass.cpp index a06e6aaa0565..65cf8cd65fb4 100644 --- a/libcxxabi/test/catch_array_02.pass.cpp +++ b/libcxxabi/test/catch_array_02.pass.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// // Can you have a catch clause of array type that catches anything? +// UNSUPPORTED: libcxxabi-no-exceptions #include diff --git a/libcxxabi/test/catch_class_01.pass.cpp b/libcxxabi/test/catch_class_01.pass.cpp index fb728b5252b1..bc46b4e72af7 100644 --- a/libcxxabi/test/catch_class_01.pass.cpp +++ b/libcxxabi/test/catch_class_01.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_class_02.pass.cpp b/libcxxabi/test/catch_class_02.pass.cpp index e1370363d554..2249602ec432 100644 --- a/libcxxabi/test/catch_class_02.pass.cpp +++ b/libcxxabi/test/catch_class_02.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_class_03.pass.cpp b/libcxxabi/test/catch_class_03.pass.cpp index ad0c9ad8d79d..f038f798e212 100644 --- a/libcxxabi/test/catch_class_03.pass.cpp +++ b/libcxxabi/test/catch_class_03.pass.cpp @@ -13,6 +13,8 @@ check against. */ +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_class_04.pass.cpp b/libcxxabi/test/catch_class_04.pass.cpp index c0e717049010..444b1de59d19 100644 --- a/libcxxabi/test/catch_class_04.pass.cpp +++ b/libcxxabi/test/catch_class_04.pass.cpp @@ -13,6 +13,8 @@ check against. It also checks that virtual bases work properly */ +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp b/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp index 417a2aa13b1e..6e86f3685c25 100644 --- a/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp +++ b/libcxxabi/test/catch_const_pointer_nullptr.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #if __has_feature(cxx_nullptr) diff --git a/libcxxabi/test/catch_function_01.pass.cpp b/libcxxabi/test/catch_function_01.pass.cpp index 1bdda69f1afe..4eb69143a280 100644 --- a/libcxxabi/test/catch_function_01.pass.cpp +++ b/libcxxabi/test/catch_function_01.pass.cpp @@ -12,6 +12,7 @@ // GCC incorrectly allows function pointer to be caught by reference. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69372 // XFAIL: gcc +// UNSUPPORTED: libcxxabi-no-exceptions #include diff --git a/libcxxabi/test/catch_function_02.pass.cpp b/libcxxabi/test/catch_function_02.pass.cpp index 8bff8d912e91..adef92c962bc 100644 --- a/libcxxabi/test/catch_function_02.pass.cpp +++ b/libcxxabi/test/catch_function_02.pass.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// // Can you have a catch clause of array type that catches anything? +// UNSUPPORTED: libcxxabi-no-exceptions #include diff --git a/libcxxabi/test/catch_in_noexcept.pass.cpp b/libcxxabi/test/catch_in_noexcept.pass.cpp index 7e48ed2507a9..d7b9c4849dfb 100644 --- a/libcxxabi/test/catch_in_noexcept.pass.cpp +++ b/libcxxabi/test/catch_in_noexcept.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions #include #include diff --git a/libcxxabi/test/catch_member_data_pointer_01.pass.cpp b/libcxxabi/test/catch_member_data_pointer_01.pass.cpp index 28bf4b569b90..c6427efc238d 100644 --- a/libcxxabi/test/catch_member_data_pointer_01.pass.cpp +++ b/libcxxabi/test/catch_member_data_pointer_01.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include struct A diff --git a/libcxxabi/test/catch_member_function_pointer_01.pass.cpp b/libcxxabi/test/catch_member_function_pointer_01.pass.cpp index 9b817304c0ca..b7bdcb64ad74 100644 --- a/libcxxabi/test/catch_member_function_pointer_01.pass.cpp +++ b/libcxxabi/test/catch_member_function_pointer_01.pass.cpp @@ -10,6 +10,7 @@ // GCC incorrectly allows PMF type "void (T::*)()" to be caught as "void (T::*)() const" // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69375 // XFAIL: gcc +// UNSUPPORTED: libcxxabi-no-exceptions #include struct A diff --git a/libcxxabi/test/catch_member_pointer_nullptr.pass.cpp b/libcxxabi/test/catch_member_pointer_nullptr.pass.cpp index 73e6c7b9e75c..fb73d97265d3 100644 --- a/libcxxabi/test/catch_member_pointer_nullptr.pass.cpp +++ b/libcxxabi/test/catch_member_pointer_nullptr.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #if __has_feature(cxx_nullptr) diff --git a/libcxxabi/test/catch_multi_level_pointer.pass.cpp b/libcxxabi/test/catch_multi_level_pointer.pass.cpp index 3246099fa56a..770cf6b24f04 100644 --- a/libcxxabi/test/catch_multi_level_pointer.pass.cpp +++ b/libcxxabi/test/catch_multi_level_pointer.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_pointer_nullptr.pass.cpp b/libcxxabi/test/catch_pointer_nullptr.pass.cpp index 7caee7b3aa0e..e0acb89f59d0 100644 --- a/libcxxabi/test/catch_pointer_nullptr.pass.cpp +++ b/libcxxabi/test/catch_pointer_nullptr.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions #include #include diff --git a/libcxxabi/test/catch_pointer_reference.pass.cpp b/libcxxabi/test/catch_pointer_reference.pass.cpp index 88d2140b759b..b1b75354a787 100644 --- a/libcxxabi/test/catch_pointer_reference.pass.cpp +++ b/libcxxabi/test/catch_pointer_reference.pass.cpp @@ -25,6 +25,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_ptr.pass.cpp b/libcxxabi/test/catch_ptr.pass.cpp index b833e2bae845..6f85d6370b5d 100644 --- a/libcxxabi/test/catch_ptr.pass.cpp +++ b/libcxxabi/test/catch_ptr.pass.cpp @@ -13,6 +13,8 @@ check against. It also checks that virtual bases work properly */ +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/catch_ptr_02.pass.cpp b/libcxxabi/test/catch_ptr_02.pass.cpp index c3c4400b45d3..a58474b99c4e 100644 --- a/libcxxabi/test/catch_ptr_02.pass.cpp +++ b/libcxxabi/test/catch_ptr_02.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #if __cplusplus < 201103L diff --git a/libcxxabi/test/cxa_bad_cast.pass.cpp b/libcxxabi/test/cxa_bad_cast.pass.cpp new file mode 100644 index 000000000000..c863d6f3ffe2 --- /dev/null +++ b/libcxxabi/test/cxa_bad_cast.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------- cxa_bad_cast.pass.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +#include +#include +#include +#include +#include + +class Base { + virtual void foo() {}; +}; + +class Derived : public Base {}; + +Derived &test_bad_cast(Base b) { + return dynamic_cast(b); +} + +Base gB; + +void my_terminate() { exit(0); } + +int main () +{ + // swap-out the terminate handler + void (*default_handler)() = std::get_terminate(); + std::set_terminate(my_terminate); + +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS + try { +#endif + Derived &d = test_bad_cast(gB); + assert(false); +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS + } catch (std::bad_cast) { + // success + return 0; + } catch (...) { + assert(false); + } +#endif + + // failure, restore the default terminate handler and fire + std::set_terminate(default_handler); + std::terminate(); +} diff --git a/libcxxabi/test/cxa_bad_typeid.pass.cpp b/libcxxabi/test/cxa_bad_typeid.pass.cpp new file mode 100644 index 000000000000..d747ff29eabd --- /dev/null +++ b/libcxxabi/test/cxa_bad_typeid.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------- cxa_bad_typeid.pass.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===------------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +#include +#include +#include +#include +#include +#include +#include + +class Base { + virtual void foo() {}; +}; + +class Derived : public Base {}; + +std::string test_bad_typeid(Derived *p) { + typeid(*p).name(); +} + +void my_terminate() { std::cout << "A" << std::endl; exit(0); } + +int main () +{ + // swap-out the terminate handler + void (*default_handler)() = std::get_terminate(); + std::set_terminate(my_terminate); + +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS + try { +#endif + test_bad_typeid(nullptr); + assert(false); +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS + } catch (std::bad_typeid) { + // success + return 0; + } catch (...) { + assert(false); + } +#endif + + // failure, restore the default terminate handler and fire + std::set_terminate(default_handler); + std::terminate(); +} diff --git a/libcxxabi/test/incomplete_type.sh.cpp b/libcxxabi/test/incomplete_type.sh.cpp index 699844597c77..701a0378d526 100644 --- a/libcxxabi/test/incomplete_type.sh.cpp +++ b/libcxxabi/test/incomplete_type.sh.cpp @@ -14,6 +14,8 @@ // incomplete flags set, equality can be tested by comparing the type_info // addresses. +// UNSUPPORTED: libcxxabi-no-exceptions + // RUN: %cxx %flags %compile_flags -c %s -o %t.one.o // RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE // RUN: %cxx %flags %t.one.o %t.two.o %link_flags -o %t.exe diff --git a/libcxxabi/test/inherited_exception.pass.cpp b/libcxxabi/test/inherited_exception.pass.cpp index 7c106c1e6123..763e26a434f6 100644 --- a/libcxxabi/test/inherited_exception.pass.cpp +++ b/libcxxabi/test/inherited_exception.pass.cpp @@ -25,6 +25,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include struct Base { diff --git a/libcxxabi/test/libcxxabi/test/config.py b/libcxxabi/test/libcxxabi/test/config.py index 766cdfa73e2c..c8a6af0f3db5 100644 --- a/libcxxabi/test/libcxxabi/test/config.py +++ b/libcxxabi/test/libcxxabi/test/config.py @@ -35,12 +35,17 @@ class Configuration(LibcxxConfiguration): def configure_features(self): super(Configuration, self).configure_features() + if not self.get_lit_bool('enable_exceptions', True): + self.config.available_features.add('libcxxabi-no-exceptions') if self.get_lit_bool('thread_atexit', True): self.config.available_features.add('thread_atexit') def configure_compile_flags(self): self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER'] - self.cxx.compile_flags += ['-funwind-tables'] + if self.get_lit_bool('enable_exceptions', True): + self.cxx.compile_flags += ['-funwind-tables'] + else: + self.cxx.compile_flags += ['-fno-exceptions', '-DLIBCXXABI_HAS_NO_EXCEPTIONS'] if not self.get_lit_bool('enable_threads', True): self.cxx.compile_flags += ['-DLIBCXXABI_HAS_NO_THREADS=1'] super(Configuration, self).configure_compile_flags() diff --git a/libcxxabi/test/lit.site.cfg.in b/libcxxabi/test/lit.site.cfg.in index 7a5836932ad4..70eee8a11db7 100644 --- a/libcxxabi/test/lit.site.cfg.in +++ b/libcxxabi/test/lit.site.cfg.in @@ -16,6 +16,7 @@ config.executor = "@LIBCXXABI_EXECUTOR@" config.thread_atexit = "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@" config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@" config.enable_shared = "@LIBCXX_ENABLE_SHARED@" +config.enable_exceptions = "@LIBCXXABI_ENABLE_EXCEPTIONS@" # Let the main config do the real work. lit_config.load_config(config, "@LIBCXXABI_SOURCE_DIR@/test/lit.cfg") diff --git a/libcxxabi/test/noexception1.pass.cpp b/libcxxabi/test/noexception1.pass.cpp new file mode 100644 index 000000000000..59d59a7f9664 --- /dev/null +++ b/libcxxabi/test/noexception1.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------- noexception1.pass.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// REQUIRES: libcxxabi-no-exceptions + +#include +#include +#include +#include + +// namespace __cxxabiv1 { +// void __cxa_increment_exception_refcount(void *thrown_object) throw(); +// } + +unsigned gCounter = 0; + +void my_terminate() { exit(0); } + +int main () +{ + // should not call std::terminate() + __cxxabiv1::__cxa_increment_exception_refcount(nullptr); + + std::set_terminate(my_terminate); + + // should call std::terminate() + __cxxabiv1::__cxa_increment_exception_refcount((void*) &gCounter); + assert(false); + + return 0; +} diff --git a/libcxxabi/test/noexception2.pass.cpp b/libcxxabi/test/noexception2.pass.cpp new file mode 100644 index 000000000000..d9d10d5fa3e2 --- /dev/null +++ b/libcxxabi/test/noexception2.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------- noexception2.pass.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// REQUIRES: libcxxabi-no-exceptions + +#include +#include +#include +#include + +// namespace __cxxabiv1 { +// void __cxa_decrement_exception_refcount(void *thrown_object) throw(); +// } + +unsigned gCounter = 0; + +void my_terminate() { exit(0); } + +int main () +{ + // should not call std::terminate() + __cxxabiv1::__cxa_decrement_exception_refcount(nullptr); + + std::set_terminate(my_terminate); + + // should call std::terminate() + __cxxabiv1::__cxa_decrement_exception_refcount((void*) &gCounter); + assert(false); + + return 0; +} diff --git a/libcxxabi/test/noexception3.pass.cpp b/libcxxabi/test/noexception3.pass.cpp new file mode 100644 index 000000000000..081c2d07ad2b --- /dev/null +++ b/libcxxabi/test/noexception3.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------- noexception3.pass.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// REQUIRES: libcxxabi-no-exceptions + +#include +#include +#include +#include + +// namespace __cxxabiv1 { +// void __cxa_rethrow_primary_exception(void* thrown_object); +// } + +unsigned gCounter = 0; + +void my_terminate() { exit(0); } + +int main () +{ + // should not call std::terminate() + __cxxabiv1::__cxa_rethrow_primary_exception(nullptr); + + std::set_terminate(my_terminate); + + // should call std::terminate() + __cxxabiv1::__cxa_rethrow_primary_exception((void*) &gCounter); + assert(false); + + return 0; +} diff --git a/libcxxabi/test/noexception4.pass.cpp b/libcxxabi/test/noexception4.pass.cpp new file mode 100644 index 000000000000..dbf6012d0e16 --- /dev/null +++ b/libcxxabi/test/noexception4.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------- noexception4.pass.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: libcxxabi-no-exceptions + +#include +#include +#include + +// namespace __cxxabiv1 { +// void *__cxa_current_primary_exception() throw(); +// extern bool __cxa_uncaught_exception () throw(); +// extern unsigned int __cxa_uncaught_exceptions() throw(); +// } + +int main () +{ + // Trivially + assert(nullptr == __cxxabiv1::__cxa_current_primary_exception()); + assert(!__cxxabiv1::__cxa_uncaught_exception()); + assert(0 == __cxxabiv1::__cxa_uncaught_exceptions()); + return 0; +} diff --git a/libcxxabi/test/test_aux_runtime.pass.cpp b/libcxxabi/test/test_aux_runtime.pass.cpp index 5506ee335f98..a9f240e5d4d5 100644 --- a/libcxxabi/test/test_aux_runtime.pass.cpp +++ b/libcxxabi/test/test_aux_runtime.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include diff --git a/libcxxabi/test/test_aux_runtime_op_array_new.pass.cpp b/libcxxabi/test/test_aux_runtime_op_array_new.pass.cpp index 8d9f547a3151..701a457a201a 100644 --- a/libcxxabi/test/test_aux_runtime_op_array_new.pass.cpp +++ b/libcxxabi/test/test_aux_runtime_op_array_new.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include diff --git a/libcxxabi/test/test_guard.pass.cpp b/libcxxabi/test/test_guard.pass.cpp index 41ff79432b56..9b0c2d5ab71e 100644 --- a/libcxxabi/test/test_guard.pass.cpp +++ b/libcxxabi/test/test_guard.pass.cpp @@ -41,6 +41,7 @@ namespace test1 { // When initialization fails, ensure that we try to initialize it again next // time. namespace test2 { +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS static int run_count = 0; int increment() { ++run_count; @@ -58,6 +59,9 @@ namespace test2 { helper(); assert(run_count == 2); } +#else + void test() {} +#endif } // Check that we can initialize a second value while initializing a first. diff --git a/libcxxabi/test/test_vector1.pass.cpp b/libcxxabi/test/test_vector1.pass.cpp index 6790cb5aa7db..978ed3ca3849 100644 --- a/libcxxabi/test/test_vector1.pass.cpp +++ b/libcxxabi/test/test_vector1.pass.cpp @@ -47,8 +47,19 @@ int gConstructorCounter; int gConstructorThrowTarget; int gDestructorCounter; int gDestructorThrowTarget; -void throw_construct ( void *p ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; } -void throw_destruct ( void *p ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; } +void throw_construct ( void *p ) { +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS + if ( gConstructorCounter == gConstructorThrowTarget ) + throw 1; + ++gConstructorCounter; +#endif +} +void throw_destruct ( void *p ) { +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS + if ( ++gDestructorCounter == gDestructorThrowTarget ) + throw 2; +#endif +} #if __cplusplus >= 201103L # define CAN_THROW noexcept(false) @@ -146,6 +157,7 @@ int test_counted ( ) { return retVal; } +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS // Make sure the constructors and destructors are matched int test_exception_in_constructor ( ) { int retVal = 0; @@ -202,7 +214,9 @@ int test_exception_in_constructor ( ) { return retVal; } +#endif +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS // Make sure the constructors and destructors are matched int test_exception_in_destructor ( ) { int retVal = 0; @@ -253,12 +267,15 @@ int test_exception_in_destructor ( ) { return retVal; } +#endif int main ( int argc, char *argv [] ) { int retVal = 0; retVal += test_empty (); retVal += test_counted (); +#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS retVal += test_exception_in_constructor (); retVal += test_exception_in_destructor (); +#endif return retVal; } diff --git a/libcxxabi/test/test_vector2.pass.cpp b/libcxxabi/test/test_vector2.pass.cpp index 1cb7d9c27078..4bc279d75b9a 100644 --- a/libcxxabi/test/test_vector2.pass.cpp +++ b/libcxxabi/test/test_vector2.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include "cxxabi.h" #include diff --git a/libcxxabi/test/test_vector3.pass.cpp b/libcxxabi/test/test_vector3.pass.cpp index 3855027b5a25..a81712595f1d 100644 --- a/libcxxabi/test/test_vector3.pass.cpp +++ b/libcxxabi/test/test_vector3.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include "cxxabi.h" #include diff --git a/libcxxabi/test/uncaught_exceptions.pass.cpp b/libcxxabi/test/uncaught_exceptions.pass.cpp index fd4b8f416460..0c6406708390 100644 --- a/libcxxabi/test/uncaught_exceptions.pass.cpp +++ b/libcxxabi/test/uncaught_exceptions.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/unwind_01.pass.cpp b/libcxxabi/test/unwind_01.pass.cpp index 9d237f894463..1bf6cfde3994 100644 --- a/libcxxabi/test/unwind_01.pass.cpp +++ b/libcxxabi/test/unwind_01.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include struct A diff --git a/libcxxabi/test/unwind_02.pass.cpp b/libcxxabi/test/unwind_02.pass.cpp index 94d53adc4165..90dc25ab90f8 100644 --- a/libcxxabi/test/unwind_02.pass.cpp +++ b/libcxxabi/test/unwind_02.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include struct A diff --git a/libcxxabi/test/unwind_03.pass.cpp b/libcxxabi/test/unwind_03.pass.cpp index 8af1d2b3fd60..bda8c316c22b 100644 --- a/libcxxabi/test/unwind_03.pass.cpp +++ b/libcxxabi/test/unwind_03.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/unwind_04.pass.cpp b/libcxxabi/test/unwind_04.pass.cpp index 0fc6587e8239..b5a08afcbe5a 100644 --- a/libcxxabi/test/unwind_04.pass.cpp +++ b/libcxxabi/test/unwind_04.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/unwind_05.pass.cpp b/libcxxabi/test/unwind_05.pass.cpp index b994c19939d3..3dea2aadde59 100644 --- a/libcxxabi/test/unwind_05.pass.cpp +++ b/libcxxabi/test/unwind_05.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include diff --git a/libcxxabi/test/unwind_06.pass.cpp b/libcxxabi/test/unwind_06.pass.cpp index dd505c8e92aa..a30efb1f01c5 100644 --- a/libcxxabi/test/unwind_06.pass.cpp +++ b/libcxxabi/test/unwind_06.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcxxabi-no-exceptions + #include #include #include