summaryrefslogtreecommitdiffstats
path: root/libcxx
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/docs/DesignDocs/DebugMode.rst100
-rw-r--r--libcxx/docs/UsingLibcxx.rst12
-rw-r--r--libcxx/docs/index.rst1
-rw-r--r--libcxx/include/__config11
-rw-r--r--libcxx/include/__debug76
-rw-r--r--libcxx/lib/abi/CHANGELOG.TXT22
-rw-r--r--libcxx/lib/abi/x86_64-apple-darwin16.0.0.abilist16
-rw-r--r--libcxx/lib/abi/x86_64-unknown-linux-gnu.abilist17
-rw-r--r--libcxx/src/debug.cpp61
-rw-r--r--libcxx/test/libcxx/debug/debug_abort.pass.cpp30
-rw-r--r--libcxx/test/libcxx/debug/debug_throw.pass.cpp36
-rw-r--r--libcxx/test/libcxx/debug/debug_throw_register.pass.cpp30
-rw-r--r--libcxx/www/debug_mode.html162
-rw-r--r--libcxx/www/index.html1
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&lt;T&gt;, T != bool</code>
-</p>
-</td>
-<td align="center"> &#10003; </td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;list&gt;</code>
-</p>
-</td>
-<td align="center"> &#10003; </td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;unordered_set&gt;</code>
-</p>
-</td>
-<td align="center"> &#10003; </td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;unordered_map&gt;</code>
-</p>
-</td>
-<td align="center"> &#10003; </td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;string&gt;</code>
-</p>
-</td>
-<td align="center"> &#10003; </td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;set&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;map&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>vector&lt;bool&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;deque&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;forward_list&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;array&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;stack&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;queue&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></td>
-</tr>
-
-<tr>
-<td>
-<p>
-<code>&lt;algorithm&gt;</code>
-</p>
-</td>
-<td align="center"><!-- &#10003; --></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>&lt;atomic&gt;</tt></a></li>
<li><a href="type_traits_design.html"><tt>&lt;type_traits&gt;</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>
OpenPOWER on IntegriCloud