Remove exception throwing debug mode handler support.
Summary: The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically, I thought that if a debug violation aborted, we could only test one violation per file. This made it impossible to test debug mode. Which throwing behavior we could test more! However, the throwing approach didn't work either, since there are debug violations underneath noexcept functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug mode was off. Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst changing the behavior of their program. This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style death tests. Reviewers: mclow.lists, ldionne, thomasanderson Reviewed By: ldionne Subscribers: christof, arphaman, libcxx-commits, #libc Differential Revision: https://reviews.llvm.org/D59166 llvm-svn: 356417
This commit is contained in:
parent
2d5e7adf26
commit
61b302f94f
|
@ -850,22 +850,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_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
|
||||
# ifdef _LIBCPP_HAS_NO_NOEXCEPT
|
||||
# define _NOEXCEPT_DEBUG
|
||||
# define _NOEXCEPT_DEBUG_(x)
|
||||
# else
|
||||
# define _NOEXCEPT_DEBUG noexcept(false)
|
||||
# define _NOEXCEPT_DEBUG_(x) noexcept(false)
|
||||
# endif
|
||||
#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;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define _LIBCPP_DEBUG_H
|
||||
|
||||
#include <__config>
|
||||
#include <iosfwd>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
|
@ -24,7 +25,6 @@
|
|||
# include <cstdlib>
|
||||
# include <cstdio>
|
||||
# include <cstddef>
|
||||
# include <exception>
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 1 && !defined(_LIBCPP_ASSERT)
|
||||
|
@ -49,10 +49,6 @@
|
|||
#define _LIBCPP_DEBUG_MODE(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_DEBUG_LEVEL < 1
|
||||
class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception;
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
|
||||
|
@ -62,6 +58,9 @@ struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
|
|||
_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 std::string what() const;
|
||||
|
||||
const char* __file_;
|
||||
int __line_;
|
||||
const char* __pred_;
|
||||
|
@ -79,38 +78,11 @@ extern _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_function_type __libcpp_debug_fun
|
|||
_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)
|
||||
# if defined(_LIBCPP_NO_EXCEPTIONS)
|
||||
# error _LIBCPP_DEBUG_USE_EXCEPTIONS cannot be used when exceptions are disabled.
|
||||
# endif
|
||||
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;
|
||||
|
|
|
@ -1260,7 +1260,7 @@ public:
|
|||
|
||||
void swap(__hash_table& __u)
|
||||
#if _LIBCPP_STD_VER <= 11
|
||||
_NOEXCEPT_DEBUG_(
|
||||
_NOEXCEPT_(
|
||||
__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
|
||||
&& (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
|
||||
|| __is_nothrow_swappable<__pointer_allocator>::value)
|
||||
|
@ -1268,7 +1268,7 @@ public:
|
|||
|| __is_nothrow_swappable<__node_allocator>::value)
|
||||
);
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value);
|
||||
_NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value);
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -2807,7 +2807,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
|||
void
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
|
||||
#if _LIBCPP_STD_VER <= 11
|
||||
_NOEXCEPT_DEBUG_(
|
||||
_NOEXCEPT_(
|
||||
__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
|
||||
&& (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
|
||||
|| __is_nothrow_swappable<__pointer_allocator>::value)
|
||||
|
@ -2815,7 +2815,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
|
|||
|| __is_nothrow_swappable<__node_allocator>::value)
|
||||
)
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
|
||||
#endif
|
||||
{
|
||||
_LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value ||
|
||||
|
|
|
@ -1241,50 +1241,50 @@ template <class _Iter> class __wrap_iter;
|
|||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
auto
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
-> decltype(__x.base() - __y.base());
|
||||
#else
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __wrap_iter<_Iter1>::difference_type
|
||||
operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
template <class _Iter>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
__wrap_iter<_Iter>
|
||||
operator+(typename __wrap_iter<_Iter>::difference_type, __wrap_iter<_Iter>) _NOEXCEPT_DEBUG;
|
||||
operator+(typename __wrap_iter<_Iter>::difference_type, __wrap_iter<_Iter>) _NOEXCEPT;
|
||||
|
||||
template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY copy(_Ip, _Ip, _Op);
|
||||
template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY copy_backward(_B1, _B1, _B2);
|
||||
|
@ -1328,7 +1328,7 @@ public:
|
|||
private:
|
||||
iterator_type __i;
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter() _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter() _NOEXCEPT
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
: __i{}
|
||||
#endif
|
||||
|
@ -1339,7 +1339,7 @@ public:
|
|||
}
|
||||
template <class _Up> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
__wrap_iter(const __wrap_iter<_Up>& __u,
|
||||
typename enable_if<is_convertible<_Up, iterator_type>::value>::type* = 0) _NOEXCEPT_DEBUG
|
||||
typename enable_if<is_convertible<_Up, iterator_type>::value>::type* = 0) _NOEXCEPT
|
||||
: __i(__u.base())
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
@ -1369,7 +1369,7 @@ public:
|
|||
__get_db()->__erase_i(this);
|
||||
}
|
||||
#endif
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator*() const _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator*() const _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
|
||||
|
@ -1377,7 +1377,7 @@ public:
|
|||
#endif
|
||||
return *__i;
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG pointer operator->() const _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG pointer operator->() const _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
|
||||
|
@ -1385,7 +1385,7 @@ public:
|
|||
#endif
|
||||
return (pointer)_VSTD::addressof(*__i);
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator++() _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator++() _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
|
||||
|
@ -1394,10 +1394,10 @@ public:
|
|||
++__i;
|
||||
return *this;
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator++(int) _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator++(int) _NOEXCEPT
|
||||
{__wrap_iter __tmp(*this); ++(*this); return __tmp;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator--() _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator--() _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__decrementable(this),
|
||||
|
@ -1406,11 +1406,11 @@ public:
|
|||
--__i;
|
||||
return *this;
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator--(int) _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator--(int) _NOEXCEPT
|
||||
{__wrap_iter __tmp(*this); --(*this); return __tmp;}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator+ (difference_type __n) const _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator+ (difference_type __n) const _NOEXCEPT
|
||||
{__wrap_iter __w(*this); __w += __n; return __w;}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator+=(difference_type __n) _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator+=(difference_type __n) _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__addable(this, __n),
|
||||
|
@ -1419,11 +1419,11 @@ public:
|
|||
__i += __n;
|
||||
return *this;
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator- (difference_type __n) const _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator- (difference_type __n) const _NOEXCEPT
|
||||
{return *this + (-__n);}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator-=(difference_type __n) _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator-=(difference_type __n) _NOEXCEPT
|
||||
{*this += -__n; return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator[](difference_type __n) const _NOEXCEPT_DEBUG
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator[](difference_type __n) const _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__subscriptable(this, __n),
|
||||
|
@ -1432,7 +1432,7 @@ public:
|
|||
return __i[__n];
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG iterator_type base() const _NOEXCEPT_DEBUG {return __i;}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG iterator_type base() const _NOEXCEPT {return __i;}
|
||||
|
||||
private:
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
@ -1441,7 +1441,7 @@ private:
|
|||
__get_db()->__insert_ic(this, __p);
|
||||
}
|
||||
#else
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(iterator_type __x) _NOEXCEPT_DEBUG : __i(__x) {}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(iterator_type __x) _NOEXCEPT : __i(__x) {}
|
||||
#endif
|
||||
|
||||
template <class _Up> friend class __wrap_iter;
|
||||
|
@ -1452,50 +1452,50 @@ private:
|
|||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
bool
|
||||
operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
bool
|
||||
operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
bool
|
||||
operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
bool
|
||||
operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
bool
|
||||
operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
bool
|
||||
operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
auto
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
-> decltype(__x.base() - __y.base());
|
||||
#else
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
typename __wrap_iter<_Iter1>::difference_type
|
||||
operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG;
|
||||
operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
template <class _Iter1>
|
||||
_LIBCPP_CONSTEXPR_IF_NODEBUG friend
|
||||
__wrap_iter<_Iter1>
|
||||
operator+(typename __wrap_iter<_Iter1>::difference_type, __wrap_iter<_Iter1>) _NOEXCEPT_DEBUG;
|
||||
operator+(typename __wrap_iter<_Iter1>::difference_type, __wrap_iter<_Iter1>) _NOEXCEPT;
|
||||
|
||||
template <class _Ip, class _Op> friend _Op copy(_Ip, _Ip, _Op);
|
||||
template <class _B1, class _B2> friend _B2 copy_backward(_B1, _B1, _B2);
|
||||
|
@ -1526,7 +1526,7 @@ private:
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
{
|
||||
return __x.base() == __y.base();
|
||||
}
|
||||
|
@ -1534,7 +1534,7 @@ operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y),
|
||||
|
@ -1546,7 +1546,7 @@ operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
{
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
@ -1554,7 +1554,7 @@ operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
{
|
||||
return __y < __x;
|
||||
}
|
||||
|
@ -1562,7 +1562,7 @@ operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
{
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
@ -1570,7 +1570,7 @@ operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
{
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
@ -1578,7 +1578,7 @@ operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX
|
|||
template <class _Iter1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG
|
||||
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
|
||||
{
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
@ -1586,7 +1586,7 @@ operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEX
|
|||
template <class _Iter1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG
|
||||
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
|
||||
{
|
||||
return __y < __x;
|
||||
}
|
||||
|
@ -1594,7 +1594,7 @@ operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXC
|
|||
template <class _Iter1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG
|
||||
operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
|
||||
{
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
@ -1602,7 +1602,7 @@ operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEX
|
|||
template <class _Iter1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
bool
|
||||
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG
|
||||
operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
|
||||
{
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
@ -1611,7 +1611,7 @@ operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEX
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
auto
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
-> decltype(__x.base() - __y.base())
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
@ -1624,7 +1624,7 @@ operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC
|
|||
template <class _Iter1, class _Iter2>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
typename __wrap_iter<_Iter1>::difference_type
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG
|
||||
operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT
|
||||
{
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
_LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y),
|
||||
|
@ -1638,7 +1638,7 @@ template <class _Iter>
|
|||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
|
||||
__wrap_iter<_Iter>
|
||||
operator+(typename __wrap_iter<_Iter>::difference_type __n,
|
||||
__wrap_iter<_Iter> __x) _NOEXCEPT_DEBUG
|
||||
__wrap_iter<_Iter> __x) _NOEXCEPT
|
||||
{
|
||||
__x += __n;
|
||||
return __x;
|
||||
|
|
|
@ -647,9 +647,9 @@ protected:
|
|||
|
||||
void swap(__list_imp& __c)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT_DEBUG;
|
||||
_NOEXCEPT;
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value);
|
||||
#endif
|
||||
|
||||
|
@ -769,9 +769,9 @@ template <class _Tp, class _Alloc>
|
|||
void
|
||||
__list_imp<_Tp, _Alloc>::swap(__list_imp& __c)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT_DEBUG
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value)
|
||||
#endif
|
||||
{
|
||||
|
@ -1038,9 +1038,9 @@ public:
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(list& __c)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT_DEBUG
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(!__node_alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<__node_allocator>::value)
|
||||
#endif
|
||||
{base::swap(__c);}
|
||||
|
|
|
@ -1236,9 +1236,9 @@ public:
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(basic_string& __str)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT_DEBUG;
|
||||
_NOEXCEPT;
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value);
|
||||
#endif
|
||||
|
||||
|
@ -3295,9 +3295,9 @@ inline
|
|||
void
|
||||
basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT_DEBUG
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value)
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -779,9 +779,9 @@ public:
|
|||
|
||||
void swap(vector&)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT_DEBUG;
|
||||
_NOEXCEPT;
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value);
|
||||
#endif
|
||||
|
||||
|
@ -2064,9 +2064,9 @@ template <class _Tp, class _Allocator>
|
|||
void
|
||||
vector<_Tp, _Allocator>::swap(vector& __x)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT_DEBUG
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value)
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -16,6 +16,47 @@ New entries should be added directly below the "Version" header.
|
|||
Version 9.0
|
||||
-----------
|
||||
|
||||
* rTBD - Remove exception throwing debug mode handler support.
|
||||
|
||||
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
|
||||
I thought that if a debug violation aborted, we could only test one violation per file. This made
|
||||
it impossible to test debug mode. Which throwing behavior we could test more!
|
||||
|
||||
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
|
||||
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
|
||||
mode was off.
|
||||
|
||||
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
|
||||
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
|
||||
changing the behavior of their program.
|
||||
|
||||
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
|
||||
death tests.
|
||||
|
||||
All Platforms (ignoring versioning namespaces)
|
||||
----------------------------------------------
|
||||
Symbol added: _ZNKSt3__119__libcpp_debug_info4whatEv
|
||||
Symbol removed: _ZNKSt3__124__libcpp_debug_exception4whatEv
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionC1ERKNS_19__libcpp_debug_infoE
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionC1ERKS0_
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionC1Ev
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionC2ERKNS_19__libcpp_debug_infoE
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionC2ERKS0_
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionC2Ev
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionD0Ev
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionD1Ev
|
||||
Symbol removed: _ZNSt3__124__libcpp_debug_exceptionD2Ev
|
||||
Symbol removed: _ZNSt3__129__libcpp_throw_debug_functionERKNS_19__libcpp_debug_infoE
|
||||
Symbol removed: _ZTINSt3__124__libcpp_debug_exceptionE
|
||||
Symbol removed: _ZTSNSt3__124__libcpp_debug_exceptionE
|
||||
Symbol removed: _ZTVNSt3__124__libcpp_debug_exceptionE
|
||||
|
||||
|
||||
x86_64-apple-apple-darwin
|
||||
-------------------------
|
||||
Symbol added: __ZNSt3__111__libcpp_db10__insert_cEPvPFPNS_8__c_nodeES1_S1_S3_E
|
||||
Symbol removed: __ZNSt3__111__libcpp_db10__insert_cEPv
|
||||
|
||||
* r355367 - Fix -fsanitize=vptr badness in <__debug>
|
||||
|
||||
This patch fixes a lifetime bug when inserting a new container into the debug database. It is
|
||||
|
|
|
@ -219,6 +219,7 @@
|
|||
{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE16do_thousands_sepEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__118__time_get_storageIcE15__do_date_orderEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__118__time_get_storageIwE15__do_date_orderEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__119__libcpp_debug_info4whatEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__119__shared_weak_count13__get_deleterERKSt9type_info', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE11do_encodingEv', 'type': 'FUNC'}
|
||||
|
@ -261,7 +262,6 @@
|
|||
{'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', 'type': 'FUNC'}
|
||||
|
@ -1201,15 +1201,6 @@
|
|||
{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutexD2Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__121undeclare_no_pointersEPcm', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__123__libcpp_debug_functionE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'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_', 'type': 'FUNC'}
|
||||
|
@ -1228,7 +1219,6 @@
|
|||
{'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': 'FUNC'}
|
||||
{'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, 'type': 'OBJECT'}
|
||||
|
@ -1654,7 +1644,6 @@
|
|||
{'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, 'type': 'OBJECT'}
|
||||
|
@ -2182,7 +2171,6 @@
|
|||
{'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, 'type': 'OBJECT'}
|
||||
|
|
|
@ -218,6 +218,7 @@
|
|||
{'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE16do_thousands_sepEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__218__time_get_storageIcE15__do_date_orderEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__218__time_get_storageIwE15__do_date_orderEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__219__libcpp_debug_info4whatEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__219__shared_weak_count13__get_deleterERKSt9type_info', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE11do_encodingEv', 'type': 'FUNC'}
|
||||
|
@ -260,7 +261,6 @@
|
|||
{'is_defined': True, 'name': '__ZNKSt3__221__basic_string_commonILb1EE20__throw_out_of_rangeEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__223__match_any_but_newlineIcE6__execERNS_7__stateIcEE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__223__match_any_but_newlineIwE6__execERNS_7__stateIwEE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__224__libcpp_debug_exception4whatEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE10do_tolowerEPcPKc', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE10do_tolowerEc', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE10do_toupperEPcPKc', 'type': 'FUNC'}
|
||||
|
@ -1123,15 +1123,6 @@
|
|||
{'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutexD2Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__221undeclare_no_pointersEPcm', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__223__libcpp_debug_functionE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC1ERKNS_19__libcpp_debug_infoE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC1ERKS0_', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC1Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC2ERKNS_19__libcpp_debug_infoE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC2ERKS0_', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC2Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionD0Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionD1Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionD2Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__225notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'}
|
||||
|
@ -1150,7 +1141,6 @@
|
|||
{'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIyyEEPyEEbT0_S5_T_', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__227__libcpp_set_debug_functionEPFvRKNS_19__libcpp_debug_infoEE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__229__libcpp_abort_debug_functionERKNS_19__libcpp_debug_infoE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__229__libcpp_throw_debug_functionERKNS_19__libcpp_debug_infoE', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__23cinE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__24cerrE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZNSt3__24clogE', 'size': 0, 'type': 'OBJECT'}
|
||||
|
@ -1577,7 +1567,6 @@
|
|||
{'is_defined': True, 'name': '__ZTINSt3__220__codecvt_utf8_utf16IwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTINSt3__220__time_get_c_storageIcEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTINSt3__220__time_get_c_storageIwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTINSt3__224__libcpp_debug_exceptionE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTINSt3__25ctypeIcEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTINSt3__25ctypeIwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTINSt3__26locale5facetE', 'size': 0, 'type': 'OBJECT'}
|
||||
|
@ -1867,7 +1856,6 @@
|
|||
{'is_defined': True, 'name': '__ZTSNSt3__220__codecvt_utf8_utf16IwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTSNSt3__220__time_get_c_storageIcEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTSNSt3__220__time_get_c_storageIwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTSNSt3__224__libcpp_debug_exceptionE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTSNSt3__25ctypeIcEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTSNSt3__25ctypeIwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTSNSt3__26locale5facetE', 'size': 0, 'type': 'OBJECT'}
|
||||
|
@ -2143,7 +2131,6 @@
|
|||
{'is_defined': True, 'name': '__ZTVNSt3__220__codecvt_utf8_utf16IDiEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTVNSt3__220__codecvt_utf8_utf16IDsEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTVNSt3__220__codecvt_utf8_utf16IwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTVNSt3__224__libcpp_debug_exceptionE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTVNSt3__25ctypeIcEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTVNSt3__25ctypeIwEE', 'size': 0, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '__ZTVNSt3__26locale5facetE', 'size': 0, 'type': 'OBJECT'}
|
||||
|
|
|
@ -211,6 +211,7 @@
|
|||
{'is_defined': True, 'name': '_ZNKSt3__117moneypunct_bynameIwLb1EE16do_thousands_sepEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNKSt3__118__time_get_storageIcE15__do_date_orderEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNKSt3__118__time_get_storageIwE15__do_date_orderEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNKSt3__119__libcpp_debug_info4whatEv', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNKSt3__119__shared_weak_count13__get_deleterERKSt9type_info', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNKSt3__120__codecvt_utf8_utf16IDiE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNKSt3__120__codecvt_utf8_utf16IDiE11do_encodingEv', 'type': 'FUNC'}
|
||||
|
@ -253,7 +254,6 @@
|
|||
{'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', 'type': 'FUNC'}
|
||||
|
@ -1114,15 +1114,6 @@
|
|||
{'is_defined': True, 'name': '_ZNSt3__121recursive_timed_mutexD2Ev', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNSt3__121undeclare_no_pointersEPcm', 'type': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNSt3__123__libcpp_debug_functionE', 'size': 8, 'type': 'OBJECT'}
|
||||
{'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_', 'type': 'FUNC'}
|
||||
|
@ -1141,7 +1132,6 @@
|
|||
{'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': 'FUNC'}
|
||||
{'is_defined': True, 'name': '_ZNSt3__13cinE', 'size': 168, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZNSt3__14cerrE', 'size': 160, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZNSt3__14clogE', 'size': 160, 'type': 'OBJECT'}
|
||||
|
@ -1524,7 +1514,6 @@
|
|||
{'is_defined': True, 'name': '_ZTINSt3__120__codecvt_utf8_utf16IwEE', 'size': 24, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTINSt3__120__time_get_c_storageIcEE', 'size': 16, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTINSt3__120__time_get_c_storageIwEE', 'size': 16, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTINSt3__124__libcpp_debug_exceptionE', 'size': 24, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTINSt3__15ctypeIcEE', 'size': 56, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTINSt3__15ctypeIwEE', 'size': 56, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTINSt3__16locale5facetE', 'size': 24, 'type': 'OBJECT'}
|
||||
|
@ -1650,7 +1639,6 @@
|
|||
{'is_defined': True, 'name': '_ZTSNSt3__120__codecvt_utf8_utf16IwEE', 'size': 34, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTSNSt3__120__time_get_c_storageIcEE', 'size': 34, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTSNSt3__120__time_get_c_storageIwEE', 'size': 34, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTSNSt3__124__libcpp_debug_exceptionE', 'size': 35, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTSNSt3__15ctypeIcEE', 'size': 18, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTSNSt3__15ctypeIwEE', 'size': 18, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTSNSt3__16locale5facetE', 'size': 22, 'type': 'OBJECT'}
|
||||
|
@ -1762,7 +1750,6 @@
|
|||
{'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDiEE', 'size': 96, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDsEE', 'size': 96, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IwEE', 'size': 96, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTVNSt3__124__libcpp_debug_exceptionE', 'size': 40, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTVNSt3__15ctypeIcEE', 'size': 104, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTVNSt3__15ctypeIwEE', 'size': 136, 'type': 'OBJECT'}
|
||||
{'is_defined': True, 'name': '_ZTVNSt3__16locale5facetE', 'size': 40, 'type': 'OBJECT'}
|
||||
|
|
|
@ -17,14 +17,18 @@
|
|||
|
||||
_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_;
|
||||
std::string __libcpp_debug_info::what() const {
|
||||
string msg = __file_;
|
||||
msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '";
|
||||
msg += __pred_;
|
||||
msg += "' failed. ";
|
||||
msg += info.__msg_;
|
||||
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();
|
||||
}
|
||||
|
||||
_LIBCPP_SAFE_STATIC __libcpp_debug_function_type
|
||||
__libcpp_debug_function = __libcpp_abort_debug_function;
|
||||
|
@ -34,51 +38,6 @@ bool __libcpp_set_debug_function(__libcpp_debug_function_type __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) {
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw __libcpp_debug_exception(info);
|
||||
#else
|
||||
__libcpp_abort_debug_function(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
|
@ -5,29 +5,18 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// UNSUPPORTED: libcpp-no-exceptions
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
||||
// test array<T, 0>::front() throws a debug exception.
|
||||
// test array<T, 0>::front() raises a debug error.
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#include <array>
|
||||
|
||||
template <class Array>
|
||||
inline bool CheckDebugThrows(Array& Arr) {
|
||||
try {
|
||||
Arr.back();
|
||||
} catch (std::__libcpp_debug_exception const&) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
|
@ -35,15 +24,15 @@ int main(int, char**)
|
|||
typedef std::array<int, 0> C;
|
||||
C c = {};
|
||||
C const& cc = c;
|
||||
assert(CheckDebugThrows(c));
|
||||
assert(CheckDebugThrows(cc));
|
||||
EXPECT_DEATH( c.back() );
|
||||
EXPECT_DEATH( cc.back() );
|
||||
}
|
||||
{
|
||||
typedef std::array<const int, 0> C;
|
||||
C c = {{}};
|
||||
C const& cc = c;
|
||||
assert(CheckDebugThrows(c));
|
||||
assert(CheckDebugThrows(cc));
|
||||
EXPECT_DEATH( c.back() );
|
||||
EXPECT_DEATH( cc.back() );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -5,29 +5,18 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// UNSUPPORTED: libcpp-no-exceptions
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
||||
// test array<T, 0>::front() throws a debug exception.
|
||||
// test array<T, 0>::front() raises a debug error.
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#include <array>
|
||||
|
||||
template <class Array>
|
||||
inline bool CheckDebugThrows(Array& Arr) {
|
||||
try {
|
||||
Arr.front();
|
||||
} catch (std::__libcpp_debug_exception const&) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
|
@ -35,15 +24,15 @@ int main(int, char**)
|
|||
typedef std::array<int, 0> C;
|
||||
C c = {};
|
||||
C const& cc = c;
|
||||
assert(CheckDebugThrows(c));
|
||||
assert(CheckDebugThrows(cc));
|
||||
EXPECT_DEATH(c.front());
|
||||
EXPECT_DEATH(cc.front());
|
||||
}
|
||||
{
|
||||
typedef std::array<const int, 0> C;
|
||||
C c = {{}};
|
||||
C const& cc = c;
|
||||
assert(CheckDebugThrows(c));
|
||||
assert(CheckDebugThrows(cc));
|
||||
EXPECT_DEATH(c.front());
|
||||
EXPECT_DEATH(cc.front());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -5,29 +5,18 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// XFAIL:*
|
||||
// UNSUPPORTED: libcpp-no-exceptions
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
||||
// test array<T, 0>::operator[] throws a debug exception.
|
||||
// test array<T, 0>::operator[] raises a debug error.
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#include <array>
|
||||
|
||||
template <class Array>
|
||||
inline bool CheckDebugThrows(Array& Arr, size_t Index) {
|
||||
try {
|
||||
Arr[Index];
|
||||
} catch (std::__libcpp_debug_exception const&) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
|
@ -35,19 +24,19 @@ int main(int, char**)
|
|||
typedef std::array<int, 0> C;
|
||||
C c = {};
|
||||
C const& cc = c;
|
||||
assert(CheckDebugThrows(c, 0));
|
||||
assert(CheckDebugThrows(c, 1));
|
||||
assert(CheckDebugThrows(cc, 0));
|
||||
assert(CheckDebugThrows(cc, 1));
|
||||
EXPECT_DEATH( c[0] );
|
||||
EXPECT_DEATH( c[1] );
|
||||
EXPECT_DEATH( cc[0] );
|
||||
EXPECT_DEATH( cc[1] );
|
||||
}
|
||||
{
|
||||
typedef std::array<const int, 0> C;
|
||||
C c = {{}};
|
||||
C const& cc = c;
|
||||
assert(CheckDebugThrows(c, 0));
|
||||
assert(CheckDebugThrows(c, 1));
|
||||
assert(CheckDebugThrows(cc, 0));
|
||||
assert(CheckDebugThrows(cc, 1));
|
||||
EXPECT_DEATH( c[0] );
|
||||
EXPECT_DEATH( c[1] );
|
||||
EXPECT_DEATH( cc[0] );
|
||||
EXPECT_DEATH( cc[1] );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
|
||||
// UNSUPPORTED: libcpp-no-if-constexpr
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
@ -17,12 +16,12 @@
|
|||
// test container debugging
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
#include "container_debug_tests.hpp"
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
using namespace IteratorDebugChecks;
|
||||
|
@ -40,11 +39,6 @@ struct AssociativeContainerChecks : BasicContainerChecks<Container, CT> {
|
|||
public:
|
||||
static void run() {
|
||||
Base::run();
|
||||
try {
|
||||
// FIXME Add tests
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -6,11 +6,9 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// XFAIL: *
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
|
||||
// UNSUPPORTED: libcpp-no-if-constexpr
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
@ -18,11 +16,12 @@
|
|||
// test container debugging
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include "container_debug_tests.hpp"
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
using namespace IteratorDebugChecks;
|
||||
|
@ -40,11 +39,10 @@ struct SequenceContainerChecks : BasicContainerChecks<Container, CT> {
|
|||
public:
|
||||
static void run() {
|
||||
Base::run();
|
||||
try {
|
||||
SanityTest();
|
||||
FrontOnEmptyContainer();
|
||||
SanityTest();
|
||||
FrontOnEmptyContainer();
|
||||
|
||||
if constexpr (CT != CT_ForwardList) {
|
||||
if constexpr(CT != CT_ForwardList) {
|
||||
AssignInvalidates();
|
||||
BackOnEmptyContainer();
|
||||
InsertIterValue();
|
||||
|
@ -52,24 +50,22 @@ public:
|
|||
InsertIterIterIter();
|
||||
EmplaceIterValue();
|
||||
EraseIterIter();
|
||||
} else {
|
||||
SpliceFirstElemAfter();
|
||||
}
|
||||
if constexpr (CT == CT_Vector || CT == CT_Deque || CT == CT_List) {
|
||||
PopBack();
|
||||
}
|
||||
if constexpr (CT == CT_List || CT == CT_Deque) {
|
||||
PopFront(); // FIXME: Run with forward list as well
|
||||
}
|
||||
if constexpr (CT == CT_List || CT == CT_ForwardList) {
|
||||
RemoveFirstElem();
|
||||
}
|
||||
if constexpr (CT == CT_List) {
|
||||
SpliceFirstElem();
|
||||
SpliceSameContainer();
|
||||
}
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
else {
|
||||
SpliceFirstElemAfter();
|
||||
}
|
||||
if constexpr (CT == CT_Vector || CT == CT_Deque || CT == CT_List) {
|
||||
PopBack();
|
||||
}
|
||||
if constexpr (CT == CT_List || CT == CT_Deque) {
|
||||
PopFront(); // FIXME: Run with forward list as well
|
||||
}
|
||||
if constexpr (CT == CT_List || CT == CT_ForwardList) {
|
||||
RemoveFirstElem();
|
||||
}
|
||||
if constexpr (CT == CT_List) {
|
||||
SpliceFirstElem();
|
||||
SpliceSameContainer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,9 +140,9 @@ private:
|
|||
it3 = C.end();
|
||||
};
|
||||
auto check = [&]() {
|
||||
CHECK_DEBUG_THROWS( C.erase(it1) );
|
||||
CHECK_DEBUG_THROWS( C.erase(it2) );
|
||||
CHECK_DEBUG_THROWS( C.erase(it3, C.end()) );
|
||||
EXPECT_DEATH( C.erase(it1) );
|
||||
EXPECT_DEATH( C.erase(it2) );
|
||||
EXPECT_DEATH( C.erase(it3, C.end()) );
|
||||
};
|
||||
reset();
|
||||
C.assign(2, makeValueType(4));
|
||||
|
@ -173,8 +169,8 @@ private:
|
|||
(void)C.back();
|
||||
(void)CC.back();
|
||||
C.clear();
|
||||
CHECK_DEBUG_THROWS( C.back() );
|
||||
CHECK_DEBUG_THROWS( CC.back() );
|
||||
EXPECT_DEATH( C.back() );
|
||||
EXPECT_DEATH( CC.back() );
|
||||
}
|
||||
|
||||
static void FrontOnEmptyContainer() {
|
||||
|
@ -184,8 +180,8 @@ private:
|
|||
(void)C.front();
|
||||
(void)CC.front();
|
||||
C.clear();
|
||||
CHECK_DEBUG_THROWS( C.front() );
|
||||
CHECK_DEBUG_THROWS( CC.front() );
|
||||
EXPECT_DEATH( C.front() );
|
||||
EXPECT_DEATH( CC.front() );
|
||||
}
|
||||
|
||||
static void EraseIterIter() {
|
||||
|
@ -198,15 +194,15 @@ private:
|
|||
iterator it1_back = --C1.end();
|
||||
assert(it1_next != it1_back);
|
||||
if (CT == CT_Vector) {
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1_next, it1) ); // bad range
|
||||
EXPECT_DEATH( C1.erase(it1_next, it1) ); // bad range
|
||||
}
|
||||
C1.erase(it1, it1_after_next);
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1) );
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1_next) );
|
||||
EXPECT_DEATH( C1.erase(it1) );
|
||||
EXPECT_DEATH( C1.erase(it1_next) );
|
||||
if (CT == CT_List) {
|
||||
C1.erase(it1_back);
|
||||
} else {
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1_back) );
|
||||
EXPECT_DEATH( C1.erase(it1_back) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,10 +212,10 @@ private:
|
|||
iterator it1 = C1.end();
|
||||
--it1;
|
||||
C1.pop_back();
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1) );
|
||||
EXPECT_DEATH( C1.erase(it1) );
|
||||
C1.erase(C1.begin());
|
||||
assert(C1.size() == 0);
|
||||
CHECK_DEBUG_THROWS( C1.pop_back() );
|
||||
EXPECT_DEATH( C1.pop_back() );
|
||||
}
|
||||
|
||||
static void PopFront() {
|
||||
|
@ -227,10 +223,10 @@ private:
|
|||
Container C1 = makeContainer(2);
|
||||
iterator it1 = C1.begin();
|
||||
C1.pop_front();
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1) );
|
||||
EXPECT_DEATH( C1.erase(it1) );
|
||||
C1.erase(C1.begin());
|
||||
assert(C1.size() == 0);
|
||||
CHECK_DEBUG_THROWS( C1.pop_front() );
|
||||
EXPECT_DEATH( C1.pop_front() );
|
||||
}
|
||||
|
||||
static void InsertIterValue() {
|
||||
|
@ -242,8 +238,8 @@ private:
|
|||
Container C2 = C1;
|
||||
const value_type value = makeValueType(3);
|
||||
value_type rvalue = makeValueType(3);
|
||||
CHECK_DEBUG_THROWS( C2.insert(it1, value) ); // wrong container
|
||||
CHECK_DEBUG_THROWS( C2.insert(it1, std::move(rvalue)) ); // wrong container
|
||||
EXPECT_DEATH( C2.insert(it1, value) ); // wrong container
|
||||
EXPECT_DEATH( C2.insert(it1, std::move(rvalue)) ); // wrong container
|
||||
C1.insert(it1_next, value);
|
||||
if (CT == CT_List) {
|
||||
C1.insert(it1_next, value);
|
||||
|
@ -251,10 +247,10 @@ private:
|
|||
C1.insert(it1_next, std::move(rvalue));
|
||||
C1.insert(it1, std::move(rvalue));
|
||||
} else {
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1_next, value) ); // invalidated iterator
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1, value) ); // invalidated iterator
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1_next, std::move(rvalue)) ); // invalidated iterator
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1, std::move(rvalue)) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1_next, value) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1, value) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1_next, std::move(rvalue)) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1, std::move(rvalue)) ); // invalidated iterator
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,15 +262,15 @@ private:
|
|||
++it1_next;
|
||||
Container C2 = C1;
|
||||
const value_type value = makeValueType(3);
|
||||
CHECK_DEBUG_THROWS( C2.emplace(it1, value) ); // wrong container
|
||||
CHECK_DEBUG_THROWS( C2.emplace(it1, makeValueType(4)) ); // wrong container
|
||||
EXPECT_DEATH( C2.emplace(it1, value) ); // wrong container
|
||||
EXPECT_DEATH( C2.emplace(it1, makeValueType(4)) ); // wrong container
|
||||
C1.emplace(it1_next, value);
|
||||
if (CT == CT_List) {
|
||||
C1.emplace(it1_next, value);
|
||||
C1.emplace(it1, value);
|
||||
} else {
|
||||
CHECK_DEBUG_THROWS( C1.emplace(it1_next, value) ); // invalidated iterator
|
||||
CHECK_DEBUG_THROWS( C1.emplace(it1, value) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.emplace(it1_next, value) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.emplace(it1, value) ); // invalidated iterator
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,14 +282,14 @@ private:
|
|||
++it1_next;
|
||||
Container C2 = C1;
|
||||
const value_type value = makeValueType(3);
|
||||
CHECK_DEBUG_THROWS( C2.insert(it1, 1, value) ); // wrong container
|
||||
EXPECT_DEATH( C2.insert(it1, 1, value) ); // wrong container
|
||||
C1.insert(it1_next, 2, value);
|
||||
if (CT == CT_List) {
|
||||
C1.insert(it1_next, 3, value);
|
||||
C1.insert(it1, 1, value);
|
||||
} else {
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1_next, 1, value) ); // invalidated iterator
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1, 1, value) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1_next, 1, value) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1, 1, value) ); // invalidated iterator
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,14 +305,14 @@ private:
|
|||
makeValueType(2),
|
||||
makeValueType(3)
|
||||
};
|
||||
CHECK_DEBUG_THROWS( C2.insert(it1, V.begin(), V.end()) ); // wrong container
|
||||
EXPECT_DEATH( C2.insert(it1, V.begin(), V.end()) ); // wrong container
|
||||
C1.insert(it1_next, V.begin(), V.end());
|
||||
if (CT == CT_List) {
|
||||
C1.insert(it1_next, V.begin(), V.end());
|
||||
C1.insert(it1, V.begin(), V.end());
|
||||
} else {
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1_next, V.begin(), V.end()) ); // invalidated iterator
|
||||
CHECK_DEBUG_THROWS( C1.insert(it1, V.begin(), V.end()) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1_next, V.begin(), V.end()) ); // invalidated iterator
|
||||
EXPECT_DEATH( C1.insert(it1, V.begin(), V.end()) ); // invalidated iterator
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
|
||||
// UNSUPPORTED: libcpp-no-if-constexpr
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
@ -17,11 +16,11 @@
|
|||
// test container debugging
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "container_debug_tests.hpp"
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
using namespace IteratorDebugChecks;
|
||||
|
@ -43,14 +42,11 @@ public:
|
|||
static void run() {
|
||||
Base::run_iterator_tests();
|
||||
Base::run_allocator_aware_tests();
|
||||
try {
|
||||
for (int N : {3, 128}) {
|
||||
FrontOnEmptyContainer(N);
|
||||
BackOnEmptyContainer(N);
|
||||
PopBack(N);
|
||||
}
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
|
||||
for (int N : {3, 128}) {
|
||||
FrontOnEmptyContainer(N);
|
||||
BackOnEmptyContainer(N);
|
||||
PopBack(N);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,10 +59,10 @@ private:
|
|||
(void)C.back();
|
||||
(void)CC.back();
|
||||
C.pop_back();
|
||||
CHECK_DEBUG_THROWS( C.erase(it) );
|
||||
EXPECT_DEATH( C.erase(it) );
|
||||
C.clear();
|
||||
CHECK_DEBUG_THROWS( C.back() );
|
||||
CHECK_DEBUG_THROWS( CC.back() );
|
||||
EXPECT_DEATH( C.back() );
|
||||
EXPECT_DEATH( CC.back() );
|
||||
}
|
||||
|
||||
static void FrontOnEmptyContainer(int N) {
|
||||
|
@ -76,8 +72,8 @@ private:
|
|||
(void)C.front();
|
||||
(void)CC.front();
|
||||
C.clear();
|
||||
CHECK_DEBUG_THROWS( C.front() );
|
||||
CHECK_DEBUG_THROWS( CC.front() );
|
||||
EXPECT_DEATH( C.front() );
|
||||
EXPECT_DEATH( CC.front() );
|
||||
}
|
||||
|
||||
static void PopBack(int N) {
|
||||
|
@ -86,10 +82,10 @@ private:
|
|||
iterator it1 = C1.end();
|
||||
--it1;
|
||||
C1.pop_back();
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1) );
|
||||
EXPECT_DEATH( C1.erase(it1) );
|
||||
C1.erase(C1.begin(), C1.end());
|
||||
assert(C1.size() == 0);
|
||||
CHECK_DEBUG_THROWS( C1.pop_back() );
|
||||
EXPECT_DEATH_MATCHES(DebugInfoMatcher("string::pop_back(): string is already empty"), C1.pop_back() );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
|
||||
// UNSUPPORTED: libcpp-no-if-constexpr
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
@ -17,11 +16,11 @@
|
|||
// test container debugging
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
#include "container_debug_tests.hpp"
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
using namespace IteratorDebugChecks;
|
||||
|
@ -39,11 +38,6 @@ struct UnorderedContainerChecks : BasicContainerChecks<Container, CT> {
|
|||
public:
|
||||
static void run() {
|
||||
Base::run();
|
||||
try {
|
||||
// FIXME
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
|
||||
#include <__debug>
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
|
||||
template <class Func>
|
||||
inline bool TestDeathTest(const char* stmt, Func&& func, DeathTest::ResultKind ExpectResult, DebugInfoMatcher Matcher = AnyMatcher) {
|
||||
DeathTest DT(Matcher);
|
||||
DeathTest::ResultKind RK = DT.Run(func);
|
||||
auto OnFailure = [&](std::string msg) {
|
||||
std::cerr << "EXPECT_DEATH( " << stmt << " ) failed! (" << msg << ")\n\n";
|
||||
if (!DT.getChildStdErr().empty()) {
|
||||
std::cerr << "---------- standard err ----------\n";
|
||||
std::cerr << DT.getChildStdErr() << "\n";
|
||||
}
|
||||
if (!DT.getChildStdOut().empty()) {
|
||||
std::cerr << "---------- standard out ----------\n";
|
||||
std::cerr << DT.getChildStdOut() << "\n";
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (RK != ExpectResult)
|
||||
return OnFailure(std::string("expected result did not occur: expected ") + DeathTest::ResultKindToString(ExpectResult) + " got: " + DeathTest::ResultKindToString(RK));
|
||||
return true;
|
||||
}
|
||||
#define TEST_DEATH_TEST(RK, ...) assert((TestDeathTest(#__VA_ARGS__, [&]() { __VA_ARGS__; }, RK, AnyMatcher )))
|
||||
|
||||
#define TEST_DEATH_TEST_MATCHES(RK, Matcher, ...) assert((TestDeathTest(#__VA_ARGS__, [&]() { __VA_ARGS__; }, RK, Matcher)))
|
||||
|
||||
void my_libcpp_assert() {
|
||||
_LIBCPP_ASSERT(false, "other");
|
||||
}
|
||||
|
||||
void test_no_match_found() {
|
||||
DebugInfoMatcher ExpectMatch("my message");
|
||||
TEST_DEATH_TEST_MATCHES(DeathTest::RK_MatchFailure, ExpectMatch, my_libcpp_assert());
|
||||
}
|
||||
|
||||
void test_did_not_die() {
|
||||
TEST_DEATH_TEST(DeathTest::RK_DidNotDie, ((void)0));
|
||||
}
|
||||
|
||||
void test_unknown() {
|
||||
TEST_DEATH_TEST(DeathTest::RK_Unknown, std::exit(13));
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_no_match_found();
|
||||
test_did_not_die();
|
||||
test_unknown();
|
||||
return 0;
|
||||
}
|
|
@ -7,31 +7,27 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcpp-no-exceptions
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
||||
// 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 <string>
|
||||
#include <type_traits>
|
||||
#include <__debug>
|
||||
#include <cassert>
|
||||
|
||||
void my_debug_function(std::__libcpp_debug_info const& info) {
|
||||
assert(info.__msg_ == std::string("foo"));
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
try {
|
||||
_LIBCPP_ASSERT(false, "foo");
|
||||
assert(false);
|
||||
} catch (...) {}
|
||||
|
||||
return 0;
|
||||
std::__libcpp_set_debug_function(&my_debug_function);
|
||||
_LIBCPP_ASSERT(false, "foo");
|
||||
return 1;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcpp-no-exceptions
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=0
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
// UNSUPPORTED: with_system_cxx_lib
|
||||
|
||||
// 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(int, char**)
|
||||
{
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -7,9 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// UNSUPPORTED: libcpp-no-exceptions
|
||||
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=0
|
||||
|
||||
// <filesystem>
|
||||
|
@ -17,7 +15,6 @@
|
|||
// class path
|
||||
|
||||
#define _LIBCPP_DEBUG 0
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#include "filesystem_include.hpp"
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
@ -25,51 +22,32 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
using ExType = std::__libcpp_debug_exception;
|
||||
// Test incrementing/decrementing a singular iterator
|
||||
{
|
||||
path::iterator singular;
|
||||
try {
|
||||
++singular;
|
||||
assert(false);
|
||||
} catch (ExType const&) {}
|
||||
try {
|
||||
--singular;
|
||||
assert(false);
|
||||
} catch (ExType const&) {}
|
||||
EXPECT_DEATH( ++singular );
|
||||
EXPECT_DEATH( --singular );
|
||||
}
|
||||
// Test decrementing the begin iterator
|
||||
{
|
||||
path p("foo/bar");
|
||||
auto it = p.begin();
|
||||
try {
|
||||
--it;
|
||||
assert(false);
|
||||
} catch (ExType const&) {}
|
||||
++it;
|
||||
++it;
|
||||
try {
|
||||
++it;
|
||||
assert(false);
|
||||
} catch (ExType const&) {}
|
||||
EXPECT_DEATH( ++it );
|
||||
}
|
||||
// Test incrementing the end iterator
|
||||
{
|
||||
path p("foo/bar");
|
||||
auto it = p.end();
|
||||
try {
|
||||
++it;
|
||||
assert(false);
|
||||
} catch (ExType const&) {}
|
||||
EXPECT_DEATH( ++it );
|
||||
--it;
|
||||
--it;
|
||||
try {
|
||||
--it;
|
||||
assert(false);
|
||||
} catch (ExType const&) {}
|
||||
EXPECT_DEATH( --it );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -6,11 +6,9 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcpp-no-exceptions
|
||||
// UNSUPPORTED: libcpp-has-no-threads
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=0
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
|
@ -24,33 +22,28 @@
|
|||
// Test that a null exception_ptr is diagnosed.
|
||||
|
||||
#define _LIBCPP_DEBUG 0
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
|
||||
#include <future>
|
||||
#include <exception>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
typedef std::__libcpp_debug_exception ExType;
|
||||
{
|
||||
typedef int T;
|
||||
std::promise<T> p;
|
||||
try {
|
||||
p.set_exception(std::exception_ptr());
|
||||
assert(false);
|
||||
} catch (ExType const&) {
|
||||
}
|
||||
|
||||
EXPECT_DEATH( p.set_exception(std::exception_ptr()) );
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
std::promise<T> p;
|
||||
try {
|
||||
p.set_exception(std::exception_ptr());
|
||||
assert(false);
|
||||
} catch (ExType const&) {
|
||||
}
|
||||
|
||||
EXPECT_DEATH( p.set_exception(std::exception_ptr()) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
// UNSUPPORTED: libcpp-has-no-threads
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
// MODULES_DEFINES: _LIBCPP_DEBUG=0
|
||||
|
||||
// Can't test the system lib because this test enables debug mode
|
||||
|
@ -24,33 +23,27 @@
|
|||
// Test that a null exception_ptr is diagnosed.
|
||||
|
||||
#define _LIBCPP_DEBUG 0
|
||||
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#include <future>
|
||||
#include <exception>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include "debug_mode_helper.h"
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
typedef std::__libcpp_debug_exception ExType;
|
||||
{
|
||||
typedef int T;
|
||||
std::promise<T> p;
|
||||
try {
|
||||
p.set_exception_at_thread_exit(std::exception_ptr());
|
||||
assert(false);
|
||||
} catch (ExType const& value) {
|
||||
}
|
||||
|
||||
EXPECT_DEATH( p.set_exception_at_thread_exit(std::exception_ptr()) );
|
||||
|
||||
}
|
||||
{
|
||||
typedef int& T;
|
||||
std::promise<T> p;
|
||||
try {
|
||||
p.set_exception_at_thread_exit(std::exception_ptr());
|
||||
assert(false);
|
||||
} catch (ExType const& value) {
|
||||
}
|
||||
|
||||
EXPECT_DEATH( p.set_exception_at_thread_exit(std::exception_ptr()) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,371 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TEST_SUPPORT_CONTAINER_DEBUG_TESTS_H
|
||||
#define TEST_SUPPORT_CONTAINER_DEBUG_TESTS_H
|
||||
|
||||
#include <ciso646>
|
||||
#ifndef _LIBCPP_VERSION
|
||||
#error This header may only be used for libc++ tests"
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_DEBUG
|
||||
#error _LIBCPP_DEBUG must be defined before including this header
|
||||
#endif
|
||||
|
||||
#include <__debug>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "debug_mode_helper.h"
|
||||
#include "assert_checkpoint.h"
|
||||
#include "test_allocator.h"
|
||||
|
||||
// These test make use of 'if constexpr'.
|
||||
#if TEST_STD_VER <= 14
|
||||
#error This header may only be used in C++17 and greater
|
||||
#endif
|
||||
|
||||
#ifndef __cpp_if_constexpr
|
||||
#error These tests require if constexpr
|
||||
#endif
|
||||
|
||||
|
||||
namespace IteratorDebugChecks {
|
||||
|
||||
enum ContainerType {
|
||||
CT_None,
|
||||
CT_String,
|
||||
CT_Vector,
|
||||
CT_VectorBool,
|
||||
CT_List,
|
||||
CT_Deque,
|
||||
CT_ForwardList,
|
||||
CT_Map,
|
||||
CT_Set,
|
||||
CT_MultiMap,
|
||||
CT_MultiSet,
|
||||
CT_UnorderedMap,
|
||||
CT_UnorderedSet,
|
||||
CT_UnorderedMultiMap,
|
||||
CT_UnorderedMultiSet
|
||||
};
|
||||
|
||||
constexpr bool isSequential(ContainerType CT) {
|
||||
return CT_Vector >= CT && CT_ForwardList <= CT;
|
||||
}
|
||||
|
||||
constexpr bool isAssociative(ContainerType CT) {
|
||||
return CT_Map >= CT && CT_MultiSet <= CT;
|
||||
}
|
||||
|
||||
constexpr bool isUnordered(ContainerType CT) {
|
||||
return CT_UnorderedMap >= CT && CT_UnorderedMultiSet <= CT;
|
||||
}
|
||||
|
||||
constexpr bool isSet(ContainerType CT) {
|
||||
return CT == CT_Set
|
||||
|| CT == CT_MultiSet
|
||||
|| CT == CT_UnorderedSet
|
||||
|| CT == CT_UnorderedMultiSet;
|
||||
}
|
||||
|
||||
constexpr bool isMap(ContainerType CT) {
|
||||
return CT == CT_Map
|
||||
|| CT == CT_MultiMap
|
||||
|| CT == CT_UnorderedMap
|
||||
|| CT == CT_UnorderedMultiMap;
|
||||
}
|
||||
|
||||
constexpr bool isMulti(ContainerType CT) {
|
||||
return CT == CT_MultiMap
|
||||
|| CT == CT_MultiSet
|
||||
|| CT == CT_UnorderedMultiMap
|
||||
|| CT == CT_UnorderedMultiSet;
|
||||
}
|
||||
|
||||
template <class Container, class ValueType = typename Container::value_type>
|
||||
struct ContainerDebugHelper {
|
||||
static_assert(std::is_constructible<ValueType, int>::value,
|
||||
"must be constructible from int");
|
||||
|
||||
static ValueType makeValueType(int val = 0, int = 0) {
|
||||
return ValueType(val);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Container>
|
||||
struct ContainerDebugHelper<Container, char> {
|
||||
static char makeValueType(int = 0, int = 0) {
|
||||
return 'A';
|
||||
}
|
||||
};
|
||||
|
||||
template <class Container, class Key, class Value>
|
||||
struct ContainerDebugHelper<Container, std::pair<const Key, Value> > {
|
||||
using ValueType = std::pair<const Key, Value>;
|
||||
static_assert(std::is_constructible<Key, int>::value,
|
||||
"must be constructible from int");
|
||||
static_assert(std::is_constructible<Value, int>::value,
|
||||
"must be constructible from int");
|
||||
|
||||
static ValueType makeValueType(int key = 0, int val = 0) {
|
||||
return ValueType(key, val);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Container, ContainerType CT,
|
||||
class Helper = ContainerDebugHelper<Container> >
|
||||
struct BasicContainerChecks {
|
||||
using value_type = typename Container::value_type;
|
||||
using iterator = typename Container::iterator;
|
||||
using const_iterator = typename Container::const_iterator;
|
||||
using allocator_type = typename Container::allocator_type;
|
||||
using traits = std::iterator_traits<iterator>;
|
||||
using category = typename traits::iterator_category;
|
||||
|
||||
static_assert(std::is_same<test_allocator<value_type>, allocator_type>::value,
|
||||
"the container must use a test allocator");
|
||||
|
||||
static constexpr bool IsBiDir =
|
||||
std::is_convertible<category, std::bidirectional_iterator_tag>::value;
|
||||
|
||||
public:
|
||||
static void run() {
|
||||
run_iterator_tests();
|
||||
run_container_tests();
|
||||
run_allocator_aware_tests();
|
||||
}
|
||||
|
||||
static void run_iterator_tests() {
|
||||
try {
|
||||
TestNullIterators<iterator>();
|
||||
TestNullIterators<const_iterator>();
|
||||
if constexpr (IsBiDir) { DecrementBegin(); }
|
||||
IncrementEnd();
|
||||
DerefEndIterator();
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
|
||||
static void run_container_tests() {
|
||||
try {
|
||||
CopyInvalidatesIterators();
|
||||
MoveInvalidatesIterators();
|
||||
if constexpr (CT != CT_ForwardList) {
|
||||
EraseIter();
|
||||
EraseIterIter();
|
||||
}
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
|
||||
static void run_allocator_aware_tests() {
|
||||
try {
|
||||
SwapNonEqualAllocators();
|
||||
if constexpr (CT != CT_ForwardList ) {
|
||||
// FIXME: This should work for both forward_list and string
|
||||
SwapInvalidatesIterators();
|
||||
}
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
|
||||
static Container makeContainer(int size, allocator_type A = allocator_type()) {
|
||||
Container C(A);
|
||||
if constexpr (CT == CT_ForwardList) {
|
||||
for (int i = 0; i < size; ++i)
|
||||
C.insert_after(C.before_begin(), Helper::makeValueType(i));
|
||||
} else {
|
||||
for (int i = 0; i < size; ++i)
|
||||
C.insert(C.end(), Helper::makeValueType(i));
|
||||
assert(C.size() == static_cast<std::size_t>(size));
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
static value_type makeValueType(int value) {
|
||||
return Helper::makeValueType(value);
|
||||
}
|
||||
|
||||
private:
|
||||
// Iterator tests
|
||||
template <class Iter>
|
||||
static void TestNullIterators() {
|
||||
CHECKPOINT("testing null iterator");
|
||||
Iter it;
|
||||
EXPECT_DEATH( ++it );
|
||||
EXPECT_DEATH( it++ );
|
||||
EXPECT_DEATH( *it );
|
||||
if constexpr (CT != CT_VectorBool) {
|
||||
EXPECT_DEATH( it.operator->() );
|
||||
}
|
||||
if constexpr (IsBiDir) {
|
||||
EXPECT_DEATH( --it );
|
||||
EXPECT_DEATH( it-- );
|
||||
}
|
||||
}
|
||||
|
||||
static void DecrementBegin() {
|
||||
CHECKPOINT("testing decrement on begin");
|
||||
Container C = makeContainer(1);
|
||||
iterator i = C.end();
|
||||
const_iterator ci = C.cend();
|
||||
--i;
|
||||
--ci;
|
||||
assert(i == C.begin());
|
||||
EXPECT_DEATH( --i );
|
||||
EXPECT_DEATH( i-- );
|
||||
EXPECT_DEATH( --ci );
|
||||
EXPECT_DEATH( ci-- );
|
||||
}
|
||||
|
||||
static void IncrementEnd() {
|
||||
CHECKPOINT("testing increment on end");
|
||||
Container C = makeContainer(1);
|
||||
iterator i = C.begin();
|
||||
const_iterator ci = C.begin();
|
||||
++i;
|
||||
++ci;
|
||||
assert(i == C.end());
|
||||
EXPECT_DEATH( ++i );
|
||||
EXPECT_DEATH( i++ );
|
||||
EXPECT_DEATH( ++ci );
|
||||
EXPECT_DEATH( ci++ );
|
||||
}
|
||||
|
||||
static void DerefEndIterator() {
|
||||
CHECKPOINT("testing deref end iterator");
|
||||
Container C = makeContainer(1);
|
||||
iterator i = C.begin();
|
||||
const_iterator ci = C.cbegin();
|
||||
(void)*i; (void)*ci;
|
||||
if constexpr (CT != CT_VectorBool) {
|
||||
i.operator->();
|
||||
ci.operator->();
|
||||
}
|
||||
++i; ++ci;
|
||||
assert(i == C.end());
|
||||
EXPECT_DEATH( *i );
|
||||
EXPECT_DEATH( *ci );
|
||||
if constexpr (CT != CT_VectorBool) {
|
||||
EXPECT_DEATH( i.operator->() );
|
||||
EXPECT_DEATH( ci.operator->() );
|
||||
}
|
||||
}
|
||||
|
||||
// Container tests
|
||||
static void CopyInvalidatesIterators() {
|
||||
CHECKPOINT("copy invalidates iterators");
|
||||
Container C1 = makeContainer(3);
|
||||
iterator i = C1.begin();
|
||||
Container C2 = C1;
|
||||
if constexpr (CT == CT_ForwardList) {
|
||||
iterator i_next = i;
|
||||
++i_next;
|
||||
(void)*i_next;
|
||||
EXPECT_DEATH( C2.erase_after(i) );
|
||||
C1.erase_after(i);
|
||||
EXPECT_DEATH( *i_next );
|
||||
} else {
|
||||
EXPECT_DEATH( C2.erase(i) );
|
||||
(void)*i;
|
||||
C1.erase(i);
|
||||
EXPECT_DEATH( *i );
|
||||
}
|
||||
}
|
||||
|
||||
static void MoveInvalidatesIterators() {
|
||||
CHECKPOINT("copy move invalidates iterators");
|
||||
Container C1 = makeContainer(3);
|
||||
iterator i = C1.begin();
|
||||
Container C2 = std::move(C1);
|
||||
(void) *i;
|
||||
if constexpr (CT == CT_ForwardList) {
|
||||
EXPECT_DEATH( C1.erase_after(i) );
|
||||
C2.erase_after(i);
|
||||
} else {
|
||||
EXPECT_DEATH( C1.erase(i) );
|
||||
C2.erase(i);
|
||||
EXPECT_DEATH(*i);
|
||||
}
|
||||
}
|
||||
|
||||
static void EraseIter() {
|
||||
CHECKPOINT("testing erase invalidation");
|
||||
Container C1 = makeContainer(2);
|
||||
iterator it1 = C1.begin();
|
||||
iterator it1_next = it1;
|
||||
++it1_next;
|
||||
Container C2 = C1;
|
||||
EXPECT_DEATH( C2.erase(it1) ); // wrong container
|
||||
EXPECT_DEATH( C2.erase(C2.end()) ); // erase with end
|
||||
C1.erase(it1_next);
|
||||
EXPECT_DEATH( C1.erase(it1_next) ); // invalidated iterator
|
||||
C1.erase(it1);
|
||||
EXPECT_DEATH( C1.erase(it1) ); // invalidated iterator
|
||||
}
|
||||
|
||||
static void EraseIterIter() {
|
||||
CHECKPOINT("testing erase iter iter invalidation");
|
||||
Container C1 = makeContainer(2);
|
||||
iterator it1 = C1.begin();
|
||||
iterator it1_next = it1;
|
||||
++it1_next;
|
||||
Container C2 = C1;
|
||||
iterator it2 = C2.begin();
|
||||
iterator it2_next = it2;
|
||||
++it2_next;
|
||||
EXPECT_DEATH( C2.erase(it1, it1_next) ); // begin from wrong container
|
||||
EXPECT_DEATH( C2.erase(it1, it2_next) ); // end from wrong container
|
||||
EXPECT_DEATH( C2.erase(it2, it1_next) ); // both from wrong container
|
||||
C2.erase(it2, it2_next);
|
||||
}
|
||||
|
||||
// Allocator aware tests
|
||||
static void SwapInvalidatesIterators() {
|
||||
CHECKPOINT("testing swap invalidates iterators");
|
||||
Container C1 = makeContainer(3);
|
||||
Container C2 = makeContainer(3);
|
||||
iterator it1 = C1.begin();
|
||||
iterator it2 = C2.begin();
|
||||
swap(C1, C2);
|
||||
EXPECT_DEATH( C1.erase(it1) );
|
||||
if (CT == CT_String) {
|
||||
EXPECT_DEATH(C1.erase(it2));
|
||||
} else
|
||||
C1.erase(it2);
|
||||
//C2.erase(it1);
|
||||
EXPECT_DEATH( C1.erase(it1) );
|
||||
}
|
||||
|
||||
static void SwapNonEqualAllocators() {
|
||||
CHECKPOINT("testing swap with non-equal allocators");
|
||||
Container C1 = makeContainer(3, allocator_type(1));
|
||||
Container C2 = makeContainer(1, allocator_type(2));
|
||||
Container C3 = makeContainer(2, allocator_type(2));
|
||||
swap(C2, C3);
|
||||
EXPECT_DEATH( swap(C1, C2) );
|
||||
}
|
||||
|
||||
private:
|
||||
BasicContainerChecks() = delete;
|
||||
};
|
||||
|
||||
} // namespace IteratorDebugChecks
|
||||
|
||||
#endif // TEST_SUPPORT_CONTAINER_DEBUG_TESTS_H
|
|
@ -12,9 +12,6 @@
|
|||
#ifndef _LIBCPP_DEBUG
|
||||
#error _LIBCPP_DEBUG must be defined before including this header
|
||||
#endif
|
||||
#ifndef _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||
#error _LIBCPP_DEBUG_USE_EXCEPTIONS must be defined before including this header
|
||||
#endif
|
||||
|
||||
#include <ciso646>
|
||||
#ifndef _LIBCPP_VERSION
|
||||
|
@ -26,360 +23,280 @@
|
|||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include "test_macros.h"
|
||||
#include "assert_checkpoint.h"
|
||||
#include "test_allocator.h"
|
||||
|
||||
// These test make use of 'if constexpr'.
|
||||
#if TEST_STD_VER <= 14
|
||||
#error This header may only be used in C++17 and greater
|
||||
#endif
|
||||
#ifdef TEST_HAS_NO_EXCEPTIONS
|
||||
#error These tests require exceptions
|
||||
#if TEST_STD_VER < 11
|
||||
# error "C++11 or greater is required to use this header"
|
||||
#endif
|
||||
|
||||
#ifndef __cpp_if_constexpr
|
||||
#error These tests require if constexpr
|
||||
#endif
|
||||
struct DebugInfoMatcher {
|
||||
static const int any_line = -1;
|
||||
static constexpr const char* any_file = "*";
|
||||
static constexpr const char* any_msg = "*";
|
||||
|
||||
/// Assert that the specified expression throws a libc++ debug exception.
|
||||
#define CHECK_DEBUG_THROWS(...) assert((CheckDebugThrows( [&]() { __VA_ARGS__; } )))
|
||||
constexpr DebugInfoMatcher() : is_empty(true), msg(any_msg), file(any_file), line(any_line) { }
|
||||
constexpr DebugInfoMatcher(const char* msg, const char* file = any_file, int line = any_line)
|
||||
: is_empty(false), msg(msg), file(file), line(line) {}
|
||||
|
||||
template <class Func>
|
||||
inline bool CheckDebugThrows(Func&& func) {
|
||||
try {
|
||||
func();
|
||||
} catch (std::__libcpp_debug_exception const&) {
|
||||
bool Matches(std::__libcpp_debug_info const& got) const {
|
||||
assert(!empty() && "empty matcher");
|
||||
|
||||
if (CheckLineMatches(got.__line_) && CheckFileMatches(got.__file_) &&
|
||||
CheckMessageMatches(got.__msg_))
|
||||
return true;
|
||||
// Write to stdout because that's the file descriptor captured by the parent
|
||||
// process.
|
||||
std::cout << "Failed to match debug info!\n"
|
||||
<< ToString() << "\n"
|
||||
<< "VS\n"
|
||||
<< got.what() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string ToString() const {
|
||||
std::stringstream ss;
|
||||
ss << "msg = \"" << msg << "\"\n"
|
||||
<< "line = " << (line == any_line ? "'*'" : std::to_string(line)) << "\n"
|
||||
<< "file = " << (file == any_file ? "'*'" : any_file) << "";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool empty() const { return is_empty; }
|
||||
private:
|
||||
bool CheckLineMatches(int got_line) const {
|
||||
if (line == any_line)
|
||||
return true;
|
||||
return got_line == line;
|
||||
}
|
||||
|
||||
bool CheckFileMatches(std::string_view got_file) const {
|
||||
assert(!empty() && "empty matcher");
|
||||
if (file == any_file)
|
||||
return true;
|
||||
std::size_t found_at = got_file.find(file);
|
||||
if (found_at == std::string_view::npos)
|
||||
return false;
|
||||
// require the match start at the beginning of the file or immediately after
|
||||
// a directory separator.
|
||||
if (found_at != 0) {
|
||||
char last_char = got_file[found_at - 1];
|
||||
if (last_char != '/' && last_char != '\\')
|
||||
return false;
|
||||
}
|
||||
// require the match goes until the end of the string.
|
||||
return got_file.substr(found_at) == file;
|
||||
}
|
||||
|
||||
bool CheckMessageMatches(std::string_view got_msg) const {
|
||||
assert(!empty() && "empty matcher");
|
||||
if (msg == any_msg)
|
||||
return true;
|
||||
std::size_t found_at = got_msg.find(msg);
|
||||
if (found_at == std::string_view::npos)
|
||||
return false;
|
||||
// Allow any match
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace IteratorDebugChecks {
|
||||
|
||||
enum ContainerType {
|
||||
CT_None,
|
||||
CT_String,
|
||||
CT_Vector,
|
||||
CT_VectorBool,
|
||||
CT_List,
|
||||
CT_Deque,
|
||||
CT_ForwardList,
|
||||
CT_Map,
|
||||
CT_Set,
|
||||
CT_MultiMap,
|
||||
CT_MultiSet,
|
||||
CT_UnorderedMap,
|
||||
CT_UnorderedSet,
|
||||
CT_UnorderedMultiMap,
|
||||
CT_UnorderedMultiSet
|
||||
};
|
||||
|
||||
constexpr bool isSequential(ContainerType CT) {
|
||||
return CT_Vector >= CT && CT_ForwardList <= CT;
|
||||
}
|
||||
|
||||
constexpr bool isAssociative(ContainerType CT) {
|
||||
return CT_Map >= CT && CT_MultiSet <= CT;
|
||||
}
|
||||
|
||||
constexpr bool isUnordered(ContainerType CT) {
|
||||
return CT_UnorderedMap >= CT && CT_UnorderedMultiSet <= CT;
|
||||
}
|
||||
|
||||
constexpr bool isSet(ContainerType CT) {
|
||||
return CT == CT_Set
|
||||
|| CT == CT_MultiSet
|
||||
|| CT == CT_UnorderedSet
|
||||
|| CT == CT_UnorderedMultiSet;
|
||||
}
|
||||
|
||||
constexpr bool isMap(ContainerType CT) {
|
||||
return CT == CT_Map
|
||||
|| CT == CT_MultiMap
|
||||
|| CT == CT_UnorderedMap
|
||||
|| CT == CT_UnorderedMultiMap;
|
||||
}
|
||||
|
||||
constexpr bool isMulti(ContainerType CT) {
|
||||
return CT == CT_MultiMap
|
||||
|| CT == CT_MultiSet
|
||||
|| CT == CT_UnorderedMultiMap
|
||||
|| CT == CT_UnorderedMultiSet;
|
||||
}
|
||||
|
||||
template <class Container, class ValueType = typename Container::value_type>
|
||||
struct ContainerDebugHelper {
|
||||
static_assert(std::is_constructible<ValueType, int>::value,
|
||||
"must be constructible from int");
|
||||
|
||||
static ValueType makeValueType(int val = 0, int = 0) {
|
||||
return ValueType(val);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Container>
|
||||
struct ContainerDebugHelper<Container, char> {
|
||||
static char makeValueType(int = 0, int = 0) {
|
||||
return 'A';
|
||||
}
|
||||
};
|
||||
|
||||
template <class Container, class Key, class Value>
|
||||
struct ContainerDebugHelper<Container, std::pair<const Key, Value> > {
|
||||
using ValueType = std::pair<const Key, Value>;
|
||||
static_assert(std::is_constructible<Key, int>::value,
|
||||
"must be constructible from int");
|
||||
static_assert(std::is_constructible<Value, int>::value,
|
||||
"must be constructible from int");
|
||||
|
||||
static ValueType makeValueType(int key = 0, int val = 0) {
|
||||
return ValueType(key, val);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Container, ContainerType CT,
|
||||
class Helper = ContainerDebugHelper<Container> >
|
||||
struct BasicContainerChecks {
|
||||
using value_type = typename Container::value_type;
|
||||
using iterator = typename Container::iterator;
|
||||
using const_iterator = typename Container::const_iterator;
|
||||
using allocator_type = typename Container::allocator_type;
|
||||
using traits = std::iterator_traits<iterator>;
|
||||
using category = typename traits::iterator_category;
|
||||
|
||||
static_assert(std::is_same<test_allocator<value_type>, allocator_type>::value,
|
||||
"the container must use a test allocator");
|
||||
|
||||
static constexpr bool IsBiDir =
|
||||
std::is_convertible<category, std::bidirectional_iterator_tag>::value;
|
||||
|
||||
public:
|
||||
static void run() {
|
||||
run_iterator_tests();
|
||||
run_container_tests();
|
||||
run_allocator_aware_tests();
|
||||
}
|
||||
|
||||
static void run_iterator_tests() {
|
||||
try {
|
||||
TestNullIterators<iterator>();
|
||||
TestNullIterators<const_iterator>();
|
||||
if constexpr (IsBiDir) { DecrementBegin(); }
|
||||
IncrementEnd();
|
||||
DerefEndIterator();
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
|
||||
static void run_container_tests() {
|
||||
try {
|
||||
CopyInvalidatesIterators();
|
||||
MoveInvalidatesIterators();
|
||||
if constexpr (CT != CT_ForwardList) {
|
||||
EraseIter();
|
||||
EraseIterIter();
|
||||
}
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
|
||||
static void run_allocator_aware_tests() {
|
||||
try {
|
||||
SwapNonEqualAllocators();
|
||||
if constexpr (CT != CT_ForwardList ) {
|
||||
// FIXME: This should work for both forward_list and string
|
||||
SwapInvalidatesIterators();
|
||||
}
|
||||
} catch (...) {
|
||||
assert(false && "uncaught debug exception");
|
||||
}
|
||||
}
|
||||
|
||||
static Container makeContainer(int size, allocator_type A = allocator_type()) {
|
||||
Container C(A);
|
||||
if constexpr (CT == CT_ForwardList) {
|
||||
for (int i = 0; i < size; ++i)
|
||||
C.insert_after(C.before_begin(), Helper::makeValueType(i));
|
||||
} else {
|
||||
for (int i = 0; i < size; ++i)
|
||||
C.insert(C.end(), Helper::makeValueType(i));
|
||||
assert(C.size() == static_cast<std::size_t>(size));
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
static value_type makeValueType(int value) {
|
||||
return Helper::makeValueType(value);
|
||||
}
|
||||
|
||||
private:
|
||||
// Iterator tests
|
||||
template <class Iter>
|
||||
static void TestNullIterators() {
|
||||
CHECKPOINT("testing null iterator");
|
||||
Iter it;
|
||||
CHECK_DEBUG_THROWS( ++it );
|
||||
CHECK_DEBUG_THROWS( it++ );
|
||||
CHECK_DEBUG_THROWS( *it );
|
||||
if constexpr (CT != CT_VectorBool) {
|
||||
CHECK_DEBUG_THROWS( it.operator->() );
|
||||
}
|
||||
if constexpr (IsBiDir) {
|
||||
CHECK_DEBUG_THROWS( --it );
|
||||
CHECK_DEBUG_THROWS( it-- );
|
||||
}
|
||||
}
|
||||
|
||||
static void DecrementBegin() {
|
||||
CHECKPOINT("testing decrement on begin");
|
||||
Container C = makeContainer(1);
|
||||
iterator i = C.end();
|
||||
const_iterator ci = C.cend();
|
||||
--i;
|
||||
--ci;
|
||||
assert(i == C.begin());
|
||||
CHECK_DEBUG_THROWS( --i );
|
||||
CHECK_DEBUG_THROWS( i-- );
|
||||
CHECK_DEBUG_THROWS( --ci );
|
||||
CHECK_DEBUG_THROWS( ci-- );
|
||||
}
|
||||
|
||||
static void IncrementEnd() {
|
||||
CHECKPOINT("testing increment on end");
|
||||
Container C = makeContainer(1);
|
||||
iterator i = C.begin();
|
||||
const_iterator ci = C.begin();
|
||||
++i;
|
||||
++ci;
|
||||
assert(i == C.end());
|
||||
CHECK_DEBUG_THROWS( ++i );
|
||||
CHECK_DEBUG_THROWS( i++ );
|
||||
CHECK_DEBUG_THROWS( ++ci );
|
||||
CHECK_DEBUG_THROWS( ci++ );
|
||||
}
|
||||
|
||||
static void DerefEndIterator() {
|
||||
CHECKPOINT("testing deref end iterator");
|
||||
Container C = makeContainer(1);
|
||||
iterator i = C.begin();
|
||||
const_iterator ci = C.cbegin();
|
||||
(void)*i; (void)*ci;
|
||||
if constexpr (CT != CT_VectorBool) {
|
||||
i.operator->();
|
||||
ci.operator->();
|
||||
}
|
||||
++i; ++ci;
|
||||
assert(i == C.end());
|
||||
CHECK_DEBUG_THROWS( *i );
|
||||
CHECK_DEBUG_THROWS( *ci );
|
||||
if constexpr (CT != CT_VectorBool) {
|
||||
CHECK_DEBUG_THROWS( i.operator->() );
|
||||
CHECK_DEBUG_THROWS( ci.operator->() );
|
||||
}
|
||||
}
|
||||
|
||||
// Container tests
|
||||
static void CopyInvalidatesIterators() {
|
||||
CHECKPOINT("copy invalidates iterators");
|
||||
Container C1 = makeContainer(3);
|
||||
iterator i = C1.begin();
|
||||
Container C2 = C1;
|
||||
if constexpr (CT == CT_ForwardList) {
|
||||
iterator i_next = i;
|
||||
++i_next;
|
||||
(void)*i_next;
|
||||
CHECK_DEBUG_THROWS( C2.erase_after(i) );
|
||||
C1.erase_after(i);
|
||||
CHECK_DEBUG_THROWS( *i_next );
|
||||
} else {
|
||||
CHECK_DEBUG_THROWS( C2.erase(i) );
|
||||
(void)*i;
|
||||
C1.erase(i);
|
||||
CHECK_DEBUG_THROWS( *i );
|
||||
}
|
||||
}
|
||||
|
||||
static void MoveInvalidatesIterators() {
|
||||
CHECKPOINT("copy move invalidates iterators");
|
||||
Container C1 = makeContainer(3);
|
||||
iterator i = C1.begin();
|
||||
Container C2 = std::move(C1);
|
||||
(void) *i;
|
||||
if constexpr (CT == CT_ForwardList) {
|
||||
CHECK_DEBUG_THROWS( C1.erase_after(i) );
|
||||
C2.erase_after(i);
|
||||
} else {
|
||||
CHECK_DEBUG_THROWS( C1.erase(i) );
|
||||
C2.erase(i);
|
||||
CHECK_DEBUG_THROWS(*i);
|
||||
}
|
||||
}
|
||||
|
||||
static void EraseIter() {
|
||||
CHECKPOINT("testing erase invalidation");
|
||||
Container C1 = makeContainer(2);
|
||||
iterator it1 = C1.begin();
|
||||
iterator it1_next = it1;
|
||||
++it1_next;
|
||||
Container C2 = C1;
|
||||
CHECK_DEBUG_THROWS( C2.erase(it1) ); // wrong container
|
||||
CHECK_DEBUG_THROWS( C2.erase(C2.end()) ); // erase with end
|
||||
C1.erase(it1_next);
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1_next) ); // invalidated iterator
|
||||
C1.erase(it1);
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1) ); // invalidated iterator
|
||||
}
|
||||
|
||||
static void EraseIterIter() {
|
||||
CHECKPOINT("testing erase iter iter invalidation");
|
||||
Container C1 = makeContainer(2);
|
||||
iterator it1 = C1.begin();
|
||||
iterator it1_next = it1;
|
||||
++it1_next;
|
||||
Container C2 = C1;
|
||||
iterator it2 = C2.begin();
|
||||
iterator it2_next = it2;
|
||||
++it2_next;
|
||||
CHECK_DEBUG_THROWS( C2.erase(it1, it1_next) ); // begin from wrong container
|
||||
CHECK_DEBUG_THROWS( C2.erase(it1, it2_next) ); // end from wrong container
|
||||
CHECK_DEBUG_THROWS( C2.erase(it2, it1_next) ); // both from wrong container
|
||||
C2.erase(it2, it2_next);
|
||||
}
|
||||
|
||||
// Allocator aware tests
|
||||
static void SwapInvalidatesIterators() {
|
||||
CHECKPOINT("testing swap invalidates iterators");
|
||||
Container C1 = makeContainer(3);
|
||||
Container C2 = makeContainer(3);
|
||||
iterator it1 = C1.begin();
|
||||
iterator it2 = C2.begin();
|
||||
swap(C1, C2);
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1) );
|
||||
if (CT == CT_String) {
|
||||
CHECK_DEBUG_THROWS(C1.erase(it2));
|
||||
} else
|
||||
C1.erase(it2);
|
||||
//C2.erase(it1);
|
||||
CHECK_DEBUG_THROWS( C1.erase(it1) );
|
||||
}
|
||||
|
||||
static void SwapNonEqualAllocators() {
|
||||
CHECKPOINT("testing swap with non-equal allocators");
|
||||
Container C1 = makeContainer(3, allocator_type(1));
|
||||
Container C2 = makeContainer(1, allocator_type(2));
|
||||
Container C3 = makeContainer(2, allocator_type(2));
|
||||
swap(C2, C3);
|
||||
CHECK_DEBUG_THROWS( swap(C1, C2) );
|
||||
}
|
||||
|
||||
private:
|
||||
BasicContainerChecks() = delete;
|
||||
bool is_empty;
|
||||
std::string_view msg;
|
||||
std::string_view file;
|
||||
int line;
|
||||
};
|
||||
|
||||
} // namespace IteratorDebugChecks
|
||||
static constexpr DebugInfoMatcher AnyMatcher(DebugInfoMatcher::any_msg);
|
||||
|
||||
inline DebugInfoMatcher& GlobalMatcher() {
|
||||
static DebugInfoMatcher GMatch;
|
||||
return GMatch;
|
||||
}
|
||||
|
||||
struct DeathTest {
|
||||
enum ResultKind {
|
||||
RK_DidNotDie, RK_MatchFound, RK_MatchFailure, RK_SetupFailure, RK_Unknown
|
||||
};
|
||||
|
||||
static const char* ResultKindToString(ResultKind RK) {
|
||||
#define CASE(K) case K: return #K
|
||||
switch (RK) {
|
||||
CASE(RK_MatchFailure);
|
||||
CASE(RK_DidNotDie);
|
||||
CASE(RK_SetupFailure);
|
||||
CASE(RK_MatchFound);
|
||||
CASE(RK_Unknown);
|
||||
}
|
||||
return "not a result kind";
|
||||
}
|
||||
|
||||
static bool IsValidResultKind(int val) {
|
||||
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) {}
|
||||
|
||||
template <class Func>
|
||||
ResultKind Run(Func&& f) {
|
||||
int pipe_res = pipe(stdout_pipe_fd_);
|
||||
assert(pipe_res != -1 && "failed to create pipe");
|
||||
pipe_res = pipe(stderr_pipe_fd_);
|
||||
assert(pipe_res != -1 && "failed to create pipe");
|
||||
pid_t child_pid = fork();
|
||||
assert(child_pid != -1 &&
|
||||
"failed to fork a process to perform a death test");
|
||||
child_pid_ = child_pid;
|
||||
if (child_pid_ == 0) {
|
||||
RunForChild(std::forward<Func>(f));
|
||||
assert(false && "unreachable");
|
||||
}
|
||||
return RunForParent();
|
||||
}
|
||||
|
||||
int getChildExitCode() const { return exit_code_; }
|
||||
std::string const& getChildStdOut() const { return stdout_from_child_; }
|
||||
std::string const& getChildStdErr() const { return stderr_from_child_; }
|
||||
private:
|
||||
template <class Func>
|
||||
TEST_NORETURN void RunForChild(Func&& f) {
|
||||
close(GetStdOutReadFD()); // don't need to read from the pipe in the child.
|
||||
close(GetStdErrReadFD());
|
||||
auto DupFD = [](int DestFD, int TargetFD) {
|
||||
int dup_result = dup2(DestFD, TargetFD);
|
||||
if (dup_result == -1)
|
||||
std::exit(RK_SetupFailure);
|
||||
};
|
||||
DupFD(GetStdOutWriteFD(), STDOUT_FILENO);
|
||||
DupFD(GetStdErrWriteFD(), STDERR_FILENO);
|
||||
|
||||
GlobalMatcher() = matcher_;
|
||||
std::__libcpp_set_debug_function(&DeathTestDebugHandler);
|
||||
f();
|
||||
std::exit(RK_DidNotDie);
|
||||
}
|
||||
|
||||
static std::string ReadChildIOUntilEnd(int FD) {
|
||||
std::string error_msg;
|
||||
char buffer[256];
|
||||
int num_read;
|
||||
do {
|
||||
while ((num_read = read(FD, buffer, 255)) > 0) {
|
||||
buffer[num_read] = '\0';
|
||||
error_msg += buffer;
|
||||
}
|
||||
} while (num_read == -1 && errno == EINTR);
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
void CaptureIOFromChild() {
|
||||
close(GetStdOutWriteFD()); // no need to write from the parent process
|
||||
close(GetStdErrWriteFD());
|
||||
stdout_from_child_ = ReadChildIOUntilEnd(GetStdOutReadFD());
|
||||
stderr_from_child_ = ReadChildIOUntilEnd(GetStdErrReadFD());
|
||||
close(GetStdOutReadFD());
|
||||
close(GetStdErrReadFD());
|
||||
}
|
||||
|
||||
ResultKind RunForParent() {
|
||||
CaptureIOFromChild();
|
||||
|
||||
int status_value;
|
||||
pid_t result = waitpid(child_pid_, &status_value, 0);
|
||||
assert(result != -1 && "there is no child process to wait for");
|
||||
|
||||
if (WIFEXITED(status_value)) {
|
||||
exit_code_ = WEXITSTATUS(status_value);
|
||||
if (!IsValidResultKind(exit_code_))
|
||||
return RK_Unknown;
|
||||
return static_cast<ResultKind>(exit_code_);
|
||||
}
|
||||
return RK_Unknown;
|
||||
}
|
||||
|
||||
DeathTest(DeathTest const&) = delete;
|
||||
DeathTest& operator=(DeathTest const&) = delete;
|
||||
|
||||
int GetStdOutReadFD() const {
|
||||
return stdout_pipe_fd_[0];
|
||||
}
|
||||
|
||||
int GetStdOutWriteFD() const {
|
||||
return stdout_pipe_fd_[1];
|
||||
}
|
||||
|
||||
int GetStdErrReadFD() const {
|
||||
return stderr_pipe_fd_[0];
|
||||
}
|
||||
|
||||
int GetStdErrWriteFD() const {
|
||||
return stderr_pipe_fd_[1];
|
||||
}
|
||||
private:
|
||||
DebugInfoMatcher matcher_;
|
||||
pid_t child_pid_ = -1;
|
||||
int exit_code_ = -1;
|
||||
int stdout_pipe_fd_[2];
|
||||
int stderr_pipe_fd_[2];
|
||||
std::string stdout_from_child_;
|
||||
std::string stderr_from_child_;
|
||||
};
|
||||
|
||||
template <class Func>
|
||||
inline bool ExpectDeath(const char* stmt, Func&& func, DebugInfoMatcher Matcher) {
|
||||
DeathTest DT(Matcher);
|
||||
DeathTest::ResultKind RK = DT.Run(func);
|
||||
auto OnFailure = [&](const char* msg) {
|
||||
std::cerr << "EXPECT_DEATH( " << stmt << " ) failed! (" << msg << ")\n\n";
|
||||
if (RK != DeathTest::RK_Unknown) {
|
||||
std::cerr << "child exit code: " << DT.getChildExitCode() << "\n";
|
||||
}
|
||||
if (!DT.getChildStdErr().empty()) {
|
||||
std::cerr << "---------- standard err ----------\n";
|
||||
std::cerr << DT.getChildStdErr() << "\n";
|
||||
}
|
||||
if (!DT.getChildStdOut().empty()) {
|
||||
std::cerr << "---------- standard out ----------\n";
|
||||
std::cerr << DT.getChildStdOut() << "\n";
|
||||
}
|
||||
return false;
|
||||
};
|
||||
switch (RK) {
|
||||
case DeathTest::RK_MatchFound:
|
||||
return true;
|
||||
case DeathTest::RK_SetupFailure:
|
||||
return OnFailure("child failed to setup test environment");
|
||||
case DeathTest::RK_Unknown:
|
||||
return OnFailure("reason unknown");
|
||||
case DeathTest::RK_DidNotDie:
|
||||
return OnFailure("child did not die");
|
||||
case DeathTest::RK_MatchFailure:
|
||||
return OnFailure("matcher failed");
|
||||
}
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
inline bool ExpectDeath(const char* stmt, Func&& func) {
|
||||
return ExpectDeath(stmt, func, AnyMatcher);
|
||||
}
|
||||
|
||||
/// Assert that the specified expression throws a libc++ debug exception.
|
||||
#define EXPECT_DEATH(...) assert((ExpectDeath(#__VA_ARGS__, [&]() { __VA_ARGS__; } )))
|
||||
|
||||
#define EXPECT_DEATH_MATCHES(Matcher, ...) assert((ExpectDeath(#__VA_ARGS__, [&]() { __VA_ARGS__; }, Matcher)))
|
||||
|
||||
#endif // TEST_SUPPORT_DEBUG_MODE_HELPER_H
|
||||
|
|
Loading…
Reference in New Issue