[libc++] Add a lightweight overridable assertion handler

This patch adds a lightweight assertion handler mechanism that can be
overriden at link-time in a fashion similar to `operator new`.

This is a third take on https://llvm.org/D121123 (which allowed customizing
the assertion handler at compile-time), and https://llvm.org/D119969
(which allowed customizing the assertion handler at runtime only).

This approach is, I think, the best of all three explored approaches.
Indeed, replacing the assertion handler in user code is ergonomic,
yet we retain the ability to provide a custom assertion handler when
deploying to older platforms that don't have a default handler in
the dylib.

As-is, this patch provides a pretty good amount of backwards compatibility
with the previous debug mode:

- Code that used to set _LIBCPP_DEBUG=0 in order to get basic assertions
  in their code will still get basic assertions out of the box, but
  those assertions will be using the new assertion handler support.
- Code that was previously compiled with references to __libcpp_debug_function
  and friends will work out-of-the-box, no changes required. This is
  because we provide the same symbols in the dylib as we used to.
- Code that used to set a custom __libcpp_debug_function will stop
  compiling, because we don't provide that declaration anymore. Users
  will have to migrate to the new way of setting a custom assertion
  handler, which is extremely easy. I suspect that pool of users is
  very limited, so breaking them at compile-time is probably acceptable.

The main downside of this approach is that code being compiled with
assertions enabled but deploying to an older platform where the assertion
handler didn't exist yet will fail to compile. However users can easily
fix the problem by providing a custom assertion handler and defining
the _LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED macro to
let the library know about the custom handler. In a way, this is
actually a feature because it avoids a load-time error that one would
otherwise get when trying to run the code on the older target.

Differential Revision: https://reviews.llvm.org/D121478
This commit is contained in:
Louis Dionne 2022-03-03 17:37:03 -05:00
parent b6efd2510a
commit b0fd9497af
75 changed files with 550 additions and 229 deletions

View File

@ -82,7 +82,10 @@ include(CMakeDependentOption)
include(HandleCompilerRT)
# Basic options ---------------------------------------------------------------
option(LIBCXX_ENABLE_ASSERTIONS "Enable assertions independent of build mode." OFF)
option(LIBCXX_ENABLE_ASSERTIONS
"Enable assertions inside the compiled library, and at the same time make it the
default when compiling user code. Note that assertions can be enabled or disabled
by users in their own code regardless of this option." OFF)
option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON)
option(LIBCXX_ENABLE_STATIC "Build libc++ as a static library." ON)
option(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY "Build libc++experimental.a" ON)
@ -694,7 +697,6 @@ if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY AND LIBCXX_ENABLE_SHARED)
endif()
# Assertion flags =============================================================
define_if(LIBCXX_ENABLE_ASSERTIONS -D_LIBCPP_DEBUG=0)
define_if(LIBCXX_DEBUG_BUILD -D_DEBUG)
if (LIBCXX_ENABLE_ASSERTIONS AND NOT LIBCXX_DEBUG_BUILD)
# MSVC doesn't like _DEBUG on release builds. See PR 4379.
@ -896,6 +898,11 @@ config_define_if_not(LIBCXX_ENABLE_LOCALIZATION _LIBCPP_HAS_NO_LOCALIZATION)
config_define_if_not(LIBCXX_ENABLE_UNICODE _LIBCPP_HAS_NO_UNICODE)
config_define_if_not(LIBCXX_ENABLE_WIDE_CHARACTERS _LIBCPP_HAS_NO_WIDE_CHARACTERS)
config_define_if_not(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS)
if (LIBCXX_ENABLE_ASSERTIONS)
config_define(1 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT)
else()
config_define(0 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT)
endif()
# Incomplete features get their own specific disabling flags. This makes it
# easier to grep for target specific flags once the feature is complete.
config_define_if_not(LIBCXX_ENABLE_INCOMPLETE_FEATURES _LIBCPP_HAS_NO_INCOMPLETE_FORMAT)

View File

@ -1 +1,3 @@
set(LIBCXX_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(LIBCXX_TEST_PARAMS "enable_assertions=True" CACHE STRING "")
set(LIBCXXABI_TEST_PARAMS "enable_assertions=True" CACHE STRING "")

View File

@ -216,7 +216,10 @@ libc++ specific options
**Default**: ``OFF``
Build libc++ with assertions enabled.
Build libc++ with assertions enabled in the compiled library, and enable assertions
by default when building user code as well. Assertions can be turned off by users
by defining ``_LIBCPP_ENABLE_ASSERTIONS=0``. For details, see
:ref:`the documentation <assertions-mode>`.
.. option:: LIBCXX_ENABLE_SHARED:BOOL

View File

@ -46,6 +46,12 @@ New Features
"heapsort with bounce" to reduce the number of comparisons, and rearranges
elements using move-assignment instead of `swap`.
- Libc++ now supports a variety of assertions that can be turned on to help catch
undefined behavior in user code. This new support is now separate from the old
(and incomplete) Debug Mode. Vendors can select whether the library they ship
should include assertions or not by default. For details, see
:ref:`the documentation <assertions-mode>` about this new feature.
API Changes
-----------
@ -74,6 +80,10 @@ API Changes
- The C++14 function ``std::quoted(const char*)`` is no longer supported in
C++03 or C++11 modes.
- Setting a custom debug handler with ``std::__libcpp_debug_function`` is not
supported anymore. Please migrate to using the new support for
:ref:`assertions <assertions-mode>` instead.
ABI Changes
-----------

View File

@ -121,6 +121,92 @@ provide pretty-printers itself. Those can be used as:
<args>
.. _assertions-mode:
Enabling the "safe libc++" mode
===============================
Libc++ contains a number of assertions whose goal is to catch undefined behavior in the
library, usually caused by precondition violations. Those assertions do not aim to be
exhaustive -- instead they aim to provide a good balance between safety and performance.
In particular, these assertions do not change the complexity of algorithms. However, they
might, in some cases, interfere with compiler optimizations.
By default, these assertions are turned off. Vendors can decide to turn them on while building
the compiled library by defining ``LIBCXX_ENABLE_ASSERTIONS=ON`` at CMake configuration time.
When ``LIBCXX_ENABLE_ASSERTIONS`` is used, the compiled library will be built with assertions
enabled, **and** user code will be built with assertions enabled by default. If
``LIBCXX_ENABLE_ASSERTIONS=OFF`` at CMake configure time, the compiled library will not contain
assertions and the default when building user code will be to have assertions disabled.
As a user, you can consult your vendor to know whether assertions are enabled by default.
Furthermore, independently of any vendor-selected default, users can always control whether
assertions are enabled in their code by defining ``_LIBCPP_ENABLE_ASSERTIONS=0|1`` before
including any libc++ header (we recommend passing ``-D_LIBCPP_ENABLE_ASSERTIONS=X`` to the
compiler). Note that if the compiled library was built by the vendor without assertions,
functions compiled inside the static or shared library won't have assertions enabled even
if the user defines ``_LIBCPP_ENABLE_ASSERTIONS=1`` (the same is true for the inverse case
where the static or shared library was compiled **with** assertions but the user tries to
disable them). However, most of the code in libc++ is in the headers, so the user-selected
value for ``_LIBCPP_ENABLE_ASSERTIONS`` (if any) will usually be respected.
When an assertion fails, an assertion handler function is called. The library provides a default
assertion handler that prints an error message and calls ``std::abort()``. Note that this assertion
handler is provided by the static or shared library, so it is only available when deploying to a
platform where the compiled library is sufficiently recent. However, users can also override that
assertion handler with their own, which can be useful to provide custom behavior, or when deploying
to older platforms where the default assertion handler isn't available.
Replacing the default assertion handler is done by defining the following function:
.. code-block:: cpp
void __libcpp_assertion_handler(char const* file, int line, char const* expression, char const* message)
This mechanism is similar to how one can replace the default definition of ``operator new``
and ``operator delete``. For example:
.. code-block:: cpp
// In HelloWorldHandler.cpp
#include <__assert> // must include <__assert> before defining the handler
void std::__libcpp_assertion_handler(char const* file, int line, char const* expression, char const* message) {
std::printf("Assertion %s failed at %s:%d, more info: %s", expression, file, line, message);
std::abort();
}
// In HelloWorld.cpp
#include <vector>
int main() {
std::vector<int> v;
int& x = v[0]; // Your assertion handler will be called here if _LIBCPP_ENABLE_ASSERTIONS=1
}
Also note that the assertion handler should usually not return. Since the assertions in libc++
catch undefined behavior, your code will proceed with undefined behavior if your assertion
handler is called and does return.
Furthermore, throwing an exception from the assertion handler is not recommended. Indeed, many
functions in the library are ``noexcept``, and any exception thrown from the assertion handler
will result in ``std::terminate`` being called.
Back-deploying with a custom assertion handler
----------------------------------------------
When deploying to an older platform that does not provide a default assertion handler, the
compiler will diagnose the usage of ``std::__libcpp_assertion_handler`` with an error. This
is done to avoid the load-time error that would otherwise happen if the code was being deployed
on the older system.
If you are providing a custom assertion handler, this error is effectively a false positive.
To let the library know that you are providing a custom assertion handler in back-deployment
scenarios, you must define the ``_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED`` macro,
and the library will assume that you are providing your own definition. If no definition is
provided and the code is back-deployed to the older platform, it will fail to load when the
dynamic linker fails to find a definition for ``std::__libcpp_assertion_handler``, so you
should only remove the guard rails if you really mean it!
Libc++ Configuration Macros
===========================

View File

@ -10,52 +10,39 @@
#ifndef _LIBCPP___ASSERT
#define _LIBCPP___ASSERT
#include <__availability>
#include <__config>
#include <iosfwd> // for std::string
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
// This is for backwards compatibility with code that might have been enabling
// assertions through the Debug mode previously.
#if _LIBCPP_DEBUG_LEVEL >= 1
# define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : ::std::__libcpp_debug_function(::std::__libcpp_debug_info(__FILE__, __LINE__, #x, m)))
# ifndef _LIBCPP_ENABLE_ASSERTIONS
# define _LIBCPP_ENABLE_ASSERTIONS 1
# endif
#endif
#ifndef _LIBCPP_ENABLE_ASSERTIONS
# define _LIBCPP_ENABLE_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS_DEFAULT
#endif
#if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1
# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1"
#endif
#if _LIBCPP_ENABLE_ASSERTIONS
# define _LIBCPP_ASSERT(expression, message) ((expression) ? (void)0 : ::std::__libcpp_assertion_handler(__FILE__, __LINE__, #expression, message))
#else
# define _LIBCPP_ASSERT(x, m) ((void)0)
# define _LIBCPP_ASSERT(x, m) ((void)0)
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
__libcpp_debug_info()
: __file_(nullptr), __line_(-1), __pred_(nullptr), __msg_(nullptr) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
__libcpp_debug_info(const char* __f, int __l, const char* __p, const char* __m)
: __file_(__f), __line_(__l), __pred_(__p), __msg_(__m) {}
_LIBCPP_FUNC_VIS string what() const;
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_EXPORTED_FROM_ABI __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_set_debug_function - Set the debug handler to the specified
/// function.
_LIBCPP_FUNC_VIS
bool __libcpp_set_debug_function(__libcpp_debug_function_type __func);
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ASSERTION_HANDLER
void __libcpp_assertion_handler(char const* __file, int __line, char const* __expression, char const* __message);
_LIBCPP_END_NAMESPACE_STD

View File

@ -159,6 +159,23 @@
# define _LIBCPP_AVAILABILITY_FORMAT
// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format
// This controls whether the std::__libcpp_assertion_handler default
// assertion handler is provided by the library.
//
// Note that when users provide their own custom assertion handler,
// it doesn't matter whether the dylib provides a default handler,
// and the availability markup can actually give a false positive
// diagnostic (it will think that no handler is provided, when in
// reality the user has provided their own).
//
// Users can pass -D_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED
// to the compiler to tell the library to ignore the fact that the
// default handler isn't available on their deployment target. Note that
// defining this macro but failing to define a custom assertion handler
// will lead to a load-time error on back-deployment targets, so it
// should be avoided.
# define _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER
#elif defined(__APPLE__)
# define _LIBCPP_AVAILABILITY_SHARED_MUTEX \
@ -260,6 +277,9 @@
# define _LIBCPP_AVAILABILITY_FORMAT \
__attribute__((unavailable))
# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format
# define _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER \
__attribute__((unavailable))
#else
// ...New vendors can add availability markup here...
@ -283,4 +303,14 @@
# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS
#endif
// Define the special assertion handler availability attribute, which can be silenced by
// users if they provide their own custom assertion handler. The rest of the code should
// not use the *_DEFAULT_* macro directly, since that would make it ignore the fact that
// the user provided a custom handler.
#if defined(_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED)
# define _LIBCPP_AVAILABILITY_ASSERTION_HANDLER /* nothing */
#else
# define _LIBCPP_AVAILABILITY_ASSERTION_HANDLER _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER
#endif
#endif // _LIBCPP___AVAILABILITY

View File

@ -32,6 +32,7 @@
#cmakedefine _LIBCPP_HAS_NO_WIDE_CHARACTERS
#cmakedefine _LIBCPP_HAS_NO_INCOMPLETE_FORMAT
#cmakedefine _LIBCPP_HAS_NO_INCOMPLETE_RANGES
#cmakedefine01 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT
// __USE_MINGW_ANSI_STDIO gets redefined on MinGW
#ifdef __clang__

View File

@ -1561,6 +1561,7 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_debug_functionE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -1534,6 +1534,7 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -1561,6 +1561,7 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_debug_functionE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -1534,6 +1534,7 @@
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -1252,6 +1252,7 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_debug_functionE', 'size': 8, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -1249,6 +1249,7 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_debug_functionE', 'size': 8, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -1228,6 +1228,7 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -1224,6 +1224,7 @@
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_debug_functionE', 'size': 8, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKciS1_S1_', '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_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'}

View File

@ -4,6 +4,7 @@ set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTOR
set(LIBCXX_SOURCES
algorithm.cpp
any.cpp
assert.cpp
atomic.cpp
barrier.cpp
bind.cpp
@ -65,8 +66,8 @@ set(LIBCXX_SOURCES
if (LIBCXX_ENABLE_DEBUG_MODE_SUPPORT)
list(APPEND LIBCXX_SOURCES
assert.cpp
debug.cpp
legacy_debug_handler.cpp
)
endif()

View File

@ -10,29 +10,13 @@
#include <__config>
#include <cstdio>
#include <cstdlib>
#include <string>
_LIBCPP_BEGIN_NAMESPACE_STD
std::string __libcpp_debug_info::what() const {
string msg = __file_;
msg += ":" + std::to_string(__line_) + ": _LIBCPP_ASSERT '";
msg += __pred_;
msg += "' failed. ";
msg += __msg_;
return msg;
}
_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
std::fprintf(stderr, "%s\n", info.what().c_str());
std::abort();
}
constinit __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_WEAK
void __libcpp_assertion_handler(char const* __file, int __line, char const* __expression, char const* __message) {
std::fprintf(stderr, "%s:%d: libc++ assertion '%s' failed. %s\n", __file, __line, __expression, __message);
std::abort();
}
_LIBCPP_END_NAMESPACE_STD

View File

@ -0,0 +1,54 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include <__config>
#include <cstdio>
#include <cstdlib>
#include <string>
// This file defines the legacy default debug handler and related mechanisms
// to set it. This is for backwards ABI compatibility with code that has been
// using this debug handler previously.
_LIBCPP_BEGIN_NAMESPACE_STD
struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
_LIBCPP_EXPORTED_FROM_ABI string what() const;
const char* __file_;
int __line_;
const char* __pred_;
const char* __msg_;
};
std::string __libcpp_debug_info::what() const {
string msg = __file_;
msg += ":" + std::to_string(__line_) + ": _LIBCPP_ASSERT '";
msg += __pred_;
msg += "' failed. ";
msg += __msg_;
return msg;
}
_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
std::fprintf(stderr, "%s\n", info.what().c_str());
std::abort();
}
typedef void (*__libcpp_debug_function_type)(__libcpp_debug_info const&);
_LIBCPP_EXPORTED_FROM_ABI
constinit __libcpp_debug_function_type __libcpp_debug_function = __libcpp_abort_debug_function;
_LIBCPP_EXPORTED_FROM_ABI
bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
__libcpp_debug_function = __func;
return true;
}
_LIBCPP_END_NAMESPACE_STD

View File

@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Test that _LIBCPP_ASSERT doesn't do anything when assertions are disabled.
// We need to use -Wno-macro-redefined because the test suite defines
// _LIBCPP_ENABLE_ASSERTIONS=1 under some configurations.
// ADDITIONAL_COMPILE_FLAGS: -Wno-macro-redefined -D_LIBCPP_ENABLE_ASSERTIONS=0
#include <__assert>
#include <cassert>
bool executed_condition = false;
bool f() { executed_condition = true; return false; }
int main(int, char**) {
_LIBCPP_ASSERT(f(), "message"); // should not execute anything
assert(!executed_condition); // really make sure we did not execute anything at all
return 0;
}

View File

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Make sure that we can enable assertions when we back-deploy to older platforms
// if we define _LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED.
//
// Note that this test isn't really different from customize_handler.pass.cpp when
// run outside of back-deployment scenarios, but we still run it all the time.
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 -D_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED
#include <__assert>
#include <cassert>
bool handler_called = false;
void std::__libcpp_assertion_handler(char const*, int, char const*, char const*) {
handler_called = true;
}
int main(int, char**) {
_LIBCPP_ASSERT(false, "message");
assert(handler_called);
return 0;
}

View File

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Test that we can set a custom assertion handler.
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime
// failures when back-deploying.
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
#include <__assert>
#include <cassert>
bool handler_called = false;
void std::__libcpp_assertion_handler(char const*, int, char const*, char const*) {
handler_called = true;
}
int main(int, char**) {
_LIBCPP_ASSERT(false, "message");
assert(handler_called);
return 0;
}

View File

@ -0,0 +1,31 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This test ensures that assertions are still enabled when _LIBCPP_DEBUG=0 is
// defined, for backwards compatibility with code that might have been using
// it to enable assertions previously.
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime
// failures when back-deploying.
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
#include <__assert>
#include <cassert>
bool handler_called = false;
void std::__libcpp_assertion_handler(char const*, int, char const*, char const*) {
handler_called = true;
}
int main(int, char**) {
_LIBCPP_ASSERT(false, "message");
assert(handler_called);
return 0;
}

View File

@ -6,26 +6,25 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=1
// Test that the default assertion handler aborts the program.
// Test that the default debug handler aborts the program.
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime
// failures when back-deploying.
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
#include <__assert>
#include <csignal>
#include <cstdlib>
#include "test_macros.h"
void signal_handler(int signal)
{
if (signal == SIGABRT)
std::_Exit(EXIT_SUCCESS);
std::_Exit(EXIT_FAILURE);
void signal_handler(int signal) {
if (signal == SIGABRT)
std::_Exit(EXIT_SUCCESS);
std::_Exit(EXIT_FAILURE);
}
int main(int, char**)
{
int main(int, char**) {
if (std::signal(SIGABRT, signal_handler) != SIG_ERR)
_LIBCPP_ASSERT(false, "foo");
return EXIT_FAILURE;

View File

@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Make sure that we diagnose any usage of the default assertion handler on a platform
// that doesn't support it at compile-time.
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// REQUIRES: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
#include <__assert>
void f() {
_LIBCPP_ASSERT(true, "message"); // expected-error {{'__libcpp_assertion_handler' is unavailable}}
}

View File

@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// test that array<T, 0>::back() triggers an assertion

View File

@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// test that array<T, 0>::back() triggers an assertion

View File

@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// test that array<T, 0>::operator[] triggers an assertion

View File

@ -10,8 +10,9 @@
// pop_back() more than the number of elements in a deque
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <deque>

View File

@ -10,8 +10,9 @@
// Call erase(const_iterator position) with end()
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <list>

View File

@ -10,8 +10,9 @@
// void pop_back();
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <list>
#include <cassert>

View File

@ -10,8 +10,9 @@
// Call back() on empty container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <vector>
#include <cassert>

View File

@ -10,8 +10,9 @@
// Call back() on empty const container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <vector>

View File

@ -10,8 +10,9 @@
// Call front() on empty const container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <vector>

View File

@ -10,8 +10,9 @@
// Index const vector out of bounds.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <vector>
#include <cassert>

View File

@ -10,8 +10,9 @@
// Call front() on empty container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <vector>
#include <cassert>

View File

@ -10,8 +10,9 @@
// Index vector out of bounds.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <vector>
#include <cassert>

View File

@ -10,8 +10,9 @@
// pop_back() more than the number of elements in a vector
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <vector>

View File

@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03
// UNSUPPORTED: debug_level=0, debug_level=1
// UNSUPPORTED: debug_level=0, debug_level=1, libcpp-has-assertions
// <vector>

View File

@ -10,8 +10,9 @@
// size_type bucket(const key_type& __k) const;
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_map>
#include <string>

View File

@ -14,8 +14,9 @@
// size_type bucket_size(size_type n) const
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_map>
#include <string>

View File

@ -15,8 +15,9 @@
// float max_load_factor() const;
// void max_load_factor(float mlf);
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_map>
#include <string>

View File

@ -14,8 +14,9 @@
// size_type bucket(const key_type& __k) const;
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_map>
#include <string>

View File

@ -14,8 +14,9 @@
// size_type bucket_size(size_type n) const
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_map>
#include <string>

View File

@ -15,8 +15,9 @@
// float max_load_factor() const;
// void max_load_factor(float mlf);
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_map>
#include <string>

View File

@ -14,8 +14,9 @@
// size_type bucket(const key_type& __k) const;
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_set>

View File

@ -14,8 +14,9 @@
// size_type bucket_size(size_type n) const
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_set>

View File

@ -15,8 +15,9 @@
// float max_load_factor() const;
// void max_load_factor(float mlf);
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_set>

View File

@ -14,8 +14,9 @@
// size_type bucket(const key_type& __k) const;
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_set>

View File

@ -14,8 +14,9 @@
// size_type bucket_size(size_type n) const
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_set>

View File

@ -15,8 +15,9 @@
// float max_load_factor() const;
// void max_load_factor(float mlf);
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <unordered_set>

View File

@ -82,7 +82,7 @@ private:
EXPECT_DEATH( C1.erase(it1) );
C1.erase(C1.begin(), C1.end());
assert(C1.size() == 0);
EXPECT_DEATH_MATCHES(DebugInfoMatcher("string::pop_back(): string is already empty"), C1.pop_back() );
TEST_LIBCPP_ASSERT_FAILURE(C1.pop_back(), "string::pop_back(): string is already empty");
}
};

View File

@ -1,30 +0,0 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=1
// UNSUPPORTED: libcxx-no-debug-mode
#include <cstdlib>
#include <string>
#include <type_traits>
#include <__debug>
#include <cassert>
#include "test_macros.h"
void my_debug_function(std::__libcpp_debug_info const& info) {
assert(info.__msg_ == std::string("foo"));
std::exit(0);
}
int main(int, char**)
{
std::__libcpp_set_debug_function(&my_debug_function);
_LIBCPP_ASSERT(false, "foo");
return 1;
}

View File

@ -12,8 +12,9 @@
// T* polymorphic_allocator<T>::deallocate(T*, size_t size)
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <experimental/memory_resource>
#include <type_traits>

View File

@ -12,8 +12,9 @@
// T* polymorphic_allocator<T>::deallocate(T*, size_t size)
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <experimental/memory_resource>
#include <type_traits>

View File

@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// <filesystem>

View File

@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// <list>

View File

@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// <list>

View File

@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// <list>

View File

@ -10,8 +10,9 @@
// Call back() on empty container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>

View File

@ -10,8 +10,9 @@
// Call back() on empty const container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>

View File

@ -10,8 +10,9 @@
// Call front() on empty const container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>

View File

@ -10,8 +10,9 @@
// Index const string out of bounds.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>
#include <cassert>

View File

@ -10,8 +10,9 @@
// Call front() on empty container.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>
#include <cassert>

View File

@ -10,8 +10,9 @@
// Index string out of bounds.
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>
#include <cassert>

View File

@ -10,8 +10,9 @@
// Call erase(const_iterator position) with end()
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>

View File

@ -10,8 +10,9 @@
// void pop_back();
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <string>

View File

@ -8,8 +8,9 @@
// UNSUPPORTED: c++11, c++14
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// Construct a string_view from a null pointer
// constexpr basic_string_view( const CharT* s );

View File

@ -8,8 +8,9 @@
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// <future>

View File

@ -8,8 +8,9 @@
// UNSUPPORTED: libcpp-has-no-threads
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
// <future>

View File

@ -15,8 +15,9 @@
// UNSUPPORTED: c++11, c++14
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <optional>

View File

@ -13,8 +13,9 @@
// UNSUPPORTED: c++11, c++14
// UNSUPPORTED: c++03, windows, libcxx-no-debug-mode
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=0
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <optional>

View File

@ -9,16 +9,6 @@
#ifndef TEST_SUPPORT_CHECK_ASSERTION_H
#define TEST_SUPPORT_CHECK_ASSERTION_H
#ifndef _LIBCPP_DEBUG
#error _LIBCPP_DEBUG must be defined before including this header
#endif
#include <ciso646>
#ifndef _LIBCPP_VERSION
#error "This header may only be used for libc++ tests"
#endif
#include <__debug>
#include <cassert>
#include <cstddef>
#include <cstdio>
@ -33,28 +23,31 @@
#include "test_macros.h"
#include "test_allocator.h"
#ifndef _LIBCPP_VERSION
# error "This header may only be used for libc++ tests"
#endif
#if TEST_STD_VER < 11
# error "C++11 or greater is required to use this header"
#endif
struct DebugInfoMatcher {
struct AssertionInfoMatcher {
static const int any_line = -1;
static constexpr const char* any_file = "*";
static constexpr const char* any_msg = "*";
constexpr DebugInfoMatcher() : is_empty_(true), msg_(any_msg, __builtin_strlen(any_msg)), file_(any_file, __builtin_strlen(any_file)), line_(any_line) { }
constexpr DebugInfoMatcher(const char* msg, const char* file = any_file, int line = any_line)
constexpr AssertionInfoMatcher() : is_empty_(true), msg_(any_msg, __builtin_strlen(any_msg)), file_(any_file, __builtin_strlen(any_file)), line_(any_line) { }
constexpr AssertionInfoMatcher(const char* msg, const char* file = any_file, int line = any_line)
: is_empty_(false), msg_(msg, __builtin_strlen(msg)), file_(file, __builtin_strlen(file)), line_(line) {}
bool Matches(std::__libcpp_debug_info const& got) const {
bool Matches(char const* file, int line, char const* message) const {
assert(!empty() && "empty matcher");
if (CheckLineMatches(got.__line_) && CheckFileMatches(got.__file_) &&
CheckMessageMatches(got.__msg_))
if (CheckLineMatches(line) && CheckFileMatches(file) && CheckMessageMatches(message))
return true;
// Write to stdout because that's the file descriptor captured by the parent
// process.
std::printf("Failed to match debug info!\n%s\nVS\n%s\n", ToString().data(), got.what().data());
std::printf("Failed to match assertion info!\n%s\nVS\n%s:%d (%s)\n", ToString().data(), file, line, message);
return false;
}
@ -108,10 +101,10 @@ private:
int line_;
};
static constexpr DebugInfoMatcher AnyMatcher(DebugInfoMatcher::any_msg);
static constexpr AssertionInfoMatcher AnyMatcher(AssertionInfoMatcher::any_msg);
inline DebugInfoMatcher& GlobalMatcher() {
static DebugInfoMatcher GMatch;
inline AssertionInfoMatcher& GlobalMatcher() {
static AssertionInfoMatcher GMatch;
return GMatch;
}
@ -136,15 +129,7 @@ struct DeathTest {
return val >= RK_DidNotDie && val <= RK_Unknown;
}
TEST_NORETURN static void DeathTestDebugHandler(std::__libcpp_debug_info const& info) {
assert(!GlobalMatcher().empty());
if (GlobalMatcher().Matches(info)) {
std::exit(RK_MatchFound);
}
std::exit(RK_MatchFailure);
}
DeathTest(DebugInfoMatcher const& Matcher) : matcher_(Matcher) {}
DeathTest(AssertionInfoMatcher const& Matcher) : matcher_(Matcher) {}
template <class Func>
ResultKind Run(Func&& f) {
@ -180,7 +165,6 @@ private:
DupFD(GetStdErrWriteFD(), STDERR_FILENO);
GlobalMatcher() = matcher_;
std::__libcpp_set_debug_function(&DeathTestDebugHandler);
f();
std::exit(RK_DidNotDie);
}
@ -242,7 +226,7 @@ private:
return stderr_pipe_fd_[1];
}
private:
DebugInfoMatcher matcher_;
AssertionInfoMatcher matcher_;
pid_t child_pid_ = -1;
int exit_code_ = -1;
int stdout_pipe_fd_[2];
@ -251,8 +235,16 @@ private:
std::string stderr_from_child_;
};
void std::__libcpp_assertion_handler(char const* file, int line, char const* /*expression*/, char const* message) {
assert(!GlobalMatcher().empty());
if (GlobalMatcher().Matches(file, line, message)) {
std::exit(DeathTest::RK_MatchFound);
}
std::exit(DeathTest::RK_MatchFailure);
}
template <class Func>
inline bool ExpectDeath(const char* stmt, Func&& func, DebugInfoMatcher Matcher) {
inline bool ExpectDeath(const char* stmt, Func&& func, AssertionInfoMatcher Matcher) {
DeathTest DT(Matcher);
DeathTest::ResultKind RK = DT.Run(func);
auto OnFailure = [&](const char* msg) {
@ -293,6 +285,6 @@ inline bool ExpectDeath(const char* stmt, Func&& func) {
#define EXPECT_DEATH_MATCHES(Matcher, ...) assert((ExpectDeath(#__VA_ARGS__, [&]() { __VA_ARGS__; }, Matcher)))
#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) assert((ExpectDeath(#expr, [&]() { (void)(expr); }, DebugInfoMatcher(message))))
#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) assert((ExpectDeath(#expr, [&]() { (void)(expr); }, AssertionInfoMatcher(message))))
#endif // TEST_SUPPORT_CHECK_ASSERTION_H

View File

@ -6,17 +6,18 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: libcxx-no-debug-mode, c++03, windows
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=1
// UNSUPPORTED: c++03, windows
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}}
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <__debug>
#include <cassert>
#include <cstdio>
#include <string>
#include "check_assertion.h"
#include "test_macros.h"
template <class Func>
inline bool TestDeathTest(const char* stmt, Func&& func, DeathTest::ResultKind ExpectResult, DebugInfoMatcher Matcher = AnyMatcher) {
inline bool TestDeathTest(const char* stmt, Func&& func, DeathTest::ResultKind ExpectResult, AssertionInfoMatcher Matcher = AnyMatcher) {
DeathTest DT(Matcher);
DeathTest::ResultKind RK = DT.Run(func);
auto OnFailure = [&](std::string msg) {
@ -42,7 +43,7 @@ void my_libcpp_assert() {
}
void test_no_match_found() {
DebugInfoMatcher ExpectMatch("my message");
AssertionInfoMatcher ExpectMatch("my message");
TEST_DEATH_TEST_MATCHES(DeathTest::RK_MatchFailure, ExpectMatch, my_libcpp_assert());
}

View File

@ -183,6 +183,14 @@ DEFAULT_PARAMETERS = [
AddFeature('libcxx-no-debug-mode')
]),
Parameter(name='enable_assertions', choices=[True, False], type=bool, default=False,
help="Whether to enable assertions when compiling the test suite. This is only meaningful when "
"running the tests against libc++.",
actions=lambda assertions: [
AddCompileFlag('-D_LIBCPP_ENABLE_ASSERTIONS=1'),
AddFeature('libcpp-has-assertions')
] if assertions else []),
Parameter(name='additional_features', type=list, default=[],
help="A comma-delimited list of additional features that will be enabled when running the tests. "
"This should be used sparingly since specifying ad-hoc features manually is error-prone and "