diff options
Diffstat (limited to 'libcxx')
-rw-r--r-- | libcxx/docs/DesignDocs/DebugMode.rst | 100 | ||||
-rw-r--r-- | libcxx/docs/UsingLibcxx.rst | 12 | ||||
-rw-r--r-- | libcxx/docs/index.rst | 1 | ||||
-rw-r--r-- | libcxx/include/__config | 11 | ||||
-rw-r--r-- | libcxx/include/__debug | 76 | ||||
-rw-r--r-- | libcxx/lib/abi/CHANGELOG.TXT | 22 | ||||
-rw-r--r-- | libcxx/lib/abi/x86_64-apple-darwin16.0.0.abilist | 16 | ||||
-rw-r--r-- | libcxx/lib/abi/x86_64-unknown-linux-gnu.abilist | 17 | ||||
-rw-r--r-- | libcxx/src/debug.cpp | 61 | ||||
-rw-r--r-- | libcxx/test/libcxx/debug/debug_abort.pass.cpp | 30 | ||||
-rw-r--r-- | libcxx/test/libcxx/debug/debug_throw.pass.cpp | 36 | ||||
-rw-r--r-- | libcxx/test/libcxx/debug/debug_throw_register.pass.cpp | 30 | ||||
-rw-r--r-- | libcxx/www/debug_mode.html | 162 | ||||
-rw-r--r-- | libcxx/www/index.html | 1 |
14 files changed, 389 insertions, 186 deletions
diff --git a/libcxx/docs/DesignDocs/DebugMode.rst b/libcxx/docs/DesignDocs/DebugMode.rst new file mode 100644 index 00000000000..166c733e663 --- /dev/null +++ b/libcxx/docs/DesignDocs/DebugMode.rst @@ -0,0 +1,100 @@ +========== +Debug Mode +========== + +.. contents:: + :local + +.. _using-debug-mode: + +Using Debug Mode +================ + +Libc++ provides a debug mode that enables assertions meant to detect incorrect +usage of the standard library. By default these assertions are disabled but +they can be enabled using the ``_LIBCPP_DEBUG`` macro. + +**_LIBCPP_DEBUG** Macro +----------------------- + +**_LIBCPP_DEBUG**: + This macro is used to enable assertions and iterator debugging checks within + libc++. By default it is undefined. + + **Values**: ``0``, ``1`` + + Defining ``_LIBCPP_DEBUG`` to ``0`` or greater enables most of libc++'s + assertions. Defining ``_LIBCPP_DEBUG`` to ``1`` enables "iterator debugging" + which provides additional assertions about the validity of iterators used by + the program. + + Note that this option has no effect on libc++'s ABI + +**_LIBCPP_DEBUG_USE_EXCEPTIONS**: + When this macro is defined ``_LIBCPP_ASSERT`` failures throw + ``__libcpp_debug_exception`` instead of aborting. Additionally this macro + disables exception specifications on functions containing ``_LIBCPP_ASSERT`` + checks. This allows assertion failures to correctly throw through these + functions. + +Handling Assertion Failures +--------------------------- + +When a debug assertion fails the assertion handler is called via the +``std::__libcpp_debug_function`` function pointer. It is possible to override +this function pointer using a different handler function. Libc++ provides two +different assertion handlers, the default handler +``std::__libcpp_abort_debug_handler`` which aborts the program, and +``std::__libcpp_throw_debug_handler`` which throws an instance of +``std::__libcpp_debug_exception``. Libc++ can be changed to use the throwing +assertion handler as follows: + +.. code-block:: cpp + + #define _LIBCPP_DEBUG 1 + #include <string> + int main() { + std::__libcpp_debug_function = std::__libcpp_throw_debug_function; + try { + std::string::iterator bad_it; + std::string str("hello world"); + str.insert(bad_it, '!'); // causes debug assertion + } catch (std::__libcpp_debug_exception const&) { + return EXIT_SUCCESS; + } + return EXIT_FAILURE; + } + +Debug Mode Checks +================= + +Libc++'s debug mode offers two levels of checking. The first enables various +precondition checks throughout libc++. The second additionally enables +"iterator debugging" which checks the validity of iterators used by the program. + +Basic Checks +============ + +These checks are enabled when ``_LIBCPP_DEBUG`` is defined to either 0 or 1. + +The following checks are enabled by ``_LIBCPP_DEBUG``: + + * FIXME: Update this list + +Iterator Debugging Checks +========================= + +These checks are enabled when ``_LIBCPP_DEBUG`` is defined to 1. + +The following containers and STL classes support iterator debugging: + + * ``std::string`` + * ``std::vector<T>`` (``T != bool``) + * ``std::list`` + * ``std::unordered_map`` + * ``std::unordered_multimap`` + * ``std::unordered_set`` + * ``std::unordered_multiset`` + +The remaining containers do not currently support iterator debugging. +Patches welcome. diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index d6d1095b83c..de87c9c159d 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -133,17 +133,7 @@ or disable extended libc++ behavior, including enabling "debug mode" or thread safety annotations. **_LIBCPP_DEBUG**: - This macro is used to enable assertions and other debugging checks within - libc++. All debugging checks are disabled by default. - - **Values**: ``0``, ``1`` - - Defining ``_LIBCPP_DEBUG`` to ``0`` or greater enables most of libc++'s - assertions. Defining ``_LIBCPP_DEBUG`` to ``1`` enables "iterator debugging" - which provides additional assertions about the validity of iterators used by - the program. - - Note that this option has no effect on libc++'s ABI + See :ref:`using-debug-mode` for more information. **_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS**: This macro is used to enable -Wthread-safety annotations on libc++'s diff --git a/libcxx/docs/index.rst b/libcxx/docs/index.rst index 0cac7fe98a9..c62dfe83392 100644 --- a/libcxx/docs/index.rst +++ b/libcxx/docs/index.rst @@ -127,6 +127,7 @@ Design Documents .. toctree:: :maxdepth: 1 + DesignDocs/DebugMode DesignDocs/CapturingConfigInfo DesignDocs/ABIVersioning DesignDocs/VisibilityMacros diff --git a/libcxx/include/__config b/libcxx/include/__config index d6ab2345ca5..868914d9899 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -651,6 +651,17 @@ namespace std { # define _NOEXCEPT_(x) #endif +#if defined(_LIBCPP_DEBUG_USE_EXCEPTIONS) +# if !defined(_LIBCPP_DEBUG) +# error cannot use _LIBCPP_DEBUG_USE_EXCEPTIONS unless _LIBCPP_DEBUG is defined +# endif +# define _NOEXCEPT_DEBUG noexcept(false) +# define _NOEXCEPT_DEBUG_(x) noexcept(false) +#else +# define _NOEXCEPT_DEBUG _NOEXCEPT +# define _NOEXCEPT_DEBUG_(x) _NOEXCEPT_(x) +#endif + #ifdef _LIBCPP_HAS_NO_UNICODE_CHARS typedef unsigned short char16_t; typedef unsigned int char32_t; diff --git a/libcxx/include/__debug b/libcxx/include/__debug index e67dd086bf6..e3a5ec965b4 100644 --- a/libcxx/include/__debug +++ b/libcxx/include/__debug @@ -17,13 +17,16 @@ #pragma GCC system_header #endif -#if _LIBCPP_DEBUG_LEVEL >= 1 +#if _LIBCPP_DEBUG_LEVEL >= 1 || defined(_LIBCPP_BUILDING_LIBRARY) # include <cstdlib> # include <cstdio> # include <cstddef> -# ifndef _LIBCPP_ASSERT -# define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (_VSTD::fprintf(stderr, "%s\n", m), _VSTD::abort())) -# endif +# include <exception> +#endif + +#if _LIBCPP_DEBUG_LEVEL >= 1 && !defined(_LIBCPP_ASSERT) +# define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : \ + _VSTD::__libcpp_debug_function(_VSTD::__libcpp_debug_info{__FILE__, __LINE__, #x, m})) #endif #if _LIBCPP_DEBUG_LEVEL >= 2 @@ -43,10 +46,61 @@ #define _LIBCPP_DEBUG_MODE(...) ((void)0) #endif -#if _LIBCPP_DEBUG_LEVEL >= 2 +#if _LIBCPP_DEBUG_LEVEL < 1 +class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception; +#endif _LIBCPP_BEGIN_NAMESPACE_STD +struct _LIBCPP_TYPE_VIS_ONLY __libcpp_debug_info { + const char* __file_; + int __line_; + const char* __pred_; + const char* __msg_; +}; + +/// __libcpp_debug_function_type - The type of the assertion failure handler. +typedef void(*__libcpp_debug_function_type)(__libcpp_debug_info const&); + +/// __libcpp_debug_function - The handler function called when a _LIBCPP_ASSERT +/// fails. +extern __libcpp_debug_function_type __libcpp_debug_function; + +/// __libcpp_abort_debug_function - A debug handler that aborts when called. +_LIBCPP_NORETURN _LIBCPP_FUNC_VIS +void __libcpp_abort_debug_function(__libcpp_debug_info const&); + +/// __libcpp_throw_debug_function - A debug handler that throws +/// an instance of __libcpp_debug_exception when called. + _LIBCPP_NORETURN _LIBCPP_FUNC_VIS +void __libcpp_throw_debug_function(__libcpp_debug_info const&); + +/// __libcpp_set_debug_function - Set the debug handler to the specified +/// function. +_LIBCPP_FUNC_VIS +bool __libcpp_set_debug_function(__libcpp_debug_function_type __func); + +// Setup the throwing debug handler during dynamic initialization. +#if _LIBCPP_DEBUG_LEVEL >= 1 && defined(_LIBCPP_DEBUG_USE_EXCEPTIONS) +static bool __init_dummy = __libcpp_set_debug_function(__libcpp_throw_debug_function); +#endif + +#if _LIBCPP_DEBUG_LEVEL >= 1 || defined(_LIBCPP_BUILDING_LIBRARY) +class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception : public exception { +public: + __libcpp_debug_exception() _NOEXCEPT; + explicit __libcpp_debug_exception(__libcpp_debug_info const& __i); + __libcpp_debug_exception(__libcpp_debug_exception const&); + ~__libcpp_debug_exception() _NOEXCEPT; + const char* what() const _NOEXCEPT; +private: + struct __libcpp_debug_exception_imp; + __libcpp_debug_exception_imp *__imp_; +}; +#endif + +#if _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY) + struct _LIBCPP_TYPE_VIS __c_node; struct _LIBCPP_TYPE_VIS __i_node @@ -115,7 +169,7 @@ struct _C_node }; template <class _Cont> -bool +inline bool _C_node<_Cont>::__dereferenceable(const void* __i) const { typedef typename _Cont::const_iterator iterator; @@ -125,7 +179,7 @@ _C_node<_Cont>::__dereferenceable(const void* __i) const } template <class _Cont> -bool +inline bool _C_node<_Cont>::__decrementable(const void* __i) const { typedef typename _Cont::const_iterator iterator; @@ -135,7 +189,7 @@ _C_node<_Cont>::__decrementable(const void* __i) const } template <class _Cont> -bool +inline bool _C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const { typedef typename _Cont::const_iterator iterator; @@ -145,7 +199,7 @@ _C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const } template <class _Cont> -bool +inline bool _C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const { typedef typename _Cont::const_iterator iterator; @@ -227,9 +281,9 @@ _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); _LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); -_LIBCPP_END_NAMESPACE_STD +#endif // _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY) -#endif +_LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_DEBUG_H diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT index 488d7b76ea7..bccca2e085e 100644 --- a/libcxx/lib/abi/CHANGELOG.TXT +++ b/libcxx/lib/abi/CHANGELOG.TXT @@ -16,6 +16,28 @@ New entries should be added directly below the "Version" header. Version 4.0 ----------- +* rTBD - Add _LIBCPP_ASSERT debug handling functions + + All Platforms + ------------- + Symbol added: _ZNSt3__124__libcpp_debug_exceptionC2ERKNS_19__libcpp_debug_infoE + Symbol added: _ZNSt3__124__libcpp_debug_exceptionD1Ev + Symbol added: _ZTINSt3__124__libcpp_debug_exceptionE + Symbol added: _ZNSt3__129__libcpp_throw_debug_functionERKNS_19__libcpp_debug_infoE + Symbol added: _ZNSt3__124__libcpp_debug_exceptionD2Ev + Symbol added: _ZNSt3__129__libcpp_abort_debug_functionERKNS_19__libcpp_debug_infoE + Symbol added: _ZNSt3__124__libcpp_debug_exceptionC2ERKS0_ + Symbol added: _ZNSt3__124__libcpp_debug_exceptionC1Ev + Symbol added: _ZNSt3__124__libcpp_debug_exceptionC1ERKNS_19__libcpp_debug_infoE + Symbol added: _ZNSt3__124__libcpp_debug_exceptionC2Ev + Symbol added: _ZTSNSt3__124__libcpp_debug_exceptionE + Symbol added: _ZNSt3__123__libcpp_debug_functionE + Symbol added: _ZNKSt3__124__libcpp_debug_exception4whatEv + Symbol added: _ZNSt3__124__libcpp_debug_exceptionC1ERKS0_ + Symbol added: _ZNSt3__124__libcpp_debug_exceptionD0Ev + Symbol added: _ZTVNSt3__124__libcpp_debug_exceptionE + Symbol added: _ZNSt3__127__libcpp_set_debug_functionEPFvRKNS_19__libcpp_debug_infoEE + * r288547 - Implement C++17 <variant> All Platforms diff --git a/libcxx/lib/abi/x86_64-apple-darwin16.0.0.abilist b/libcxx/lib/abi/x86_64-apple-darwin16.0.0.abilist index 1b6acad008a..f7218a45fbb 100644 --- a/libcxx/lib/abi/x86_64-apple-darwin16.0.0.abilist +++ b/libcxx/lib/abi/x86_64-apple-darwin16.0.0.abilist @@ -262,6 +262,7 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__121__basic_string_commonILb1EE20__throw_out_of_rangeEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__123__match_any_but_newlineIcE6__execERNS_7__stateIcEE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__123__match_any_but_newlineIwE6__execERNS_7__stateIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__124__libcpp_debug_exception4whatEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE10do_tolowerEPcPKc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE10do_tolowerEc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE10do_toupperEPcPKc'} @@ -1212,6 +1213,16 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutexD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutexD2Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121undeclare_no_pointersEPcm'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__123__libcpp_debug_functionE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionC1ERKNS_19__libcpp_debug_infoE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionC1ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionC2ERKNS_19__libcpp_debug_infoE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionC2ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__124__libcpp_debug_exceptionD2Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_'} @@ -1228,6 +1239,9 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIwwEEPwEEbT0_S5_T_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIxxEEPxEEbT0_S5_T_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIyyEEPyEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__127__libcpp_set_debug_functionEPFvRKNS_19__libcpp_debug_infoEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__129__libcpp_abort_debug_functionERKNS_19__libcpp_debug_infoE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__129__libcpp_throw_debug_functionERKNS_19__libcpp_debug_infoE'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__13cinE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__14cerrE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__14clogE', 'size': 0} @@ -1651,6 +1665,7 @@ {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__120__codecvt_utf8_utf16IwEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__120__time_get_c_storageIcEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__120__time_get_c_storageIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__124__libcpp_debug_exceptionE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__15ctypeIcEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__15ctypeIwEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__16locale5facetE', 'size': 0} @@ -2182,6 +2197,7 @@ {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__120__codecvt_utf8_utf16IDiEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__120__codecvt_utf8_utf16IDsEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__120__codecvt_utf8_utf16IwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__124__libcpp_debug_exceptionE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__15ctypeIcEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__15ctypeIwEE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__16locale5facetE', 'size': 0} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.abilist index a802ae46265..7282fa7b219 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.abilist @@ -252,6 +252,7 @@ {'is_defined': True, 'type': 'FUNC', 'name': '_ZNKSt3__121__basic_string_commonILb1EE20__throw_out_of_rangeEv'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNKSt3__123__match_any_but_newlineIcE6__execERNS_7__stateIcEE'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNKSt3__123__match_any_but_newlineIwE6__execERNS_7__stateIwEE'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNKSt3__124__libcpp_debug_exception4whatEv'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNKSt3__15ctypeIcE10do_tolowerEPcPKc'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNKSt3__15ctypeIcE10do_tolowerEc'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNKSt3__15ctypeIcE10do_toupperEPcPKc'} @@ -1136,6 +1137,16 @@ {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__121recursive_timed_mutexD1Ev'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__121recursive_timed_mutexD2Ev'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__121undeclare_no_pointersEPcm'} +{'is_defined': True, 'type': 'OBJECT', 'name': '_ZNSt3__123__libcpp_debug_functionE', 'size': 8} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionC1ERKNS_19__libcpp_debug_infoE'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionC1ERKS0_'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionC1Ev'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionC2ERKNS_19__libcpp_debug_infoE'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionC2ERKS0_'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionC2Ev'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionD0Ev'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionD1Ev'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__124__libcpp_debug_exceptionD2Ev'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__125__num_get_signed_integralIlEET_PKcS3_Rji'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__125__num_get_signed_integralIxEET_PKcS3_Rji'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE'} @@ -1154,10 +1165,13 @@ {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIwwEEPwEEbT0_S5_T_'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIxxEEPxEEbT0_S5_T_'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIyyEEPyEEbT0_S5_T_'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__libcpp_set_debug_functionEPFvRKNS_19__libcpp_debug_infoEE'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__num_get_unsigned_integralIjEET_PKcS3_Rji'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__num_get_unsigned_integralImEET_PKcS3_Rji'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__num_get_unsigned_integralItEET_PKcS3_Rji'} {'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__127__num_get_unsigned_integralIyEET_PKcS3_Rji'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__129__libcpp_abort_debug_functionERKNS_19__libcpp_debug_infoE'} +{'is_defined': True, 'type': 'FUNC', 'name': '_ZNSt3__129__libcpp_throw_debug_functionERKNS_19__libcpp_debug_infoE'} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZNSt3__13cinE', 'size': 168} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZNSt3__14cerrE', 'size': 160} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZNSt3__14clogE', 'size': 160} @@ -1554,6 +1568,7 @@ {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTINSt3__120__codecvt_utf8_utf16IwEE', 'size': 24} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTINSt3__120__time_get_c_storageIcEE', 'size': 16} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTINSt3__120__time_get_c_storageIwEE', 'size': 16} +{'is_defined': True, 'type': 'OBJECT', 'name': '_ZTINSt3__124__libcpp_debug_exceptionE', 'size': 24} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTINSt3__15ctypeIcEE', 'size': 56} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTINSt3__15ctypeIwEE', 'size': 56} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTINSt3__16locale5facetE', 'size': 24} @@ -1679,6 +1694,7 @@ {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTSNSt3__120__codecvt_utf8_utf16IwEE', 'size': 34} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTSNSt3__120__time_get_c_storageIcEE', 'size': 34} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTSNSt3__120__time_get_c_storageIwEE', 'size': 34} +{'is_defined': True, 'type': 'OBJECT', 'name': '_ZTSNSt3__124__libcpp_debug_exceptionE', 'size': 35} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTSNSt3__15ctypeIcEE', 'size': 18} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTSNSt3__15ctypeIwEE', 'size': 18} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTSNSt3__16locale5facetE', 'size': 22} @@ -1790,6 +1806,7 @@ {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDiEE', 'size': 96} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDsEE', 'size': 96} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IwEE', 'size': 96} +{'is_defined': True, 'type': 'OBJECT', 'name': '_ZTVNSt3__124__libcpp_debug_exceptionE', 'size': 40} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTVNSt3__15ctypeIcEE', 'size': 104} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTVNSt3__15ctypeIwEE', 'size': 136} {'is_defined': True, 'type': 'OBJECT', 'name': '_ZTVNSt3__16locale5facetE', 'size': 40} diff --git a/libcxx/src/debug.cpp b/libcxx/src/debug.cpp index d46935cc9ed..fe27dc82ca6 100644 --- a/libcxx/src/debug.cpp +++ b/libcxx/src/debug.cpp @@ -7,16 +7,75 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_DEBUG 1 #include "__config" #include "__debug" #include "functional" #include "algorithm" +#include "string" +#include "cstdio" #include "__hash_table" #include "mutex" _LIBCPP_BEGIN_NAMESPACE_STD +static std::string make_what_str(__libcpp_debug_info const& info) { + string msg = info.__file_; + msg += ":" + to_string(info.__line_) + ": _LIBCPP_ASSERT '"; + msg += info.__pred_; + msg += "' failed. "; + msg += info.__msg_; + return msg; +} + +_LIBCPP_SAFE_STATIC __libcpp_debug_function_type + __libcpp_debug_function = __libcpp_abort_debug_function; + +bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) { + __libcpp_debug_function = __func; + return true; +} + +_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) { + std::fprintf(stderr, "%s\n", make_what_str(info).c_str()); + std::abort(); +} + +_LIBCPP_NORETURN void __libcpp_throw_debug_function(__libcpp_debug_info const& info) { + throw __libcpp_debug_exception(info); +} + +struct __libcpp_debug_exception::__libcpp_debug_exception_imp { + __libcpp_debug_info __info_; + std::string __what_str_; +}; + +__libcpp_debug_exception::__libcpp_debug_exception() _NOEXCEPT + : __imp_(nullptr) { +} + +__libcpp_debug_exception::__libcpp_debug_exception( + __libcpp_debug_info const& info) : __imp_(new __libcpp_debug_exception_imp) +{ + __imp_->__info_ = info; + __imp_->__what_str_ = make_what_str(info); +} +__libcpp_debug_exception::__libcpp_debug_exception( + __libcpp_debug_exception const& other) : __imp_(nullptr) { + if (other.__imp_) + __imp_ = new __libcpp_debug_exception_imp(*other.__imp_); +} + +__libcpp_debug_exception::~__libcpp_debug_exception() _NOEXCEPT { + if (__imp_) + delete __imp_; +} + +const char* __libcpp_debug_exception::what() const _NOEXCEPT { + if (__imp_) + return __imp_->__what_str_.c_str(); + return "__libcpp_debug_exception"; +} + _LIBCPP_FUNC_VIS __libcpp_db* __get_db() diff --git a/libcxx/test/libcxx/debug/debug_abort.pass.cpp b/libcxx/test/libcxx/debug/debug_abort.pass.cpp new file mode 100644 index 00000000000..cfe63202705 --- /dev/null +++ b/libcxx/test/libcxx/debug/debug_abort.pass.cpp @@ -0,0 +1,30 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// Test that the default debug handler aborts the program. + +#define _LIBCPP_DEBUG 0 + +#include <csignal> +#include <cstdlib> +#include <__debug> + +void signal_handler(int signal) +{ + if (signal == SIGABRT) + std::_Exit(EXIT_SUCCESS); + std::_Exit(EXIT_FAILURE); +} + +int main() +{ + if (std::signal(SIGABRT, signal_handler) != SIG_ERR) + _LIBCPP_ASSERT(false, "foo"); + return EXIT_FAILURE; +} diff --git a/libcxx/test/libcxx/debug/debug_throw.pass.cpp b/libcxx/test/libcxx/debug/debug_throw.pass.cpp new file mode 100644 index 00000000000..109f9e93b03 --- /dev/null +++ b/libcxx/test/libcxx/debug/debug_throw.pass.cpp @@ -0,0 +1,36 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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: libcpp-no-exceptions + +// Test that the default debug handler can be overridden and test the +// throwing debug handler. + +#define _LIBCPP_DEBUG 0 + +#include <cstdlib> +#include <exception> +#include <type_traits> +#include <__debug> + +int main() +{ + { + std::__libcpp_debug_function = std::__libcpp_throw_debug_function; + try { + _LIBCPP_ASSERT(false, "foo"); + } catch (std::__libcpp_debug_exception const&) {} + } + { + // test that the libc++ exception type derives from std::exception + static_assert(std::is_base_of<std::exception, + std::__libcpp_debug_exception + >::value, "must be an exception"); + } +} diff --git a/libcxx/test/libcxx/debug/debug_throw_register.pass.cpp b/libcxx/test/libcxx/debug/debug_throw_register.pass.cpp new file mode 100644 index 00000000000..21b1d5255d3 --- /dev/null +++ b/libcxx/test/libcxx/debug/debug_throw_register.pass.cpp @@ -0,0 +1,30 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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: libcpp-no-exceptions + +// Test that defining _LIBCPP_DEBUG_USE_EXCEPTIONS causes _LIBCPP_ASSERT +// to throw on failure. + +#define _LIBCPP_DEBUG 1 +#define _LIBCPP_DEBUG_USE_EXCEPTIONS + +#include <cstdlib> +#include <exception> +#include <type_traits> +#include <__debug> +#include <cassert> + +int main() +{ + try { + _LIBCPP_ASSERT(false, "foo"); + assert(false); + } catch (...) {} +} diff --git a/libcxx/www/debug_mode.html b/libcxx/www/debug_mode.html deleted file mode 100644 index 943c47db011..00000000000 --- a/libcxx/www/debug_mode.html +++ /dev/null @@ -1,162 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" - "http://www.w3.org/TR/html4/strict.dtd"> -<html> -<head> - <title>libc++ debug mode status</title> -</head> -<body> - -<p> -Work is beginning on a libc++ debug mode. The purpose of this table is to -record which parts of libc++ have debug mode support. -</p> - -<p> -Note: Debug mode is currently not functional. Defining _LIBCPP_DEBUG will result -in fairly nasty compile errors. -</p> - -<table border=1> -<tr> -<th>Section</th> -<th>Completed ?</th> -</tr> - -<tr> -<td> -<p> -<code>vector<T>, T != bool</code> -</p> -</td> -<td align="center"> ✓ </td> -</tr> - -<tr> -<td> -<p> -<code><list></code> -</p> -</td> -<td align="center"> ✓ </td> -</tr> - -<tr> -<td> -<p> -<code><unordered_set></code> -</p> -</td> -<td align="center"> ✓ </td> -</tr> - -<tr> -<td> -<p> -<code><unordered_map></code> -</p> -</td> -<td align="center"> ✓ </td> -</tr> - -<tr> -<td> -<p> -<code><string></code> -</p> -</td> -<td align="center"> ✓ </td> -</tr> - -<tr> -<td> -<p> -<code><set></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code><map></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code>vector<bool></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code><deque></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code><forward_list></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code><array></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code><stack></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code><queue></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - -<tr> -<td> -<p> -<code><algorithm></code> -</p> -</td> -<td align="center"><!-- ✓ --></td> -</tr> - - -</table> - -<p> -At present the table is known to not be a complete list. It is currently ordered -in approximate priority order. -</p> - -<p>Last Updated: 3-June-2014</p> - -</body> -</html> diff --git a/libcxx/www/index.html b/libcxx/www/index.html index e0f02f2de2e..6b464ebec4e 100644 --- a/libcxx/www/index.html +++ b/libcxx/www/index.html @@ -220,7 +220,6 @@ <li><a href="atomic_design.html"><tt><atomic></tt></a></li> <li><a href="type_traits_design.html"><tt><type_traits></tt></a></li> <li><a href="http://cplusplusmusings.wordpress.com/2012/07/05/clang-and-standard-libraries-on-mac-os-x/">Excellent notes by Marshall Clow</a></li> -<li><a href="debug_mode.html">Status of debug mode</a></li> </ul> </div> |