diff --git a/libcxx/docs/DesignDocs/DebugMode.rst b/libcxx/docs/DesignDocs/DebugMode.rst --- a/libcxx/docs/DesignDocs/DebugMode.rst +++ b/libcxx/docs/DesignDocs/DebugMode.rst @@ -27,18 +27,13 @@ When ``_LIBCPP_DEBUG`` is not defined, there are no debugging checks performed by the library. This is the default. -Basic checks (``_LIBCPP_DEBUG == 0``) -------------------------------------- -When ``_LIBCPP_DEBUG`` is defined to ``0`` (to be understood as level ``0``), some -debugging checks are enabled. The non-exhaustive list of things is: - -- Many algorithms, such as ``binary_search``, ``merge``, ``next_permutation``, and ``sort``, - wrap the user-provided comparator to assert that `!comp(y, x)` whenever - `comp(x, y)`. This can cause the user-provided comparator to be evaluated - up to twice as many times as it would be without ``_LIBCPP_DEBUG``, and - causes the library to violate some of the Standard's complexity clauses. - -- FIXME: Update this list +Comparator consistency checks (``_LIBCPP_DEBUG == 1``) +------------------------------------------------------ +Libc++ provides some checks for the consistency of comparators passed to algorithms. Specifically, +many algorithms such as ``binary_search``, ``merge``, ``next_permutation``, and ``sort``, wrap the +user-provided comparator to assert that `!comp(y, x)` whenever `comp(x, y)`. This can cause the +user-provided comparator to be evaluated up to twice as many times as it would be without the +debug mode, and causes the library to violate some of the Standard's complexity clauses. Iterator debugging checks (``_LIBCPP_DEBUG == 1``) -------------------------------------------------- diff --git a/libcxx/include/__algorithm/comp_ref_type.h b/libcxx/include/__algorithm/comp_ref_type.h --- a/libcxx/include/__algorithm/comp_ref_type.h +++ b/libcxx/include/__algorithm/comp_ref_type.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___ALGORITHM_COMP_REF_TYPE_H #define _LIBCPP___ALGORITHM_COMP_REF_TYPE_H -#include <__assert> #include <__config> #include <__debug> #include <__utility/declval.h> @@ -53,7 +52,7 @@ decltype((void)declval<_Compare&>()( declval<_LHS &>(), declval<_RHS &>())) __do_compare_assert(int, _LHS & __l, _RHS & __r) { - _LIBCPP_ASSERT(!__comp_(__l, __r), + _LIBCPP_DEBUG_ASSERT(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering"); (void)__l; (void)__r; diff --git a/libcxx/include/__assert b/libcxx/include/__assert --- a/libcxx/include/__assert +++ b/libcxx/include/__assert @@ -42,16 +42,9 @@ #endif #if _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ASSERT_IMPL(x, m) ((x) ? (void)0 : _LIBCPP_ASSERTION_HANDLER(::std::__libcpp_assertion_info(__FILE__, __LINE__, #x, m))) +# define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : _LIBCPP_ASSERTION_HANDLER(::std::__libcpp_assertion_info(__FILE__, __LINE__, #x, m))) #else -# define _LIBCPP_ASSERT_IMPL(x, m) ((void)0) -#endif - -// We do this dance because some of our tests re-define _LIBCPP_ASSERT to something else. -// In the future, we should find other ways to test our assertions and disallow re-defining -// _LIBCPP_ASSERT. -#if !defined(_LIBCPP_ASSERT) -# define _LIBCPP_ASSERT(x, m) _LIBCPP_ASSERT_IMPL(x, m) +# define _LIBCPP_ASSERT(x, m) ((void)0) #endif _LIBCPP_BEGIN_NAMESPACE_STD diff --git a/libcxx/test/libcxx/algorithms/debug_less.pass.cpp b/libcxx/test/libcxx/algorithms/debug_less.pass.cpp --- a/libcxx/test/libcxx/algorithms/debug_less.pass.cpp +++ b/libcxx/test/libcxx/algorithms/debug_less.pass.cpp @@ -14,11 +14,14 @@ // __debug_less checks that a comparator actually provides a strict-weak ordering. +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 +// ADDITIONAL_COMPILE_FLAGS: -D'_LIBCPP_ASSERTION_HANDLER(x)=::assertion_handler(x)' +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DEBUG=1 +#include <__assert> struct DebugException {}; - -// ADDITIONAL_COMPILE_FLAGS: -Wno-macro-redefined -#define _LIBCPP_DEBUG 0 -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : throw ::DebugException()) +inline void assertion_handler(std::__libcpp_assertion_info) { + throw ::DebugException(); +} #include #include diff --git a/libcxx/test/libcxx/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/db_deallocate.pass.cpp b/libcxx/test/libcxx/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/deallocate.assert.pass.cpp rename from libcxx/test/libcxx/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/db_deallocate.pass.cpp rename to libcxx/test/libcxx/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/deallocate.assert.pass.cpp --- a/libcxx/test/libcxx/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/db_deallocate.pass.cpp +++ b/libcxx/test/libcxx/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/deallocate.assert.pass.cpp @@ -14,11 +14,14 @@ // T* polymorphic_allocator::deallocate(T*, size_t size) +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 +// ADDITIONAL_COMPILE_FLAGS: -D'_LIBCPP_ASSERTION_HANDLER(x)=::assertion_handler(x)' +#include <__assert> int AssertCount = 0; +inline void assertion_handler(std::__libcpp_assertion_info) { + ++AssertCount; +} -// ADDITIONAL_COMPILE_FLAGS: -Wno-macro-redefined -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) -#define _LIBCPP_DEBUG 0 #include #include #include diff --git a/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp b/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/deallocate.assert.pass.cpp rename from libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp rename to libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/deallocate.assert.pass.cpp --- a/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp +++ b/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/deallocate.assert.pass.cpp @@ -14,11 +14,14 @@ // T* polymorphic_allocator::deallocate(T*, size_t size) +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 +// ADDITIONAL_COMPILE_FLAGS: -D'_LIBCPP_ASSERTION_HANDLER(x)=::assertion_handler(x)' +#include <__assert> int AssertCount = 0; +inline void assertion_handler(std::__libcpp_assertion_info) { + ++AssertCount; +} -// ADDITIONAL_COMPILE_FLAGS: -Wno-macro-redefined -#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) -#define _LIBCPP_DEBUG 0 #include #include #include diff --git a/libcxx/utils/libcxx/test/format.py b/libcxx/utils/libcxx/test/format.py --- a/libcxx/utils/libcxx/test/format.py +++ b/libcxx/utils/libcxx/test/format.py @@ -194,24 +194,11 @@ if any([re.search(ext, filename) for ext in SUPPORTED_SUFFIXES]): yield lit.Test.Test(testSuite, pathInSuite + (filename,), localConfig) - def _disableWithModules(self, test): - with open(test.getSourcePath(), 'rb') as f: - contents = f.read() - return b'#define _LIBCPP_ASSERT' in contents - def execute(self, test, litConfig): VERIFY_FLAGS = '-Xclang -verify -Xclang -verify-ignore-unexpected=note -ferror-limit=0' supportsVerify = 'verify-support' in test.config.available_features filename = test.path_in_suite[-1] - # TODO(ldionne): We currently disable tests that re-define _LIBCPP_ASSERT - # when we run with modules enabled. Instead, we should - # split the part that does a death test outside of the - # test, and only disable that part when modules are - # enabled. - if 'modules-build' in test.config.available_features and self._disableWithModules(test): - return lit.Test.Result(lit.Test.UNSUPPORTED, 'Test {} is unsupported when modules are enabled') - if re.search('[.]sh[.][^.]+$', filename): steps = [ ] # The steps are already in the script return self._executeShTest(test, litConfig, steps)