| author | |
| committer | |
| log | 92b69215e63a3303a5e904ab332e2eec236e0ed2 |
| tree | 82dc7298eba67fb6881e0a9014d251073c6a76ae |
| parent | 1b8f0d8b56a578dbd699021dd14ea80d743b7cf8 |
585 files changed, 39534 insertions(+), 26229 deletions(-)
lib/libcxx/include/__algorithm/adjacent_find.h created+51| ... | ... | @@ -0,0 +1,51 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_ADJACENT_FIND_H | |
| 11 | #define _LIBCPP___ALGORITHM_ADJACENT_FIND_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator, class _BinaryPredicate> | |
| 27 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 28 | adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { | |
| 29 | if (__first != __last) { | |
| 30 | _ForwardIterator __i = __first; | |
| 31 | while (++__i != __last) { | |
| 32 | if (__pred(*__first, *__i)) | |
| 33 | return __first; | |
| 34 | __first = __i; | |
| 35 | } | |
| 36 | } | |
| 37 | return __last; | |
| 38 | } | |
| 39 | ||
| 40 | template <class _ForwardIterator> | |
| 41 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 42 | adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { | |
| 43 | typedef typename iterator_traits<_ForwardIterator>::value_type __v; | |
| 44 | return _VSTD::adjacent_find(__first, __last, __equal_to<__v>()); | |
| 45 | } | |
| 46 | ||
| 47 | _LIBCPP_END_NAMESPACE_STD | |
| 48 | ||
| 49 | _LIBCPP_POP_MACROS | |
| 50 | ||
| 51 | #endif // _LIBCPP___ALGORITHM_ADJACENT_FIND_H |
lib/libcxx/include/__algorithm/all_of.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_ALL_OF_H | |
| 11 | #define _LIBCPP___ALGORITHM_ALL_OF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _InputIterator, class _Predicate> | |
| 25 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 26 | all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | |
| 27 | for (; __first != __last; ++__first) | |
| 28 | if (!__pred(*__first)) | |
| 29 | return false; | |
| 30 | return true; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_ALL_OF_H |
lib/libcxx/include/__algorithm/any_of.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_ANY_OF_H | |
| 11 | #define _LIBCPP___ALGORITHM_ANY_OF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _InputIterator, class _Predicate> | |
| 25 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 26 | any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | |
| 27 | for (; __first != __last; ++__first) | |
| 28 | if (__pred(*__first)) | |
| 29 | return true; | |
| 30 | return false; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_ANY_OF_H |
lib/libcxx/include/__algorithm/binary_search.h created+61| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_BINARY_SEARCH_H | |
| 10 | #define _LIBCPP___ALGORITHM_BINARY_SEARCH_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/lower_bound.h> | |
| 15 | #include <__algorithm/comp_ref_type.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 28 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 29 | bool | |
| 30 | __binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 31 | { | |
| 32 | __first = _VSTD::__lower_bound<_Compare>(__first, __last, __value_, __comp); | |
| 33 | return __first != __last && !__comp(__value_, *__first); | |
| 34 | } | |
| 35 | ||
| 36 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 37 | _LIBCPP_NODISCARD_EXT inline | |
| 38 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 39 | bool | |
| 40 | binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 41 | { | |
| 42 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 43 | return _VSTD::__binary_search<_Comp_ref>(__first, __last, __value_, __comp); | |
| 44 | } | |
| 45 | ||
| 46 | template <class _ForwardIterator, class _Tp> | |
| 47 | _LIBCPP_NODISCARD_EXT inline | |
| 48 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 49 | bool | |
| 50 | binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 51 | { | |
| 52 | return _VSTD::binary_search(__first, __last, __value_, | |
| 53 | __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); | |
| 54 | } | |
| 55 | ||
| 56 | ||
| 57 | _LIBCPP_END_NAMESPACE_STD | |
| 58 | ||
| 59 | _LIBCPP_POP_MACROS | |
| 60 | ||
| 61 | #endif // _LIBCPP___ALGORITHM_BINARY_SEARCH_H |
lib/libcxx/include/__algorithm/clamp.h created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_CLAMP_H | |
| 10 | #define _LIBCPP___ALGORITHM_CLAMP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__debug> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if _LIBCPP_STD_VER > 14 | |
| 26 | // clamp | |
| 27 | template<class _Tp, class _Compare> | |
| 28 | _LIBCPP_NODISCARD_EXT inline | |
| 29 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 30 | const _Tp& | |
| 31 | clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) | |
| 32 | { | |
| 33 | _LIBCPP_ASSERT(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); | |
| 34 | return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; | |
| 35 | ||
| 36 | } | |
| 37 | ||
| 38 | template<class _Tp> | |
| 39 | _LIBCPP_NODISCARD_EXT inline | |
| 40 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 41 | const _Tp& | |
| 42 | clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) | |
| 43 | { | |
| 44 | return _VSTD::clamp(__v, __lo, __hi, __less<_Tp>()); | |
| 45 | } | |
| 46 | #endif | |
| 47 | ||
| 48 | _LIBCPP_END_NAMESPACE_STD | |
| 49 | ||
| 50 | _LIBCPP_POP_MACROS | |
| 51 | ||
| 52 | #endif // _LIBCPP___ALGORITHM_CLAMP_H |
lib/libcxx/include/__algorithm/comp.h created+97| ... | ... | @@ -0,0 +1,97 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_COMP_H | |
| 10 | #define _LIBCPP___ALGORITHM_COMP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | // I'd like to replace these with _VSTD::equal_to<void>, but can't because: | |
| 24 | // * That only works with C++14 and later, and | |
| 25 | // * We haven't included <functional> here. | |
| 26 | template <class _T1, class _T2 = _T1> | |
| 27 | struct __equal_to | |
| 28 | { | |
| 29 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 30 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T2& __y) const {return __x == __y;} | |
| 31 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T1& __y) const {return __x == __y;} | |
| 32 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T2& __y) const {return __x == __y;} | |
| 33 | }; | |
| 34 | ||
| 35 | template <class _T1> | |
| 36 | struct __equal_to<_T1, _T1> | |
| 37 | { | |
| 38 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 39 | bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 40 | }; | |
| 41 | ||
| 42 | template <class _T1> | |
| 43 | struct __equal_to<const _T1, _T1> | |
| 44 | { | |
| 45 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 46 | bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 47 | }; | |
| 48 | ||
| 49 | template <class _T1> | |
| 50 | struct __equal_to<_T1, const _T1> | |
| 51 | { | |
| 52 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 53 | bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 54 | }; | |
| 55 | ||
| 56 | template <class _T1, class _T2 = _T1> | |
| 57 | struct __less | |
| 58 | { | |
| 59 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 60 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 61 | ||
| 62 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 63 | bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;} | |
| 64 | ||
| 65 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 66 | bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;} | |
| 67 | ||
| 68 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 69 | bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;} | |
| 70 | }; | |
| 71 | ||
| 72 | template <class _T1> | |
| 73 | struct __less<_T1, _T1> | |
| 74 | { | |
| 75 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 76 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 77 | }; | |
| 78 | ||
| 79 | template <class _T1> | |
| 80 | struct __less<const _T1, _T1> | |
| 81 | { | |
| 82 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 83 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 84 | }; | |
| 85 | ||
| 86 | template <class _T1> | |
| 87 | struct __less<_T1, const _T1> | |
| 88 | { | |
| 89 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 90 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 91 | }; | |
| 92 | ||
| 93 | _LIBCPP_END_NAMESPACE_STD | |
| 94 | ||
| 95 | _LIBCPP_POP_MACROS | |
| 96 | ||
| 97 | #endif // _LIBCPP___ALGORITHM_COMP_H |
lib/libcxx/include/__algorithm/comp_ref_type.h created+87| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_COMP_REF_TYPE_H | |
| 10 | #define _LIBCPP___ALGORITHM_COMP_REF_TYPE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <type_traits> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #ifdef _LIBCPP_DEBUG | |
| 25 | ||
| 26 | template <class _Compare> | |
| 27 | struct __debug_less | |
| 28 | { | |
| 29 | _Compare &__comp_; | |
| 30 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 31 | __debug_less(_Compare& __c) : __comp_(__c) {} | |
| 32 | ||
| 33 | template <class _Tp, class _Up> | |
| 34 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 35 | bool operator()(const _Tp& __x, const _Up& __y) | |
| 36 | { | |
| 37 | bool __r = __comp_(__x, __y); | |
| 38 | if (__r) | |
| 39 | __do_compare_assert(0, __y, __x); | |
| 40 | return __r; | |
| 41 | } | |
| 42 | ||
| 43 | template <class _Tp, class _Up> | |
| 44 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 45 | bool operator()(_Tp& __x, _Up& __y) | |
| 46 | { | |
| 47 | bool __r = __comp_(__x, __y); | |
| 48 | if (__r) | |
| 49 | __do_compare_assert(0, __y, __x); | |
| 50 | return __r; | |
| 51 | } | |
| 52 | ||
| 53 | template <class _LHS, class _RHS> | |
| 54 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 55 | inline _LIBCPP_INLINE_VISIBILITY | |
| 56 | decltype((void)declval<_Compare&>()( | |
| 57 | declval<_LHS &>(), declval<_RHS &>())) | |
| 58 | __do_compare_assert(int, _LHS & __l, _RHS & __r) { | |
| 59 | _LIBCPP_ASSERT(!__comp_(__l, __r), | |
| 60 | "Comparator does not induce a strict weak ordering"); | |
| 61 | } | |
| 62 | ||
| 63 | template <class _LHS, class _RHS> | |
| 64 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 65 | inline _LIBCPP_INLINE_VISIBILITY | |
| 66 | void __do_compare_assert(long, _LHS &, _RHS &) {} | |
| 67 | }; | |
| 68 | ||
| 69 | #endif // _LIBCPP_DEBUG | |
| 70 | ||
| 71 | template <class _Comp> | |
| 72 | struct __comp_ref_type { | |
| 73 | // Pass the comparator by lvalue reference. Or in debug mode, using a | |
| 74 | // debugging wrapper that stores a reference. | |
| 75 | #ifndef _LIBCPP_DEBUG | |
| 76 | typedef typename add_lvalue_reference<_Comp>::type type; | |
| 77 | #else | |
| 78 | typedef __debug_less<_Comp> type; | |
| 79 | #endif | |
| 80 | }; | |
| 81 | ||
| 82 | ||
| 83 | _LIBCPP_END_NAMESPACE_STD | |
| 84 | ||
| 85 | _LIBCPP_POP_MACROS | |
| 86 | ||
| 87 | #endif // _LIBCPP___ALGORITHM_COMP_REF_TYPE_H |
lib/libcxx/include/__algorithm/copy.h created+82| ... | ... | @@ -0,0 +1,82 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/unwrap_iter.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <cstring> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | // copy | |
| 28 | ||
| 29 | template <class _InputIterator, class _OutputIterator> | |
| 30 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 31 | _OutputIterator | |
| 32 | __copy_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 33 | { | |
| 34 | for (; __first != __last; ++__first, (void) ++__result) | |
| 35 | *__result = *__first; | |
| 36 | return __result; | |
| 37 | } | |
| 38 | ||
| 39 | template <class _InputIterator, class _OutputIterator> | |
| 40 | inline _LIBCPP_INLINE_VISIBILITY | |
| 41 | _OutputIterator | |
| 42 | __copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 43 | { | |
| 44 | return _VSTD::__copy_constexpr(__first, __last, __result); | |
| 45 | } | |
| 46 | ||
| 47 | template <class _Tp, class _Up> | |
| 48 | inline _LIBCPP_INLINE_VISIBILITY | |
| 49 | typename enable_if | |
| 50 | < | |
| 51 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 52 | is_trivially_copy_assignable<_Up>::value, | |
| 53 | _Up* | |
| 54 | >::type | |
| 55 | __copy(_Tp* __first, _Tp* __last, _Up* __result) | |
| 56 | { | |
| 57 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 58 | if (__n > 0) | |
| 59 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 60 | return __result + __n; | |
| 61 | } | |
| 62 | ||
| 63 | template <class _InputIterator, class _OutputIterator> | |
| 64 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 65 | _OutputIterator | |
| 66 | copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 67 | { | |
| 68 | if (__libcpp_is_constant_evaluated()) { | |
| 69 | return _VSTD::__copy_constexpr(__first, __last, __result); | |
| 70 | } else { | |
| 71 | return _VSTD::__rewrap_iter(__result, | |
| 72 | _VSTD::__copy(_VSTD::__unwrap_iter(__first), | |
| 73 | _VSTD::__unwrap_iter(__last), | |
| 74 | _VSTD::__unwrap_iter(__result))); | |
| 75 | } | |
| 76 | } | |
| 77 | ||
| 78 | _LIBCPP_END_NAMESPACE_STD | |
| 79 | ||
| 80 | _LIBCPP_POP_MACROS | |
| 81 | ||
| 82 | #endif // _LIBCPP___ALGORITHM_COPY_H |
lib/libcxx/include/__algorithm/copy_backward.h created+84| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_COPY_BACKWARD_H | |
| 10 | #define _LIBCPP___ALGORITHM_COPY_BACKWARD_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/unwrap_iter.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <cstring> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _BidirectionalIterator, class _OutputIterator> | |
| 28 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 29 | _OutputIterator | |
| 30 | __copy_backward_constexpr(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) | |
| 31 | { | |
| 32 | while (__first != __last) | |
| 33 | *--__result = *--__last; | |
| 34 | return __result; | |
| 35 | } | |
| 36 | ||
| 37 | template <class _BidirectionalIterator, class _OutputIterator> | |
| 38 | inline _LIBCPP_INLINE_VISIBILITY | |
| 39 | _OutputIterator | |
| 40 | __copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) | |
| 41 | { | |
| 42 | return _VSTD::__copy_backward_constexpr(__first, __last, __result); | |
| 43 | } | |
| 44 | ||
| 45 | template <class _Tp, class _Up> | |
| 46 | inline _LIBCPP_INLINE_VISIBILITY | |
| 47 | typename enable_if | |
| 48 | < | |
| 49 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 50 | is_trivially_copy_assignable<_Up>::value, | |
| 51 | _Up* | |
| 52 | >::type | |
| 53 | __copy_backward(_Tp* __first, _Tp* __last, _Up* __result) | |
| 54 | { | |
| 55 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 56 | if (__n > 0) | |
| 57 | { | |
| 58 | __result -= __n; | |
| 59 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 60 | } | |
| 61 | return __result; | |
| 62 | } | |
| 63 | ||
| 64 | template <class _BidirectionalIterator1, class _BidirectionalIterator2> | |
| 65 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 66 | _BidirectionalIterator2 | |
| 67 | copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, | |
| 68 | _BidirectionalIterator2 __result) | |
| 69 | { | |
| 70 | if (__libcpp_is_constant_evaluated()) { | |
| 71 | return _VSTD::__copy_backward_constexpr(__first, __last, __result); | |
| 72 | } else { | |
| 73 | return _VSTD::__rewrap_iter(__result, | |
| 74 | _VSTD::__copy_backward(_VSTD::__unwrap_iter(__first), | |
| 75 | _VSTD::__unwrap_iter(__last), | |
| 76 | _VSTD::__unwrap_iter(__result))); | |
| 77 | } | |
| 78 | } | |
| 79 | ||
| 80 | _LIBCPP_END_NAMESPACE_STD | |
| 81 | ||
| 82 | _LIBCPP_POP_MACROS | |
| 83 | ||
| 84 | #endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H |
lib/libcxx/include/__algorithm/copy_if.h created+48| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_COPY_IF_H | |
| 10 | #define _LIBCPP___ALGORITHM_COPY_IF_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/unwrap_iter.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <cstring> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template<class _InputIterator, class _OutputIterator, class _Predicate> | |
| 28 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 29 | _OutputIterator | |
| 30 | copy_if(_InputIterator __first, _InputIterator __last, | |
| 31 | _OutputIterator __result, _Predicate __pred) | |
| 32 | { | |
| 33 | for (; __first != __last; ++__first) | |
| 34 | { | |
| 35 | if (__pred(*__first)) | |
| 36 | { | |
| 37 | *__result = *__first; | |
| 38 | ++__result; | |
| 39 | } | |
| 40 | } | |
| 41 | return __result; | |
| 42 | } | |
| 43 | ||
| 44 | _LIBCPP_END_NAMESPACE_STD | |
| 45 | ||
| 46 | _LIBCPP_POP_MACROS | |
| 47 | ||
| 48 | #endif // _LIBCPP___ALGORITHM_COPY_IF_H |
lib/libcxx/include/__algorithm/copy_n.h created+72| ... | ... | @@ -0,0 +1,72 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_COPY_N_H | |
| 10 | #define _LIBCPP___ALGORITHM_COPY_N_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/copy.h> | |
| 14 | #include <__algorithm/unwrap_iter.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <cstring> | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template<class _InputIterator, class _Size, class _OutputIterator> | |
| 29 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 30 | typename enable_if | |
| 31 | < | |
| 32 | __is_cpp17_input_iterator<_InputIterator>::value && | |
| 33 | !__is_cpp17_random_access_iterator<_InputIterator>::value, | |
| 34 | _OutputIterator | |
| 35 | >::type | |
| 36 | copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) | |
| 37 | { | |
| 38 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 39 | _IntegralSize __n = __orig_n; | |
| 40 | if (__n > 0) | |
| 41 | { | |
| 42 | *__result = *__first; | |
| 43 | ++__result; | |
| 44 | for (--__n; __n > 0; --__n) | |
| 45 | { | |
| 46 | ++__first; | |
| 47 | *__result = *__first; | |
| 48 | ++__result; | |
| 49 | } | |
| 50 | } | |
| 51 | return __result; | |
| 52 | } | |
| 53 | ||
| 54 | template<class _InputIterator, class _Size, class _OutputIterator> | |
| 55 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 56 | typename enable_if | |
| 57 | < | |
| 58 | __is_cpp17_random_access_iterator<_InputIterator>::value, | |
| 59 | _OutputIterator | |
| 60 | >::type | |
| 61 | copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) | |
| 62 | { | |
| 63 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 64 | _IntegralSize __n = __orig_n; | |
| 65 | return _VSTD::copy(__first, __first + __n, __result); | |
| 66 | } | |
| 67 | ||
| 68 | _LIBCPP_END_NAMESPACE_STD | |
| 69 | ||
| 70 | _LIBCPP_POP_MACROS | |
| 71 | ||
| 72 | #endif // _LIBCPP___ALGORITHM_COPY_N_H |
lib/libcxx/include/__algorithm/count.h created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_COUNT_H | |
| 11 | #define _LIBCPP___ALGORITHM_COUNT_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _InputIterator, class _Tp> | |
| 26 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 27 | typename iterator_traits<_InputIterator>::difference_type | |
| 28 | count(_InputIterator __first, _InputIterator __last, const _Tp& __value_) { | |
| 29 | typename iterator_traits<_InputIterator>::difference_type __r(0); | |
| 30 | for (; __first != __last; ++__first) | |
| 31 | if (*__first == __value_) | |
| 32 | ++__r; | |
| 33 | return __r; | |
| 34 | } | |
| 35 | ||
| 36 | _LIBCPP_END_NAMESPACE_STD | |
| 37 | ||
| 38 | _LIBCPP_POP_MACROS | |
| 39 | ||
| 40 | #endif // _LIBCPP___ALGORITHM_COUNT_H |
lib/libcxx/include/__algorithm/count_if.h created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_COUNT_IF_H | |
| 11 | #define _LIBCPP___ALGORITHM_COUNT_IF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _InputIterator, class _Predicate> | |
| 26 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 27 | typename iterator_traits<_InputIterator>::difference_type | |
| 28 | count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | |
| 29 | typename iterator_traits<_InputIterator>::difference_type __r(0); | |
| 30 | for (; __first != __last; ++__first) | |
| 31 | if (__pred(*__first)) | |
| 32 | ++__r; | |
| 33 | return __r; | |
| 34 | } | |
| 35 | ||
| 36 | _LIBCPP_END_NAMESPACE_STD | |
| 37 | ||
| 38 | _LIBCPP_POP_MACROS | |
| 39 | ||
| 40 | #endif // _LIBCPP___ALGORITHM_COUNT_IF_H |
lib/libcxx/include/__algorithm/equal.h created+90| ... | ... | @@ -0,0 +1,90 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_EQUAL_H | |
| 11 | #define _LIBCPP___ALGORITHM_EQUAL_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <iterator> // FIXME: replace with <__iterator/distance.h> when it lands | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 28 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 29 | equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { | |
| 30 | for (; __first1 != __last1; ++__first1, (void)++__first2) | |
| 31 | if (!__pred(*__first1, *__first2)) | |
| 32 | return false; | |
| 33 | return true; | |
| 34 | } | |
| 35 | ||
| 36 | template <class _InputIterator1, class _InputIterator2> | |
| 37 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 38 | equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { | |
| 39 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 40 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 41 | return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>()); | |
| 42 | } | |
| 43 | ||
| 44 | #if _LIBCPP_STD_VER > 11 | |
| 45 | template <class _BinaryPredicate, class _InputIterator1, class _InputIterator2> | |
| 46 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 47 | __equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, | |
| 48 | _BinaryPredicate __pred, input_iterator_tag, input_iterator_tag) { | |
| 49 | for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) | |
| 50 | if (!__pred(*__first1, *__first2)) | |
| 51 | return false; | |
| 52 | return __first1 == __last1 && __first2 == __last2; | |
| 53 | } | |
| 54 | ||
| 55 | template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 56 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 57 | __equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, | |
| 58 | _RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag, | |
| 59 | random_access_iterator_tag) { | |
| 60 | if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) | |
| 61 | return false; | |
| 62 | return _VSTD::equal<_RandomAccessIterator1, _RandomAccessIterator2, | |
| 63 | typename add_lvalue_reference<_BinaryPredicate>::type>(__first1, __last1, __first2, __pred); | |
| 64 | } | |
| 65 | ||
| 66 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 67 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 68 | equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, | |
| 69 | _BinaryPredicate __pred) { | |
| 70 | return _VSTD::__equal<typename add_lvalue_reference<_BinaryPredicate>::type>( | |
| 71 | __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_InputIterator1>::iterator_category(), | |
| 72 | typename iterator_traits<_InputIterator2>::iterator_category()); | |
| 73 | } | |
| 74 | ||
| 75 | template <class _InputIterator1, class _InputIterator2> | |
| 76 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 77 | equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { | |
| 78 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 79 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 80 | return _VSTD::__equal(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(), | |
| 81 | typename iterator_traits<_InputIterator1>::iterator_category(), | |
| 82 | typename iterator_traits<_InputIterator2>::iterator_category()); | |
| 83 | } | |
| 84 | #endif | |
| 85 | ||
| 86 | _LIBCPP_END_NAMESPACE_STD | |
| 87 | ||
| 88 | _LIBCPP_POP_MACROS | |
| 89 | ||
| 90 | #endif // _LIBCPP___ALGORITHM_EQUAL_H |
lib/libcxx/include/__algorithm/equal_range.h created+87| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_EQUAL_RANGE_H | |
| 10 | #define _LIBCPP___ALGORITHM_EQUAL_RANGE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/half_positive.h> | |
| 16 | #include <__algorithm/lower_bound.h> | |
| 17 | #include <__algorithm/upper_bound.h> | |
| 18 | #include <iterator> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 30 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator> | |
| 31 | __equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 32 | { | |
| 33 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 34 | difference_type __len = _VSTD::distance(__first, __last); | |
| 35 | while (__len != 0) | |
| 36 | { | |
| 37 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 38 | _ForwardIterator __m = __first; | |
| 39 | _VSTD::advance(__m, __l2); | |
| 40 | if (__comp(*__m, __value_)) | |
| 41 | { | |
| 42 | __first = ++__m; | |
| 43 | __len -= __l2 + 1; | |
| 44 | } | |
| 45 | else if (__comp(__value_, *__m)) | |
| 46 | { | |
| 47 | __last = __m; | |
| 48 | __len = __l2; | |
| 49 | } | |
| 50 | else | |
| 51 | { | |
| 52 | _ForwardIterator __mp1 = __m; | |
| 53 | return pair<_ForwardIterator, _ForwardIterator> | |
| 54 | ( | |
| 55 | _VSTD::__lower_bound<_Compare>(__first, __m, __value_, __comp), | |
| 56 | _VSTD::__upper_bound<_Compare>(++__mp1, __last, __value_, __comp) | |
| 57 | ); | |
| 58 | } | |
| 59 | } | |
| 60 | return pair<_ForwardIterator, _ForwardIterator>(__first, __first); | |
| 61 | } | |
| 62 | ||
| 63 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 64 | _LIBCPP_NODISCARD_EXT inline | |
| 65 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 66 | pair<_ForwardIterator, _ForwardIterator> | |
| 67 | equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 68 | { | |
| 69 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 70 | return _VSTD::__equal_range<_Comp_ref>(__first, __last, __value_, __comp); | |
| 71 | } | |
| 72 | ||
| 73 | template <class _ForwardIterator, class _Tp> | |
| 74 | _LIBCPP_NODISCARD_EXT inline | |
| 75 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 76 | pair<_ForwardIterator, _ForwardIterator> | |
| 77 | equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 78 | { | |
| 79 | return _VSTD::equal_range(__first, __last, __value_, | |
| 80 | __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); | |
| 81 | } | |
| 82 | ||
| 83 | _LIBCPP_END_NAMESPACE_STD | |
| 84 | ||
| 85 | _LIBCPP_POP_MACROS | |
| 86 | ||
| 87 | #endif // _LIBCPP___ALGORITHM_EQUAL_RANGE_H |
lib/libcxx/include/__algorithm/fill.h created+55| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_FILL_H | |
| 10 | #define _LIBCPP___ALGORITHM_FILL_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/fill_n.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator, class _Tp> | |
| 27 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 28 | void | |
| 29 | __fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, forward_iterator_tag) | |
| 30 | { | |
| 31 | for (; __first != __last; ++__first) | |
| 32 | *__first = __value_; | |
| 33 | } | |
| 34 | ||
| 35 | template <class _RandomAccessIterator, class _Tp> | |
| 36 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 37 | void | |
| 38 | __fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value_, random_access_iterator_tag) | |
| 39 | { | |
| 40 | _VSTD::fill_n(__first, __last - __first, __value_); | |
| 41 | } | |
| 42 | ||
| 43 | template <class _ForwardIterator, class _Tp> | |
| 44 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 45 | void | |
| 46 | fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 47 | { | |
| 48 | _VSTD::__fill(__first, __last, __value_, typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 49 | } | |
| 50 | ||
| 51 | _LIBCPP_END_NAMESPACE_STD | |
| 52 | ||
| 53 | _LIBCPP_POP_MACROS | |
| 54 | ||
| 55 | #endif // _LIBCPP___ALGORITHM_FILL_H |
lib/libcxx/include/__algorithm/fill_n.h created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_FILL_N_H | |
| 10 | #define _LIBCPP___ALGORITHM_FILL_N_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/iterator_traits.h> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _OutputIterator, class _Size, class _Tp> | |
| 26 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 27 | _OutputIterator | |
| 28 | __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_) | |
| 29 | { | |
| 30 | for (; __n > 0; ++__first, (void) --__n) | |
| 31 | *__first = __value_; | |
| 32 | return __first; | |
| 33 | } | |
| 34 | ||
| 35 | template <class _OutputIterator, class _Size, class _Tp> | |
| 36 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 37 | _OutputIterator | |
| 38 | fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_) | |
| 39 | { | |
| 40 | return _VSTD::__fill_n(__first, _VSTD::__convert_to_integral(__n), __value_); | |
| 41 | } | |
| 42 | ||
| 43 | _LIBCPP_END_NAMESPACE_STD | |
| 44 | ||
| 45 | _LIBCPP_POP_MACROS | |
| 46 | ||
| 47 | #endif // _LIBCPP___ALGORITHM_FILL_N_H |
lib/libcxx/include/__algorithm/find.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_FIND_H | |
| 11 | #define _LIBCPP___ALGORITHM_FIND_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _InputIterator, class _Tp> | |
| 25 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator | |
| 26 | find(_InputIterator __first, _InputIterator __last, const _Tp& __value_) { | |
| 27 | for (; __first != __last; ++__first) | |
| 28 | if (*__first == __value_) | |
| 29 | break; | |
| 30 | return __first; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_FIND_H |
lib/libcxx/include/__algorithm/find_end.h created+154| ... | ... | @@ -0,0 +1,154 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_FIND_END_OF_H | |
| 11 | #define _LIBCPP___ALGORITHM_FIND_END_OF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 29 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, | |
| 30 | _BinaryPredicate __pred, forward_iterator_tag, | |
| 31 | forward_iterator_tag) { | |
| 32 | // modeled after search algorithm | |
| 33 | _ForwardIterator1 __r = __last1; // __last1 is the "default" answer | |
| 34 | if (__first2 == __last2) | |
| 35 | return __r; | |
| 36 | while (true) { | |
| 37 | while (true) { | |
| 38 | if (__first1 == __last1) // if source exhausted return last correct answer | |
| 39 | return __r; // (or __last1 if never found) | |
| 40 | if (__pred(*__first1, *__first2)) | |
| 41 | break; | |
| 42 | ++__first1; | |
| 43 | } | |
| 44 | // *__first1 matches *__first2, now match elements after here | |
| 45 | _ForwardIterator1 __m1 = __first1; | |
| 46 | _ForwardIterator2 __m2 = __first2; | |
| 47 | while (true) { | |
| 48 | if (++__m2 == __last2) { // Pattern exhaused, record answer and search for another one | |
| 49 | __r = __first1; | |
| 50 | ++__first1; | |
| 51 | break; | |
| 52 | } | |
| 53 | if (++__m1 == __last1) // Source exhausted, return last answer | |
| 54 | return __r; | |
| 55 | if (!__pred(*__m1, *__m2)) // mismatch, restart with a new __first | |
| 56 | { | |
| 57 | ++__first1; | |
| 58 | break; | |
| 59 | } // else there is a match, check next elements | |
| 60 | } | |
| 61 | } | |
| 62 | } | |
| 63 | ||
| 64 | template <class _BinaryPredicate, class _BidirectionalIterator1, class _BidirectionalIterator2> | |
| 65 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator1 __find_end( | |
| 66 | _BidirectionalIterator1 __first1, _BidirectionalIterator1 __last1, _BidirectionalIterator2 __first2, | |
| 67 | _BidirectionalIterator2 __last2, _BinaryPredicate __pred, bidirectional_iterator_tag, bidirectional_iterator_tag) { | |
| 68 | // modeled after search algorithm (in reverse) | |
| 69 | if (__first2 == __last2) | |
| 70 | return __last1; // Everything matches an empty sequence | |
| 71 | _BidirectionalIterator1 __l1 = __last1; | |
| 72 | _BidirectionalIterator2 __l2 = __last2; | |
| 73 | --__l2; | |
| 74 | while (true) { | |
| 75 | // Find last element in sequence 1 that matchs *(__last2-1), with a mininum of loop checks | |
| 76 | while (true) { | |
| 77 | if (__first1 == __l1) // return __last1 if no element matches *__first2 | |
| 78 | return __last1; | |
| 79 | if (__pred(*--__l1, *__l2)) | |
| 80 | break; | |
| 81 | } | |
| 82 | // *__l1 matches *__l2, now match elements before here | |
| 83 | _BidirectionalIterator1 __m1 = __l1; | |
| 84 | _BidirectionalIterator2 __m2 = __l2; | |
| 85 | while (true) { | |
| 86 | if (__m2 == __first2) // If pattern exhausted, __m1 is the answer (works for 1 element pattern) | |
| 87 | return __m1; | |
| 88 | if (__m1 == __first1) // Otherwise if source exhaused, pattern not found | |
| 89 | return __last1; | |
| 90 | if (!__pred(*--__m1, *--__m2)) // if there is a mismatch, restart with a new __l1 | |
| 91 | { | |
| 92 | break; | |
| 93 | } // else there is a match, check next elements | |
| 94 | } | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 98 | template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 99 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator1 __find_end( | |
| 100 | _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, | |
| 101 | _RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag, random_access_iterator_tag) { | |
| 102 | // Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern | |
| 103 | typename iterator_traits<_RandomAccessIterator2>::difference_type __len2 = __last2 - __first2; | |
| 104 | if (__len2 == 0) | |
| 105 | return __last1; | |
| 106 | typename iterator_traits<_RandomAccessIterator1>::difference_type __len1 = __last1 - __first1; | |
| 107 | if (__len1 < __len2) | |
| 108 | return __last1; | |
| 109 | const _RandomAccessIterator1 __s = __first1 + (__len2 - 1); // End of pattern match can't go before here | |
| 110 | _RandomAccessIterator1 __l1 = __last1; | |
| 111 | _RandomAccessIterator2 __l2 = __last2; | |
| 112 | --__l2; | |
| 113 | while (true) { | |
| 114 | while (true) { | |
| 115 | if (__s == __l1) | |
| 116 | return __last1; | |
| 117 | if (__pred(*--__l1, *__l2)) | |
| 118 | break; | |
| 119 | } | |
| 120 | _RandomAccessIterator1 __m1 = __l1; | |
| 121 | _RandomAccessIterator2 __m2 = __l2; | |
| 122 | while (true) { | |
| 123 | if (__m2 == __first2) | |
| 124 | return __m1; | |
| 125 | // no need to check range on __m1 because __s guarantees we have enough source | |
| 126 | if (!__pred(*--__m1, *--__m2)) { | |
| 127 | break; | |
| 128 | } | |
| 129 | } | |
| 130 | } | |
| 131 | } | |
| 132 | ||
| 133 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 134 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 | |
| 135 | find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, | |
| 136 | _BinaryPredicate __pred) { | |
| 137 | return _VSTD::__find_end<typename add_lvalue_reference<_BinaryPredicate>::type>( | |
| 138 | __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 139 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 140 | } | |
| 141 | ||
| 142 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 143 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 | |
| 144 | find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { | |
| 145 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 146 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 147 | return _VSTD::find_end(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 148 | } | |
| 149 | ||
| 150 | _LIBCPP_END_NAMESPACE_STD | |
| 151 | ||
| 152 | _LIBCPP_POP_MACROS | |
| 153 | ||
| 154 | #endif // _LIBCPP___ALGORITHM_FIND_END_OF_H |
lib/libcxx/include/__algorithm/find_first_of.h created+57| ... | ... | @@ -0,0 +1,57 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_FIND_FIRST_OF_H | |
| 11 | #define _LIBCPP___ALGORITHM_FIND_FIRST_OF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 27 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator1 __find_first_of_ce(_ForwardIterator1 __first1, | |
| 28 | _ForwardIterator1 __last1, | |
| 29 | _ForwardIterator2 __first2, | |
| 30 | _ForwardIterator2 __last2, _BinaryPredicate __pred) { | |
| 31 | for (; __first1 != __last1; ++__first1) | |
| 32 | for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) | |
| 33 | if (__pred(*__first1, *__j)) | |
| 34 | return __first1; | |
| 35 | return __last1; | |
| 36 | } | |
| 37 | ||
| 38 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 39 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 | |
| 40 | find_first_of(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, | |
| 41 | _ForwardIterator2 __last2, _BinaryPredicate __pred) { | |
| 42 | return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __pred); | |
| 43 | } | |
| 44 | ||
| 45 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 46 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 find_first_of( | |
| 47 | _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { | |
| 48 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 49 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 50 | return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 51 | } | |
| 52 | ||
| 53 | _LIBCPP_END_NAMESPACE_STD | |
| 54 | ||
| 55 | _LIBCPP_POP_MACROS | |
| 56 | ||
| 57 | #endif // _LIBCPP___ALGORITHM_FIND_FIRST_OF_H |
lib/libcxx/include/__algorithm/find_if.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_FIND_IF_H | |
| 11 | #define _LIBCPP___ALGORITHM_FIND_IF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _InputIterator, class _Predicate> | |
| 25 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator | |
| 26 | find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | |
| 27 | for (; __first != __last; ++__first) | |
| 28 | if (__pred(*__first)) | |
| 29 | break; | |
| 30 | return __first; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_FIND_IF_H |
lib/libcxx/include/__algorithm/find_if_not.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_FIND_IF_NOT_H | |
| 11 | #define _LIBCPP___ALGORITHM_FIND_IF_NOT_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _InputIterator, class _Predicate> | |
| 25 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator | |
| 26 | find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | |
| 27 | for (; __first != __last; ++__first) | |
| 28 | if (!__pred(*__first)) | |
| 29 | break; | |
| 30 | return __first; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_FIND_IF_NOT_H |
lib/libcxx/include/__algorithm/for_each.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_FOR_EACH_H | |
| 11 | #define _LIBCPP___ALGORITHM_FOR_EACH_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _InputIterator, class _Function> | |
| 25 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Function for_each(_InputIterator __first, | |
| 26 | _InputIterator __last, | |
| 27 | _Function __f) { | |
| 28 | for (; __first != __last; ++__first) | |
| 29 | __f(*__first); | |
| 30 | return __f; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_FOR_EACH_H |
lib/libcxx/include/__algorithm/for_each_n.h created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_H | |
| 11 | #define _LIBCPP___ALGORITHM_FOR_EACH_N_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if _LIBCPP_STD_VER > 14 | |
| 26 | ||
| 27 | template <class _InputIterator, class _Size, class _Function> | |
| 28 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator for_each_n(_InputIterator __first, | |
| 29 | _Size __orig_n, | |
| 30 | _Function __f) { | |
| 31 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 32 | _IntegralSize __n = __orig_n; | |
| 33 | while (__n > 0) { | |
| 34 | __f(*__first); | |
| 35 | ++__first; | |
| 36 | --__n; | |
| 37 | } | |
| 38 | return __first; | |
| 39 | } | |
| 40 | ||
| 41 | #endif | |
| 42 | ||
| 43 | _LIBCPP_END_NAMESPACE_STD | |
| 44 | ||
| 45 | _LIBCPP_POP_MACROS | |
| 46 | ||
| 47 | #endif // _LIBCPP___ALGORITHM_FOR_EACH_N_H |
lib/libcxx/include/__algorithm/generate.h created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_GENERATE_H | |
| 10 | #define _LIBCPP___ALGORITHM_GENERATE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _ForwardIterator, class _Generator> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | void | |
| 26 | generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) | |
| 27 | { | |
| 28 | for (; __first != __last; ++__first) | |
| 29 | *__first = __gen(); | |
| 30 | } | |
| 31 | ||
| 32 | _LIBCPP_END_NAMESPACE_STD | |
| 33 | ||
| 34 | _LIBCPP_POP_MACROS | |
| 35 | ||
| 36 | #endif // _LIBCPP___ALGORITHM_GENERATE_H |
lib/libcxx/include/__algorithm/generate_n.h created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_GENERATE_N_H | |
| 10 | #define _LIBCPP___ALGORITHM_GENERATE_N_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <type_traits> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _OutputIterator, class _Size, class _Generator> | |
| 25 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 26 | _OutputIterator | |
| 27 | generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) | |
| 28 | { | |
| 29 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 30 | _IntegralSize __n = __orig_n; | |
| 31 | for (; __n > 0; ++__first, (void) --__n) | |
| 32 | *__first = __gen(); | |
| 33 | return __first; | |
| 34 | } | |
| 35 | ||
| 36 | _LIBCPP_END_NAMESPACE_STD | |
| 37 | ||
| 38 | _LIBCPP_POP_MACROS | |
| 39 | ||
| 40 | #endif // _LIBCPP___ALGORITHM_GENERATE_N_H |
lib/libcxx/include/__algorithm/half_positive.h created+54| ... | ... | @@ -0,0 +1,54 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_HALF_POSITIVE_H | |
| 10 | #define _LIBCPP___ALGORITHM_HALF_POSITIVE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <type_traits> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | // Perform division by two quickly for positive integers (llvm.org/PR39129) | |
| 25 | ||
| 26 | template <typename _Integral> | |
| 27 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 28 | typename enable_if | |
| 29 | < | |
| 30 | is_integral<_Integral>::value, | |
| 31 | _Integral | |
| 32 | >::type | |
| 33 | __half_positive(_Integral __value) | |
| 34 | { | |
| 35 | return static_cast<_Integral>(static_cast<typename make_unsigned<_Integral>::type>(__value) / 2); | |
| 36 | } | |
| 37 | ||
| 38 | template <typename _Tp> | |
| 39 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 40 | typename enable_if | |
| 41 | < | |
| 42 | !is_integral<_Tp>::value, | |
| 43 | _Tp | |
| 44 | >::type | |
| 45 | __half_positive(_Tp __value) | |
| 46 | { | |
| 47 | return __value / 2; | |
| 48 | } | |
| 49 | ||
| 50 | _LIBCPP_END_NAMESPACE_STD | |
| 51 | ||
| 52 | _LIBCPP_POP_MACROS | |
| 53 | ||
| 54 | #endif // _LIBCPP___ALGORITHM_HALF_POSITIVE_H |
lib/libcxx/include/__algorithm/includes.h created+67| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_INCLUDES_H | |
| 10 | #define _LIBCPP___ALGORITHM_INCLUDES_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Compare, class _InputIterator1, class _InputIterator2> | |
| 27 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 28 | __includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, | |
| 29 | _Compare __comp) | |
| 30 | { | |
| 31 | for (; __first2 != __last2; ++__first1) | |
| 32 | { | |
| 33 | if (__first1 == __last1 || __comp(*__first2, *__first1)) | |
| 34 | return false; | |
| 35 | if (!__comp(*__first1, *__first2)) | |
| 36 | ++__first2; | |
| 37 | } | |
| 38 | return true; | |
| 39 | } | |
| 40 | ||
| 41 | template <class _InputIterator1, class _InputIterator2, class _Compare> | |
| 42 | _LIBCPP_NODISCARD_EXT inline | |
| 43 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 44 | bool | |
| 45 | includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, | |
| 46 | _Compare __comp) | |
| 47 | { | |
| 48 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 49 | return _VSTD::__includes<_Comp_ref>(__first1, __last1, __first2, __last2, __comp); | |
| 50 | } | |
| 51 | ||
| 52 | template <class _InputIterator1, class _InputIterator2> | |
| 53 | _LIBCPP_NODISCARD_EXT inline | |
| 54 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 55 | bool | |
| 56 | includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) | |
| 57 | { | |
| 58 | return _VSTD::includes(__first1, __last1, __first2, __last2, | |
| 59 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 60 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 61 | } | |
| 62 | ||
| 63 | _LIBCPP_END_NAMESPACE_STD | |
| 64 | ||
| 65 | _LIBCPP_POP_MACROS | |
| 66 | ||
| 67 | #endif // _LIBCPP___ALGORITHM_INCLUDES_H |
lib/libcxx/include/__algorithm/inplace_merge.h created+231| ... | ... | @@ -0,0 +1,231 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_INPLACE_MERGE_H | |
| 10 | #define _LIBCPP___ALGORITHM_INPLACE_MERGE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp_ref_type.h> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | #include <__algorithm/lower_bound.h> | |
| 16 | #include <__algorithm/min.h> | |
| 17 | #include <__algorithm/move.h> | |
| 18 | #include <__algorithm/rotate.h> | |
| 19 | #include <__algorithm/upper_bound.h> | |
| 20 | #include <__iterator/iterator_traits.h> | |
| 21 | #include <__utility/swap.h> | |
| 22 | #include <memory> | |
| 23 | ||
| 24 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 25 | #pragma GCC system_header | |
| 26 | #endif | |
| 27 | ||
| 28 | _LIBCPP_PUSH_MACROS | |
| 29 | #include <__undef_macros> | |
| 30 | ||
| 31 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 32 | ||
| 33 | template <class _Predicate> | |
| 34 | class __invert // invert the sense of a comparison | |
| 35 | { | |
| 36 | private: | |
| 37 | _Predicate __p_; | |
| 38 | public: | |
| 39 | _LIBCPP_INLINE_VISIBILITY __invert() {} | |
| 40 | ||
| 41 | _LIBCPP_INLINE_VISIBILITY | |
| 42 | explicit __invert(_Predicate __p) : __p_(__p) {} | |
| 43 | ||
| 44 | template <class _T1> | |
| 45 | _LIBCPP_INLINE_VISIBILITY | |
| 46 | bool operator()(const _T1& __x) {return !__p_(__x);} | |
| 47 | ||
| 48 | template <class _T1, class _T2> | |
| 49 | _LIBCPP_INLINE_VISIBILITY | |
| 50 | bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);} | |
| 51 | }; | |
| 52 | ||
| 53 | template <class _Compare, class _InputIterator1, class _InputIterator2, | |
| 54 | class _OutputIterator> | |
| 55 | void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 56 | _InputIterator2 __first2, _InputIterator2 __last2, | |
| 57 | _OutputIterator __result, _Compare __comp) | |
| 58 | { | |
| 59 | for (; __first1 != __last1; ++__result) | |
| 60 | { | |
| 61 | if (__first2 == __last2) | |
| 62 | { | |
| 63 | _VSTD::move(__first1, __last1, __result); | |
| 64 | return; | |
| 65 | } | |
| 66 | ||
| 67 | if (__comp(*__first2, *__first1)) | |
| 68 | { | |
| 69 | *__result = _VSTD::move(*__first2); | |
| 70 | ++__first2; | |
| 71 | } | |
| 72 | else | |
| 73 | { | |
| 74 | *__result = _VSTD::move(*__first1); | |
| 75 | ++__first1; | |
| 76 | } | |
| 77 | } | |
| 78 | // __first2 through __last2 are already in the right spot. | |
| 79 | } | |
| 80 | ||
| 81 | template <class _Compare, class _BidirectionalIterator> | |
| 82 | void | |
| 83 | __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 84 | _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, | |
| 85 | typename iterator_traits<_BidirectionalIterator>::difference_type __len2, | |
| 86 | typename iterator_traits<_BidirectionalIterator>::value_type* __buff) | |
| 87 | { | |
| 88 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 89 | __destruct_n __d(0); | |
| 90 | unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); | |
| 91 | if (__len1 <= __len2) | |
| 92 | { | |
| 93 | value_type* __p = __buff; | |
| 94 | for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) | |
| 95 | ::new ((void*)__p) value_type(_VSTD::move(*__i)); | |
| 96 | _VSTD::__half_inplace_merge<_Compare>(__buff, __p, __middle, __last, __first, __comp); | |
| 97 | } | |
| 98 | else | |
| 99 | { | |
| 100 | value_type* __p = __buff; | |
| 101 | for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) | |
| 102 | ::new ((void*)__p) value_type(_VSTD::move(*__i)); | |
| 103 | typedef reverse_iterator<_BidirectionalIterator> _RBi; | |
| 104 | typedef reverse_iterator<value_type*> _Rv; | |
| 105 | typedef __invert<_Compare> _Inverted; | |
| 106 | _VSTD::__half_inplace_merge<_Inverted>(_Rv(__p), _Rv(__buff), | |
| 107 | _RBi(__middle), _RBi(__first), | |
| 108 | _RBi(__last), _Inverted(__comp)); | |
| 109 | } | |
| 110 | } | |
| 111 | ||
| 112 | template <class _Compare, class _BidirectionalIterator> | |
| 113 | void | |
| 114 | __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 115 | _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, | |
| 116 | typename iterator_traits<_BidirectionalIterator>::difference_type __len2, | |
| 117 | typename iterator_traits<_BidirectionalIterator>::value_type* __buff, ptrdiff_t __buff_size) | |
| 118 | { | |
| 119 | typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; | |
| 120 | while (true) | |
| 121 | { | |
| 122 | // if __middle == __last, we're done | |
| 123 | if (__len2 == 0) | |
| 124 | return; | |
| 125 | if (__len1 <= __buff_size || __len2 <= __buff_size) | |
| 126 | return _VSTD::__buffered_inplace_merge<_Compare> | |
| 127 | (__first, __middle, __last, __comp, __len1, __len2, __buff); | |
| 128 | // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 | |
| 129 | for (; true; ++__first, (void) --__len1) | |
| 130 | { | |
| 131 | if (__len1 == 0) | |
| 132 | return; | |
| 133 | if (__comp(*__middle, *__first)) | |
| 134 | break; | |
| 135 | } | |
| 136 | // __first < __middle < __last | |
| 137 | // *__first > *__middle | |
| 138 | // partition [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) such that | |
| 139 | // all elements in: | |
| 140 | // [__first, __m1) <= [__middle, __m2) | |
| 141 | // [__middle, __m2) < [__m1, __middle) | |
| 142 | // [__m1, __middle) <= [__m2, __last) | |
| 143 | // and __m1 or __m2 is in the middle of its range | |
| 144 | _BidirectionalIterator __m1; // "median" of [__first, __middle) | |
| 145 | _BidirectionalIterator __m2; // "median" of [__middle, __last) | |
| 146 | difference_type __len11; // distance(__first, __m1) | |
| 147 | difference_type __len21; // distance(__middle, __m2) | |
| 148 | // binary search smaller range | |
| 149 | if (__len1 < __len2) | |
| 150 | { // __len >= 1, __len2 >= 2 | |
| 151 | __len21 = __len2 / 2; | |
| 152 | __m2 = __middle; | |
| 153 | _VSTD::advance(__m2, __len21); | |
| 154 | __m1 = _VSTD::__upper_bound<_Compare>(__first, __middle, *__m2, __comp); | |
| 155 | __len11 = _VSTD::distance(__first, __m1); | |
| 156 | } | |
| 157 | else | |
| 158 | { | |
| 159 | if (__len1 == 1) | |
| 160 | { // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1 | |
| 161 | // It is known *__first > *__middle | |
| 162 | swap(*__first, *__middle); | |
| 163 | return; | |
| 164 | } | |
| 165 | // __len1 >= 2, __len2 >= 1 | |
| 166 | __len11 = __len1 / 2; | |
| 167 | __m1 = __first; | |
| 168 | _VSTD::advance(__m1, __len11); | |
| 169 | __m2 = _VSTD::__lower_bound<_Compare>(__middle, __last, *__m1, __comp); | |
| 170 | __len21 = _VSTD::distance(__middle, __m2); | |
| 171 | } | |
| 172 | difference_type __len12 = __len1 - __len11; // distance(__m1, __middle) | |
| 173 | difference_type __len22 = __len2 - __len21; // distance(__m2, __last) | |
| 174 | // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) | |
| 175 | // swap middle two partitions | |
| 176 | __middle = _VSTD::rotate(__m1, __middle, __m2); | |
| 177 | // __len12 and __len21 now have swapped meanings | |
| 178 | // merge smaller range with recursive call and larger with tail recursion elimination | |
| 179 | if (__len11 + __len21 < __len12 + __len22) | |
| 180 | { | |
| 181 | _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); | |
| 182 | // _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); | |
| 183 | __first = __middle; | |
| 184 | __middle = __m2; | |
| 185 | __len1 = __len12; | |
| 186 | __len2 = __len22; | |
| 187 | } | |
| 188 | else | |
| 189 | { | |
| 190 | _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); | |
| 191 | // _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); | |
| 192 | __last = __middle; | |
| 193 | __middle = __m1; | |
| 194 | __len1 = __len11; | |
| 195 | __len2 = __len21; | |
| 196 | } | |
| 197 | } | |
| 198 | } | |
| 199 | ||
| 200 | template <class _BidirectionalIterator, class _Compare> | |
| 201 | inline _LIBCPP_INLINE_VISIBILITY | |
| 202 | void | |
| 203 | inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 204 | _Compare __comp) | |
| 205 | { | |
| 206 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 207 | typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; | |
| 208 | difference_type __len1 = _VSTD::distance(__first, __middle); | |
| 209 | difference_type __len2 = _VSTD::distance(__middle, __last); | |
| 210 | difference_type __buf_size = _VSTD::min(__len1, __len2); | |
| 211 | pair<value_type*, ptrdiff_t> __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size); | |
| 212 | unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first); | |
| 213 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 214 | return _VSTD::__inplace_merge<_Comp_ref>(__first, __middle, __last, __comp, __len1, __len2, | |
| 215 | __buf.first, __buf.second); | |
| 216 | } | |
| 217 | ||
| 218 | template <class _BidirectionalIterator> | |
| 219 | inline _LIBCPP_INLINE_VISIBILITY | |
| 220 | void | |
| 221 | inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) | |
| 222 | { | |
| 223 | _VSTD::inplace_merge(__first, __middle, __last, | |
| 224 | __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); | |
| 225 | } | |
| 226 | ||
| 227 | _LIBCPP_END_NAMESPACE_STD | |
| 228 | ||
| 229 | _LIBCPP_POP_MACROS | |
| 230 | ||
| 231 | #endif // _LIBCPP___ALGORITHM_INPLACE_MERGE_H |
lib/libcxx/include/__algorithm/is_heap.h created+48| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_IS_HEAP_H | |
| 10 | #define _LIBCPP___ALGORITHM_IS_HEAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/is_heap_until.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _RandomAccessIterator, class _Compare> | |
| 27 | _LIBCPP_NODISCARD_EXT inline | |
| 28 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 29 | bool | |
| 30 | is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 31 | { | |
| 32 | return _VSTD::is_heap_until(__first, __last, __comp) == __last; | |
| 33 | } | |
| 34 | ||
| 35 | template<class _RandomAccessIterator> | |
| 36 | _LIBCPP_NODISCARD_EXT inline | |
| 37 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 38 | bool | |
| 39 | is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 40 | { | |
| 41 | return _VSTD::is_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 42 | } | |
| 43 | ||
| 44 | _LIBCPP_END_NAMESPACE_STD | |
| 45 | ||
| 46 | _LIBCPP_POP_MACROS | |
| 47 | ||
| 48 | #endif // _LIBCPP___ALGORITHM_IS_HEAP_H |
lib/libcxx/include/__algorithm/is_heap_until.h created+65| ... | ... | @@ -0,0 +1,65 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H | |
| 10 | #define _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _RandomAccessIterator, class _Compare> | |
| 26 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator | |
| 27 | is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 28 | { | |
| 29 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 30 | difference_type __len = __last - __first; | |
| 31 | difference_type __p = 0; | |
| 32 | difference_type __c = 1; | |
| 33 | _RandomAccessIterator __pp = __first; | |
| 34 | while (__c < __len) | |
| 35 | { | |
| 36 | _RandomAccessIterator __cp = __first + __c; | |
| 37 | if (__comp(*__pp, *__cp)) | |
| 38 | return __cp; | |
| 39 | ++__c; | |
| 40 | ++__cp; | |
| 41 | if (__c == __len) | |
| 42 | return __last; | |
| 43 | if (__comp(*__pp, *__cp)) | |
| 44 | return __cp; | |
| 45 | ++__p; | |
| 46 | ++__pp; | |
| 47 | __c = 2 * __p + 1; | |
| 48 | } | |
| 49 | return __last; | |
| 50 | } | |
| 51 | ||
| 52 | template<class _RandomAccessIterator> | |
| 53 | _LIBCPP_NODISCARD_EXT inline | |
| 54 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 55 | _RandomAccessIterator | |
| 56 | is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 57 | { | |
| 58 | return _VSTD::is_heap_until(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 59 | } | |
| 60 | ||
| 61 | _LIBCPP_END_NAMESPACE_STD | |
| 62 | ||
| 63 | _LIBCPP_POP_MACROS | |
| 64 | ||
| 65 | #endif // _LIBCPP___ALGORITHM_IS_HEAP_UNTIL_H |
lib/libcxx/include/__algorithm/is_partitioned.h created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_IS_PARTITIONED_H | |
| 10 | #define _LIBCPP___ALGORITHM_IS_PARTITIONED_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _InputIterator, class _Predicate> | |
| 24 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 25 | is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 26 | { | |
| 27 | for (; __first != __last; ++__first) | |
| 28 | if (!__pred(*__first)) | |
| 29 | break; | |
| 30 | if ( __first == __last ) | |
| 31 | return true; | |
| 32 | ++__first; | |
| 33 | for (; __first != __last; ++__first) | |
| 34 | if (__pred(*__first)) | |
| 35 | return false; | |
| 36 | return true; | |
| 37 | } | |
| 38 | ||
| 39 | _LIBCPP_END_NAMESPACE_STD | |
| 40 | ||
| 41 | _LIBCPP_POP_MACROS | |
| 42 | ||
| 43 | #endif // _LIBCPP___ALGORITHM_IS_PARTITIONED_H |
lib/libcxx/include/__algorithm/is_permutation.h created+168| ... | ... | @@ -0,0 +1,168 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_IS_PERMUTATION_H | |
| 11 | #define _LIBCPP___ALGORITHM_IS_PERMUTATION_H | |
| 12 | ||
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__config> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__iterator/next.h> | |
| 17 | #include <iterator> // FIXME: replace with <__iterator/distance.h> when it lands | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 29 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 30 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, | |
| 31 | _BinaryPredicate __pred) { | |
| 32 | // shorten sequences as much as possible by lopping of any equal prefix | |
| 33 | for (; __first1 != __last1; ++__first1, (void)++__first2) | |
| 34 | if (!__pred(*__first1, *__first2)) | |
| 35 | break; | |
| 36 | if (__first1 == __last1) | |
| 37 | return true; | |
| 38 | ||
| 39 | // __first1 != __last1 && *__first1 != *__first2 | |
| 40 | typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; | |
| 41 | _D1 __l1 = _VSTD::distance(__first1, __last1); | |
| 42 | if (__l1 == _D1(1)) | |
| 43 | return false; | |
| 44 | _ForwardIterator2 __last2 = _VSTD::next(__first2, __l1); | |
| 45 | // For each element in [f1, l1) see if there are the same number of | |
| 46 | // equal elements in [f2, l2) | |
| 47 | for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) { | |
| 48 | // Have we already counted the number of *__i in [f1, l1)? | |
| 49 | _ForwardIterator1 __match = __first1; | |
| 50 | for (; __match != __i; ++__match) | |
| 51 | if (__pred(*__match, *__i)) | |
| 52 | break; | |
| 53 | if (__match == __i) { | |
| 54 | // Count number of *__i in [f2, l2) | |
| 55 | _D1 __c2 = 0; | |
| 56 | for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) | |
| 57 | if (__pred(*__i, *__j)) | |
| 58 | ++__c2; | |
| 59 | if (__c2 == 0) | |
| 60 | return false; | |
| 61 | // Count number of *__i in [__i, l1) (we can start with 1) | |
| 62 | _D1 __c1 = 1; | |
| 63 | for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) | |
| 64 | if (__pred(*__i, *__j)) | |
| 65 | ++__c1; | |
| 66 | if (__c1 != __c2) | |
| 67 | return false; | |
| 68 | } | |
| 69 | } | |
| 70 | return true; | |
| 71 | } | |
| 72 | ||
| 73 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 74 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 75 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { | |
| 76 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 77 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 78 | return _VSTD::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>()); | |
| 79 | } | |
| 80 | ||
| 81 | #if _LIBCPP_STD_VER > 11 | |
| 82 | template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2> | |
| 83 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 84 | __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, | |
| 85 | _ForwardIterator2 __last2, _BinaryPredicate __pred, forward_iterator_tag, forward_iterator_tag) { | |
| 86 | // shorten sequences as much as possible by lopping of any equal prefix | |
| 87 | for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) | |
| 88 | if (!__pred(*__first1, *__first2)) | |
| 89 | break; | |
| 90 | if (__first1 == __last1) | |
| 91 | return __first2 == __last2; | |
| 92 | else if (__first2 == __last2) | |
| 93 | return false; | |
| 94 | ||
| 95 | typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; | |
| 96 | _D1 __l1 = _VSTD::distance(__first1, __last1); | |
| 97 | ||
| 98 | typedef typename iterator_traits<_ForwardIterator2>::difference_type _D2; | |
| 99 | _D2 __l2 = _VSTD::distance(__first2, __last2); | |
| 100 | if (__l1 != __l2) | |
| 101 | return false; | |
| 102 | ||
| 103 | // For each element in [f1, l1) see if there are the same number of | |
| 104 | // equal elements in [f2, l2) | |
| 105 | for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) { | |
| 106 | // Have we already counted the number of *__i in [f1, l1)? | |
| 107 | _ForwardIterator1 __match = __first1; | |
| 108 | for (; __match != __i; ++__match) | |
| 109 | if (__pred(*__match, *__i)) | |
| 110 | break; | |
| 111 | if (__match == __i) { | |
| 112 | // Count number of *__i in [f2, l2) | |
| 113 | _D1 __c2 = 0; | |
| 114 | for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) | |
| 115 | if (__pred(*__i, *__j)) | |
| 116 | ++__c2; | |
| 117 | if (__c2 == 0) | |
| 118 | return false; | |
| 119 | // Count number of *__i in [__i, l1) (we can start with 1) | |
| 120 | _D1 __c1 = 1; | |
| 121 | for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) | |
| 122 | if (__pred(*__i, *__j)) | |
| 123 | ++__c1; | |
| 124 | if (__c1 != __c2) | |
| 125 | return false; | |
| 126 | } | |
| 127 | } | |
| 128 | return true; | |
| 129 | } | |
| 130 | ||
| 131 | template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 132 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __is_permutation(_RandomAccessIterator1 __first1, _RandomAccessIterator2 __last1, | |
| 133 | _RandomAccessIterator1 __first2, _RandomAccessIterator2 __last2, | |
| 134 | _BinaryPredicate __pred, random_access_iterator_tag, | |
| 135 | random_access_iterator_tag) { | |
| 136 | if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) | |
| 137 | return false; | |
| 138 | return _VSTD::is_permutation<_RandomAccessIterator1, _RandomAccessIterator2, | |
| 139 | typename add_lvalue_reference<_BinaryPredicate>::type>(__first1, __last1, __first2, | |
| 140 | __pred); | |
| 141 | } | |
| 142 | ||
| 143 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 144 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 145 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, | |
| 146 | _ForwardIterator2 __last2, _BinaryPredicate __pred) { | |
| 147 | return _VSTD::__is_permutation<typename add_lvalue_reference<_BinaryPredicate>::type>( | |
| 148 | __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 149 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 150 | } | |
| 151 | ||
| 152 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 153 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 154 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, | |
| 155 | _ForwardIterator2 __last2) { | |
| 156 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 157 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 158 | return _VSTD::__is_permutation(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(), | |
| 159 | typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 160 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 161 | } | |
| 162 | #endif | |
| 163 | ||
| 164 | _LIBCPP_END_NAMESPACE_STD | |
| 165 | ||
| 166 | _LIBCPP_POP_MACROS | |
| 167 | ||
| 168 | #endif // _LIBCPP___ALGORITHM_IS_PERMUTATION_H |
lib/libcxx/include/__algorithm/is_sorted.h created+48| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_IS_SORTED_H | |
| 10 | #define _LIBCPP___ALGORITHM_IS_SORTED_H | |
| 11 | ||
| 12 | #include <__algorithm/comp.h> | |
| 13 | #include <__algorithm/is_sorted_until.h> | |
| 14 | #include <__config> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator, class _Compare> | |
| 27 | _LIBCPP_NODISCARD_EXT inline | |
| 28 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 29 | bool | |
| 30 | is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 31 | { | |
| 32 | return _VSTD::is_sorted_until(__first, __last, __comp) == __last; | |
| 33 | } | |
| 34 | ||
| 35 | template<class _ForwardIterator> | |
| 36 | _LIBCPP_NODISCARD_EXT inline | |
| 37 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 38 | bool | |
| 39 | is_sorted(_ForwardIterator __first, _ForwardIterator __last) | |
| 40 | { | |
| 41 | return _VSTD::is_sorted(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 42 | } | |
| 43 | ||
| 44 | _LIBCPP_END_NAMESPACE_STD | |
| 45 | ||
| 46 | _LIBCPP_POP_MACROS | |
| 47 | ||
| 48 | #endif // _LIBCPP___ALGORITHM_IS_SORTED_H |
lib/libcxx/include/__algorithm/is_sorted_until.h created+55| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H | |
| 10 | #define _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _ForwardIterator, class _Compare> | |
| 26 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 27 | is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 28 | { | |
| 29 | if (__first != __last) | |
| 30 | { | |
| 31 | _ForwardIterator __i = __first; | |
| 32 | while (++__i != __last) | |
| 33 | { | |
| 34 | if (__comp(*__i, *__first)) | |
| 35 | return __i; | |
| 36 | __first = __i; | |
| 37 | } | |
| 38 | } | |
| 39 | return __last; | |
| 40 | } | |
| 41 | ||
| 42 | template<class _ForwardIterator> | |
| 43 | _LIBCPP_NODISCARD_EXT inline | |
| 44 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 45 | _ForwardIterator | |
| 46 | is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) | |
| 47 | { | |
| 48 | return _VSTD::is_sorted_until(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 49 | } | |
| 50 | ||
| 51 | _LIBCPP_END_NAMESPACE_STD | |
| 52 | ||
| 53 | _LIBCPP_POP_MACROS | |
| 54 | ||
| 55 | #endif // _LIBCPP___ALGORITHM_IS_SORTED_UNTIL_H |
lib/libcxx/include/__algorithm/iter_swap.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_ITER_SWAP_H | |
| 10 | #define _LIBCPP___ALGORITHM_ITER_SWAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__utility/declval.h> | |
| 14 | #include <__utility/swap.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 26 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void iter_swap(_ForwardIterator1 __a, | |
| 27 | _ForwardIterator2 __b) | |
| 28 | // _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b))) | |
| 29 | _NOEXCEPT_(_NOEXCEPT_(swap(*declval<_ForwardIterator1>(), *declval<_ForwardIterator2>()))) { | |
| 30 | swap(*__a, *__b); | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_ITER_SWAP_H |
lib/libcxx/include/__algorithm/lexicographical_compare.h created+68| ... | ... | @@ -0,0 +1,68 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H | |
| 10 | #define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Compare, class _InputIterator1, class _InputIterator2> | |
| 27 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 28 | __lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 29 | _InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) | |
| 30 | { | |
| 31 | for (; __first2 != __last2; ++__first1, (void) ++__first2) | |
| 32 | { | |
| 33 | if (__first1 == __last1 || __comp(*__first1, *__first2)) | |
| 34 | return true; | |
| 35 | if (__comp(*__first2, *__first1)) | |
| 36 | return false; | |
| 37 | } | |
| 38 | return false; | |
| 39 | } | |
| 40 | ||
| 41 | template <class _InputIterator1, class _InputIterator2, class _Compare> | |
| 42 | _LIBCPP_NODISCARD_EXT inline | |
| 43 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 44 | bool | |
| 45 | lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 46 | _InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) | |
| 47 | { | |
| 48 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 49 | return _VSTD::__lexicographical_compare<_Comp_ref>(__first1, __last1, __first2, __last2, __comp); | |
| 50 | } | |
| 51 | ||
| 52 | template <class _InputIterator1, class _InputIterator2> | |
| 53 | _LIBCPP_NODISCARD_EXT inline | |
| 54 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 55 | bool | |
| 56 | lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 57 | _InputIterator2 __first2, _InputIterator2 __last2) | |
| 58 | { | |
| 59 | return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, | |
| 60 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 61 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 62 | } | |
| 63 | ||
| 64 | _LIBCPP_END_NAMESPACE_STD | |
| 65 | ||
| 66 | _LIBCPP_POP_MACROS | |
| 67 | ||
| 68 | #endif // _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_H |
lib/libcxx/include/__algorithm/lower_bound.h created+72| ... | ... | @@ -0,0 +1,72 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_LOWER_BOUND_H | |
| 10 | #define _LIBCPP___ALGORITHM_LOWER_BOUND_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/half_positive.h> | |
| 15 | #include <iterator> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 27 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 28 | __lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 29 | { | |
| 30 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 31 | difference_type __len = _VSTD::distance(__first, __last); | |
| 32 | while (__len != 0) | |
| 33 | { | |
| 34 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 35 | _ForwardIterator __m = __first; | |
| 36 | _VSTD::advance(__m, __l2); | |
| 37 | if (__comp(*__m, __value_)) | |
| 38 | { | |
| 39 | __first = ++__m; | |
| 40 | __len -= __l2 + 1; | |
| 41 | } | |
| 42 | else | |
| 43 | __len = __l2; | |
| 44 | } | |
| 45 | return __first; | |
| 46 | } | |
| 47 | ||
| 48 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 49 | _LIBCPP_NODISCARD_EXT inline | |
| 50 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 51 | _ForwardIterator | |
| 52 | lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 53 | { | |
| 54 | typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; | |
| 55 | return _VSTD::__lower_bound<_Comp_ref>(__first, __last, __value_, __comp); | |
| 56 | } | |
| 57 | ||
| 58 | template <class _ForwardIterator, class _Tp> | |
| 59 | _LIBCPP_NODISCARD_EXT inline | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 61 | _ForwardIterator | |
| 62 | lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 63 | { | |
| 64 | return _VSTD::lower_bound(__first, __last, __value_, | |
| 65 | __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); | |
| 66 | } | |
| 67 | ||
| 68 | _LIBCPP_END_NAMESPACE_STD | |
| 69 | ||
| 70 | _LIBCPP_POP_MACROS | |
| 71 | ||
| 72 | #endif // _LIBCPP___ALGORITHM_LOWER_BOUND_H |
lib/libcxx/include/__algorithm/make_heap.h created+64| ... | ... | @@ -0,0 +1,64 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MAKE_HEAP_H | |
| 10 | #define _LIBCPP___ALGORITHM_MAKE_HEAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/sift_down.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Compare, class _RandomAccessIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX11 void | |
| 29 | __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 30 | { | |
| 31 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 32 | difference_type __n = __last - __first; | |
| 33 | if (__n > 1) | |
| 34 | { | |
| 35 | // start from the first parent, there is no need to consider children | |
| 36 | for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) | |
| 37 | { | |
| 38 | _VSTD::__sift_down<_Compare>(__first, __last, __comp, __n, __first + __start); | |
| 39 | } | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 43 | template <class _RandomAccessIterator, class _Compare> | |
| 44 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 45 | void | |
| 46 | make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 47 | { | |
| 48 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 49 | _VSTD::__make_heap<_Comp_ref>(__first, __last, __comp); | |
| 50 | } | |
| 51 | ||
| 52 | template <class _RandomAccessIterator> | |
| 53 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 54 | void | |
| 55 | make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 56 | { | |
| 57 | _VSTD::make_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 58 | } | |
| 59 | ||
| 60 | _LIBCPP_END_NAMESPACE_STD | |
| 61 | ||
| 62 | _LIBCPP_POP_MACROS | |
| 63 | ||
| 64 | #endif // _LIBCPP___ALGORITHM_MAKE_HEAP_H |
lib/libcxx/include/__algorithm/max.h created+70| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MAX_H | |
| 10 | #define _LIBCPP___ALGORITHM_MAX_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/max_element.h> | |
| 15 | #include <initializer_list> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Tp, class _Compare> | |
| 27 | _LIBCPP_NODISCARD_EXT inline | |
| 28 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 29 | const _Tp& | |
| 30 | max(const _Tp& __a, const _Tp& __b, _Compare __comp) | |
| 31 | { | |
| 32 | return __comp(__a, __b) ? __b : __a; | |
| 33 | } | |
| 34 | ||
| 35 | template <class _Tp> | |
| 36 | _LIBCPP_NODISCARD_EXT inline | |
| 37 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 38 | const _Tp& | |
| 39 | max(const _Tp& __a, const _Tp& __b) | |
| 40 | { | |
| 41 | return _VSTD::max(__a, __b, __less<_Tp>()); | |
| 42 | } | |
| 43 | ||
| 44 | #ifndef _LIBCPP_CXX03_LANG | |
| 45 | ||
| 46 | template<class _Tp, class _Compare> | |
| 47 | _LIBCPP_NODISCARD_EXT inline | |
| 48 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 49 | _Tp | |
| 50 | max(initializer_list<_Tp> __t, _Compare __comp) | |
| 51 | { | |
| 52 | return *_VSTD::max_element(__t.begin(), __t.end(), __comp); | |
| 53 | } | |
| 54 | ||
| 55 | template<class _Tp> | |
| 56 | _LIBCPP_NODISCARD_EXT inline | |
| 57 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 58 | _Tp | |
| 59 | max(initializer_list<_Tp> __t) | |
| 60 | { | |
| 61 | return *_VSTD::max_element(__t.begin(), __t.end(), __less<_Tp>()); | |
| 62 | } | |
| 63 | ||
| 64 | #endif // _LIBCPP_CXX03_LANG | |
| 65 | ||
| 66 | _LIBCPP_END_NAMESPACE_STD | |
| 67 | ||
| 68 | _LIBCPP_POP_MACROS | |
| 69 | ||
| 70 | #endif // _LIBCPP___ALGORITHM_MAX_H |
lib/libcxx/include/__algorithm/max_element.h created+58| ... | ... | @@ -0,0 +1,58 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MAX_ELEMENT_H | |
| 10 | #define _LIBCPP___ALGORITHM_MAX_ELEMENT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _ForwardIterator, class _Compare> | |
| 26 | _LIBCPP_NODISCARD_EXT inline | |
| 27 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 28 | _ForwardIterator | |
| 29 | max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 30 | { | |
| 31 | static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 32 | "std::max_element requires a ForwardIterator"); | |
| 33 | if (__first != __last) | |
| 34 | { | |
| 35 | _ForwardIterator __i = __first; | |
| 36 | while (++__i != __last) | |
| 37 | if (__comp(*__first, *__i)) | |
| 38 | __first = __i; | |
| 39 | } | |
| 40 | return __first; | |
| 41 | } | |
| 42 | ||
| 43 | ||
| 44 | template <class _ForwardIterator> | |
| 45 | _LIBCPP_NODISCARD_EXT inline | |
| 46 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 47 | _ForwardIterator | |
| 48 | max_element(_ForwardIterator __first, _ForwardIterator __last) | |
| 49 | { | |
| 50 | return _VSTD::max_element(__first, __last, | |
| 51 | __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 52 | } | |
| 53 | ||
| 54 | _LIBCPP_END_NAMESPACE_STD | |
| 55 | ||
| 56 | _LIBCPP_POP_MACROS | |
| 57 | ||
| 58 | #endif // _LIBCPP___ALGORITHM_MAX_ELEMENT_H |
lib/libcxx/include/__algorithm/merge.h created+76| ... | ... | @@ -0,0 +1,76 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MERGE_H | |
| 10 | #define _LIBCPP___ALGORITHM_MERGE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/copy.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 29 | _OutputIterator | |
| 30 | __merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 31 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 32 | { | |
| 33 | for (; __first1 != __last1; ++__result) | |
| 34 | { | |
| 35 | if (__first2 == __last2) | |
| 36 | return _VSTD::copy(__first1, __last1, __result); | |
| 37 | if (__comp(*__first2, *__first1)) | |
| 38 | { | |
| 39 | *__result = *__first2; | |
| 40 | ++__first2; | |
| 41 | } | |
| 42 | else | |
| 43 | { | |
| 44 | *__result = *__first1; | |
| 45 | ++__first1; | |
| 46 | } | |
| 47 | } | |
| 48 | return _VSTD::copy(__first2, __last2, __result); | |
| 49 | } | |
| 50 | ||
| 51 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 52 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 53 | _OutputIterator | |
| 54 | merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 55 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 56 | { | |
| 57 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 58 | return _VSTD::__merge<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 59 | } | |
| 60 | ||
| 61 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 62 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 63 | _OutputIterator | |
| 64 | merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 65 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 66 | { | |
| 67 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 68 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 69 | return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<__v1, __v2>()); | |
| 70 | } | |
| 71 | ||
| 72 | _LIBCPP_END_NAMESPACE_STD | |
| 73 | ||
| 74 | _LIBCPP_POP_MACROS | |
| 75 | ||
| 76 | #endif // _LIBCPP___ALGORITHM_MERGE_H |
lib/libcxx/include/__algorithm/min.h created+70| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MIN_H | |
| 10 | #define _LIBCPP___ALGORITHM_MIN_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/min_element.h> | |
| 15 | #include <initializer_list> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Tp, class _Compare> | |
| 27 | _LIBCPP_NODISCARD_EXT inline | |
| 28 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 29 | const _Tp& | |
| 30 | min(const _Tp& __a, const _Tp& __b, _Compare __comp) | |
| 31 | { | |
| 32 | return __comp(__b, __a) ? __b : __a; | |
| 33 | } | |
| 34 | ||
| 35 | template <class _Tp> | |
| 36 | _LIBCPP_NODISCARD_EXT inline | |
| 37 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 38 | const _Tp& | |
| 39 | min(const _Tp& __a, const _Tp& __b) | |
| 40 | { | |
| 41 | return _VSTD::min(__a, __b, __less<_Tp>()); | |
| 42 | } | |
| 43 | ||
| 44 | #ifndef _LIBCPP_CXX03_LANG | |
| 45 | ||
| 46 | template<class _Tp, class _Compare> | |
| 47 | _LIBCPP_NODISCARD_EXT inline | |
| 48 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 49 | _Tp | |
| 50 | min(initializer_list<_Tp> __t, _Compare __comp) | |
| 51 | { | |
| 52 | return *_VSTD::min_element(__t.begin(), __t.end(), __comp); | |
| 53 | } | |
| 54 | ||
| 55 | template<class _Tp> | |
| 56 | _LIBCPP_NODISCARD_EXT inline | |
| 57 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 58 | _Tp | |
| 59 | min(initializer_list<_Tp> __t) | |
| 60 | { | |
| 61 | return *_VSTD::min_element(__t.begin(), __t.end(), __less<_Tp>()); | |
| 62 | } | |
| 63 | ||
| 64 | #endif // _LIBCPP_CXX03_LANG | |
| 65 | ||
| 66 | _LIBCPP_END_NAMESPACE_STD | |
| 67 | ||
| 68 | _LIBCPP_POP_MACROS | |
| 69 | ||
| 70 | #endif // _LIBCPP___ALGORITHM_MIN_H |
lib/libcxx/include/__algorithm/min_element.h created+57| ... | ... | @@ -0,0 +1,57 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MIN_ELEMENT_H | |
| 10 | #define _LIBCPP___ALGORITHM_MIN_ELEMENT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _ForwardIterator, class _Compare> | |
| 26 | _LIBCPP_NODISCARD_EXT inline | |
| 27 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 28 | _ForwardIterator | |
| 29 | min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 30 | { | |
| 31 | static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 32 | "std::min_element requires a ForwardIterator"); | |
| 33 | if (__first != __last) | |
| 34 | { | |
| 35 | _ForwardIterator __i = __first; | |
| 36 | while (++__i != __last) | |
| 37 | if (__comp(*__i, *__first)) | |
| 38 | __first = __i; | |
| 39 | } | |
| 40 | return __first; | |
| 41 | } | |
| 42 | ||
| 43 | template <class _ForwardIterator> | |
| 44 | _LIBCPP_NODISCARD_EXT inline | |
| 45 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 46 | _ForwardIterator | |
| 47 | min_element(_ForwardIterator __first, _ForwardIterator __last) | |
| 48 | { | |
| 49 | return _VSTD::min_element(__first, __last, | |
| 50 | __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 51 | } | |
| 52 | ||
| 53 | _LIBCPP_END_NAMESPACE_STD | |
| 54 | ||
| 55 | _LIBCPP_POP_MACROS | |
| 56 | ||
| 57 | #endif // _LIBCPP___ALGORITHM_MIN_ELEMENT_H |
lib/libcxx/include/__algorithm/minmax.h created+101| ... | ... | @@ -0,0 +1,101 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MINMAX_H | |
| 10 | #define _LIBCPP___ALGORITHM_MINMAX_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <initializer_list> | |
| 15 | #include <utility> | |
| 16 | ||
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template<class _Tp, class _Compare> | |
| 28 | _LIBCPP_NODISCARD_EXT inline | |
| 29 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 30 | pair<const _Tp&, const _Tp&> | |
| 31 | minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) | |
| 32 | { | |
| 33 | return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a) : | |
| 34 | pair<const _Tp&, const _Tp&>(__a, __b); | |
| 35 | } | |
| 36 | ||
| 37 | template<class _Tp> | |
| 38 | _LIBCPP_NODISCARD_EXT inline | |
| 39 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 40 | pair<const _Tp&, const _Tp&> | |
| 41 | minmax(const _Tp& __a, const _Tp& __b) | |
| 42 | { | |
| 43 | return _VSTD::minmax(__a, __b, __less<_Tp>()); | |
| 44 | } | |
| 45 | ||
| 46 | #ifndef _LIBCPP_CXX03_LANG | |
| 47 | ||
| 48 | template<class _Tp, class _Compare> | |
| 49 | _LIBCPP_NODISCARD_EXT inline | |
| 50 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 51 | pair<_Tp, _Tp> | |
| 52 | minmax(initializer_list<_Tp> __t, _Compare __comp) | |
| 53 | { | |
| 54 | typedef typename initializer_list<_Tp>::const_iterator _Iter; | |
| 55 | _Iter __first = __t.begin(); | |
| 56 | _Iter __last = __t.end(); | |
| 57 | pair<_Tp, _Tp> __result(*__first, *__first); | |
| 58 | ||
| 59 | ++__first; | |
| 60 | if (__t.size() % 2 == 0) | |
| 61 | { | |
| 62 | if (__comp(*__first, __result.first)) | |
| 63 | __result.first = *__first; | |
| 64 | else | |
| 65 | __result.second = *__first; | |
| 66 | ++__first; | |
| 67 | } | |
| 68 | ||
| 69 | while (__first != __last) | |
| 70 | { | |
| 71 | _Tp __prev = *__first++; | |
| 72 | if (__comp(*__first, __prev)) { | |
| 73 | if ( __comp(*__first, __result.first)) __result.first = *__first; | |
| 74 | if (!__comp(__prev, __result.second)) __result.second = __prev; | |
| 75 | } | |
| 76 | else { | |
| 77 | if ( __comp(__prev, __result.first)) __result.first = __prev; | |
| 78 | if (!__comp(*__first, __result.second)) __result.second = *__first; | |
| 79 | } | |
| 80 | ||
| 81 | __first++; | |
| 82 | } | |
| 83 | return __result; | |
| 84 | } | |
| 85 | ||
| 86 | template<class _Tp> | |
| 87 | _LIBCPP_NODISCARD_EXT inline | |
| 88 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 89 | pair<_Tp, _Tp> | |
| 90 | minmax(initializer_list<_Tp> __t) | |
| 91 | { | |
| 92 | return _VSTD::minmax(__t, __less<_Tp>()); | |
| 93 | } | |
| 94 | ||
| 95 | #endif // _LIBCPP_CXX03_LANG | |
| 96 | ||
| 97 | _LIBCPP_END_NAMESPACE_STD | |
| 98 | ||
| 99 | _LIBCPP_POP_MACROS | |
| 100 | ||
| 101 | #endif // _LIBCPP___ALGORITHM_MINMAX_H |
lib/libcxx/include/__algorithm/minmax_element.h created+90| ... | ... | @@ -0,0 +1,90 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H | |
| 10 | #define _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <utility> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator, class _Compare> | |
| 27 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 28 | pair<_ForwardIterator, _ForwardIterator> | |
| 29 | minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 30 | { | |
| 31 | static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 32 | "std::minmax_element requires a ForwardIterator"); | |
| 33 | pair<_ForwardIterator, _ForwardIterator> __result(__first, __first); | |
| 34 | if (__first != __last) | |
| 35 | { | |
| 36 | if (++__first != __last) | |
| 37 | { | |
| 38 | if (__comp(*__first, *__result.first)) | |
| 39 | __result.first = __first; | |
| 40 | else | |
| 41 | __result.second = __first; | |
| 42 | while (++__first != __last) | |
| 43 | { | |
| 44 | _ForwardIterator __i = __first; | |
| 45 | if (++__first == __last) | |
| 46 | { | |
| 47 | if (__comp(*__i, *__result.first)) | |
| 48 | __result.first = __i; | |
| 49 | else if (!__comp(*__i, *__result.second)) | |
| 50 | __result.second = __i; | |
| 51 | break; | |
| 52 | } | |
| 53 | else | |
| 54 | { | |
| 55 | if (__comp(*__first, *__i)) | |
| 56 | { | |
| 57 | if (__comp(*__first, *__result.first)) | |
| 58 | __result.first = __first; | |
| 59 | if (!__comp(*__i, *__result.second)) | |
| 60 | __result.second = __i; | |
| 61 | } | |
| 62 | else | |
| 63 | { | |
| 64 | if (__comp(*__i, *__result.first)) | |
| 65 | __result.first = __i; | |
| 66 | if (!__comp(*__first, *__result.second)) | |
| 67 | __result.second = __first; | |
| 68 | } | |
| 69 | } | |
| 70 | } | |
| 71 | } | |
| 72 | } | |
| 73 | return __result; | |
| 74 | } | |
| 75 | ||
| 76 | template <class _ForwardIterator> | |
| 77 | _LIBCPP_NODISCARD_EXT inline | |
| 78 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 79 | pair<_ForwardIterator, _ForwardIterator> | |
| 80 | minmax_element(_ForwardIterator __first, _ForwardIterator __last) | |
| 81 | { | |
| 82 | return _VSTD::minmax_element(__first, __last, | |
| 83 | __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 84 | } | |
| 85 | ||
| 86 | _LIBCPP_END_NAMESPACE_STD | |
| 87 | ||
| 88 | _LIBCPP_POP_MACROS | |
| 89 | ||
| 90 | #endif // _LIBCPP___ALGORITHM_MINMAX_ELEMENT_H |
lib/libcxx/include/__algorithm/mismatch.h created+72| ... | ... | @@ -0,0 +1,72 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_MISMATCH_H | |
| 11 | #define _LIBCPP___ALGORITHM_MISMATCH_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <utility> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 28 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY | |
| 29 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2> | |
| 30 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { | |
| 31 | for (; __first1 != __last1; ++__first1, (void)++__first2) | |
| 32 | if (!__pred(*__first1, *__first2)) | |
| 33 | break; | |
| 34 | return pair<_InputIterator1, _InputIterator2>(__first1, __first2); | |
| 35 | } | |
| 36 | ||
| 37 | template <class _InputIterator1, class _InputIterator2> | |
| 38 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY | |
| 39 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2> | |
| 40 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { | |
| 41 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 42 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 43 | return _VSTD::mismatch(__first1, __last1, __first2, __equal_to<__v1, __v2>()); | |
| 44 | } | |
| 45 | ||
| 46 | #if _LIBCPP_STD_VER > 11 | |
| 47 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 48 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY | |
| 49 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2> | |
| 50 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, | |
| 51 | _BinaryPredicate __pred) { | |
| 52 | for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) | |
| 53 | if (!__pred(*__first1, *__first2)) | |
| 54 | break; | |
| 55 | return pair<_InputIterator1, _InputIterator2>(__first1, __first2); | |
| 56 | } | |
| 57 | ||
| 58 | template <class _InputIterator1, class _InputIterator2> | |
| 59 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY | |
| 60 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2> | |
| 61 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { | |
| 62 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 63 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 64 | return _VSTD::mismatch(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 65 | } | |
| 66 | #endif | |
| 67 | ||
| 68 | _LIBCPP_END_NAMESPACE_STD | |
| 69 | ||
| 70 | _LIBCPP_POP_MACROS | |
| 71 | ||
| 72 | #endif // _LIBCPP___ALGORITHM_MISMATCH_H |
lib/libcxx/include/__algorithm/move.h created+83| ... | ... | @@ -0,0 +1,83 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MOVE_H | |
| 10 | #define _LIBCPP___ALGORITHM_MOVE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/unwrap_iter.h> | |
| 14 | #include <__utility/move.h> | |
| 15 | #include <cstring> | |
| 16 | #include <utility> | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | // move | |
| 29 | ||
| 30 | template <class _InputIterator, class _OutputIterator> | |
| 31 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 32 | _OutputIterator | |
| 33 | __move_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 34 | { | |
| 35 | for (; __first != __last; ++__first, (void) ++__result) | |
| 36 | *__result = _VSTD::move(*__first); | |
| 37 | return __result; | |
| 38 | } | |
| 39 | ||
| 40 | template <class _InputIterator, class _OutputIterator> | |
| 41 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 42 | _OutputIterator | |
| 43 | __move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 44 | { | |
| 45 | return _VSTD::__move_constexpr(__first, __last, __result); | |
| 46 | } | |
| 47 | ||
| 48 | template <class _Tp, class _Up> | |
| 49 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 50 | typename enable_if | |
| 51 | < | |
| 52 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 53 | is_trivially_move_assignable<_Up>::value, | |
| 54 | _Up* | |
| 55 | >::type | |
| 56 | __move(_Tp* __first, _Tp* __last, _Up* __result) | |
| 57 | { | |
| 58 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 59 | if (__n > 0) | |
| 60 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 61 | return __result + __n; | |
| 62 | } | |
| 63 | ||
| 64 | template <class _InputIterator, class _OutputIterator> | |
| 65 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 66 | _OutputIterator | |
| 67 | move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 68 | { | |
| 69 | if (__libcpp_is_constant_evaluated()) { | |
| 70 | return _VSTD::__move_constexpr(__first, __last, __result); | |
| 71 | } else { | |
| 72 | return _VSTD::__rewrap_iter(__result, | |
| 73 | _VSTD::__move(_VSTD::__unwrap_iter(__first), | |
| 74 | _VSTD::__unwrap_iter(__last), | |
| 75 | _VSTD::__unwrap_iter(__result))); | |
| 76 | } | |
| 77 | } | |
| 78 | ||
| 79 | _LIBCPP_END_NAMESPACE_STD | |
| 80 | ||
| 81 | _LIBCPP_POP_MACROS | |
| 82 | ||
| 83 | #endif // _LIBCPP___ALGORITHM_MOVE_H |
lib/libcxx/include/__algorithm/move_backward.h created+84| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H | |
| 10 | #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/unwrap_iter.h> | |
| 14 | #include <cstring> | |
| 15 | #include <utility> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _InputIterator, class _OutputIterator> | |
| 28 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 29 | _OutputIterator | |
| 30 | __move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 31 | { | |
| 32 | while (__first != __last) | |
| 33 | *--__result = _VSTD::move(*--__last); | |
| 34 | return __result; | |
| 35 | } | |
| 36 | ||
| 37 | template <class _InputIterator, class _OutputIterator> | |
| 38 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 39 | _OutputIterator | |
| 40 | __move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 41 | { | |
| 42 | return _VSTD::__move_backward_constexpr(__first, __last, __result); | |
| 43 | } | |
| 44 | ||
| 45 | template <class _Tp, class _Up> | |
| 46 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 47 | typename enable_if | |
| 48 | < | |
| 49 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 50 | is_trivially_move_assignable<_Up>::value, | |
| 51 | _Up* | |
| 52 | >::type | |
| 53 | __move_backward(_Tp* __first, _Tp* __last, _Up* __result) | |
| 54 | { | |
| 55 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 56 | if (__n > 0) | |
| 57 | { | |
| 58 | __result -= __n; | |
| 59 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 60 | } | |
| 61 | return __result; | |
| 62 | } | |
| 63 | ||
| 64 | template <class _BidirectionalIterator1, class _BidirectionalIterator2> | |
| 65 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 66 | _BidirectionalIterator2 | |
| 67 | move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, | |
| 68 | _BidirectionalIterator2 __result) | |
| 69 | { | |
| 70 | if (__libcpp_is_constant_evaluated()) { | |
| 71 | return _VSTD::__move_backward_constexpr(__first, __last, __result); | |
| 72 | } else { | |
| 73 | return _VSTD::__rewrap_iter(__result, | |
| 74 | _VSTD::__move_backward(_VSTD::__unwrap_iter(__first), | |
| 75 | _VSTD::__unwrap_iter(__last), | |
| 76 | _VSTD::__unwrap_iter(__result))); | |
| 77 | } | |
| 78 | } | |
| 79 | ||
| 80 | _LIBCPP_END_NAMESPACE_STD | |
| 81 | ||
| 82 | _LIBCPP_POP_MACROS | |
| 83 | ||
| 84 | #endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H |
lib/libcxx/include/__algorithm/next_permutation.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H | |
| 10 | #define _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/reverse.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <__utility/swap.h> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _Compare, class _BidirectionalIterator> | |
| 29 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 30 | __next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 31 | { | |
| 32 | _BidirectionalIterator __i = __last; | |
| 33 | if (__first == __last || __first == --__i) | |
| 34 | return false; | |
| 35 | while (true) | |
| 36 | { | |
| 37 | _BidirectionalIterator __ip1 = __i; | |
| 38 | if (__comp(*--__i, *__ip1)) | |
| 39 | { | |
| 40 | _BidirectionalIterator __j = __last; | |
| 41 | while (!__comp(*__i, *--__j)) | |
| 42 | ; | |
| 43 | swap(*__i, *__j); | |
| 44 | _VSTD::reverse(__ip1, __last); | |
| 45 | return true; | |
| 46 | } | |
| 47 | if (__i == __first) | |
| 48 | { | |
| 49 | _VSTD::reverse(__first, __last); | |
| 50 | return false; | |
| 51 | } | |
| 52 | } | |
| 53 | } | |
| 54 | ||
| 55 | template <class _BidirectionalIterator, class _Compare> | |
| 56 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 57 | bool | |
| 58 | next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 59 | { | |
| 60 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 61 | return _VSTD::__next_permutation<_Comp_ref>(__first, __last, __comp); | |
| 62 | } | |
| 63 | ||
| 64 | template <class _BidirectionalIterator> | |
| 65 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 66 | bool | |
| 67 | next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 68 | { | |
| 69 | return _VSTD::next_permutation(__first, __last, | |
| 70 | __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); | |
| 71 | } | |
| 72 | ||
| 73 | _LIBCPP_END_NAMESPACE_STD | |
| 74 | ||
| 75 | _LIBCPP_POP_MACROS | |
| 76 | ||
| 77 | #endif // _LIBCPP___ALGORITHM_NEXT_PERMUTATION_H |
lib/libcxx/include/__algorithm/none_of.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_NONE_OF_H | |
| 11 | #define _LIBCPP___ALGORITHM_NONE_OF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _InputIterator, class _Predicate> | |
| 25 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 26 | none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { | |
| 27 | for (; __first != __last; ++__first) | |
| 28 | if (__pred(*__first)) | |
| 29 | return false; | |
| 30 | return true; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_NONE_OF_H |
lib/libcxx/include/__algorithm/nth_element.h created+244| ... | ... | @@ -0,0 +1,244 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_NTH_ELEMENT_H | |
| 10 | #define _LIBCPP___ALGORITHM_NTH_ELEMENT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/sort.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <__utility/swap.h> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template<class _Compare, class _RandomAccessIterator> | |
| 29 | _LIBCPP_CONSTEXPR_AFTER_CXX11 bool | |
| 30 | __nth_element_find_guard(_RandomAccessIterator& __i, _RandomAccessIterator& __j, | |
| 31 | _RandomAccessIterator __m, _Compare __comp) | |
| 32 | { | |
| 33 | // manually guard downward moving __j against __i | |
| 34 | while (true) { | |
| 35 | if (__i == --__j) { | |
| 36 | return false; | |
| 37 | } | |
| 38 | if (__comp(*__j, *__m)) { | |
| 39 | return true; // found guard for downward moving __j, now use unguarded partition | |
| 40 | } | |
| 41 | } | |
| 42 | } | |
| 43 | ||
| 44 | template <class _Compare, class _RandomAccessIterator> | |
| 45 | _LIBCPP_CONSTEXPR_AFTER_CXX11 void | |
| 46 | __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) | |
| 47 | { | |
| 48 | // _Compare is known to be a reference type | |
| 49 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 50 | const difference_type __limit = 7; | |
| 51 | while (true) | |
| 52 | { | |
| 53 | if (__nth == __last) | |
| 54 | return; | |
| 55 | difference_type __len = __last - __first; | |
| 56 | switch (__len) | |
| 57 | { | |
| 58 | case 0: | |
| 59 | case 1: | |
| 60 | return; | |
| 61 | case 2: | |
| 62 | if (__comp(*--__last, *__first)) | |
| 63 | swap(*__first, *__last); | |
| 64 | return; | |
| 65 | case 3: | |
| 66 | { | |
| 67 | _RandomAccessIterator __m = __first; | |
| 68 | _VSTD::__sort3<_Compare>(__first, ++__m, --__last, __comp); | |
| 69 | return; | |
| 70 | } | |
| 71 | } | |
| 72 | if (__len <= __limit) | |
| 73 | { | |
| 74 | _VSTD::__selection_sort<_Compare>(__first, __last, __comp); | |
| 75 | return; | |
| 76 | } | |
| 77 | // __len > __limit >= 3 | |
| 78 | _RandomAccessIterator __m = __first + __len/2; | |
| 79 | _RandomAccessIterator __lm1 = __last; | |
| 80 | unsigned __n_swaps = _VSTD::__sort3<_Compare>(__first, __m, --__lm1, __comp); | |
| 81 | // *__m is median | |
| 82 | // partition [__first, __m) < *__m and *__m <= [__m, __last) | |
| 83 | // (this inhibits tossing elements equivalent to __m around unnecessarily) | |
| 84 | _RandomAccessIterator __i = __first; | |
| 85 | _RandomAccessIterator __j = __lm1; | |
| 86 | // j points beyond range to be tested, *__lm1 is known to be <= *__m | |
| 87 | // The search going up is known to be guarded but the search coming down isn't. | |
| 88 | // Prime the downward search with a guard. | |
| 89 | if (!__comp(*__i, *__m)) // if *__first == *__m | |
| 90 | { | |
| 91 | // *__first == *__m, *__first doesn't go in first part | |
| 92 | if (_VSTD::__nth_element_find_guard<_Compare>(__i, __j, __m, __comp)) { | |
| 93 | swap(*__i, *__j); | |
| 94 | ++__n_swaps; | |
| 95 | } else { | |
| 96 | // *__first == *__m, *__m <= all other elements | |
| 97 | // Partition instead into [__first, __i) == *__first and *__first < [__i, __last) | |
| 98 | ++__i; // __first + 1 | |
| 99 | __j = __last; | |
| 100 | if (!__comp(*__first, *--__j)) { // we need a guard if *__first == *(__last-1) | |
| 101 | while (true) { | |
| 102 | if (__i == __j) { | |
| 103 | return; // [__first, __last) all equivalent elements | |
| 104 | } else if (__comp(*__first, *__i)) { | |
| 105 | swap(*__i, *__j); | |
| 106 | ++__n_swaps; | |
| 107 | ++__i; | |
| 108 | break; | |
| 109 | } | |
| 110 | ++__i; | |
| 111 | } | |
| 112 | } | |
| 113 | // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 | |
| 114 | if (__i == __j) { | |
| 115 | return; | |
| 116 | } | |
| 117 | while (true) { | |
| 118 | while (!__comp(*__first, *__i)) | |
| 119 | ++__i; | |
| 120 | while (__comp(*__first, *--__j)) | |
| 121 | ; | |
| 122 | if (__i >= __j) | |
| 123 | break; | |
| 124 | swap(*__i, *__j); | |
| 125 | ++__n_swaps; | |
| 126 | ++__i; | |
| 127 | } | |
| 128 | // [__first, __i) == *__first and *__first < [__i, __last) | |
| 129 | // The first part is sorted, | |
| 130 | if (__nth < __i) { | |
| 131 | return; | |
| 132 | } | |
| 133 | // __nth_element the second part | |
| 134 | // _VSTD::__nth_element<_Compare>(__i, __nth, __last, __comp); | |
| 135 | __first = __i; | |
| 136 | continue; | |
| 137 | } | |
| 138 | } | |
| 139 | ++__i; | |
| 140 | // j points beyond range to be tested, *__lm1 is known to be <= *__m | |
| 141 | // if not yet partitioned... | |
| 142 | if (__i < __j) | |
| 143 | { | |
| 144 | // known that *(__i - 1) < *__m | |
| 145 | while (true) | |
| 146 | { | |
| 147 | // __m still guards upward moving __i | |
| 148 | while (__comp(*__i, *__m)) | |
| 149 | ++__i; | |
| 150 | // It is now known that a guard exists for downward moving __j | |
| 151 | while (!__comp(*--__j, *__m)) | |
| 152 | ; | |
| 153 | if (__i >= __j) | |
| 154 | break; | |
| 155 | swap(*__i, *__j); | |
| 156 | ++__n_swaps; | |
| 157 | // It is known that __m != __j | |
| 158 | // If __m just moved, follow it | |
| 159 | if (__m == __i) | |
| 160 | __m = __j; | |
| 161 | ++__i; | |
| 162 | } | |
| 163 | } | |
| 164 | // [__first, __i) < *__m and *__m <= [__i, __last) | |
| 165 | if (__i != __m && __comp(*__m, *__i)) | |
| 166 | { | |
| 167 | swap(*__i, *__m); | |
| 168 | ++__n_swaps; | |
| 169 | } | |
| 170 | // [__first, __i) < *__i and *__i <= [__i+1, __last) | |
| 171 | if (__nth == __i) | |
| 172 | return; | |
| 173 | if (__n_swaps == 0) | |
| 174 | { | |
| 175 | // We were given a perfectly partitioned sequence. Coincidence? | |
| 176 | if (__nth < __i) | |
| 177 | { | |
| 178 | // Check for [__first, __i) already sorted | |
| 179 | __j = __m = __first; | |
| 180 | while (true) { | |
| 181 | if (++__j == __i) { | |
| 182 | // [__first, __i) sorted | |
| 183 | return; | |
| 184 | } | |
| 185 | if (__comp(*__j, *__m)) { | |
| 186 | // not yet sorted, so sort | |
| 187 | break; | |
| 188 | } | |
| 189 | __m = __j; | |
| 190 | } | |
| 191 | } | |
| 192 | else | |
| 193 | { | |
| 194 | // Check for [__i, __last) already sorted | |
| 195 | __j = __m = __i; | |
| 196 | while (true) { | |
| 197 | if (++__j == __last) { | |
| 198 | // [__i, __last) sorted | |
| 199 | return; | |
| 200 | } | |
| 201 | if (__comp(*__j, *__m)) { | |
| 202 | // not yet sorted, so sort | |
| 203 | break; | |
| 204 | } | |
| 205 | __m = __j; | |
| 206 | } | |
| 207 | } | |
| 208 | } | |
| 209 | // __nth_element on range containing __nth | |
| 210 | if (__nth < __i) | |
| 211 | { | |
| 212 | // _VSTD::__nth_element<_Compare>(__first, __nth, __i, __comp); | |
| 213 | __last = __i; | |
| 214 | } | |
| 215 | else | |
| 216 | { | |
| 217 | // _VSTD::__nth_element<_Compare>(__i+1, __nth, __last, __comp); | |
| 218 | __first = ++__i; | |
| 219 | } | |
| 220 | } | |
| 221 | } | |
| 222 | ||
| 223 | template <class _RandomAccessIterator, class _Compare> | |
| 224 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 225 | void | |
| 226 | nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) | |
| 227 | { | |
| 228 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 229 | _VSTD::__nth_element<_Comp_ref>(__first, __nth, __last, __comp); | |
| 230 | } | |
| 231 | ||
| 232 | template <class _RandomAccessIterator> | |
| 233 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 234 | void | |
| 235 | nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) | |
| 236 | { | |
| 237 | _VSTD::nth_element(__first, __nth, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 238 | } | |
| 239 | ||
| 240 | _LIBCPP_END_NAMESPACE_STD | |
| 241 | ||
| 242 | _LIBCPP_POP_MACROS | |
| 243 | ||
| 244 | #endif // _LIBCPP___ALGORITHM_NTH_ELEMENT_H |
lib/libcxx/include/__algorithm/partial_sort.h created+71| ... | ... | @@ -0,0 +1,71 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_PARTIAL_SORT_H | |
| 10 | #define _LIBCPP___ALGORITHM_PARTIAL_SORT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/make_heap.h> | |
| 16 | #include <__algorithm/sift_down.h> | |
| 17 | #include <__algorithm/sort_heap.h> | |
| 18 | #include <__iterator/iterator_traits.h> | |
| 19 | #include <__utility/swap.h> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | template <class _Compare, class _RandomAccessIterator> | |
| 31 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void | |
| 32 | __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, | |
| 33 | _Compare __comp) | |
| 34 | { | |
| 35 | _VSTD::__make_heap<_Compare>(__first, __middle, __comp); | |
| 36 | typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; | |
| 37 | for (_RandomAccessIterator __i = __middle; __i != __last; ++__i) | |
| 38 | { | |
| 39 | if (__comp(*__i, *__first)) | |
| 40 | { | |
| 41 | swap(*__i, *__first); | |
| 42 | _VSTD::__sift_down<_Compare>(__first, __middle, __comp, __len, __first); | |
| 43 | } | |
| 44 | } | |
| 45 | _VSTD::__sort_heap<_Compare>(__first, __middle, __comp); | |
| 46 | } | |
| 47 | ||
| 48 | template <class _RandomAccessIterator, class _Compare> | |
| 49 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 50 | void | |
| 51 | partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, | |
| 52 | _Compare __comp) | |
| 53 | { | |
| 54 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 55 | _VSTD::__partial_sort<_Comp_ref>(__first, __middle, __last, __comp); | |
| 56 | } | |
| 57 | ||
| 58 | template <class _RandomAccessIterator> | |
| 59 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 60 | void | |
| 61 | partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) | |
| 62 | { | |
| 63 | _VSTD::partial_sort(__first, __middle, __last, | |
| 64 | __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 65 | } | |
| 66 | ||
| 67 | _LIBCPP_END_NAMESPACE_STD | |
| 68 | ||
| 69 | _LIBCPP_POP_MACROS | |
| 70 | ||
| 71 | #endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_H |
lib/libcxx/include/__algorithm/partial_sort_copy.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/make_heap.h> | |
| 16 | #include <__algorithm/sift_down.h> | |
| 17 | #include <__algorithm/sort_heap.h> | |
| 18 | #include <__iterator/iterator_traits.h> | |
| 19 | #include <type_traits> // swap | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | template <class _Compare, class _InputIterator, class _RandomAccessIterator> | |
| 31 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator | |
| 32 | __partial_sort_copy(_InputIterator __first, _InputIterator __last, | |
| 33 | _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) | |
| 34 | { | |
| 35 | _RandomAccessIterator __r = __result_first; | |
| 36 | if (__r != __result_last) | |
| 37 | { | |
| 38 | for (; __first != __last && __r != __result_last; ++__first, (void) ++__r) | |
| 39 | *__r = *__first; | |
| 40 | _VSTD::__make_heap<_Compare>(__result_first, __r, __comp); | |
| 41 | typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first; | |
| 42 | for (; __first != __last; ++__first) | |
| 43 | if (__comp(*__first, *__result_first)) | |
| 44 | { | |
| 45 | *__result_first = *__first; | |
| 46 | _VSTD::__sift_down<_Compare>(__result_first, __r, __comp, __len, __result_first); | |
| 47 | } | |
| 48 | _VSTD::__sort_heap<_Compare>(__result_first, __r, __comp); | |
| 49 | } | |
| 50 | return __r; | |
| 51 | } | |
| 52 | ||
| 53 | template <class _InputIterator, class _RandomAccessIterator, class _Compare> | |
| 54 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 55 | _RandomAccessIterator | |
| 56 | partial_sort_copy(_InputIterator __first, _InputIterator __last, | |
| 57 | _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) | |
| 58 | { | |
| 59 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 60 | return _VSTD::__partial_sort_copy<_Comp_ref>(__first, __last, __result_first, __result_last, __comp); | |
| 61 | } | |
| 62 | ||
| 63 | template <class _InputIterator, class _RandomAccessIterator> | |
| 64 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 65 | _RandomAccessIterator | |
| 66 | partial_sort_copy(_InputIterator __first, _InputIterator __last, | |
| 67 | _RandomAccessIterator __result_first, _RandomAccessIterator __result_last) | |
| 68 | { | |
| 69 | return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, | |
| 70 | __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 71 | } | |
| 72 | ||
| 73 | _LIBCPP_END_NAMESPACE_STD | |
| 74 | ||
| 75 | _LIBCPP_POP_MACROS | |
| 76 | ||
| 77 | #endif // _LIBCPP___ALGORITHM_PARTIAL_SORT_COPY_H |
lib/libcxx/include/__algorithm/partition.h created+88| ... | ... | @@ -0,0 +1,88 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_PARTITION_H | |
| 10 | #define _LIBCPP___ALGORITHM_PARTITION_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/iterator_traits.h> | |
| 14 | #include <__utility/swap.h> | |
| 15 | #include <utility> // pair | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Predicate, class _ForwardIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 29 | __partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) | |
| 30 | { | |
| 31 | while (true) | |
| 32 | { | |
| 33 | if (__first == __last) | |
| 34 | return __first; | |
| 35 | if (!__pred(*__first)) | |
| 36 | break; | |
| 37 | ++__first; | |
| 38 | } | |
| 39 | for (_ForwardIterator __p = __first; ++__p != __last;) | |
| 40 | { | |
| 41 | if (__pred(*__p)) | |
| 42 | { | |
| 43 | swap(*__first, *__p); | |
| 44 | ++__first; | |
| 45 | } | |
| 46 | } | |
| 47 | return __first; | |
| 48 | } | |
| 49 | ||
| 50 | template <class _Predicate, class _BidirectionalIterator> | |
| 51 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator | |
| 52 | __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, | |
| 53 | bidirectional_iterator_tag) | |
| 54 | { | |
| 55 | while (true) | |
| 56 | { | |
| 57 | while (true) | |
| 58 | { | |
| 59 | if (__first == __last) | |
| 60 | return __first; | |
| 61 | if (!__pred(*__first)) | |
| 62 | break; | |
| 63 | ++__first; | |
| 64 | } | |
| 65 | do | |
| 66 | { | |
| 67 | if (__first == --__last) | |
| 68 | return __first; | |
| 69 | } while (!__pred(*__last)); | |
| 70 | swap(*__first, *__last); | |
| 71 | ++__first; | |
| 72 | } | |
| 73 | } | |
| 74 | ||
| 75 | template <class _ForwardIterator, class _Predicate> | |
| 76 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 77 | _ForwardIterator | |
| 78 | partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 79 | { | |
| 80 | return _VSTD::__partition<typename add_lvalue_reference<_Predicate>::type> | |
| 81 | (__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 82 | } | |
| 83 | ||
| 84 | _LIBCPP_END_NAMESPACE_STD | |
| 85 | ||
| 86 | _LIBCPP_POP_MACROS | |
| 87 | ||
| 88 | #endif // _LIBCPP___ALGORITHM_PARTITION_H |
lib/libcxx/include/__algorithm/partition_copy.h created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_PARTITION_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_PARTITION_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/iterator_traits.h> | |
| 14 | #include <utility> // pair | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _InputIterator, class _OutputIterator1, | |
| 26 | class _OutputIterator2, class _Predicate> | |
| 27 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_OutputIterator1, _OutputIterator2> | |
| 28 | partition_copy(_InputIterator __first, _InputIterator __last, | |
| 29 | _OutputIterator1 __out_true, _OutputIterator2 __out_false, | |
| 30 | _Predicate __pred) | |
| 31 | { | |
| 32 | for (; __first != __last; ++__first) | |
| 33 | { | |
| 34 | if (__pred(*__first)) | |
| 35 | { | |
| 36 | *__out_true = *__first; | |
| 37 | ++__out_true; | |
| 38 | } | |
| 39 | else | |
| 40 | { | |
| 41 | *__out_false = *__first; | |
| 42 | ++__out_false; | |
| 43 | } | |
| 44 | } | |
| 45 | return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); | |
| 46 | } | |
| 47 | ||
| 48 | _LIBCPP_END_NAMESPACE_STD | |
| 49 | ||
| 50 | _LIBCPP_POP_MACROS | |
| 51 | ||
| 52 | #endif // _LIBCPP___ALGORITHM_PARTITION_COPY_H |
lib/libcxx/include/__algorithm/partition_point.h created+51| ... | ... | @@ -0,0 +1,51 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_PARTITION_POINT_H | |
| 10 | #define _LIBCPP___ALGORITHM_PARTITION_POINT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/half_positive.h> | |
| 14 | #include <iterator> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template<class _ForwardIterator, class _Predicate> | |
| 26 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 27 | partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 28 | { | |
| 29 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 30 | difference_type __len = _VSTD::distance(__first, __last); | |
| 31 | while (__len != 0) | |
| 32 | { | |
| 33 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 34 | _ForwardIterator __m = __first; | |
| 35 | _VSTD::advance(__m, __l2); | |
| 36 | if (__pred(*__m)) | |
| 37 | { | |
| 38 | __first = ++__m; | |
| 39 | __len -= __l2 + 1; | |
| 40 | } | |
| 41 | else | |
| 42 | __len = __l2; | |
| 43 | } | |
| 44 | return __first; | |
| 45 | } | |
| 46 | ||
| 47 | _LIBCPP_END_NAMESPACE_STD | |
| 48 | ||
| 49 | _LIBCPP_POP_MACROS | |
| 50 | ||
| 51 | #endif // _LIBCPP___ALGORITHM_PARTITION_POINT_H |
lib/libcxx/include/__algorithm/pop_heap.h created+62| ... | ... | @@ -0,0 +1,62 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_POP_HEAP_H | |
| 10 | #define _LIBCPP___ALGORITHM_POP_HEAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/sift_down.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <__utility/swap.h> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _Compare, class _RandomAccessIterator> | |
| 29 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 30 | void | |
| 31 | __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 32 | typename iterator_traits<_RandomAccessIterator>::difference_type __len) | |
| 33 | { | |
| 34 | if (__len > 1) | |
| 35 | { | |
| 36 | swap(*__first, *--__last); | |
| 37 | _VSTD::__sift_down<_Compare>(__first, __last, __comp, __len - 1, __first); | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | template <class _RandomAccessIterator, class _Compare> | |
| 42 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 43 | void | |
| 44 | pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 45 | { | |
| 46 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 47 | _VSTD::__pop_heap<_Comp_ref>(__first, __last, __comp, __last - __first); | |
| 48 | } | |
| 49 | ||
| 50 | template <class _RandomAccessIterator> | |
| 51 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 52 | void | |
| 53 | pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 54 | { | |
| 55 | _VSTD::pop_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 56 | } | |
| 57 | ||
| 58 | _LIBCPP_END_NAMESPACE_STD | |
| 59 | ||
| 60 | _LIBCPP_POP_MACROS | |
| 61 | ||
| 62 | #endif // _LIBCPP___ALGORITHM_POP_HEAP_H |
lib/libcxx/include/__algorithm/prev_permutation.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_PREV_PERMUTATION_H | |
| 10 | #define _LIBCPP___ALGORITHM_PREV_PERMUTATION_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/reverse.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <__utility/swap.h> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _Compare, class _BidirectionalIterator> | |
| 29 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 30 | __prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 31 | { | |
| 32 | _BidirectionalIterator __i = __last; | |
| 33 | if (__first == __last || __first == --__i) | |
| 34 | return false; | |
| 35 | while (true) | |
| 36 | { | |
| 37 | _BidirectionalIterator __ip1 = __i; | |
| 38 | if (__comp(*__ip1, *--__i)) | |
| 39 | { | |
| 40 | _BidirectionalIterator __j = __last; | |
| 41 | while (!__comp(*--__j, *__i)) | |
| 42 | ; | |
| 43 | swap(*__i, *__j); | |
| 44 | _VSTD::reverse(__ip1, __last); | |
| 45 | return true; | |
| 46 | } | |
| 47 | if (__i == __first) | |
| 48 | { | |
| 49 | _VSTD::reverse(__first, __last); | |
| 50 | return false; | |
| 51 | } | |
| 52 | } | |
| 53 | } | |
| 54 | ||
| 55 | template <class _BidirectionalIterator, class _Compare> | |
| 56 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 57 | bool | |
| 58 | prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 59 | { | |
| 60 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 61 | return _VSTD::__prev_permutation<_Comp_ref>(__first, __last, __comp); | |
| 62 | } | |
| 63 | ||
| 64 | template <class _BidirectionalIterator> | |
| 65 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 66 | bool | |
| 67 | prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 68 | { | |
| 69 | return _VSTD::prev_permutation(__first, __last, | |
| 70 | __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); | |
| 71 | } | |
| 72 | ||
| 73 | _LIBCPP_END_NAMESPACE_STD | |
| 74 | ||
| 75 | _LIBCPP_POP_MACROS | |
| 76 | ||
| 77 | #endif // _LIBCPP___ALGORITHM_PREV_PERMUTATION_H |
lib/libcxx/include/__algorithm/push_heap.h created+75| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_PUSH_HEAP_H | |
| 10 | #define _LIBCPP___ALGORITHM_PUSH_HEAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__utility/move.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Compare, class _RandomAccessIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX11 void | |
| 29 | __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 30 | typename iterator_traits<_RandomAccessIterator>::difference_type __len) | |
| 31 | { | |
| 32 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 33 | if (__len > 1) | |
| 34 | { | |
| 35 | __len = (__len - 2) / 2; | |
| 36 | _RandomAccessIterator __ptr = __first + __len; | |
| 37 | if (__comp(*__ptr, *--__last)) | |
| 38 | { | |
| 39 | value_type __t(_VSTD::move(*__last)); | |
| 40 | do | |
| 41 | { | |
| 42 | *__last = _VSTD::move(*__ptr); | |
| 43 | __last = __ptr; | |
| 44 | if (__len == 0) | |
| 45 | break; | |
| 46 | __len = (__len - 1) / 2; | |
| 47 | __ptr = __first + __len; | |
| 48 | } while (__comp(*__ptr, __t)); | |
| 49 | *__last = _VSTD::move(__t); | |
| 50 | } | |
| 51 | } | |
| 52 | } | |
| 53 | ||
| 54 | template <class _RandomAccessIterator, class _Compare> | |
| 55 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 56 | void | |
| 57 | push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 58 | { | |
| 59 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 60 | _VSTD::__sift_up<_Comp_ref>(__first, __last, __comp, __last - __first); | |
| 61 | } | |
| 62 | ||
| 63 | template <class _RandomAccessIterator> | |
| 64 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 65 | void | |
| 66 | push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 67 | { | |
| 68 | _VSTD::push_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 69 | } | |
| 70 | ||
| 71 | _LIBCPP_END_NAMESPACE_STD | |
| 72 | ||
| 73 | _LIBCPP_POP_MACROS | |
| 74 | ||
| 75 | #endif // _LIBCPP___ALGORITHM_PUSH_HEAP_H |
lib/libcxx/include/__algorithm/remove.h created+50| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REMOVE_H | |
| 10 | #define _LIBCPP___ALGORITHM_REMOVE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/find.h> | |
| 14 | #include <__algorithm/find_if.h> | |
| 15 | #include <__utility/move.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator, class _Tp> | |
| 27 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 28 | remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 29 | { | |
| 30 | __first = _VSTD::find(__first, __last, __value_); | |
| 31 | if (__first != __last) | |
| 32 | { | |
| 33 | _ForwardIterator __i = __first; | |
| 34 | while (++__i != __last) | |
| 35 | { | |
| 36 | if (!(*__i == __value_)) | |
| 37 | { | |
| 38 | *__first = _VSTD::move(*__i); | |
| 39 | ++__first; | |
| 40 | } | |
| 41 | } | |
| 42 | } | |
| 43 | return __first; | |
| 44 | } | |
| 45 | ||
| 46 | _LIBCPP_END_NAMESPACE_STD | |
| 47 | ||
| 48 | _LIBCPP_POP_MACROS | |
| 49 | ||
| 50 | #endif // _LIBCPP___ALGORITHM_REMOVE_H |
lib/libcxx/include/__algorithm/remove_copy.h created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REMOVE_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_REMOVE_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _InputIterator, class _OutputIterator, class _Tp> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | _OutputIterator | |
| 26 | remove_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, const _Tp& __value_) | |
| 27 | { | |
| 28 | for (; __first != __last; ++__first) | |
| 29 | { | |
| 30 | if (!(*__first == __value_)) | |
| 31 | { | |
| 32 | *__result = *__first; | |
| 33 | ++__result; | |
| 34 | } | |
| 35 | } | |
| 36 | return __result; | |
| 37 | } | |
| 38 | ||
| 39 | _LIBCPP_END_NAMESPACE_STD | |
| 40 | ||
| 41 | _LIBCPP_POP_MACROS | |
| 42 | ||
| 43 | #endif // _LIBCPP___ALGORITHM_REMOVE_COPY_H |
lib/libcxx/include/__algorithm/remove_copy_if.h created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REMOVE_COPY_IF_H | |
| 10 | #define _LIBCPP___ALGORITHM_REMOVE_COPY_IF_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _InputIterator, class _OutputIterator, class _Predicate> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | _OutputIterator | |
| 26 | remove_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) | |
| 27 | { | |
| 28 | for (; __first != __last; ++__first) | |
| 29 | { | |
| 30 | if (!__pred(*__first)) | |
| 31 | { | |
| 32 | *__result = *__first; | |
| 33 | ++__result; | |
| 34 | } | |
| 35 | } | |
| 36 | return __result; | |
| 37 | } | |
| 38 | ||
| 39 | _LIBCPP_END_NAMESPACE_STD | |
| 40 | ||
| 41 | _LIBCPP_POP_MACROS | |
| 42 | ||
| 43 | #endif // _LIBCPP___ALGORITHM_REMOVE_COPY_IF_H |
lib/libcxx/include/__algorithm/remove_if.h created+51| ... | ... | @@ -0,0 +1,51 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REMOVE_IF_H | |
| 10 | #define _LIBCPP___ALGORITHM_REMOVE_IF_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/find_if.h> | |
| 14 | #include <utility> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator, class _Predicate> | |
| 27 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 28 | remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 29 | { | |
| 30 | __first = _VSTD::find_if<_ForwardIterator, typename add_lvalue_reference<_Predicate>::type> | |
| 31 | (__first, __last, __pred); | |
| 32 | if (__first != __last) | |
| 33 | { | |
| 34 | _ForwardIterator __i = __first; | |
| 35 | while (++__i != __last) | |
| 36 | { | |
| 37 | if (!__pred(*__i)) | |
| 38 | { | |
| 39 | *__first = _VSTD::move(*__i); | |
| 40 | ++__first; | |
| 41 | } | |
| 42 | } | |
| 43 | } | |
| 44 | return __first; | |
| 45 | } | |
| 46 | ||
| 47 | _LIBCPP_END_NAMESPACE_STD | |
| 48 | ||
| 49 | _LIBCPP_POP_MACROS | |
| 50 | ||
| 51 | #endif // _LIBCPP___ALGORITHM_REMOVE_IF_H |
lib/libcxx/include/__algorithm/replace.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REPLACE_H | |
| 10 | #define _LIBCPP___ALGORITHM_REPLACE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _ForwardIterator, class _Tp> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | void | |
| 26 | replace(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __old_value, const _Tp& __new_value) | |
| 27 | { | |
| 28 | for (; __first != __last; ++__first) | |
| 29 | if (*__first == __old_value) | |
| 30 | *__first = __new_value; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_REPLACE_H |
lib/libcxx/include/__algorithm/replace_copy.h created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REPLACE_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_REPLACE_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _InputIterator, class _OutputIterator, class _Tp> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | _OutputIterator | |
| 26 | replace_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, | |
| 27 | const _Tp& __old_value, const _Tp& __new_value) | |
| 28 | { | |
| 29 | for (; __first != __last; ++__first, (void) ++__result) | |
| 30 | if (*__first == __old_value) | |
| 31 | *__result = __new_value; | |
| 32 | else | |
| 33 | *__result = *__first; | |
| 34 | return __result; | |
| 35 | } | |
| 36 | ||
| 37 | _LIBCPP_END_NAMESPACE_STD | |
| 38 | ||
| 39 | _LIBCPP_POP_MACROS | |
| 40 | ||
| 41 | #endif // _LIBCPP___ALGORITHM_REPLACE_COPY_H |
lib/libcxx/include/__algorithm/replace_copy_if.h created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REPLACE_COPY_IF_H | |
| 10 | #define _LIBCPP___ALGORITHM_REPLACE_COPY_IF_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _InputIterator, class _OutputIterator, class _Predicate, class _Tp> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | _OutputIterator | |
| 26 | replace_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, | |
| 27 | _Predicate __pred, const _Tp& __new_value) | |
| 28 | { | |
| 29 | for (; __first != __last; ++__first, (void) ++__result) | |
| 30 | if (__pred(*__first)) | |
| 31 | *__result = __new_value; | |
| 32 | else | |
| 33 | *__result = *__first; | |
| 34 | return __result; | |
| 35 | } | |
| 36 | ||
| 37 | _LIBCPP_END_NAMESPACE_STD | |
| 38 | ||
| 39 | _LIBCPP_POP_MACROS | |
| 40 | ||
| 41 | #endif // _LIBCPP___ALGORITHM_REPLACE_COPY_IF_H |
lib/libcxx/include/__algorithm/replace_if.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REPLACE_IF_H | |
| 10 | #define _LIBCPP___ALGORITHM_REPLACE_IF_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _ForwardIterator, class _Predicate, class _Tp> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | void | |
| 26 | replace_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, const _Tp& __new_value) | |
| 27 | { | |
| 28 | for (; __first != __last; ++__first) | |
| 29 | if (__pred(*__first)) | |
| 30 | *__first = __new_value; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_REPLACE_IF_H |
lib/libcxx/include/__algorithm/reverse.h created+61| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REVERSE_H | |
| 10 | #define _LIBCPP___ALGORITHM_REVERSE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/iter_swap.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _BidirectionalIterator> | |
| 26 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 27 | void | |
| 28 | __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag) | |
| 29 | { | |
| 30 | while (__first != __last) | |
| 31 | { | |
| 32 | if (__first == --__last) | |
| 33 | break; | |
| 34 | _VSTD::iter_swap(__first, __last); | |
| 35 | ++__first; | |
| 36 | } | |
| 37 | } | |
| 38 | ||
| 39 | template <class _RandomAccessIterator> | |
| 40 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 41 | void | |
| 42 | __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) | |
| 43 | { | |
| 44 | if (__first != __last) | |
| 45 | for (; __first < --__last; ++__first) | |
| 46 | _VSTD::iter_swap(__first, __last); | |
| 47 | } | |
| 48 | ||
| 49 | template <class _BidirectionalIterator> | |
| 50 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 51 | void | |
| 52 | reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 53 | { | |
| 54 | _VSTD::__reverse(__first, __last, typename iterator_traits<_BidirectionalIterator>::iterator_category()); | |
| 55 | } | |
| 56 | ||
| 57 | _LIBCPP_END_NAMESPACE_STD | |
| 58 | ||
| 59 | _LIBCPP_POP_MACROS | |
| 60 | ||
| 61 | #endif // _LIBCPP___ALGORITHM_REVERSE_H |
lib/libcxx/include/__algorithm/reverse_copy.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_REVERSE_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_REVERSE_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _BidirectionalIterator, class _OutputIterator> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | _OutputIterator | |
| 26 | reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) | |
| 27 | { | |
| 28 | for (; __first != __last; ++__result) | |
| 29 | *__result = *--__last; | |
| 30 | return __result; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_REVERSE_COPY_H |
lib/libcxx/include/__algorithm/rotate.h created+205| ... | ... | @@ -0,0 +1,205 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_ROTATE_H | |
| 10 | #define _LIBCPP___ALGORITHM_ROTATE_H | |
| 11 | ||
| 12 | #include <__algorithm/move.h> | |
| 13 | #include <__algorithm/move_backward.h> | |
| 14 | #include <__algorithm/swap_ranges.h> | |
| 15 | #include <__config> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <__iterator/next.h> | |
| 18 | #include <__iterator/prev.h> | |
| 19 | #include <__utility/swap.h> | |
| 20 | #include <iterator> | |
| 21 | ||
| 22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 23 | #pragma GCC system_header | |
| 24 | #endif | |
| 25 | ||
| 26 | _LIBCPP_PUSH_MACROS | |
| 27 | #include <__undef_macros> | |
| 28 | ||
| 29 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 30 | ||
| 31 | template <class _ForwardIterator> | |
| 32 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator | |
| 33 | __rotate_left(_ForwardIterator __first, _ForwardIterator __last) | |
| 34 | { | |
| 35 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 36 | value_type __tmp = _VSTD::move(*__first); | |
| 37 | _ForwardIterator __lm1 = _VSTD::move(_VSTD::next(__first), __last, __first); | |
| 38 | *__lm1 = _VSTD::move(__tmp); | |
| 39 | return __lm1; | |
| 40 | } | |
| 41 | ||
| 42 | template <class _BidirectionalIterator> | |
| 43 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator | |
| 44 | __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 45 | { | |
| 46 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 47 | _BidirectionalIterator __lm1 = _VSTD::prev(__last); | |
| 48 | value_type __tmp = _VSTD::move(*__lm1); | |
| 49 | _BidirectionalIterator __fp1 = _VSTD::move_backward(__first, __lm1, __last); | |
| 50 | *__first = _VSTD::move(__tmp); | |
| 51 | return __fp1; | |
| 52 | } | |
| 53 | ||
| 54 | template <class _ForwardIterator> | |
| 55 | _LIBCPP_CONSTEXPR_AFTER_CXX14 _ForwardIterator | |
| 56 | __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) | |
| 57 | { | |
| 58 | _ForwardIterator __i = __middle; | |
| 59 | while (true) | |
| 60 | { | |
| 61 | swap(*__first, *__i); | |
| 62 | ++__first; | |
| 63 | if (++__i == __last) | |
| 64 | break; | |
| 65 | if (__first == __middle) | |
| 66 | __middle = __i; | |
| 67 | } | |
| 68 | _ForwardIterator __r = __first; | |
| 69 | if (__first != __middle) | |
| 70 | { | |
| 71 | __i = __middle; | |
| 72 | while (true) | |
| 73 | { | |
| 74 | swap(*__first, *__i); | |
| 75 | ++__first; | |
| 76 | if (++__i == __last) | |
| 77 | { | |
| 78 | if (__first == __middle) | |
| 79 | break; | |
| 80 | __i = __middle; | |
| 81 | } | |
| 82 | else if (__first == __middle) | |
| 83 | __middle = __i; | |
| 84 | } | |
| 85 | } | |
| 86 | return __r; | |
| 87 | } | |
| 88 | ||
| 89 | template<typename _Integral> | |
| 90 | inline _LIBCPP_INLINE_VISIBILITY | |
| 91 | _LIBCPP_CONSTEXPR_AFTER_CXX14 _Integral | |
| 92 | __algo_gcd(_Integral __x, _Integral __y) | |
| 93 | { | |
| 94 | do | |
| 95 | { | |
| 96 | _Integral __t = __x % __y; | |
| 97 | __x = __y; | |
| 98 | __y = __t; | |
| 99 | } while (__y); | |
| 100 | return __x; | |
| 101 | } | |
| 102 | ||
| 103 | template<typename _RandomAccessIterator> | |
| 104 | _LIBCPP_CONSTEXPR_AFTER_CXX14 _RandomAccessIterator | |
| 105 | __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) | |
| 106 | { | |
| 107 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 108 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 109 | ||
| 110 | const difference_type __m1 = __middle - __first; | |
| 111 | const difference_type __m2 = __last - __middle; | |
| 112 | if (__m1 == __m2) | |
| 113 | { | |
| 114 | _VSTD::swap_ranges(__first, __middle, __middle); | |
| 115 | return __middle; | |
| 116 | } | |
| 117 | const difference_type __g = _VSTD::__algo_gcd(__m1, __m2); | |
| 118 | for (_RandomAccessIterator __p = __first + __g; __p != __first;) | |
| 119 | { | |
| 120 | value_type __t(_VSTD::move(*--__p)); | |
| 121 | _RandomAccessIterator __p1 = __p; | |
| 122 | _RandomAccessIterator __p2 = __p1 + __m1; | |
| 123 | do | |
| 124 | { | |
| 125 | *__p1 = _VSTD::move(*__p2); | |
| 126 | __p1 = __p2; | |
| 127 | const difference_type __d = __last - __p2; | |
| 128 | if (__m1 < __d) | |
| 129 | __p2 += __m1; | |
| 130 | else | |
| 131 | __p2 = __first + (__m1 - __d); | |
| 132 | } while (__p2 != __p); | |
| 133 | *__p1 = _VSTD::move(__t); | |
| 134 | } | |
| 135 | return __first + __m2; | |
| 136 | } | |
| 137 | ||
| 138 | template <class _ForwardIterator> | |
| 139 | inline _LIBCPP_INLINE_VISIBILITY | |
| 140 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator | |
| 141 | __rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, | |
| 142 | _VSTD::forward_iterator_tag) | |
| 143 | { | |
| 144 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 145 | if (is_trivially_move_assignable<value_type>::value) | |
| 146 | { | |
| 147 | if (_VSTD::next(__first) == __middle) | |
| 148 | return _VSTD::__rotate_left(__first, __last); | |
| 149 | } | |
| 150 | return _VSTD::__rotate_forward(__first, __middle, __last); | |
| 151 | } | |
| 152 | ||
| 153 | template <class _BidirectionalIterator> | |
| 154 | inline _LIBCPP_INLINE_VISIBILITY | |
| 155 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator | |
| 156 | __rotate(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 157 | bidirectional_iterator_tag) | |
| 158 | { | |
| 159 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 160 | if (is_trivially_move_assignable<value_type>::value) | |
| 161 | { | |
| 162 | if (_VSTD::next(__first) == __middle) | |
| 163 | return _VSTD::__rotate_left(__first, __last); | |
| 164 | if (_VSTD::next(__middle) == __last) | |
| 165 | return _VSTD::__rotate_right(__first, __last); | |
| 166 | } | |
| 167 | return _VSTD::__rotate_forward(__first, __middle, __last); | |
| 168 | } | |
| 169 | ||
| 170 | template <class _RandomAccessIterator> | |
| 171 | inline _LIBCPP_INLINE_VISIBILITY | |
| 172 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator | |
| 173 | __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, | |
| 174 | random_access_iterator_tag) | |
| 175 | { | |
| 176 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 177 | if (is_trivially_move_assignable<value_type>::value) | |
| 178 | { | |
| 179 | if (_VSTD::next(__first) == __middle) | |
| 180 | return _VSTD::__rotate_left(__first, __last); | |
| 181 | if (_VSTD::next(__middle) == __last) | |
| 182 | return _VSTD::__rotate_right(__first, __last); | |
| 183 | return _VSTD::__rotate_gcd(__first, __middle, __last); | |
| 184 | } | |
| 185 | return _VSTD::__rotate_forward(__first, __middle, __last); | |
| 186 | } | |
| 187 | ||
| 188 | template <class _ForwardIterator> | |
| 189 | inline _LIBCPP_INLINE_VISIBILITY | |
| 190 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 191 | rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) | |
| 192 | { | |
| 193 | if (__first == __middle) | |
| 194 | return __last; | |
| 195 | if (__middle == __last) | |
| 196 | return __first; | |
| 197 | return _VSTD::__rotate(__first, __middle, __last, | |
| 198 | typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 199 | } | |
| 200 | ||
| 201 | _LIBCPP_END_NAMESPACE_STD | |
| 202 | ||
| 203 | _LIBCPP_POP_MACROS | |
| 204 | ||
| 205 | #endif // _LIBCPP___ALGORITHM_ROTATE_H |
lib/libcxx/include/__algorithm/rotate_copy.h created+38| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_ROTATE_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_ROTATE_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/copy.h> | |
| 14 | #include <iterator> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _ForwardIterator, class _OutputIterator> | |
| 27 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 28 | _OutputIterator | |
| 29 | rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, _OutputIterator __result) | |
| 30 | { | |
| 31 | return _VSTD::copy(__first, __middle, _VSTD::copy(__middle, __last, __result)); | |
| 32 | } | |
| 33 | ||
| 34 | _LIBCPP_END_NAMESPACE_STD | |
| 35 | ||
| 36 | _LIBCPP_POP_MACROS | |
| 37 | ||
| 38 | #endif // _LIBCPP___ALGORITHM_ROTATE_COPY_H |
lib/libcxx/include/__algorithm/sample.h created+101| ... | ... | @@ -0,0 +1,101 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SAMPLE_H | |
| 10 | #define _LIBCPP___ALGORITHM_SAMPLE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/min.h> | |
| 14 | #include <__random/uniform_int_distribution.h> | |
| 15 | #include <iterator> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 27 | class _UniformRandomNumberGenerator> | |
| 28 | _LIBCPP_INLINE_VISIBILITY | |
| 29 | _SampleIterator __sample(_PopulationIterator __first, | |
| 30 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 31 | _Distance __n, | |
| 32 | _UniformRandomNumberGenerator & __g, | |
| 33 | input_iterator_tag) { | |
| 34 | ||
| 35 | _Distance __k = 0; | |
| 36 | for (; __first != __last && __k < __n; ++__first, (void) ++__k) | |
| 37 | __output_iter[__k] = *__first; | |
| 38 | _Distance __sz = __k; | |
| 39 | for (; __first != __last; ++__first, (void) ++__k) { | |
| 40 | _Distance __r = uniform_int_distribution<_Distance>(0, __k)(__g); | |
| 41 | if (__r < __sz) | |
| 42 | __output_iter[__r] = *__first; | |
| 43 | } | |
| 44 | return __output_iter + _VSTD::min(__n, __k); | |
| 45 | } | |
| 46 | ||
| 47 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 48 | class _UniformRandomNumberGenerator> | |
| 49 | _LIBCPP_INLINE_VISIBILITY | |
| 50 | _SampleIterator __sample(_PopulationIterator __first, | |
| 51 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 52 | _Distance __n, | |
| 53 | _UniformRandomNumberGenerator& __g, | |
| 54 | forward_iterator_tag) { | |
| 55 | _Distance __unsampled_sz = _VSTD::distance(__first, __last); | |
| 56 | for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) { | |
| 57 | _Distance __r = uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g); | |
| 58 | if (__r < __n) { | |
| 59 | *__output_iter++ = *__first; | |
| 60 | --__n; | |
| 61 | } | |
| 62 | } | |
| 63 | return __output_iter; | |
| 64 | } | |
| 65 | ||
| 66 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 67 | class _UniformRandomNumberGenerator> | |
| 68 | _LIBCPP_INLINE_VISIBILITY | |
| 69 | _SampleIterator __sample(_PopulationIterator __first, | |
| 70 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 71 | _Distance __n, _UniformRandomNumberGenerator& __g) { | |
| 72 | typedef typename iterator_traits<_PopulationIterator>::iterator_category | |
| 73 | _PopCategory; | |
| 74 | typedef typename iterator_traits<_PopulationIterator>::difference_type | |
| 75 | _Difference; | |
| 76 | static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || | |
| 77 | __is_cpp17_random_access_iterator<_SampleIterator>::value, | |
| 78 | "SampleIterator must meet the requirements of RandomAccessIterator"); | |
| 79 | typedef typename common_type<_Distance, _Difference>::type _CommonType; | |
| 80 | _LIBCPP_ASSERT(__n >= 0, "N must be a positive number."); | |
| 81 | return _VSTD::__sample( | |
| 82 | __first, __last, __output_iter, _CommonType(__n), | |
| 83 | __g, _PopCategory()); | |
| 84 | } | |
| 85 | ||
| 86 | #if _LIBCPP_STD_VER > 14 | |
| 87 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 88 | class _UniformRandomNumberGenerator> | |
| 89 | inline _LIBCPP_INLINE_VISIBILITY | |
| 90 | _SampleIterator sample(_PopulationIterator __first, | |
| 91 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 92 | _Distance __n, _UniformRandomNumberGenerator&& __g) { | |
| 93 | return _VSTD::__sample(__first, __last, __output_iter, __n, __g); | |
| 94 | } | |
| 95 | #endif // _LIBCPP_STD_VER > 14 | |
| 96 | ||
| 97 | _LIBCPP_END_NAMESPACE_STD | |
| 98 | ||
| 99 | _LIBCPP_POP_MACROS | |
| 100 | ||
| 101 | #endif // _LIBCPP___ALGORITHM_SAMPLE_H |
lib/libcxx/include/__algorithm/search.h created+131| ... | ... | @@ -0,0 +1,131 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_SEARCH_H | |
| 11 | #define _LIBCPP___ALGORITHM_SEARCH_H | |
| 12 | ||
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__config> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <type_traits> | |
| 17 | #include <utility> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2> | |
| 29 | pair<_ForwardIterator1, _ForwardIterator1> | |
| 30 | _LIBCPP_CONSTEXPR_AFTER_CXX11 __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 31 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, | |
| 32 | _BinaryPredicate __pred, forward_iterator_tag, forward_iterator_tag) { | |
| 33 | if (__first2 == __last2) | |
| 34 | return _VSTD::make_pair(__first1, __first1); // Everything matches an empty sequence | |
| 35 | while (true) { | |
| 36 | // Find first element in sequence 1 that matchs *__first2, with a mininum of loop checks | |
| 37 | while (true) { | |
| 38 | if (__first1 == __last1) // return __last1 if no element matches *__first2 | |
| 39 | return _VSTD::make_pair(__last1, __last1); | |
| 40 | if (__pred(*__first1, *__first2)) | |
| 41 | break; | |
| 42 | ++__first1; | |
| 43 | } | |
| 44 | // *__first1 matches *__first2, now match elements after here | |
| 45 | _ForwardIterator1 __m1 = __first1; | |
| 46 | _ForwardIterator2 __m2 = __first2; | |
| 47 | while (true) { | |
| 48 | if (++__m2 == __last2) // If pattern exhausted, __first1 is the answer (works for 1 element pattern) | |
| 49 | return _VSTD::make_pair(__first1, __m1); | |
| 50 | if (++__m1 == __last1) // Otherwise if source exhaused, pattern not found | |
| 51 | return _VSTD::make_pair(__last1, __last1); | |
| 52 | if (!__pred(*__m1, *__m2)) // if there is a mismatch, restart with a new __first1 | |
| 53 | { | |
| 54 | ++__first1; | |
| 55 | break; | |
| 56 | } // else there is a match, check next elements | |
| 57 | } | |
| 58 | } | |
| 59 | } | |
| 60 | ||
| 61 | template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 62 | _LIBCPP_CONSTEXPR_AFTER_CXX11 pair<_RandomAccessIterator1, _RandomAccessIterator1> | |
| 63 | __search(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, | |
| 64 | _RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag, | |
| 65 | random_access_iterator_tag) { | |
| 66 | typedef typename iterator_traits<_RandomAccessIterator1>::difference_type _D1; | |
| 67 | typedef typename iterator_traits<_RandomAccessIterator2>::difference_type _D2; | |
| 68 | // Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern | |
| 69 | const _D2 __len2 = __last2 - __first2; | |
| 70 | if (__len2 == 0) | |
| 71 | return _VSTD::make_pair(__first1, __first1); | |
| 72 | const _D1 __len1 = __last1 - __first1; | |
| 73 | if (__len1 < __len2) | |
| 74 | return _VSTD::make_pair(__last1, __last1); | |
| 75 | const _RandomAccessIterator1 __s = __last1 - (__len2 - 1); // Start of pattern match can't go beyond here | |
| 76 | ||
| 77 | while (true) { | |
| 78 | while (true) { | |
| 79 | if (__first1 == __s) | |
| 80 | return _VSTD::make_pair(__last1, __last1); | |
| 81 | if (__pred(*__first1, *__first2)) | |
| 82 | break; | |
| 83 | ++__first1; | |
| 84 | } | |
| 85 | ||
| 86 | _RandomAccessIterator1 __m1 = __first1; | |
| 87 | _RandomAccessIterator2 __m2 = __first2; | |
| 88 | while (true) { | |
| 89 | if (++__m2 == __last2) | |
| 90 | return _VSTD::make_pair(__first1, __first1 + __len2); | |
| 91 | ++__m1; // no need to check range on __m1 because __s guarantees we have enough source | |
| 92 | if (!__pred(*__m1, *__m2)) { | |
| 93 | ++__first1; | |
| 94 | break; | |
| 95 | } | |
| 96 | } | |
| 97 | } | |
| 98 | } | |
| 99 | ||
| 100 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 101 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 | |
| 102 | search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, | |
| 103 | _BinaryPredicate __pred) { | |
| 104 | return _VSTD::__search<typename add_lvalue_reference<_BinaryPredicate>::type>( | |
| 105 | __first1, __last1, __first2, __last2, __pred, | |
| 106 | typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 107 | typename iterator_traits<_ForwardIterator2>::iterator_category()).first; | |
| 108 | } | |
| 109 | ||
| 110 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 111 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 | |
| 112 | search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { | |
| 113 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 114 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 115 | return _VSTD::search(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 116 | } | |
| 117 | ||
| 118 | #if _LIBCPP_STD_VER > 14 | |
| 119 | template <class _ForwardIterator, class _Searcher> | |
| 120 | _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 121 | search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { | |
| 122 | return __s(__f, __l).first; | |
| 123 | } | |
| 124 | ||
| 125 | #endif | |
| 126 | ||
| 127 | _LIBCPP_END_NAMESPACE_STD | |
| 128 | ||
| 129 | _LIBCPP_POP_MACROS | |
| 130 | ||
| 131 | #endif // _LIBCPP___ALGORITHM_SEARCH_H |
lib/libcxx/include/__algorithm/search_n.h created+116| ... | ... | @@ -0,0 +1,116 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ALGORITHM_SEARCH_N_H | |
| 11 | #define _LIBCPP___ALGORITHM_SEARCH_N_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__algorithm/comp.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _BinaryPredicate, class _ForwardIterator, class _Size, class _Tp> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator __search_n(_ForwardIterator __first, _ForwardIterator __last, | |
| 29 | _Size __count, const _Tp& __value_, _BinaryPredicate __pred, | |
| 30 | forward_iterator_tag) { | |
| 31 | if (__count <= 0) | |
| 32 | return __first; | |
| 33 | while (true) { | |
| 34 | // Find first element in sequence that matchs __value_, with a mininum of loop checks | |
| 35 | while (true) { | |
| 36 | if (__first == __last) // return __last if no element matches __value_ | |
| 37 | return __last; | |
| 38 | if (__pred(*__first, __value_)) | |
| 39 | break; | |
| 40 | ++__first; | |
| 41 | } | |
| 42 | // *__first matches __value_, now match elements after here | |
| 43 | _ForwardIterator __m = __first; | |
| 44 | _Size __c(0); | |
| 45 | while (true) { | |
| 46 | if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern) | |
| 47 | return __first; | |
| 48 | if (++__m == __last) // Otherwise if source exhaused, pattern not found | |
| 49 | return __last; | |
| 50 | if (!__pred(*__m, __value_)) // if there is a mismatch, restart with a new __first | |
| 51 | { | |
| 52 | __first = __m; | |
| 53 | ++__first; | |
| 54 | break; | |
| 55 | } // else there is a match, check next elements | |
| 56 | } | |
| 57 | } | |
| 58 | } | |
| 59 | ||
| 60 | template <class _BinaryPredicate, class _RandomAccessIterator, class _Size, class _Tp> | |
| 61 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator __search_n(_RandomAccessIterator __first, | |
| 62 | _RandomAccessIterator __last, _Size __count, | |
| 63 | const _Tp& __value_, _BinaryPredicate __pred, | |
| 64 | random_access_iterator_tag) { | |
| 65 | if (__count <= 0) | |
| 66 | return __first; | |
| 67 | _Size __len = static_cast<_Size>(__last - __first); | |
| 68 | if (__len < __count) | |
| 69 | return __last; | |
| 70 | const _RandomAccessIterator __s = __last - (__count - 1); // Start of pattern match can't go beyond here | |
| 71 | while (true) { | |
| 72 | // Find first element in sequence that matchs __value_, with a mininum of loop checks | |
| 73 | while (true) { | |
| 74 | if (__first >= __s) // return __last if no element matches __value_ | |
| 75 | return __last; | |
| 76 | if (__pred(*__first, __value_)) | |
| 77 | break; | |
| 78 | ++__first; | |
| 79 | } | |
| 80 | // *__first matches __value_, now match elements after here | |
| 81 | _RandomAccessIterator __m = __first; | |
| 82 | _Size __c(0); | |
| 83 | while (true) { | |
| 84 | if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern) | |
| 85 | return __first; | |
| 86 | ++__m; // no need to check range on __m because __s guarantees we have enough source | |
| 87 | if (!__pred(*__m, __value_)) // if there is a mismatch, restart with a new __first | |
| 88 | { | |
| 89 | __first = __m; | |
| 90 | ++__first; | |
| 91 | break; | |
| 92 | } // else there is a match, check next elements | |
| 93 | } | |
| 94 | } | |
| 95 | } | |
| 96 | ||
| 97 | template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> | |
| 98 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator search_n( | |
| 99 | _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value_, _BinaryPredicate __pred) { | |
| 100 | return _VSTD::__search_n<typename add_lvalue_reference<_BinaryPredicate>::type>( | |
| 101 | __first, __last, _VSTD::__convert_to_integral(__count), __value_, __pred, | |
| 102 | typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 103 | } | |
| 104 | ||
| 105 | template <class _ForwardIterator, class _Size, class _Tp> | |
| 106 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 107 | search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value_) { | |
| 108 | typedef typename iterator_traits<_ForwardIterator>::value_type __v; | |
| 109 | return _VSTD::search_n(__first, __last, _VSTD::__convert_to_integral(__count), __value_, __equal_to<__v, _Tp>()); | |
| 110 | } | |
| 111 | ||
| 112 | _LIBCPP_END_NAMESPACE_STD | |
| 113 | ||
| 114 | _LIBCPP_POP_MACROS | |
| 115 | ||
| 116 | #endif // _LIBCPP___ALGORITHM_SEARCH_N_H |
lib/libcxx/include/__algorithm/set_difference.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SET_DIFFERENCE_H | |
| 10 | #define _LIBCPP___ALGORITHM_SET_DIFFERENCE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/copy.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 29 | __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 30 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 31 | { | |
| 32 | while (__first1 != __last1) | |
| 33 | { | |
| 34 | if (__first2 == __last2) | |
| 35 | return _VSTD::copy(__first1, __last1, __result); | |
| 36 | if (__comp(*__first1, *__first2)) | |
| 37 | { | |
| 38 | *__result = *__first1; | |
| 39 | ++__result; | |
| 40 | ++__first1; | |
| 41 | } | |
| 42 | else | |
| 43 | { | |
| 44 | if (!__comp(*__first2, *__first1)) | |
| 45 | ++__first1; | |
| 46 | ++__first2; | |
| 47 | } | |
| 48 | } | |
| 49 | return __result; | |
| 50 | } | |
| 51 | ||
| 52 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 53 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 54 | _OutputIterator | |
| 55 | set_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 56 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 57 | { | |
| 58 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 59 | return _VSTD::__set_difference<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 60 | } | |
| 61 | ||
| 62 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 63 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 64 | _OutputIterator | |
| 65 | set_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 66 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 67 | { | |
| 68 | return _VSTD::set_difference(__first1, __last1, __first2, __last2, __result, | |
| 69 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 70 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 71 | } | |
| 72 | ||
| 73 | _LIBCPP_END_NAMESPACE_STD | |
| 74 | ||
| 75 | _LIBCPP_POP_MACROS | |
| 76 | ||
| 77 | #endif // _LIBCPP___ALGORITHM_SET_DIFFERENCE_H |
lib/libcxx/include/__algorithm/set_intersection.h created+74| ... | ... | @@ -0,0 +1,74 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SET_INTERSECTION_H | |
| 10 | #define _LIBCPP___ALGORITHM_SET_INTERSECTION_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 27 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 28 | __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 29 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 30 | { | |
| 31 | while (__first1 != __last1 && __first2 != __last2) | |
| 32 | { | |
| 33 | if (__comp(*__first1, *__first2)) | |
| 34 | ++__first1; | |
| 35 | else | |
| 36 | { | |
| 37 | if (!__comp(*__first2, *__first1)) | |
| 38 | { | |
| 39 | *__result = *__first1; | |
| 40 | ++__result; | |
| 41 | ++__first1; | |
| 42 | } | |
| 43 | ++__first2; | |
| 44 | } | |
| 45 | } | |
| 46 | return __result; | |
| 47 | } | |
| 48 | ||
| 49 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 50 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 51 | _OutputIterator | |
| 52 | set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 53 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 54 | { | |
| 55 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 56 | return _VSTD::__set_intersection<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 57 | } | |
| 58 | ||
| 59 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 60 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 61 | _OutputIterator | |
| 62 | set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 63 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 64 | { | |
| 65 | return _VSTD::set_intersection(__first1, __last1, __first2, __last2, __result, | |
| 66 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 67 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 68 | } | |
| 69 | ||
| 70 | _LIBCPP_END_NAMESPACE_STD | |
| 71 | ||
| 72 | _LIBCPP_POP_MACROS | |
| 73 | ||
| 74 | #endif // _LIBCPP___ALGORITHM_SET_INTERSECTION_H |
lib/libcxx/include/__algorithm/set_symmetric_difference.h created+82| ... | ... | @@ -0,0 +1,82 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H | |
| 10 | #define _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/copy.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 29 | __set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 30 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 31 | { | |
| 32 | while (__first1 != __last1) | |
| 33 | { | |
| 34 | if (__first2 == __last2) | |
| 35 | return _VSTD::copy(__first1, __last1, __result); | |
| 36 | if (__comp(*__first1, *__first2)) | |
| 37 | { | |
| 38 | *__result = *__first1; | |
| 39 | ++__result; | |
| 40 | ++__first1; | |
| 41 | } | |
| 42 | else | |
| 43 | { | |
| 44 | if (__comp(*__first2, *__first1)) | |
| 45 | { | |
| 46 | *__result = *__first2; | |
| 47 | ++__result; | |
| 48 | } | |
| 49 | else | |
| 50 | ++__first1; | |
| 51 | ++__first2; | |
| 52 | } | |
| 53 | } | |
| 54 | return _VSTD::copy(__first2, __last2, __result); | |
| 55 | } | |
| 56 | ||
| 57 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 58 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 59 | _OutputIterator | |
| 60 | set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 61 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 62 | { | |
| 63 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 64 | return _VSTD::__set_symmetric_difference<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 65 | } | |
| 66 | ||
| 67 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 68 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 69 | _OutputIterator | |
| 70 | set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 71 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 72 | { | |
| 73 | return _VSTD::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, | |
| 74 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 75 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 76 | } | |
| 77 | ||
| 78 | _LIBCPP_END_NAMESPACE_STD | |
| 79 | ||
| 80 | _LIBCPP_POP_MACROS | |
| 81 | ||
| 82 | #endif // _LIBCPP___ALGORITHM_SET_SYMMETRIC_DIFFERENCE_H |
lib/libcxx/include/__algorithm/set_union.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SET_UNION_H | |
| 10 | #define _LIBCPP___ALGORITHM_SET_UNION_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/copy.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 29 | __set_union(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 30 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 31 | { | |
| 32 | for (; __first1 != __last1; ++__result) | |
| 33 | { | |
| 34 | if (__first2 == __last2) | |
| 35 | return _VSTD::copy(__first1, __last1, __result); | |
| 36 | if (__comp(*__first2, *__first1)) | |
| 37 | { | |
| 38 | *__result = *__first2; | |
| 39 | ++__first2; | |
| 40 | } | |
| 41 | else | |
| 42 | { | |
| 43 | if (!__comp(*__first1, *__first2)) | |
| 44 | ++__first2; | |
| 45 | *__result = *__first1; | |
| 46 | ++__first1; | |
| 47 | } | |
| 48 | } | |
| 49 | return _VSTD::copy(__first2, __last2, __result); | |
| 50 | } | |
| 51 | ||
| 52 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 53 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 54 | _OutputIterator | |
| 55 | set_union(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 56 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 57 | { | |
| 58 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 59 | return _VSTD::__set_union<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 60 | } | |
| 61 | ||
| 62 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 63 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 64 | _OutputIterator | |
| 65 | set_union(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 66 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 67 | { | |
| 68 | return _VSTD::set_union(__first1, __last1, __first2, __last2, __result, | |
| 69 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 70 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 71 | } | |
| 72 | ||
| 73 | _LIBCPP_END_NAMESPACE_STD | |
| 74 | ||
| 75 | _LIBCPP_POP_MACROS | |
| 76 | ||
| 77 | #endif // _LIBCPP___ALGORITHM_SET_UNION_H |
lib/libcxx/include/__algorithm/shift_left.h created+61| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SHIFT_LEFT_H | |
| 10 | #define _LIBCPP___ALGORITHM_SHIFT_LEFT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/move.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <type_traits> // swap | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if _LIBCPP_STD_VER > 17 | |
| 27 | ||
| 28 | template <class _ForwardIterator> | |
| 29 | inline _LIBCPP_INLINE_VISIBILITY constexpr | |
| 30 | _ForwardIterator | |
| 31 | shift_left(_ForwardIterator __first, _ForwardIterator __last, | |
| 32 | typename iterator_traits<_ForwardIterator>::difference_type __n) | |
| 33 | { | |
| 34 | if (__n == 0) { | |
| 35 | return __last; | |
| 36 | } | |
| 37 | ||
| 38 | _ForwardIterator __m = __first; | |
| 39 | if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { | |
| 40 | if (__n >= __last - __first) { | |
| 41 | return __first; | |
| 42 | } | |
| 43 | __m += __n; | |
| 44 | } else { | |
| 45 | for (; __n > 0; --__n) { | |
| 46 | if (__m == __last) { | |
| 47 | return __first; | |
| 48 | } | |
| 49 | ++__m; | |
| 50 | } | |
| 51 | } | |
| 52 | return _VSTD::move(__m, __last, __first); | |
| 53 | } | |
| 54 | ||
| 55 | #endif // _LIBCPP_STD_VER > 17 | |
| 56 | ||
| 57 | _LIBCPP_END_NAMESPACE_STD | |
| 58 | ||
| 59 | _LIBCPP_POP_MACROS | |
| 60 | ||
| 61 | #endif // _LIBCPP___ALGORITHM_SHIFT_LEFT_H |
lib/libcxx/include/__algorithm/shift_right.h created+106| ... | ... | @@ -0,0 +1,106 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SHIFT_RIGHT_H | |
| 10 | #define _LIBCPP___ALGORITHM_SHIFT_RIGHT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/move.h> | |
| 14 | #include <__algorithm/move_backward.h> | |
| 15 | #include <__algorithm/swap_ranges.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <type_traits> // swap | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | #if _LIBCPP_STD_VER > 17 | |
| 29 | ||
| 30 | template <class _ForwardIterator> | |
| 31 | inline _LIBCPP_INLINE_VISIBILITY constexpr | |
| 32 | _ForwardIterator | |
| 33 | shift_right(_ForwardIterator __first, _ForwardIterator __last, | |
| 34 | typename iterator_traits<_ForwardIterator>::difference_type __n) | |
| 35 | { | |
| 36 | if (__n == 0) { | |
| 37 | return __first; | |
| 38 | } | |
| 39 | ||
| 40 | if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { | |
| 41 | decltype(__n) __d = __last - __first; | |
| 42 | if (__n >= __d) { | |
| 43 | return __last; | |
| 44 | } | |
| 45 | _ForwardIterator __m = __first + (__d - __n); | |
| 46 | return _VSTD::move_backward(__first, __m, __last); | |
| 47 | } else if constexpr (__is_cpp17_bidirectional_iterator<_ForwardIterator>::value) { | |
| 48 | _ForwardIterator __m = __last; | |
| 49 | for (; __n > 0; --__n) { | |
| 50 | if (__m == __first) { | |
| 51 | return __last; | |
| 52 | } | |
| 53 | --__m; | |
| 54 | } | |
| 55 | return _VSTD::move_backward(__first, __m, __last); | |
| 56 | } else { | |
| 57 | _ForwardIterator __ret = __first; | |
| 58 | for (; __n > 0; --__n) { | |
| 59 | if (__ret == __last) { | |
| 60 | return __last; | |
| 61 | } | |
| 62 | ++__ret; | |
| 63 | } | |
| 64 | ||
| 65 | // We have an __n-element scratch space from __first to __ret. | |
| 66 | // Slide an __n-element window [__trail, __lead) from left to right. | |
| 67 | // We're essentially doing swap_ranges(__first, __ret, __trail, __lead) | |
| 68 | // over and over; but once __lead reaches __last we needn't bother | |
| 69 | // to save the values of elements [__trail, __last). | |
| 70 | ||
| 71 | auto __trail = __first; | |
| 72 | auto __lead = __ret; | |
| 73 | while (__trail != __ret) { | |
| 74 | if (__lead == __last) { | |
| 75 | _VSTD::move(__first, __trail, __ret); | |
| 76 | return __ret; | |
| 77 | } | |
| 78 | ++__trail; | |
| 79 | ++__lead; | |
| 80 | } | |
| 81 | ||
| 82 | _ForwardIterator __mid = __first; | |
| 83 | while (true) { | |
| 84 | if (__lead == __last) { | |
| 85 | __trail = _VSTD::move(__mid, __ret, __trail); | |
| 86 | _VSTD::move(__first, __mid, __trail); | |
| 87 | return __ret; | |
| 88 | } | |
| 89 | swap(*__mid, *__trail); | |
| 90 | ++__mid; | |
| 91 | ++__trail; | |
| 92 | ++__lead; | |
| 93 | if (__mid == __ret) { | |
| 94 | __mid = __first; | |
| 95 | } | |
| 96 | } | |
| 97 | } | |
| 98 | } | |
| 99 | ||
| 100 | #endif // _LIBCPP_STD_VER > 17 | |
| 101 | ||
| 102 | _LIBCPP_END_NAMESPACE_STD | |
| 103 | ||
| 104 | _LIBCPP_POP_MACROS | |
| 105 | ||
| 106 | #endif // _LIBCPP___ALGORITHM_SHIFT_RIGHT_H |
lib/libcxx/include/__algorithm/shuffle.h created+127| ... | ... | @@ -0,0 +1,127 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SHUFFLE_H | |
| 10 | #define _LIBCPP___ALGORITHM_SHUFFLE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/iterator_traits.h> | |
| 14 | #include <__random/uniform_int_distribution.h> | |
| 15 | #include <__utility/swap.h> | |
| 16 | #include <cstddef> | |
| 17 | #include <cstdint> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | ||
| 29 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ | |
| 30 | || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 31 | class _LIBCPP_TYPE_VIS __rs_default; | |
| 32 | ||
| 33 | _LIBCPP_FUNC_VIS __rs_default __rs_get(); | |
| 34 | ||
| 35 | class _LIBCPP_TYPE_VIS __rs_default | |
| 36 | { | |
| 37 | static unsigned __c_; | |
| 38 | ||
| 39 | __rs_default(); | |
| 40 | public: | |
| 41 | typedef uint_fast32_t result_type; | |
| 42 | ||
| 43 | static const result_type _Min = 0; | |
| 44 | static const result_type _Max = 0xFFFFFFFF; | |
| 45 | ||
| 46 | __rs_default(const __rs_default&); | |
| 47 | ~__rs_default(); | |
| 48 | ||
| 49 | result_type operator()(); | |
| 50 | ||
| 51 | static _LIBCPP_CONSTEXPR result_type min() {return _Min;} | |
| 52 | static _LIBCPP_CONSTEXPR result_type max() {return _Max;} | |
| 53 | ||
| 54 | friend _LIBCPP_FUNC_VIS __rs_default __rs_get(); | |
| 55 | }; | |
| 56 | ||
| 57 | _LIBCPP_FUNC_VIS __rs_default __rs_get(); | |
| 58 | ||
| 59 | template <class _RandomAccessIterator> | |
| 60 | _LIBCPP_DEPRECATED_IN_CXX14 void | |
| 61 | random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 62 | { | |
| 63 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 64 | typedef uniform_int_distribution<ptrdiff_t> _Dp; | |
| 65 | typedef typename _Dp::param_type _Pp; | |
| 66 | difference_type __d = __last - __first; | |
| 67 | if (__d > 1) | |
| 68 | { | |
| 69 | _Dp __uid; | |
| 70 | __rs_default __g = __rs_get(); | |
| 71 | for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) | |
| 72 | { | |
| 73 | difference_type __i = __uid(__g, _Pp(0, __d)); | |
| 74 | if (__i != difference_type(0)) | |
| 75 | swap(*__first, *(__first + __i)); | |
| 76 | } | |
| 77 | } | |
| 78 | } | |
| 79 | ||
| 80 | template <class _RandomAccessIterator, class _RandomNumberGenerator> | |
| 81 | _LIBCPP_DEPRECATED_IN_CXX14 void | |
| 82 | random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, | |
| 83 | #ifndef _LIBCPP_CXX03_LANG | |
| 84 | _RandomNumberGenerator&& __rand) | |
| 85 | #else | |
| 86 | _RandomNumberGenerator& __rand) | |
| 87 | #endif | |
| 88 | { | |
| 89 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 90 | difference_type __d = __last - __first; | |
| 91 | if (__d > 1) | |
| 92 | { | |
| 93 | for (--__last; __first < __last; ++__first, (void) --__d) | |
| 94 | { | |
| 95 | difference_type __i = __rand(__d); | |
| 96 | if (__i != difference_type(0)) | |
| 97 | swap(*__first, *(__first + __i)); | |
| 98 | } | |
| 99 | } | |
| 100 | } | |
| 101 | #endif | |
| 102 | ||
| 103 | template<class _RandomAccessIterator, class _UniformRandomNumberGenerator> | |
| 104 | void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, | |
| 105 | _UniformRandomNumberGenerator&& __g) | |
| 106 | { | |
| 107 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 108 | typedef uniform_int_distribution<ptrdiff_t> _Dp; | |
| 109 | typedef typename _Dp::param_type _Pp; | |
| 110 | difference_type __d = __last - __first; | |
| 111 | if (__d > 1) | |
| 112 | { | |
| 113 | _Dp __uid; | |
| 114 | for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) | |
| 115 | { | |
| 116 | difference_type __i = __uid(__g, _Pp(0, __d)); | |
| 117 | if (__i != difference_type(0)) | |
| 118 | swap(*__first, *(__first + __i)); | |
| 119 | } | |
| 120 | } | |
| 121 | } | |
| 122 | ||
| 123 | _LIBCPP_END_NAMESPACE_STD | |
| 124 | ||
| 125 | _LIBCPP_POP_MACROS | |
| 126 | ||
| 127 | #endif // _LIBCPP___ALGORITHM_SHUFFLE_H |
lib/libcxx/include/__algorithm/sift_down.h created+84| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SIFT_DOWN_H | |
| 10 | #define _LIBCPP___ALGORITHM_SIFT_DOWN_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/iterator_traits.h> | |
| 14 | #include <__utility/move.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _Compare, class _RandomAccessIterator> | |
| 26 | _LIBCPP_CONSTEXPR_AFTER_CXX11 void | |
| 27 | __sift_down(_RandomAccessIterator __first, _RandomAccessIterator /*__last*/, | |
| 28 | _Compare __comp, | |
| 29 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 30 | _RandomAccessIterator __start) | |
| 31 | { | |
| 32 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 33 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 34 | // left-child of __start is at 2 * __start + 1 | |
| 35 | // right-child of __start is at 2 * __start + 2 | |
| 36 | difference_type __child = __start - __first; | |
| 37 | ||
| 38 | if (__len < 2 || (__len - 2) / 2 < __child) | |
| 39 | return; | |
| 40 | ||
| 41 | __child = 2 * __child + 1; | |
| 42 | _RandomAccessIterator __child_i = __first + __child; | |
| 43 | ||
| 44 | if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + 1))) { | |
| 45 | // right-child exists and is greater than left-child | |
| 46 | ++__child_i; | |
| 47 | ++__child; | |
| 48 | } | |
| 49 | ||
| 50 | // check if we are in heap-order | |
| 51 | if (__comp(*__child_i, *__start)) | |
| 52 | // we are, __start is larger than it's largest child | |
| 53 | return; | |
| 54 | ||
| 55 | value_type __top(_VSTD::move(*__start)); | |
| 56 | do | |
| 57 | { | |
| 58 | // we are not in heap-order, swap the parent with its largest child | |
| 59 | *__start = _VSTD::move(*__child_i); | |
| 60 | __start = __child_i; | |
| 61 | ||
| 62 | if ((__len - 2) / 2 < __child) | |
| 63 | break; | |
| 64 | ||
| 65 | // recompute the child based off of the updated parent | |
| 66 | __child = 2 * __child + 1; | |
| 67 | __child_i = __first + __child; | |
| 68 | ||
| 69 | if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + 1))) { | |
| 70 | // right-child exists and is greater than left-child | |
| 71 | ++__child_i; | |
| 72 | ++__child; | |
| 73 | } | |
| 74 | ||
| 75 | // check if we are in heap-order | |
| 76 | } while (!__comp(*__child_i, __top)); | |
| 77 | *__start = _VSTD::move(__top); | |
| 78 | } | |
| 79 | ||
| 80 | _LIBCPP_END_NAMESPACE_STD | |
| 81 | ||
| 82 | _LIBCPP_POP_MACROS | |
| 83 | ||
| 84 | #endif // _LIBCPP___ALGORITHM_SIFT_DOWN_H |
lib/libcxx/include/__algorithm/sort.h created+530| ... | ... | @@ -0,0 +1,530 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SORT_H | |
| 10 | #define _LIBCPP___ALGORITHM_SORT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/min_element.h> | |
| 16 | #include <__algorithm/partial_sort.h> | |
| 17 | #include <__algorithm/unwrap_iter.h> | |
| 18 | #include <__utility/swap.h> | |
| 19 | #include <memory> | |
| 20 | #include <type_traits> // swap | |
| 21 | ||
| 22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 23 | #pragma GCC system_header | |
| 24 | #endif | |
| 25 | ||
| 26 | _LIBCPP_PUSH_MACROS | |
| 27 | #include <__undef_macros> | |
| 28 | ||
| 29 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 30 | ||
| 31 | // stable, 2-3 compares, 0-2 swaps | |
| 32 | ||
| 33 | template <class _Compare, class _ForwardIterator> | |
| 34 | _LIBCPP_CONSTEXPR_AFTER_CXX11 unsigned | |
| 35 | __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z, _Compare __c) | |
| 36 | { | |
| 37 | unsigned __r = 0; | |
| 38 | if (!__c(*__y, *__x)) // if x <= y | |
| 39 | { | |
| 40 | if (!__c(*__z, *__y)) // if y <= z | |
| 41 | return __r; // x <= y && y <= z | |
| 42 | // x <= y && y > z | |
| 43 | swap(*__y, *__z); // x <= z && y < z | |
| 44 | __r = 1; | |
| 45 | if (__c(*__y, *__x)) // if x > y | |
| 46 | { | |
| 47 | swap(*__x, *__y); // x < y && y <= z | |
| 48 | __r = 2; | |
| 49 | } | |
| 50 | return __r; // x <= y && y < z | |
| 51 | } | |
| 52 | if (__c(*__z, *__y)) // x > y, if y > z | |
| 53 | { | |
| 54 | swap(*__x, *__z); // x < y && y < z | |
| 55 | __r = 1; | |
| 56 | return __r; | |
| 57 | } | |
| 58 | swap(*__x, *__y); // x > y && y <= z | |
| 59 | __r = 1; // x < y && x <= z | |
| 60 | if (__c(*__z, *__y)) // if y > z | |
| 61 | { | |
| 62 | swap(*__y, *__z); // x <= y && y < z | |
| 63 | __r = 2; | |
| 64 | } | |
| 65 | return __r; | |
| 66 | } // x <= y && y <= z | |
| 67 | ||
| 68 | // stable, 3-6 compares, 0-5 swaps | |
| 69 | ||
| 70 | template <class _Compare, class _ForwardIterator> | |
| 71 | unsigned | |
| 72 | __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, | |
| 73 | _ForwardIterator __x4, _Compare __c) | |
| 74 | { | |
| 75 | unsigned __r = _VSTD::__sort3<_Compare>(__x1, __x2, __x3, __c); | |
| 76 | if (__c(*__x4, *__x3)) | |
| 77 | { | |
| 78 | swap(*__x3, *__x4); | |
| 79 | ++__r; | |
| 80 | if (__c(*__x3, *__x2)) | |
| 81 | { | |
| 82 | swap(*__x2, *__x3); | |
| 83 | ++__r; | |
| 84 | if (__c(*__x2, *__x1)) | |
| 85 | { | |
| 86 | swap(*__x1, *__x2); | |
| 87 | ++__r; | |
| 88 | } | |
| 89 | } | |
| 90 | } | |
| 91 | return __r; | |
| 92 | } | |
| 93 | ||
| 94 | // stable, 4-10 compares, 0-9 swaps | |
| 95 | ||
| 96 | template <class _Compare, class _ForwardIterator> | |
| 97 | _LIBCPP_HIDDEN | |
| 98 | unsigned | |
| 99 | __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, | |
| 100 | _ForwardIterator __x4, _ForwardIterator __x5, _Compare __c) | |
| 101 | { | |
| 102 | unsigned __r = _VSTD::__sort4<_Compare>(__x1, __x2, __x3, __x4, __c); | |
| 103 | if (__c(*__x5, *__x4)) | |
| 104 | { | |
| 105 | swap(*__x4, *__x5); | |
| 106 | ++__r; | |
| 107 | if (__c(*__x4, *__x3)) | |
| 108 | { | |
| 109 | swap(*__x3, *__x4); | |
| 110 | ++__r; | |
| 111 | if (__c(*__x3, *__x2)) | |
| 112 | { | |
| 113 | swap(*__x2, *__x3); | |
| 114 | ++__r; | |
| 115 | if (__c(*__x2, *__x1)) | |
| 116 | { | |
| 117 | swap(*__x1, *__x2); | |
| 118 | ++__r; | |
| 119 | } | |
| 120 | } | |
| 121 | } | |
| 122 | } | |
| 123 | return __r; | |
| 124 | } | |
| 125 | ||
| 126 | // Assumes size > 0 | |
| 127 | template <class _Compare, class _BidirectionalIterator> | |
| 128 | _LIBCPP_CONSTEXPR_AFTER_CXX11 void | |
| 129 | __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 130 | { | |
| 131 | _BidirectionalIterator __lm1 = __last; | |
| 132 | for (--__lm1; __first != __lm1; ++__first) | |
| 133 | { | |
| 134 | _BidirectionalIterator __i = _VSTD::min_element<_BidirectionalIterator, | |
| 135 | typename add_lvalue_reference<_Compare>::type> | |
| 136 | (__first, __last, __comp); | |
| 137 | if (__i != __first) | |
| 138 | swap(*__first, *__i); | |
| 139 | } | |
| 140 | } | |
| 141 | ||
| 142 | template <class _Compare, class _BidirectionalIterator> | |
| 143 | void | |
| 144 | __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 145 | { | |
| 146 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 147 | if (__first != __last) | |
| 148 | { | |
| 149 | _BidirectionalIterator __i = __first; | |
| 150 | for (++__i; __i != __last; ++__i) | |
| 151 | { | |
| 152 | _BidirectionalIterator __j = __i; | |
| 153 | value_type __t(_VSTD::move(*__j)); | |
| 154 | for (_BidirectionalIterator __k = __i; __k != __first && __comp(__t, *--__k); --__j) | |
| 155 | *__j = _VSTD::move(*__k); | |
| 156 | *__j = _VSTD::move(__t); | |
| 157 | } | |
| 158 | } | |
| 159 | } | |
| 160 | ||
| 161 | template <class _Compare, class _RandomAccessIterator> | |
| 162 | void | |
| 163 | __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 164 | { | |
| 165 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 166 | _RandomAccessIterator __j = __first+2; | |
| 167 | _VSTD::__sort3<_Compare>(__first, __first+1, __j, __comp); | |
| 168 | for (_RandomAccessIterator __i = __j+1; __i != __last; ++__i) | |
| 169 | { | |
| 170 | if (__comp(*__i, *__j)) | |
| 171 | { | |
| 172 | value_type __t(_VSTD::move(*__i)); | |
| 173 | _RandomAccessIterator __k = __j; | |
| 174 | __j = __i; | |
| 175 | do | |
| 176 | { | |
| 177 | *__j = _VSTD::move(*__k); | |
| 178 | __j = __k; | |
| 179 | } while (__j != __first && __comp(__t, *--__k)); | |
| 180 | *__j = _VSTD::move(__t); | |
| 181 | } | |
| 182 | __j = __i; | |
| 183 | } | |
| 184 | } | |
| 185 | ||
| 186 | template <class _Compare, class _RandomAccessIterator> | |
| 187 | bool | |
| 188 | __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 189 | { | |
| 190 | switch (__last - __first) | |
| 191 | { | |
| 192 | case 0: | |
| 193 | case 1: | |
| 194 | return true; | |
| 195 | case 2: | |
| 196 | if (__comp(*--__last, *__first)) | |
| 197 | swap(*__first, *__last); | |
| 198 | return true; | |
| 199 | case 3: | |
| 200 | _VSTD::__sort3<_Compare>(__first, __first+1, --__last, __comp); | |
| 201 | return true; | |
| 202 | case 4: | |
| 203 | _VSTD::__sort4<_Compare>(__first, __first+1, __first+2, --__last, __comp); | |
| 204 | return true; | |
| 205 | case 5: | |
| 206 | _VSTD::__sort5<_Compare>(__first, __first+1, __first+2, __first+3, --__last, __comp); | |
| 207 | return true; | |
| 208 | } | |
| 209 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 210 | _RandomAccessIterator __j = __first+2; | |
| 211 | _VSTD::__sort3<_Compare>(__first, __first+1, __j, __comp); | |
| 212 | const unsigned __limit = 8; | |
| 213 | unsigned __count = 0; | |
| 214 | for (_RandomAccessIterator __i = __j+1; __i != __last; ++__i) | |
| 215 | { | |
| 216 | if (__comp(*__i, *__j)) | |
| 217 | { | |
| 218 | value_type __t(_VSTD::move(*__i)); | |
| 219 | _RandomAccessIterator __k = __j; | |
| 220 | __j = __i; | |
| 221 | do | |
| 222 | { | |
| 223 | *__j = _VSTD::move(*__k); | |
| 224 | __j = __k; | |
| 225 | } while (__j != __first && __comp(__t, *--__k)); | |
| 226 | *__j = _VSTD::move(__t); | |
| 227 | if (++__count == __limit) | |
| 228 | return ++__i == __last; | |
| 229 | } | |
| 230 | __j = __i; | |
| 231 | } | |
| 232 | return true; | |
| 233 | } | |
| 234 | ||
| 235 | template <class _Compare, class _BidirectionalIterator> | |
| 236 | void | |
| 237 | __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, | |
| 238 | typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) | |
| 239 | { | |
| 240 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 241 | if (__first1 != __last1) | |
| 242 | { | |
| 243 | __destruct_n __d(0); | |
| 244 | unique_ptr<value_type, __destruct_n&> __h(__first2, __d); | |
| 245 | value_type* __last2 = __first2; | |
| 246 | ::new ((void*)__last2) value_type(_VSTD::move(*__first1)); | |
| 247 | __d.template __incr<value_type>(); | |
| 248 | for (++__last2; ++__first1 != __last1; ++__last2) | |
| 249 | { | |
| 250 | value_type* __j2 = __last2; | |
| 251 | value_type* __i2 = __j2; | |
| 252 | if (__comp(*__first1, *--__i2)) | |
| 253 | { | |
| 254 | ::new ((void*)__j2) value_type(_VSTD::move(*__i2)); | |
| 255 | __d.template __incr<value_type>(); | |
| 256 | for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) | |
| 257 | *__j2 = _VSTD::move(*__i2); | |
| 258 | *__j2 = _VSTD::move(*__first1); | |
| 259 | } | |
| 260 | else | |
| 261 | { | |
| 262 | ::new ((void*)__j2) value_type(_VSTD::move(*__first1)); | |
| 263 | __d.template __incr<value_type>(); | |
| 264 | } | |
| 265 | } | |
| 266 | __h.release(); | |
| 267 | } | |
| 268 | } | |
| 269 | ||
| 270 | template <class _Compare, class _RandomAccessIterator> | |
| 271 | void | |
| 272 | __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 273 | { | |
| 274 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 275 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 276 | const difference_type __limit = is_trivially_copy_constructible<value_type>::value && | |
| 277 | is_trivially_copy_assignable<value_type>::value ? 30 : 6; | |
| 278 | while (true) | |
| 279 | { | |
| 280 | __restart: | |
| 281 | difference_type __len = __last - __first; | |
| 282 | switch (__len) | |
| 283 | { | |
| 284 | case 0: | |
| 285 | case 1: | |
| 286 | return; | |
| 287 | case 2: | |
| 288 | if (__comp(*--__last, *__first)) | |
| 289 | swap(*__first, *__last); | |
| 290 | return; | |
| 291 | case 3: | |
| 292 | _VSTD::__sort3<_Compare>(__first, __first+1, --__last, __comp); | |
| 293 | return; | |
| 294 | case 4: | |
| 295 | _VSTD::__sort4<_Compare>(__first, __first+1, __first+2, --__last, __comp); | |
| 296 | return; | |
| 297 | case 5: | |
| 298 | _VSTD::__sort5<_Compare>(__first, __first+1, __first+2, __first+3, --__last, __comp); | |
| 299 | return; | |
| 300 | } | |
| 301 | if (__len <= __limit) | |
| 302 | { | |
| 303 | _VSTD::__insertion_sort_3<_Compare>(__first, __last, __comp); | |
| 304 | return; | |
| 305 | } | |
| 306 | // __len > 5 | |
| 307 | _RandomAccessIterator __m = __first; | |
| 308 | _RandomAccessIterator __lm1 = __last; | |
| 309 | --__lm1; | |
| 310 | unsigned __n_swaps; | |
| 311 | { | |
| 312 | difference_type __delta; | |
| 313 | if (__len >= 1000) | |
| 314 | { | |
| 315 | __delta = __len/2; | |
| 316 | __m += __delta; | |
| 317 | __delta /= 2; | |
| 318 | __n_swaps = _VSTD::__sort5<_Compare>(__first, __first + __delta, __m, __m+__delta, __lm1, __comp); | |
| 319 | } | |
| 320 | else | |
| 321 | { | |
| 322 | __delta = __len/2; | |
| 323 | __m += __delta; | |
| 324 | __n_swaps = _VSTD::__sort3<_Compare>(__first, __m, __lm1, __comp); | |
| 325 | } | |
| 326 | } | |
| 327 | // *__m is median | |
| 328 | // partition [__first, __m) < *__m and *__m <= [__m, __last) | |
| 329 | // (this inhibits tossing elements equivalent to __m around unnecessarily) | |
| 330 | _RandomAccessIterator __i = __first; | |
| 331 | _RandomAccessIterator __j = __lm1; | |
| 332 | // j points beyond range to be tested, *__m is known to be <= *__lm1 | |
| 333 | // The search going up is known to be guarded but the search coming down isn't. | |
| 334 | // Prime the downward search with a guard. | |
| 335 | if (!__comp(*__i, *__m)) // if *__first == *__m | |
| 336 | { | |
| 337 | // *__first == *__m, *__first doesn't go in first part | |
| 338 | // manually guard downward moving __j against __i | |
| 339 | while (true) | |
| 340 | { | |
| 341 | if (__i == --__j) | |
| 342 | { | |
| 343 | // *__first == *__m, *__m <= all other elements | |
| 344 | // Parition instead into [__first, __i) == *__first and *__first < [__i, __last) | |
| 345 | ++__i; // __first + 1 | |
| 346 | __j = __last; | |
| 347 | if (!__comp(*__first, *--__j)) // we need a guard if *__first == *(__last-1) | |
| 348 | { | |
| 349 | while (true) | |
| 350 | { | |
| 351 | if (__i == __j) | |
| 352 | return; // [__first, __last) all equivalent elements | |
| 353 | if (__comp(*__first, *__i)) | |
| 354 | { | |
| 355 | swap(*__i, *__j); | |
| 356 | ++__n_swaps; | |
| 357 | ++__i; | |
| 358 | break; | |
| 359 | } | |
| 360 | ++__i; | |
| 361 | } | |
| 362 | } | |
| 363 | // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 | |
| 364 | if (__i == __j) | |
| 365 | return; | |
| 366 | while (true) | |
| 367 | { | |
| 368 | while (!__comp(*__first, *__i)) | |
| 369 | ++__i; | |
| 370 | while (__comp(*__first, *--__j)) | |
| 371 | ; | |
| 372 | if (__i >= __j) | |
| 373 | break; | |
| 374 | swap(*__i, *__j); | |
| 375 | ++__n_swaps; | |
| 376 | ++__i; | |
| 377 | } | |
| 378 | // [__first, __i) == *__first and *__first < [__i, __last) | |
| 379 | // The first part is sorted, sort the second part | |
| 380 | // _VSTD::__sort<_Compare>(__i, __last, __comp); | |
| 381 | __first = __i; | |
| 382 | goto __restart; | |
| 383 | } | |
| 384 | if (__comp(*__j, *__m)) | |
| 385 | { | |
| 386 | swap(*__i, *__j); | |
| 387 | ++__n_swaps; | |
| 388 | break; // found guard for downward moving __j, now use unguarded partition | |
| 389 | } | |
| 390 | } | |
| 391 | } | |
| 392 | // It is known that *__i < *__m | |
| 393 | ++__i; | |
| 394 | // j points beyond range to be tested, *__m is known to be <= *__lm1 | |
| 395 | // if not yet partitioned... | |
| 396 | if (__i < __j) | |
| 397 | { | |
| 398 | // known that *(__i - 1) < *__m | |
| 399 | // known that __i <= __m | |
| 400 | while (true) | |
| 401 | { | |
| 402 | // __m still guards upward moving __i | |
| 403 | while (__comp(*__i, *__m)) | |
| 404 | ++__i; | |
| 405 | // It is now known that a guard exists for downward moving __j | |
| 406 | while (!__comp(*--__j, *__m)) | |
| 407 | ; | |
| 408 | if (__i > __j) | |
| 409 | break; | |
| 410 | swap(*__i, *__j); | |
| 411 | ++__n_swaps; | |
| 412 | // It is known that __m != __j | |
| 413 | // If __m just moved, follow it | |
| 414 | if (__m == __i) | |
| 415 | __m = __j; | |
| 416 | ++__i; | |
| 417 | } | |
| 418 | } | |
| 419 | // [__first, __i) < *__m and *__m <= [__i, __last) | |
| 420 | if (__i != __m && __comp(*__m, *__i)) | |
| 421 | { | |
| 422 | swap(*__i, *__m); | |
| 423 | ++__n_swaps; | |
| 424 | } | |
| 425 | // [__first, __i) < *__i and *__i <= [__i+1, __last) | |
| 426 | // If we were given a perfect partition, see if insertion sort is quick... | |
| 427 | if (__n_swaps == 0) | |
| 428 | { | |
| 429 | bool __fs = _VSTD::__insertion_sort_incomplete<_Compare>(__first, __i, __comp); | |
| 430 | if (_VSTD::__insertion_sort_incomplete<_Compare>(__i+1, __last, __comp)) | |
| 431 | { | |
| 432 | if (__fs) | |
| 433 | return; | |
| 434 | __last = __i; | |
| 435 | continue; | |
| 436 | } | |
| 437 | else | |
| 438 | { | |
| 439 | if (__fs) | |
| 440 | { | |
| 441 | __first = ++__i; | |
| 442 | continue; | |
| 443 | } | |
| 444 | } | |
| 445 | } | |
| 446 | // sort smaller range with recursive call and larger with tail recursion elimination | |
| 447 | if (__i - __first < __last - __i) | |
| 448 | { | |
| 449 | _VSTD::__sort<_Compare>(__first, __i, __comp); | |
| 450 | // _VSTD::__sort<_Compare>(__i+1, __last, __comp); | |
| 451 | __first = ++__i; | |
| 452 | } | |
| 453 | else | |
| 454 | { | |
| 455 | _VSTD::__sort<_Compare>(__i+1, __last, __comp); | |
| 456 | // _VSTD::__sort<_Compare>(__first, __i, __comp); | |
| 457 | __last = __i; | |
| 458 | } | |
| 459 | } | |
| 460 | } | |
| 461 | ||
| 462 | template <class _Compare, class _Tp> | |
| 463 | inline _LIBCPP_INLINE_VISIBILITY | |
| 464 | void | |
| 465 | __sort(_Tp** __first, _Tp** __last, __less<_Tp*>&) | |
| 466 | { | |
| 467 | __less<uintptr_t> __comp; | |
| 468 | _VSTD::__sort<__less<uintptr_t>&, uintptr_t*>((uintptr_t*)__first, (uintptr_t*)__last, __comp); | |
| 469 | } | |
| 470 | ||
| 471 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<char>&, char*>(char*, char*, __less<char>&)) | |
| 472 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&)) | |
| 473 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&)) | |
| 474 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&)) | |
| 475 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<short>&, short*>(short*, short*, __less<short>&)) | |
| 476 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&)) | |
| 477 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<int>&, int*>(int*, int*, __less<int>&)) | |
| 478 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&)) | |
| 479 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<long>&, long*>(long*, long*, __less<long>&)) | |
| 480 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&)) | |
| 481 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&)) | |
| 482 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&)) | |
| 483 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<float>&, float*>(float*, float*, __less<float>&)) | |
| 484 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<double>&, double*>(double*, double*, __less<double>&)) | |
| 485 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&)) | |
| 486 | ||
| 487 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&)) | |
| 488 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&)) | |
| 489 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&)) | |
| 490 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&)) | |
| 491 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&)) | |
| 492 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&)) | |
| 493 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&)) | |
| 494 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&)) | |
| 495 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&)) | |
| 496 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&)) | |
| 497 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&)) | |
| 498 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&)) | |
| 499 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&)) | |
| 500 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&)) | |
| 501 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&)) | |
| 502 | ||
| 503 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&)) | |
| 504 | ||
| 505 | template <class _RandomAccessIterator, class _Compare> | |
| 506 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 507 | void | |
| 508 | sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 509 | { | |
| 510 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 511 | if (__libcpp_is_constant_evaluated()) { | |
| 512 | _VSTD::__partial_sort<_Comp_ref>(__first, __last, __last, _Comp_ref(__comp)); | |
| 513 | } else { | |
| 514 | _VSTD::__sort<_Comp_ref>(_VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _Comp_ref(__comp)); | |
| 515 | } | |
| 516 | } | |
| 517 | ||
| 518 | template <class _RandomAccessIterator> | |
| 519 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 520 | void | |
| 521 | sort(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 522 | { | |
| 523 | _VSTD::sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 524 | } | |
| 525 | ||
| 526 | _LIBCPP_END_NAMESPACE_STD | |
| 527 | ||
| 528 | _LIBCPP_POP_MACROS | |
| 529 | ||
| 530 | #endif // _LIBCPP___ALGORITHM_SORT_H |
lib/libcxx/include/__algorithm/sort_heap.h created+58| ... | ... | @@ -0,0 +1,58 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SORT_HEAP_H | |
| 10 | #define _LIBCPP___ALGORITHM_SORT_HEAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/pop_heap.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <type_traits> // swap | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _Compare, class _RandomAccessIterator> | |
| 29 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void | |
| 30 | __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 31 | { | |
| 32 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 33 | for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n) | |
| 34 | _VSTD::__pop_heap<_Compare>(__first, __last, __comp, __n); | |
| 35 | } | |
| 36 | ||
| 37 | template <class _RandomAccessIterator, class _Compare> | |
| 38 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 39 | void | |
| 40 | sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 41 | { | |
| 42 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 43 | _VSTD::__sort_heap<_Comp_ref>(__first, __last, __comp); | |
| 44 | } | |
| 45 | ||
| 46 | template <class _RandomAccessIterator> | |
| 47 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 48 | void | |
| 49 | sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 50 | { | |
| 51 | _VSTD::sort_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 52 | } | |
| 53 | ||
| 54 | _LIBCPP_END_NAMESPACE_STD | |
| 55 | ||
| 56 | _LIBCPP_POP_MACROS | |
| 57 | ||
| 58 | #endif // _LIBCPP___ALGORITHM_SORT_HEAP_H |
lib/libcxx/include/__algorithm/stable_partition.h created+305| ... | ... | @@ -0,0 +1,305 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H | |
| 10 | #define _LIBCPP___ALGORITHM_STABLE_PARTITION_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/rotate.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__utility/swap.h> | |
| 16 | #include <memory> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Predicate, class _ForwardIterator, class _Distance, class _Pair> | |
| 28 | _ForwardIterator | |
| 29 | __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, | |
| 30 | _Distance __len, _Pair __p, forward_iterator_tag __fit) | |
| 31 | { | |
| 32 | // *__first is known to be false | |
| 33 | // __len >= 1 | |
| 34 | if (__len == 1) | |
| 35 | return __first; | |
| 36 | if (__len == 2) | |
| 37 | { | |
| 38 | _ForwardIterator __m = __first; | |
| 39 | if (__pred(*++__m)) | |
| 40 | { | |
| 41 | swap(*__first, *__m); | |
| 42 | return __m; | |
| 43 | } | |
| 44 | return __first; | |
| 45 | } | |
| 46 | if (__len <= __p.second) | |
| 47 | { // The buffer is big enough to use | |
| 48 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 49 | __destruct_n __d(0); | |
| 50 | unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); | |
| 51 | // Move the falses into the temporary buffer, and the trues to the front of the line | |
| 52 | // Update __first to always point to the end of the trues | |
| 53 | value_type* __t = __p.first; | |
| 54 | ::new ((void*)__t) value_type(_VSTD::move(*__first)); | |
| 55 | __d.template __incr<value_type>(); | |
| 56 | ++__t; | |
| 57 | _ForwardIterator __i = __first; | |
| 58 | while (++__i != __last) | |
| 59 | { | |
| 60 | if (__pred(*__i)) | |
| 61 | { | |
| 62 | *__first = _VSTD::move(*__i); | |
| 63 | ++__first; | |
| 64 | } | |
| 65 | else | |
| 66 | { | |
| 67 | ::new ((void*)__t) value_type(_VSTD::move(*__i)); | |
| 68 | __d.template __incr<value_type>(); | |
| 69 | ++__t; | |
| 70 | } | |
| 71 | } | |
| 72 | // All trues now at start of range, all falses in buffer | |
| 73 | // Move falses back into range, but don't mess up __first which points to first false | |
| 74 | __i = __first; | |
| 75 | for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) | |
| 76 | *__i = _VSTD::move(*__t2); | |
| 77 | // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer | |
| 78 | return __first; | |
| 79 | } | |
| 80 | // Else not enough buffer, do in place | |
| 81 | // __len >= 3 | |
| 82 | _ForwardIterator __m = __first; | |
| 83 | _Distance __len2 = __len / 2; // __len2 >= 2 | |
| 84 | _VSTD::advance(__m, __len2); | |
| 85 | // recurse on [__first, __m), *__first know to be false | |
| 86 | // F????????????????? | |
| 87 | // f m l | |
| 88 | typedef typename add_lvalue_reference<_Predicate>::type _PredRef; | |
| 89 | _ForwardIterator __first_false = _VSTD::__stable_partition<_PredRef>(__first, __m, __pred, __len2, __p, __fit); | |
| 90 | // TTTFFFFF?????????? | |
| 91 | // f ff m l | |
| 92 | // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true | |
| 93 | _ForwardIterator __m1 = __m; | |
| 94 | _ForwardIterator __second_false = __last; | |
| 95 | _Distance __len_half = __len - __len2; | |
| 96 | while (__pred(*__m1)) | |
| 97 | { | |
| 98 | if (++__m1 == __last) | |
| 99 | goto __second_half_done; | |
| 100 | --__len_half; | |
| 101 | } | |
| 102 | // TTTFFFFFTTTF?????? | |
| 103 | // f ff m m1 l | |
| 104 | __second_false = _VSTD::__stable_partition<_PredRef>(__m1, __last, __pred, __len_half, __p, __fit); | |
| 105 | __second_half_done: | |
| 106 | // TTTFFFFFTTTTTFFFFF | |
| 107 | // f ff m sf l | |
| 108 | return _VSTD::rotate(__first_false, __m, __second_false); | |
| 109 | // TTTTTTTTFFFFFFFFFF | |
| 110 | // | | |
| 111 | } | |
| 112 | ||
| 113 | template <class _Predicate, class _ForwardIterator> | |
| 114 | _ForwardIterator | |
| 115 | __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, | |
| 116 | forward_iterator_tag) | |
| 117 | { | |
| 118 | const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment | |
| 119 | // Either prove all true and return __first or point to first false | |
| 120 | while (true) | |
| 121 | { | |
| 122 | if (__first == __last) | |
| 123 | return __first; | |
| 124 | if (!__pred(*__first)) | |
| 125 | break; | |
| 126 | ++__first; | |
| 127 | } | |
| 128 | // We now have a reduced range [__first, __last) | |
| 129 | // *__first is known to be false | |
| 130 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 131 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 132 | difference_type __len = _VSTD::distance(__first, __last); | |
| 133 | pair<value_type*, ptrdiff_t> __p(0, 0); | |
| 134 | unique_ptr<value_type, __return_temporary_buffer> __h; | |
| 135 | if (__len >= __alloc_limit) | |
| 136 | { | |
| 137 | __p = _VSTD::get_temporary_buffer<value_type>(__len); | |
| 138 | __h.reset(__p.first); | |
| 139 | } | |
| 140 | return _VSTD::__stable_partition<typename add_lvalue_reference<_Predicate>::type> | |
| 141 | (__first, __last, __pred, __len, __p, forward_iterator_tag()); | |
| 142 | } | |
| 143 | ||
| 144 | template <class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair> | |
| 145 | _BidirectionalIterator | |
| 146 | __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, | |
| 147 | _Distance __len, _Pair __p, bidirectional_iterator_tag __bit) | |
| 148 | { | |
| 149 | // *__first is known to be false | |
| 150 | // *__last is known to be true | |
| 151 | // __len >= 2 | |
| 152 | if (__len == 2) | |
| 153 | { | |
| 154 | swap(*__first, *__last); | |
| 155 | return __last; | |
| 156 | } | |
| 157 | if (__len == 3) | |
| 158 | { | |
| 159 | _BidirectionalIterator __m = __first; | |
| 160 | if (__pred(*++__m)) | |
| 161 | { | |
| 162 | swap(*__first, *__m); | |
| 163 | swap(*__m, *__last); | |
| 164 | return __last; | |
| 165 | } | |
| 166 | swap(*__m, *__last); | |
| 167 | swap(*__first, *__m); | |
| 168 | return __m; | |
| 169 | } | |
| 170 | if (__len <= __p.second) | |
| 171 | { // The buffer is big enough to use | |
| 172 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 173 | __destruct_n __d(0); | |
| 174 | unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); | |
| 175 | // Move the falses into the temporary buffer, and the trues to the front of the line | |
| 176 | // Update __first to always point to the end of the trues | |
| 177 | value_type* __t = __p.first; | |
| 178 | ::new ((void*)__t) value_type(_VSTD::move(*__first)); | |
| 179 | __d.template __incr<value_type>(); | |
| 180 | ++__t; | |
| 181 | _BidirectionalIterator __i = __first; | |
| 182 | while (++__i != __last) | |
| 183 | { | |
| 184 | if (__pred(*__i)) | |
| 185 | { | |
| 186 | *__first = _VSTD::move(*__i); | |
| 187 | ++__first; | |
| 188 | } | |
| 189 | else | |
| 190 | { | |
| 191 | ::new ((void*)__t) value_type(_VSTD::move(*__i)); | |
| 192 | __d.template __incr<value_type>(); | |
| 193 | ++__t; | |
| 194 | } | |
| 195 | } | |
| 196 | // move *__last, known to be true | |
| 197 | *__first = _VSTD::move(*__i); | |
| 198 | __i = ++__first; | |
| 199 | // All trues now at start of range, all falses in buffer | |
| 200 | // Move falses back into range, but don't mess up __first which points to first false | |
| 201 | for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) | |
| 202 | *__i = _VSTD::move(*__t2); | |
| 203 | // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer | |
| 204 | return __first; | |
| 205 | } | |
| 206 | // Else not enough buffer, do in place | |
| 207 | // __len >= 4 | |
| 208 | _BidirectionalIterator __m = __first; | |
| 209 | _Distance __len2 = __len / 2; // __len2 >= 2 | |
| 210 | _VSTD::advance(__m, __len2); | |
| 211 | // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false | |
| 212 | // F????????????????T | |
| 213 | // f m l | |
| 214 | _BidirectionalIterator __m1 = __m; | |
| 215 | _BidirectionalIterator __first_false = __first; | |
| 216 | _Distance __len_half = __len2; | |
| 217 | while (!__pred(*--__m1)) | |
| 218 | { | |
| 219 | if (__m1 == __first) | |
| 220 | goto __first_half_done; | |
| 221 | --__len_half; | |
| 222 | } | |
| 223 | // F???TFFF?????????T | |
| 224 | // f m1 m l | |
| 225 | typedef typename add_lvalue_reference<_Predicate>::type _PredRef; | |
| 226 | __first_false = _VSTD::__stable_partition<_PredRef>(__first, __m1, __pred, __len_half, __p, __bit); | |
| 227 | __first_half_done: | |
| 228 | // TTTFFFFF?????????T | |
| 229 | // f ff m l | |
| 230 | // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true | |
| 231 | __m1 = __m; | |
| 232 | _BidirectionalIterator __second_false = __last; | |
| 233 | ++__second_false; | |
| 234 | __len_half = __len - __len2; | |
| 235 | while (__pred(*__m1)) | |
| 236 | { | |
| 237 | if (++__m1 == __last) | |
| 238 | goto __second_half_done; | |
| 239 | --__len_half; | |
| 240 | } | |
| 241 | // TTTFFFFFTTTF?????T | |
| 242 | // f ff m m1 l | |
| 243 | __second_false = _VSTD::__stable_partition<_PredRef>(__m1, __last, __pred, __len_half, __p, __bit); | |
| 244 | __second_half_done: | |
| 245 | // TTTFFFFFTTTTTFFFFF | |
| 246 | // f ff m sf l | |
| 247 | return _VSTD::rotate(__first_false, __m, __second_false); | |
| 248 | // TTTTTTTTFFFFFFFFFF | |
| 249 | // | | |
| 250 | } | |
| 251 | ||
| 252 | template <class _Predicate, class _BidirectionalIterator> | |
| 253 | _BidirectionalIterator | |
| 254 | __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, | |
| 255 | bidirectional_iterator_tag) | |
| 256 | { | |
| 257 | typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; | |
| 258 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 259 | const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment | |
| 260 | // Either prove all true and return __first or point to first false | |
| 261 | while (true) | |
| 262 | { | |
| 263 | if (__first == __last) | |
| 264 | return __first; | |
| 265 | if (!__pred(*__first)) | |
| 266 | break; | |
| 267 | ++__first; | |
| 268 | } | |
| 269 | // __first points to first false, everything prior to __first is already set. | |
| 270 | // Either prove [__first, __last) is all false and return __first, or point __last to last true | |
| 271 | do | |
| 272 | { | |
| 273 | if (__first == --__last) | |
| 274 | return __first; | |
| 275 | } while (!__pred(*__last)); | |
| 276 | // We now have a reduced range [__first, __last] | |
| 277 | // *__first is known to be false | |
| 278 | // *__last is known to be true | |
| 279 | // __len >= 2 | |
| 280 | difference_type __len = _VSTD::distance(__first, __last) + 1; | |
| 281 | pair<value_type*, ptrdiff_t> __p(0, 0); | |
| 282 | unique_ptr<value_type, __return_temporary_buffer> __h; | |
| 283 | if (__len >= __alloc_limit) | |
| 284 | { | |
| 285 | __p = _VSTD::get_temporary_buffer<value_type>(__len); | |
| 286 | __h.reset(__p.first); | |
| 287 | } | |
| 288 | return _VSTD::__stable_partition<typename add_lvalue_reference<_Predicate>::type> | |
| 289 | (__first, __last, __pred, __len, __p, bidirectional_iterator_tag()); | |
| 290 | } | |
| 291 | ||
| 292 | template <class _ForwardIterator, class _Predicate> | |
| 293 | inline _LIBCPP_INLINE_VISIBILITY | |
| 294 | _ForwardIterator | |
| 295 | stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 296 | { | |
| 297 | return _VSTD::__stable_partition<typename add_lvalue_reference<_Predicate>::type> | |
| 298 | (__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 299 | } | |
| 300 | ||
| 301 | _LIBCPP_END_NAMESPACE_STD | |
| 302 | ||
| 303 | _LIBCPP_POP_MACROS | |
| 304 | ||
| 305 | #endif // _LIBCPP___ALGORITHM_STABLE_PARTITION_H |
lib/libcxx/include/__algorithm/stable_sort.h created+235| ... | ... | @@ -0,0 +1,235 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_STABLE_SORT_H | |
| 10 | #define _LIBCPP___ALGORITHM_STABLE_SORT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/comp_ref_type.h> | |
| 15 | #include <__algorithm/inplace_merge.h> | |
| 16 | #include <__algorithm/sort.h> | |
| 17 | #include <__iterator/iterator_traits.h> | |
| 18 | #include <__utility/swap.h> | |
| 19 | #include <memory> | |
| 20 | #include <type_traits> // swap | |
| 21 | ||
| 22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 23 | #pragma GCC system_header | |
| 24 | #endif | |
| 25 | ||
| 26 | _LIBCPP_PUSH_MACROS | |
| 27 | #include <__undef_macros> | |
| 28 | ||
| 29 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 30 | ||
| 31 | template <class _Compare, class _InputIterator1, class _InputIterator2> | |
| 32 | void | |
| 33 | __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 34 | _InputIterator2 __first2, _InputIterator2 __last2, | |
| 35 | typename iterator_traits<_InputIterator1>::value_type* __result, _Compare __comp) | |
| 36 | { | |
| 37 | typedef typename iterator_traits<_InputIterator1>::value_type value_type; | |
| 38 | __destruct_n __d(0); | |
| 39 | unique_ptr<value_type, __destruct_n&> __h(__result, __d); | |
| 40 | for (; true; ++__result) | |
| 41 | { | |
| 42 | if (__first1 == __last1) | |
| 43 | { | |
| 44 | for (; __first2 != __last2; ++__first2, ++__result, (void)__d.template __incr<value_type>()) | |
| 45 | ::new ((void*)__result) value_type(_VSTD::move(*__first2)); | |
| 46 | __h.release(); | |
| 47 | return; | |
| 48 | } | |
| 49 | if (__first2 == __last2) | |
| 50 | { | |
| 51 | for (; __first1 != __last1; ++__first1, ++__result, (void)__d.template __incr<value_type>()) | |
| 52 | ::new ((void*)__result) value_type(_VSTD::move(*__first1)); | |
| 53 | __h.release(); | |
| 54 | return; | |
| 55 | } | |
| 56 | if (__comp(*__first2, *__first1)) | |
| 57 | { | |
| 58 | ::new ((void*)__result) value_type(_VSTD::move(*__first2)); | |
| 59 | __d.template __incr<value_type>(); | |
| 60 | ++__first2; | |
| 61 | } | |
| 62 | else | |
| 63 | { | |
| 64 | ::new ((void*)__result) value_type(_VSTD::move(*__first1)); | |
| 65 | __d.template __incr<value_type>(); | |
| 66 | ++__first1; | |
| 67 | } | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 72 | void | |
| 73 | __merge_move_assign(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 74 | _InputIterator2 __first2, _InputIterator2 __last2, | |
| 75 | _OutputIterator __result, _Compare __comp) | |
| 76 | { | |
| 77 | for (; __first1 != __last1; ++__result) | |
| 78 | { | |
| 79 | if (__first2 == __last2) | |
| 80 | { | |
| 81 | for (; __first1 != __last1; ++__first1, (void) ++__result) | |
| 82 | *__result = _VSTD::move(*__first1); | |
| 83 | return; | |
| 84 | } | |
| 85 | if (__comp(*__first2, *__first1)) | |
| 86 | { | |
| 87 | *__result = _VSTD::move(*__first2); | |
| 88 | ++__first2; | |
| 89 | } | |
| 90 | else | |
| 91 | { | |
| 92 | *__result = _VSTD::move(*__first1); | |
| 93 | ++__first1; | |
| 94 | } | |
| 95 | } | |
| 96 | for (; __first2 != __last2; ++__first2, (void) ++__result) | |
| 97 | *__result = _VSTD::move(*__first2); | |
| 98 | } | |
| 99 | ||
| 100 | template <class _Compare, class _RandomAccessIterator> | |
| 101 | void | |
| 102 | __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 103 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 104 | typename iterator_traits<_RandomAccessIterator>::value_type* __buff, ptrdiff_t __buff_size); | |
| 105 | ||
| 106 | template <class _Compare, class _RandomAccessIterator> | |
| 107 | void | |
| 108 | __stable_sort_move(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Compare __comp, | |
| 109 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 110 | typename iterator_traits<_RandomAccessIterator>::value_type* __first2) | |
| 111 | { | |
| 112 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 113 | switch (__len) | |
| 114 | { | |
| 115 | case 0: | |
| 116 | return; | |
| 117 | case 1: | |
| 118 | ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); | |
| 119 | return; | |
| 120 | case 2: | |
| 121 | __destruct_n __d(0); | |
| 122 | unique_ptr<value_type, __destruct_n&> __h2(__first2, __d); | |
| 123 | if (__comp(*--__last1, *__first1)) | |
| 124 | { | |
| 125 | ::new ((void*)__first2) value_type(_VSTD::move(*__last1)); | |
| 126 | __d.template __incr<value_type>(); | |
| 127 | ++__first2; | |
| 128 | ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); | |
| 129 | } | |
| 130 | else | |
| 131 | { | |
| 132 | ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); | |
| 133 | __d.template __incr<value_type>(); | |
| 134 | ++__first2; | |
| 135 | ::new ((void*)__first2) value_type(_VSTD::move(*__last1)); | |
| 136 | } | |
| 137 | __h2.release(); | |
| 138 | return; | |
| 139 | } | |
| 140 | if (__len <= 8) | |
| 141 | { | |
| 142 | _VSTD::__insertion_sort_move<_Compare>(__first1, __last1, __first2, __comp); | |
| 143 | return; | |
| 144 | } | |
| 145 | typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; | |
| 146 | _RandomAccessIterator __m = __first1 + __l2; | |
| 147 | _VSTD::__stable_sort<_Compare>(__first1, __m, __comp, __l2, __first2, __l2); | |
| 148 | _VSTD::__stable_sort<_Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2); | |
| 149 | _VSTD::__merge_move_construct<_Compare>(__first1, __m, __m, __last1, __first2, __comp); | |
| 150 | } | |
| 151 | ||
| 152 | template <class _Tp> | |
| 153 | struct __stable_sort_switch | |
| 154 | { | |
| 155 | static const unsigned value = 128*is_trivially_copy_assignable<_Tp>::value; | |
| 156 | }; | |
| 157 | ||
| 158 | template <class _Compare, class _RandomAccessIterator> | |
| 159 | void | |
| 160 | __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 161 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 162 | typename iterator_traits<_RandomAccessIterator>::value_type* __buff, ptrdiff_t __buff_size) | |
| 163 | { | |
| 164 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 165 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 166 | switch (__len) | |
| 167 | { | |
| 168 | case 0: | |
| 169 | case 1: | |
| 170 | return; | |
| 171 | case 2: | |
| 172 | if (__comp(*--__last, *__first)) | |
| 173 | swap(*__first, *__last); | |
| 174 | return; | |
| 175 | } | |
| 176 | if (__len <= static_cast<difference_type>(__stable_sort_switch<value_type>::value)) | |
| 177 | { | |
| 178 | _VSTD::__insertion_sort<_Compare>(__first, __last, __comp); | |
| 179 | return; | |
| 180 | } | |
| 181 | typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; | |
| 182 | _RandomAccessIterator __m = __first + __l2; | |
| 183 | if (__len <= __buff_size) | |
| 184 | { | |
| 185 | __destruct_n __d(0); | |
| 186 | unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); | |
| 187 | _VSTD::__stable_sort_move<_Compare>(__first, __m, __comp, __l2, __buff); | |
| 188 | __d.__set(__l2, (value_type*)nullptr); | |
| 189 | _VSTD::__stable_sort_move<_Compare>(__m, __last, __comp, __len - __l2, __buff + __l2); | |
| 190 | __d.__set(__len, (value_type*)nullptr); | |
| 191 | _VSTD::__merge_move_assign<_Compare>(__buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp); | |
| 192 | // _VSTD::__merge<_Compare>(move_iterator<value_type*>(__buff), | |
| 193 | // move_iterator<value_type*>(__buff + __l2), | |
| 194 | // move_iterator<_RandomAccessIterator>(__buff + __l2), | |
| 195 | // move_iterator<_RandomAccessIterator>(__buff + __len), | |
| 196 | // __first, __comp); | |
| 197 | return; | |
| 198 | } | |
| 199 | _VSTD::__stable_sort<_Compare>(__first, __m, __comp, __l2, __buff, __buff_size); | |
| 200 | _VSTD::__stable_sort<_Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); | |
| 201 | _VSTD::__inplace_merge<_Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); | |
| 202 | } | |
| 203 | ||
| 204 | template <class _RandomAccessIterator, class _Compare> | |
| 205 | inline _LIBCPP_INLINE_VISIBILITY | |
| 206 | void | |
| 207 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 208 | { | |
| 209 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 210 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 211 | difference_type __len = __last - __first; | |
| 212 | pair<value_type*, ptrdiff_t> __buf(0, 0); | |
| 213 | unique_ptr<value_type, __return_temporary_buffer> __h; | |
| 214 | if (__len > static_cast<difference_type>(__stable_sort_switch<value_type>::value)) | |
| 215 | { | |
| 216 | __buf = _VSTD::get_temporary_buffer<value_type>(__len); | |
| 217 | __h.reset(__buf.first); | |
| 218 | } | |
| 219 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 220 | _VSTD::__stable_sort<_Comp_ref>(__first, __last, __comp, __len, __buf.first, __buf.second); | |
| 221 | } | |
| 222 | ||
| 223 | template <class _RandomAccessIterator> | |
| 224 | inline _LIBCPP_INLINE_VISIBILITY | |
| 225 | void | |
| 226 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 227 | { | |
| 228 | _VSTD::stable_sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 229 | } | |
| 230 | ||
| 231 | _LIBCPP_END_NAMESPACE_STD | |
| 232 | ||
| 233 | _LIBCPP_POP_MACROS | |
| 234 | ||
| 235 | #endif // _LIBCPP___ALGORITHM_STABLE_SORT_H |
lib/libcxx/include/__algorithm/swap_ranges.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_SWAP_RANGES_H | |
| 10 | #define _LIBCPP___ALGORITHM_SWAP_RANGES_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__utility/swap.h> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 26 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator2 | |
| 27 | swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { | |
| 28 | for (; __first1 != __last1; ++__first1, (void)++__first2) | |
| 29 | swap(*__first1, *__first2); | |
| 30 | return __first2; | |
| 31 | } | |
| 32 | ||
| 33 | _LIBCPP_END_NAMESPACE_STD | |
| 34 | ||
| 35 | _LIBCPP_POP_MACROS | |
| 36 | ||
| 37 | #endif // _LIBCPP___ALGORITHM_SWAP_RANGES_H |
lib/libcxx/include/__algorithm/transform.h created+48| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_TRANSFORM_H | |
| 10 | #define _LIBCPP___ALGORITHM_TRANSFORM_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _InputIterator, class _OutputIterator, class _UnaryOperation> | |
| 24 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 25 | _OutputIterator | |
| 26 | transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op) | |
| 27 | { | |
| 28 | for (; __first != __last; ++__first, (void) ++__result) | |
| 29 | *__result = __op(*__first); | |
| 30 | return __result; | |
| 31 | } | |
| 32 | ||
| 33 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _BinaryOperation> | |
| 34 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 35 | _OutputIterator | |
| 36 | transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, | |
| 37 | _OutputIterator __result, _BinaryOperation __binary_op) | |
| 38 | { | |
| 39 | for (; __first1 != __last1; ++__first1, (void) ++__first2, ++__result) | |
| 40 | *__result = __binary_op(*__first1, *__first2); | |
| 41 | return __result; | |
| 42 | } | |
| 43 | ||
| 44 | _LIBCPP_END_NAMESPACE_STD | |
| 45 | ||
| 46 | _LIBCPP_POP_MACROS | |
| 47 | ||
| 48 | #endif // _LIBCPP___ALGORITHM_TRANSFORM_H |
lib/libcxx/include/__algorithm/unique.h created+63| ... | ... | @@ -0,0 +1,63 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_UNIQUE_H | |
| 10 | #define _LIBCPP___ALGORITHM_UNIQUE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/adjacent_find.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__utility/move.h> | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | // unique | |
| 29 | ||
| 30 | template <class _ForwardIterator, class _BinaryPredicate> | |
| 31 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 32 | unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) | |
| 33 | { | |
| 34 | __first = _VSTD::adjacent_find<_ForwardIterator, typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 35 | (__first, __last, __pred); | |
| 36 | if (__first != __last) | |
| 37 | { | |
| 38 | // ... a a ? ... | |
| 39 | // f i | |
| 40 | _ForwardIterator __i = __first; | |
| 41 | for (++__i; ++__i != __last;) | |
| 42 | if (!__pred(*__first, *__i)) | |
| 43 | *++__first = _VSTD::move(*__i); | |
| 44 | ++__first; | |
| 45 | } | |
| 46 | return __first; | |
| 47 | } | |
| 48 | ||
| 49 | template <class _ForwardIterator> | |
| 50 | _LIBCPP_NODISCARD_EXT inline | |
| 51 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 52 | _ForwardIterator | |
| 53 | unique(_ForwardIterator __first, _ForwardIterator __last) | |
| 54 | { | |
| 55 | typedef typename iterator_traits<_ForwardIterator>::value_type __v; | |
| 56 | return _VSTD::unique(__first, __last, __equal_to<__v>()); | |
| 57 | } | |
| 58 | ||
| 59 | _LIBCPP_END_NAMESPACE_STD | |
| 60 | ||
| 61 | _LIBCPP_POP_MACROS | |
| 62 | ||
| 63 | #endif // _LIBCPP___ALGORITHM_UNIQUE_H |
lib/libcxx/include/__algorithm/unique_copy.h created+114| ... | ... | @@ -0,0 +1,114 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_UNIQUE_COPY_H | |
| 10 | #define _LIBCPP___ALGORITHM_UNIQUE_COPY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <utility> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _BinaryPredicate, class _InputIterator, class _OutputIterator> | |
| 28 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 29 | __unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred, | |
| 30 | input_iterator_tag, output_iterator_tag) | |
| 31 | { | |
| 32 | if (__first != __last) | |
| 33 | { | |
| 34 | typename iterator_traits<_InputIterator>::value_type __t(*__first); | |
| 35 | *__result = __t; | |
| 36 | ++__result; | |
| 37 | while (++__first != __last) | |
| 38 | { | |
| 39 | if (!__pred(__t, *__first)) | |
| 40 | { | |
| 41 | __t = *__first; | |
| 42 | *__result = __t; | |
| 43 | ++__result; | |
| 44 | } | |
| 45 | } | |
| 46 | } | |
| 47 | return __result; | |
| 48 | } | |
| 49 | ||
| 50 | template <class _BinaryPredicate, class _ForwardIterator, class _OutputIterator> | |
| 51 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 52 | __unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred, | |
| 53 | forward_iterator_tag, output_iterator_tag) | |
| 54 | { | |
| 55 | if (__first != __last) | |
| 56 | { | |
| 57 | _ForwardIterator __i = __first; | |
| 58 | *__result = *__i; | |
| 59 | ++__result; | |
| 60 | while (++__first != __last) | |
| 61 | { | |
| 62 | if (!__pred(*__i, *__first)) | |
| 63 | { | |
| 64 | *__result = *__first; | |
| 65 | ++__result; | |
| 66 | __i = __first; | |
| 67 | } | |
| 68 | } | |
| 69 | } | |
| 70 | return __result; | |
| 71 | } | |
| 72 | ||
| 73 | template <class _BinaryPredicate, class _InputIterator, class _ForwardIterator> | |
| 74 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 75 | __unique_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result, _BinaryPredicate __pred, | |
| 76 | input_iterator_tag, forward_iterator_tag) | |
| 77 | { | |
| 78 | if (__first != __last) | |
| 79 | { | |
| 80 | *__result = *__first; | |
| 81 | while (++__first != __last) | |
| 82 | if (!__pred(*__result, *__first)) | |
| 83 | *++__result = *__first; | |
| 84 | ++__result; | |
| 85 | } | |
| 86 | return __result; | |
| 87 | } | |
| 88 | ||
| 89 | template <class _InputIterator, class _OutputIterator, class _BinaryPredicate> | |
| 90 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 91 | _OutputIterator | |
| 92 | unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) | |
| 93 | { | |
| 94 | return _VSTD::__unique_copy<typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 95 | (__first, __last, __result, __pred, | |
| 96 | typename iterator_traits<_InputIterator>::iterator_category(), | |
| 97 | typename iterator_traits<_OutputIterator>::iterator_category()); | |
| 98 | } | |
| 99 | ||
| 100 | template <class _InputIterator, class _OutputIterator> | |
| 101 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 102 | _OutputIterator | |
| 103 | unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 104 | { | |
| 105 | typedef typename iterator_traits<_InputIterator>::value_type __v; | |
| 106 | return _VSTD::unique_copy(__first, __last, __result, __equal_to<__v>()); | |
| 107 | } | |
| 108 | ||
| 109 | ||
| 110 | _LIBCPP_END_NAMESPACE_STD | |
| 111 | ||
| 112 | _LIBCPP_POP_MACROS | |
| 113 | ||
| 114 | #endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H |
lib/libcxx/include/__algorithm/unwrap_iter.h created+87| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_UNWRAP_ITER_H | |
| 10 | #define _LIBCPP___ALGORITHM_UNWRAP_ITER_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <iterator> | |
| 14 | #include <__memory/pointer_traits.h> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | // The job of __unwrap_iter is to lower contiguous iterators (such as | |
| 27 | // vector<T>::iterator) into pointers, to reduce the number of template | |
| 28 | // instantiations and to enable pointer-based optimizations e.g. in std::copy. | |
| 29 | // For iterators that are not contiguous, it must be a no-op. | |
| 30 | // In debug mode, we don't do this. | |
| 31 | // | |
| 32 | // __unwrap_iter is non-constexpr for user-defined iterators whose | |
| 33 | // `to_address` and/or `operator->` is non-constexpr. This is okay; but we | |
| 34 | // try to avoid doing __unwrap_iter in constant-evaluated contexts anyway. | |
| 35 | // | |
| 36 | // Some algorithms (e.g. std::copy, but not std::sort) need to convert an | |
| 37 | // "unwrapped" result back into a contiguous iterator. Since contiguous iterators | |
| 38 | // are random-access, we can do this portably using iterator arithmetic; this | |
| 39 | // is the job of __rewrap_iter. | |
| 40 | ||
| 41 | template <class _Iter, bool = __is_cpp17_contiguous_iterator<_Iter>::value> | |
| 42 | struct __unwrap_iter_impl { | |
| 43 | static _LIBCPP_CONSTEXPR _Iter | |
| 44 | __apply(_Iter __i) _NOEXCEPT { | |
| 45 | return __i; | |
| 46 | } | |
| 47 | }; | |
| 48 | ||
| 49 | #if _LIBCPP_DEBUG_LEVEL < 2 | |
| 50 | ||
| 51 | template <class _Iter> | |
| 52 | struct __unwrap_iter_impl<_Iter, true> { | |
| 53 | static _LIBCPP_CONSTEXPR decltype(_VSTD::__to_address(declval<_Iter>())) | |
| 54 | __apply(_Iter __i) _NOEXCEPT { | |
| 55 | return _VSTD::__to_address(__i); | |
| 56 | } | |
| 57 | }; | |
| 58 | ||
| 59 | #endif // _LIBCPP_DEBUG_LEVEL < 2 | |
| 60 | ||
| 61 | template<class _Iter, class _Impl = __unwrap_iter_impl<_Iter> > | |
| 62 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 63 | decltype(_Impl::__apply(declval<_Iter>())) | |
| 64 | __unwrap_iter(_Iter __i) _NOEXCEPT | |
| 65 | { | |
| 66 | return _Impl::__apply(__i); | |
| 67 | } | |
| 68 | ||
| 69 | template<class _OrigIter> | |
| 70 | _OrigIter __rewrap_iter(_OrigIter, _OrigIter __result) | |
| 71 | { | |
| 72 | return __result; | |
| 73 | } | |
| 74 | ||
| 75 | template<class _OrigIter, class _UnwrappedIter> | |
| 76 | _OrigIter __rewrap_iter(_OrigIter __first, _UnwrappedIter __result) | |
| 77 | { | |
| 78 | // Precondition: __result is reachable from __first | |
| 79 | // Precondition: _OrigIter is a contiguous iterator | |
| 80 | return __first + (__result - _VSTD::__unwrap_iter(__first)); | |
| 81 | } | |
| 82 | ||
| 83 | _LIBCPP_END_NAMESPACE_STD | |
| 84 | ||
| 85 | _LIBCPP_POP_MACROS | |
| 86 | ||
| 87 | #endif // _LIBCPP___ALGORITHM_UNWRAP_ITER_H |
lib/libcxx/include/__algorithm/upper_bound.h created+72| ... | ... | @@ -0,0 +1,72 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___ALGORITHM_UPPER_BOUND_H | |
| 10 | #define _LIBCPP___ALGORITHM_UPPER_BOUND_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__algorithm/comp.h> | |
| 14 | #include <__algorithm/half_positive.h> | |
| 15 | #include <iterator> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 27 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 28 | __upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 29 | { | |
| 30 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 31 | difference_type __len = _VSTD::distance(__first, __last); | |
| 32 | while (__len != 0) | |
| 33 | { | |
| 34 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 35 | _ForwardIterator __m = __first; | |
| 36 | _VSTD::advance(__m, __l2); | |
| 37 | if (__comp(__value_, *__m)) | |
| 38 | __len = __l2; | |
| 39 | else | |
| 40 | { | |
| 41 | __first = ++__m; | |
| 42 | __len -= __l2 + 1; | |
| 43 | } | |
| 44 | } | |
| 45 | return __first; | |
| 46 | } | |
| 47 | ||
| 48 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 49 | _LIBCPP_NODISCARD_EXT inline | |
| 50 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 51 | _ForwardIterator | |
| 52 | upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 53 | { | |
| 54 | typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; | |
| 55 | return _VSTD::__upper_bound<_Comp_ref>(__first, __last, __value_, __comp); | |
| 56 | } | |
| 57 | ||
| 58 | template <class _ForwardIterator, class _Tp> | |
| 59 | _LIBCPP_NODISCARD_EXT inline | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 61 | _ForwardIterator | |
| 62 | upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 63 | { | |
| 64 | return _VSTD::upper_bound(__first, __last, __value_, | |
| 65 | __less<_Tp, typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 66 | } | |
| 67 | ||
| 68 | _LIBCPP_END_NAMESPACE_STD | |
| 69 | ||
| 70 | _LIBCPP_POP_MACROS | |
| 71 | ||
| 72 | #endif // _LIBCPP___ALGORITHM_UPPER_BOUND_H |
lib/libcxx/include/__availability+66-2| ... | ... | @@ -43,6 +43,14 @@ |
| 43 | 43 | // as unavailable. When vendors decide to ship the feature as part of their |
| 44 | 44 | // shared library, they can update the markup appropriately. |
| 45 | 45 | // |
| 46 | // Furthermore, many features in the standard library have corresponding | |
| 47 | // feature-test macros. When a feature is made unavailable on some deployment | |
| 48 | // target, a macro should be defined to signal that it is unavailable. That | |
| 49 | // macro can then be picked up when feature-test macros are generated (see | |
| 50 | // generate_feature_test_macro_components.py) to make sure that feature-test | |
| 51 | // macros don't announce a feature as being implemented if it has been marked | |
| 52 | // as unavailable. | |
| 53 | // | |
| 46 | 54 | // Note that this mechanism is disabled by default in the "upstream" libc++. |
| 47 | 55 | // Availability annotations are only meaningful when shipping libc++ inside |
| 48 | 56 | // a platform (i.e. as a system library), and so vendors that want them should |
| ... | ... | @@ -76,6 +84,8 @@ |
| 76 | 84 | // This controls the availability of std::shared_mutex and std::shared_timed_mutex, |
| 77 | 85 | // which were added to the dylib later. |
| 78 | 86 | # define _LIBCPP_AVAILABILITY_SHARED_MUTEX |
| 87 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex | |
| 88 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex | |
| 79 | 89 | |
| 80 | 90 | // These macros control the availability of std::bad_optional_access and |
| 81 | 91 | // other exception types. These were put in the shared library to prevent |
| ... | ... | @@ -114,6 +124,7 @@ |
| 114 | 124 | # define _LIBCPP_AVAILABILITY_FILESYSTEM |
| 115 | 125 | # define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH |
| 116 | 126 | # define _LIBCPP_AVAILABILITY_FILESYSTEM_POP |
| 127 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem | |
| 117 | 128 | |
| 118 | 129 | // This controls the availability of std::to_chars. |
| 119 | 130 | # define _LIBCPP_AVAILABILITY_TO_CHARS |
| ... | ... | @@ -122,6 +133,17 @@ |
| 122 | 133 | // which requires shared library support for various operations |
| 123 | 134 | // (see libcxx/src/atomic.cpp). |
| 124 | 135 | # define _LIBCPP_AVAILABILITY_SYNC |
| 136 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait | |
| 137 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier | |
| 138 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch | |
| 139 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore | |
| 140 | ||
| 141 | // This controls the availability of the C++20 format library. | |
| 142 | // The library is in development and not ABI stable yet. Currently | |
| 143 | // P2216 is aiming to be retroactively accepted in C++20. This paper | |
| 144 | // contains ABI breaking changes. | |
| 145 | # define _LIBCPP_AVAILABILITY_FORMAT | |
| 146 | // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format | |
| 125 | 147 | |
| 126 | 148 | #elif defined(__APPLE__) |
| 127 | 149 | |
| ... | ... | @@ -130,6 +152,14 @@ |
| 130 | 152 | __attribute__((availability(ios,strict,introduced=10.0))) \ |
| 131 | 153 | __attribute__((availability(tvos,strict,introduced=10.0))) \ |
| 132 | 154 | __attribute__((availability(watchos,strict,introduced=3.0))) |
| 155 | # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ | |
| 156 | (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ | |
| 157 | (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ | |
| 158 | (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) | |
| 159 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex | |
| 160 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex | |
| 161 | # endif | |
| 162 | ||
| 133 | 163 | # define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \ |
| 134 | 164 | __attribute__((availability(macosx,strict,introduced=10.13))) \ |
| 135 | 165 | __attribute__((availability(ios,strict,introduced=11.0))) \ |
| ... | ... | @@ -139,27 +169,34 @@ |
| 139 | 169 | _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS |
| 140 | 170 | # define _LIBCPP_AVAILABILITY_BAD_ANY_CAST \ |
| 141 | 171 | _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS |
| 172 | ||
| 142 | 173 | # define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS \ |
| 143 | 174 | __attribute__((availability(macosx,strict,introduced=10.12))) \ |
| 144 | 175 | __attribute__((availability(ios,strict,introduced=10.0))) \ |
| 145 | 176 | __attribute__((availability(tvos,strict,introduced=10.0))) \ |
| 146 | 177 | __attribute__((availability(watchos,strict,introduced=3.0))) |
| 178 | ||
| 147 | 179 | # define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE \ |
| 148 | 180 | __attribute__((availability(macosx,strict,introduced=10.12))) \ |
| 149 | 181 | __attribute__((availability(ios,strict,introduced=10.0))) \ |
| 150 | 182 | __attribute__((availability(tvos,strict,introduced=10.0))) \ |
| 151 | 183 | __attribute__((availability(watchos,strict,introduced=3.0))) |
| 184 | ||
| 152 | 185 | # define _LIBCPP_AVAILABILITY_FUTURE_ERROR \ |
| 153 | 186 | __attribute__((availability(ios,strict,introduced=6.0))) |
| 187 | ||
| 154 | 188 | # define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE \ |
| 155 | 189 | __attribute__((availability(macosx,strict,introduced=10.9))) \ |
| 156 | 190 | __attribute__((availability(ios,strict,introduced=7.0))) |
| 191 | ||
| 157 | 192 | # define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY \ |
| 158 | 193 | __attribute__((availability(macosx,strict,introduced=10.9))) \ |
| 159 | 194 | __attribute__((availability(ios,strict,introduced=7.0))) |
| 195 | ||
| 160 | 196 | # define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR \ |
| 161 | 197 | __attribute__((availability(macosx,strict,introduced=10.9))) \ |
| 162 | 198 | __attribute__((availability(ios,strict,introduced=7.0))) |
| 199 | ||
| 163 | 200 | # define _LIBCPP_AVAILABILITY_FILESYSTEM \ |
| 164 | 201 | __attribute__((availability(macosx,strict,introduced=10.15))) \ |
| 165 | 202 | __attribute__((availability(ios,strict,introduced=13.0))) \ |
| ... | ... | @@ -175,11 +212,38 @@ |
| 175 | 212 | _Pragma("clang attribute pop") \ |
| 176 | 213 | _Pragma("clang attribute pop") \ |
| 177 | 214 | _Pragma("clang attribute pop") |
| 215 | # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ | |
| 216 | (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ | |
| 217 | (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ | |
| 218 | (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) | |
| 219 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem | |
| 220 | # endif | |
| 221 | ||
| 178 | 222 | # define _LIBCPP_AVAILABILITY_TO_CHARS \ |
| 179 | 223 | _LIBCPP_AVAILABILITY_FILESYSTEM |
| 224 | ||
| 180 | 225 | # define _LIBCPP_AVAILABILITY_SYNC \ |
| 181 | __attribute__((unavailable)) | |
| 226 | __attribute__((availability(macosx,strict,introduced=11.0))) \ | |
| 227 | __attribute__((availability(ios,strict,introduced=14.0))) \ | |
| 228 | __attribute__((availability(tvos,strict,introduced=14.0))) \ | |
| 229 | __attribute__((availability(watchos,strict,introduced=7.0))) | |
| 230 | # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ | |
| 231 | (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ | |
| 232 | (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ | |
| 233 | (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) | |
| 234 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait | |
| 235 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier | |
| 236 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch | |
| 237 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore | |
| 238 | # endif | |
| 182 | 239 | |
| 240 | // This controls the availability of the C++20 format library. | |
| 241 | // The library is in development and not ABI stable yet. Currently | |
| 242 | // P2216 is aiming to be retroactively accepted in C++20. This paper | |
| 243 | // contains ABI breaking changes. | |
| 244 | # define _LIBCPP_AVAILABILITY_FORMAT \ | |
| 245 | __attribute__((unavailable)) | |
| 246 | # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format | |
| 183 | 247 | #else |
| 184 | 248 | |
| 185 | 249 | // ...New vendors can add availability markup here... |
| ... | ... | @@ -203,4 +267,4 @@ |
| 203 | 267 | # define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS |
| 204 | 268 | #endif |
| 205 | 269 | |
| 206 | #endif // _LIBCPP___AVAILABILITY | |
| 270 | #endif // _LIBCPP___AVAILABILITY |
lib/libcxx/include/__bit_reference+17-19| ... | ... | @@ -1114,28 +1114,26 @@ public: |
| 1114 | 1114 | #endif |
| 1115 | 1115 | {} |
| 1116 | 1116 | |
| 1117 | // avoid re-declaring a copy constructor for the non-const version. | |
| 1118 | using __type_for_copy_to_const = | |
| 1119 | _If<_IsConst, __bit_iterator<_Cp, false>, struct __private_nat>; | |
| 1120 | ||
| 1117 | // When _IsConst=false, this is the copy constructor. | |
| 1118 | // It is non-trivial. Making it trivial would break ABI. | |
| 1119 | // When _IsConst=true, this is a converting constructor; | |
| 1120 | // the copy and move constructors are implicitly generated | |
| 1121 | // and trivial. | |
| 1121 | 1122 | _LIBCPP_INLINE_VISIBILITY |
| 1122 | __bit_iterator(const __type_for_copy_to_const& __it) _NOEXCEPT | |
| 1123 | __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT | |
| 1123 | 1124 | : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} |
| 1124 | 1125 | |
| 1125 | // The non-const __bit_iterator has historically had a non-trivial | |
| 1126 | // copy constructor (as a quirk of its construction). We need to maintain | |
| 1127 | // this for ABI purposes. | |
| 1128 | using __type_for_abi_non_trivial_copy_ctor = | |
| 1129 | _If<!_IsConst, __bit_iterator, struct __private_nat>; | |
| 1130 | ||
| 1131 | _LIBCPP_INLINE_VISIBILITY | |
| 1132 | __bit_iterator(__type_for_abi_non_trivial_copy_ctor const& __it) _NOEXCEPT | |
| 1133 | : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} | |
| 1134 | ||
| 1135 | // Always declare the copy assignment operator since the implicit declaration | |
| 1136 | // is deprecated. | |
| 1126 | // When _IsConst=false, we have a user-provided copy constructor, | |
| 1127 | // so we must also provide a copy assignment operator because | |
| 1128 | // the implicit generation of a defaulted one is deprecated. | |
| 1129 | // When _IsConst=true, the assignment operators are | |
| 1130 | // implicitly generated and trivial. | |
| 1137 | 1131 | _LIBCPP_INLINE_VISIBILITY |
| 1138 | __bit_iterator& operator=(__bit_iterator const&) = default; | |
| 1132 | __bit_iterator& operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) { | |
| 1133 | __seg_ = __it.__seg_; | |
| 1134 | __ctz_ = __it.__ctz_; | |
| 1135 | return *this; | |
| 1136 | } | |
| 1139 | 1137 | |
| 1140 | 1138 | _LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT |
| 1141 | 1139 | {return reference(__seg_, __storage_type(1) << __ctz_);} |
| ... | ... | @@ -1302,4 +1300,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 1302 | 1300 | |
| 1303 | 1301 | _LIBCPP_POP_MACROS |
| 1304 | 1302 | |
| 1305 | #endif // _LIBCPP___BIT_REFERENCE | |
| 1303 | #endif // _LIBCPP___BIT_REFERENCE |
lib/libcxx/include/__bits+1-2| ... | ... | @@ -76,7 +76,6 @@ inline _LIBCPP_INLINE_VISIBILITY |
| 76 | 76 | int __libcpp_ctz(unsigned long long __x) { |
| 77 | 77 | unsigned long __where; |
| 78 | 78 | #if defined(_LIBCPP_HAS_BITSCAN64) |
| 79 | (defined(_M_AMD64) || defined(__x86_64__)) | |
| 80 | 79 | if (_BitScanForward64(&__where, __x)) |
| 81 | 80 | return static_cast<int>(__where); |
| 82 | 81 | #else |
| ... | ... | @@ -143,4 +142,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 143 | 142 | |
| 144 | 143 | _LIBCPP_POP_MACROS |
| 145 | 144 | |
| 146 | #endif // _LIBCPP__BITS | |
| 145 | #endif // _LIBCPP___BITS |
lib/libcxx/include/__bsd_locale_fallbacks.h+2-2| ... | ... | @@ -13,9 +13,9 @@ |
| 13 | 13 | #ifndef _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H |
| 14 | 14 | #define _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H |
| 15 | 15 | |
| 16 | #include <stdlib.h> | |
| 17 | #include <stdarg.h> | |
| 18 | 16 | #include <memory> |
| 17 | #include <stdarg.h> | |
| 18 | #include <stdlib.h> | |
| 19 | 19 | |
| 20 | 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 21 | 21 | #pragma GCC system_header |
lib/libcxx/include/__config+136-127| ... | ... | @@ -32,7 +32,7 @@ |
| 32 | 32 | # define _GNUC_VER_NEW 0 |
| 33 | 33 | #endif |
| 34 | 34 | |
| 35 | #define _LIBCPP_VERSION 12000 | |
| 35 | #define _LIBCPP_VERSION 13000 | |
| 36 | 36 | |
| 37 | 37 | #ifndef _LIBCPP_ABI_VERSION |
| 38 | 38 | # define _LIBCPP_ABI_VERSION 1 |
| ... | ... | @@ -54,7 +54,7 @@ |
| 54 | 54 | # else |
| 55 | 55 | # define _LIBCPP_STD_VER 21 // current year, or date of c++2b ratification |
| 56 | 56 | # endif |
| 57 | #endif // _LIBCPP_STD_VER | |
| 57 | #endif // _LIBCPP_STD_VER | |
| 58 | 58 | |
| 59 | 59 | #if defined(__ELF__) |
| 60 | 60 | # define _LIBCPP_OBJECT_FORMAT_ELF 1 |
| ... | ... | @@ -86,17 +86,18 @@ |
| 86 | 86 | // provided under the alternate keyword __nullptr, which changes the mangling |
| 87 | 87 | // of nullptr_t. This option is ABI incompatible with GCC in C++03 mode. |
| 88 | 88 | # define _LIBCPP_ABI_ALWAYS_USE_CXX11_NULLPTR |
| 89 | // Define the `pointer_safety` enum as a C++11 strongly typed enumeration | |
| 90 | // instead of as a class simulating an enum. If this option is enabled | |
| 91 | // `pointer_safety` and `get_pointer_safety()` will no longer be available | |
| 92 | // in C++03. | |
| 93 | # define _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE | |
| 94 | 89 | // Define a key function for `bad_function_call` in the library, to centralize |
| 95 | 90 | // its vtable and typeinfo to libc++ rather than having all other libraries |
| 96 | 91 | // using that class define their own copies. |
| 97 | 92 | # define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION |
| 98 | 93 | // Enable optimized version of __do_get_(un)signed which avoids redundant copies. |
| 99 | 94 | # define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET |
| 95 | // In C++20 and later, don't derive std::plus from std::binary_function, | |
| 96 | // nor std::negate from std::unary_function. | |
| 97 | # define _LIBCPP_ABI_NO_BINDER_BASES | |
| 98 | // Give reverse_iterator<T> one data member of type T, not two. | |
| 99 | // Also, in C++17 and later, don't derive iterator types from std::iterator. | |
| 100 | # define _LIBCPP_ABI_NO_ITERATOR_BASES | |
| 100 | 101 | // Use the smallest possible integer type to represent the index of the variant. |
| 101 | 102 | // Previously libc++ used "unsigned int" exclusively. |
| 102 | 103 | # define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION |
| ... | ... | @@ -104,6 +105,8 @@ |
| 104 | 105 | # define _LIBCPP_ABI_OPTIMIZED_FUNCTION |
| 105 | 106 | // All the regex constants must be distinct and nonzero. |
| 106 | 107 | # define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO |
| 108 | // Use raw pointers, not wrapped ones, for std::span's iterator type. | |
| 109 | # define _LIBCPP_ABI_SPAN_POINTER_ITERATORS | |
| 107 | 110 | // Re-worked external template instantiations for std::string with a focus on |
| 108 | 111 | // performance and fast-path inlining. |
| 109 | 112 | # define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION |
| ... | ... | @@ -181,11 +184,12 @@ |
| 181 | 184 | #define __has_include(...) 0 |
| 182 | 185 | #endif |
| 183 | 186 | |
| 184 | #if defined(__clang__) | |
| 185 | # define _LIBCPP_COMPILER_CLANG | |
| 186 | # ifndef __apple_build_version__ | |
| 187 | # define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) | |
| 188 | # endif | |
| 187 | #if defined(__apple_build_version__) | |
| 188 | # define _LIBCPP_COMPILER_CLANG_BASED | |
| 189 | # define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) | |
| 190 | #elif defined(__clang__) | |
| 191 | # define _LIBCPP_COMPILER_CLANG_BASED | |
| 192 | # define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) | |
| 189 | 193 | #elif defined(__GNUC__) |
| 190 | 194 | # define _LIBCPP_COMPILER_GCC |
| 191 | 195 | #elif defined(_MSC_VER) |
| ... | ... | @@ -235,13 +239,13 @@ |
| 235 | 239 | # if __LITTLE_ENDIAN__ |
| 236 | 240 | # define _LIBCPP_LITTLE_ENDIAN |
| 237 | 241 | # endif // __LITTLE_ENDIAN__ |
| 238 | #endif // __LITTLE_ENDIAN__ | |
| 242 | #endif // __LITTLE_ENDIAN__ | |
| 239 | 243 | |
| 240 | 244 | #ifdef __BIG_ENDIAN__ |
| 241 | 245 | # if __BIG_ENDIAN__ |
| 242 | 246 | # define _LIBCPP_BIG_ENDIAN |
| 243 | 247 | # endif // __BIG_ENDIAN__ |
| 244 | #endif // __BIG_ENDIAN__ | |
| 248 | #endif // __BIG_ENDIAN__ | |
| 245 | 249 | |
| 246 | 250 | #ifdef __BYTE_ORDER__ |
| 247 | 251 | # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
| ... | ... | @@ -262,7 +266,7 @@ |
| 262 | 266 | # ifndef __LONG_LONG_SUPPORTED |
| 263 | 267 | # define _LIBCPP_HAS_NO_LONG_LONG |
| 264 | 268 | # endif // __LONG_LONG_SUPPORTED |
| 265 | #endif // __FreeBSD__ | |
| 269 | #endif // __FreeBSD__ | |
| 266 | 270 | |
| 267 | 271 | #if defined(__NetBSD__) || defined(__OpenBSD__) |
| 268 | 272 | # include <sys/endian.h> |
| ... | ... | @@ -271,7 +275,7 @@ |
| 271 | 275 | # else // _BYTE_ORDER == _LITTLE_ENDIAN |
| 272 | 276 | # define _LIBCPP_BIG_ENDIAN |
| 273 | 277 | # endif // _BYTE_ORDER == _LITTLE_ENDIAN |
| 274 | #endif // defined(__NetBSD__) || defined(__OpenBSD__) | |
| 278 | #endif // defined(__NetBSD__) || defined(__OpenBSD__) | |
| 275 | 279 | |
| 276 | 280 | #if defined(_WIN32) |
| 277 | 281 | # define _LIBCPP_WIN32API |
| ... | ... | @@ -340,7 +344,7 @@ |
| 340 | 344 | # else // __BYTE_ORDER == __BIG_ENDIAN |
| 341 | 345 | # error unable to determine endian |
| 342 | 346 | # endif |
| 343 | #endif // !defined(_LIBCPP_LITTLE_ENDIAN) && !defined(_LIBCPP_BIG_ENDIAN) | |
| 347 | #endif // !defined(_LIBCPP_LITTLE_ENDIAN) && !defined(_LIBCPP_BIG_ENDIAN) | |
| 344 | 348 | |
| 345 | 349 | #if __has_attribute(__no_sanitize__) && !defined(_LIBCPP_COMPILER_GCC) |
| 346 | 350 | # define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) |
| ... | ... | @@ -348,7 +352,7 @@ |
| 348 | 352 | # define _LIBCPP_NO_CFI |
| 349 | 353 | #endif |
| 350 | 354 | |
| 351 | #if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L | |
| 355 | #if (defined(__ISO_C_VISIBLE) && (__ISO_C_VISIBLE >= 2011)) || __cplusplus >= 201103L | |
| 352 | 356 | # if defined(__FreeBSD__) |
| 353 | 357 | # define _LIBCPP_HAS_ALIGNED_ALLOC |
| 354 | 358 | # define _LIBCPP_HAS_QUICK_EXIT |
| ... | ... | @@ -387,13 +391,16 @@ |
| 387 | 391 | # define _LIBCPP_HAS_QUICK_EXIT |
| 388 | 392 | # define _LIBCPP_HAS_TIMESPEC_GET |
| 389 | 393 | # endif |
| 394 | # elif defined(_LIBCPP_MSVCRT) | |
| 395 | // Using Microsoft's C Runtime library, not MinGW | |
| 396 | # define _LIBCPP_HAS_TIMESPEC_GET | |
| 390 | 397 | # elif defined(__APPLE__) |
| 391 | 398 | // timespec_get and aligned_alloc were introduced in macOS 10.15 and |
| 392 | 399 | // aligned releases |
| 393 | # if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500 || \ | |
| 394 | __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000 || \ | |
| 395 | __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 130000 || \ | |
| 396 | __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 60000) | |
| 400 | # if ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500) || \ | |
| 401 | (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000) || \ | |
| 402 | (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 130000) || \ | |
| 403 | (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 60000)) | |
| 397 | 404 | # define _LIBCPP_HAS_ALIGNED_ALLOC |
| 398 | 405 | # define _LIBCPP_HAS_TIMESPEC_GET |
| 399 | 406 | # endif |
| ... | ... | @@ -402,7 +409,7 @@ |
| 402 | 409 | |
| 403 | 410 | #ifndef _LIBCPP_CXX03_LANG |
| 404 | 411 | # define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp) |
| 405 | #elif defined(_LIBCPP_COMPILER_CLANG) | |
| 412 | #elif defined(_LIBCPP_COMPILER_CLANG_BASED) | |
| 406 | 413 | # define _LIBCPP_ALIGNOF(_Tp) _Alignof(_Tp) |
| 407 | 414 | #else |
| 408 | 415 | # error "We don't know a correct way to implement alignof(T) in C++03 outside of Clang" |
| ... | ... | @@ -410,7 +417,7 @@ |
| 410 | 417 | |
| 411 | 418 | #define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) |
| 412 | 419 | |
| 413 | #if defined(_LIBCPP_COMPILER_CLANG) | |
| 420 | #if defined(_LIBCPP_COMPILER_CLANG_BASED) | |
| 414 | 421 | |
| 415 | 422 | #if defined(_LIBCPP_ALTERNATE_STRING_LAYOUT) |
| 416 | 423 | # error _LIBCPP_ALTERNATE_STRING_LAYOUT is deprecated, please use _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT instead |
| ... | ... | @@ -484,12 +491,12 @@ typedef __char32_t char32_t; |
| 484 | 491 | #define _LIBCPP_HAS_NO_NOEXCEPT |
| 485 | 492 | #endif |
| 486 | 493 | |
| 487 | #if !defined(_LIBCPP_HAS_NO_ASAN) && !__has_feature(address_sanitizer) | |
| 494 | #if !__has_feature(address_sanitizer) | |
| 488 | 495 | #define _LIBCPP_HAS_NO_ASAN |
| 489 | 496 | #endif |
| 490 | 497 | |
| 491 | 498 | // Allow for build-time disabling of unsigned integer sanitization |
| 492 | #if !defined(_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK) && __has_attribute(no_sanitize) | |
| 499 | #if __has_attribute(no_sanitize) | |
| 493 | 500 | #define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) |
| 494 | 501 | #endif |
| 495 | 502 | |
| ... | ... | @@ -508,8 +515,8 @@ typedef __char32_t char32_t; |
| 508 | 515 | #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) |
| 509 | 516 | |
| 510 | 517 | // Literal operators ""d and ""y are supported starting with LLVM Clang 8 and AppleClang 10.0.1 |
| 511 | #if (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 800) || \ | |
| 512 | (defined(__apple_build_version__) && __apple_build_version__ < 10010000) | |
| 518 | #if (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 800) || \ | |
| 519 | (defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1001) | |
| 513 | 520 | #define _LIBCPP_HAS_NO_CXX20_CHRONO_LITERALS |
| 514 | 521 | #endif |
| 515 | 522 | |
| ... | ... | @@ -522,7 +529,7 @@ typedef __char32_t char32_t; |
| 522 | 529 | |
| 523 | 530 | #define _LIBCPP_NORETURN __attribute__((noreturn)) |
| 524 | 531 | |
| 525 | #if !__EXCEPTIONS | |
| 532 | #if !defined(__EXCEPTIONS) | |
| 526 | 533 | # define _LIBCPP_NO_EXCEPTIONS |
| 527 | 534 | #endif |
| 528 | 535 | |
| ... | ... | @@ -536,7 +543,7 @@ typedef __char32_t char32_t; |
| 536 | 543 | #define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES |
| 537 | 544 | #endif |
| 538 | 545 | |
| 539 | #if !defined(_LIBCPP_HAS_NO_ASAN) && !defined(__SANITIZE_ADDRESS__) | |
| 546 | #if !defined(__SANITIZE_ADDRESS__) | |
| 540 | 547 | #define _LIBCPP_HAS_NO_ASAN |
| 541 | 548 | #endif |
| 542 | 549 | |
| ... | ... | @@ -640,6 +647,7 @@ typedef __char32_t char32_t; |
| 640 | 647 | #define _LIBCPP_HIDDEN |
| 641 | 648 | #define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| 642 | 649 | #define _LIBCPP_TEMPLATE_VIS |
| 650 | #define _LIBCPP_TEMPLATE_DATA_VIS | |
| 643 | 651 | #define _LIBCPP_ENUM_VIS |
| 644 | 652 | |
| 645 | 653 | #endif // defined(_LIBCPP_OBJECT_FORMAT_COFF) |
| ... | ... | @@ -689,6 +697,14 @@ typedef __char32_t char32_t; |
| 689 | 697 | # endif |
| 690 | 698 | #endif |
| 691 | 699 | |
| 700 | #ifndef _LIBCPP_TEMPLATE_DATA_VIS | |
| 701 | # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) | |
| 702 | # define _LIBCPP_TEMPLATE_DATA_VIS __attribute__ ((__visibility__("default"))) | |
| 703 | # else | |
| 704 | # define _LIBCPP_TEMPLATE_DATA_VIS | |
| 705 | # endif | |
| 706 | #endif | |
| 707 | ||
| 692 | 708 | #ifndef _LIBCPP_EXPORTED_FROM_ABI |
| 693 | 709 | # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) |
| 694 | 710 | # define _LIBCPP_EXPORTED_FROM_ABI __attribute__((__visibility__("default"))) |
| ... | ... | @@ -792,10 +808,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD |
| 792 | 808 | |
| 793 | 809 | #define _VSTD_FS _VSTD::__fs::filesystem |
| 794 | 810 | |
| 795 | #ifndef _LIBCPP_PREFERRED_OVERLOAD | |
| 796 | # if __has_attribute(__enable_if__) | |
| 797 | # define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, ""))) | |
| 798 | # endif | |
| 811 | #if __has_attribute(__enable_if__) | |
| 812 | # define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, ""))) | |
| 799 | 813 | #endif |
| 800 | 814 | |
| 801 | 815 | #ifndef _LIBCPP_HAS_NO_NOEXCEPT |
| ... | ... | @@ -809,7 +823,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD |
| 809 | 823 | #ifdef _LIBCPP_HAS_NO_UNICODE_CHARS |
| 810 | 824 | typedef unsigned short char16_t; |
| 811 | 825 | typedef unsigned int char32_t; |
| 812 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 826 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 813 | 827 | |
| 814 | 828 | #ifndef __SIZEOF_INT128__ |
| 815 | 829 | #define _LIBCPP_HAS_NO_INT128 |
| ... | ... | @@ -818,7 +832,7 @@ typedef unsigned int char32_t; |
| 818 | 832 | #ifdef _LIBCPP_CXX03_LANG |
| 819 | 833 | # define static_assert(...) _Static_assert(__VA_ARGS__) |
| 820 | 834 | # define decltype(...) __decltype(__VA_ARGS__) |
| 821 | #endif // _LIBCPP_CXX03_LANG | |
| 835 | #endif // _LIBCPP_CXX03_LANG | |
| 822 | 836 | |
| 823 | 837 | #ifdef _LIBCPP_CXX03_LANG |
| 824 | 838 | # define _LIBCPP_CONSTEXPR |
| ... | ... | @@ -832,6 +846,14 @@ typedef unsigned int char32_t; |
| 832 | 846 | # define _LIBCPP_CONSTEVAL consteval |
| 833 | 847 | #endif |
| 834 | 848 | |
| 849 | #if !defined(__cpp_concepts) || __cpp_concepts < 201907L | |
| 850 | #define _LIBCPP_HAS_NO_CONCEPTS | |
| 851 | #endif | |
| 852 | ||
| 853 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 854 | #define _LIBCPP_HAS_NO_RANGES | |
| 855 | #endif | |
| 856 | ||
| 835 | 857 | #ifdef _LIBCPP_CXX03_LANG |
| 836 | 858 | # define _LIBCPP_DEFAULT {} |
| 837 | 859 | #else |
| ... | ... | @@ -850,11 +872,10 @@ typedef unsigned int char32_t; |
| 850 | 872 | # define _LIBCPP_NOALIAS |
| 851 | 873 | #endif |
| 852 | 874 | |
| 853 | #if __has_feature(cxx_explicit_conversions) || defined(__IBMCPP__) || \ | |
| 854 | (!defined(_LIBCPP_CXX03_LANG) && defined(__GNUC__)) // All supported GCC versions | |
| 855 | # define _LIBCPP_EXPLICIT explicit | |
| 875 | #if __has_attribute(using_if_exists) | |
| 876 | # define _LIBCPP_USING_IF_EXISTS __attribute__((using_if_exists)) | |
| 856 | 877 | #else |
| 857 | # define _LIBCPP_EXPLICIT | |
| 878 | # define _LIBCPP_USING_IF_EXISTS | |
| 858 | 879 | #endif |
| 859 | 880 | |
| 860 | 881 | #ifdef _LIBCPP_HAS_NO_STRONG_ENUMS |
| ... | ... | @@ -868,7 +889,7 @@ typedef unsigned int char32_t; |
| 868 | 889 | #else // _LIBCPP_HAS_NO_STRONG_ENUMS |
| 869 | 890 | # define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x |
| 870 | 891 | # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) |
| 871 | #endif // _LIBCPP_HAS_NO_STRONG_ENUMS | |
| 892 | #endif // _LIBCPP_HAS_NO_STRONG_ENUMS | |
| 872 | 893 | |
| 873 | 894 | // _LIBCPP_DEBUG potential values: |
| 874 | 895 | // - undefined: No assertions. This is the default. |
| ... | ... | @@ -884,33 +905,25 @@ typedef unsigned int char32_t; |
| 884 | 905 | # error Supported values for _LIBCPP_DEBUG are 0 and 1 |
| 885 | 906 | #endif |
| 886 | 907 | |
| 887 | // _LIBCPP_DEBUG_LEVEL is always defined to one of [0, 1, 2] at this point | |
| 888 | #if _LIBCPP_DEBUG_LEVEL >= 1 && !defined(_LIBCPP_DISABLE_EXTERN_TEMPLATE) | |
| 889 | # define _LIBCPP_EXTERN_TEMPLATE(...) | |
| 890 | #endif | |
| 891 | ||
| 892 | #ifdef _LIBCPP_DISABLE_EXTERN_TEMPLATE | |
| 893 | # define _LIBCPP_EXTERN_TEMPLATE(...) | |
| 894 | # define _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(...) | |
| 895 | #endif | |
| 896 | ||
| 897 | #ifndef _LIBCPP_EXTERN_TEMPLATE | |
| 898 | #define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__; | |
| 899 | #endif | |
| 900 | ||
| 901 | // When the Debug mode is enabled, we disable extern declarations because we | |
| 902 | // don't want to use the functions compiled in the library, which might not | |
| 903 | // have had the debug mode enabled when built. However, some extern declarations | |
| 904 | // need to be used, because code correctness depends on it (several instances | |
| 905 | // in the <locale>). Those special declarations are declared with | |
| 906 | // _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE, which is enabled even | |
| 907 | // when the debug mode is enabled. | |
| 908 | #ifndef _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE | |
| 909 | # define _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(...) extern template __VA_ARGS__; | |
| 910 | #endif | |
| 911 | ||
| 912 | #ifndef _LIBCPP_EXTERN_TEMPLATE_DEFINE | |
| 913 | #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; | |
| 908 | // Libc++ allows disabling extern template instantiation declarations by | |
| 909 | // means of users defining _LIBCPP_DISABLE_EXTERN_TEMPLATE. | |
| 910 | // | |
| 911 | // Furthermore, when the Debug mode is enabled, we disable extern declarations | |
| 912 | // when building user code because we don't want to use the functions compiled | |
| 913 | // in the library, which might not have had the debug mode enabled when built. | |
| 914 | // However, some extern declarations need to be used, because code correctness | |
| 915 | // depends on it (several instances in <locale>). Those special declarations | |
| 916 | // are declared with _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE, which is enabled | |
| 917 | // even when the debug mode is enabled. | |
| 918 | #if defined(_LIBCPP_DISABLE_EXTERN_TEMPLATE) | |
| 919 | # define _LIBCPP_EXTERN_TEMPLATE(...) /* nothing */ | |
| 920 | # define _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(...) /* nothing */ | |
| 921 | #elif _LIBCPP_DEBUG_LEVEL >= 1 && !defined(_LIBCPP_BUILDING_LIBRARY) | |
| 922 | # define _LIBCPP_EXTERN_TEMPLATE(...) /* nothing */ | |
| 923 | # define _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(...) extern template __VA_ARGS__; | |
| 924 | #else | |
| 925 | # define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__; | |
| 926 | # define _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(...) extern template __VA_ARGS__; | |
| 914 | 927 | #endif |
| 915 | 928 | |
| 916 | 929 | #if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || \ |
| ... | ... | @@ -918,13 +931,6 @@ typedef unsigned int char32_t; |
| 918 | 931 | #define _LIBCPP_LOCALE__L_EXTENSIONS 1 |
| 919 | 932 | #endif |
| 920 | 933 | |
| 921 | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | |
| 922 | // Most unix variants have catopen. These are the specific ones that don't. | |
| 923 | # if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) | |
| 924 | # define _LIBCPP_HAS_CATOPEN 1 | |
| 925 | # endif | |
| 926 | #endif | |
| 927 | ||
| 928 | 934 | #ifdef __FreeBSD__ |
| 929 | 935 | #define _DECLARE_C99_LDBL_MATH 1 |
| 930 | 936 | #endif |
| ... | ... | @@ -948,9 +954,8 @@ typedef unsigned int char32_t; |
| 948 | 954 | # endif |
| 949 | 955 | #endif // defined(__APPLE__) |
| 950 | 956 | |
| 951 | #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) && \ | |
| 952 | (defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) || \ | |
| 953 | (!defined(__cpp_aligned_new) || __cpp_aligned_new < 201606)) | |
| 957 | #if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) || \ | |
| 958 | (!defined(__cpp_aligned_new) || __cpp_aligned_new < 201606) | |
| 954 | 959 | # define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION |
| 955 | 960 | #endif |
| 956 | 961 | |
| ... | ... | @@ -963,7 +968,7 @@ typedef unsigned int char32_t; |
| 963 | 968 | #endif |
| 964 | 969 | |
| 965 | 970 | #if _LIBCPP_STD_VER <= 17 || !defined(__cpp_char8_t) |
| 966 | #define _LIBCPP_NO_HAS_CHAR8_T | |
| 971 | #define _LIBCPP_HAS_NO_CHAR8_T | |
| 967 | 972 | #endif |
| 968 | 973 | |
| 969 | 974 | // Deprecation macros. |
| ... | ... | @@ -1006,24 +1011,23 @@ typedef unsigned int char32_t; |
| 1006 | 1011 | # define _LIBCPP_DEPRECATED_IN_CXX20 |
| 1007 | 1012 | #endif |
| 1008 | 1013 | |
| 1009 | #if !defined(_LIBCPP_NO_HAS_CHAR8_T) | |
| 1014 | #if !defined(_LIBCPP_HAS_NO_CHAR8_T) | |
| 1010 | 1015 | # define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED |
| 1011 | 1016 | #else |
| 1012 | 1017 | # define _LIBCPP_DEPRECATED_WITH_CHAR8_T |
| 1013 | 1018 | #endif |
| 1014 | 1019 | |
| 1015 | 1020 | // Macros to enter and leave a state where deprecation warnings are suppressed. |
| 1016 | #if !defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) && \ | |
| 1017 | (defined(_LIBCPP_COMPILER_CLANG) || defined(_LIBCPP_COMPILER_GCC)) | |
| 1018 | # define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \ | |
| 1019 | _Pragma("GCC diagnostic push") \ | |
| 1020 | _Pragma("GCC diagnostic ignored \"-Wdeprecated\"") | |
| 1021 | # define _LIBCPP_SUPPRESS_DEPRECATED_POP \ | |
| 1022 | _Pragma("GCC diagnostic pop") | |
| 1023 | #endif | |
| 1024 | #if !defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) | |
| 1025 | # define _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 1026 | # define _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 1021 | #if defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_COMPILER_GCC) | |
| 1022 | # define _LIBCPP_SUPPRESS_DEPRECATED_PUSH \ | |
| 1023 | _Pragma("GCC diagnostic push") \ | |
| 1024 | _Pragma("GCC diagnostic ignored \"-Wdeprecated\"") \ | |
| 1025 | _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") | |
| 1026 | # define _LIBCPP_SUPPRESS_DEPRECATED_POP \ | |
| 1027 | _Pragma("GCC diagnostic pop") | |
| 1028 | #else | |
| 1029 | # define _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 1030 | # define _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 1027 | 1031 | #endif |
| 1028 | 1032 | |
| 1029 | 1033 | #if _LIBCPP_STD_VER <= 11 |
| ... | ... | @@ -1054,7 +1058,7 @@ typedef unsigned int char32_t; |
| 1054 | 1058 | // NODISCARD macros to the correct attribute. |
| 1055 | 1059 | #if __has_cpp_attribute(nodiscard) || defined(_LIBCPP_COMPILER_MSVC) |
| 1056 | 1060 | # define _LIBCPP_NODISCARD_ATTRIBUTE [[nodiscard]] |
| 1057 | #elif defined(_LIBCPP_COMPILER_CLANG) && !defined(_LIBCPP_CXX03_LANG) | |
| 1061 | #elif defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(_LIBCPP_CXX03_LANG) | |
| 1058 | 1062 | # define _LIBCPP_NODISCARD_ATTRIBUTE [[clang::warn_unused_result]] |
| 1059 | 1063 | #else |
| 1060 | 1064 | // We can't use GCC's [[gnu::warn_unused_result]] and |
| ... | ... | @@ -1084,12 +1088,10 @@ typedef unsigned int char32_t; |
| 1084 | 1088 | # define _LIBCPP_INLINE_VAR |
| 1085 | 1089 | #endif |
| 1086 | 1090 | |
| 1087 | #ifndef _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1088 | 1091 | #if defined(_LIBCPP_DEBUG) || defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) |
| 1089 | #define _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1092 | # define _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1090 | 1093 | #else |
| 1091 | #define _LIBCPP_CONSTEXPR_IF_NODEBUG constexpr | |
| 1092 | #endif | |
| 1094 | # define _LIBCPP_CONSTEXPR_IF_NODEBUG constexpr | |
| 1093 | 1095 | #endif |
| 1094 | 1096 | |
| 1095 | 1097 | #if __has_attribute(no_destroy) |
| ... | ... | @@ -1104,7 +1106,7 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1104 | 1106 | #endif |
| 1105 | 1107 | |
| 1106 | 1108 | // Try to find out if RTTI is disabled. |
| 1107 | #if defined(_LIBCPP_COMPILER_CLANG) && !__has_feature(cxx_rtti) | |
| 1109 | #if defined(_LIBCPP_COMPILER_CLANG_BASED) && !__has_feature(cxx_rtti) | |
| 1108 | 1110 | # define _LIBCPP_NO_RTTI |
| 1109 | 1111 | #elif defined(__GNUC__) && !defined(__GXX_RTTI) |
| 1110 | 1112 | # define _LIBCPP_NO_RTTI |
| ... | ... | @@ -1132,6 +1134,7 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1132 | 1134 | defined(__CloudABI__) || \ |
| 1133 | 1135 | defined(__sun__) || \ |
| 1134 | 1136 | defined(__MVS__) || \ |
| 1137 | defined(_AIX) || \ | |
| 1135 | 1138 | (defined(__MINGW32__) && __has_include(<pthread.h>)) |
| 1136 | 1139 | # define _LIBCPP_HAS_THREAD_API_PTHREAD |
| 1137 | 1140 | # elif defined(__Fuchsia__) |
| ... | ... | @@ -1218,12 +1221,10 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1218 | 1221 | #endif |
| 1219 | 1222 | |
| 1220 | 1223 | // Some systems do not provide gets() in their C library, for security reasons. |
| 1221 | #ifndef _LIBCPP_C_HAS_NO_GETS | |
| 1222 | # if defined(_LIBCPP_MSVCRT) || \ | |
| 1223 | (defined(__FreeBSD_version) && __FreeBSD_version >= 1300043) || \ | |
| 1224 | defined(__OpenBSD__) | |
| 1225 | # define _LIBCPP_C_HAS_NO_GETS | |
| 1226 | # endif | |
| 1224 | #if defined(_LIBCPP_MSVCRT) || \ | |
| 1225 | (defined(__FreeBSD_version) && __FreeBSD_version >= 1300043) || \ | |
| 1226 | defined(__OpenBSD__) | |
| 1227 | # define _LIBCPP_C_HAS_NO_GETS | |
| 1227 | 1228 | #endif |
| 1228 | 1229 | |
| 1229 | 1230 | #if defined(__BIONIC__) || defined(__CloudABI__) || defined(__NuttX__) || \ |
| ... | ... | @@ -1273,13 +1274,11 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1273 | 1274 | # endif |
| 1274 | 1275 | #endif |
| 1275 | 1276 | |
| 1276 | #ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION | |
| 1277 | # ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS | |
| 1278 | # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) | |
| 1279 | # else | |
| 1280 | # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) | |
| 1281 | # endif | |
| 1282 | #endif // _LIBCPP_THREAD_SAFETY_ANNOTATION | |
| 1277 | #ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS | |
| 1278 | # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) | |
| 1279 | #else | |
| 1280 | # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) | |
| 1281 | #endif | |
| 1283 | 1282 | |
| 1284 | 1283 | #if __has_attribute(require_constant_initialization) |
| 1285 | 1284 | # define _LIBCPP_SAFE_STATIC __attribute__((__require_constant_initialization__)) |
| ... | ... | @@ -1295,12 +1294,6 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1295 | 1294 | #define _LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED |
| 1296 | 1295 | #endif |
| 1297 | 1296 | |
| 1298 | #if !defined(_LIBCPP_HAS_NO_OFF_T_FUNCTIONS) | |
| 1299 | # if defined(_LIBCPP_MSVCRT) || defined(_NEWLIB_VERSION) | |
| 1300 | # define _LIBCPP_HAS_NO_OFF_T_FUNCTIONS | |
| 1301 | # endif | |
| 1302 | #endif | |
| 1303 | ||
| 1304 | 1297 | #if __has_attribute(diagnose_if) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) |
| 1305 | 1298 | # define _LIBCPP_DIAGNOSE_WARNING(...) \ |
| 1306 | 1299 | __attribute__((diagnose_if(__VA_ARGS__, "warning"))) |
| ... | ... | @@ -1328,14 +1321,17 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1328 | 1321 | #define _LIBCPP_NODEBUG |
| 1329 | 1322 | #endif |
| 1330 | 1323 | |
| 1331 | #ifndef _LIBCPP_NODEBUG_TYPE | |
| 1332 | #if __has_attribute(__nodebug__) && \ | |
| 1333 | (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 900) | |
| 1334 | #define _LIBCPP_NODEBUG_TYPE __attribute__((nodebug)) | |
| 1324 | #if __has_attribute(__nodebug__) && (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 900) | |
| 1325 | # define _LIBCPP_NODEBUG_TYPE __attribute__((nodebug)) | |
| 1335 | 1326 | #else |
| 1336 | #define _LIBCPP_NODEBUG_TYPE | |
| 1327 | # define _LIBCPP_NODEBUG_TYPE | |
| 1328 | #endif | |
| 1329 | ||
| 1330 | #if __has_attribute(__standalone_debug__) | |
| 1331 | #define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__)) | |
| 1332 | #else | |
| 1333 | #define _LIBCPP_STANDALONE_DEBUG | |
| 1337 | 1334 | #endif |
| 1338 | #endif // !defined(_LIBCPP_NODEBUG_TYPE) | |
| 1339 | 1335 | |
| 1340 | 1336 | #if __has_attribute(__preferred_name__) |
| 1341 | 1337 | #define _LIBCPP_PREFERRED_NAME(x) __attribute__((__preferred_name__(x))) |
| ... | ... | @@ -1352,11 +1348,19 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1352 | 1348 | |
| 1353 | 1349 | #if defined(_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES) |
| 1354 | 1350 | #define _LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR |
| 1355 | #define _LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS | |
| 1356 | #define _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE | |
| 1357 | 1351 | #define _LIBCPP_ENABLE_CXX17_REMOVED_BINDERS |
| 1352 | #define _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE | |
| 1353 | #define _LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS | |
| 1358 | 1354 | #endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES |
| 1359 | 1355 | |
| 1356 | #if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES) | |
| 1357 | #define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS | |
| 1358 | #define _LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS | |
| 1359 | #define _LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS | |
| 1360 | #define _LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR | |
| 1361 | #define _LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS | |
| 1362 | #endif // _LIBCPP_ENABLE_CXX20_REMOVED_FEATURES | |
| 1363 | ||
| 1360 | 1364 | #if !defined(__cpp_deduction_guides) || __cpp_deduction_guides < 201611 |
| 1361 | 1365 | #define _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 1362 | 1366 | #endif |
| ... | ... | @@ -1405,7 +1409,7 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1405 | 1409 | |
| 1406 | 1410 | #ifndef _LIBCPP_NO_AUTO_LINK |
| 1407 | 1411 | # if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY) |
| 1408 | # if defined(_DLL) | |
| 1412 | # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) | |
| 1409 | 1413 | # pragma comment(lib, "c++.lib") |
| 1410 | 1414 | # else |
| 1411 | 1415 | # pragma comment(lib, "libc++.lib") |
| ... | ... | @@ -1413,8 +1417,6 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1413 | 1417 | # endif // defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY) |
| 1414 | 1418 | #endif // _LIBCPP_NO_AUTO_LINK |
| 1415 | 1419 | |
| 1416 | #define _LIBCPP_UNUSED_VAR(x) ((void)(x)) | |
| 1417 | ||
| 1418 | 1420 | // Configures the fopen close-on-exec mode character, if any. This string will |
| 1419 | 1421 | // be appended to any mode string used by fstream for fopen/fdopen. |
| 1420 | 1422 | // |
| ... | ... | @@ -1445,6 +1447,13 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( |
| 1445 | 1447 | # define _LIBCPP_INIT_PRIORITY_MAX |
| 1446 | 1448 | #endif |
| 1447 | 1449 | |
| 1450 | #if defined(__GNUC__) || defined(__clang__) | |
| 1451 | #define _LIBCPP_FORMAT_PRINTF(a, b) \ | |
| 1452 | __attribute__((__format__(__printf__, a, b))) | |
| 1453 | #else | |
| 1454 | #define _LIBCPP_FORMAT_PRINTF(a, b) | |
| 1455 | #endif | |
| 1456 | ||
| 1448 | 1457 | #endif // __cplusplus |
| 1449 | 1458 | |
| 1450 | 1459 | #endif // _LIBCPP_CONFIG |
lib/libcxx/include/__config_site.in deleted-40| ... | ... | @@ -1,40 +0,0 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP_CONFIG_SITE | |
| 10 | #define _LIBCPP_CONFIG_SITE | |
| 11 | ||
| 12 | #cmakedefine _LIBCPP_ABI_VERSION @_LIBCPP_ABI_VERSION@ | |
| 13 | #cmakedefine _LIBCPP_ABI_UNSTABLE | |
| 14 | #cmakedefine _LIBCPP_ABI_FORCE_ITANIUM | |
| 15 | #cmakedefine _LIBCPP_ABI_FORCE_MICROSOFT | |
| 16 | #cmakedefine _LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT | |
| 17 | #cmakedefine _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE | |
| 18 | #cmakedefine _LIBCPP_HAS_NO_STDIN | |
| 19 | #cmakedefine _LIBCPP_HAS_NO_STDOUT | |
| 20 | #cmakedefine _LIBCPP_HAS_NO_THREADS | |
| 21 | #cmakedefine _LIBCPP_HAS_NO_MONOTONIC_CLOCK | |
| 22 | #cmakedefine _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS | |
| 23 | #cmakedefine _LIBCPP_HAS_MUSL_LIBC | |
| 24 | #cmakedefine _LIBCPP_HAS_THREAD_API_PTHREAD | |
| 25 | #cmakedefine _LIBCPP_HAS_THREAD_API_EXTERNAL | |
| 26 | #cmakedefine _LIBCPP_HAS_THREAD_API_WIN32 | |
| 27 | #cmakedefine _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL | |
| 28 | #cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS | |
| 29 | #cmakedefine _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS | |
| 30 | #cmakedefine _LIBCPP_NO_VCRUNTIME | |
| 31 | #cmakedefine _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION @_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION@ | |
| 32 | #cmakedefine _LIBCPP_ABI_NAMESPACE @_LIBCPP_ABI_NAMESPACE@ | |
| 33 | #cmakedefine _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY | |
| 34 | #cmakedefine _LIBCPP_HAS_PARALLEL_ALGORITHMS | |
| 35 | #cmakedefine _LIBCPP_HAS_NO_RANDOM_DEVICE | |
| 36 | #cmakedefine _LIBCPP_HAS_NO_LOCALIZATION | |
| 37 | ||
| 38 | @_LIBCPP_ABI_DEFINES@ | |
| 39 | ||
| 40 | #endif // _LIBCPP_CONFIG_SITE |
lib/libcxx/include/__debug+1-1| ... | ... | @@ -270,4 +270,4 @@ _LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); |
| 270 | 270 | |
| 271 | 271 | _LIBCPP_END_NAMESPACE_STD |
| 272 | 272 | |
| 273 | #endif // _LIBCPP_DEBUG_H | |
| 273 | #endif // _LIBCPP_DEBUG_H |
lib/libcxx/include/__errc+1-1| ... | ... | @@ -214,4 +214,4 @@ _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(errc) |
| 214 | 214 | |
| 215 | 215 | _LIBCPP_END_NAMESPACE_STD |
| 216 | 216 | |
| 217 | #endif // _LIBCPP___ERRC | |
| 217 | #endif // _LIBCPP___ERRC |
lib/libcxx/include/__format/format_error.h created+56| ... | ... | @@ -0,0 +1,56 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FORMAT_FORMAT_ERROR_H | |
| 11 | #define _LIBCPP___FORMAT_FORMAT_ERROR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <stdexcept> | |
| 15 | ||
| 16 | #ifdef _LIBCPP_NO_EXCEPTIONS | |
| 17 | #include <cstdlib> | |
| 18 | #endif | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | #if _LIBCPP_STD_VER > 17 | |
| 30 | ||
| 31 | class _LIBCPP_EXCEPTION_ABI format_error : public runtime_error { | |
| 32 | public: | |
| 33 | _LIBCPP_HIDE_FROM_ABI explicit format_error(const string& __s) | |
| 34 | : runtime_error(__s) {} | |
| 35 | _LIBCPP_HIDE_FROM_ABI explicit format_error(const char* __s) | |
| 36 | : runtime_error(__s) {} | |
| 37 | virtual ~format_error() noexcept; | |
| 38 | }; | |
| 39 | ||
| 40 | _LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void | |
| 41 | __throw_format_error(const char* __s) { | |
| 42 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 43 | throw format_error(__s); | |
| 44 | #else | |
| 45 | (void)__s; | |
| 46 | _VSTD::abort(); | |
| 47 | #endif | |
| 48 | } | |
| 49 | ||
| 50 | #endif //_LIBCPP_STD_VER > 17 | |
| 51 | ||
| 52 | _LIBCPP_END_NAMESPACE_STD | |
| 53 | ||
| 54 | _LIBCPP_POP_MACROS | |
| 55 | ||
| 56 | #endif // _LIBCPP___FORMAT_FORMAT_ERROR_H |
lib/libcxx/include/__format/format_parse_context.h created+113| ... | ... | @@ -0,0 +1,113 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H | |
| 11 | #define _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__format/format_error.h> | |
| 15 | #include <string_view> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if _LIBCPP_STD_VER > 17 | |
| 27 | ||
| 28 | // TODO FMT Remove this once we require compilers with proper C++20 support. | |
| 29 | // If the compiler has no concepts support, the format header will be disabled. | |
| 30 | // Without concepts support enable_if needs to be used and that too much effort | |
| 31 | // to support compilers with partial C++20 support. | |
| 32 | #if !defined(_LIBCPP_HAS_NO_CONCEPTS) && \ | |
| 33 | !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) | |
| 34 | ||
| 35 | template <class _CharT> | |
| 36 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_parse_context { | |
| 37 | public: | |
| 38 | using char_type = _CharT; | |
| 39 | using const_iterator = typename basic_string_view<_CharT>::const_iterator; | |
| 40 | using iterator = const_iterator; | |
| 41 | ||
| 42 | _LIBCPP_HIDE_FROM_ABI | |
| 43 | constexpr explicit basic_format_parse_context(basic_string_view<_CharT> __fmt, | |
| 44 | size_t __num_args = 0) noexcept | |
| 45 | : __begin_(__fmt.begin()), | |
| 46 | __end_(__fmt.end()), | |
| 47 | __indexing_(__unknown), | |
| 48 | __next_arg_id_(0), | |
| 49 | __num_args_(__num_args) {} | |
| 50 | ||
| 51 | basic_format_parse_context(const basic_format_parse_context&) = delete; | |
| 52 | basic_format_parse_context& | |
| 53 | operator=(const basic_format_parse_context&) = delete; | |
| 54 | ||
| 55 | _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept { | |
| 56 | return __begin_; | |
| 57 | } | |
| 58 | _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept { | |
| 59 | return __end_; | |
| 60 | } | |
| 61 | _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(const_iterator __it) { | |
| 62 | __begin_ = __it; | |
| 63 | } | |
| 64 | ||
| 65 | _LIBCPP_HIDE_FROM_ABI constexpr size_t next_arg_id() { | |
| 66 | if (__indexing_ == __manual) | |
| 67 | __throw_format_error("Using automatic argument numbering in manual " | |
| 68 | "argument numbering mode"); | |
| 69 | ||
| 70 | if (__indexing_ == __unknown) | |
| 71 | __indexing_ = __automatic; | |
| 72 | return __next_arg_id_++; | |
| 73 | } | |
| 74 | _LIBCPP_HIDE_FROM_ABI constexpr void check_arg_id(size_t __id) { | |
| 75 | if (__indexing_ == __automatic) | |
| 76 | __throw_format_error("Using manual argument numbering in automatic " | |
| 77 | "argument numbering mode"); | |
| 78 | ||
| 79 | if (__indexing_ == __unknown) | |
| 80 | __indexing_ = __manual; | |
| 81 | ||
| 82 | // Throws an exception to make the expression a non core constant | |
| 83 | // expression as required by: | |
| 84 | // [format.parse.ctx]/11 | |
| 85 | // Remarks: Call expressions where id >= num_args_ are not core constant | |
| 86 | // expressions ([expr.const]). | |
| 87 | // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the | |
| 88 | // behavior when id >= num_args_. | |
| 89 | if (is_constant_evaluated() && __id >= __num_args_) | |
| 90 | __throw_format_error("Argument index outside the valid range"); | |
| 91 | } | |
| 92 | ||
| 93 | private: | |
| 94 | iterator __begin_; | |
| 95 | iterator __end_; | |
| 96 | enum _Indexing { __unknown, __manual, __automatic }; | |
| 97 | _Indexing __indexing_; | |
| 98 | size_t __next_arg_id_; | |
| 99 | size_t __num_args_; | |
| 100 | }; | |
| 101 | ||
| 102 | using format_parse_context = basic_format_parse_context<char>; | |
| 103 | using wformat_parse_context = basic_format_parse_context<wchar_t>; | |
| 104 | ||
| 105 | #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) | |
| 106 | ||
| 107 | #endif //_LIBCPP_STD_VER > 17 | |
| 108 | ||
| 109 | _LIBCPP_END_NAMESPACE_STD | |
| 110 | ||
| 111 | _LIBCPP_POP_MACROS | |
| 112 | ||
| 113 | #endif // _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H |
lib/libcxx/include/__function_like.h created+56| ... | ... | @@ -0,0 +1,56 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_FUNCTION_LIKE_H | |
| 11 | #define _LIBCPP___ITERATOR_FUNCTION_LIKE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 25 | ||
| 26 | namespace ranges { | |
| 27 | // Per [range.iter.ops.general] and [algorithms.requirements], functions in namespace std::ranges | |
| 28 | // can't be found by ADL and inhibit ADL when found by unqualified lookup. The easiest way to | |
| 29 | // facilitate this is to use function objects. | |
| 30 | // | |
| 31 | // Since these are still standard library functions, we use `__function_like` to eliminate most of | |
| 32 | // the properties that function objects get by default (e.g. semiregularity, addressability), to | |
| 33 | // limit the surface area of the unintended public interface, so as to curb the effect of Hyrum's | |
| 34 | // law. | |
| 35 | struct __function_like { | |
| 36 | __function_like() = delete; | |
| 37 | __function_like(__function_like const&) = delete; | |
| 38 | __function_like& operator=(__function_like const&) = delete; | |
| 39 | ||
| 40 | void operator&() const = delete; | |
| 41 | ||
| 42 | struct __tag { }; | |
| 43 | ||
| 44 | protected: | |
| 45 | constexpr explicit __function_like(__tag) noexcept {} | |
| 46 | ~__function_like() = default; | |
| 47 | }; | |
| 48 | } // namespace ranges | |
| 49 | ||
| 50 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 51 | ||
| 52 | _LIBCPP_END_NAMESPACE_STD | |
| 53 | ||
| 54 | _LIBCPP_POP_MACROS | |
| 55 | ||
| 56 | #endif // _LIBCPP___ITERATOR_FUNCTION_LIKE_H |
lib/libcxx/include/__functional/binary_function.h created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_BINARY_FUNCTION_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_BINARY_FUNCTION_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 20 | ||
| 21 | template <class _Arg1, class _Arg2, class _Result> | |
| 22 | struct _LIBCPP_TEMPLATE_VIS binary_function | |
| 23 | { | |
| 24 | typedef _Arg1 first_argument_type; | |
| 25 | typedef _Arg2 second_argument_type; | |
| 26 | typedef _Result result_type; | |
| 27 | }; | |
| 28 | ||
| 29 | _LIBCPP_END_NAMESPACE_STD | |
| 30 | ||
| 31 | #endif // _LIBCPP___FUNCTIONAL_BINARY_FUNCTION_H |
lib/libcxx/include/__functional/binary_negate.h created+50| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_BINARY_NEGATE_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_BINARY_NEGATE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/binary_function.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) | |
| 23 | ||
| 24 | template <class _Predicate> | |
| 25 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 binary_negate | |
| 26 | : public binary_function<typename _Predicate::first_argument_type, | |
| 27 | typename _Predicate::second_argument_type, | |
| 28 | bool> | |
| 29 | { | |
| 30 | _Predicate __pred_; | |
| 31 | public: | |
| 32 | _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 33 | binary_negate(const _Predicate& __pred) : __pred_(__pred) {} | |
| 34 | ||
| 35 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 36 | bool operator()(const typename _Predicate::first_argument_type& __x, | |
| 37 | const typename _Predicate::second_argument_type& __y) const | |
| 38 | {return !__pred_(__x, __y);} | |
| 39 | }; | |
| 40 | ||
| 41 | template <class _Predicate> | |
| 42 | _LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 43 | binary_negate<_Predicate> | |
| 44 | not2(const _Predicate& __pred) {return binary_negate<_Predicate>(__pred);} | |
| 45 | ||
| 46 | #endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) | |
| 47 | ||
| 48 | _LIBCPP_END_NAMESPACE_STD | |
| 49 | ||
| 50 | #endif // _LIBCPP___FUNCTIONAL_BINARY_NEGATE_H |
lib/libcxx/include/__functional/bind.h created+386| ... | ... | @@ -0,0 +1,386 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_BIND_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_BIND_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/weak_result_type.h> | |
| 15 | #include <__functional/invoke.h> | |
| 16 | #include <cstddef> | |
| 17 | #include <tuple> | |
| 18 | #include <type_traits> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template<class _Tp> struct __is_bind_expression : public false_type {}; | |
| 27 | template<class _Tp> struct _LIBCPP_TEMPLATE_VIS is_bind_expression | |
| 28 | : public __is_bind_expression<typename remove_cv<_Tp>::type> {}; | |
| 29 | ||
| 30 | #if _LIBCPP_STD_VER > 14 | |
| 31 | template <class _Tp> | |
| 32 | _LIBCPP_INLINE_VAR constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; | |
| 33 | #endif | |
| 34 | ||
| 35 | template<class _Tp> struct __is_placeholder : public integral_constant<int, 0> {}; | |
| 36 | template<class _Tp> struct _LIBCPP_TEMPLATE_VIS is_placeholder | |
| 37 | : public __is_placeholder<typename remove_cv<_Tp>::type> {}; | |
| 38 | ||
| 39 | #if _LIBCPP_STD_VER > 14 | |
| 40 | template <class _Tp> | |
| 41 | _LIBCPP_INLINE_VAR constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value; | |
| 42 | #endif | |
| 43 | ||
| 44 | namespace placeholders | |
| 45 | { | |
| 46 | ||
| 47 | template <int _Np> struct __ph {}; | |
| 48 | ||
| 49 | #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 50 | _LIBCPP_FUNC_VIS extern const __ph<1> _1; | |
| 51 | _LIBCPP_FUNC_VIS extern const __ph<2> _2; | |
| 52 | _LIBCPP_FUNC_VIS extern const __ph<3> _3; | |
| 53 | _LIBCPP_FUNC_VIS extern const __ph<4> _4; | |
| 54 | _LIBCPP_FUNC_VIS extern const __ph<5> _5; | |
| 55 | _LIBCPP_FUNC_VIS extern const __ph<6> _6; | |
| 56 | _LIBCPP_FUNC_VIS extern const __ph<7> _7; | |
| 57 | _LIBCPP_FUNC_VIS extern const __ph<8> _8; | |
| 58 | _LIBCPP_FUNC_VIS extern const __ph<9> _9; | |
| 59 | _LIBCPP_FUNC_VIS extern const __ph<10> _10; | |
| 60 | #else | |
| 61 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<1> _1{}; | |
| 62 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<2> _2{}; | |
| 63 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<3> _3{}; | |
| 64 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<4> _4{}; | |
| 65 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<5> _5{}; | |
| 66 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<6> _6{}; | |
| 67 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<7> _7{}; | |
| 68 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<8> _8{}; | |
| 69 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<9> _9{}; | |
| 70 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<10> _10{}; | |
| 71 | #endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 72 | ||
| 73 | } // placeholders | |
| 74 | ||
| 75 | template<int _Np> | |
| 76 | struct __is_placeholder<placeholders::__ph<_Np> > | |
| 77 | : public integral_constant<int, _Np> {}; | |
| 78 | ||
| 79 | ||
| 80 | #ifndef _LIBCPP_CXX03_LANG | |
| 81 | ||
| 82 | template <class _Tp, class _Uj> | |
| 83 | inline _LIBCPP_INLINE_VISIBILITY | |
| 84 | _Tp& | |
| 85 | __mu(reference_wrapper<_Tp> __t, _Uj&) | |
| 86 | { | |
| 87 | return __t.get(); | |
| 88 | } | |
| 89 | ||
| 90 | template <class _Ti, class ..._Uj, size_t ..._Indx> | |
| 91 | inline _LIBCPP_INLINE_VISIBILITY | |
| 92 | typename __invoke_of<_Ti&, _Uj...>::type | |
| 93 | __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) | |
| 94 | { | |
| 95 | return __ti(_VSTD::forward<_Uj>(_VSTD::get<_Indx>(__uj))...); | |
| 96 | } | |
| 97 | ||
| 98 | template <class _Ti, class ..._Uj> | |
| 99 | inline _LIBCPP_INLINE_VISIBILITY | |
| 100 | typename _EnableIf | |
| 101 | < | |
| 102 | is_bind_expression<_Ti>::value, | |
| 103 | __invoke_of<_Ti&, _Uj...> | |
| 104 | >::type | |
| 105 | __mu(_Ti& __ti, tuple<_Uj...>& __uj) | |
| 106 | { | |
| 107 | typedef typename __make_tuple_indices<sizeof...(_Uj)>::type __indices; | |
| 108 | return _VSTD::__mu_expand(__ti, __uj, __indices()); | |
| 109 | } | |
| 110 | ||
| 111 | template <bool IsPh, class _Ti, class _Uj> | |
| 112 | struct __mu_return2 {}; | |
| 113 | ||
| 114 | template <class _Ti, class _Uj> | |
| 115 | struct __mu_return2<true, _Ti, _Uj> | |
| 116 | { | |
| 117 | typedef typename tuple_element<is_placeholder<_Ti>::value - 1, _Uj>::type type; | |
| 118 | }; | |
| 119 | ||
| 120 | template <class _Ti, class _Uj> | |
| 121 | inline _LIBCPP_INLINE_VISIBILITY | |
| 122 | typename enable_if | |
| 123 | < | |
| 124 | 0 < is_placeholder<_Ti>::value, | |
| 125 | typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type | |
| 126 | >::type | |
| 127 | __mu(_Ti&, _Uj& __uj) | |
| 128 | { | |
| 129 | const size_t _Indx = is_placeholder<_Ti>::value - 1; | |
| 130 | return _VSTD::forward<typename tuple_element<_Indx, _Uj>::type>(_VSTD::get<_Indx>(__uj)); | |
| 131 | } | |
| 132 | ||
| 133 | template <class _Ti, class _Uj> | |
| 134 | inline _LIBCPP_INLINE_VISIBILITY | |
| 135 | typename enable_if | |
| 136 | < | |
| 137 | !is_bind_expression<_Ti>::value && | |
| 138 | is_placeholder<_Ti>::value == 0 && | |
| 139 | !__is_reference_wrapper<_Ti>::value, | |
| 140 | _Ti& | |
| 141 | >::type | |
| 142 | __mu(_Ti& __ti, _Uj&) | |
| 143 | { | |
| 144 | return __ti; | |
| 145 | } | |
| 146 | ||
| 147 | template <class _Ti, bool IsReferenceWrapper, bool IsBindEx, bool IsPh, | |
| 148 | class _TupleUj> | |
| 149 | struct __mu_return_impl; | |
| 150 | ||
| 151 | template <bool _Invokable, class _Ti, class ..._Uj> | |
| 152 | struct __mu_return_invokable // false | |
| 153 | { | |
| 154 | typedef __nat type; | |
| 155 | }; | |
| 156 | ||
| 157 | template <class _Ti, class ..._Uj> | |
| 158 | struct __mu_return_invokable<true, _Ti, _Uj...> | |
| 159 | { | |
| 160 | typedef typename __invoke_of<_Ti&, _Uj...>::type type; | |
| 161 | }; | |
| 162 | ||
| 163 | template <class _Ti, class ..._Uj> | |
| 164 | struct __mu_return_impl<_Ti, false, true, false, tuple<_Uj...> > | |
| 165 | : public __mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...> | |
| 166 | { | |
| 167 | }; | |
| 168 | ||
| 169 | template <class _Ti, class _TupleUj> | |
| 170 | struct __mu_return_impl<_Ti, false, false, true, _TupleUj> | |
| 171 | { | |
| 172 | typedef typename tuple_element<is_placeholder<_Ti>::value - 1, | |
| 173 | _TupleUj>::type&& type; | |
| 174 | }; | |
| 175 | ||
| 176 | template <class _Ti, class _TupleUj> | |
| 177 | struct __mu_return_impl<_Ti, true, false, false, _TupleUj> | |
| 178 | { | |
| 179 | typedef typename _Ti::type& type; | |
| 180 | }; | |
| 181 | ||
| 182 | template <class _Ti, class _TupleUj> | |
| 183 | struct __mu_return_impl<_Ti, false, false, false, _TupleUj> | |
| 184 | { | |
| 185 | typedef _Ti& type; | |
| 186 | }; | |
| 187 | ||
| 188 | template <class _Ti, class _TupleUj> | |
| 189 | struct __mu_return | |
| 190 | : public __mu_return_impl<_Ti, | |
| 191 | __is_reference_wrapper<_Ti>::value, | |
| 192 | is_bind_expression<_Ti>::value, | |
| 193 | 0 < is_placeholder<_Ti>::value && | |
| 194 | is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value, | |
| 195 | _TupleUj> | |
| 196 | { | |
| 197 | }; | |
| 198 | ||
| 199 | template <class _Fp, class _BoundArgs, class _TupleUj> | |
| 200 | struct __is_valid_bind_return | |
| 201 | { | |
| 202 | static const bool value = false; | |
| 203 | }; | |
| 204 | ||
| 205 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 206 | struct __is_valid_bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj> | |
| 207 | { | |
| 208 | static const bool value = __invokable<_Fp, | |
| 209 | typename __mu_return<_BoundArgs, _TupleUj>::type...>::value; | |
| 210 | }; | |
| 211 | ||
| 212 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 213 | struct __is_valid_bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj> | |
| 214 | { | |
| 215 | static const bool value = __invokable<_Fp, | |
| 216 | typename __mu_return<const _BoundArgs, _TupleUj>::type...>::value; | |
| 217 | }; | |
| 218 | ||
| 219 | template <class _Fp, class _BoundArgs, class _TupleUj, | |
| 220 | bool = __is_valid_bind_return<_Fp, _BoundArgs, _TupleUj>::value> | |
| 221 | struct __bind_return; | |
| 222 | ||
| 223 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 224 | struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true> | |
| 225 | { | |
| 226 | typedef typename __invoke_of | |
| 227 | < | |
| 228 | _Fp&, | |
| 229 | typename __mu_return | |
| 230 | < | |
| 231 | _BoundArgs, | |
| 232 | _TupleUj | |
| 233 | >::type... | |
| 234 | >::type type; | |
| 235 | }; | |
| 236 | ||
| 237 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 238 | struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> | |
| 239 | { | |
| 240 | typedef typename __invoke_of | |
| 241 | < | |
| 242 | _Fp&, | |
| 243 | typename __mu_return | |
| 244 | < | |
| 245 | const _BoundArgs, | |
| 246 | _TupleUj | |
| 247 | >::type... | |
| 248 | >::type type; | |
| 249 | }; | |
| 250 | ||
| 251 | template <class _Fp, class _BoundArgs, size_t ..._Indx, class _Args> | |
| 252 | inline _LIBCPP_INLINE_VISIBILITY | |
| 253 | typename __bind_return<_Fp, _BoundArgs, _Args>::type | |
| 254 | __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, | |
| 255 | _Args&& __args) | |
| 256 | { | |
| 257 | return _VSTD::__invoke(__f, _VSTD::__mu(_VSTD::get<_Indx>(__bound_args), __args)...); | |
| 258 | } | |
| 259 | ||
| 260 | template<class _Fp, class ..._BoundArgs> | |
| 261 | class __bind | |
| 262 | #if _LIBCPP_STD_VER <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 263 | : public __weak_result_type<typename decay<_Fp>::type> | |
| 264 | #endif | |
| 265 | { | |
| 266 | protected: | |
| 267 | typedef typename decay<_Fp>::type _Fd; | |
| 268 | typedef tuple<typename decay<_BoundArgs>::type...> _Td; | |
| 269 | private: | |
| 270 | _Fd __f_; | |
| 271 | _Td __bound_args_; | |
| 272 | ||
| 273 | typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices; | |
| 274 | public: | |
| 275 | template <class _Gp, class ..._BA, | |
| 276 | class = typename enable_if | |
| 277 | < | |
| 278 | is_constructible<_Fd, _Gp>::value && | |
| 279 | !is_same<typename remove_reference<_Gp>::type, | |
| 280 | __bind>::value | |
| 281 | >::type> | |
| 282 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 283 | explicit __bind(_Gp&& __f, _BA&& ...__bound_args) | |
| 284 | : __f_(_VSTD::forward<_Gp>(__f)), | |
| 285 | __bound_args_(_VSTD::forward<_BA>(__bound_args)...) {} | |
| 286 | ||
| 287 | template <class ..._Args> | |
| 288 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 289 | typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type | |
| 290 | operator()(_Args&& ...__args) | |
| 291 | { | |
| 292 | return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), | |
| 293 | tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); | |
| 294 | } | |
| 295 | ||
| 296 | template <class ..._Args> | |
| 297 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 298 | typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type | |
| 299 | operator()(_Args&& ...__args) const | |
| 300 | { | |
| 301 | return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), | |
| 302 | tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); | |
| 303 | } | |
| 304 | }; | |
| 305 | ||
| 306 | template<class _Fp, class ..._BoundArgs> | |
| 307 | struct __is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; | |
| 308 | ||
| 309 | template<class _Rp, class _Fp, class ..._BoundArgs> | |
| 310 | class __bind_r | |
| 311 | : public __bind<_Fp, _BoundArgs...> | |
| 312 | { | |
| 313 | typedef __bind<_Fp, _BoundArgs...> base; | |
| 314 | typedef typename base::_Fd _Fd; | |
| 315 | typedef typename base::_Td _Td; | |
| 316 | public: | |
| 317 | typedef _Rp result_type; | |
| 318 | ||
| 319 | ||
| 320 | template <class _Gp, class ..._BA, | |
| 321 | class = typename enable_if | |
| 322 | < | |
| 323 | is_constructible<_Fd, _Gp>::value && | |
| 324 | !is_same<typename remove_reference<_Gp>::type, | |
| 325 | __bind_r>::value | |
| 326 | >::type> | |
| 327 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 328 | explicit __bind_r(_Gp&& __f, _BA&& ...__bound_args) | |
| 329 | : base(_VSTD::forward<_Gp>(__f), | |
| 330 | _VSTD::forward<_BA>(__bound_args)...) {} | |
| 331 | ||
| 332 | template <class ..._Args> | |
| 333 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 334 | typename enable_if | |
| 335 | < | |
| 336 | is_convertible<typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type, | |
| 337 | result_type>::value || is_void<_Rp>::value, | |
| 338 | result_type | |
| 339 | >::type | |
| 340 | operator()(_Args&& ...__args) | |
| 341 | { | |
| 342 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 343 | return _Invoker::__call(static_cast<base&>(*this), _VSTD::forward<_Args>(__args)...); | |
| 344 | } | |
| 345 | ||
| 346 | template <class ..._Args> | |
| 347 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 348 | typename enable_if | |
| 349 | < | |
| 350 | is_convertible<typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type, | |
| 351 | result_type>::value || is_void<_Rp>::value, | |
| 352 | result_type | |
| 353 | >::type | |
| 354 | operator()(_Args&& ...__args) const | |
| 355 | { | |
| 356 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 357 | return _Invoker::__call(static_cast<base const&>(*this), _VSTD::forward<_Args>(__args)...); | |
| 358 | } | |
| 359 | }; | |
| 360 | ||
| 361 | template<class _Rp, class _Fp, class ..._BoundArgs> | |
| 362 | struct __is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; | |
| 363 | ||
| 364 | template<class _Fp, class ..._BoundArgs> | |
| 365 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 366 | __bind<_Fp, _BoundArgs...> | |
| 367 | bind(_Fp&& __f, _BoundArgs&&... __bound_args) | |
| 368 | { | |
| 369 | typedef __bind<_Fp, _BoundArgs...> type; | |
| 370 | return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); | |
| 371 | } | |
| 372 | ||
| 373 | template<class _Rp, class _Fp, class ..._BoundArgs> | |
| 374 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 375 | __bind_r<_Rp, _Fp, _BoundArgs...> | |
| 376 | bind(_Fp&& __f, _BoundArgs&&... __bound_args) | |
| 377 | { | |
| 378 | typedef __bind_r<_Rp, _Fp, _BoundArgs...> type; | |
| 379 | return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); | |
| 380 | } | |
| 381 | ||
| 382 | #endif // _LIBCPP_CXX03_LANG | |
| 383 | ||
| 384 | _LIBCPP_END_NAMESPACE_STD | |
| 385 | ||
| 386 | #endif // _LIBCPP___FUNCTIONAL_BIND_H |
lib/libcxx/include/__functional/bind_front.h created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_BIND_FRONT_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_BIND_FRONT_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/perfect_forward.h> | |
| 15 | #include <__functional/invoke.h> | |
| 16 | #include <type_traits> | |
| 17 | #include <utility> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if _LIBCPP_STD_VER > 17 | |
| 26 | ||
| 27 | struct __bind_front_op | |
| 28 | { | |
| 29 | template<class... _Args> | |
| 30 | constexpr static auto __call(_Args&&... __args) | |
| 31 | noexcept(noexcept(_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) | |
| 32 | -> decltype( _VSTD::invoke(_VSTD::forward<_Args>(__args)...)) | |
| 33 | { return _VSTD::invoke(_VSTD::forward<_Args>(__args)...); } | |
| 34 | }; | |
| 35 | ||
| 36 | template<class _Fn, class... _Args, | |
| 37 | class = _EnableIf<conjunction<is_constructible<decay_t<_Fn>, _Fn>, | |
| 38 | is_move_constructible<decay_t<_Fn>>, | |
| 39 | is_constructible<decay_t<_Args>, _Args>..., | |
| 40 | is_move_constructible<decay_t<_Args>>... | |
| 41 | >::value>> | |
| 42 | constexpr auto bind_front(_Fn&& __f, _Args&&... __args) | |
| 43 | { | |
| 44 | return __perfect_forward<__bind_front_op, _Fn, _Args...>(_VSTD::forward<_Fn>(__f), | |
| 45 | _VSTD::forward<_Args>(__args)...); | |
| 46 | } | |
| 47 | ||
| 48 | #endif // _LIBCPP_STD_VER > 17 | |
| 49 | ||
| 50 | _LIBCPP_END_NAMESPACE_STD | |
| 51 | ||
| 52 | #endif // _LIBCPP___FUNCTIONAL_BIND_FRONT_H |
lib/libcxx/include/__functional/binder1st.h created+54| ... | ... | @@ -0,0 +1,54 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_BINDER1ST_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_BINDER1ST_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/unary_function.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 23 | ||
| 24 | template <class __Operation> | |
| 25 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder1st | |
| 26 | : public unary_function<typename __Operation::second_argument_type, | |
| 27 | typename __Operation::result_type> | |
| 28 | { | |
| 29 | protected: | |
| 30 | __Operation op; | |
| 31 | typename __Operation::first_argument_type value; | |
| 32 | public: | |
| 33 | _LIBCPP_INLINE_VISIBILITY binder1st(const __Operation& __x, | |
| 34 | const typename __Operation::first_argument_type __y) | |
| 35 | : op(__x), value(__y) {} | |
| 36 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 37 | (typename __Operation::second_argument_type& __x) const | |
| 38 | {return op(value, __x);} | |
| 39 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 40 | (const typename __Operation::second_argument_type& __x) const | |
| 41 | {return op(value, __x);} | |
| 42 | }; | |
| 43 | ||
| 44 | template <class __Operation, class _Tp> | |
| 45 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 46 | binder1st<__Operation> | |
| 47 | bind1st(const __Operation& __op, const _Tp& __x) | |
| 48 | {return binder1st<__Operation>(__op, __x);} | |
| 49 | ||
| 50 | #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 51 | ||
| 52 | _LIBCPP_END_NAMESPACE_STD | |
| 53 | ||
| 54 | #endif // _LIBCPP___FUNCTIONAL_BINDER1ST_H |
lib/libcxx/include/__functional/binder2nd.h created+54| ... | ... | @@ -0,0 +1,54 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_BINDER2ND_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_BINDER2ND_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/unary_function.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 23 | ||
| 24 | template <class __Operation> | |
| 25 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder2nd | |
| 26 | : public unary_function<typename __Operation::first_argument_type, | |
| 27 | typename __Operation::result_type> | |
| 28 | { | |
| 29 | protected: | |
| 30 | __Operation op; | |
| 31 | typename __Operation::second_argument_type value; | |
| 32 | public: | |
| 33 | _LIBCPP_INLINE_VISIBILITY | |
| 34 | binder2nd(const __Operation& __x, const typename __Operation::second_argument_type __y) | |
| 35 | : op(__x), value(__y) {} | |
| 36 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 37 | ( typename __Operation::first_argument_type& __x) const | |
| 38 | {return op(__x, value);} | |
| 39 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 40 | (const typename __Operation::first_argument_type& __x) const | |
| 41 | {return op(__x, value);} | |
| 42 | }; | |
| 43 | ||
| 44 | template <class __Operation, class _Tp> | |
| 45 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 46 | binder2nd<__Operation> | |
| 47 | bind2nd(const __Operation& __op, const _Tp& __x) | |
| 48 | {return binder2nd<__Operation>(__op, __x);} | |
| 49 | ||
| 50 | #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 51 | ||
| 52 | _LIBCPP_END_NAMESPACE_STD | |
| 53 | ||
| 54 | #endif // _LIBCPP___FUNCTIONAL_BINDER2ND_H |
lib/libcxx/include/__functional/default_searcher.h created+56| ... | ... | @@ -0,0 +1,56 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_DEFAULT_SEARCHER_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_DEFAULT_SEARCHER_H | |
| 12 | ||
| 13 | #include <__algorithm/search.h> | |
| 14 | #include <__config> | |
| 15 | #include <__functional/operations.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <utility> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if _LIBCPP_STD_VER > 14 | |
| 26 | ||
| 27 | // default searcher | |
| 28 | template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> | |
| 29 | class _LIBCPP_TEMPLATE_VIS default_searcher { | |
| 30 | public: | |
| 31 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 32 | default_searcher(_ForwardIterator __f, _ForwardIterator __l, | |
| 33 | _BinaryPredicate __p = _BinaryPredicate()) | |
| 34 | : __first_(__f), __last_(__l), __pred_(__p) {} | |
| 35 | ||
| 36 | template <typename _ForwardIterator2> | |
| 37 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 38 | pair<_ForwardIterator2, _ForwardIterator2> | |
| 39 | operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const | |
| 40 | { | |
| 41 | return _VSTD::__search(__f, __l, __first_, __last_, __pred_, | |
| 42 | typename iterator_traits<_ForwardIterator>::iterator_category(), | |
| 43 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 44 | } | |
| 45 | ||
| 46 | private: | |
| 47 | _ForwardIterator __first_; | |
| 48 | _ForwardIterator __last_; | |
| 49 | _BinaryPredicate __pred_; | |
| 50 | }; | |
| 51 | ||
| 52 | #endif // _LIBCPP_STD_VER > 14 | |
| 53 | ||
| 54 | _LIBCPP_END_NAMESPACE_STD | |
| 55 | ||
| 56 | #endif // _LIBCPP___FUNCTIONAL_DEFAULT_SEARCHER_H |
lib/libcxx/include/__functional/function.h created+2809| ... | ... | @@ -0,0 +1,2809 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_FUNCTION_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_FUNCTION_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/binary_function.h> | |
| 15 | #include <__functional/invoke.h> | |
| 16 | #include <__functional/unary_function.h> | |
| 17 | #include <__iterator/iterator_traits.h> | |
| 18 | #include <__memory/allocator_traits.h> | |
| 19 | #include <__memory/compressed_pair.h> | |
| 20 | #include <__memory/shared_ptr.h> | |
| 21 | #include <exception> | |
| 22 | #include <memory> // TODO: replace with <__memory/__builtin_new_allocator.h> | |
| 23 | #include <type_traits> | |
| 24 | #include <utility> | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 27 | #pragma GCC system_header | |
| 28 | #endif | |
| 29 | ||
| 30 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 31 | ||
| 32 | // bad_function_call | |
| 33 | ||
| 34 | class _LIBCPP_EXCEPTION_ABI bad_function_call | |
| 35 | : public exception | |
| 36 | { | |
| 37 | #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION | |
| 38 | public: | |
| 39 | virtual ~bad_function_call() _NOEXCEPT; | |
| 40 | ||
| 41 | virtual const char* what() const _NOEXCEPT; | |
| 42 | #endif | |
| 43 | }; | |
| 44 | ||
| 45 | _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY | |
| 46 | void __throw_bad_function_call() | |
| 47 | { | |
| 48 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 49 | throw bad_function_call(); | |
| 50 | #else | |
| 51 | _VSTD::abort(); | |
| 52 | #endif | |
| 53 | } | |
| 54 | ||
| 55 | #if defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) && __has_attribute(deprecated) | |
| 56 | # define _LIBCPP_DEPRECATED_CXX03_FUNCTION \ | |
| 57 | __attribute__((deprecated("Using std::function in C++03 is not supported anymore. Please upgrade to C++11 or later, or use a different type"))) | |
| 58 | #else | |
| 59 | # define _LIBCPP_DEPRECATED_CXX03_FUNCTION /* nothing */ | |
| 60 | #endif | |
| 61 | ||
| 62 | template<class _Fp> class _LIBCPP_DEPRECATED_CXX03_FUNCTION _LIBCPP_TEMPLATE_VIS function; // undefined | |
| 63 | ||
| 64 | namespace __function | |
| 65 | { | |
| 66 | ||
| 67 | template<class _Rp> | |
| 68 | struct __maybe_derive_from_unary_function | |
| 69 | { | |
| 70 | }; | |
| 71 | ||
| 72 | template<class _Rp, class _A1> | |
| 73 | struct __maybe_derive_from_unary_function<_Rp(_A1)> | |
| 74 | : public unary_function<_A1, _Rp> | |
| 75 | { | |
| 76 | }; | |
| 77 | ||
| 78 | template<class _Rp> | |
| 79 | struct __maybe_derive_from_binary_function | |
| 80 | { | |
| 81 | }; | |
| 82 | ||
| 83 | template<class _Rp, class _A1, class _A2> | |
| 84 | struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> | |
| 85 | : public binary_function<_A1, _A2, _Rp> | |
| 86 | { | |
| 87 | }; | |
| 88 | ||
| 89 | template <class _Fp> | |
| 90 | _LIBCPP_INLINE_VISIBILITY | |
| 91 | bool __not_null(_Fp const&) { return true; } | |
| 92 | ||
| 93 | template <class _Fp> | |
| 94 | _LIBCPP_INLINE_VISIBILITY | |
| 95 | bool __not_null(_Fp* __ptr) { return __ptr; } | |
| 96 | ||
| 97 | template <class _Ret, class _Class> | |
| 98 | _LIBCPP_INLINE_VISIBILITY | |
| 99 | bool __not_null(_Ret _Class::*__ptr) { return __ptr; } | |
| 100 | ||
| 101 | template <class _Fp> | |
| 102 | _LIBCPP_INLINE_VISIBILITY | |
| 103 | bool __not_null(function<_Fp> const& __f) { return !!__f; } | |
| 104 | ||
| 105 | #ifdef _LIBCPP_HAS_EXTENSION_BLOCKS | |
| 106 | template <class _Rp, class ..._Args> | |
| 107 | _LIBCPP_INLINE_VISIBILITY | |
| 108 | bool __not_null(_Rp (^__p)(_Args...)) { return __p; } | |
| 109 | #endif | |
| 110 | ||
| 111 | } // namespace __function | |
| 112 | ||
| 113 | #ifndef _LIBCPP_CXX03_LANG | |
| 114 | ||
| 115 | namespace __function { | |
| 116 | ||
| 117 | // __alloc_func holds a functor and an allocator. | |
| 118 | ||
| 119 | template <class _Fp, class _Ap, class _FB> class __alloc_func; | |
| 120 | template <class _Fp, class _FB> | |
| 121 | class __default_alloc_func; | |
| 122 | ||
| 123 | template <class _Fp, class _Ap, class _Rp, class... _ArgTypes> | |
| 124 | class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> | |
| 125 | { | |
| 126 | __compressed_pair<_Fp, _Ap> __f_; | |
| 127 | ||
| 128 | public: | |
| 129 | typedef _LIBCPP_NODEBUG_TYPE _Fp _Target; | |
| 130 | typedef _LIBCPP_NODEBUG_TYPE _Ap _Alloc; | |
| 131 | ||
| 132 | _LIBCPP_INLINE_VISIBILITY | |
| 133 | const _Target& __target() const { return __f_.first(); } | |
| 134 | ||
| 135 | // WIN32 APIs may define __allocator, so use __get_allocator instead. | |
| 136 | _LIBCPP_INLINE_VISIBILITY | |
| 137 | const _Alloc& __get_allocator() const { return __f_.second(); } | |
| 138 | ||
| 139 | _LIBCPP_INLINE_VISIBILITY | |
| 140 | explicit __alloc_func(_Target&& __f) | |
| 141 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), | |
| 142 | _VSTD::forward_as_tuple()) | |
| 143 | { | |
| 144 | } | |
| 145 | ||
| 146 | _LIBCPP_INLINE_VISIBILITY | |
| 147 | explicit __alloc_func(const _Target& __f, const _Alloc& __a) | |
| 148 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), | |
| 149 | _VSTD::forward_as_tuple(__a)) | |
| 150 | { | |
| 151 | } | |
| 152 | ||
| 153 | _LIBCPP_INLINE_VISIBILITY | |
| 154 | explicit __alloc_func(const _Target& __f, _Alloc&& __a) | |
| 155 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), | |
| 156 | _VSTD::forward_as_tuple(_VSTD::move(__a))) | |
| 157 | { | |
| 158 | } | |
| 159 | ||
| 160 | _LIBCPP_INLINE_VISIBILITY | |
| 161 | explicit __alloc_func(_Target&& __f, _Alloc&& __a) | |
| 162 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), | |
| 163 | _VSTD::forward_as_tuple(_VSTD::move(__a))) | |
| 164 | { | |
| 165 | } | |
| 166 | ||
| 167 | _LIBCPP_INLINE_VISIBILITY | |
| 168 | _Rp operator()(_ArgTypes&&... __arg) | |
| 169 | { | |
| 170 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 171 | return _Invoker::__call(__f_.first(), | |
| 172 | _VSTD::forward<_ArgTypes>(__arg)...); | |
| 173 | } | |
| 174 | ||
| 175 | _LIBCPP_INLINE_VISIBILITY | |
| 176 | __alloc_func* __clone() const | |
| 177 | { | |
| 178 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 179 | typedef | |
| 180 | typename __rebind_alloc_helper<__alloc_traits, __alloc_func>::type | |
| 181 | _AA; | |
| 182 | _AA __a(__f_.second()); | |
| 183 | typedef __allocator_destructor<_AA> _Dp; | |
| 184 | unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 185 | ::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a)); | |
| 186 | return __hold.release(); | |
| 187 | } | |
| 188 | ||
| 189 | _LIBCPP_INLINE_VISIBILITY | |
| 190 | void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); } | |
| 191 | ||
| 192 | static void __destroy_and_delete(__alloc_func* __f) { | |
| 193 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 194 | typedef typename __rebind_alloc_helper<__alloc_traits, __alloc_func>::type | |
| 195 | _FunAlloc; | |
| 196 | _FunAlloc __a(__f->__get_allocator()); | |
| 197 | __f->destroy(); | |
| 198 | __a.deallocate(__f, 1); | |
| 199 | } | |
| 200 | }; | |
| 201 | ||
| 202 | template <class _Fp, class _Rp, class... _ArgTypes> | |
| 203 | class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> { | |
| 204 | _Fp __f_; | |
| 205 | ||
| 206 | public: | |
| 207 | typedef _LIBCPP_NODEBUG_TYPE _Fp _Target; | |
| 208 | ||
| 209 | _LIBCPP_INLINE_VISIBILITY | |
| 210 | const _Target& __target() const { return __f_; } | |
| 211 | ||
| 212 | _LIBCPP_INLINE_VISIBILITY | |
| 213 | explicit __default_alloc_func(_Target&& __f) : __f_(_VSTD::move(__f)) {} | |
| 214 | ||
| 215 | _LIBCPP_INLINE_VISIBILITY | |
| 216 | explicit __default_alloc_func(const _Target& __f) : __f_(__f) {} | |
| 217 | ||
| 218 | _LIBCPP_INLINE_VISIBILITY | |
| 219 | _Rp operator()(_ArgTypes&&... __arg) { | |
| 220 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 221 | return _Invoker::__call(__f_, _VSTD::forward<_ArgTypes>(__arg)...); | |
| 222 | } | |
| 223 | ||
| 224 | _LIBCPP_INLINE_VISIBILITY | |
| 225 | __default_alloc_func* __clone() const { | |
| 226 | __builtin_new_allocator::__holder_t __hold = | |
| 227 | __builtin_new_allocator::__allocate_type<__default_alloc_func>(1); | |
| 228 | __default_alloc_func* __res = | |
| 229 | ::new ((void*)__hold.get()) __default_alloc_func(__f_); | |
| 230 | (void)__hold.release(); | |
| 231 | return __res; | |
| 232 | } | |
| 233 | ||
| 234 | _LIBCPP_INLINE_VISIBILITY | |
| 235 | void destroy() _NOEXCEPT { __f_.~_Target(); } | |
| 236 | ||
| 237 | static void __destroy_and_delete(__default_alloc_func* __f) { | |
| 238 | __f->destroy(); | |
| 239 | __builtin_new_allocator::__deallocate_type<__default_alloc_func>(__f, 1); | |
| 240 | } | |
| 241 | }; | |
| 242 | ||
| 243 | // __base provides an abstract interface for copyable functors. | |
| 244 | ||
| 245 | template<class _Fp> class _LIBCPP_TEMPLATE_VIS __base; | |
| 246 | ||
| 247 | template<class _Rp, class ..._ArgTypes> | |
| 248 | class __base<_Rp(_ArgTypes...)> | |
| 249 | { | |
| 250 | __base(const __base&); | |
| 251 | __base& operator=(const __base&); | |
| 252 | public: | |
| 253 | _LIBCPP_INLINE_VISIBILITY __base() {} | |
| 254 | _LIBCPP_INLINE_VISIBILITY virtual ~__base() {} | |
| 255 | virtual __base* __clone() const = 0; | |
| 256 | virtual void __clone(__base*) const = 0; | |
| 257 | virtual void destroy() _NOEXCEPT = 0; | |
| 258 | virtual void destroy_deallocate() _NOEXCEPT = 0; | |
| 259 | virtual _Rp operator()(_ArgTypes&& ...) = 0; | |
| 260 | #ifndef _LIBCPP_NO_RTTI | |
| 261 | virtual const void* target(const type_info&) const _NOEXCEPT = 0; | |
| 262 | virtual const std::type_info& target_type() const _NOEXCEPT = 0; | |
| 263 | #endif // _LIBCPP_NO_RTTI | |
| 264 | }; | |
| 265 | ||
| 266 | // __func implements __base for a given functor type. | |
| 267 | ||
| 268 | template<class _FD, class _Alloc, class _FB> class __func; | |
| 269 | ||
| 270 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 271 | class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> | |
| 272 | : public __base<_Rp(_ArgTypes...)> | |
| 273 | { | |
| 274 | __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; | |
| 275 | public: | |
| 276 | _LIBCPP_INLINE_VISIBILITY | |
| 277 | explicit __func(_Fp&& __f) | |
| 278 | : __f_(_VSTD::move(__f)) {} | |
| 279 | ||
| 280 | _LIBCPP_INLINE_VISIBILITY | |
| 281 | explicit __func(const _Fp& __f, const _Alloc& __a) | |
| 282 | : __f_(__f, __a) {} | |
| 283 | ||
| 284 | _LIBCPP_INLINE_VISIBILITY | |
| 285 | explicit __func(const _Fp& __f, _Alloc&& __a) | |
| 286 | : __f_(__f, _VSTD::move(__a)) {} | |
| 287 | ||
| 288 | _LIBCPP_INLINE_VISIBILITY | |
| 289 | explicit __func(_Fp&& __f, _Alloc&& __a) | |
| 290 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 291 | ||
| 292 | virtual __base<_Rp(_ArgTypes...)>* __clone() const; | |
| 293 | virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; | |
| 294 | virtual void destroy() _NOEXCEPT; | |
| 295 | virtual void destroy_deallocate() _NOEXCEPT; | |
| 296 | virtual _Rp operator()(_ArgTypes&&... __arg); | |
| 297 | #ifndef _LIBCPP_NO_RTTI | |
| 298 | virtual const void* target(const type_info&) const _NOEXCEPT; | |
| 299 | virtual const std::type_info& target_type() const _NOEXCEPT; | |
| 300 | #endif // _LIBCPP_NO_RTTI | |
| 301 | }; | |
| 302 | ||
| 303 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 304 | __base<_Rp(_ArgTypes...)>* | |
| 305 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const | |
| 306 | { | |
| 307 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 308 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 309 | _Ap __a(__f_.__get_allocator()); | |
| 310 | typedef __allocator_destructor<_Ap> _Dp; | |
| 311 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 312 | ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a)); | |
| 313 | return __hold.release(); | |
| 314 | } | |
| 315 | ||
| 316 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 317 | void | |
| 318 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const | |
| 319 | { | |
| 320 | ::new ((void*)__p) __func(__f_.__target(), __f_.__get_allocator()); | |
| 321 | } | |
| 322 | ||
| 323 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 324 | void | |
| 325 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT | |
| 326 | { | |
| 327 | __f_.destroy(); | |
| 328 | } | |
| 329 | ||
| 330 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 331 | void | |
| 332 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT | |
| 333 | { | |
| 334 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 335 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 336 | _Ap __a(__f_.__get_allocator()); | |
| 337 | __f_.destroy(); | |
| 338 | __a.deallocate(this, 1); | |
| 339 | } | |
| 340 | ||
| 341 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 342 | _Rp | |
| 343 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) | |
| 344 | { | |
| 345 | return __f_(_VSTD::forward<_ArgTypes>(__arg)...); | |
| 346 | } | |
| 347 | ||
| 348 | #ifndef _LIBCPP_NO_RTTI | |
| 349 | ||
| 350 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 351 | const void* | |
| 352 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT | |
| 353 | { | |
| 354 | if (__ti == typeid(_Fp)) | |
| 355 | return &__f_.__target(); | |
| 356 | return nullptr; | |
| 357 | } | |
| 358 | ||
| 359 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 360 | const std::type_info& | |
| 361 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT | |
| 362 | { | |
| 363 | return typeid(_Fp); | |
| 364 | } | |
| 365 | ||
| 366 | #endif // _LIBCPP_NO_RTTI | |
| 367 | ||
| 368 | // __value_func creates a value-type from a __func. | |
| 369 | ||
| 370 | template <class _Fp> class __value_func; | |
| 371 | ||
| 372 | template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> | |
| 373 | { | |
| 374 | typename aligned_storage<3 * sizeof(void*)>::type __buf_; | |
| 375 | ||
| 376 | typedef __base<_Rp(_ArgTypes...)> __func; | |
| 377 | __func* __f_; | |
| 378 | ||
| 379 | _LIBCPP_NO_CFI static __func* __as_base(void* p) | |
| 380 | { | |
| 381 | return reinterpret_cast<__func*>(p); | |
| 382 | } | |
| 383 | ||
| 384 | public: | |
| 385 | _LIBCPP_INLINE_VISIBILITY | |
| 386 | __value_func() _NOEXCEPT : __f_(nullptr) {} | |
| 387 | ||
| 388 | template <class _Fp, class _Alloc> | |
| 389 | _LIBCPP_INLINE_VISIBILITY __value_func(_Fp&& __f, const _Alloc& __a) | |
| 390 | : __f_(nullptr) | |
| 391 | { | |
| 392 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 393 | typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; | |
| 394 | typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type | |
| 395 | _FunAlloc; | |
| 396 | ||
| 397 | if (__function::__not_null(__f)) | |
| 398 | { | |
| 399 | _FunAlloc __af(__a); | |
| 400 | if (sizeof(_Fun) <= sizeof(__buf_) && | |
| 401 | is_nothrow_copy_constructible<_Fp>::value && | |
| 402 | is_nothrow_copy_constructible<_FunAlloc>::value) | |
| 403 | { | |
| 404 | __f_ = | |
| 405 | ::new ((void*)&__buf_) _Fun(_VSTD::move(__f), _Alloc(__af)); | |
| 406 | } | |
| 407 | else | |
| 408 | { | |
| 409 | typedef __allocator_destructor<_FunAlloc> _Dp; | |
| 410 | unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); | |
| 411 | ::new ((void*)__hold.get()) _Fun(_VSTD::move(__f), _Alloc(__a)); | |
| 412 | __f_ = __hold.release(); | |
| 413 | } | |
| 414 | } | |
| 415 | } | |
| 416 | ||
| 417 | template <class _Fp, | |
| 418 | class = typename enable_if<!is_same<typename decay<_Fp>::type, __value_func>::value>::type> | |
| 419 | _LIBCPP_INLINE_VISIBILITY explicit __value_func(_Fp&& __f) | |
| 420 | : __value_func(_VSTD::forward<_Fp>(__f), allocator<_Fp>()) {} | |
| 421 | ||
| 422 | _LIBCPP_INLINE_VISIBILITY | |
| 423 | __value_func(const __value_func& __f) | |
| 424 | { | |
| 425 | if (__f.__f_ == nullptr) | |
| 426 | __f_ = nullptr; | |
| 427 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 428 | { | |
| 429 | __f_ = __as_base(&__buf_); | |
| 430 | __f.__f_->__clone(__f_); | |
| 431 | } | |
| 432 | else | |
| 433 | __f_ = __f.__f_->__clone(); | |
| 434 | } | |
| 435 | ||
| 436 | _LIBCPP_INLINE_VISIBILITY | |
| 437 | __value_func(__value_func&& __f) _NOEXCEPT | |
| 438 | { | |
| 439 | if (__f.__f_ == nullptr) | |
| 440 | __f_ = nullptr; | |
| 441 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 442 | { | |
| 443 | __f_ = __as_base(&__buf_); | |
| 444 | __f.__f_->__clone(__f_); | |
| 445 | } | |
| 446 | else | |
| 447 | { | |
| 448 | __f_ = __f.__f_; | |
| 449 | __f.__f_ = nullptr; | |
| 450 | } | |
| 451 | } | |
| 452 | ||
| 453 | _LIBCPP_INLINE_VISIBILITY | |
| 454 | ~__value_func() | |
| 455 | { | |
| 456 | if ((void*)__f_ == &__buf_) | |
| 457 | __f_->destroy(); | |
| 458 | else if (__f_) | |
| 459 | __f_->destroy_deallocate(); | |
| 460 | } | |
| 461 | ||
| 462 | _LIBCPP_INLINE_VISIBILITY | |
| 463 | __value_func& operator=(__value_func&& __f) | |
| 464 | { | |
| 465 | *this = nullptr; | |
| 466 | if (__f.__f_ == nullptr) | |
| 467 | __f_ = nullptr; | |
| 468 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 469 | { | |
| 470 | __f_ = __as_base(&__buf_); | |
| 471 | __f.__f_->__clone(__f_); | |
| 472 | } | |
| 473 | else | |
| 474 | { | |
| 475 | __f_ = __f.__f_; | |
| 476 | __f.__f_ = nullptr; | |
| 477 | } | |
| 478 | return *this; | |
| 479 | } | |
| 480 | ||
| 481 | _LIBCPP_INLINE_VISIBILITY | |
| 482 | __value_func& operator=(nullptr_t) | |
| 483 | { | |
| 484 | __func* __f = __f_; | |
| 485 | __f_ = nullptr; | |
| 486 | if ((void*)__f == &__buf_) | |
| 487 | __f->destroy(); | |
| 488 | else if (__f) | |
| 489 | __f->destroy_deallocate(); | |
| 490 | return *this; | |
| 491 | } | |
| 492 | ||
| 493 | _LIBCPP_INLINE_VISIBILITY | |
| 494 | _Rp operator()(_ArgTypes&&... __args) const | |
| 495 | { | |
| 496 | if (__f_ == nullptr) | |
| 497 | __throw_bad_function_call(); | |
| 498 | return (*__f_)(_VSTD::forward<_ArgTypes>(__args)...); | |
| 499 | } | |
| 500 | ||
| 501 | _LIBCPP_INLINE_VISIBILITY | |
| 502 | void swap(__value_func& __f) _NOEXCEPT | |
| 503 | { | |
| 504 | if (&__f == this) | |
| 505 | return; | |
| 506 | if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_) | |
| 507 | { | |
| 508 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 509 | __func* __t = __as_base(&__tempbuf); | |
| 510 | __f_->__clone(__t); | |
| 511 | __f_->destroy(); | |
| 512 | __f_ = nullptr; | |
| 513 | __f.__f_->__clone(__as_base(&__buf_)); | |
| 514 | __f.__f_->destroy(); | |
| 515 | __f.__f_ = nullptr; | |
| 516 | __f_ = __as_base(&__buf_); | |
| 517 | __t->__clone(__as_base(&__f.__buf_)); | |
| 518 | __t->destroy(); | |
| 519 | __f.__f_ = __as_base(&__f.__buf_); | |
| 520 | } | |
| 521 | else if ((void*)__f_ == &__buf_) | |
| 522 | { | |
| 523 | __f_->__clone(__as_base(&__f.__buf_)); | |
| 524 | __f_->destroy(); | |
| 525 | __f_ = __f.__f_; | |
| 526 | __f.__f_ = __as_base(&__f.__buf_); | |
| 527 | } | |
| 528 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 529 | { | |
| 530 | __f.__f_->__clone(__as_base(&__buf_)); | |
| 531 | __f.__f_->destroy(); | |
| 532 | __f.__f_ = __f_; | |
| 533 | __f_ = __as_base(&__buf_); | |
| 534 | } | |
| 535 | else | |
| 536 | _VSTD::swap(__f_, __f.__f_); | |
| 537 | } | |
| 538 | ||
| 539 | _LIBCPP_INLINE_VISIBILITY | |
| 540 | explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; } | |
| 541 | ||
| 542 | #ifndef _LIBCPP_NO_RTTI | |
| 543 | _LIBCPP_INLINE_VISIBILITY | |
| 544 | const std::type_info& target_type() const _NOEXCEPT | |
| 545 | { | |
| 546 | if (__f_ == nullptr) | |
| 547 | return typeid(void); | |
| 548 | return __f_->target_type(); | |
| 549 | } | |
| 550 | ||
| 551 | template <typename _Tp> | |
| 552 | _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT | |
| 553 | { | |
| 554 | if (__f_ == nullptr) | |
| 555 | return nullptr; | |
| 556 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 557 | } | |
| 558 | #endif // _LIBCPP_NO_RTTI | |
| 559 | }; | |
| 560 | ||
| 561 | // Storage for a functor object, to be used with __policy to manage copy and | |
| 562 | // destruction. | |
| 563 | union __policy_storage | |
| 564 | { | |
| 565 | mutable char __small[sizeof(void*) * 2]; | |
| 566 | void* __large; | |
| 567 | }; | |
| 568 | ||
| 569 | // True if _Fun can safely be held in __policy_storage.__small. | |
| 570 | template <typename _Fun> | |
| 571 | struct __use_small_storage | |
| 572 | : public integral_constant< | |
| 573 | bool, sizeof(_Fun) <= sizeof(__policy_storage) && | |
| 574 | _LIBCPP_ALIGNOF(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage) && | |
| 575 | is_trivially_copy_constructible<_Fun>::value && | |
| 576 | is_trivially_destructible<_Fun>::value> {}; | |
| 577 | ||
| 578 | // Policy contains information about how to copy, destroy, and move the | |
| 579 | // underlying functor. You can think of it as a vtable of sorts. | |
| 580 | struct __policy | |
| 581 | { | |
| 582 | // Used to copy or destroy __large values. null for trivial objects. | |
| 583 | void* (*const __clone)(const void*); | |
| 584 | void (*const __destroy)(void*); | |
| 585 | ||
| 586 | // True if this is the null policy (no value). | |
| 587 | const bool __is_null; | |
| 588 | ||
| 589 | // The target type. May be null if RTTI is disabled. | |
| 590 | const std::type_info* const __type_info; | |
| 591 | ||
| 592 | // Returns a pointer to a static policy object suitable for the functor | |
| 593 | // type. | |
| 594 | template <typename _Fun> | |
| 595 | _LIBCPP_INLINE_VISIBILITY static const __policy* __create() | |
| 596 | { | |
| 597 | return __choose_policy<_Fun>(__use_small_storage<_Fun>()); | |
| 598 | } | |
| 599 | ||
| 600 | _LIBCPP_INLINE_VISIBILITY | |
| 601 | static const __policy* __create_empty() | |
| 602 | { | |
| 603 | static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, | |
| 604 | true, | |
| 605 | #ifndef _LIBCPP_NO_RTTI | |
| 606 | &typeid(void) | |
| 607 | #else | |
| 608 | nullptr | |
| 609 | #endif | |
| 610 | }; | |
| 611 | return &__policy_; | |
| 612 | } | |
| 613 | ||
| 614 | private: | |
| 615 | template <typename _Fun> static void* __large_clone(const void* __s) | |
| 616 | { | |
| 617 | const _Fun* __f = static_cast<const _Fun*>(__s); | |
| 618 | return __f->__clone(); | |
| 619 | } | |
| 620 | ||
| 621 | template <typename _Fun> | |
| 622 | static void __large_destroy(void* __s) { | |
| 623 | _Fun::__destroy_and_delete(static_cast<_Fun*>(__s)); | |
| 624 | } | |
| 625 | ||
| 626 | template <typename _Fun> | |
| 627 | _LIBCPP_INLINE_VISIBILITY static const __policy* | |
| 628 | __choose_policy(/* is_small = */ false_type) { | |
| 629 | static const _LIBCPP_CONSTEXPR __policy __policy_ = { | |
| 630 | &__large_clone<_Fun>, &__large_destroy<_Fun>, false, | |
| 631 | #ifndef _LIBCPP_NO_RTTI | |
| 632 | &typeid(typename _Fun::_Target) | |
| 633 | #else | |
| 634 | nullptr | |
| 635 | #endif | |
| 636 | }; | |
| 637 | return &__policy_; | |
| 638 | } | |
| 639 | ||
| 640 | template <typename _Fun> | |
| 641 | _LIBCPP_INLINE_VISIBILITY static const __policy* | |
| 642 | __choose_policy(/* is_small = */ true_type) | |
| 643 | { | |
| 644 | static const _LIBCPP_CONSTEXPR __policy __policy_ = { | |
| 645 | nullptr, nullptr, false, | |
| 646 | #ifndef _LIBCPP_NO_RTTI | |
| 647 | &typeid(typename _Fun::_Target) | |
| 648 | #else | |
| 649 | nullptr | |
| 650 | #endif | |
| 651 | }; | |
| 652 | return &__policy_; | |
| 653 | } | |
| 654 | }; | |
| 655 | ||
| 656 | // Used to choose between perfect forwarding or pass-by-value. Pass-by-value is | |
| 657 | // faster for types that can be passed in registers. | |
| 658 | template <typename _Tp> | |
| 659 | using __fast_forward = | |
| 660 | typename conditional<is_scalar<_Tp>::value, _Tp, _Tp&&>::type; | |
| 661 | ||
| 662 | // __policy_invoker calls an instance of __alloc_func held in __policy_storage. | |
| 663 | ||
| 664 | template <class _Fp> struct __policy_invoker; | |
| 665 | ||
| 666 | template <class _Rp, class... _ArgTypes> | |
| 667 | struct __policy_invoker<_Rp(_ArgTypes...)> | |
| 668 | { | |
| 669 | typedef _Rp (*__Call)(const __policy_storage*, | |
| 670 | __fast_forward<_ArgTypes>...); | |
| 671 | ||
| 672 | __Call __call_; | |
| 673 | ||
| 674 | // Creates an invoker that throws bad_function_call. | |
| 675 | _LIBCPP_INLINE_VISIBILITY | |
| 676 | __policy_invoker() : __call_(&__call_empty) {} | |
| 677 | ||
| 678 | // Creates an invoker that calls the given instance of __func. | |
| 679 | template <typename _Fun> | |
| 680 | _LIBCPP_INLINE_VISIBILITY static __policy_invoker __create() | |
| 681 | { | |
| 682 | return __policy_invoker(&__call_impl<_Fun>); | |
| 683 | } | |
| 684 | ||
| 685 | private: | |
| 686 | _LIBCPP_INLINE_VISIBILITY | |
| 687 | explicit __policy_invoker(__Call __c) : __call_(__c) {} | |
| 688 | ||
| 689 | static _Rp __call_empty(const __policy_storage*, | |
| 690 | __fast_forward<_ArgTypes>...) | |
| 691 | { | |
| 692 | __throw_bad_function_call(); | |
| 693 | } | |
| 694 | ||
| 695 | template <typename _Fun> | |
| 696 | static _Rp __call_impl(const __policy_storage* __buf, | |
| 697 | __fast_forward<_ArgTypes>... __args) | |
| 698 | { | |
| 699 | _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value | |
| 700 | ? &__buf->__small | |
| 701 | : __buf->__large); | |
| 702 | return (*__f)(_VSTD::forward<_ArgTypes>(__args)...); | |
| 703 | } | |
| 704 | }; | |
| 705 | ||
| 706 | // __policy_func uses a __policy and __policy_invoker to create a type-erased, | |
| 707 | // copyable functor. | |
| 708 | ||
| 709 | template <class _Fp> class __policy_func; | |
| 710 | ||
| 711 | template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> | |
| 712 | { | |
| 713 | // Inline storage for small objects. | |
| 714 | __policy_storage __buf_; | |
| 715 | ||
| 716 | // Calls the value stored in __buf_. This could technically be part of | |
| 717 | // policy, but storing it here eliminates a level of indirection inside | |
| 718 | // operator(). | |
| 719 | typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker; | |
| 720 | __invoker __invoker_; | |
| 721 | ||
| 722 | // The policy that describes how to move / copy / destroy __buf_. Never | |
| 723 | // null, even if the function is empty. | |
| 724 | const __policy* __policy_; | |
| 725 | ||
| 726 | public: | |
| 727 | _LIBCPP_INLINE_VISIBILITY | |
| 728 | __policy_func() : __policy_(__policy::__create_empty()) {} | |
| 729 | ||
| 730 | template <class _Fp, class _Alloc> | |
| 731 | _LIBCPP_INLINE_VISIBILITY __policy_func(_Fp&& __f, const _Alloc& __a) | |
| 732 | : __policy_(__policy::__create_empty()) | |
| 733 | { | |
| 734 | typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; | |
| 735 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 736 | typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type | |
| 737 | _FunAlloc; | |
| 738 | ||
| 739 | if (__function::__not_null(__f)) | |
| 740 | { | |
| 741 | __invoker_ = __invoker::template __create<_Fun>(); | |
| 742 | __policy_ = __policy::__create<_Fun>(); | |
| 743 | ||
| 744 | _FunAlloc __af(__a); | |
| 745 | if (__use_small_storage<_Fun>()) | |
| 746 | { | |
| 747 | ::new ((void*)&__buf_.__small) | |
| 748 | _Fun(_VSTD::move(__f), _Alloc(__af)); | |
| 749 | } | |
| 750 | else | |
| 751 | { | |
| 752 | typedef __allocator_destructor<_FunAlloc> _Dp; | |
| 753 | unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); | |
| 754 | ::new ((void*)__hold.get()) | |
| 755 | _Fun(_VSTD::move(__f), _Alloc(__af)); | |
| 756 | __buf_.__large = __hold.release(); | |
| 757 | } | |
| 758 | } | |
| 759 | } | |
| 760 | ||
| 761 | template <class _Fp, class = typename enable_if<!is_same<typename decay<_Fp>::type, __policy_func>::value>::type> | |
| 762 | _LIBCPP_INLINE_VISIBILITY explicit __policy_func(_Fp&& __f) | |
| 763 | : __policy_(__policy::__create_empty()) { | |
| 764 | typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun; | |
| 765 | ||
| 766 | if (__function::__not_null(__f)) { | |
| 767 | __invoker_ = __invoker::template __create<_Fun>(); | |
| 768 | __policy_ = __policy::__create<_Fun>(); | |
| 769 | if (__use_small_storage<_Fun>()) { | |
| 770 | ::new ((void*)&__buf_.__small) _Fun(_VSTD::move(__f)); | |
| 771 | } else { | |
| 772 | __builtin_new_allocator::__holder_t __hold = | |
| 773 | __builtin_new_allocator::__allocate_type<_Fun>(1); | |
| 774 | __buf_.__large = ::new ((void*)__hold.get()) _Fun(_VSTD::move(__f)); | |
| 775 | (void)__hold.release(); | |
| 776 | } | |
| 777 | } | |
| 778 | } | |
| 779 | ||
| 780 | _LIBCPP_INLINE_VISIBILITY | |
| 781 | __policy_func(const __policy_func& __f) | |
| 782 | : __buf_(__f.__buf_), __invoker_(__f.__invoker_), | |
| 783 | __policy_(__f.__policy_) | |
| 784 | { | |
| 785 | if (__policy_->__clone) | |
| 786 | __buf_.__large = __policy_->__clone(__f.__buf_.__large); | |
| 787 | } | |
| 788 | ||
| 789 | _LIBCPP_INLINE_VISIBILITY | |
| 790 | __policy_func(__policy_func&& __f) | |
| 791 | : __buf_(__f.__buf_), __invoker_(__f.__invoker_), | |
| 792 | __policy_(__f.__policy_) | |
| 793 | { | |
| 794 | if (__policy_->__destroy) | |
| 795 | { | |
| 796 | __f.__policy_ = __policy::__create_empty(); | |
| 797 | __f.__invoker_ = __invoker(); | |
| 798 | } | |
| 799 | } | |
| 800 | ||
| 801 | _LIBCPP_INLINE_VISIBILITY | |
| 802 | ~__policy_func() | |
| 803 | { | |
| 804 | if (__policy_->__destroy) | |
| 805 | __policy_->__destroy(__buf_.__large); | |
| 806 | } | |
| 807 | ||
| 808 | _LIBCPP_INLINE_VISIBILITY | |
| 809 | __policy_func& operator=(__policy_func&& __f) | |
| 810 | { | |
| 811 | *this = nullptr; | |
| 812 | __buf_ = __f.__buf_; | |
| 813 | __invoker_ = __f.__invoker_; | |
| 814 | __policy_ = __f.__policy_; | |
| 815 | __f.__policy_ = __policy::__create_empty(); | |
| 816 | __f.__invoker_ = __invoker(); | |
| 817 | return *this; | |
| 818 | } | |
| 819 | ||
| 820 | _LIBCPP_INLINE_VISIBILITY | |
| 821 | __policy_func& operator=(nullptr_t) | |
| 822 | { | |
| 823 | const __policy* __p = __policy_; | |
| 824 | __policy_ = __policy::__create_empty(); | |
| 825 | __invoker_ = __invoker(); | |
| 826 | if (__p->__destroy) | |
| 827 | __p->__destroy(__buf_.__large); | |
| 828 | return *this; | |
| 829 | } | |
| 830 | ||
| 831 | _LIBCPP_INLINE_VISIBILITY | |
| 832 | _Rp operator()(_ArgTypes&&... __args) const | |
| 833 | { | |
| 834 | return __invoker_.__call_(_VSTD::addressof(__buf_), | |
| 835 | _VSTD::forward<_ArgTypes>(__args)...); | |
| 836 | } | |
| 837 | ||
| 838 | _LIBCPP_INLINE_VISIBILITY | |
| 839 | void swap(__policy_func& __f) | |
| 840 | { | |
| 841 | _VSTD::swap(__invoker_, __f.__invoker_); | |
| 842 | _VSTD::swap(__policy_, __f.__policy_); | |
| 843 | _VSTD::swap(__buf_, __f.__buf_); | |
| 844 | } | |
| 845 | ||
| 846 | _LIBCPP_INLINE_VISIBILITY | |
| 847 | explicit operator bool() const _NOEXCEPT | |
| 848 | { | |
| 849 | return !__policy_->__is_null; | |
| 850 | } | |
| 851 | ||
| 852 | #ifndef _LIBCPP_NO_RTTI | |
| 853 | _LIBCPP_INLINE_VISIBILITY | |
| 854 | const std::type_info& target_type() const _NOEXCEPT | |
| 855 | { | |
| 856 | return *__policy_->__type_info; | |
| 857 | } | |
| 858 | ||
| 859 | template <typename _Tp> | |
| 860 | _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT | |
| 861 | { | |
| 862 | if (__policy_->__is_null || typeid(_Tp) != *__policy_->__type_info) | |
| 863 | return nullptr; | |
| 864 | if (__policy_->__clone) // Out of line storage. | |
| 865 | return reinterpret_cast<const _Tp*>(__buf_.__large); | |
| 866 | else | |
| 867 | return reinterpret_cast<const _Tp*>(&__buf_.__small); | |
| 868 | } | |
| 869 | #endif // _LIBCPP_NO_RTTI | |
| 870 | }; | |
| 871 | ||
| 872 | #if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) && !defined(_LIBCPP_HAS_OBJC_ARC) | |
| 873 | ||
| 874 | extern "C" void *_Block_copy(const void *); | |
| 875 | extern "C" void _Block_release(const void *); | |
| 876 | ||
| 877 | template<class _Rp1, class ..._ArgTypes1, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 878 | class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> | |
| 879 | : public __base<_Rp(_ArgTypes...)> | |
| 880 | { | |
| 881 | typedef _Rp1(^__block_type)(_ArgTypes1...); | |
| 882 | __block_type __f_; | |
| 883 | ||
| 884 | public: | |
| 885 | _LIBCPP_INLINE_VISIBILITY | |
| 886 | explicit __func(__block_type const& __f) | |
| 887 | : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) | |
| 888 | { } | |
| 889 | ||
| 890 | // [TODO] add && to save on a retain | |
| 891 | ||
| 892 | _LIBCPP_INLINE_VISIBILITY | |
| 893 | explicit __func(__block_type __f, const _Alloc& /* unused */) | |
| 894 | : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) | |
| 895 | { } | |
| 896 | ||
| 897 | virtual __base<_Rp(_ArgTypes...)>* __clone() const { | |
| 898 | _LIBCPP_ASSERT(false, | |
| 899 | "Block pointers are just pointers, so they should always fit into " | |
| 900 | "std::function's small buffer optimization. This function should " | |
| 901 | "never be invoked."); | |
| 902 | return nullptr; | |
| 903 | } | |
| 904 | ||
| 905 | virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const { | |
| 906 | ::new ((void*)__p) __func(__f_); | |
| 907 | } | |
| 908 | ||
| 909 | virtual void destroy() _NOEXCEPT { | |
| 910 | if (__f_) | |
| 911 | _Block_release(__f_); | |
| 912 | __f_ = 0; | |
| 913 | } | |
| 914 | ||
| 915 | virtual void destroy_deallocate() _NOEXCEPT { | |
| 916 | _LIBCPP_ASSERT(false, | |
| 917 | "Block pointers are just pointers, so they should always fit into " | |
| 918 | "std::function's small buffer optimization. This function should " | |
| 919 | "never be invoked."); | |
| 920 | } | |
| 921 | ||
| 922 | virtual _Rp operator()(_ArgTypes&& ... __arg) { | |
| 923 | return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...); | |
| 924 | } | |
| 925 | ||
| 926 | #ifndef _LIBCPP_NO_RTTI | |
| 927 | virtual const void* target(type_info const& __ti) const _NOEXCEPT { | |
| 928 | if (__ti == typeid(__func::__block_type)) | |
| 929 | return &__f_; | |
| 930 | return (const void*)nullptr; | |
| 931 | } | |
| 932 | ||
| 933 | virtual const std::type_info& target_type() const _NOEXCEPT { | |
| 934 | return typeid(__func::__block_type); | |
| 935 | } | |
| 936 | #endif // _LIBCPP_NO_RTTI | |
| 937 | }; | |
| 938 | ||
| 939 | #endif // _LIBCPP_HAS_EXTENSION_BLOCKS && !_LIBCPP_HAS_OBJC_ARC | |
| 940 | ||
| 941 | } // __function | |
| 942 | ||
| 943 | template<class _Rp, class ..._ArgTypes> | |
| 944 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> | |
| 945 | #if _LIBCPP_STD_VER <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 946 | : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>, | |
| 947 | public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> | |
| 948 | #endif | |
| 949 | { | |
| 950 | #ifndef _LIBCPP_ABI_OPTIMIZED_FUNCTION | |
| 951 | typedef __function::__value_func<_Rp(_ArgTypes...)> __func; | |
| 952 | #else | |
| 953 | typedef __function::__policy_func<_Rp(_ArgTypes...)> __func; | |
| 954 | #endif | |
| 955 | ||
| 956 | __func __f_; | |
| 957 | ||
| 958 | template <class _Fp, bool = _And< | |
| 959 | _IsNotSame<__uncvref_t<_Fp>, function>, | |
| 960 | __invokable<_Fp, _ArgTypes...> | |
| 961 | >::value> | |
| 962 | struct __callable; | |
| 963 | template <class _Fp> | |
| 964 | struct __callable<_Fp, true> | |
| 965 | { | |
| 966 | static const bool value = is_void<_Rp>::value || | |
| 967 | __is_core_convertible<typename __invoke_of<_Fp, _ArgTypes...>::type, | |
| 968 | _Rp>::value; | |
| 969 | }; | |
| 970 | template <class _Fp> | |
| 971 | struct __callable<_Fp, false> | |
| 972 | { | |
| 973 | static const bool value = false; | |
| 974 | }; | |
| 975 | ||
| 976 | template <class _Fp> | |
| 977 | using _EnableIfLValueCallable = typename enable_if<__callable<_Fp&>::value>::type; | |
| 978 | public: | |
| 979 | typedef _Rp result_type; | |
| 980 | ||
| 981 | // construct/copy/destroy: | |
| 982 | _LIBCPP_INLINE_VISIBILITY | |
| 983 | function() _NOEXCEPT { } | |
| 984 | _LIBCPP_INLINE_VISIBILITY | |
| 985 | function(nullptr_t) _NOEXCEPT {} | |
| 986 | function(const function&); | |
| 987 | function(function&&) _NOEXCEPT; | |
| 988 | template<class _Fp, class = _EnableIfLValueCallable<_Fp>> | |
| 989 | function(_Fp); | |
| 990 | ||
| 991 | #if _LIBCPP_STD_VER <= 14 | |
| 992 | template<class _Alloc> | |
| 993 | _LIBCPP_INLINE_VISIBILITY | |
| 994 | function(allocator_arg_t, const _Alloc&) _NOEXCEPT {} | |
| 995 | template<class _Alloc> | |
| 996 | _LIBCPP_INLINE_VISIBILITY | |
| 997 | function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT {} | |
| 998 | template<class _Alloc> | |
| 999 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 1000 | template<class _Alloc> | |
| 1001 | function(allocator_arg_t, const _Alloc&, function&&); | |
| 1002 | template<class _Fp, class _Alloc, class = _EnableIfLValueCallable<_Fp>> | |
| 1003 | function(allocator_arg_t, const _Alloc& __a, _Fp __f); | |
| 1004 | #endif | |
| 1005 | ||
| 1006 | function& operator=(const function&); | |
| 1007 | function& operator=(function&&) _NOEXCEPT; | |
| 1008 | function& operator=(nullptr_t) _NOEXCEPT; | |
| 1009 | template<class _Fp, class = _EnableIfLValueCallable<typename decay<_Fp>::type>> | |
| 1010 | function& operator=(_Fp&&); | |
| 1011 | ||
| 1012 | ~function(); | |
| 1013 | ||
| 1014 | // function modifiers: | |
| 1015 | void swap(function&) _NOEXCEPT; | |
| 1016 | ||
| 1017 | #if _LIBCPP_STD_VER <= 14 | |
| 1018 | template<class _Fp, class _Alloc> | |
| 1019 | _LIBCPP_INLINE_VISIBILITY | |
| 1020 | void assign(_Fp&& __f, const _Alloc& __a) | |
| 1021 | {function(allocator_arg, __a, _VSTD::forward<_Fp>(__f)).swap(*this);} | |
| 1022 | #endif | |
| 1023 | ||
| 1024 | // function capacity: | |
| 1025 | _LIBCPP_INLINE_VISIBILITY | |
| 1026 | explicit operator bool() const _NOEXCEPT { | |
| 1027 | return static_cast<bool>(__f_); | |
| 1028 | } | |
| 1029 | ||
| 1030 | // deleted overloads close possible hole in the type system | |
| 1031 | template<class _R2, class... _ArgTypes2> | |
| 1032 | bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete; | |
| 1033 | template<class _R2, class... _ArgTypes2> | |
| 1034 | bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete; | |
| 1035 | public: | |
| 1036 | // function invocation: | |
| 1037 | _Rp operator()(_ArgTypes...) const; | |
| 1038 | ||
| 1039 | #ifndef _LIBCPP_NO_RTTI | |
| 1040 | // function target access: | |
| 1041 | const std::type_info& target_type() const _NOEXCEPT; | |
| 1042 | template <typename _Tp> _Tp* target() _NOEXCEPT; | |
| 1043 | template <typename _Tp> const _Tp* target() const _NOEXCEPT; | |
| 1044 | #endif // _LIBCPP_NO_RTTI | |
| 1045 | }; | |
| 1046 | ||
| 1047 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 1048 | template<class _Rp, class ..._Ap> | |
| 1049 | function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>; | |
| 1050 | ||
| 1051 | template<class _Fp> | |
| 1052 | struct __strip_signature; | |
| 1053 | ||
| 1054 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1055 | struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; | |
| 1056 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1057 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); }; | |
| 1058 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1059 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); }; | |
| 1060 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1061 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); }; | |
| 1062 | ||
| 1063 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1064 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); }; | |
| 1065 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1066 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); }; | |
| 1067 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1068 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); }; | |
| 1069 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1070 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); }; | |
| 1071 | ||
| 1072 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1073 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); }; | |
| 1074 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1075 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); }; | |
| 1076 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1077 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); }; | |
| 1078 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1079 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); }; | |
| 1080 | ||
| 1081 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1082 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); }; | |
| 1083 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1084 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); }; | |
| 1085 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1086 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; | |
| 1087 | template<class _Rp, class _Gp, class ..._Ap> | |
| 1088 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); }; | |
| 1089 | ||
| 1090 | template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type> | |
| 1091 | function(_Fp) -> function<_Stripped>; | |
| 1092 | #endif // !_LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 1093 | ||
| 1094 | template<class _Rp, class ..._ArgTypes> | |
| 1095 | function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {} | |
| 1096 | ||
| 1097 | #if _LIBCPP_STD_VER <= 14 | |
| 1098 | template<class _Rp, class ..._ArgTypes> | |
| 1099 | template <class _Alloc> | |
| 1100 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, | |
| 1101 | const function& __f) : __f_(__f.__f_) {} | |
| 1102 | #endif | |
| 1103 | ||
| 1104 | template <class _Rp, class... _ArgTypes> | |
| 1105 | function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPT | |
| 1106 | : __f_(_VSTD::move(__f.__f_)) {} | |
| 1107 | ||
| 1108 | #if _LIBCPP_STD_VER <= 14 | |
| 1109 | template<class _Rp, class ..._ArgTypes> | |
| 1110 | template <class _Alloc> | |
| 1111 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, | |
| 1112 | function&& __f) | |
| 1113 | : __f_(_VSTD::move(__f.__f_)) {} | |
| 1114 | #endif | |
| 1115 | ||
| 1116 | template <class _Rp, class... _ArgTypes> | |
| 1117 | template <class _Fp, class> | |
| 1118 | function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(_VSTD::move(__f)) {} | |
| 1119 | ||
| 1120 | #if _LIBCPP_STD_VER <= 14 | |
| 1121 | template <class _Rp, class... _ArgTypes> | |
| 1122 | template <class _Fp, class _Alloc, class> | |
| 1123 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, | |
| 1124 | _Fp __f) | |
| 1125 | : __f_(_VSTD::move(__f), __a) {} | |
| 1126 | #endif | |
| 1127 | ||
| 1128 | template<class _Rp, class ..._ArgTypes> | |
| 1129 | function<_Rp(_ArgTypes...)>& | |
| 1130 | function<_Rp(_ArgTypes...)>::operator=(const function& __f) | |
| 1131 | { | |
| 1132 | function(__f).swap(*this); | |
| 1133 | return *this; | |
| 1134 | } | |
| 1135 | ||
| 1136 | template<class _Rp, class ..._ArgTypes> | |
| 1137 | function<_Rp(_ArgTypes...)>& | |
| 1138 | function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT | |
| 1139 | { | |
| 1140 | __f_ = _VSTD::move(__f.__f_); | |
| 1141 | return *this; | |
| 1142 | } | |
| 1143 | ||
| 1144 | template<class _Rp, class ..._ArgTypes> | |
| 1145 | function<_Rp(_ArgTypes...)>& | |
| 1146 | function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT | |
| 1147 | { | |
| 1148 | __f_ = nullptr; | |
| 1149 | return *this; | |
| 1150 | } | |
| 1151 | ||
| 1152 | template<class _Rp, class ..._ArgTypes> | |
| 1153 | template <class _Fp, class> | |
| 1154 | function<_Rp(_ArgTypes...)>& | |
| 1155 | function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) | |
| 1156 | { | |
| 1157 | function(_VSTD::forward<_Fp>(__f)).swap(*this); | |
| 1158 | return *this; | |
| 1159 | } | |
| 1160 | ||
| 1161 | template<class _Rp, class ..._ArgTypes> | |
| 1162 | function<_Rp(_ArgTypes...)>::~function() {} | |
| 1163 | ||
| 1164 | template<class _Rp, class ..._ArgTypes> | |
| 1165 | void | |
| 1166 | function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT | |
| 1167 | { | |
| 1168 | __f_.swap(__f.__f_); | |
| 1169 | } | |
| 1170 | ||
| 1171 | template<class _Rp, class ..._ArgTypes> | |
| 1172 | _Rp | |
| 1173 | function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const | |
| 1174 | { | |
| 1175 | return __f_(_VSTD::forward<_ArgTypes>(__arg)...); | |
| 1176 | } | |
| 1177 | ||
| 1178 | #ifndef _LIBCPP_NO_RTTI | |
| 1179 | ||
| 1180 | template<class _Rp, class ..._ArgTypes> | |
| 1181 | const std::type_info& | |
| 1182 | function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPT | |
| 1183 | { | |
| 1184 | return __f_.target_type(); | |
| 1185 | } | |
| 1186 | ||
| 1187 | template<class _Rp, class ..._ArgTypes> | |
| 1188 | template <typename _Tp> | |
| 1189 | _Tp* | |
| 1190 | function<_Rp(_ArgTypes...)>::target() _NOEXCEPT | |
| 1191 | { | |
| 1192 | return (_Tp*)(__f_.template target<_Tp>()); | |
| 1193 | } | |
| 1194 | ||
| 1195 | template<class _Rp, class ..._ArgTypes> | |
| 1196 | template <typename _Tp> | |
| 1197 | const _Tp* | |
| 1198 | function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT | |
| 1199 | { | |
| 1200 | return __f_.template target<_Tp>(); | |
| 1201 | } | |
| 1202 | ||
| 1203 | #endif // _LIBCPP_NO_RTTI | |
| 1204 | ||
| 1205 | template <class _Rp, class... _ArgTypes> | |
| 1206 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1207 | bool | |
| 1208 | operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return !__f;} | |
| 1209 | ||
| 1210 | template <class _Rp, class... _ArgTypes> | |
| 1211 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1212 | bool | |
| 1213 | operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return !__f;} | |
| 1214 | ||
| 1215 | template <class _Rp, class... _ArgTypes> | |
| 1216 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1217 | bool | |
| 1218 | operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return (bool)__f;} | |
| 1219 | ||
| 1220 | template <class _Rp, class... _ArgTypes> | |
| 1221 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1222 | bool | |
| 1223 | operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return (bool)__f;} | |
| 1224 | ||
| 1225 | template <class _Rp, class... _ArgTypes> | |
| 1226 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1227 | void | |
| 1228 | swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCEPT | |
| 1229 | {return __x.swap(__y);} | |
| 1230 | ||
| 1231 | #else // _LIBCPP_CXX03_LANG | |
| 1232 | ||
| 1233 | namespace __function { | |
| 1234 | ||
| 1235 | template<class _Fp> class __base; | |
| 1236 | ||
| 1237 | template<class _Rp> | |
| 1238 | class __base<_Rp()> | |
| 1239 | { | |
| 1240 | __base(const __base&); | |
| 1241 | __base& operator=(const __base&); | |
| 1242 | public: | |
| 1243 | __base() {} | |
| 1244 | virtual ~__base() {} | |
| 1245 | virtual __base* __clone() const = 0; | |
| 1246 | virtual void __clone(__base*) const = 0; | |
| 1247 | virtual void destroy() = 0; | |
| 1248 | virtual void destroy_deallocate() = 0; | |
| 1249 | virtual _Rp operator()() = 0; | |
| 1250 | #ifndef _LIBCPP_NO_RTTI | |
| 1251 | virtual const void* target(const type_info&) const = 0; | |
| 1252 | virtual const std::type_info& target_type() const = 0; | |
| 1253 | #endif // _LIBCPP_NO_RTTI | |
| 1254 | }; | |
| 1255 | ||
| 1256 | template<class _Rp, class _A0> | |
| 1257 | class __base<_Rp(_A0)> | |
| 1258 | { | |
| 1259 | __base(const __base&); | |
| 1260 | __base& operator=(const __base&); | |
| 1261 | public: | |
| 1262 | __base() {} | |
| 1263 | virtual ~__base() {} | |
| 1264 | virtual __base* __clone() const = 0; | |
| 1265 | virtual void __clone(__base*) const = 0; | |
| 1266 | virtual void destroy() = 0; | |
| 1267 | virtual void destroy_deallocate() = 0; | |
| 1268 | virtual _Rp operator()(_A0) = 0; | |
| 1269 | #ifndef _LIBCPP_NO_RTTI | |
| 1270 | virtual const void* target(const type_info&) const = 0; | |
| 1271 | virtual const std::type_info& target_type() const = 0; | |
| 1272 | #endif // _LIBCPP_NO_RTTI | |
| 1273 | }; | |
| 1274 | ||
| 1275 | template<class _Rp, class _A0, class _A1> | |
| 1276 | class __base<_Rp(_A0, _A1)> | |
| 1277 | { | |
| 1278 | __base(const __base&); | |
| 1279 | __base& operator=(const __base&); | |
| 1280 | public: | |
| 1281 | __base() {} | |
| 1282 | virtual ~__base() {} | |
| 1283 | virtual __base* __clone() const = 0; | |
| 1284 | virtual void __clone(__base*) const = 0; | |
| 1285 | virtual void destroy() = 0; | |
| 1286 | virtual void destroy_deallocate() = 0; | |
| 1287 | virtual _Rp operator()(_A0, _A1) = 0; | |
| 1288 | #ifndef _LIBCPP_NO_RTTI | |
| 1289 | virtual const void* target(const type_info&) const = 0; | |
| 1290 | virtual const std::type_info& target_type() const = 0; | |
| 1291 | #endif // _LIBCPP_NO_RTTI | |
| 1292 | }; | |
| 1293 | ||
| 1294 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1295 | class __base<_Rp(_A0, _A1, _A2)> | |
| 1296 | { | |
| 1297 | __base(const __base&); | |
| 1298 | __base& operator=(const __base&); | |
| 1299 | public: | |
| 1300 | __base() {} | |
| 1301 | virtual ~__base() {} | |
| 1302 | virtual __base* __clone() const = 0; | |
| 1303 | virtual void __clone(__base*) const = 0; | |
| 1304 | virtual void destroy() = 0; | |
| 1305 | virtual void destroy_deallocate() = 0; | |
| 1306 | virtual _Rp operator()(_A0, _A1, _A2) = 0; | |
| 1307 | #ifndef _LIBCPP_NO_RTTI | |
| 1308 | virtual const void* target(const type_info&) const = 0; | |
| 1309 | virtual const std::type_info& target_type() const = 0; | |
| 1310 | #endif // _LIBCPP_NO_RTTI | |
| 1311 | }; | |
| 1312 | ||
| 1313 | template<class _FD, class _Alloc, class _FB> class __func; | |
| 1314 | ||
| 1315 | template<class _Fp, class _Alloc, class _Rp> | |
| 1316 | class __func<_Fp, _Alloc, _Rp()> | |
| 1317 | : public __base<_Rp()> | |
| 1318 | { | |
| 1319 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 1320 | public: | |
| 1321 | explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 1322 | explicit __func(_Fp __f, _Alloc __a) : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 1323 | virtual __base<_Rp()>* __clone() const; | |
| 1324 | virtual void __clone(__base<_Rp()>*) const; | |
| 1325 | virtual void destroy(); | |
| 1326 | virtual void destroy_deallocate(); | |
| 1327 | virtual _Rp operator()(); | |
| 1328 | #ifndef _LIBCPP_NO_RTTI | |
| 1329 | virtual const void* target(const type_info&) const; | |
| 1330 | virtual const std::type_info& target_type() const; | |
| 1331 | #endif // _LIBCPP_NO_RTTI | |
| 1332 | }; | |
| 1333 | ||
| 1334 | template<class _Fp, class _Alloc, class _Rp> | |
| 1335 | __base<_Rp()>* | |
| 1336 | __func<_Fp, _Alloc, _Rp()>::__clone() const | |
| 1337 | { | |
| 1338 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1339 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1340 | _Ap __a(__f_.second()); | |
| 1341 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1342 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1343 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 1344 | return __hold.release(); | |
| 1345 | } | |
| 1346 | ||
| 1347 | template<class _Fp, class _Alloc, class _Rp> | |
| 1348 | void | |
| 1349 | __func<_Fp, _Alloc, _Rp()>::__clone(__base<_Rp()>* __p) const | |
| 1350 | { | |
| 1351 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 1352 | } | |
| 1353 | ||
| 1354 | template<class _Fp, class _Alloc, class _Rp> | |
| 1355 | void | |
| 1356 | __func<_Fp, _Alloc, _Rp()>::destroy() | |
| 1357 | { | |
| 1358 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1359 | } | |
| 1360 | ||
| 1361 | template<class _Fp, class _Alloc, class _Rp> | |
| 1362 | void | |
| 1363 | __func<_Fp, _Alloc, _Rp()>::destroy_deallocate() | |
| 1364 | { | |
| 1365 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1366 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1367 | _Ap __a(__f_.second()); | |
| 1368 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1369 | __a.deallocate(this, 1); | |
| 1370 | } | |
| 1371 | ||
| 1372 | template<class _Fp, class _Alloc, class _Rp> | |
| 1373 | _Rp | |
| 1374 | __func<_Fp, _Alloc, _Rp()>::operator()() | |
| 1375 | { | |
| 1376 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 1377 | return _Invoker::__call(__f_.first()); | |
| 1378 | } | |
| 1379 | ||
| 1380 | #ifndef _LIBCPP_NO_RTTI | |
| 1381 | ||
| 1382 | template<class _Fp, class _Alloc, class _Rp> | |
| 1383 | const void* | |
| 1384 | __func<_Fp, _Alloc, _Rp()>::target(const type_info& __ti) const | |
| 1385 | { | |
| 1386 | if (__ti == typeid(_Fp)) | |
| 1387 | return &__f_.first(); | |
| 1388 | return (const void*)0; | |
| 1389 | } | |
| 1390 | ||
| 1391 | template<class _Fp, class _Alloc, class _Rp> | |
| 1392 | const std::type_info& | |
| 1393 | __func<_Fp, _Alloc, _Rp()>::target_type() const | |
| 1394 | { | |
| 1395 | return typeid(_Fp); | |
| 1396 | } | |
| 1397 | ||
| 1398 | #endif // _LIBCPP_NO_RTTI | |
| 1399 | ||
| 1400 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1401 | class __func<_Fp, _Alloc, _Rp(_A0)> | |
| 1402 | : public __base<_Rp(_A0)> | |
| 1403 | { | |
| 1404 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 1405 | public: | |
| 1406 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 1407 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) | |
| 1408 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 1409 | virtual __base<_Rp(_A0)>* __clone() const; | |
| 1410 | virtual void __clone(__base<_Rp(_A0)>*) const; | |
| 1411 | virtual void destroy(); | |
| 1412 | virtual void destroy_deallocate(); | |
| 1413 | virtual _Rp operator()(_A0); | |
| 1414 | #ifndef _LIBCPP_NO_RTTI | |
| 1415 | virtual const void* target(const type_info&) const; | |
| 1416 | virtual const std::type_info& target_type() const; | |
| 1417 | #endif // _LIBCPP_NO_RTTI | |
| 1418 | }; | |
| 1419 | ||
| 1420 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1421 | __base<_Rp(_A0)>* | |
| 1422 | __func<_Fp, _Alloc, _Rp(_A0)>::__clone() const | |
| 1423 | { | |
| 1424 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1425 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1426 | _Ap __a(__f_.second()); | |
| 1427 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1428 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1429 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 1430 | return __hold.release(); | |
| 1431 | } | |
| 1432 | ||
| 1433 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1434 | void | |
| 1435 | __func<_Fp, _Alloc, _Rp(_A0)>::__clone(__base<_Rp(_A0)>* __p) const | |
| 1436 | { | |
| 1437 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 1438 | } | |
| 1439 | ||
| 1440 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1441 | void | |
| 1442 | __func<_Fp, _Alloc, _Rp(_A0)>::destroy() | |
| 1443 | { | |
| 1444 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1445 | } | |
| 1446 | ||
| 1447 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1448 | void | |
| 1449 | __func<_Fp, _Alloc, _Rp(_A0)>::destroy_deallocate() | |
| 1450 | { | |
| 1451 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1452 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1453 | _Ap __a(__f_.second()); | |
| 1454 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1455 | __a.deallocate(this, 1); | |
| 1456 | } | |
| 1457 | ||
| 1458 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1459 | _Rp | |
| 1460 | __func<_Fp, _Alloc, _Rp(_A0)>::operator()(_A0 __a0) | |
| 1461 | { | |
| 1462 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 1463 | return _Invoker::__call(__f_.first(), __a0); | |
| 1464 | } | |
| 1465 | ||
| 1466 | #ifndef _LIBCPP_NO_RTTI | |
| 1467 | ||
| 1468 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1469 | const void* | |
| 1470 | __func<_Fp, _Alloc, _Rp(_A0)>::target(const type_info& __ti) const | |
| 1471 | { | |
| 1472 | if (__ti == typeid(_Fp)) | |
| 1473 | return &__f_.first(); | |
| 1474 | return (const void*)0; | |
| 1475 | } | |
| 1476 | ||
| 1477 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 1478 | const std::type_info& | |
| 1479 | __func<_Fp, _Alloc, _Rp(_A0)>::target_type() const | |
| 1480 | { | |
| 1481 | return typeid(_Fp); | |
| 1482 | } | |
| 1483 | ||
| 1484 | #endif // _LIBCPP_NO_RTTI | |
| 1485 | ||
| 1486 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1487 | class __func<_Fp, _Alloc, _Rp(_A0, _A1)> | |
| 1488 | : public __base<_Rp(_A0, _A1)> | |
| 1489 | { | |
| 1490 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 1491 | public: | |
| 1492 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 1493 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) | |
| 1494 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 1495 | virtual __base<_Rp(_A0, _A1)>* __clone() const; | |
| 1496 | virtual void __clone(__base<_Rp(_A0, _A1)>*) const; | |
| 1497 | virtual void destroy(); | |
| 1498 | virtual void destroy_deallocate(); | |
| 1499 | virtual _Rp operator()(_A0, _A1); | |
| 1500 | #ifndef _LIBCPP_NO_RTTI | |
| 1501 | virtual const void* target(const type_info&) const; | |
| 1502 | virtual const std::type_info& target_type() const; | |
| 1503 | #endif // _LIBCPP_NO_RTTI | |
| 1504 | }; | |
| 1505 | ||
| 1506 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1507 | __base<_Rp(_A0, _A1)>* | |
| 1508 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone() const | |
| 1509 | { | |
| 1510 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1511 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1512 | _Ap __a(__f_.second()); | |
| 1513 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1514 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1515 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 1516 | return __hold.release(); | |
| 1517 | } | |
| 1518 | ||
| 1519 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1520 | void | |
| 1521 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone(__base<_Rp(_A0, _A1)>* __p) const | |
| 1522 | { | |
| 1523 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 1524 | } | |
| 1525 | ||
| 1526 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1527 | void | |
| 1528 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy() | |
| 1529 | { | |
| 1530 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1531 | } | |
| 1532 | ||
| 1533 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1534 | void | |
| 1535 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy_deallocate() | |
| 1536 | { | |
| 1537 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1538 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1539 | _Ap __a(__f_.second()); | |
| 1540 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1541 | __a.deallocate(this, 1); | |
| 1542 | } | |
| 1543 | ||
| 1544 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1545 | _Rp | |
| 1546 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) | |
| 1547 | { | |
| 1548 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 1549 | return _Invoker::__call(__f_.first(), __a0, __a1); | |
| 1550 | } | |
| 1551 | ||
| 1552 | #ifndef _LIBCPP_NO_RTTI | |
| 1553 | ||
| 1554 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1555 | const void* | |
| 1556 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::target(const type_info& __ti) const | |
| 1557 | { | |
| 1558 | if (__ti == typeid(_Fp)) | |
| 1559 | return &__f_.first(); | |
| 1560 | return (const void*)0; | |
| 1561 | } | |
| 1562 | ||
| 1563 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 1564 | const std::type_info& | |
| 1565 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::target_type() const | |
| 1566 | { | |
| 1567 | return typeid(_Fp); | |
| 1568 | } | |
| 1569 | ||
| 1570 | #endif // _LIBCPP_NO_RTTI | |
| 1571 | ||
| 1572 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1573 | class __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> | |
| 1574 | : public __base<_Rp(_A0, _A1, _A2)> | |
| 1575 | { | |
| 1576 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 1577 | public: | |
| 1578 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 1579 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) | |
| 1580 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 1581 | virtual __base<_Rp(_A0, _A1, _A2)>* __clone() const; | |
| 1582 | virtual void __clone(__base<_Rp(_A0, _A1, _A2)>*) const; | |
| 1583 | virtual void destroy(); | |
| 1584 | virtual void destroy_deallocate(); | |
| 1585 | virtual _Rp operator()(_A0, _A1, _A2); | |
| 1586 | #ifndef _LIBCPP_NO_RTTI | |
| 1587 | virtual const void* target(const type_info&) const; | |
| 1588 | virtual const std::type_info& target_type() const; | |
| 1589 | #endif // _LIBCPP_NO_RTTI | |
| 1590 | }; | |
| 1591 | ||
| 1592 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1593 | __base<_Rp(_A0, _A1, _A2)>* | |
| 1594 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone() const | |
| 1595 | { | |
| 1596 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1597 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1598 | _Ap __a(__f_.second()); | |
| 1599 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1600 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1601 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 1602 | return __hold.release(); | |
| 1603 | } | |
| 1604 | ||
| 1605 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1606 | void | |
| 1607 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone(__base<_Rp(_A0, _A1, _A2)>* __p) const | |
| 1608 | { | |
| 1609 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 1610 | } | |
| 1611 | ||
| 1612 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1613 | void | |
| 1614 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy() | |
| 1615 | { | |
| 1616 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1617 | } | |
| 1618 | ||
| 1619 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1620 | void | |
| 1621 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy_deallocate() | |
| 1622 | { | |
| 1623 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1624 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1625 | _Ap __a(__f_.second()); | |
| 1626 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 1627 | __a.deallocate(this, 1); | |
| 1628 | } | |
| 1629 | ||
| 1630 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1631 | _Rp | |
| 1632 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) | |
| 1633 | { | |
| 1634 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 1635 | return _Invoker::__call(__f_.first(), __a0, __a1, __a2); | |
| 1636 | } | |
| 1637 | ||
| 1638 | #ifndef _LIBCPP_NO_RTTI | |
| 1639 | ||
| 1640 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1641 | const void* | |
| 1642 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target(const type_info& __ti) const | |
| 1643 | { | |
| 1644 | if (__ti == typeid(_Fp)) | |
| 1645 | return &__f_.first(); | |
| 1646 | return (const void*)0; | |
| 1647 | } | |
| 1648 | ||
| 1649 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 1650 | const std::type_info& | |
| 1651 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target_type() const | |
| 1652 | { | |
| 1653 | return typeid(_Fp); | |
| 1654 | } | |
| 1655 | ||
| 1656 | #endif // _LIBCPP_NO_RTTI | |
| 1657 | ||
| 1658 | } // __function | |
| 1659 | ||
| 1660 | template<class _Rp> | |
| 1661 | class _LIBCPP_TEMPLATE_VIS function<_Rp()> | |
| 1662 | { | |
| 1663 | typedef __function::__base<_Rp()> __base; | |
| 1664 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 1665 | __base* __f_; | |
| 1666 | ||
| 1667 | public: | |
| 1668 | typedef _Rp result_type; | |
| 1669 | ||
| 1670 | // 20.7.16.2.1, construct/copy/destroy: | |
| 1671 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 1672 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 1673 | function(const function&); | |
| 1674 | template<class _Fp> | |
| 1675 | function(_Fp, | |
| 1676 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1677 | ||
| 1678 | template<class _Alloc> | |
| 1679 | _LIBCPP_INLINE_VISIBILITY | |
| 1680 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 1681 | template<class _Alloc> | |
| 1682 | _LIBCPP_INLINE_VISIBILITY | |
| 1683 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 1684 | template<class _Alloc> | |
| 1685 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 1686 | template<class _Fp, class _Alloc> | |
| 1687 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 1688 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1689 | ||
| 1690 | function& operator=(const function&); | |
| 1691 | function& operator=(nullptr_t); | |
| 1692 | template<class _Fp> | |
| 1693 | typename enable_if | |
| 1694 | < | |
| 1695 | !is_integral<_Fp>::value, | |
| 1696 | function& | |
| 1697 | >::type | |
| 1698 | operator=(_Fp); | |
| 1699 | ||
| 1700 | ~function(); | |
| 1701 | ||
| 1702 | // 20.7.16.2.2, function modifiers: | |
| 1703 | void swap(function&); | |
| 1704 | template<class _Fp, class _Alloc> | |
| 1705 | _LIBCPP_INLINE_VISIBILITY | |
| 1706 | void assign(_Fp __f, const _Alloc& __a) | |
| 1707 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 1708 | ||
| 1709 | // 20.7.16.2.3, function capacity: | |
| 1710 | _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} | |
| 1711 | ||
| 1712 | private: | |
| 1713 | // deleted overloads close possible hole in the type system | |
| 1714 | template<class _R2> | |
| 1715 | bool operator==(const function<_R2()>&) const;// = delete; | |
| 1716 | template<class _R2> | |
| 1717 | bool operator!=(const function<_R2()>&) const;// = delete; | |
| 1718 | public: | |
| 1719 | // 20.7.16.2.4, function invocation: | |
| 1720 | _Rp operator()() const; | |
| 1721 | ||
| 1722 | #ifndef _LIBCPP_NO_RTTI | |
| 1723 | // 20.7.16.2.5, function target access: | |
| 1724 | const std::type_info& target_type() const; | |
| 1725 | template <typename _Tp> _Tp* target(); | |
| 1726 | template <typename _Tp> const _Tp* target() const; | |
| 1727 | #endif // _LIBCPP_NO_RTTI | |
| 1728 | }; | |
| 1729 | ||
| 1730 | template<class _Rp> | |
| 1731 | function<_Rp()>::function(const function& __f) | |
| 1732 | { | |
| 1733 | if (__f.__f_ == 0) | |
| 1734 | __f_ = 0; | |
| 1735 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 1736 | { | |
| 1737 | __f_ = (__base*)&__buf_; | |
| 1738 | __f.__f_->__clone(__f_); | |
| 1739 | } | |
| 1740 | else | |
| 1741 | __f_ = __f.__f_->__clone(); | |
| 1742 | } | |
| 1743 | ||
| 1744 | template<class _Rp> | |
| 1745 | template<class _Alloc> | |
| 1746 | function<_Rp()>::function(allocator_arg_t, const _Alloc&, const function& __f) | |
| 1747 | { | |
| 1748 | if (__f.__f_ == 0) | |
| 1749 | __f_ = 0; | |
| 1750 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 1751 | { | |
| 1752 | __f_ = (__base*)&__buf_; | |
| 1753 | __f.__f_->__clone(__f_); | |
| 1754 | } | |
| 1755 | else | |
| 1756 | __f_ = __f.__f_->__clone(); | |
| 1757 | } | |
| 1758 | ||
| 1759 | template<class _Rp> | |
| 1760 | template <class _Fp> | |
| 1761 | function<_Rp()>::function(_Fp __f, | |
| 1762 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 1763 | : __f_(0) | |
| 1764 | { | |
| 1765 | if (__function::__not_null(__f)) | |
| 1766 | { | |
| 1767 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp()> _FF; | |
| 1768 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 1769 | { | |
| 1770 | __f_ = (__base*)&__buf_; | |
| 1771 | ::new ((void*)__f_) _FF(__f); | |
| 1772 | } | |
| 1773 | else | |
| 1774 | { | |
| 1775 | typedef allocator<_FF> _Ap; | |
| 1776 | _Ap __a; | |
| 1777 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1778 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1779 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 1780 | __f_ = __hold.release(); | |
| 1781 | } | |
| 1782 | } | |
| 1783 | } | |
| 1784 | ||
| 1785 | template<class _Rp> | |
| 1786 | template <class _Fp, class _Alloc> | |
| 1787 | function<_Rp()>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 1788 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 1789 | : __f_(0) | |
| 1790 | { | |
| 1791 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1792 | if (__function::__not_null(__f)) | |
| 1793 | { | |
| 1794 | typedef __function::__func<_Fp, _Alloc, _Rp()> _FF; | |
| 1795 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 1796 | { | |
| 1797 | __f_ = (__base*)&__buf_; | |
| 1798 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 1799 | } | |
| 1800 | else | |
| 1801 | { | |
| 1802 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 1803 | _Ap __a(__a0); | |
| 1804 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1805 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1806 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 1807 | __f_ = __hold.release(); | |
| 1808 | } | |
| 1809 | } | |
| 1810 | } | |
| 1811 | ||
| 1812 | template<class _Rp> | |
| 1813 | function<_Rp()>& | |
| 1814 | function<_Rp()>::operator=(const function& __f) | |
| 1815 | { | |
| 1816 | if (__f) | |
| 1817 | function(__f).swap(*this); | |
| 1818 | else | |
| 1819 | *this = nullptr; | |
| 1820 | return *this; | |
| 1821 | } | |
| 1822 | ||
| 1823 | template<class _Rp> | |
| 1824 | function<_Rp()>& | |
| 1825 | function<_Rp()>::operator=(nullptr_t) | |
| 1826 | { | |
| 1827 | __base* __t = __f_; | |
| 1828 | __f_ = 0; | |
| 1829 | if (__t == (__base*)&__buf_) | |
| 1830 | __t->destroy(); | |
| 1831 | else if (__t) | |
| 1832 | __t->destroy_deallocate(); | |
| 1833 | return *this; | |
| 1834 | } | |
| 1835 | ||
| 1836 | template<class _Rp> | |
| 1837 | template <class _Fp> | |
| 1838 | typename enable_if | |
| 1839 | < | |
| 1840 | !is_integral<_Fp>::value, | |
| 1841 | function<_Rp()>& | |
| 1842 | >::type | |
| 1843 | function<_Rp()>::operator=(_Fp __f) | |
| 1844 | { | |
| 1845 | function(_VSTD::move(__f)).swap(*this); | |
| 1846 | return *this; | |
| 1847 | } | |
| 1848 | ||
| 1849 | template<class _Rp> | |
| 1850 | function<_Rp()>::~function() | |
| 1851 | { | |
| 1852 | if (__f_ == (__base*)&__buf_) | |
| 1853 | __f_->destroy(); | |
| 1854 | else if (__f_) | |
| 1855 | __f_->destroy_deallocate(); | |
| 1856 | } | |
| 1857 | ||
| 1858 | template<class _Rp> | |
| 1859 | void | |
| 1860 | function<_Rp()>::swap(function& __f) | |
| 1861 | { | |
| 1862 | if (_VSTD::addressof(__f) == this) | |
| 1863 | return; | |
| 1864 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 1865 | { | |
| 1866 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 1867 | __base* __t = (__base*)&__tempbuf; | |
| 1868 | __f_->__clone(__t); | |
| 1869 | __f_->destroy(); | |
| 1870 | __f_ = 0; | |
| 1871 | __f.__f_->__clone((__base*)&__buf_); | |
| 1872 | __f.__f_->destroy(); | |
| 1873 | __f.__f_ = 0; | |
| 1874 | __f_ = (__base*)&__buf_; | |
| 1875 | __t->__clone((__base*)&__f.__buf_); | |
| 1876 | __t->destroy(); | |
| 1877 | __f.__f_ = (__base*)&__f.__buf_; | |
| 1878 | } | |
| 1879 | else if (__f_ == (__base*)&__buf_) | |
| 1880 | { | |
| 1881 | __f_->__clone((__base*)&__f.__buf_); | |
| 1882 | __f_->destroy(); | |
| 1883 | __f_ = __f.__f_; | |
| 1884 | __f.__f_ = (__base*)&__f.__buf_; | |
| 1885 | } | |
| 1886 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 1887 | { | |
| 1888 | __f.__f_->__clone((__base*)&__buf_); | |
| 1889 | __f.__f_->destroy(); | |
| 1890 | __f.__f_ = __f_; | |
| 1891 | __f_ = (__base*)&__buf_; | |
| 1892 | } | |
| 1893 | else | |
| 1894 | _VSTD::swap(__f_, __f.__f_); | |
| 1895 | } | |
| 1896 | ||
| 1897 | template<class _Rp> | |
| 1898 | _Rp | |
| 1899 | function<_Rp()>::operator()() const | |
| 1900 | { | |
| 1901 | if (__f_ == 0) | |
| 1902 | __throw_bad_function_call(); | |
| 1903 | return (*__f_)(); | |
| 1904 | } | |
| 1905 | ||
| 1906 | #ifndef _LIBCPP_NO_RTTI | |
| 1907 | ||
| 1908 | template<class _Rp> | |
| 1909 | const std::type_info& | |
| 1910 | function<_Rp()>::target_type() const | |
| 1911 | { | |
| 1912 | if (__f_ == 0) | |
| 1913 | return typeid(void); | |
| 1914 | return __f_->target_type(); | |
| 1915 | } | |
| 1916 | ||
| 1917 | template<class _Rp> | |
| 1918 | template <typename _Tp> | |
| 1919 | _Tp* | |
| 1920 | function<_Rp()>::target() | |
| 1921 | { | |
| 1922 | if (__f_ == 0) | |
| 1923 | return (_Tp*)0; | |
| 1924 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 1925 | } | |
| 1926 | ||
| 1927 | template<class _Rp> | |
| 1928 | template <typename _Tp> | |
| 1929 | const _Tp* | |
| 1930 | function<_Rp()>::target() const | |
| 1931 | { | |
| 1932 | if (__f_ == 0) | |
| 1933 | return (const _Tp*)0; | |
| 1934 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 1935 | } | |
| 1936 | ||
| 1937 | #endif // _LIBCPP_NO_RTTI | |
| 1938 | ||
| 1939 | template<class _Rp, class _A0> | |
| 1940 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_A0)> | |
| 1941 | : public unary_function<_A0, _Rp> | |
| 1942 | { | |
| 1943 | typedef __function::__base<_Rp(_A0)> __base; | |
| 1944 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 1945 | __base* __f_; | |
| 1946 | ||
| 1947 | public: | |
| 1948 | typedef _Rp result_type; | |
| 1949 | ||
| 1950 | // 20.7.16.2.1, construct/copy/destroy: | |
| 1951 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 1952 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 1953 | function(const function&); | |
| 1954 | template<class _Fp> | |
| 1955 | function(_Fp, | |
| 1956 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1957 | ||
| 1958 | template<class _Alloc> | |
| 1959 | _LIBCPP_INLINE_VISIBILITY | |
| 1960 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 1961 | template<class _Alloc> | |
| 1962 | _LIBCPP_INLINE_VISIBILITY | |
| 1963 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 1964 | template<class _Alloc> | |
| 1965 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 1966 | template<class _Fp, class _Alloc> | |
| 1967 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 1968 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1969 | ||
| 1970 | function& operator=(const function&); | |
| 1971 | function& operator=(nullptr_t); | |
| 1972 | template<class _Fp> | |
| 1973 | typename enable_if | |
| 1974 | < | |
| 1975 | !is_integral<_Fp>::value, | |
| 1976 | function& | |
| 1977 | >::type | |
| 1978 | operator=(_Fp); | |
| 1979 | ||
| 1980 | ~function(); | |
| 1981 | ||
| 1982 | // 20.7.16.2.2, function modifiers: | |
| 1983 | void swap(function&); | |
| 1984 | template<class _Fp, class _Alloc> | |
| 1985 | _LIBCPP_INLINE_VISIBILITY | |
| 1986 | void assign(_Fp __f, const _Alloc& __a) | |
| 1987 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 1988 | ||
| 1989 | // 20.7.16.2.3, function capacity: | |
| 1990 | _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} | |
| 1991 | ||
| 1992 | private: | |
| 1993 | // deleted overloads close possible hole in the type system | |
| 1994 | template<class _R2, class _B0> | |
| 1995 | bool operator==(const function<_R2(_B0)>&) const;// = delete; | |
| 1996 | template<class _R2, class _B0> | |
| 1997 | bool operator!=(const function<_R2(_B0)>&) const;// = delete; | |
| 1998 | public: | |
| 1999 | // 20.7.16.2.4, function invocation: | |
| 2000 | _Rp operator()(_A0) const; | |
| 2001 | ||
| 2002 | #ifndef _LIBCPP_NO_RTTI | |
| 2003 | // 20.7.16.2.5, function target access: | |
| 2004 | const std::type_info& target_type() const; | |
| 2005 | template <typename _Tp> _Tp* target(); | |
| 2006 | template <typename _Tp> const _Tp* target() const; | |
| 2007 | #endif // _LIBCPP_NO_RTTI | |
| 2008 | }; | |
| 2009 | ||
| 2010 | template<class _Rp, class _A0> | |
| 2011 | function<_Rp(_A0)>::function(const function& __f) | |
| 2012 | { | |
| 2013 | if (__f.__f_ == 0) | |
| 2014 | __f_ = 0; | |
| 2015 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 2016 | { | |
| 2017 | __f_ = (__base*)&__buf_; | |
| 2018 | __f.__f_->__clone(__f_); | |
| 2019 | } | |
| 2020 | else | |
| 2021 | __f_ = __f.__f_->__clone(); | |
| 2022 | } | |
| 2023 | ||
| 2024 | template<class _Rp, class _A0> | |
| 2025 | template<class _Alloc> | |
| 2026 | function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc&, const function& __f) | |
| 2027 | { | |
| 2028 | if (__f.__f_ == 0) | |
| 2029 | __f_ = 0; | |
| 2030 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 2031 | { | |
| 2032 | __f_ = (__base*)&__buf_; | |
| 2033 | __f.__f_->__clone(__f_); | |
| 2034 | } | |
| 2035 | else | |
| 2036 | __f_ = __f.__f_->__clone(); | |
| 2037 | } | |
| 2038 | ||
| 2039 | template<class _Rp, class _A0> | |
| 2040 | template <class _Fp> | |
| 2041 | function<_Rp(_A0)>::function(_Fp __f, | |
| 2042 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 2043 | : __f_(0) | |
| 2044 | { | |
| 2045 | if (__function::__not_null(__f)) | |
| 2046 | { | |
| 2047 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0)> _FF; | |
| 2048 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 2049 | { | |
| 2050 | __f_ = (__base*)&__buf_; | |
| 2051 | ::new ((void*)__f_) _FF(__f); | |
| 2052 | } | |
| 2053 | else | |
| 2054 | { | |
| 2055 | typedef allocator<_FF> _Ap; | |
| 2056 | _Ap __a; | |
| 2057 | typedef __allocator_destructor<_Ap> _Dp; | |
| 2058 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 2059 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 2060 | __f_ = __hold.release(); | |
| 2061 | } | |
| 2062 | } | |
| 2063 | } | |
| 2064 | ||
| 2065 | template<class _Rp, class _A0> | |
| 2066 | template <class _Fp, class _Alloc> | |
| 2067 | function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 2068 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 2069 | : __f_(0) | |
| 2070 | { | |
| 2071 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 2072 | if (__function::__not_null(__f)) | |
| 2073 | { | |
| 2074 | typedef __function::__func<_Fp, _Alloc, _Rp(_A0)> _FF; | |
| 2075 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 2076 | { | |
| 2077 | __f_ = (__base*)&__buf_; | |
| 2078 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 2079 | } | |
| 2080 | else | |
| 2081 | { | |
| 2082 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 2083 | _Ap __a(__a0); | |
| 2084 | typedef __allocator_destructor<_Ap> _Dp; | |
| 2085 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 2086 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 2087 | __f_ = __hold.release(); | |
| 2088 | } | |
| 2089 | } | |
| 2090 | } | |
| 2091 | ||
| 2092 | template<class _Rp, class _A0> | |
| 2093 | function<_Rp(_A0)>& | |
| 2094 | function<_Rp(_A0)>::operator=(const function& __f) | |
| 2095 | { | |
| 2096 | if (__f) | |
| 2097 | function(__f).swap(*this); | |
| 2098 | else | |
| 2099 | *this = nullptr; | |
| 2100 | return *this; | |
| 2101 | } | |
| 2102 | ||
| 2103 | template<class _Rp, class _A0> | |
| 2104 | function<_Rp(_A0)>& | |
| 2105 | function<_Rp(_A0)>::operator=(nullptr_t) | |
| 2106 | { | |
| 2107 | __base* __t = __f_; | |
| 2108 | __f_ = 0; | |
| 2109 | if (__t == (__base*)&__buf_) | |
| 2110 | __t->destroy(); | |
| 2111 | else if (__t) | |
| 2112 | __t->destroy_deallocate(); | |
| 2113 | return *this; | |
| 2114 | } | |
| 2115 | ||
| 2116 | template<class _Rp, class _A0> | |
| 2117 | template <class _Fp> | |
| 2118 | typename enable_if | |
| 2119 | < | |
| 2120 | !is_integral<_Fp>::value, | |
| 2121 | function<_Rp(_A0)>& | |
| 2122 | >::type | |
| 2123 | function<_Rp(_A0)>::operator=(_Fp __f) | |
| 2124 | { | |
| 2125 | function(_VSTD::move(__f)).swap(*this); | |
| 2126 | return *this; | |
| 2127 | } | |
| 2128 | ||
| 2129 | template<class _Rp, class _A0> | |
| 2130 | function<_Rp(_A0)>::~function() | |
| 2131 | { | |
| 2132 | if (__f_ == (__base*)&__buf_) | |
| 2133 | __f_->destroy(); | |
| 2134 | else if (__f_) | |
| 2135 | __f_->destroy_deallocate(); | |
| 2136 | } | |
| 2137 | ||
| 2138 | template<class _Rp, class _A0> | |
| 2139 | void | |
| 2140 | function<_Rp(_A0)>::swap(function& __f) | |
| 2141 | { | |
| 2142 | if (_VSTD::addressof(__f) == this) | |
| 2143 | return; | |
| 2144 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 2145 | { | |
| 2146 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 2147 | __base* __t = (__base*)&__tempbuf; | |
| 2148 | __f_->__clone(__t); | |
| 2149 | __f_->destroy(); | |
| 2150 | __f_ = 0; | |
| 2151 | __f.__f_->__clone((__base*)&__buf_); | |
| 2152 | __f.__f_->destroy(); | |
| 2153 | __f.__f_ = 0; | |
| 2154 | __f_ = (__base*)&__buf_; | |
| 2155 | __t->__clone((__base*)&__f.__buf_); | |
| 2156 | __t->destroy(); | |
| 2157 | __f.__f_ = (__base*)&__f.__buf_; | |
| 2158 | } | |
| 2159 | else if (__f_ == (__base*)&__buf_) | |
| 2160 | { | |
| 2161 | __f_->__clone((__base*)&__f.__buf_); | |
| 2162 | __f_->destroy(); | |
| 2163 | __f_ = __f.__f_; | |
| 2164 | __f.__f_ = (__base*)&__f.__buf_; | |
| 2165 | } | |
| 2166 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 2167 | { | |
| 2168 | __f.__f_->__clone((__base*)&__buf_); | |
| 2169 | __f.__f_->destroy(); | |
| 2170 | __f.__f_ = __f_; | |
| 2171 | __f_ = (__base*)&__buf_; | |
| 2172 | } | |
| 2173 | else | |
| 2174 | _VSTD::swap(__f_, __f.__f_); | |
| 2175 | } | |
| 2176 | ||
| 2177 | template<class _Rp, class _A0> | |
| 2178 | _Rp | |
| 2179 | function<_Rp(_A0)>::operator()(_A0 __a0) const | |
| 2180 | { | |
| 2181 | if (__f_ == 0) | |
| 2182 | __throw_bad_function_call(); | |
| 2183 | return (*__f_)(__a0); | |
| 2184 | } | |
| 2185 | ||
| 2186 | #ifndef _LIBCPP_NO_RTTI | |
| 2187 | ||
| 2188 | template<class _Rp, class _A0> | |
| 2189 | const std::type_info& | |
| 2190 | function<_Rp(_A0)>::target_type() const | |
| 2191 | { | |
| 2192 | if (__f_ == 0) | |
| 2193 | return typeid(void); | |
| 2194 | return __f_->target_type(); | |
| 2195 | } | |
| 2196 | ||
| 2197 | template<class _Rp, class _A0> | |
| 2198 | template <typename _Tp> | |
| 2199 | _Tp* | |
| 2200 | function<_Rp(_A0)>::target() | |
| 2201 | { | |
| 2202 | if (__f_ == 0) | |
| 2203 | return (_Tp*)0; | |
| 2204 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 2205 | } | |
| 2206 | ||
| 2207 | template<class _Rp, class _A0> | |
| 2208 | template <typename _Tp> | |
| 2209 | const _Tp* | |
| 2210 | function<_Rp(_A0)>::target() const | |
| 2211 | { | |
| 2212 | if (__f_ == 0) | |
| 2213 | return (const _Tp*)0; | |
| 2214 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 2215 | } | |
| 2216 | ||
| 2217 | #endif // _LIBCPP_NO_RTTI | |
| 2218 | ||
| 2219 | template<class _Rp, class _A0, class _A1> | |
| 2220 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_A0, _A1)> | |
| 2221 | : public binary_function<_A0, _A1, _Rp> | |
| 2222 | { | |
| 2223 | typedef __function::__base<_Rp(_A0, _A1)> __base; | |
| 2224 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 2225 | __base* __f_; | |
| 2226 | ||
| 2227 | public: | |
| 2228 | typedef _Rp result_type; | |
| 2229 | ||
| 2230 | // 20.7.16.2.1, construct/copy/destroy: | |
| 2231 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 2232 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 2233 | function(const function&); | |
| 2234 | template<class _Fp> | |
| 2235 | function(_Fp, | |
| 2236 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 2237 | ||
| 2238 | template<class _Alloc> | |
| 2239 | _LIBCPP_INLINE_VISIBILITY | |
| 2240 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 2241 | template<class _Alloc> | |
| 2242 | _LIBCPP_INLINE_VISIBILITY | |
| 2243 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 2244 | template<class _Alloc> | |
| 2245 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 2246 | template<class _Fp, class _Alloc> | |
| 2247 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 2248 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 2249 | ||
| 2250 | function& operator=(const function&); | |
| 2251 | function& operator=(nullptr_t); | |
| 2252 | template<class _Fp> | |
| 2253 | typename enable_if | |
| 2254 | < | |
| 2255 | !is_integral<_Fp>::value, | |
| 2256 | function& | |
| 2257 | >::type | |
| 2258 | operator=(_Fp); | |
| 2259 | ||
| 2260 | ~function(); | |
| 2261 | ||
| 2262 | // 20.7.16.2.2, function modifiers: | |
| 2263 | void swap(function&); | |
| 2264 | template<class _Fp, class _Alloc> | |
| 2265 | _LIBCPP_INLINE_VISIBILITY | |
| 2266 | void assign(_Fp __f, const _Alloc& __a) | |
| 2267 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 2268 | ||
| 2269 | // 20.7.16.2.3, function capacity: | |
| 2270 | _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} | |
| 2271 | ||
| 2272 | private: | |
| 2273 | // deleted overloads close possible hole in the type system | |
| 2274 | template<class _R2, class _B0, class _B1> | |
| 2275 | bool operator==(const function<_R2(_B0, _B1)>&) const;// = delete; | |
| 2276 | template<class _R2, class _B0, class _B1> | |
| 2277 | bool operator!=(const function<_R2(_B0, _B1)>&) const;// = delete; | |
| 2278 | public: | |
| 2279 | // 20.7.16.2.4, function invocation: | |
| 2280 | _Rp operator()(_A0, _A1) const; | |
| 2281 | ||
| 2282 | #ifndef _LIBCPP_NO_RTTI | |
| 2283 | // 20.7.16.2.5, function target access: | |
| 2284 | const std::type_info& target_type() const; | |
| 2285 | template <typename _Tp> _Tp* target(); | |
| 2286 | template <typename _Tp> const _Tp* target() const; | |
| 2287 | #endif // _LIBCPP_NO_RTTI | |
| 2288 | }; | |
| 2289 | ||
| 2290 | template<class _Rp, class _A0, class _A1> | |
| 2291 | function<_Rp(_A0, _A1)>::function(const function& __f) | |
| 2292 | { | |
| 2293 | if (__f.__f_ == 0) | |
| 2294 | __f_ = 0; | |
| 2295 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 2296 | { | |
| 2297 | __f_ = (__base*)&__buf_; | |
| 2298 | __f.__f_->__clone(__f_); | |
| 2299 | } | |
| 2300 | else | |
| 2301 | __f_ = __f.__f_->__clone(); | |
| 2302 | } | |
| 2303 | ||
| 2304 | template<class _Rp, class _A0, class _A1> | |
| 2305 | template<class _Alloc> | |
| 2306 | function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc&, const function& __f) | |
| 2307 | { | |
| 2308 | if (__f.__f_ == 0) | |
| 2309 | __f_ = 0; | |
| 2310 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 2311 | { | |
| 2312 | __f_ = (__base*)&__buf_; | |
| 2313 | __f.__f_->__clone(__f_); | |
| 2314 | } | |
| 2315 | else | |
| 2316 | __f_ = __f.__f_->__clone(); | |
| 2317 | } | |
| 2318 | ||
| 2319 | template<class _Rp, class _A0, class _A1> | |
| 2320 | template <class _Fp> | |
| 2321 | function<_Rp(_A0, _A1)>::function(_Fp __f, | |
| 2322 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 2323 | : __f_(0) | |
| 2324 | { | |
| 2325 | if (__function::__not_null(__f)) | |
| 2326 | { | |
| 2327 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1)> _FF; | |
| 2328 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 2329 | { | |
| 2330 | __f_ = (__base*)&__buf_; | |
| 2331 | ::new ((void*)__f_) _FF(__f); | |
| 2332 | } | |
| 2333 | else | |
| 2334 | { | |
| 2335 | typedef allocator<_FF> _Ap; | |
| 2336 | _Ap __a; | |
| 2337 | typedef __allocator_destructor<_Ap> _Dp; | |
| 2338 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 2339 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 2340 | __f_ = __hold.release(); | |
| 2341 | } | |
| 2342 | } | |
| 2343 | } | |
| 2344 | ||
| 2345 | template<class _Rp, class _A0, class _A1> | |
| 2346 | template <class _Fp, class _Alloc> | |
| 2347 | function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 2348 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 2349 | : __f_(0) | |
| 2350 | { | |
| 2351 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 2352 | if (__function::__not_null(__f)) | |
| 2353 | { | |
| 2354 | typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1)> _FF; | |
| 2355 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 2356 | { | |
| 2357 | __f_ = (__base*)&__buf_; | |
| 2358 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 2359 | } | |
| 2360 | else | |
| 2361 | { | |
| 2362 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 2363 | _Ap __a(__a0); | |
| 2364 | typedef __allocator_destructor<_Ap> _Dp; | |
| 2365 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 2366 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 2367 | __f_ = __hold.release(); | |
| 2368 | } | |
| 2369 | } | |
| 2370 | } | |
| 2371 | ||
| 2372 | template<class _Rp, class _A0, class _A1> | |
| 2373 | function<_Rp(_A0, _A1)>& | |
| 2374 | function<_Rp(_A0, _A1)>::operator=(const function& __f) | |
| 2375 | { | |
| 2376 | if (__f) | |
| 2377 | function(__f).swap(*this); | |
| 2378 | else | |
| 2379 | *this = nullptr; | |
| 2380 | return *this; | |
| 2381 | } | |
| 2382 | ||
| 2383 | template<class _Rp, class _A0, class _A1> | |
| 2384 | function<_Rp(_A0, _A1)>& | |
| 2385 | function<_Rp(_A0, _A1)>::operator=(nullptr_t) | |
| 2386 | { | |
| 2387 | __base* __t = __f_; | |
| 2388 | __f_ = 0; | |
| 2389 | if (__t == (__base*)&__buf_) | |
| 2390 | __t->destroy(); | |
| 2391 | else if (__t) | |
| 2392 | __t->destroy_deallocate(); | |
| 2393 | return *this; | |
| 2394 | } | |
| 2395 | ||
| 2396 | template<class _Rp, class _A0, class _A1> | |
| 2397 | template <class _Fp> | |
| 2398 | typename enable_if | |
| 2399 | < | |
| 2400 | !is_integral<_Fp>::value, | |
| 2401 | function<_Rp(_A0, _A1)>& | |
| 2402 | >::type | |
| 2403 | function<_Rp(_A0, _A1)>::operator=(_Fp __f) | |
| 2404 | { | |
| 2405 | function(_VSTD::move(__f)).swap(*this); | |
| 2406 | return *this; | |
| 2407 | } | |
| 2408 | ||
| 2409 | template<class _Rp, class _A0, class _A1> | |
| 2410 | function<_Rp(_A0, _A1)>::~function() | |
| 2411 | { | |
| 2412 | if (__f_ == (__base*)&__buf_) | |
| 2413 | __f_->destroy(); | |
| 2414 | else if (__f_) | |
| 2415 | __f_->destroy_deallocate(); | |
| 2416 | } | |
| 2417 | ||
| 2418 | template<class _Rp, class _A0, class _A1> | |
| 2419 | void | |
| 2420 | function<_Rp(_A0, _A1)>::swap(function& __f) | |
| 2421 | { | |
| 2422 | if (_VSTD::addressof(__f) == this) | |
| 2423 | return; | |
| 2424 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 2425 | { | |
| 2426 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 2427 | __base* __t = (__base*)&__tempbuf; | |
| 2428 | __f_->__clone(__t); | |
| 2429 | __f_->destroy(); | |
| 2430 | __f_ = 0; | |
| 2431 | __f.__f_->__clone((__base*)&__buf_); | |
| 2432 | __f.__f_->destroy(); | |
| 2433 | __f.__f_ = 0; | |
| 2434 | __f_ = (__base*)&__buf_; | |
| 2435 | __t->__clone((__base*)&__f.__buf_); | |
| 2436 | __t->destroy(); | |
| 2437 | __f.__f_ = (__base*)&__f.__buf_; | |
| 2438 | } | |
| 2439 | else if (__f_ == (__base*)&__buf_) | |
| 2440 | { | |
| 2441 | __f_->__clone((__base*)&__f.__buf_); | |
| 2442 | __f_->destroy(); | |
| 2443 | __f_ = __f.__f_; | |
| 2444 | __f.__f_ = (__base*)&__f.__buf_; | |
| 2445 | } | |
| 2446 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 2447 | { | |
| 2448 | __f.__f_->__clone((__base*)&__buf_); | |
| 2449 | __f.__f_->destroy(); | |
| 2450 | __f.__f_ = __f_; | |
| 2451 | __f_ = (__base*)&__buf_; | |
| 2452 | } | |
| 2453 | else | |
| 2454 | _VSTD::swap(__f_, __f.__f_); | |
| 2455 | } | |
| 2456 | ||
| 2457 | template<class _Rp, class _A0, class _A1> | |
| 2458 | _Rp | |
| 2459 | function<_Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) const | |
| 2460 | { | |
| 2461 | if (__f_ == 0) | |
| 2462 | __throw_bad_function_call(); | |
| 2463 | return (*__f_)(__a0, __a1); | |
| 2464 | } | |
| 2465 | ||
| 2466 | #ifndef _LIBCPP_NO_RTTI | |
| 2467 | ||
| 2468 | template<class _Rp, class _A0, class _A1> | |
| 2469 | const std::type_info& | |
| 2470 | function<_Rp(_A0, _A1)>::target_type() const | |
| 2471 | { | |
| 2472 | if (__f_ == 0) | |
| 2473 | return typeid(void); | |
| 2474 | return __f_->target_type(); | |
| 2475 | } | |
| 2476 | ||
| 2477 | template<class _Rp, class _A0, class _A1> | |
| 2478 | template <typename _Tp> | |
| 2479 | _Tp* | |
| 2480 | function<_Rp(_A0, _A1)>::target() | |
| 2481 | { | |
| 2482 | if (__f_ == 0) | |
| 2483 | return (_Tp*)0; | |
| 2484 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 2485 | } | |
| 2486 | ||
| 2487 | template<class _Rp, class _A0, class _A1> | |
| 2488 | template <typename _Tp> | |
| 2489 | const _Tp* | |
| 2490 | function<_Rp(_A0, _A1)>::target() const | |
| 2491 | { | |
| 2492 | if (__f_ == 0) | |
| 2493 | return (const _Tp*)0; | |
| 2494 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 2495 | } | |
| 2496 | ||
| 2497 | #endif // _LIBCPP_NO_RTTI | |
| 2498 | ||
| 2499 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2500 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_A0, _A1, _A2)> | |
| 2501 | { | |
| 2502 | typedef __function::__base<_Rp(_A0, _A1, _A2)> __base; | |
| 2503 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 2504 | __base* __f_; | |
| 2505 | ||
| 2506 | public: | |
| 2507 | typedef _Rp result_type; | |
| 2508 | ||
| 2509 | // 20.7.16.2.1, construct/copy/destroy: | |
| 2510 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 2511 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 2512 | function(const function&); | |
| 2513 | template<class _Fp> | |
| 2514 | function(_Fp, | |
| 2515 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 2516 | ||
| 2517 | template<class _Alloc> | |
| 2518 | _LIBCPP_INLINE_VISIBILITY | |
| 2519 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 2520 | template<class _Alloc> | |
| 2521 | _LIBCPP_INLINE_VISIBILITY | |
| 2522 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 2523 | template<class _Alloc> | |
| 2524 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 2525 | template<class _Fp, class _Alloc> | |
| 2526 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 2527 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 2528 | ||
| 2529 | function& operator=(const function&); | |
| 2530 | function& operator=(nullptr_t); | |
| 2531 | template<class _Fp> | |
| 2532 | typename enable_if | |
| 2533 | < | |
| 2534 | !is_integral<_Fp>::value, | |
| 2535 | function& | |
| 2536 | >::type | |
| 2537 | operator=(_Fp); | |
| 2538 | ||
| 2539 | ~function(); | |
| 2540 | ||
| 2541 | // 20.7.16.2.2, function modifiers: | |
| 2542 | void swap(function&); | |
| 2543 | template<class _Fp, class _Alloc> | |
| 2544 | _LIBCPP_INLINE_VISIBILITY | |
| 2545 | void assign(_Fp __f, const _Alloc& __a) | |
| 2546 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 2547 | ||
| 2548 | // 20.7.16.2.3, function capacity: | |
| 2549 | _LIBCPP_INLINE_VISIBILITY explicit operator bool() const {return __f_;} | |
| 2550 | ||
| 2551 | private: | |
| 2552 | // deleted overloads close possible hole in the type system | |
| 2553 | template<class _R2, class _B0, class _B1, class _B2> | |
| 2554 | bool operator==(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; | |
| 2555 | template<class _R2, class _B0, class _B1, class _B2> | |
| 2556 | bool operator!=(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; | |
| 2557 | public: | |
| 2558 | // 20.7.16.2.4, function invocation: | |
| 2559 | _Rp operator()(_A0, _A1, _A2) const; | |
| 2560 | ||
| 2561 | #ifndef _LIBCPP_NO_RTTI | |
| 2562 | // 20.7.16.2.5, function target access: | |
| 2563 | const std::type_info& target_type() const; | |
| 2564 | template <typename _Tp> _Tp* target(); | |
| 2565 | template <typename _Tp> const _Tp* target() const; | |
| 2566 | #endif // _LIBCPP_NO_RTTI | |
| 2567 | }; | |
| 2568 | ||
| 2569 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2570 | function<_Rp(_A0, _A1, _A2)>::function(const function& __f) | |
| 2571 | { | |
| 2572 | if (__f.__f_ == 0) | |
| 2573 | __f_ = 0; | |
| 2574 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 2575 | { | |
| 2576 | __f_ = (__base*)&__buf_; | |
| 2577 | __f.__f_->__clone(__f_); | |
| 2578 | } | |
| 2579 | else | |
| 2580 | __f_ = __f.__f_->__clone(); | |
| 2581 | } | |
| 2582 | ||
| 2583 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2584 | template<class _Alloc> | |
| 2585 | function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc&, | |
| 2586 | const function& __f) | |
| 2587 | { | |
| 2588 | if (__f.__f_ == 0) | |
| 2589 | __f_ = 0; | |
| 2590 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 2591 | { | |
| 2592 | __f_ = (__base*)&__buf_; | |
| 2593 | __f.__f_->__clone(__f_); | |
| 2594 | } | |
| 2595 | else | |
| 2596 | __f_ = __f.__f_->__clone(); | |
| 2597 | } | |
| 2598 | ||
| 2599 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2600 | template <class _Fp> | |
| 2601 | function<_Rp(_A0, _A1, _A2)>::function(_Fp __f, | |
| 2602 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 2603 | : __f_(0) | |
| 2604 | { | |
| 2605 | if (__function::__not_null(__f)) | |
| 2606 | { | |
| 2607 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1, _A2)> _FF; | |
| 2608 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 2609 | { | |
| 2610 | __f_ = (__base*)&__buf_; | |
| 2611 | ::new ((void*)__f_) _FF(__f); | |
| 2612 | } | |
| 2613 | else | |
| 2614 | { | |
| 2615 | typedef allocator<_FF> _Ap; | |
| 2616 | _Ap __a; | |
| 2617 | typedef __allocator_destructor<_Ap> _Dp; | |
| 2618 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 2619 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 2620 | __f_ = __hold.release(); | |
| 2621 | } | |
| 2622 | } | |
| 2623 | } | |
| 2624 | ||
| 2625 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2626 | template <class _Fp, class _Alloc> | |
| 2627 | function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 2628 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 2629 | : __f_(0) | |
| 2630 | { | |
| 2631 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 2632 | if (__function::__not_null(__f)) | |
| 2633 | { | |
| 2634 | typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> _FF; | |
| 2635 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 2636 | { | |
| 2637 | __f_ = (__base*)&__buf_; | |
| 2638 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 2639 | } | |
| 2640 | else | |
| 2641 | { | |
| 2642 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 2643 | _Ap __a(__a0); | |
| 2644 | typedef __allocator_destructor<_Ap> _Dp; | |
| 2645 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 2646 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 2647 | __f_ = __hold.release(); | |
| 2648 | } | |
| 2649 | } | |
| 2650 | } | |
| 2651 | ||
| 2652 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2653 | function<_Rp(_A0, _A1, _A2)>& | |
| 2654 | function<_Rp(_A0, _A1, _A2)>::operator=(const function& __f) | |
| 2655 | { | |
| 2656 | if (__f) | |
| 2657 | function(__f).swap(*this); | |
| 2658 | else | |
| 2659 | *this = nullptr; | |
| 2660 | return *this; | |
| 2661 | } | |
| 2662 | ||
| 2663 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2664 | function<_Rp(_A0, _A1, _A2)>& | |
| 2665 | function<_Rp(_A0, _A1, _A2)>::operator=(nullptr_t) | |
| 2666 | { | |
| 2667 | __base* __t = __f_; | |
| 2668 | __f_ = 0; | |
| 2669 | if (__t == (__base*)&__buf_) | |
| 2670 | __t->destroy(); | |
| 2671 | else if (__t) | |
| 2672 | __t->destroy_deallocate(); | |
| 2673 | return *this; | |
| 2674 | } | |
| 2675 | ||
| 2676 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2677 | template <class _Fp> | |
| 2678 | typename enable_if | |
| 2679 | < | |
| 2680 | !is_integral<_Fp>::value, | |
| 2681 | function<_Rp(_A0, _A1, _A2)>& | |
| 2682 | >::type | |
| 2683 | function<_Rp(_A0, _A1, _A2)>::operator=(_Fp __f) | |
| 2684 | { | |
| 2685 | function(_VSTD::move(__f)).swap(*this); | |
| 2686 | return *this; | |
| 2687 | } | |
| 2688 | ||
| 2689 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2690 | function<_Rp(_A0, _A1, _A2)>::~function() | |
| 2691 | { | |
| 2692 | if (__f_ == (__base*)&__buf_) | |
| 2693 | __f_->destroy(); | |
| 2694 | else if (__f_) | |
| 2695 | __f_->destroy_deallocate(); | |
| 2696 | } | |
| 2697 | ||
| 2698 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2699 | void | |
| 2700 | function<_Rp(_A0, _A1, _A2)>::swap(function& __f) | |
| 2701 | { | |
| 2702 | if (_VSTD::addressof(__f) == this) | |
| 2703 | return; | |
| 2704 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 2705 | { | |
| 2706 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 2707 | __base* __t = (__base*)&__tempbuf; | |
| 2708 | __f_->__clone(__t); | |
| 2709 | __f_->destroy(); | |
| 2710 | __f_ = 0; | |
| 2711 | __f.__f_->__clone((__base*)&__buf_); | |
| 2712 | __f.__f_->destroy(); | |
| 2713 | __f.__f_ = 0; | |
| 2714 | __f_ = (__base*)&__buf_; | |
| 2715 | __t->__clone((__base*)&__f.__buf_); | |
| 2716 | __t->destroy(); | |
| 2717 | __f.__f_ = (__base*)&__f.__buf_; | |
| 2718 | } | |
| 2719 | else if (__f_ == (__base*)&__buf_) | |
| 2720 | { | |
| 2721 | __f_->__clone((__base*)&__f.__buf_); | |
| 2722 | __f_->destroy(); | |
| 2723 | __f_ = __f.__f_; | |
| 2724 | __f.__f_ = (__base*)&__f.__buf_; | |
| 2725 | } | |
| 2726 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 2727 | { | |
| 2728 | __f.__f_->__clone((__base*)&__buf_); | |
| 2729 | __f.__f_->destroy(); | |
| 2730 | __f.__f_ = __f_; | |
| 2731 | __f_ = (__base*)&__buf_; | |
| 2732 | } | |
| 2733 | else | |
| 2734 | _VSTD::swap(__f_, __f.__f_); | |
| 2735 | } | |
| 2736 | ||
| 2737 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2738 | _Rp | |
| 2739 | function<_Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) const | |
| 2740 | { | |
| 2741 | if (__f_ == 0) | |
| 2742 | __throw_bad_function_call(); | |
| 2743 | return (*__f_)(__a0, __a1, __a2); | |
| 2744 | } | |
| 2745 | ||
| 2746 | #ifndef _LIBCPP_NO_RTTI | |
| 2747 | ||
| 2748 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2749 | const std::type_info& | |
| 2750 | function<_Rp(_A0, _A1, _A2)>::target_type() const | |
| 2751 | { | |
| 2752 | if (__f_ == 0) | |
| 2753 | return typeid(void); | |
| 2754 | return __f_->target_type(); | |
| 2755 | } | |
| 2756 | ||
| 2757 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2758 | template <typename _Tp> | |
| 2759 | _Tp* | |
| 2760 | function<_Rp(_A0, _A1, _A2)>::target() | |
| 2761 | { | |
| 2762 | if (__f_ == 0) | |
| 2763 | return (_Tp*)0; | |
| 2764 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 2765 | } | |
| 2766 | ||
| 2767 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 2768 | template <typename _Tp> | |
| 2769 | const _Tp* | |
| 2770 | function<_Rp(_A0, _A1, _A2)>::target() const | |
| 2771 | { | |
| 2772 | if (__f_ == 0) | |
| 2773 | return (const _Tp*)0; | |
| 2774 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 2775 | } | |
| 2776 | ||
| 2777 | #endif // _LIBCPP_NO_RTTI | |
| 2778 | ||
| 2779 | template <class _Fp> | |
| 2780 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2781 | bool | |
| 2782 | operator==(const function<_Fp>& __f, nullptr_t) {return !__f;} | |
| 2783 | ||
| 2784 | template <class _Fp> | |
| 2785 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2786 | bool | |
| 2787 | operator==(nullptr_t, const function<_Fp>& __f) {return !__f;} | |
| 2788 | ||
| 2789 | template <class _Fp> | |
| 2790 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2791 | bool | |
| 2792 | operator!=(const function<_Fp>& __f, nullptr_t) {return (bool)__f;} | |
| 2793 | ||
| 2794 | template <class _Fp> | |
| 2795 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2796 | bool | |
| 2797 | operator!=(nullptr_t, const function<_Fp>& __f) {return (bool)__f;} | |
| 2798 | ||
| 2799 | template <class _Fp> | |
| 2800 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2801 | void | |
| 2802 | swap(function<_Fp>& __x, function<_Fp>& __y) | |
| 2803 | {return __x.swap(__y);} | |
| 2804 | ||
| 2805 | #endif | |
| 2806 | ||
| 2807 | _LIBCPP_END_NAMESPACE_STD | |
| 2808 | ||
| 2809 | #endif // _LIBCPP___FUNCTIONAL_FUNCTION_H |
lib/libcxx/include/__functional/hash.h created+873| ... | ... | @@ -0,0 +1,873 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___FUNCTIONAL_HASH_H | |
| 10 | #define _LIBCPP___FUNCTIONAL_HASH_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__functional/unary_function.h> | |
| 14 | #include <__tuple> | |
| 15 | #include <__utility/forward.h> | |
| 16 | #include <__utility/move.h> | |
| 17 | #include <__utility/pair.h> | |
| 18 | #include <__utility/swap.h> | |
| 19 | #include <cstdint> | |
| 20 | #include <cstring> | |
| 21 | #include <cstddef> | |
| 22 | #include <limits> | |
| 23 | #include <type_traits> | |
| 24 | ||
| 25 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 26 | #pragma GCC system_header | |
| 27 | #endif | |
| 28 | ||
| 29 | _LIBCPP_PUSH_MACROS | |
| 30 | #include <__undef_macros> | |
| 31 | ||
| 32 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 33 | ||
| 34 | template <class _Size> | |
| 35 | inline _LIBCPP_INLINE_VISIBILITY | |
| 36 | _Size | |
| 37 | __loadword(const void* __p) | |
| 38 | { | |
| 39 | _Size __r; | |
| 40 | _VSTD::memcpy(&__r, __p, sizeof(__r)); | |
| 41 | return __r; | |
| 42 | } | |
| 43 | ||
| 44 | // We use murmur2 when size_t is 32 bits, and cityhash64 when size_t | |
| 45 | // is 64 bits. This is because cityhash64 uses 64bit x 64bit | |
| 46 | // multiplication, which can be very slow on 32-bit systems. | |
| 47 | template <class _Size, size_t = sizeof(_Size)*__CHAR_BIT__> | |
| 48 | struct __murmur2_or_cityhash; | |
| 49 | ||
| 50 | template <class _Size> | |
| 51 | struct __murmur2_or_cityhash<_Size, 32> | |
| 52 | { | |
| 53 | inline _Size operator()(const void* __key, _Size __len) | |
| 54 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; | |
| 55 | }; | |
| 56 | ||
| 57 | // murmur2 | |
| 58 | template <class _Size> | |
| 59 | _Size | |
| 60 | __murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) | |
| 61 | { | |
| 62 | const _Size __m = 0x5bd1e995; | |
| 63 | const _Size __r = 24; | |
| 64 | _Size __h = __len; | |
| 65 | const unsigned char* __data = static_cast<const unsigned char*>(__key); | |
| 66 | for (; __len >= 4; __data += 4, __len -= 4) | |
| 67 | { | |
| 68 | _Size __k = __loadword<_Size>(__data); | |
| 69 | __k *= __m; | |
| 70 | __k ^= __k >> __r; | |
| 71 | __k *= __m; | |
| 72 | __h *= __m; | |
| 73 | __h ^= __k; | |
| 74 | } | |
| 75 | switch (__len) | |
| 76 | { | |
| 77 | case 3: | |
| 78 | __h ^= static_cast<_Size>(__data[2] << 16); | |
| 79 | _LIBCPP_FALLTHROUGH(); | |
| 80 | case 2: | |
| 81 | __h ^= static_cast<_Size>(__data[1] << 8); | |
| 82 | _LIBCPP_FALLTHROUGH(); | |
| 83 | case 1: | |
| 84 | __h ^= __data[0]; | |
| 85 | __h *= __m; | |
| 86 | } | |
| 87 | __h ^= __h >> 13; | |
| 88 | __h *= __m; | |
| 89 | __h ^= __h >> 15; | |
| 90 | return __h; | |
| 91 | } | |
| 92 | ||
| 93 | template <class _Size> | |
| 94 | struct __murmur2_or_cityhash<_Size, 64> | |
| 95 | { | |
| 96 | inline _Size operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; | |
| 97 | ||
| 98 | private: | |
| 99 | // Some primes between 2^63 and 2^64. | |
| 100 | static const _Size __k0 = 0xc3a5c85c97cb3127ULL; | |
| 101 | static const _Size __k1 = 0xb492b66fbe98f273ULL; | |
| 102 | static const _Size __k2 = 0x9ae16a3b2f90404fULL; | |
| 103 | static const _Size __k3 = 0xc949d7c7509e6557ULL; | |
| 104 | ||
| 105 | static _Size __rotate(_Size __val, int __shift) { | |
| 106 | return __shift == 0 ? __val : ((__val >> __shift) | (__val << (64 - __shift))); | |
| 107 | } | |
| 108 | ||
| 109 | static _Size __rotate_by_at_least_1(_Size __val, int __shift) { | |
| 110 | return (__val >> __shift) | (__val << (64 - __shift)); | |
| 111 | } | |
| 112 | ||
| 113 | static _Size __shift_mix(_Size __val) { | |
| 114 | return __val ^ (__val >> 47); | |
| 115 | } | |
| 116 | ||
| 117 | static _Size __hash_len_16(_Size __u, _Size __v) | |
| 118 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 119 | { | |
| 120 | const _Size __mul = 0x9ddfea08eb382d69ULL; | |
| 121 | _Size __a = (__u ^ __v) * __mul; | |
| 122 | __a ^= (__a >> 47); | |
| 123 | _Size __b = (__v ^ __a) * __mul; | |
| 124 | __b ^= (__b >> 47); | |
| 125 | __b *= __mul; | |
| 126 | return __b; | |
| 127 | } | |
| 128 | ||
| 129 | static _Size __hash_len_0_to_16(const char* __s, _Size __len) | |
| 130 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 131 | { | |
| 132 | if (__len > 8) { | |
| 133 | const _Size __a = __loadword<_Size>(__s); | |
| 134 | const _Size __b = __loadword<_Size>(__s + __len - 8); | |
| 135 | return __hash_len_16(__a, __rotate_by_at_least_1(__b + __len, __len)) ^ __b; | |
| 136 | } | |
| 137 | if (__len >= 4) { | |
| 138 | const uint32_t __a = __loadword<uint32_t>(__s); | |
| 139 | const uint32_t __b = __loadword<uint32_t>(__s + __len - 4); | |
| 140 | return __hash_len_16(__len + (__a << 3), __b); | |
| 141 | } | |
| 142 | if (__len > 0) { | |
| 143 | const unsigned char __a = static_cast<unsigned char>(__s[0]); | |
| 144 | const unsigned char __b = static_cast<unsigned char>(__s[__len >> 1]); | |
| 145 | const unsigned char __c = static_cast<unsigned char>(__s[__len - 1]); | |
| 146 | const uint32_t __y = static_cast<uint32_t>(__a) + | |
| 147 | (static_cast<uint32_t>(__b) << 8); | |
| 148 | const uint32_t __z = __len + (static_cast<uint32_t>(__c) << 2); | |
| 149 | return __shift_mix(__y * __k2 ^ __z * __k3) * __k2; | |
| 150 | } | |
| 151 | return __k2; | |
| 152 | } | |
| 153 | ||
| 154 | static _Size __hash_len_17_to_32(const char *__s, _Size __len) | |
| 155 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 156 | { | |
| 157 | const _Size __a = __loadword<_Size>(__s) * __k1; | |
| 158 | const _Size __b = __loadword<_Size>(__s + 8); | |
| 159 | const _Size __c = __loadword<_Size>(__s + __len - 8) * __k2; | |
| 160 | const _Size __d = __loadword<_Size>(__s + __len - 16) * __k0; | |
| 161 | return __hash_len_16(__rotate(__a - __b, 43) + __rotate(__c, 30) + __d, | |
| 162 | __a + __rotate(__b ^ __k3, 20) - __c + __len); | |
| 163 | } | |
| 164 | ||
| 165 | // Return a 16-byte hash for 48 bytes. Quick and dirty. | |
| 166 | // Callers do best to use "random-looking" values for a and b. | |
| 167 | static pair<_Size, _Size> __weak_hash_len_32_with_seeds( | |
| 168 | _Size __w, _Size __x, _Size __y, _Size __z, _Size __a, _Size __b) | |
| 169 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 170 | { | |
| 171 | __a += __w; | |
| 172 | __b = __rotate(__b + __a + __z, 21); | |
| 173 | const _Size __c = __a; | |
| 174 | __a += __x; | |
| 175 | __a += __y; | |
| 176 | __b += __rotate(__a, 44); | |
| 177 | return pair<_Size, _Size>(__a + __z, __b + __c); | |
| 178 | } | |
| 179 | ||
| 180 | // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. | |
| 181 | static pair<_Size, _Size> __weak_hash_len_32_with_seeds( | |
| 182 | const char* __s, _Size __a, _Size __b) | |
| 183 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 184 | { | |
| 185 | return __weak_hash_len_32_with_seeds(__loadword<_Size>(__s), | |
| 186 | __loadword<_Size>(__s + 8), | |
| 187 | __loadword<_Size>(__s + 16), | |
| 188 | __loadword<_Size>(__s + 24), | |
| 189 | __a, | |
| 190 | __b); | |
| 191 | } | |
| 192 | ||
| 193 | // Return an 8-byte hash for 33 to 64 bytes. | |
| 194 | static _Size __hash_len_33_to_64(const char *__s, size_t __len) | |
| 195 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 196 | { | |
| 197 | _Size __z = __loadword<_Size>(__s + 24); | |
| 198 | _Size __a = __loadword<_Size>(__s) + | |
| 199 | (__len + __loadword<_Size>(__s + __len - 16)) * __k0; | |
| 200 | _Size __b = __rotate(__a + __z, 52); | |
| 201 | _Size __c = __rotate(__a, 37); | |
| 202 | __a += __loadword<_Size>(__s + 8); | |
| 203 | __c += __rotate(__a, 7); | |
| 204 | __a += __loadword<_Size>(__s + 16); | |
| 205 | _Size __vf = __a + __z; | |
| 206 | _Size __vs = __b + __rotate(__a, 31) + __c; | |
| 207 | __a = __loadword<_Size>(__s + 16) + __loadword<_Size>(__s + __len - 32); | |
| 208 | __z += __loadword<_Size>(__s + __len - 8); | |
| 209 | __b = __rotate(__a + __z, 52); | |
| 210 | __c = __rotate(__a, 37); | |
| 211 | __a += __loadword<_Size>(__s + __len - 24); | |
| 212 | __c += __rotate(__a, 7); | |
| 213 | __a += __loadword<_Size>(__s + __len - 16); | |
| 214 | _Size __wf = __a + __z; | |
| 215 | _Size __ws = __b + __rotate(__a, 31) + __c; | |
| 216 | _Size __r = __shift_mix((__vf + __ws) * __k2 + (__wf + __vs) * __k0); | |
| 217 | return __shift_mix(__r * __k0 + __vs) * __k2; | |
| 218 | } | |
| 219 | }; | |
| 220 | ||
| 221 | // cityhash64 | |
| 222 | template <class _Size> | |
| 223 | _Size | |
| 224 | __murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len) | |
| 225 | { | |
| 226 | const char* __s = static_cast<const char*>(__key); | |
| 227 | if (__len <= 32) { | |
| 228 | if (__len <= 16) { | |
| 229 | return __hash_len_0_to_16(__s, __len); | |
| 230 | } else { | |
| 231 | return __hash_len_17_to_32(__s, __len); | |
| 232 | } | |
| 233 | } else if (__len <= 64) { | |
| 234 | return __hash_len_33_to_64(__s, __len); | |
| 235 | } | |
| 236 | ||
| 237 | // For strings over 64 bytes we hash the end first, and then as we | |
| 238 | // loop we keep 56 bytes of state: v, w, x, y, and z. | |
| 239 | _Size __x = __loadword<_Size>(__s + __len - 40); | |
| 240 | _Size __y = __loadword<_Size>(__s + __len - 16) + | |
| 241 | __loadword<_Size>(__s + __len - 56); | |
| 242 | _Size __z = __hash_len_16(__loadword<_Size>(__s + __len - 48) + __len, | |
| 243 | __loadword<_Size>(__s + __len - 24)); | |
| 244 | pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); | |
| 245 | pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); | |
| 246 | __x = __x * __k1 + __loadword<_Size>(__s); | |
| 247 | ||
| 248 | // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. | |
| 249 | __len = (__len - 1) & ~static_cast<_Size>(63); | |
| 250 | do { | |
| 251 | __x = __rotate(__x + __y + __v.first + __loadword<_Size>(__s + 8), 37) * __k1; | |
| 252 | __y = __rotate(__y + __v.second + __loadword<_Size>(__s + 48), 42) * __k1; | |
| 253 | __x ^= __w.second; | |
| 254 | __y += __v.first + __loadword<_Size>(__s + 40); | |
| 255 | __z = __rotate(__z + __w.first, 33) * __k1; | |
| 256 | __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); | |
| 257 | __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, | |
| 258 | __y + __loadword<_Size>(__s + 16)); | |
| 259 | _VSTD::swap(__z, __x); | |
| 260 | __s += 64; | |
| 261 | __len -= 64; | |
| 262 | } while (__len != 0); | |
| 263 | return __hash_len_16( | |
| 264 | __hash_len_16(__v.first, __w.first) + __shift_mix(__y) * __k1 + __z, | |
| 265 | __hash_len_16(__v.second, __w.second) + __x); | |
| 266 | } | |
| 267 | ||
| 268 | template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)> | |
| 269 | struct __scalar_hash; | |
| 270 | ||
| 271 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 272 | template <class _Tp> | |
| 273 | struct __scalar_hash<_Tp, 0> | |
| 274 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 275 | : public unary_function<_Tp, size_t> | |
| 276 | #endif | |
| 277 | { | |
| 278 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 279 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 280 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 281 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 282 | #endif | |
| 283 | _LIBCPP_INLINE_VISIBILITY | |
| 284 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 285 | { | |
| 286 | union | |
| 287 | { | |
| 288 | _Tp __t; | |
| 289 | size_t __a; | |
| 290 | } __u; | |
| 291 | __u.__a = 0; | |
| 292 | __u.__t = __v; | |
| 293 | return __u.__a; | |
| 294 | } | |
| 295 | }; | |
| 296 | ||
| 297 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 298 | template <class _Tp> | |
| 299 | struct __scalar_hash<_Tp, 1> | |
| 300 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 301 | : public unary_function<_Tp, size_t> | |
| 302 | #endif | |
| 303 | { | |
| 304 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 305 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 306 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 307 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 308 | #endif | |
| 309 | _LIBCPP_INLINE_VISIBILITY | |
| 310 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 311 | { | |
| 312 | union | |
| 313 | { | |
| 314 | _Tp __t; | |
| 315 | size_t __a; | |
| 316 | } __u; | |
| 317 | __u.__t = __v; | |
| 318 | return __u.__a; | |
| 319 | } | |
| 320 | }; | |
| 321 | ||
| 322 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 323 | template <class _Tp> | |
| 324 | struct __scalar_hash<_Tp, 2> | |
| 325 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 326 | : public unary_function<_Tp, size_t> | |
| 327 | #endif | |
| 328 | { | |
| 329 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 330 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 331 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 332 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 333 | #endif | |
| 334 | _LIBCPP_INLINE_VISIBILITY | |
| 335 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 336 | { | |
| 337 | union | |
| 338 | { | |
| 339 | _Tp __t; | |
| 340 | struct | |
| 341 | { | |
| 342 | size_t __a; | |
| 343 | size_t __b; | |
| 344 | } __s; | |
| 345 | } __u; | |
| 346 | __u.__t = __v; | |
| 347 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 348 | } | |
| 349 | }; | |
| 350 | ||
| 351 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 352 | template <class _Tp> | |
| 353 | struct __scalar_hash<_Tp, 3> | |
| 354 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 355 | : public unary_function<_Tp, size_t> | |
| 356 | #endif | |
| 357 | { | |
| 358 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 359 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 360 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 361 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 362 | #endif | |
| 363 | _LIBCPP_INLINE_VISIBILITY | |
| 364 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 365 | { | |
| 366 | union | |
| 367 | { | |
| 368 | _Tp __t; | |
| 369 | struct | |
| 370 | { | |
| 371 | size_t __a; | |
| 372 | size_t __b; | |
| 373 | size_t __c; | |
| 374 | } __s; | |
| 375 | } __u; | |
| 376 | __u.__t = __v; | |
| 377 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 378 | } | |
| 379 | }; | |
| 380 | ||
| 381 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 382 | template <class _Tp> | |
| 383 | struct __scalar_hash<_Tp, 4> | |
| 384 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 385 | : public unary_function<_Tp, size_t> | |
| 386 | #endif | |
| 387 | { | |
| 388 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 389 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 390 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 391 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 392 | #endif | |
| 393 | _LIBCPP_INLINE_VISIBILITY | |
| 394 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 395 | { | |
| 396 | union | |
| 397 | { | |
| 398 | _Tp __t; | |
| 399 | struct | |
| 400 | { | |
| 401 | size_t __a; | |
| 402 | size_t __b; | |
| 403 | size_t __c; | |
| 404 | size_t __d; | |
| 405 | } __s; | |
| 406 | } __u; | |
| 407 | __u.__t = __v; | |
| 408 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 409 | } | |
| 410 | }; | |
| 411 | ||
| 412 | struct _PairT { | |
| 413 | size_t first; | |
| 414 | size_t second; | |
| 415 | }; | |
| 416 | ||
| 417 | _LIBCPP_INLINE_VISIBILITY | |
| 418 | inline size_t __hash_combine(size_t __lhs, size_t __rhs) _NOEXCEPT { | |
| 419 | typedef __scalar_hash<_PairT> _HashT; | |
| 420 | const _PairT __p = {__lhs, __rhs}; | |
| 421 | return _HashT()(__p); | |
| 422 | } | |
| 423 | ||
| 424 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 425 | template<class _Tp> | |
| 426 | struct _LIBCPP_TEMPLATE_VIS hash<_Tp*> | |
| 427 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 428 | : public unary_function<_Tp*, size_t> | |
| 429 | #endif | |
| 430 | { | |
| 431 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 432 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 433 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 434 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp* argument_type; | |
| 435 | #endif | |
| 436 | _LIBCPP_INLINE_VISIBILITY | |
| 437 | size_t operator()(_Tp* __v) const _NOEXCEPT | |
| 438 | { | |
| 439 | union | |
| 440 | { | |
| 441 | _Tp* __t; | |
| 442 | size_t __a; | |
| 443 | } __u; | |
| 444 | __u.__t = __v; | |
| 445 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 446 | } | |
| 447 | }; | |
| 448 | ||
| 449 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 450 | template <> | |
| 451 | struct _LIBCPP_TEMPLATE_VIS hash<bool> | |
| 452 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 453 | : public unary_function<bool, size_t> | |
| 454 | #endif | |
| 455 | { | |
| 456 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 457 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 458 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 459 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool argument_type; | |
| 460 | #endif | |
| 461 | _LIBCPP_INLINE_VISIBILITY | |
| 462 | size_t operator()(bool __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 463 | }; | |
| 464 | ||
| 465 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 466 | template <> | |
| 467 | struct _LIBCPP_TEMPLATE_VIS hash<char> | |
| 468 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 469 | : public unary_function<char, size_t> | |
| 470 | #endif | |
| 471 | { | |
| 472 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 473 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 474 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 475 | _LIBCPP_DEPRECATED_IN_CXX17 typedef char argument_type; | |
| 476 | #endif | |
| 477 | _LIBCPP_INLINE_VISIBILITY | |
| 478 | size_t operator()(char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 479 | }; | |
| 480 | ||
| 481 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 482 | template <> | |
| 483 | struct _LIBCPP_TEMPLATE_VIS hash<signed char> | |
| 484 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 485 | : public unary_function<signed char, size_t> | |
| 486 | #endif | |
| 487 | { | |
| 488 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 489 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 490 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 491 | _LIBCPP_DEPRECATED_IN_CXX17 typedef signed char argument_type; | |
| 492 | #endif | |
| 493 | _LIBCPP_INLINE_VISIBILITY | |
| 494 | size_t operator()(signed char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 495 | }; | |
| 496 | ||
| 497 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 498 | template <> | |
| 499 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned char> | |
| 500 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 501 | : public unary_function<unsigned char, size_t> | |
| 502 | #endif | |
| 503 | { | |
| 504 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 505 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 506 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 507 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unsigned char argument_type; | |
| 508 | #endif | |
| 509 | _LIBCPP_INLINE_VISIBILITY | |
| 510 | size_t operator()(unsigned char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 511 | }; | |
| 512 | ||
| 513 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 514 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 515 | template <> | |
| 516 | struct _LIBCPP_TEMPLATE_VIS hash<char8_t> | |
| 517 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 518 | : public unary_function<char8_t, size_t> | |
| 519 | #endif | |
| 520 | { | |
| 521 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 522 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 523 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 524 | _LIBCPP_DEPRECATED_IN_CXX17 typedef char8_t argument_type; | |
| 525 | #endif | |
| 526 | _LIBCPP_INLINE_VISIBILITY | |
| 527 | size_t operator()(char8_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 528 | }; | |
| 529 | #endif // !_LIBCPP_HAS_NO_CHAR8_T | |
| 530 | ||
| 531 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 532 | ||
| 533 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 534 | template <> | |
| 535 | struct _LIBCPP_TEMPLATE_VIS hash<char16_t> | |
| 536 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 537 | : public unary_function<char16_t, size_t> | |
| 538 | #endif | |
| 539 | { | |
| 540 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 541 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 542 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 543 | _LIBCPP_DEPRECATED_IN_CXX17 typedef char16_t argument_type; | |
| 544 | #endif | |
| 545 | _LIBCPP_INLINE_VISIBILITY | |
| 546 | size_t operator()(char16_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 547 | }; | |
| 548 | ||
| 549 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 550 | template <> | |
| 551 | struct _LIBCPP_TEMPLATE_VIS hash<char32_t> | |
| 552 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 553 | : public unary_function<char32_t, size_t> | |
| 554 | #endif | |
| 555 | { | |
| 556 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 557 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 558 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 559 | _LIBCPP_DEPRECATED_IN_CXX17 typedef char32_t argument_type; | |
| 560 | #endif | |
| 561 | _LIBCPP_INLINE_VISIBILITY | |
| 562 | size_t operator()(char32_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 563 | }; | |
| 564 | ||
| 565 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 566 | ||
| 567 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 568 | template <> | |
| 569 | struct _LIBCPP_TEMPLATE_VIS hash<wchar_t> | |
| 570 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 571 | : public unary_function<wchar_t, size_t> | |
| 572 | #endif | |
| 573 | { | |
| 574 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 575 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 576 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 577 | _LIBCPP_DEPRECATED_IN_CXX17 typedef wchar_t argument_type; | |
| 578 | #endif | |
| 579 | _LIBCPP_INLINE_VISIBILITY | |
| 580 | size_t operator()(wchar_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 581 | }; | |
| 582 | ||
| 583 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 584 | template <> | |
| 585 | struct _LIBCPP_TEMPLATE_VIS hash<short> | |
| 586 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 587 | : public unary_function<short, size_t> | |
| 588 | #endif | |
| 589 | { | |
| 590 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 591 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 592 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 593 | _LIBCPP_DEPRECATED_IN_CXX17 typedef short argument_type; | |
| 594 | #endif | |
| 595 | _LIBCPP_INLINE_VISIBILITY | |
| 596 | size_t operator()(short __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 597 | }; | |
| 598 | ||
| 599 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 600 | template <> | |
| 601 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned short> | |
| 602 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 603 | : public unary_function<unsigned short, size_t> | |
| 604 | #endif | |
| 605 | { | |
| 606 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 607 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 608 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 609 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unsigned short argument_type; | |
| 610 | #endif | |
| 611 | _LIBCPP_INLINE_VISIBILITY | |
| 612 | size_t operator()(unsigned short __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 613 | }; | |
| 614 | ||
| 615 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 616 | template <> | |
| 617 | struct _LIBCPP_TEMPLATE_VIS hash<int> | |
| 618 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 619 | : public unary_function<int, size_t> | |
| 620 | #endif | |
| 621 | { | |
| 622 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 623 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 624 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 625 | _LIBCPP_DEPRECATED_IN_CXX17 typedef int argument_type; | |
| 626 | #endif | |
| 627 | _LIBCPP_INLINE_VISIBILITY | |
| 628 | size_t operator()(int __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 629 | }; | |
| 630 | ||
| 631 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 632 | template <> | |
| 633 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned int> | |
| 634 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 635 | : public unary_function<unsigned int, size_t> | |
| 636 | #endif | |
| 637 | { | |
| 638 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 639 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 640 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 641 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unsigned int argument_type; | |
| 642 | #endif | |
| 643 | _LIBCPP_INLINE_VISIBILITY | |
| 644 | size_t operator()(unsigned int __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 645 | }; | |
| 646 | ||
| 647 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 648 | template <> | |
| 649 | struct _LIBCPP_TEMPLATE_VIS hash<long> | |
| 650 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 651 | : public unary_function<long, size_t> | |
| 652 | #endif | |
| 653 | { | |
| 654 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 655 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 656 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 657 | _LIBCPP_DEPRECATED_IN_CXX17 typedef long argument_type; | |
| 658 | #endif | |
| 659 | _LIBCPP_INLINE_VISIBILITY | |
| 660 | size_t operator()(long __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 661 | }; | |
| 662 | ||
| 663 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 664 | template <> | |
| 665 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned long> | |
| 666 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 667 | : public unary_function<unsigned long, size_t> | |
| 668 | #endif | |
| 669 | { | |
| 670 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 671 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 672 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 673 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unsigned long argument_type; | |
| 674 | #endif | |
| 675 | _LIBCPP_INLINE_VISIBILITY | |
| 676 | size_t operator()(unsigned long __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 677 | }; | |
| 678 | ||
| 679 | template <> | |
| 680 | struct _LIBCPP_TEMPLATE_VIS hash<long long> | |
| 681 | : public __scalar_hash<long long> | |
| 682 | { | |
| 683 | }; | |
| 684 | ||
| 685 | template <> | |
| 686 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned long long> | |
| 687 | : public __scalar_hash<unsigned long long> | |
| 688 | { | |
| 689 | }; | |
| 690 | ||
| 691 | #ifndef _LIBCPP_HAS_NO_INT128 | |
| 692 | ||
| 693 | template <> | |
| 694 | struct _LIBCPP_TEMPLATE_VIS hash<__int128_t> | |
| 695 | : public __scalar_hash<__int128_t> | |
| 696 | { | |
| 697 | }; | |
| 698 | ||
| 699 | template <> | |
| 700 | struct _LIBCPP_TEMPLATE_VIS hash<__uint128_t> | |
| 701 | : public __scalar_hash<__uint128_t> | |
| 702 | { | |
| 703 | }; | |
| 704 | ||
| 705 | #endif | |
| 706 | ||
| 707 | template <> | |
| 708 | struct _LIBCPP_TEMPLATE_VIS hash<float> | |
| 709 | : public __scalar_hash<float> | |
| 710 | { | |
| 711 | _LIBCPP_INLINE_VISIBILITY | |
| 712 | size_t operator()(float __v) const _NOEXCEPT | |
| 713 | { | |
| 714 | // -0.0 and 0.0 should return same hash | |
| 715 | if (__v == 0.0f) | |
| 716 | return 0; | |
| 717 | return __scalar_hash<float>::operator()(__v); | |
| 718 | } | |
| 719 | }; | |
| 720 | ||
| 721 | template <> | |
| 722 | struct _LIBCPP_TEMPLATE_VIS hash<double> | |
| 723 | : public __scalar_hash<double> | |
| 724 | { | |
| 725 | _LIBCPP_INLINE_VISIBILITY | |
| 726 | size_t operator()(double __v) const _NOEXCEPT | |
| 727 | { | |
| 728 | // -0.0 and 0.0 should return same hash | |
| 729 | if (__v == 0.0) | |
| 730 | return 0; | |
| 731 | return __scalar_hash<double>::operator()(__v); | |
| 732 | } | |
| 733 | }; | |
| 734 | ||
| 735 | template <> | |
| 736 | struct _LIBCPP_TEMPLATE_VIS hash<long double> | |
| 737 | : public __scalar_hash<long double> | |
| 738 | { | |
| 739 | _LIBCPP_INLINE_VISIBILITY | |
| 740 | size_t operator()(long double __v) const _NOEXCEPT | |
| 741 | { | |
| 742 | // -0.0 and 0.0 should return same hash | |
| 743 | if (__v == 0.0L) | |
| 744 | return 0; | |
| 745 | #if defined(__i386__) || (defined(__x86_64__) && defined(__ILP32__)) | |
| 746 | // Zero out padding bits | |
| 747 | union | |
| 748 | { | |
| 749 | long double __t; | |
| 750 | struct | |
| 751 | { | |
| 752 | size_t __a; | |
| 753 | size_t __b; | |
| 754 | size_t __c; | |
| 755 | size_t __d; | |
| 756 | } __s; | |
| 757 | } __u; | |
| 758 | __u.__s.__a = 0; | |
| 759 | __u.__s.__b = 0; | |
| 760 | __u.__s.__c = 0; | |
| 761 | __u.__s.__d = 0; | |
| 762 | __u.__t = __v; | |
| 763 | return __u.__s.__a ^ __u.__s.__b ^ __u.__s.__c ^ __u.__s.__d; | |
| 764 | #elif defined(__x86_64__) | |
| 765 | // Zero out padding bits | |
| 766 | union | |
| 767 | { | |
| 768 | long double __t; | |
| 769 | struct | |
| 770 | { | |
| 771 | size_t __a; | |
| 772 | size_t __b; | |
| 773 | } __s; | |
| 774 | } __u; | |
| 775 | __u.__s.__a = 0; | |
| 776 | __u.__s.__b = 0; | |
| 777 | __u.__t = __v; | |
| 778 | return __u.__s.__a ^ __u.__s.__b; | |
| 779 | #else | |
| 780 | return __scalar_hash<long double>::operator()(__v); | |
| 781 | #endif | |
| 782 | } | |
| 783 | }; | |
| 784 | ||
| 785 | #if _LIBCPP_STD_VER > 11 | |
| 786 | ||
| 787 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 788 | template <class _Tp, bool = is_enum<_Tp>::value> | |
| 789 | struct _LIBCPP_TEMPLATE_VIS __enum_hash | |
| 790 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 791 | : public unary_function<_Tp, size_t> | |
| 792 | #endif | |
| 793 | { | |
| 794 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 795 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 796 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 797 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 798 | #endif | |
| 799 | _LIBCPP_INLINE_VISIBILITY | |
| 800 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 801 | { | |
| 802 | typedef typename underlying_type<_Tp>::type type; | |
| 803 | return hash<type>{}(static_cast<type>(__v)); | |
| 804 | } | |
| 805 | }; | |
| 806 | template <class _Tp> | |
| 807 | struct _LIBCPP_TEMPLATE_VIS __enum_hash<_Tp, false> { | |
| 808 | __enum_hash() = delete; | |
| 809 | __enum_hash(__enum_hash const&) = delete; | |
| 810 | __enum_hash& operator=(__enum_hash const&) = delete; | |
| 811 | }; | |
| 812 | ||
| 813 | template <class _Tp> | |
| 814 | struct _LIBCPP_TEMPLATE_VIS hash : public __enum_hash<_Tp> | |
| 815 | { | |
| 816 | }; | |
| 817 | #endif | |
| 818 | ||
| 819 | #if _LIBCPP_STD_VER > 14 | |
| 820 | ||
| 821 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 822 | template <> | |
| 823 | struct _LIBCPP_TEMPLATE_VIS hash<nullptr_t> | |
| 824 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 825 | : public unary_function<nullptr_t, size_t> | |
| 826 | #endif | |
| 827 | { | |
| 828 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 829 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 830 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 831 | _LIBCPP_DEPRECATED_IN_CXX17 typedef nullptr_t argument_type; | |
| 832 | #endif | |
| 833 | _LIBCPP_INLINE_VISIBILITY | |
| 834 | size_t operator()(nullptr_t) const _NOEXCEPT { | |
| 835 | return 662607004ull; | |
| 836 | } | |
| 837 | }; | |
| 838 | #endif | |
| 839 | ||
| 840 | #ifndef _LIBCPP_CXX03_LANG | |
| 841 | template <class _Key, class _Hash> | |
| 842 | using __check_hash_requirements _LIBCPP_NODEBUG_TYPE = integral_constant<bool, | |
| 843 | is_copy_constructible<_Hash>::value && | |
| 844 | is_move_constructible<_Hash>::value && | |
| 845 | __invokable_r<size_t, _Hash, _Key const&>::value | |
| 846 | >; | |
| 847 | ||
| 848 | template <class _Key, class _Hash = hash<_Key> > | |
| 849 | using __has_enabled_hash _LIBCPP_NODEBUG_TYPE = integral_constant<bool, | |
| 850 | __check_hash_requirements<_Key, _Hash>::value && | |
| 851 | is_default_constructible<_Hash>::value | |
| 852 | >; | |
| 853 | ||
| 854 | #if _LIBCPP_STD_VER > 14 | |
| 855 | template <class _Type, class> | |
| 856 | using __enable_hash_helper_imp _LIBCPP_NODEBUG_TYPE = _Type; | |
| 857 | ||
| 858 | template <class _Type, class ..._Keys> | |
| 859 | using __enable_hash_helper _LIBCPP_NODEBUG_TYPE = __enable_hash_helper_imp<_Type, | |
| 860 | typename enable_if<__all<__has_enabled_hash<_Keys>::value...>::value>::type | |
| 861 | >; | |
| 862 | #else | |
| 863 | template <class _Type, class ...> | |
| 864 | using __enable_hash_helper _LIBCPP_NODEBUG_TYPE = _Type; | |
| 865 | #endif | |
| 866 | ||
| 867 | #endif // !_LIBCPP_CXX03_LANG | |
| 868 | ||
| 869 | _LIBCPP_END_NAMESPACE_STD | |
| 870 | ||
| 871 | _LIBCPP_POP_MACROS | |
| 872 | ||
| 873 | #endif // _LIBCPP___FUNCTIONAL_HASH_H |
lib/libcxx/include/__functional/identity.h created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_IDENTITY_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_IDENTITY_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <utility> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER > 17 | |
| 23 | ||
| 24 | struct identity { | |
| 25 | template<class _Tp> | |
| 26 | _LIBCPP_NODISCARD_EXT constexpr _Tp&& operator()(_Tp&& __t) const noexcept | |
| 27 | { | |
| 28 | return _VSTD::forward<_Tp>(__t); | |
| 29 | } | |
| 30 | ||
| 31 | using is_transparent = void; | |
| 32 | }; | |
| 33 | #endif // _LIBCPP_STD_VER > 17 | |
| 34 | ||
| 35 | _LIBCPP_END_NAMESPACE_STD | |
| 36 | ||
| 37 | #endif // _LIBCPP___FUNCTIONAL_IDENTITY_H |
lib/libcxx/include/__functional/invoke.h created+100| ... | ... | @@ -0,0 +1,100 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_INVOKE_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_INVOKE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/weak_result_type.h> | |
| 15 | #include <__utility/forward.h> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _Ret, bool = is_void<_Ret>::value> | |
| 25 | struct __invoke_void_return_wrapper | |
| 26 | { | |
| 27 | #ifndef _LIBCPP_CXX03_LANG | |
| 28 | template <class ..._Args> | |
| 29 | static _Ret __call(_Args&&... __args) { | |
| 30 | return _VSTD::__invoke(_VSTD::forward<_Args>(__args)...); | |
| 31 | } | |
| 32 | #else | |
| 33 | template <class _Fn> | |
| 34 | static _Ret __call(_Fn __f) { | |
| 35 | return _VSTD::__invoke(__f); | |
| 36 | } | |
| 37 | ||
| 38 | template <class _Fn, class _A0> | |
| 39 | static _Ret __call(_Fn __f, _A0& __a0) { | |
| 40 | return _VSTD::__invoke(__f, __a0); | |
| 41 | } | |
| 42 | ||
| 43 | template <class _Fn, class _A0, class _A1> | |
| 44 | static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) { | |
| 45 | return _VSTD::__invoke(__f, __a0, __a1); | |
| 46 | } | |
| 47 | ||
| 48 | template <class _Fn, class _A0, class _A1, class _A2> | |
| 49 | static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){ | |
| 50 | return _VSTD::__invoke(__f, __a0, __a1, __a2); | |
| 51 | } | |
| 52 | #endif | |
| 53 | }; | |
| 54 | ||
| 55 | template <class _Ret> | |
| 56 | struct __invoke_void_return_wrapper<_Ret, true> | |
| 57 | { | |
| 58 | #ifndef _LIBCPP_CXX03_LANG | |
| 59 | template <class ..._Args> | |
| 60 | static void __call(_Args&&... __args) { | |
| 61 | _VSTD::__invoke(_VSTD::forward<_Args>(__args)...); | |
| 62 | } | |
| 63 | #else | |
| 64 | template <class _Fn> | |
| 65 | static void __call(_Fn __f) { | |
| 66 | _VSTD::__invoke(__f); | |
| 67 | } | |
| 68 | ||
| 69 | template <class _Fn, class _A0> | |
| 70 | static void __call(_Fn __f, _A0& __a0) { | |
| 71 | _VSTD::__invoke(__f, __a0); | |
| 72 | } | |
| 73 | ||
| 74 | template <class _Fn, class _A0, class _A1> | |
| 75 | static void __call(_Fn __f, _A0& __a0, _A1& __a1) { | |
| 76 | _VSTD::__invoke(__f, __a0, __a1); | |
| 77 | } | |
| 78 | ||
| 79 | template <class _Fn, class _A0, class _A1, class _A2> | |
| 80 | static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) { | |
| 81 | _VSTD::__invoke(__f, __a0, __a1, __a2); | |
| 82 | } | |
| 83 | #endif | |
| 84 | }; | |
| 85 | ||
| 86 | #if _LIBCPP_STD_VER > 14 | |
| 87 | ||
| 88 | template <class _Fn, class ..._Args> | |
| 89 | _LIBCPP_CONSTEXPR_AFTER_CXX17 invoke_result_t<_Fn, _Args...> | |
| 90 | invoke(_Fn&& __f, _Args&&... __args) | |
| 91 | noexcept(is_nothrow_invocable_v<_Fn, _Args...>) | |
| 92 | { | |
| 93 | return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); | |
| 94 | } | |
| 95 | ||
| 96 | #endif // _LIBCPP_STD_VER > 14 | |
| 97 | ||
| 98 | _LIBCPP_END_NAMESPACE_STD | |
| 99 | ||
| 100 | #endif // _LIBCPP___FUNCTIONAL_INVOKE_H |
lib/libcxx/include/__functional/is_transparent.h created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_IS_TRANSPARENT | |
| 11 | #define _LIBCPP___FUNCTIONAL_IS_TRANSPARENT | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER > 11 | |
| 23 | ||
| 24 | template <class _Tp, class, class = void> | |
| 25 | struct __is_transparent : false_type {}; | |
| 26 | ||
| 27 | template <class _Tp, class _Up> | |
| 28 | struct __is_transparent<_Tp, _Up, | |
| 29 | typename __void_t<typename _Tp::is_transparent>::type> | |
| 30 | : true_type {}; | |
| 31 | ||
| 32 | #endif | |
| 33 | ||
| 34 | _LIBCPP_END_NAMESPACE_STD | |
| 35 | ||
| 36 | #endif // _LIBCPP___FUNCTIONAL_IS_TRANSPARENT |
lib/libcxx/include/__functional/mem_fn.h created+161| ... | ... | @@ -0,0 +1,161 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_MEM_FN_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_MEM_FN_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/weak_result_type.h> | |
| 15 | #include <__functional/binary_function.h> | |
| 16 | #include <__functional/invoke.h> | |
| 17 | #include <utility> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _Tp> | |
| 26 | class __mem_fn | |
| 27 | #if _LIBCPP_STD_VER <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 28 | : public __weak_result_type<_Tp> | |
| 29 | #endif | |
| 30 | { | |
| 31 | public: | |
| 32 | // types | |
| 33 | typedef _Tp type; | |
| 34 | private: | |
| 35 | type __f_; | |
| 36 | ||
| 37 | public: | |
| 38 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 39 | __mem_fn(type __f) _NOEXCEPT : __f_(__f) {} | |
| 40 | ||
| 41 | #ifndef _LIBCPP_CXX03_LANG | |
| 42 | // invoke | |
| 43 | template <class... _ArgTypes> | |
| 44 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 45 | typename __invoke_return<type, _ArgTypes...>::type | |
| 46 | operator() (_ArgTypes&&... __args) const { | |
| 47 | return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...); | |
| 48 | } | |
| 49 | #else | |
| 50 | ||
| 51 | template <class _A0> | |
| 52 | _LIBCPP_INLINE_VISIBILITY | |
| 53 | typename __invoke_return0<type, _A0>::type | |
| 54 | operator() (_A0& __a0) const { | |
| 55 | return _VSTD::__invoke(__f_, __a0); | |
| 56 | } | |
| 57 | ||
| 58 | template <class _A0> | |
| 59 | _LIBCPP_INLINE_VISIBILITY | |
| 60 | typename __invoke_return0<type, _A0 const>::type | |
| 61 | operator() (_A0 const& __a0) const { | |
| 62 | return _VSTD::__invoke(__f_, __a0); | |
| 63 | } | |
| 64 | ||
| 65 | template <class _A0, class _A1> | |
| 66 | _LIBCPP_INLINE_VISIBILITY | |
| 67 | typename __invoke_return1<type, _A0, _A1>::type | |
| 68 | operator() (_A0& __a0, _A1& __a1) const { | |
| 69 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 70 | } | |
| 71 | ||
| 72 | template <class _A0, class _A1> | |
| 73 | _LIBCPP_INLINE_VISIBILITY | |
| 74 | typename __invoke_return1<type, _A0 const, _A1>::type | |
| 75 | operator() (_A0 const& __a0, _A1& __a1) const { | |
| 76 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 77 | } | |
| 78 | ||
| 79 | template <class _A0, class _A1> | |
| 80 | _LIBCPP_INLINE_VISIBILITY | |
| 81 | typename __invoke_return1<type, _A0, _A1 const>::type | |
| 82 | operator() (_A0& __a0, _A1 const& __a1) const { | |
| 83 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 84 | } | |
| 85 | ||
| 86 | template <class _A0, class _A1> | |
| 87 | _LIBCPP_INLINE_VISIBILITY | |
| 88 | typename __invoke_return1<type, _A0 const, _A1 const>::type | |
| 89 | operator() (_A0 const& __a0, _A1 const& __a1) const { | |
| 90 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 91 | } | |
| 92 | ||
| 93 | template <class _A0, class _A1, class _A2> | |
| 94 | _LIBCPP_INLINE_VISIBILITY | |
| 95 | typename __invoke_return2<type, _A0, _A1, _A2>::type | |
| 96 | operator() (_A0& __a0, _A1& __a1, _A2& __a2) const { | |
| 97 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 98 | } | |
| 99 | ||
| 100 | template <class _A0, class _A1, class _A2> | |
| 101 | _LIBCPP_INLINE_VISIBILITY | |
| 102 | typename __invoke_return2<type, _A0 const, _A1, _A2>::type | |
| 103 | operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const { | |
| 104 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 105 | } | |
| 106 | ||
| 107 | template <class _A0, class _A1, class _A2> | |
| 108 | _LIBCPP_INLINE_VISIBILITY | |
| 109 | typename __invoke_return2<type, _A0, _A1 const, _A2>::type | |
| 110 | operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 111 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 112 | } | |
| 113 | ||
| 114 | template <class _A0, class _A1, class _A2> | |
| 115 | _LIBCPP_INLINE_VISIBILITY | |
| 116 | typename __invoke_return2<type, _A0, _A1, _A2 const>::type | |
| 117 | operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 118 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 119 | } | |
| 120 | ||
| 121 | template <class _A0, class _A1, class _A2> | |
| 122 | _LIBCPP_INLINE_VISIBILITY | |
| 123 | typename __invoke_return2<type, _A0 const, _A1 const, _A2>::type | |
| 124 | operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 125 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 126 | } | |
| 127 | ||
| 128 | template <class _A0, class _A1, class _A2> | |
| 129 | _LIBCPP_INLINE_VISIBILITY | |
| 130 | typename __invoke_return2<type, _A0 const, _A1, _A2 const>::type | |
| 131 | operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 132 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 133 | } | |
| 134 | ||
| 135 | template <class _A0, class _A1, class _A2> | |
| 136 | _LIBCPP_INLINE_VISIBILITY | |
| 137 | typename __invoke_return2<type, _A0, _A1 const, _A2 const>::type | |
| 138 | operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 139 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 140 | } | |
| 141 | ||
| 142 | template <class _A0, class _A1, class _A2> | |
| 143 | _LIBCPP_INLINE_VISIBILITY | |
| 144 | typename __invoke_return2<type, _A0 const, _A1 const, _A2 const>::type | |
| 145 | operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 146 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 147 | } | |
| 148 | #endif | |
| 149 | }; | |
| 150 | ||
| 151 | template<class _Rp, class _Tp> | |
| 152 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 153 | __mem_fn<_Rp _Tp::*> | |
| 154 | mem_fn(_Rp _Tp::* __pm) _NOEXCEPT | |
| 155 | { | |
| 156 | return __mem_fn<_Rp _Tp::*>(__pm); | |
| 157 | } | |
| 158 | ||
| 159 | _LIBCPP_END_NAMESPACE_STD | |
| 160 | ||
| 161 | #endif // _LIBCPP___FUNCTIONAL_MEM_FN_H |
lib/libcxx/include/__functional/mem_fun_ref.h created+173| ... | ... | @@ -0,0 +1,173 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_MEM_FUN_REF_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_MEM_FUN_REF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/unary_function.h> | |
| 15 | #include <__functional/binary_function.h> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 24 | ||
| 25 | template<class _Sp, class _Tp> | |
| 26 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_t | |
| 27 | : public unary_function<_Tp*, _Sp> | |
| 28 | { | |
| 29 | _Sp (_Tp::*__p_)(); | |
| 30 | public: | |
| 31 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun_t(_Sp (_Tp::*__p)()) | |
| 32 | : __p_(__p) {} | |
| 33 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp* __p) const | |
| 34 | {return (__p->*__p_)();} | |
| 35 | }; | |
| 36 | ||
| 37 | template<class _Sp, class _Tp, class _Ap> | |
| 38 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_t | |
| 39 | : public binary_function<_Tp*, _Ap, _Sp> | |
| 40 | { | |
| 41 | _Sp (_Tp::*__p_)(_Ap); | |
| 42 | public: | |
| 43 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun1_t(_Sp (_Tp::*__p)(_Ap)) | |
| 44 | : __p_(__p) {} | |
| 45 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp* __p, _Ap __x) const | |
| 46 | {return (__p->*__p_)(__x);} | |
| 47 | }; | |
| 48 | ||
| 49 | template<class _Sp, class _Tp> | |
| 50 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 51 | mem_fun_t<_Sp,_Tp> | |
| 52 | mem_fun(_Sp (_Tp::*__f)()) | |
| 53 | {return mem_fun_t<_Sp,_Tp>(__f);} | |
| 54 | ||
| 55 | template<class _Sp, class _Tp, class _Ap> | |
| 56 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 57 | mem_fun1_t<_Sp,_Tp,_Ap> | |
| 58 | mem_fun(_Sp (_Tp::*__f)(_Ap)) | |
| 59 | {return mem_fun1_t<_Sp,_Tp,_Ap>(__f);} | |
| 60 | ||
| 61 | template<class _Sp, class _Tp> | |
| 62 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_ref_t | |
| 63 | : public unary_function<_Tp, _Sp> | |
| 64 | { | |
| 65 | _Sp (_Tp::*__p_)(); | |
| 66 | public: | |
| 67 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun_ref_t(_Sp (_Tp::*__p)()) | |
| 68 | : __p_(__p) {} | |
| 69 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp& __p) const | |
| 70 | {return (__p.*__p_)();} | |
| 71 | }; | |
| 72 | ||
| 73 | template<class _Sp, class _Tp, class _Ap> | |
| 74 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_ref_t | |
| 75 | : public binary_function<_Tp, _Ap, _Sp> | |
| 76 | { | |
| 77 | _Sp (_Tp::*__p_)(_Ap); | |
| 78 | public: | |
| 79 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun1_ref_t(_Sp (_Tp::*__p)(_Ap)) | |
| 80 | : __p_(__p) {} | |
| 81 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp& __p, _Ap __x) const | |
| 82 | {return (__p.*__p_)(__x);} | |
| 83 | }; | |
| 84 | ||
| 85 | template<class _Sp, class _Tp> | |
| 86 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 87 | mem_fun_ref_t<_Sp,_Tp> | |
| 88 | mem_fun_ref(_Sp (_Tp::*__f)()) | |
| 89 | {return mem_fun_ref_t<_Sp,_Tp>(__f);} | |
| 90 | ||
| 91 | template<class _Sp, class _Tp, class _Ap> | |
| 92 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 93 | mem_fun1_ref_t<_Sp,_Tp,_Ap> | |
| 94 | mem_fun_ref(_Sp (_Tp::*__f)(_Ap)) | |
| 95 | {return mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} | |
| 96 | ||
| 97 | template <class _Sp, class _Tp> | |
| 98 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_t | |
| 99 | : public unary_function<const _Tp*, _Sp> | |
| 100 | { | |
| 101 | _Sp (_Tp::*__p_)() const; | |
| 102 | public: | |
| 103 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun_t(_Sp (_Tp::*__p)() const) | |
| 104 | : __p_(__p) {} | |
| 105 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp* __p) const | |
| 106 | {return (__p->*__p_)();} | |
| 107 | }; | |
| 108 | ||
| 109 | template <class _Sp, class _Tp, class _Ap> | |
| 110 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t | |
| 111 | : public binary_function<const _Tp*, _Ap, _Sp> | |
| 112 | { | |
| 113 | _Sp (_Tp::*__p_)(_Ap) const; | |
| 114 | public: | |
| 115 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun1_t(_Sp (_Tp::*__p)(_Ap) const) | |
| 116 | : __p_(__p) {} | |
| 117 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp* __p, _Ap __x) const | |
| 118 | {return (__p->*__p_)(__x);} | |
| 119 | }; | |
| 120 | ||
| 121 | template <class _Sp, class _Tp> | |
| 122 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 123 | const_mem_fun_t<_Sp,_Tp> | |
| 124 | mem_fun(_Sp (_Tp::*__f)() const) | |
| 125 | {return const_mem_fun_t<_Sp,_Tp>(__f);} | |
| 126 | ||
| 127 | template <class _Sp, class _Tp, class _Ap> | |
| 128 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 129 | const_mem_fun1_t<_Sp,_Tp,_Ap> | |
| 130 | mem_fun(_Sp (_Tp::*__f)(_Ap) const) | |
| 131 | {return const_mem_fun1_t<_Sp,_Tp,_Ap>(__f);} | |
| 132 | ||
| 133 | template <class _Sp, class _Tp> | |
| 134 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_ref_t | |
| 135 | : public unary_function<_Tp, _Sp> | |
| 136 | { | |
| 137 | _Sp (_Tp::*__p_)() const; | |
| 138 | public: | |
| 139 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun_ref_t(_Sp (_Tp::*__p)() const) | |
| 140 | : __p_(__p) {} | |
| 141 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp& __p) const | |
| 142 | {return (__p.*__p_)();} | |
| 143 | }; | |
| 144 | ||
| 145 | template <class _Sp, class _Tp, class _Ap> | |
| 146 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_ref_t | |
| 147 | : public binary_function<_Tp, _Ap, _Sp> | |
| 148 | { | |
| 149 | _Sp (_Tp::*__p_)(_Ap) const; | |
| 150 | public: | |
| 151 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun1_ref_t(_Sp (_Tp::*__p)(_Ap) const) | |
| 152 | : __p_(__p) {} | |
| 153 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp& __p, _Ap __x) const | |
| 154 | {return (__p.*__p_)(__x);} | |
| 155 | }; | |
| 156 | ||
| 157 | template <class _Sp, class _Tp> | |
| 158 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 159 | const_mem_fun_ref_t<_Sp,_Tp> | |
| 160 | mem_fun_ref(_Sp (_Tp::*__f)() const) | |
| 161 | {return const_mem_fun_ref_t<_Sp,_Tp>(__f);} | |
| 162 | ||
| 163 | template <class _Sp, class _Tp, class _Ap> | |
| 164 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 165 | const_mem_fun1_ref_t<_Sp,_Tp,_Ap> | |
| 166 | mem_fun_ref(_Sp (_Tp::*__f)(_Ap) const) | |
| 167 | {return const_mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} | |
| 168 | ||
| 169 | #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 170 | ||
| 171 | _LIBCPP_END_NAMESPACE_STD | |
| 172 | ||
| 173 | #endif // _LIBCPP___FUNCTIONAL_MEM_FUN_REF_H |
lib/libcxx/include/__functional/not_fn.h created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_NOT_FN_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_NOT_FN_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/perfect_forward.h> | |
| 15 | #include <__functional/invoke.h> | |
| 16 | #include <utility> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #if _LIBCPP_STD_VER > 14 | |
| 25 | ||
| 26 | struct __not_fn_op | |
| 27 | { | |
| 28 | template<class... _Args> | |
| 29 | static _LIBCPP_CONSTEXPR_AFTER_CXX17 auto __call(_Args&&... __args) | |
| 30 | noexcept(noexcept(!_VSTD::invoke(_VSTD::forward<_Args>(__args)...))) | |
| 31 | -> decltype( !_VSTD::invoke(_VSTD::forward<_Args>(__args)...)) | |
| 32 | { return !_VSTD::invoke(_VSTD::forward<_Args>(__args)...); } | |
| 33 | }; | |
| 34 | ||
| 35 | template<class _Fn, | |
| 36 | class = _EnableIf<is_constructible_v<decay_t<_Fn>, _Fn> && | |
| 37 | is_move_constructible_v<_Fn>>> | |
| 38 | _LIBCPP_CONSTEXPR_AFTER_CXX17 auto not_fn(_Fn&& __f) | |
| 39 | { | |
| 40 | return __perfect_forward<__not_fn_op, _Fn>(_VSTD::forward<_Fn>(__f)); | |
| 41 | } | |
| 42 | ||
| 43 | #endif // _LIBCPP_STD_VER > 14 | |
| 44 | ||
| 45 | _LIBCPP_END_NAMESPACE_STD | |
| 46 | ||
| 47 | #endif // _LIBCPP___FUNCTIONAL_NOT_FN_H |
lib/libcxx/include/__functional/operations.h created+729| ... | ... | @@ -0,0 +1,729 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_OPERATIONS_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_OPERATIONS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/binary_function.h> | |
| 15 | #include <__functional/unary_function.h> | |
| 16 | #include <__utility/forward.h> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | // Arithmetic operations | |
| 25 | ||
| 26 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 27 | #if _LIBCPP_STD_VER > 11 | |
| 28 | template <class _Tp = void> | |
| 29 | #else | |
| 30 | template <class _Tp> | |
| 31 | #endif | |
| 32 | struct _LIBCPP_TEMPLATE_VIS plus | |
| 33 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 34 | : binary_function<_Tp, _Tp, _Tp> | |
| 35 | #endif | |
| 36 | { | |
| 37 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 38 | typedef _Tp __result_type; // used by valarray | |
| 39 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 40 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 41 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 42 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 43 | #endif | |
| 44 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 45 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 46 | {return __x + __y;} | |
| 47 | }; | |
| 48 | ||
| 49 | #if _LIBCPP_STD_VER > 11 | |
| 50 | template <> | |
| 51 | struct _LIBCPP_TEMPLATE_VIS plus<void> | |
| 52 | { | |
| 53 | template <class _T1, class _T2> | |
| 54 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 55 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 56 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u))) | |
| 57 | -> decltype (_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u)) | |
| 58 | { return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); } | |
| 59 | typedef void is_transparent; | |
| 60 | }; | |
| 61 | #endif | |
| 62 | ||
| 63 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 64 | #if _LIBCPP_STD_VER > 11 | |
| 65 | template <class _Tp = void> | |
| 66 | #else | |
| 67 | template <class _Tp> | |
| 68 | #endif | |
| 69 | struct _LIBCPP_TEMPLATE_VIS minus | |
| 70 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 71 | : binary_function<_Tp, _Tp, _Tp> | |
| 72 | #endif | |
| 73 | { | |
| 74 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 75 | typedef _Tp __result_type; // used by valarray | |
| 76 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 77 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 78 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 79 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 80 | #endif | |
| 81 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 82 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 83 | {return __x - __y;} | |
| 84 | }; | |
| 85 | ||
| 86 | #if _LIBCPP_STD_VER > 11 | |
| 87 | template <> | |
| 88 | struct _LIBCPP_TEMPLATE_VIS minus<void> | |
| 89 | { | |
| 90 | template <class _T1, class _T2> | |
| 91 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 92 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 93 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u))) | |
| 94 | -> decltype (_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u)) | |
| 95 | { return _VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u); } | |
| 96 | typedef void is_transparent; | |
| 97 | }; | |
| 98 | #endif | |
| 99 | ||
| 100 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 101 | #if _LIBCPP_STD_VER > 11 | |
| 102 | template <class _Tp = void> | |
| 103 | #else | |
| 104 | template <class _Tp> | |
| 105 | #endif | |
| 106 | struct _LIBCPP_TEMPLATE_VIS multiplies | |
| 107 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 108 | : binary_function<_Tp, _Tp, _Tp> | |
| 109 | #endif | |
| 110 | { | |
| 111 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 112 | typedef _Tp __result_type; // used by valarray | |
| 113 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 114 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 115 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 116 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 117 | #endif | |
| 118 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 119 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 120 | {return __x * __y;} | |
| 121 | }; | |
| 122 | ||
| 123 | #if _LIBCPP_STD_VER > 11 | |
| 124 | template <> | |
| 125 | struct _LIBCPP_TEMPLATE_VIS multiplies<void> | |
| 126 | { | |
| 127 | template <class _T1, class _T2> | |
| 128 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 129 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 130 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u))) | |
| 131 | -> decltype (_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u)) | |
| 132 | { return _VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u); } | |
| 133 | typedef void is_transparent; | |
| 134 | }; | |
| 135 | #endif | |
| 136 | ||
| 137 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 138 | #if _LIBCPP_STD_VER > 11 | |
| 139 | template <class _Tp = void> | |
| 140 | #else | |
| 141 | template <class _Tp> | |
| 142 | #endif | |
| 143 | struct _LIBCPP_TEMPLATE_VIS divides | |
| 144 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 145 | : binary_function<_Tp, _Tp, _Tp> | |
| 146 | #endif | |
| 147 | { | |
| 148 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 149 | typedef _Tp __result_type; // used by valarray | |
| 150 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 151 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 152 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 153 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 154 | #endif | |
| 155 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 156 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 157 | {return __x / __y;} | |
| 158 | }; | |
| 159 | ||
| 160 | #if _LIBCPP_STD_VER > 11 | |
| 161 | template <> | |
| 162 | struct _LIBCPP_TEMPLATE_VIS divides<void> | |
| 163 | { | |
| 164 | template <class _T1, class _T2> | |
| 165 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 166 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 167 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u))) | |
| 168 | -> decltype (_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u)) | |
| 169 | { return _VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u); } | |
| 170 | typedef void is_transparent; | |
| 171 | }; | |
| 172 | #endif | |
| 173 | ||
| 174 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 175 | #if _LIBCPP_STD_VER > 11 | |
| 176 | template <class _Tp = void> | |
| 177 | #else | |
| 178 | template <class _Tp> | |
| 179 | #endif | |
| 180 | struct _LIBCPP_TEMPLATE_VIS modulus | |
| 181 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 182 | : binary_function<_Tp, _Tp, _Tp> | |
| 183 | #endif | |
| 184 | { | |
| 185 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 186 | typedef _Tp __result_type; // used by valarray | |
| 187 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 188 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 189 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 190 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 191 | #endif | |
| 192 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 193 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 194 | {return __x % __y;} | |
| 195 | }; | |
| 196 | ||
| 197 | #if _LIBCPP_STD_VER > 11 | |
| 198 | template <> | |
| 199 | struct _LIBCPP_TEMPLATE_VIS modulus<void> | |
| 200 | { | |
| 201 | template <class _T1, class _T2> | |
| 202 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 203 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 204 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u))) | |
| 205 | -> decltype (_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u)) | |
| 206 | { return _VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u); } | |
| 207 | typedef void is_transparent; | |
| 208 | }; | |
| 209 | #endif | |
| 210 | ||
| 211 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 212 | #if _LIBCPP_STD_VER > 11 | |
| 213 | template <class _Tp = void> | |
| 214 | #else | |
| 215 | template <class _Tp> | |
| 216 | #endif | |
| 217 | struct _LIBCPP_TEMPLATE_VIS negate | |
| 218 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 219 | : unary_function<_Tp, _Tp> | |
| 220 | #endif | |
| 221 | { | |
| 222 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 223 | typedef _Tp __result_type; // used by valarray | |
| 224 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 225 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 226 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 227 | #endif | |
| 228 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 229 | _Tp operator()(const _Tp& __x) const | |
| 230 | {return -__x;} | |
| 231 | }; | |
| 232 | ||
| 233 | #if _LIBCPP_STD_VER > 11 | |
| 234 | template <> | |
| 235 | struct _LIBCPP_TEMPLATE_VIS negate<void> | |
| 236 | { | |
| 237 | template <class _Tp> | |
| 238 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 239 | auto operator()(_Tp&& __x) const | |
| 240 | _NOEXCEPT_(noexcept(- _VSTD::forward<_Tp>(__x))) | |
| 241 | -> decltype (- _VSTD::forward<_Tp>(__x)) | |
| 242 | { return - _VSTD::forward<_Tp>(__x); } | |
| 243 | typedef void is_transparent; | |
| 244 | }; | |
| 245 | #endif | |
| 246 | ||
| 247 | // Bitwise operations | |
| 248 | ||
| 249 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 250 | #if _LIBCPP_STD_VER > 11 | |
| 251 | template <class _Tp = void> | |
| 252 | #else | |
| 253 | template <class _Tp> | |
| 254 | #endif | |
| 255 | struct _LIBCPP_TEMPLATE_VIS bit_and | |
| 256 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 257 | : binary_function<_Tp, _Tp, _Tp> | |
| 258 | #endif | |
| 259 | { | |
| 260 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 261 | typedef _Tp __result_type; // used by valarray | |
| 262 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 263 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 264 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 265 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 266 | #endif | |
| 267 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 268 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 269 | {return __x & __y;} | |
| 270 | }; | |
| 271 | ||
| 272 | #if _LIBCPP_STD_VER > 11 | |
| 273 | template <> | |
| 274 | struct _LIBCPP_TEMPLATE_VIS bit_and<void> | |
| 275 | { | |
| 276 | template <class _T1, class _T2> | |
| 277 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 278 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 279 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u))) | |
| 280 | -> decltype (_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u)) | |
| 281 | { return _VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u); } | |
| 282 | typedef void is_transparent; | |
| 283 | }; | |
| 284 | #endif | |
| 285 | ||
| 286 | #if _LIBCPP_STD_VER > 11 | |
| 287 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 288 | template <class _Tp = void> | |
| 289 | struct _LIBCPP_TEMPLATE_VIS bit_not | |
| 290 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 291 | : unary_function<_Tp, _Tp> | |
| 292 | #endif | |
| 293 | { | |
| 294 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 295 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 296 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 297 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 298 | #endif | |
| 299 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 300 | _Tp operator()(const _Tp& __x) const | |
| 301 | {return ~__x;} | |
| 302 | }; | |
| 303 | ||
| 304 | template <> | |
| 305 | struct _LIBCPP_TEMPLATE_VIS bit_not<void> | |
| 306 | { | |
| 307 | template <class _Tp> | |
| 308 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 309 | auto operator()(_Tp&& __x) const | |
| 310 | _NOEXCEPT_(noexcept(~_VSTD::forward<_Tp>(__x))) | |
| 311 | -> decltype (~_VSTD::forward<_Tp>(__x)) | |
| 312 | { return ~_VSTD::forward<_Tp>(__x); } | |
| 313 | typedef void is_transparent; | |
| 314 | }; | |
| 315 | #endif | |
| 316 | ||
| 317 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 318 | #if _LIBCPP_STD_VER > 11 | |
| 319 | template <class _Tp = void> | |
| 320 | #else | |
| 321 | template <class _Tp> | |
| 322 | #endif | |
| 323 | struct _LIBCPP_TEMPLATE_VIS bit_or | |
| 324 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 325 | : binary_function<_Tp, _Tp, _Tp> | |
| 326 | #endif | |
| 327 | { | |
| 328 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 329 | typedef _Tp __result_type; // used by valarray | |
| 330 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 331 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 332 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 333 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 334 | #endif | |
| 335 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 336 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 337 | {return __x | __y;} | |
| 338 | }; | |
| 339 | ||
| 340 | #if _LIBCPP_STD_VER > 11 | |
| 341 | template <> | |
| 342 | struct _LIBCPP_TEMPLATE_VIS bit_or<void> | |
| 343 | { | |
| 344 | template <class _T1, class _T2> | |
| 345 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 346 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 347 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u))) | |
| 348 | -> decltype (_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u)) | |
| 349 | { return _VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u); } | |
| 350 | typedef void is_transparent; | |
| 351 | }; | |
| 352 | #endif | |
| 353 | ||
| 354 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 355 | #if _LIBCPP_STD_VER > 11 | |
| 356 | template <class _Tp = void> | |
| 357 | #else | |
| 358 | template <class _Tp> | |
| 359 | #endif | |
| 360 | struct _LIBCPP_TEMPLATE_VIS bit_xor | |
| 361 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 362 | : binary_function<_Tp, _Tp, _Tp> | |
| 363 | #endif | |
| 364 | { | |
| 365 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 366 | typedef _Tp __result_type; // used by valarray | |
| 367 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 368 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp result_type; | |
| 369 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 370 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 371 | #endif | |
| 372 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 373 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 374 | {return __x ^ __y;} | |
| 375 | }; | |
| 376 | ||
| 377 | #if _LIBCPP_STD_VER > 11 | |
| 378 | template <> | |
| 379 | struct _LIBCPP_TEMPLATE_VIS bit_xor<void> | |
| 380 | { | |
| 381 | template <class _T1, class _T2> | |
| 382 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 383 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 384 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u))) | |
| 385 | -> decltype (_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u)) | |
| 386 | { return _VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u); } | |
| 387 | typedef void is_transparent; | |
| 388 | }; | |
| 389 | #endif | |
| 390 | ||
| 391 | // Comparison operations | |
| 392 | ||
| 393 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 394 | #if _LIBCPP_STD_VER > 11 | |
| 395 | template <class _Tp = void> | |
| 396 | #else | |
| 397 | template <class _Tp> | |
| 398 | #endif | |
| 399 | struct _LIBCPP_TEMPLATE_VIS equal_to | |
| 400 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 401 | : binary_function<_Tp, _Tp, bool> | |
| 402 | #endif | |
| 403 | { | |
| 404 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 405 | typedef bool __result_type; // used by valarray | |
| 406 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 407 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 408 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 409 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 410 | #endif | |
| 411 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 412 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 413 | {return __x == __y;} | |
| 414 | }; | |
| 415 | ||
| 416 | #if _LIBCPP_STD_VER > 11 | |
| 417 | template <> | |
| 418 | struct _LIBCPP_TEMPLATE_VIS equal_to<void> | |
| 419 | { | |
| 420 | template <class _T1, class _T2> | |
| 421 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 422 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 423 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u))) | |
| 424 | -> decltype (_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u)) | |
| 425 | { return _VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u); } | |
| 426 | typedef void is_transparent; | |
| 427 | }; | |
| 428 | #endif | |
| 429 | ||
| 430 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 431 | #if _LIBCPP_STD_VER > 11 | |
| 432 | template <class _Tp = void> | |
| 433 | #else | |
| 434 | template <class _Tp> | |
| 435 | #endif | |
| 436 | struct _LIBCPP_TEMPLATE_VIS not_equal_to | |
| 437 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 438 | : binary_function<_Tp, _Tp, bool> | |
| 439 | #endif | |
| 440 | { | |
| 441 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 442 | typedef bool __result_type; // used by valarray | |
| 443 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 444 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 445 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 446 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 447 | #endif | |
| 448 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 449 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 450 | {return __x != __y;} | |
| 451 | }; | |
| 452 | ||
| 453 | #if _LIBCPP_STD_VER > 11 | |
| 454 | template <> | |
| 455 | struct _LIBCPP_TEMPLATE_VIS not_equal_to<void> | |
| 456 | { | |
| 457 | template <class _T1, class _T2> | |
| 458 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 459 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 460 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u))) | |
| 461 | -> decltype (_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u)) | |
| 462 | { return _VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u); } | |
| 463 | typedef void is_transparent; | |
| 464 | }; | |
| 465 | #endif | |
| 466 | ||
| 467 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 468 | #if _LIBCPP_STD_VER > 11 | |
| 469 | template <class _Tp = void> | |
| 470 | #else | |
| 471 | template <class _Tp> | |
| 472 | #endif | |
| 473 | struct _LIBCPP_TEMPLATE_VIS less | |
| 474 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 475 | : binary_function<_Tp, _Tp, bool> | |
| 476 | #endif | |
| 477 | { | |
| 478 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 479 | typedef bool __result_type; // used by valarray | |
| 480 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 481 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 482 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 483 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 484 | #endif | |
| 485 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 486 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 487 | {return __x < __y;} | |
| 488 | }; | |
| 489 | ||
| 490 | #if _LIBCPP_STD_VER > 11 | |
| 491 | template <> | |
| 492 | struct _LIBCPP_TEMPLATE_VIS less<void> | |
| 493 | { | |
| 494 | template <class _T1, class _T2> | |
| 495 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 496 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 497 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u))) | |
| 498 | -> decltype (_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)) | |
| 499 | { return _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u); } | |
| 500 | typedef void is_transparent; | |
| 501 | }; | |
| 502 | #endif | |
| 503 | ||
| 504 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 505 | #if _LIBCPP_STD_VER > 11 | |
| 506 | template <class _Tp = void> | |
| 507 | #else | |
| 508 | template <class _Tp> | |
| 509 | #endif | |
| 510 | struct _LIBCPP_TEMPLATE_VIS less_equal | |
| 511 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 512 | : binary_function<_Tp, _Tp, bool> | |
| 513 | #endif | |
| 514 | { | |
| 515 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 516 | typedef bool __result_type; // used by valarray | |
| 517 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 518 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 519 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 520 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 521 | #endif | |
| 522 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 523 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 524 | {return __x <= __y;} | |
| 525 | }; | |
| 526 | ||
| 527 | #if _LIBCPP_STD_VER > 11 | |
| 528 | template <> | |
| 529 | struct _LIBCPP_TEMPLATE_VIS less_equal<void> | |
| 530 | { | |
| 531 | template <class _T1, class _T2> | |
| 532 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 533 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 534 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u))) | |
| 535 | -> decltype (_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u)) | |
| 536 | { return _VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u); } | |
| 537 | typedef void is_transparent; | |
| 538 | }; | |
| 539 | #endif | |
| 540 | ||
| 541 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 542 | #if _LIBCPP_STD_VER > 11 | |
| 543 | template <class _Tp = void> | |
| 544 | #else | |
| 545 | template <class _Tp> | |
| 546 | #endif | |
| 547 | struct _LIBCPP_TEMPLATE_VIS greater_equal | |
| 548 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 549 | : binary_function<_Tp, _Tp, bool> | |
| 550 | #endif | |
| 551 | { | |
| 552 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 553 | typedef bool __result_type; // used by valarray | |
| 554 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 555 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 556 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 557 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 558 | #endif | |
| 559 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 560 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 561 | {return __x >= __y;} | |
| 562 | }; | |
| 563 | ||
| 564 | #if _LIBCPP_STD_VER > 11 | |
| 565 | template <> | |
| 566 | struct _LIBCPP_TEMPLATE_VIS greater_equal<void> | |
| 567 | { | |
| 568 | template <class _T1, class _T2> | |
| 569 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 570 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 571 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u))) | |
| 572 | -> decltype (_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u)) | |
| 573 | { return _VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u); } | |
| 574 | typedef void is_transparent; | |
| 575 | }; | |
| 576 | #endif | |
| 577 | ||
| 578 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 579 | #if _LIBCPP_STD_VER > 11 | |
| 580 | template <class _Tp = void> | |
| 581 | #else | |
| 582 | template <class _Tp> | |
| 583 | #endif | |
| 584 | struct _LIBCPP_TEMPLATE_VIS greater | |
| 585 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 586 | : binary_function<_Tp, _Tp, bool> | |
| 587 | #endif | |
| 588 | { | |
| 589 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 590 | typedef bool __result_type; // used by valarray | |
| 591 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 592 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 593 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 594 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 595 | #endif | |
| 596 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 597 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 598 | {return __x > __y;} | |
| 599 | }; | |
| 600 | ||
| 601 | #if _LIBCPP_STD_VER > 11 | |
| 602 | template <> | |
| 603 | struct _LIBCPP_TEMPLATE_VIS greater<void> | |
| 604 | { | |
| 605 | template <class _T1, class _T2> | |
| 606 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 607 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 608 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u))) | |
| 609 | -> decltype (_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u)) | |
| 610 | { return _VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u); } | |
| 611 | typedef void is_transparent; | |
| 612 | }; | |
| 613 | #endif | |
| 614 | ||
| 615 | // Logical operations | |
| 616 | ||
| 617 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 618 | #if _LIBCPP_STD_VER > 11 | |
| 619 | template <class _Tp = void> | |
| 620 | #else | |
| 621 | template <class _Tp> | |
| 622 | #endif | |
| 623 | struct _LIBCPP_TEMPLATE_VIS logical_and | |
| 624 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 625 | : binary_function<_Tp, _Tp, bool> | |
| 626 | #endif | |
| 627 | { | |
| 628 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 629 | typedef bool __result_type; // used by valarray | |
| 630 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 631 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 632 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 633 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 634 | #endif | |
| 635 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 636 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 637 | {return __x && __y;} | |
| 638 | }; | |
| 639 | ||
| 640 | #if _LIBCPP_STD_VER > 11 | |
| 641 | template <> | |
| 642 | struct _LIBCPP_TEMPLATE_VIS logical_and<void> | |
| 643 | { | |
| 644 | template <class _T1, class _T2> | |
| 645 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 646 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 647 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u))) | |
| 648 | -> decltype (_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u)) | |
| 649 | { return _VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u); } | |
| 650 | typedef void is_transparent; | |
| 651 | }; | |
| 652 | #endif | |
| 653 | ||
| 654 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 655 | #if _LIBCPP_STD_VER > 11 | |
| 656 | template <class _Tp = void> | |
| 657 | #else | |
| 658 | template <class _Tp> | |
| 659 | #endif | |
| 660 | struct _LIBCPP_TEMPLATE_VIS logical_not | |
| 661 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 662 | : unary_function<_Tp, bool> | |
| 663 | #endif | |
| 664 | { | |
| 665 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 666 | typedef bool __result_type; // used by valarray | |
| 667 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 668 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 669 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp argument_type; | |
| 670 | #endif | |
| 671 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 672 | bool operator()(const _Tp& __x) const | |
| 673 | {return !__x;} | |
| 674 | }; | |
| 675 | ||
| 676 | #if _LIBCPP_STD_VER > 11 | |
| 677 | template <> | |
| 678 | struct _LIBCPP_TEMPLATE_VIS logical_not<void> | |
| 679 | { | |
| 680 | template <class _Tp> | |
| 681 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 682 | auto operator()(_Tp&& __x) const | |
| 683 | _NOEXCEPT_(noexcept(!_VSTD::forward<_Tp>(__x))) | |
| 684 | -> decltype (!_VSTD::forward<_Tp>(__x)) | |
| 685 | { return !_VSTD::forward<_Tp>(__x); } | |
| 686 | typedef void is_transparent; | |
| 687 | }; | |
| 688 | #endif | |
| 689 | ||
| 690 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 691 | #if _LIBCPP_STD_VER > 11 | |
| 692 | template <class _Tp = void> | |
| 693 | #else | |
| 694 | template <class _Tp> | |
| 695 | #endif | |
| 696 | struct _LIBCPP_TEMPLATE_VIS logical_or | |
| 697 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 698 | : binary_function<_Tp, _Tp, bool> | |
| 699 | #endif | |
| 700 | { | |
| 701 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 702 | typedef bool __result_type; // used by valarray | |
| 703 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 704 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 705 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp first_argument_type; | |
| 706 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp second_argument_type; | |
| 707 | #endif | |
| 708 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 709 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 710 | {return __x || __y;} | |
| 711 | }; | |
| 712 | ||
| 713 | #if _LIBCPP_STD_VER > 11 | |
| 714 | template <> | |
| 715 | struct _LIBCPP_TEMPLATE_VIS logical_or<void> | |
| 716 | { | |
| 717 | template <class _T1, class _T2> | |
| 718 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 719 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 720 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u))) | |
| 721 | -> decltype (_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u)) | |
| 722 | { return _VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u); } | |
| 723 | typedef void is_transparent; | |
| 724 | }; | |
| 725 | #endif | |
| 726 | ||
| 727 | _LIBCPP_END_NAMESPACE_STD | |
| 728 | ||
| 729 | #endif // _LIBCPP___FUNCTIONAL_OPERATIONS_H |
lib/libcxx/include/__functional/perfect_forward.h created+88| ... | ... | @@ -0,0 +1,88 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <tuple> | |
| 15 | #include <type_traits> | |
| 16 | #include <utility> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #if _LIBCPP_STD_VER > 14 | |
| 25 | ||
| 26 | template<class _Op, class _Tuple, | |
| 27 | class _Idxs = typename __make_tuple_indices<tuple_size<_Tuple>::value>::type> | |
| 28 | struct __perfect_forward_impl; | |
| 29 | ||
| 30 | template<class _Op, class... _Bound, size_t... _Idxs> | |
| 31 | struct __perfect_forward_impl<_Op, __tuple_types<_Bound...>, __tuple_indices<_Idxs...>> | |
| 32 | { | |
| 33 | tuple<_Bound...> __bound_; | |
| 34 | ||
| 35 | template<class... _Args> | |
| 36 | _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) & | |
| 37 | noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))) | |
| 38 | -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)) | |
| 39 | {return _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);} | |
| 40 | ||
| 41 | template<class... _Args> | |
| 42 | _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const& | |
| 43 | noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))) | |
| 44 | -> decltype( _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)) | |
| 45 | {return _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);} | |
| 46 | ||
| 47 | template<class... _Args> | |
| 48 | _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) && | |
| 49 | noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., | |
| 50 | _VSTD::forward<_Args>(__args)...))) | |
| 51 | -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., | |
| 52 | _VSTD::forward<_Args>(__args)...)) | |
| 53 | {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., | |
| 54 | _VSTD::forward<_Args>(__args)...);} | |
| 55 | ||
| 56 | template<class... _Args> | |
| 57 | _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&& | |
| 58 | noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., | |
| 59 | _VSTD::forward<_Args>(__args)...))) | |
| 60 | -> decltype( _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., | |
| 61 | _VSTD::forward<_Args>(__args)...)) | |
| 62 | {return _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))..., | |
| 63 | _VSTD::forward<_Args>(__args)...);} | |
| 64 | ||
| 65 | template<class _Fn = typename tuple_element<0, tuple<_Bound...>>::type, | |
| 66 | class = _EnableIf<is_copy_constructible_v<_Fn>>> | |
| 67 | constexpr __perfect_forward_impl(__perfect_forward_impl const& __other) | |
| 68 | : __bound_(__other.__bound_) {} | |
| 69 | ||
| 70 | template<class _Fn = typename tuple_element<0, tuple<_Bound...>>::type, | |
| 71 | class = _EnableIf<is_move_constructible_v<_Fn>>> | |
| 72 | constexpr __perfect_forward_impl(__perfect_forward_impl && __other) | |
| 73 | : __bound_(_VSTD::move(__other.__bound_)) {} | |
| 74 | ||
| 75 | template<class... _BoundArgs> | |
| 76 | explicit constexpr __perfect_forward_impl(_BoundArgs&&... __bound) : | |
| 77 | __bound_(_VSTD::forward<_BoundArgs>(__bound)...) { } | |
| 78 | }; | |
| 79 | ||
| 80 | template<class _Op, class... _Args> | |
| 81 | using __perfect_forward = | |
| 82 | __perfect_forward_impl<_Op, __tuple_types<decay_t<_Args>...>>; | |
| 83 | ||
| 84 | #endif // _LIBCPP_STD_VER > 14 | |
| 85 | ||
| 86 | _LIBCPP_END_NAMESPACE_STD | |
| 87 | ||
| 88 | #endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H |
lib/libcxx/include/__functional/pointer_to_binary_function.h created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_POINTER_TO_BINARY_FUNCTION_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_POINTER_TO_BINARY_FUNCTION_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/binary_function.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 23 | ||
| 24 | template <class _Arg1, class _Arg2, class _Result> | |
| 25 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function | |
| 26 | : public binary_function<_Arg1, _Arg2, _Result> | |
| 27 | { | |
| 28 | _Result (*__f_)(_Arg1, _Arg2); | |
| 29 | public: | |
| 30 | _LIBCPP_INLINE_VISIBILITY explicit pointer_to_binary_function(_Result (*__f)(_Arg1, _Arg2)) | |
| 31 | : __f_(__f) {} | |
| 32 | _LIBCPP_INLINE_VISIBILITY _Result operator()(_Arg1 __x, _Arg2 __y) const | |
| 33 | {return __f_(__x, __y);} | |
| 34 | }; | |
| 35 | ||
| 36 | template <class _Arg1, class _Arg2, class _Result> | |
| 37 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 38 | pointer_to_binary_function<_Arg1,_Arg2,_Result> | |
| 39 | ptr_fun(_Result (*__f)(_Arg1,_Arg2)) | |
| 40 | {return pointer_to_binary_function<_Arg1,_Arg2,_Result>(__f);} | |
| 41 | ||
| 42 | #endif | |
| 43 | ||
| 44 | _LIBCPP_END_NAMESPACE_STD | |
| 45 | ||
| 46 | #endif // _LIBCPP___FUNCTIONAL_POINTER_TO_BINARY_FUNCTION_H |
lib/libcxx/include/__functional/pointer_to_unary_function.h created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_POINTER_TO_UNARY_FUNCTION_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_POINTER_TO_UNARY_FUNCTION_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/unary_function.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 23 | ||
| 24 | template <class _Arg, class _Result> | |
| 25 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function | |
| 26 | : public unary_function<_Arg, _Result> | |
| 27 | { | |
| 28 | _Result (*__f_)(_Arg); | |
| 29 | public: | |
| 30 | _LIBCPP_INLINE_VISIBILITY explicit pointer_to_unary_function(_Result (*__f)(_Arg)) | |
| 31 | : __f_(__f) {} | |
| 32 | _LIBCPP_INLINE_VISIBILITY _Result operator()(_Arg __x) const | |
| 33 | {return __f_(__x);} | |
| 34 | }; | |
| 35 | ||
| 36 | template <class _Arg, class _Result> | |
| 37 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 38 | pointer_to_unary_function<_Arg,_Result> | |
| 39 | ptr_fun(_Result (*__f)(_Arg)) | |
| 40 | {return pointer_to_unary_function<_Arg,_Result>(__f);} | |
| 41 | ||
| 42 | #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 43 | ||
| 44 | _LIBCPP_END_NAMESPACE_STD | |
| 45 | ||
| 46 | #endif // _LIBCPP___FUNCTIONAL_POINTER_TO_UNARY_FUNCTION_H |
lib/libcxx/include/__functional/ranges_operations.h created+97| ... | ... | @@ -0,0 +1,97 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_RANGES_OPERATIONS_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_RANGES_OPERATIONS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <concepts> | |
| 15 | #include <utility> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 24 | namespace ranges { | |
| 25 | ||
| 26 | struct equal_to { | |
| 27 | template <class _Tp, class _Up> | |
| 28 | requires equality_comparable_with<_Tp, _Up> | |
| 29 | [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const | |
| 30 | noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)))) { | |
| 31 | return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u); | |
| 32 | } | |
| 33 | ||
| 34 | using is_transparent = void; | |
| 35 | }; | |
| 36 | ||
| 37 | struct not_equal_to { | |
| 38 | template <class _Tp, class _Up> | |
| 39 | requires equality_comparable_with<_Tp, _Up> | |
| 40 | [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const | |
| 41 | noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u))))) { | |
| 42 | return !(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)); | |
| 43 | } | |
| 44 | ||
| 45 | using is_transparent = void; | |
| 46 | }; | |
| 47 | ||
| 48 | struct less { | |
| 49 | template <class _Tp, class _Up> | |
| 50 | requires totally_ordered_with<_Tp, _Up> | |
| 51 | [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const | |
| 52 | noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)))) { | |
| 53 | return _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u); | |
| 54 | } | |
| 55 | ||
| 56 | using is_transparent = void; | |
| 57 | }; | |
| 58 | ||
| 59 | struct less_equal { | |
| 60 | template <class _Tp, class _Up> | |
| 61 | requires totally_ordered_with<_Tp, _Up> | |
| 62 | [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const | |
| 63 | noexcept(noexcept(bool(!(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t))))) { | |
| 64 | return !(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)); | |
| 65 | } | |
| 66 | ||
| 67 | using is_transparent = void; | |
| 68 | }; | |
| 69 | ||
| 70 | struct greater { | |
| 71 | template <class _Tp, class _Up> | |
| 72 | requires totally_ordered_with<_Tp, _Up> | |
| 73 | [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const | |
| 74 | noexcept(noexcept(bool(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)))) { | |
| 75 | return _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t); | |
| 76 | } | |
| 77 | ||
| 78 | using is_transparent = void; | |
| 79 | }; | |
| 80 | ||
| 81 | struct greater_equal { | |
| 82 | template <class _Tp, class _Up> | |
| 83 | requires totally_ordered_with<_Tp, _Up> | |
| 84 | [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const | |
| 85 | noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u))))) { | |
| 86 | return !(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)); | |
| 87 | } | |
| 88 | ||
| 89 | using is_transparent = void; | |
| 90 | }; | |
| 91 | ||
| 92 | } // namespace ranges | |
| 93 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 94 | ||
| 95 | _LIBCPP_END_NAMESPACE_STD | |
| 96 | ||
| 97 | #endif // _LIBCPP___FUNCTIONAL_RANGES_OPERATIONS_H |
lib/libcxx/include/__functional/reference_wrapper.h created+223| ... | ... | @@ -0,0 +1,223 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/weak_result_type.h> | |
| 15 | #include <__memory/addressof.h> | |
| 16 | #include <__utility/forward.h> | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _Tp> | |
| 26 | class _LIBCPP_TEMPLATE_VIS reference_wrapper | |
| 27 | #if _LIBCPP_STD_VER <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 28 | : public __weak_result_type<_Tp> | |
| 29 | #endif | |
| 30 | { | |
| 31 | public: | |
| 32 | // types | |
| 33 | typedef _Tp type; | |
| 34 | private: | |
| 35 | type* __f_; | |
| 36 | ||
| 37 | #ifndef _LIBCPP_CXX03_LANG | |
| 38 | static void __fun(_Tp&) _NOEXCEPT; | |
| 39 | static void __fun(_Tp&&) = delete; | |
| 40 | #endif | |
| 41 | ||
| 42 | public: | |
| 43 | // construct/copy/destroy | |
| 44 | #ifdef _LIBCPP_CXX03_LANG | |
| 45 | _LIBCPP_INLINE_VISIBILITY | |
| 46 | reference_wrapper(type& __f) _NOEXCEPT | |
| 47 | : __f_(_VSTD::addressof(__f)) {} | |
| 48 | #else | |
| 49 | template <class _Up, class = _EnableIf<!__is_same_uncvref<_Up, reference_wrapper>::value, decltype(__fun(declval<_Up>())) >> | |
| 50 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 51 | reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(declval<_Up>()))) { | |
| 52 | type& __f = static_cast<_Up&&>(__u); | |
| 53 | __f_ = _VSTD::addressof(__f); | |
| 54 | } | |
| 55 | #endif | |
| 56 | ||
| 57 | // access | |
| 58 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 59 | operator type&() const _NOEXCEPT {return *__f_;} | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 61 | type& get() const _NOEXCEPT {return *__f_;} | |
| 62 | ||
| 63 | #ifndef _LIBCPP_CXX03_LANG | |
| 64 | // invoke | |
| 65 | template <class... _ArgTypes> | |
| 66 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 67 | typename __invoke_of<type&, _ArgTypes...>::type | |
| 68 | operator() (_ArgTypes&&... __args) const { | |
| 69 | return _VSTD::__invoke(get(), _VSTD::forward<_ArgTypes>(__args)...); | |
| 70 | } | |
| 71 | #else | |
| 72 | ||
| 73 | _LIBCPP_INLINE_VISIBILITY | |
| 74 | typename __invoke_return<type>::type | |
| 75 | operator() () const { | |
| 76 | return _VSTD::__invoke(get()); | |
| 77 | } | |
| 78 | ||
| 79 | template <class _A0> | |
| 80 | _LIBCPP_INLINE_VISIBILITY | |
| 81 | typename __invoke_return0<type, _A0>::type | |
| 82 | operator() (_A0& __a0) const { | |
| 83 | return _VSTD::__invoke(get(), __a0); | |
| 84 | } | |
| 85 | ||
| 86 | template <class _A0> | |
| 87 | _LIBCPP_INLINE_VISIBILITY | |
| 88 | typename __invoke_return0<type, _A0 const>::type | |
| 89 | operator() (_A0 const& __a0) const { | |
| 90 | return _VSTD::__invoke(get(), __a0); | |
| 91 | } | |
| 92 | ||
| 93 | template <class _A0, class _A1> | |
| 94 | _LIBCPP_INLINE_VISIBILITY | |
| 95 | typename __invoke_return1<type, _A0, _A1>::type | |
| 96 | operator() (_A0& __a0, _A1& __a1) const { | |
| 97 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 98 | } | |
| 99 | ||
| 100 | template <class _A0, class _A1> | |
| 101 | _LIBCPP_INLINE_VISIBILITY | |
| 102 | typename __invoke_return1<type, _A0 const, _A1>::type | |
| 103 | operator() (_A0 const& __a0, _A1& __a1) const { | |
| 104 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 105 | } | |
| 106 | ||
| 107 | template <class _A0, class _A1> | |
| 108 | _LIBCPP_INLINE_VISIBILITY | |
| 109 | typename __invoke_return1<type, _A0, _A1 const>::type | |
| 110 | operator() (_A0& __a0, _A1 const& __a1) const { | |
| 111 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 112 | } | |
| 113 | ||
| 114 | template <class _A0, class _A1> | |
| 115 | _LIBCPP_INLINE_VISIBILITY | |
| 116 | typename __invoke_return1<type, _A0 const, _A1 const>::type | |
| 117 | operator() (_A0 const& __a0, _A1 const& __a1) const { | |
| 118 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 119 | } | |
| 120 | ||
| 121 | template <class _A0, class _A1, class _A2> | |
| 122 | _LIBCPP_INLINE_VISIBILITY | |
| 123 | typename __invoke_return2<type, _A0, _A1, _A2>::type | |
| 124 | operator() (_A0& __a0, _A1& __a1, _A2& __a2) const { | |
| 125 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 126 | } | |
| 127 | ||
| 128 | template <class _A0, class _A1, class _A2> | |
| 129 | _LIBCPP_INLINE_VISIBILITY | |
| 130 | typename __invoke_return2<type, _A0 const, _A1, _A2>::type | |
| 131 | operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const { | |
| 132 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 133 | } | |
| 134 | ||
| 135 | template <class _A0, class _A1, class _A2> | |
| 136 | _LIBCPP_INLINE_VISIBILITY | |
| 137 | typename __invoke_return2<type, _A0, _A1 const, _A2>::type | |
| 138 | operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 139 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 140 | } | |
| 141 | ||
| 142 | template <class _A0, class _A1, class _A2> | |
| 143 | _LIBCPP_INLINE_VISIBILITY | |
| 144 | typename __invoke_return2<type, _A0, _A1, _A2 const>::type | |
| 145 | operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 146 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 147 | } | |
| 148 | ||
| 149 | template <class _A0, class _A1, class _A2> | |
| 150 | _LIBCPP_INLINE_VISIBILITY | |
| 151 | typename __invoke_return2<type, _A0 const, _A1 const, _A2>::type | |
| 152 | operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 153 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 154 | } | |
| 155 | ||
| 156 | template <class _A0, class _A1, class _A2> | |
| 157 | _LIBCPP_INLINE_VISIBILITY | |
| 158 | typename __invoke_return2<type, _A0 const, _A1, _A2 const>::type | |
| 159 | operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 160 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 161 | } | |
| 162 | ||
| 163 | template <class _A0, class _A1, class _A2> | |
| 164 | _LIBCPP_INLINE_VISIBILITY | |
| 165 | typename __invoke_return2<type, _A0, _A1 const, _A2 const>::type | |
| 166 | operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 167 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 168 | } | |
| 169 | ||
| 170 | template <class _A0, class _A1, class _A2> | |
| 171 | _LIBCPP_INLINE_VISIBILITY | |
| 172 | typename __invoke_return2<type, _A0 const, _A1 const, _A2 const>::type | |
| 173 | operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 174 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 175 | } | |
| 176 | #endif // _LIBCPP_CXX03_LANG | |
| 177 | }; | |
| 178 | ||
| 179 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 180 | template <class _Tp> | |
| 181 | reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; | |
| 182 | #endif | |
| 183 | ||
| 184 | template <class _Tp> | |
| 185 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 186 | reference_wrapper<_Tp> | |
| 187 | ref(_Tp& __t) _NOEXCEPT | |
| 188 | { | |
| 189 | return reference_wrapper<_Tp>(__t); | |
| 190 | } | |
| 191 | ||
| 192 | template <class _Tp> | |
| 193 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 194 | reference_wrapper<_Tp> | |
| 195 | ref(reference_wrapper<_Tp> __t) _NOEXCEPT | |
| 196 | { | |
| 197 | return _VSTD::ref(__t.get()); | |
| 198 | } | |
| 199 | ||
| 200 | template <class _Tp> | |
| 201 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 202 | reference_wrapper<const _Tp> | |
| 203 | cref(const _Tp& __t) _NOEXCEPT | |
| 204 | { | |
| 205 | return reference_wrapper<const _Tp>(__t); | |
| 206 | } | |
| 207 | ||
| 208 | template <class _Tp> | |
| 209 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 210 | reference_wrapper<const _Tp> | |
| 211 | cref(reference_wrapper<_Tp> __t) _NOEXCEPT | |
| 212 | { | |
| 213 | return _VSTD::cref(__t.get()); | |
| 214 | } | |
| 215 | ||
| 216 | #ifndef _LIBCPP_CXX03_LANG | |
| 217 | template <class _Tp> void ref(const _Tp&&) = delete; | |
| 218 | template <class _Tp> void cref(const _Tp&&) = delete; | |
| 219 | #endif | |
| 220 | ||
| 221 | _LIBCPP_END_NAMESPACE_STD | |
| 222 | ||
| 223 | #endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H |
lib/libcxx/include/__functional/unary_function.h created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___FUNCTIONAL_UNARY_FUNCTION_H | |
| 10 | #define _LIBCPP___FUNCTIONAL_UNARY_FUNCTION_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _Arg, class _Result> | |
| 24 | struct _LIBCPP_TEMPLATE_VIS unary_function | |
| 25 | { | |
| 26 | typedef _Arg argument_type; | |
| 27 | typedef _Result result_type; | |
| 28 | }; | |
| 29 | ||
| 30 | _LIBCPP_END_NAMESPACE_STD | |
| 31 | ||
| 32 | _LIBCPP_POP_MACROS | |
| 33 | ||
| 34 | #endif // _LIBCPP___FUNCTIONAL_UNARY_FUNCTION_H |
lib/libcxx/include/__functional/unary_negate.h created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_UNARY_NEGATE_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_UNARY_NEGATE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/unary_function.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 21 | ||
| 22 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) | |
| 23 | ||
| 24 | template <class _Predicate> | |
| 25 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 unary_negate | |
| 26 | : public unary_function<typename _Predicate::argument_type, bool> | |
| 27 | { | |
| 28 | _Predicate __pred_; | |
| 29 | public: | |
| 30 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 31 | explicit unary_negate(const _Predicate& __pred) | |
| 32 | : __pred_(__pred) {} | |
| 33 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 34 | bool operator()(const typename _Predicate::argument_type& __x) const | |
| 35 | {return !__pred_(__x);} | |
| 36 | }; | |
| 37 | ||
| 38 | template <class _Predicate> | |
| 39 | _LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 40 | unary_negate<_Predicate> | |
| 41 | not1(const _Predicate& __pred) {return unary_negate<_Predicate>(__pred);} | |
| 42 | ||
| 43 | #endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) | |
| 44 | ||
| 45 | _LIBCPP_END_NAMESPACE_STD | |
| 46 | ||
| 47 | #endif // _LIBCPP___FUNCTIONAL_UNARY_NEGATE_H |
lib/libcxx/include/__functional/unwrap_ref.h created+62| ... | ... | @@ -0,0 +1,62 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___FUNCTIONAL_UNWRAP_REF_H | |
| 10 | #define _LIBCPP___FUNCTIONAL_UNWRAP_REF_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _Tp> | |
| 24 | struct __unwrap_reference { typedef _LIBCPP_NODEBUG_TYPE _Tp type; }; | |
| 25 | ||
| 26 | template <class _Tp> | |
| 27 | class reference_wrapper; | |
| 28 | ||
| 29 | template <class _Tp> | |
| 30 | struct __unwrap_reference<reference_wrapper<_Tp> > { typedef _LIBCPP_NODEBUG_TYPE _Tp& type; }; | |
| 31 | ||
| 32 | template <class _Tp> | |
| 33 | struct decay; | |
| 34 | ||
| 35 | #if _LIBCPP_STD_VER > 17 | |
| 36 | template <class _Tp> | |
| 37 | struct unwrap_reference : __unwrap_reference<_Tp> { }; | |
| 38 | ||
| 39 | template <class _Tp> | |
| 40 | using unwrap_reference_t = typename unwrap_reference<_Tp>::type; | |
| 41 | ||
| 42 | template <class _Tp> | |
| 43 | struct unwrap_ref_decay : unwrap_reference<typename decay<_Tp>::type> { }; | |
| 44 | ||
| 45 | template <class _Tp> | |
| 46 | using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; | |
| 47 | #endif // > C++17 | |
| 48 | ||
| 49 | template <class _Tp> | |
| 50 | struct __unwrap_ref_decay | |
| 51 | #if _LIBCPP_STD_VER > 17 | |
| 52 | : unwrap_ref_decay<_Tp> | |
| 53 | #else | |
| 54 | : __unwrap_reference<typename decay<_Tp>::type> | |
| 55 | #endif | |
| 56 | { }; | |
| 57 | ||
| 58 | _LIBCPP_END_NAMESPACE_STD | |
| 59 | ||
| 60 | _LIBCPP_POP_MACROS | |
| 61 | ||
| 62 | #endif // _LIBCPP___FUNCTIONAL_UNWRAP_REF_H |
lib/libcxx/include/__functional/weak_result_type.h created+481| ... | ... | @@ -0,0 +1,481 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H | |
| 11 | #define _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/binary_function.h> | |
| 15 | #include <__functional/unary_function.h> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _Tp> | |
| 25 | struct __has_result_type | |
| 26 | { | |
| 27 | private: | |
| 28 | struct __two {char __lx; char __lxx;}; | |
| 29 | template <class _Up> static __two __test(...); | |
| 30 | template <class _Up> static char __test(typename _Up::result_type* = 0); | |
| 31 | public: | |
| 32 | static const bool value = sizeof(__test<_Tp>(0)) == 1; | |
| 33 | }; | |
| 34 | ||
| 35 | // __weak_result_type | |
| 36 | ||
| 37 | template <class _Tp> | |
| 38 | struct __derives_from_unary_function | |
| 39 | { | |
| 40 | private: | |
| 41 | struct __two {char __lx; char __lxx;}; | |
| 42 | static __two __test(...); | |
| 43 | template <class _Ap, class _Rp> | |
| 44 | static unary_function<_Ap, _Rp> | |
| 45 | __test(const volatile unary_function<_Ap, _Rp>*); | |
| 46 | public: | |
| 47 | static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value; | |
| 48 | typedef decltype(__test((_Tp*)0)) type; | |
| 49 | }; | |
| 50 | ||
| 51 | template <class _Tp> | |
| 52 | struct __derives_from_binary_function | |
| 53 | { | |
| 54 | private: | |
| 55 | struct __two {char __lx; char __lxx;}; | |
| 56 | static __two __test(...); | |
| 57 | template <class _A1, class _A2, class _Rp> | |
| 58 | static binary_function<_A1, _A2, _Rp> | |
| 59 | __test(const volatile binary_function<_A1, _A2, _Rp>*); | |
| 60 | public: | |
| 61 | static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value; | |
| 62 | typedef decltype(__test((_Tp*)0)) type; | |
| 63 | }; | |
| 64 | ||
| 65 | template <class _Tp, bool = __derives_from_unary_function<_Tp>::value> | |
| 66 | struct __maybe_derive_from_unary_function // bool is true | |
| 67 | : public __derives_from_unary_function<_Tp>::type | |
| 68 | { | |
| 69 | }; | |
| 70 | ||
| 71 | template <class _Tp> | |
| 72 | struct __maybe_derive_from_unary_function<_Tp, false> | |
| 73 | { | |
| 74 | }; | |
| 75 | ||
| 76 | template <class _Tp, bool = __derives_from_binary_function<_Tp>::value> | |
| 77 | struct __maybe_derive_from_binary_function // bool is true | |
| 78 | : public __derives_from_binary_function<_Tp>::type | |
| 79 | { | |
| 80 | }; | |
| 81 | ||
| 82 | template <class _Tp> | |
| 83 | struct __maybe_derive_from_binary_function<_Tp, false> | |
| 84 | { | |
| 85 | }; | |
| 86 | ||
| 87 | template <class _Tp, bool = __has_result_type<_Tp>::value> | |
| 88 | struct __weak_result_type_imp // bool is true | |
| 89 | : public __maybe_derive_from_unary_function<_Tp>, | |
| 90 | public __maybe_derive_from_binary_function<_Tp> | |
| 91 | { | |
| 92 | typedef _LIBCPP_NODEBUG_TYPE typename _Tp::result_type result_type; | |
| 93 | }; | |
| 94 | ||
| 95 | template <class _Tp> | |
| 96 | struct __weak_result_type_imp<_Tp, false> | |
| 97 | : public __maybe_derive_from_unary_function<_Tp>, | |
| 98 | public __maybe_derive_from_binary_function<_Tp> | |
| 99 | { | |
| 100 | }; | |
| 101 | ||
| 102 | template <class _Tp> | |
| 103 | struct __weak_result_type | |
| 104 | : public __weak_result_type_imp<_Tp> | |
| 105 | { | |
| 106 | }; | |
| 107 | ||
| 108 | // 0 argument case | |
| 109 | ||
| 110 | template <class _Rp> | |
| 111 | struct __weak_result_type<_Rp ()> | |
| 112 | { | |
| 113 | typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; | |
| 114 | }; | |
| 115 | ||
| 116 | template <class _Rp> | |
| 117 | struct __weak_result_type<_Rp (&)()> | |
| 118 | { | |
| 119 | typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; | |
| 120 | }; | |
| 121 | ||
| 122 | template <class _Rp> | |
| 123 | struct __weak_result_type<_Rp (*)()> | |
| 124 | { | |
| 125 | typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; | |
| 126 | }; | |
| 127 | ||
| 128 | // 1 argument case | |
| 129 | ||
| 130 | template <class _Rp, class _A1> | |
| 131 | struct __weak_result_type<_Rp (_A1)> | |
| 132 | : public unary_function<_A1, _Rp> | |
| 133 | { | |
| 134 | }; | |
| 135 | ||
| 136 | template <class _Rp, class _A1> | |
| 137 | struct __weak_result_type<_Rp (&)(_A1)> | |
| 138 | : public unary_function<_A1, _Rp> | |
| 139 | { | |
| 140 | }; | |
| 141 | ||
| 142 | template <class _Rp, class _A1> | |
| 143 | struct __weak_result_type<_Rp (*)(_A1)> | |
| 144 | : public unary_function<_A1, _Rp> | |
| 145 | { | |
| 146 | }; | |
| 147 | ||
| 148 | template <class _Rp, class _Cp> | |
| 149 | struct __weak_result_type<_Rp (_Cp::*)()> | |
| 150 | : public unary_function<_Cp*, _Rp> | |
| 151 | { | |
| 152 | }; | |
| 153 | ||
| 154 | template <class _Rp, class _Cp> | |
| 155 | struct __weak_result_type<_Rp (_Cp::*)() const> | |
| 156 | : public unary_function<const _Cp*, _Rp> | |
| 157 | { | |
| 158 | }; | |
| 159 | ||
| 160 | template <class _Rp, class _Cp> | |
| 161 | struct __weak_result_type<_Rp (_Cp::*)() volatile> | |
| 162 | : public unary_function<volatile _Cp*, _Rp> | |
| 163 | { | |
| 164 | }; | |
| 165 | ||
| 166 | template <class _Rp, class _Cp> | |
| 167 | struct __weak_result_type<_Rp (_Cp::*)() const volatile> | |
| 168 | : public unary_function<const volatile _Cp*, _Rp> | |
| 169 | { | |
| 170 | }; | |
| 171 | ||
| 172 | // 2 argument case | |
| 173 | ||
| 174 | template <class _Rp, class _A1, class _A2> | |
| 175 | struct __weak_result_type<_Rp (_A1, _A2)> | |
| 176 | : public binary_function<_A1, _A2, _Rp> | |
| 177 | { | |
| 178 | }; | |
| 179 | ||
| 180 | template <class _Rp, class _A1, class _A2> | |
| 181 | struct __weak_result_type<_Rp (*)(_A1, _A2)> | |
| 182 | : public binary_function<_A1, _A2, _Rp> | |
| 183 | { | |
| 184 | }; | |
| 185 | ||
| 186 | template <class _Rp, class _A1, class _A2> | |
| 187 | struct __weak_result_type<_Rp (&)(_A1, _A2)> | |
| 188 | : public binary_function<_A1, _A2, _Rp> | |
| 189 | { | |
| 190 | }; | |
| 191 | ||
| 192 | template <class _Rp, class _Cp, class _A1> | |
| 193 | struct __weak_result_type<_Rp (_Cp::*)(_A1)> | |
| 194 | : public binary_function<_Cp*, _A1, _Rp> | |
| 195 | { | |
| 196 | }; | |
| 197 | ||
| 198 | template <class _Rp, class _Cp, class _A1> | |
| 199 | struct __weak_result_type<_Rp (_Cp::*)(_A1) const> | |
| 200 | : public binary_function<const _Cp*, _A1, _Rp> | |
| 201 | { | |
| 202 | }; | |
| 203 | ||
| 204 | template <class _Rp, class _Cp, class _A1> | |
| 205 | struct __weak_result_type<_Rp (_Cp::*)(_A1) volatile> | |
| 206 | : public binary_function<volatile _Cp*, _A1, _Rp> | |
| 207 | { | |
| 208 | }; | |
| 209 | ||
| 210 | template <class _Rp, class _Cp, class _A1> | |
| 211 | struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile> | |
| 212 | : public binary_function<const volatile _Cp*, _A1, _Rp> | |
| 213 | { | |
| 214 | }; | |
| 215 | ||
| 216 | ||
| 217 | #ifndef _LIBCPP_CXX03_LANG | |
| 218 | // 3 or more arguments | |
| 219 | ||
| 220 | template <class _Rp, class _A1, class _A2, class _A3, class ..._A4> | |
| 221 | struct __weak_result_type<_Rp (_A1, _A2, _A3, _A4...)> | |
| 222 | { | |
| 223 | typedef _Rp result_type; | |
| 224 | }; | |
| 225 | ||
| 226 | template <class _Rp, class _A1, class _A2, class _A3, class ..._A4> | |
| 227 | struct __weak_result_type<_Rp (&)(_A1, _A2, _A3, _A4...)> | |
| 228 | { | |
| 229 | typedef _Rp result_type; | |
| 230 | }; | |
| 231 | ||
| 232 | template <class _Rp, class _A1, class _A2, class _A3, class ..._A4> | |
| 233 | struct __weak_result_type<_Rp (*)(_A1, _A2, _A3, _A4...)> | |
| 234 | { | |
| 235 | typedef _Rp result_type; | |
| 236 | }; | |
| 237 | ||
| 238 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 239 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...)> | |
| 240 | { | |
| 241 | typedef _Rp result_type; | |
| 242 | }; | |
| 243 | ||
| 244 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 245 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const> | |
| 246 | { | |
| 247 | typedef _Rp result_type; | |
| 248 | }; | |
| 249 | ||
| 250 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 251 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) volatile> | |
| 252 | { | |
| 253 | typedef _Rp result_type; | |
| 254 | }; | |
| 255 | ||
| 256 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 257 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> | |
| 258 | { | |
| 259 | typedef _Rp result_type; | |
| 260 | }; | |
| 261 | ||
| 262 | template <class _Tp, class ..._Args> | |
| 263 | struct __invoke_return | |
| 264 | { | |
| 265 | typedef decltype(_VSTD::__invoke(declval<_Tp>(), declval<_Args>()...)) type; | |
| 266 | }; | |
| 267 | ||
| 268 | #else // defined(_LIBCPP_CXX03_LANG) | |
| 269 | ||
| 270 | template <class _Ret, class _T1, bool _IsFunc, bool _IsBase> | |
| 271 | struct __enable_invoke_imp; | |
| 272 | ||
| 273 | template <class _Ret, class _T1> | |
| 274 | struct __enable_invoke_imp<_Ret, _T1, true, true> { | |
| 275 | typedef _Ret _Bullet1; | |
| 276 | typedef _Bullet1 type; | |
| 277 | }; | |
| 278 | ||
| 279 | template <class _Ret, class _T1> | |
| 280 | struct __enable_invoke_imp<_Ret, _T1, true, false> { | |
| 281 | typedef _Ret _Bullet2; | |
| 282 | typedef _Bullet2 type; | |
| 283 | }; | |
| 284 | ||
| 285 | template <class _Ret, class _T1> | |
| 286 | struct __enable_invoke_imp<_Ret, _T1, false, true> { | |
| 287 | typedef typename add_lvalue_reference< | |
| 288 | typename __apply_cv<_T1, _Ret>::type | |
| 289 | >::type _Bullet3; | |
| 290 | typedef _Bullet3 type; | |
| 291 | }; | |
| 292 | ||
| 293 | template <class _Ret, class _T1> | |
| 294 | struct __enable_invoke_imp<_Ret, _T1, false, false> { | |
| 295 | typedef typename add_lvalue_reference< | |
| 296 | typename __apply_cv<decltype(*declval<_T1>()), _Ret>::type | |
| 297 | >::type _Bullet4; | |
| 298 | typedef _Bullet4 type; | |
| 299 | }; | |
| 300 | ||
| 301 | template <class _Ret, class _T1> | |
| 302 | struct __enable_invoke_imp<_Ret, _T1*, false, false> { | |
| 303 | typedef typename add_lvalue_reference< | |
| 304 | typename __apply_cv<_T1, _Ret>::type | |
| 305 | >::type _Bullet4; | |
| 306 | typedef _Bullet4 type; | |
| 307 | }; | |
| 308 | ||
| 309 | template <class _Fn, class _T1, | |
| 310 | class _Traits = __member_pointer_traits<_Fn>, | |
| 311 | class _Ret = typename _Traits::_ReturnType, | |
| 312 | class _Class = typename _Traits::_ClassType> | |
| 313 | struct __enable_invoke : __enable_invoke_imp< | |
| 314 | _Ret, _T1, | |
| 315 | is_member_function_pointer<_Fn>::value, | |
| 316 | is_base_of<_Class, typename remove_reference<_T1>::type>::value> | |
| 317 | { | |
| 318 | }; | |
| 319 | ||
| 320 | __nat __invoke(__any, ...); | |
| 321 | ||
| 322 | // first bullet | |
| 323 | ||
| 324 | template <class _Fn, class _T1> | |
| 325 | inline _LIBCPP_INLINE_VISIBILITY | |
| 326 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 327 | __invoke(_Fn __f, _T1& __t1) { | |
| 328 | return (__t1.*__f)(); | |
| 329 | } | |
| 330 | ||
| 331 | template <class _Fn, class _T1, class _A0> | |
| 332 | inline _LIBCPP_INLINE_VISIBILITY | |
| 333 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 334 | __invoke(_Fn __f, _T1& __t1, _A0& __a0) { | |
| 335 | return (__t1.*__f)(__a0); | |
| 336 | } | |
| 337 | ||
| 338 | template <class _Fn, class _T1, class _A0, class _A1> | |
| 339 | inline _LIBCPP_INLINE_VISIBILITY | |
| 340 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 341 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { | |
| 342 | return (__t1.*__f)(__a0, __a1); | |
| 343 | } | |
| 344 | ||
| 345 | template <class _Fn, class _T1, class _A0, class _A1, class _A2> | |
| 346 | inline _LIBCPP_INLINE_VISIBILITY | |
| 347 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 348 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { | |
| 349 | return (__t1.*__f)(__a0, __a1, __a2); | |
| 350 | } | |
| 351 | ||
| 352 | template <class _Fn, class _T1> | |
| 353 | inline _LIBCPP_INLINE_VISIBILITY | |
| 354 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 355 | __invoke(_Fn __f, _T1& __t1) { | |
| 356 | return ((*__t1).*__f)(); | |
| 357 | } | |
| 358 | ||
| 359 | template <class _Fn, class _T1, class _A0> | |
| 360 | inline _LIBCPP_INLINE_VISIBILITY | |
| 361 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 362 | __invoke(_Fn __f, _T1& __t1, _A0& __a0) { | |
| 363 | return ((*__t1).*__f)(__a0); | |
| 364 | } | |
| 365 | ||
| 366 | template <class _Fn, class _T1, class _A0, class _A1> | |
| 367 | inline _LIBCPP_INLINE_VISIBILITY | |
| 368 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 369 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { | |
| 370 | return ((*__t1).*__f)(__a0, __a1); | |
| 371 | } | |
| 372 | ||
| 373 | template <class _Fn, class _T1, class _A0, class _A1, class _A2> | |
| 374 | inline _LIBCPP_INLINE_VISIBILITY | |
| 375 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 376 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { | |
| 377 | return ((*__t1).*__f)(__a0, __a1, __a2); | |
| 378 | } | |
| 379 | ||
| 380 | template <class _Fn, class _T1> | |
| 381 | inline _LIBCPP_INLINE_VISIBILITY | |
| 382 | typename __enable_invoke<_Fn, _T1>::_Bullet3 | |
| 383 | __invoke(_Fn __f, _T1& __t1) { | |
| 384 | return __t1.*__f; | |
| 385 | } | |
| 386 | ||
| 387 | template <class _Fn, class _T1> | |
| 388 | inline _LIBCPP_INLINE_VISIBILITY | |
| 389 | typename __enable_invoke<_Fn, _T1>::_Bullet4 | |
| 390 | __invoke(_Fn __f, _T1& __t1) { | |
| 391 | return (*__t1).*__f; | |
| 392 | } | |
| 393 | ||
| 394 | // fifth bullet | |
| 395 | ||
| 396 | template <class _Fp> | |
| 397 | inline _LIBCPP_INLINE_VISIBILITY | |
| 398 | decltype(declval<_Fp&>()()) | |
| 399 | __invoke(_Fp& __f) | |
| 400 | { | |
| 401 | return __f(); | |
| 402 | } | |
| 403 | ||
| 404 | template <class _Fp, class _A0> | |
| 405 | inline _LIBCPP_INLINE_VISIBILITY | |
| 406 | decltype(declval<_Fp&>()(declval<_A0&>())) | |
| 407 | __invoke(_Fp& __f, _A0& __a0) | |
| 408 | { | |
| 409 | return __f(__a0); | |
| 410 | } | |
| 411 | ||
| 412 | template <class _Fp, class _A0, class _A1> | |
| 413 | inline _LIBCPP_INLINE_VISIBILITY | |
| 414 | decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>())) | |
| 415 | __invoke(_Fp& __f, _A0& __a0, _A1& __a1) | |
| 416 | { | |
| 417 | return __f(__a0, __a1); | |
| 418 | } | |
| 419 | ||
| 420 | template <class _Fp, class _A0, class _A1, class _A2> | |
| 421 | inline _LIBCPP_INLINE_VISIBILITY | |
| 422 | decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>(), declval<_A2&>())) | |
| 423 | __invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2) | |
| 424 | { | |
| 425 | return __f(__a0, __a1, __a2); | |
| 426 | } | |
| 427 | ||
| 428 | template <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value> | |
| 429 | struct __invoke_return | |
| 430 | { | |
| 431 | typedef typename __weak_result_type<_Fp>::result_type type; | |
| 432 | }; | |
| 433 | ||
| 434 | template <class _Fp> | |
| 435 | struct __invoke_return<_Fp, false> | |
| 436 | { | |
| 437 | typedef decltype(_VSTD::__invoke(declval<_Fp&>())) type; | |
| 438 | }; | |
| 439 | ||
| 440 | template <class _Tp, class _A0> | |
| 441 | struct __invoke_return0 | |
| 442 | { | |
| 443 | typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>())) type; | |
| 444 | }; | |
| 445 | ||
| 446 | template <class _Rp, class _Tp, class _A0> | |
| 447 | struct __invoke_return0<_Rp _Tp::*, _A0> | |
| 448 | { | |
| 449 | typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type; | |
| 450 | }; | |
| 451 | ||
| 452 | template <class _Tp, class _A0, class _A1> | |
| 453 | struct __invoke_return1 | |
| 454 | { | |
| 455 | typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(), | |
| 456 | declval<_A1&>())) type; | |
| 457 | }; | |
| 458 | ||
| 459 | template <class _Rp, class _Class, class _A0, class _A1> | |
| 460 | struct __invoke_return1<_Rp _Class::*, _A0, _A1> { | |
| 461 | typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type; | |
| 462 | }; | |
| 463 | ||
| 464 | template <class _Tp, class _A0, class _A1, class _A2> | |
| 465 | struct __invoke_return2 | |
| 466 | { | |
| 467 | typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(), | |
| 468 | declval<_A1&>(), | |
| 469 | declval<_A2&>())) type; | |
| 470 | }; | |
| 471 | ||
| 472 | template <class _Ret, class _Class, class _A0, class _A1, class _A2> | |
| 473 | struct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> { | |
| 474 | typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type; | |
| 475 | }; | |
| 476 | ||
| 477 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 478 | ||
| 479 | _LIBCPP_END_NAMESPACE_STD | |
| 480 | ||
| 481 | #endif // _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H |
lib/libcxx/include/__functional_03 deleted-1591| ... | ... | @@ -1,1591 +0,0 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP_FUNCTIONAL_03 | |
| 11 | #define _LIBCPP_FUNCTIONAL_03 | |
| 12 | ||
| 13 | // manual variadic expansion for <functional> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | namespace __function { | |
| 20 | ||
| 21 | template<class _Fp> class __base; | |
| 22 | ||
| 23 | template<class _Rp> | |
| 24 | class __base<_Rp()> | |
| 25 | { | |
| 26 | __base(const __base&); | |
| 27 | __base& operator=(const __base&); | |
| 28 | public: | |
| 29 | __base() {} | |
| 30 | virtual ~__base() {} | |
| 31 | virtual __base* __clone() const = 0; | |
| 32 | virtual void __clone(__base*) const = 0; | |
| 33 | virtual void destroy() = 0; | |
| 34 | virtual void destroy_deallocate() = 0; | |
| 35 | virtual _Rp operator()() = 0; | |
| 36 | #ifndef _LIBCPP_NO_RTTI | |
| 37 | virtual const void* target(const type_info&) const = 0; | |
| 38 | virtual const std::type_info& target_type() const = 0; | |
| 39 | #endif // _LIBCPP_NO_RTTI | |
| 40 | }; | |
| 41 | ||
| 42 | template<class _Rp, class _A0> | |
| 43 | class __base<_Rp(_A0)> | |
| 44 | { | |
| 45 | __base(const __base&); | |
| 46 | __base& operator=(const __base&); | |
| 47 | public: | |
| 48 | __base() {} | |
| 49 | virtual ~__base() {} | |
| 50 | virtual __base* __clone() const = 0; | |
| 51 | virtual void __clone(__base*) const = 0; | |
| 52 | virtual void destroy() = 0; | |
| 53 | virtual void destroy_deallocate() = 0; | |
| 54 | virtual _Rp operator()(_A0) = 0; | |
| 55 | #ifndef _LIBCPP_NO_RTTI | |
| 56 | virtual const void* target(const type_info&) const = 0; | |
| 57 | virtual const std::type_info& target_type() const = 0; | |
| 58 | #endif // _LIBCPP_NO_RTTI | |
| 59 | }; | |
| 60 | ||
| 61 | template<class _Rp, class _A0, class _A1> | |
| 62 | class __base<_Rp(_A0, _A1)> | |
| 63 | { | |
| 64 | __base(const __base&); | |
| 65 | __base& operator=(const __base&); | |
| 66 | public: | |
| 67 | __base() {} | |
| 68 | virtual ~__base() {} | |
| 69 | virtual __base* __clone() const = 0; | |
| 70 | virtual void __clone(__base*) const = 0; | |
| 71 | virtual void destroy() = 0; | |
| 72 | virtual void destroy_deallocate() = 0; | |
| 73 | virtual _Rp operator()(_A0, _A1) = 0; | |
| 74 | #ifndef _LIBCPP_NO_RTTI | |
| 75 | virtual const void* target(const type_info&) const = 0; | |
| 76 | virtual const std::type_info& target_type() const = 0; | |
| 77 | #endif // _LIBCPP_NO_RTTI | |
| 78 | }; | |
| 79 | ||
| 80 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 81 | class __base<_Rp(_A0, _A1, _A2)> | |
| 82 | { | |
| 83 | __base(const __base&); | |
| 84 | __base& operator=(const __base&); | |
| 85 | public: | |
| 86 | __base() {} | |
| 87 | virtual ~__base() {} | |
| 88 | virtual __base* __clone() const = 0; | |
| 89 | virtual void __clone(__base*) const = 0; | |
| 90 | virtual void destroy() = 0; | |
| 91 | virtual void destroy_deallocate() = 0; | |
| 92 | virtual _Rp operator()(_A0, _A1, _A2) = 0; | |
| 93 | #ifndef _LIBCPP_NO_RTTI | |
| 94 | virtual const void* target(const type_info&) const = 0; | |
| 95 | virtual const std::type_info& target_type() const = 0; | |
| 96 | #endif // _LIBCPP_NO_RTTI | |
| 97 | }; | |
| 98 | ||
| 99 | template<class _FD, class _Alloc, class _FB> class __func; | |
| 100 | ||
| 101 | template<class _Fp, class _Alloc, class _Rp> | |
| 102 | class __func<_Fp, _Alloc, _Rp()> | |
| 103 | : public __base<_Rp()> | |
| 104 | { | |
| 105 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 106 | public: | |
| 107 | explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 108 | explicit __func(_Fp __f, _Alloc __a) : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 109 | virtual __base<_Rp()>* __clone() const; | |
| 110 | virtual void __clone(__base<_Rp()>*) const; | |
| 111 | virtual void destroy(); | |
| 112 | virtual void destroy_deallocate(); | |
| 113 | virtual _Rp operator()(); | |
| 114 | #ifndef _LIBCPP_NO_RTTI | |
| 115 | virtual const void* target(const type_info&) const; | |
| 116 | virtual const std::type_info& target_type() const; | |
| 117 | #endif // _LIBCPP_NO_RTTI | |
| 118 | }; | |
| 119 | ||
| 120 | template<class _Fp, class _Alloc, class _Rp> | |
| 121 | __base<_Rp()>* | |
| 122 | __func<_Fp, _Alloc, _Rp()>::__clone() const | |
| 123 | { | |
| 124 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 125 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 126 | _Ap __a(__f_.second()); | |
| 127 | typedef __allocator_destructor<_Ap> _Dp; | |
| 128 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 129 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 130 | return __hold.release(); | |
| 131 | } | |
| 132 | ||
| 133 | template<class _Fp, class _Alloc, class _Rp> | |
| 134 | void | |
| 135 | __func<_Fp, _Alloc, _Rp()>::__clone(__base<_Rp()>* __p) const | |
| 136 | { | |
| 137 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 138 | } | |
| 139 | ||
| 140 | template<class _Fp, class _Alloc, class _Rp> | |
| 141 | void | |
| 142 | __func<_Fp, _Alloc, _Rp()>::destroy() | |
| 143 | { | |
| 144 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 145 | } | |
| 146 | ||
| 147 | template<class _Fp, class _Alloc, class _Rp> | |
| 148 | void | |
| 149 | __func<_Fp, _Alloc, _Rp()>::destroy_deallocate() | |
| 150 | { | |
| 151 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 152 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 153 | _Ap __a(__f_.second()); | |
| 154 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 155 | __a.deallocate(this, 1); | |
| 156 | } | |
| 157 | ||
| 158 | template<class _Fp, class _Alloc, class _Rp> | |
| 159 | _Rp | |
| 160 | __func<_Fp, _Alloc, _Rp()>::operator()() | |
| 161 | { | |
| 162 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 163 | return _Invoker::__call(__f_.first()); | |
| 164 | } | |
| 165 | ||
| 166 | #ifndef _LIBCPP_NO_RTTI | |
| 167 | ||
| 168 | template<class _Fp, class _Alloc, class _Rp> | |
| 169 | const void* | |
| 170 | __func<_Fp, _Alloc, _Rp()>::target(const type_info& __ti) const | |
| 171 | { | |
| 172 | if (__ti == typeid(_Fp)) | |
| 173 | return &__f_.first(); | |
| 174 | return (const void*)0; | |
| 175 | } | |
| 176 | ||
| 177 | template<class _Fp, class _Alloc, class _Rp> | |
| 178 | const std::type_info& | |
| 179 | __func<_Fp, _Alloc, _Rp()>::target_type() const | |
| 180 | { | |
| 181 | return typeid(_Fp); | |
| 182 | } | |
| 183 | ||
| 184 | #endif // _LIBCPP_NO_RTTI | |
| 185 | ||
| 186 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 187 | class __func<_Fp, _Alloc, _Rp(_A0)> | |
| 188 | : public __base<_Rp(_A0)> | |
| 189 | { | |
| 190 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 191 | public: | |
| 192 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 193 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) | |
| 194 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 195 | virtual __base<_Rp(_A0)>* __clone() const; | |
| 196 | virtual void __clone(__base<_Rp(_A0)>*) const; | |
| 197 | virtual void destroy(); | |
| 198 | virtual void destroy_deallocate(); | |
| 199 | virtual _Rp operator()(_A0); | |
| 200 | #ifndef _LIBCPP_NO_RTTI | |
| 201 | virtual const void* target(const type_info&) const; | |
| 202 | virtual const std::type_info& target_type() const; | |
| 203 | #endif // _LIBCPP_NO_RTTI | |
| 204 | }; | |
| 205 | ||
| 206 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 207 | __base<_Rp(_A0)>* | |
| 208 | __func<_Fp, _Alloc, _Rp(_A0)>::__clone() const | |
| 209 | { | |
| 210 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 211 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 212 | _Ap __a(__f_.second()); | |
| 213 | typedef __allocator_destructor<_Ap> _Dp; | |
| 214 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 215 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 216 | return __hold.release(); | |
| 217 | } | |
| 218 | ||
| 219 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 220 | void | |
| 221 | __func<_Fp, _Alloc, _Rp(_A0)>::__clone(__base<_Rp(_A0)>* __p) const | |
| 222 | { | |
| 223 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 224 | } | |
| 225 | ||
| 226 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 227 | void | |
| 228 | __func<_Fp, _Alloc, _Rp(_A0)>::destroy() | |
| 229 | { | |
| 230 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 231 | } | |
| 232 | ||
| 233 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 234 | void | |
| 235 | __func<_Fp, _Alloc, _Rp(_A0)>::destroy_deallocate() | |
| 236 | { | |
| 237 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 238 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 239 | _Ap __a(__f_.second()); | |
| 240 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 241 | __a.deallocate(this, 1); | |
| 242 | } | |
| 243 | ||
| 244 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 245 | _Rp | |
| 246 | __func<_Fp, _Alloc, _Rp(_A0)>::operator()(_A0 __a0) | |
| 247 | { | |
| 248 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 249 | return _Invoker::__call(__f_.first(), __a0); | |
| 250 | } | |
| 251 | ||
| 252 | #ifndef _LIBCPP_NO_RTTI | |
| 253 | ||
| 254 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 255 | const void* | |
| 256 | __func<_Fp, _Alloc, _Rp(_A0)>::target(const type_info& __ti) const | |
| 257 | { | |
| 258 | if (__ti == typeid(_Fp)) | |
| 259 | return &__f_.first(); | |
| 260 | return (const void*)0; | |
| 261 | } | |
| 262 | ||
| 263 | template<class _Fp, class _Alloc, class _Rp, class _A0> | |
| 264 | const std::type_info& | |
| 265 | __func<_Fp, _Alloc, _Rp(_A0)>::target_type() const | |
| 266 | { | |
| 267 | return typeid(_Fp); | |
| 268 | } | |
| 269 | ||
| 270 | #endif // _LIBCPP_NO_RTTI | |
| 271 | ||
| 272 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 273 | class __func<_Fp, _Alloc, _Rp(_A0, _A1)> | |
| 274 | : public __base<_Rp(_A0, _A1)> | |
| 275 | { | |
| 276 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 277 | public: | |
| 278 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 279 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) | |
| 280 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 281 | virtual __base<_Rp(_A0, _A1)>* __clone() const; | |
| 282 | virtual void __clone(__base<_Rp(_A0, _A1)>*) const; | |
| 283 | virtual void destroy(); | |
| 284 | virtual void destroy_deallocate(); | |
| 285 | virtual _Rp operator()(_A0, _A1); | |
| 286 | #ifndef _LIBCPP_NO_RTTI | |
| 287 | virtual const void* target(const type_info&) const; | |
| 288 | virtual const std::type_info& target_type() const; | |
| 289 | #endif // _LIBCPP_NO_RTTI | |
| 290 | }; | |
| 291 | ||
| 292 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 293 | __base<_Rp(_A0, _A1)>* | |
| 294 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone() const | |
| 295 | { | |
| 296 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 297 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 298 | _Ap __a(__f_.second()); | |
| 299 | typedef __allocator_destructor<_Ap> _Dp; | |
| 300 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 301 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 302 | return __hold.release(); | |
| 303 | } | |
| 304 | ||
| 305 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 306 | void | |
| 307 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone(__base<_Rp(_A0, _A1)>* __p) const | |
| 308 | { | |
| 309 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 310 | } | |
| 311 | ||
| 312 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 313 | void | |
| 314 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy() | |
| 315 | { | |
| 316 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 317 | } | |
| 318 | ||
| 319 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 320 | void | |
| 321 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy_deallocate() | |
| 322 | { | |
| 323 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 324 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 325 | _Ap __a(__f_.second()); | |
| 326 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 327 | __a.deallocate(this, 1); | |
| 328 | } | |
| 329 | ||
| 330 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 331 | _Rp | |
| 332 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) | |
| 333 | { | |
| 334 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 335 | return _Invoker::__call(__f_.first(), __a0, __a1); | |
| 336 | } | |
| 337 | ||
| 338 | #ifndef _LIBCPP_NO_RTTI | |
| 339 | ||
| 340 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 341 | const void* | |
| 342 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::target(const type_info& __ti) const | |
| 343 | { | |
| 344 | if (__ti == typeid(_Fp)) | |
| 345 | return &__f_.first(); | |
| 346 | return (const void*)0; | |
| 347 | } | |
| 348 | ||
| 349 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> | |
| 350 | const std::type_info& | |
| 351 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::target_type() const | |
| 352 | { | |
| 353 | return typeid(_Fp); | |
| 354 | } | |
| 355 | ||
| 356 | #endif // _LIBCPP_NO_RTTI | |
| 357 | ||
| 358 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 359 | class __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> | |
| 360 | : public __base<_Rp(_A0, _A1, _A2)> | |
| 361 | { | |
| 362 | __compressed_pair<_Fp, _Alloc> __f_; | |
| 363 | public: | |
| 364 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f), __default_init_tag()) {} | |
| 365 | _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) | |
| 366 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 367 | virtual __base<_Rp(_A0, _A1, _A2)>* __clone() const; | |
| 368 | virtual void __clone(__base<_Rp(_A0, _A1, _A2)>*) const; | |
| 369 | virtual void destroy(); | |
| 370 | virtual void destroy_deallocate(); | |
| 371 | virtual _Rp operator()(_A0, _A1, _A2); | |
| 372 | #ifndef _LIBCPP_NO_RTTI | |
| 373 | virtual const void* target(const type_info&) const; | |
| 374 | virtual const std::type_info& target_type() const; | |
| 375 | #endif // _LIBCPP_NO_RTTI | |
| 376 | }; | |
| 377 | ||
| 378 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 379 | __base<_Rp(_A0, _A1, _A2)>* | |
| 380 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone() const | |
| 381 | { | |
| 382 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 383 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 384 | _Ap __a(__f_.second()); | |
| 385 | typedef __allocator_destructor<_Ap> _Dp; | |
| 386 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 387 | ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a)); | |
| 388 | return __hold.release(); | |
| 389 | } | |
| 390 | ||
| 391 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 392 | void | |
| 393 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone(__base<_Rp(_A0, _A1, _A2)>* __p) const | |
| 394 | { | |
| 395 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); | |
| 396 | } | |
| 397 | ||
| 398 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 399 | void | |
| 400 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy() | |
| 401 | { | |
| 402 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 403 | } | |
| 404 | ||
| 405 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 406 | void | |
| 407 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy_deallocate() | |
| 408 | { | |
| 409 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 410 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 411 | _Ap __a(__f_.second()); | |
| 412 | __f_.~__compressed_pair<_Fp, _Alloc>(); | |
| 413 | __a.deallocate(this, 1); | |
| 414 | } | |
| 415 | ||
| 416 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 417 | _Rp | |
| 418 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) | |
| 419 | { | |
| 420 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 421 | return _Invoker::__call(__f_.first(), __a0, __a1, __a2); | |
| 422 | } | |
| 423 | ||
| 424 | #ifndef _LIBCPP_NO_RTTI | |
| 425 | ||
| 426 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 427 | const void* | |
| 428 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target(const type_info& __ti) const | |
| 429 | { | |
| 430 | if (__ti == typeid(_Fp)) | |
| 431 | return &__f_.first(); | |
| 432 | return (const void*)0; | |
| 433 | } | |
| 434 | ||
| 435 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> | |
| 436 | const std::type_info& | |
| 437 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target_type() const | |
| 438 | { | |
| 439 | return typeid(_Fp); | |
| 440 | } | |
| 441 | ||
| 442 | #endif // _LIBCPP_NO_RTTI | |
| 443 | ||
| 444 | } // __function | |
| 445 | ||
| 446 | template<class _Rp> | |
| 447 | class _LIBCPP_TEMPLATE_VIS function<_Rp()> | |
| 448 | { | |
| 449 | typedef __function::__base<_Rp()> __base; | |
| 450 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 451 | __base* __f_; | |
| 452 | ||
| 453 | public: | |
| 454 | typedef _Rp result_type; | |
| 455 | ||
| 456 | // 20.7.16.2.1, construct/copy/destroy: | |
| 457 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 458 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 459 | function(const function&); | |
| 460 | template<class _Fp> | |
| 461 | function(_Fp, | |
| 462 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 463 | ||
| 464 | template<class _Alloc> | |
| 465 | _LIBCPP_INLINE_VISIBILITY | |
| 466 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 467 | template<class _Alloc> | |
| 468 | _LIBCPP_INLINE_VISIBILITY | |
| 469 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 470 | template<class _Alloc> | |
| 471 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 472 | template<class _Fp, class _Alloc> | |
| 473 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 474 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 475 | ||
| 476 | function& operator=(const function&); | |
| 477 | function& operator=(nullptr_t); | |
| 478 | template<class _Fp> | |
| 479 | typename enable_if | |
| 480 | < | |
| 481 | !is_integral<_Fp>::value, | |
| 482 | function& | |
| 483 | >::type | |
| 484 | operator=(_Fp); | |
| 485 | ||
| 486 | ~function(); | |
| 487 | ||
| 488 | // 20.7.16.2.2, function modifiers: | |
| 489 | void swap(function&); | |
| 490 | template<class _Fp, class _Alloc> | |
| 491 | _LIBCPP_INLINE_VISIBILITY | |
| 492 | void assign(_Fp __f, const _Alloc& __a) | |
| 493 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 494 | ||
| 495 | // 20.7.16.2.3, function capacity: | |
| 496 | _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;} | |
| 497 | ||
| 498 | private: | |
| 499 | // deleted overloads close possible hole in the type system | |
| 500 | template<class _R2> | |
| 501 | bool operator==(const function<_R2()>&) const;// = delete; | |
| 502 | template<class _R2> | |
| 503 | bool operator!=(const function<_R2()>&) const;// = delete; | |
| 504 | public: | |
| 505 | // 20.7.16.2.4, function invocation: | |
| 506 | _Rp operator()() const; | |
| 507 | ||
| 508 | #ifndef _LIBCPP_NO_RTTI | |
| 509 | // 20.7.16.2.5, function target access: | |
| 510 | const std::type_info& target_type() const; | |
| 511 | template <typename _Tp> _Tp* target(); | |
| 512 | template <typename _Tp> const _Tp* target() const; | |
| 513 | #endif // _LIBCPP_NO_RTTI | |
| 514 | }; | |
| 515 | ||
| 516 | template<class _Rp> | |
| 517 | function<_Rp()>::function(const function& __f) | |
| 518 | { | |
| 519 | if (__f.__f_ == 0) | |
| 520 | __f_ = 0; | |
| 521 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 522 | { | |
| 523 | __f_ = (__base*)&__buf_; | |
| 524 | __f.__f_->__clone(__f_); | |
| 525 | } | |
| 526 | else | |
| 527 | __f_ = __f.__f_->__clone(); | |
| 528 | } | |
| 529 | ||
| 530 | template<class _Rp> | |
| 531 | template<class _Alloc> | |
| 532 | function<_Rp()>::function(allocator_arg_t, const _Alloc&, const function& __f) | |
| 533 | { | |
| 534 | if (__f.__f_ == 0) | |
| 535 | __f_ = 0; | |
| 536 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 537 | { | |
| 538 | __f_ = (__base*)&__buf_; | |
| 539 | __f.__f_->__clone(__f_); | |
| 540 | } | |
| 541 | else | |
| 542 | __f_ = __f.__f_->__clone(); | |
| 543 | } | |
| 544 | ||
| 545 | template<class _Rp> | |
| 546 | template <class _Fp> | |
| 547 | function<_Rp()>::function(_Fp __f, | |
| 548 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 549 | : __f_(0) | |
| 550 | { | |
| 551 | if (__function::__not_null(__f)) | |
| 552 | { | |
| 553 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp()> _FF; | |
| 554 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 555 | { | |
| 556 | __f_ = (__base*)&__buf_; | |
| 557 | ::new ((void*)__f_) _FF(__f); | |
| 558 | } | |
| 559 | else | |
| 560 | { | |
| 561 | typedef allocator<_FF> _Ap; | |
| 562 | _Ap __a; | |
| 563 | typedef __allocator_destructor<_Ap> _Dp; | |
| 564 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 565 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 566 | __f_ = __hold.release(); | |
| 567 | } | |
| 568 | } | |
| 569 | } | |
| 570 | ||
| 571 | template<class _Rp> | |
| 572 | template <class _Fp, class _Alloc> | |
| 573 | function<_Rp()>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 574 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 575 | : __f_(0) | |
| 576 | { | |
| 577 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 578 | if (__function::__not_null(__f)) | |
| 579 | { | |
| 580 | typedef __function::__func<_Fp, _Alloc, _Rp()> _FF; | |
| 581 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 582 | { | |
| 583 | __f_ = (__base*)&__buf_; | |
| 584 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 585 | } | |
| 586 | else | |
| 587 | { | |
| 588 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 589 | _Ap __a(__a0); | |
| 590 | typedef __allocator_destructor<_Ap> _Dp; | |
| 591 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 592 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 593 | __f_ = __hold.release(); | |
| 594 | } | |
| 595 | } | |
| 596 | } | |
| 597 | ||
| 598 | template<class _Rp> | |
| 599 | function<_Rp()>& | |
| 600 | function<_Rp()>::operator=(const function& __f) | |
| 601 | { | |
| 602 | if (__f) | |
| 603 | function(__f).swap(*this); | |
| 604 | else | |
| 605 | *this = nullptr; | |
| 606 | return *this; | |
| 607 | } | |
| 608 | ||
| 609 | template<class _Rp> | |
| 610 | function<_Rp()>& | |
| 611 | function<_Rp()>::operator=(nullptr_t) | |
| 612 | { | |
| 613 | __base* __t = __f_; | |
| 614 | __f_ = 0; | |
| 615 | if (__t == (__base*)&__buf_) | |
| 616 | __t->destroy(); | |
| 617 | else if (__t) | |
| 618 | __t->destroy_deallocate(); | |
| 619 | return *this; | |
| 620 | } | |
| 621 | ||
| 622 | template<class _Rp> | |
| 623 | template <class _Fp> | |
| 624 | typename enable_if | |
| 625 | < | |
| 626 | !is_integral<_Fp>::value, | |
| 627 | function<_Rp()>& | |
| 628 | >::type | |
| 629 | function<_Rp()>::operator=(_Fp __f) | |
| 630 | { | |
| 631 | function(_VSTD::move(__f)).swap(*this); | |
| 632 | return *this; | |
| 633 | } | |
| 634 | ||
| 635 | template<class _Rp> | |
| 636 | function<_Rp()>::~function() | |
| 637 | { | |
| 638 | if (__f_ == (__base*)&__buf_) | |
| 639 | __f_->destroy(); | |
| 640 | else if (__f_) | |
| 641 | __f_->destroy_deallocate(); | |
| 642 | } | |
| 643 | ||
| 644 | template<class _Rp> | |
| 645 | void | |
| 646 | function<_Rp()>::swap(function& __f) | |
| 647 | { | |
| 648 | if (_VSTD::addressof(__f) == this) | |
| 649 | return; | |
| 650 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 651 | { | |
| 652 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 653 | __base* __t = (__base*)&__tempbuf; | |
| 654 | __f_->__clone(__t); | |
| 655 | __f_->destroy(); | |
| 656 | __f_ = 0; | |
| 657 | __f.__f_->__clone((__base*)&__buf_); | |
| 658 | __f.__f_->destroy(); | |
| 659 | __f.__f_ = 0; | |
| 660 | __f_ = (__base*)&__buf_; | |
| 661 | __t->__clone((__base*)&__f.__buf_); | |
| 662 | __t->destroy(); | |
| 663 | __f.__f_ = (__base*)&__f.__buf_; | |
| 664 | } | |
| 665 | else if (__f_ == (__base*)&__buf_) | |
| 666 | { | |
| 667 | __f_->__clone((__base*)&__f.__buf_); | |
| 668 | __f_->destroy(); | |
| 669 | __f_ = __f.__f_; | |
| 670 | __f.__f_ = (__base*)&__f.__buf_; | |
| 671 | } | |
| 672 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 673 | { | |
| 674 | __f.__f_->__clone((__base*)&__buf_); | |
| 675 | __f.__f_->destroy(); | |
| 676 | __f.__f_ = __f_; | |
| 677 | __f_ = (__base*)&__buf_; | |
| 678 | } | |
| 679 | else | |
| 680 | _VSTD::swap(__f_, __f.__f_); | |
| 681 | } | |
| 682 | ||
| 683 | template<class _Rp> | |
| 684 | _Rp | |
| 685 | function<_Rp()>::operator()() const | |
| 686 | { | |
| 687 | if (__f_ == 0) | |
| 688 | __throw_bad_function_call(); | |
| 689 | return (*__f_)(); | |
| 690 | } | |
| 691 | ||
| 692 | #ifndef _LIBCPP_NO_RTTI | |
| 693 | ||
| 694 | template<class _Rp> | |
| 695 | const std::type_info& | |
| 696 | function<_Rp()>::target_type() const | |
| 697 | { | |
| 698 | if (__f_ == 0) | |
| 699 | return typeid(void); | |
| 700 | return __f_->target_type(); | |
| 701 | } | |
| 702 | ||
| 703 | template<class _Rp> | |
| 704 | template <typename _Tp> | |
| 705 | _Tp* | |
| 706 | function<_Rp()>::target() | |
| 707 | { | |
| 708 | if (__f_ == 0) | |
| 709 | return (_Tp*)0; | |
| 710 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 711 | } | |
| 712 | ||
| 713 | template<class _Rp> | |
| 714 | template <typename _Tp> | |
| 715 | const _Tp* | |
| 716 | function<_Rp()>::target() const | |
| 717 | { | |
| 718 | if (__f_ == 0) | |
| 719 | return (const _Tp*)0; | |
| 720 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 721 | } | |
| 722 | ||
| 723 | #endif // _LIBCPP_NO_RTTI | |
| 724 | ||
| 725 | template<class _Rp, class _A0> | |
| 726 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_A0)> | |
| 727 | : public unary_function<_A0, _Rp> | |
| 728 | { | |
| 729 | typedef __function::__base<_Rp(_A0)> __base; | |
| 730 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 731 | __base* __f_; | |
| 732 | ||
| 733 | public: | |
| 734 | typedef _Rp result_type; | |
| 735 | ||
| 736 | // 20.7.16.2.1, construct/copy/destroy: | |
| 737 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 738 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 739 | function(const function&); | |
| 740 | template<class _Fp> | |
| 741 | function(_Fp, | |
| 742 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 743 | ||
| 744 | template<class _Alloc> | |
| 745 | _LIBCPP_INLINE_VISIBILITY | |
| 746 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 747 | template<class _Alloc> | |
| 748 | _LIBCPP_INLINE_VISIBILITY | |
| 749 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 750 | template<class _Alloc> | |
| 751 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 752 | template<class _Fp, class _Alloc> | |
| 753 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 754 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 755 | ||
| 756 | function& operator=(const function&); | |
| 757 | function& operator=(nullptr_t); | |
| 758 | template<class _Fp> | |
| 759 | typename enable_if | |
| 760 | < | |
| 761 | !is_integral<_Fp>::value, | |
| 762 | function& | |
| 763 | >::type | |
| 764 | operator=(_Fp); | |
| 765 | ||
| 766 | ~function(); | |
| 767 | ||
| 768 | // 20.7.16.2.2, function modifiers: | |
| 769 | void swap(function&); | |
| 770 | template<class _Fp, class _Alloc> | |
| 771 | _LIBCPP_INLINE_VISIBILITY | |
| 772 | void assign(_Fp __f, const _Alloc& __a) | |
| 773 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 774 | ||
| 775 | // 20.7.16.2.3, function capacity: | |
| 776 | _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;} | |
| 777 | ||
| 778 | private: | |
| 779 | // deleted overloads close possible hole in the type system | |
| 780 | template<class _R2, class _B0> | |
| 781 | bool operator==(const function<_R2(_B0)>&) const;// = delete; | |
| 782 | template<class _R2, class _B0> | |
| 783 | bool operator!=(const function<_R2(_B0)>&) const;// = delete; | |
| 784 | public: | |
| 785 | // 20.7.16.2.4, function invocation: | |
| 786 | _Rp operator()(_A0) const; | |
| 787 | ||
| 788 | #ifndef _LIBCPP_NO_RTTI | |
| 789 | // 20.7.16.2.5, function target access: | |
| 790 | const std::type_info& target_type() const; | |
| 791 | template <typename _Tp> _Tp* target(); | |
| 792 | template <typename _Tp> const _Tp* target() const; | |
| 793 | #endif // _LIBCPP_NO_RTTI | |
| 794 | }; | |
| 795 | ||
| 796 | template<class _Rp, class _A0> | |
| 797 | function<_Rp(_A0)>::function(const function& __f) | |
| 798 | { | |
| 799 | if (__f.__f_ == 0) | |
| 800 | __f_ = 0; | |
| 801 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 802 | { | |
| 803 | __f_ = (__base*)&__buf_; | |
| 804 | __f.__f_->__clone(__f_); | |
| 805 | } | |
| 806 | else | |
| 807 | __f_ = __f.__f_->__clone(); | |
| 808 | } | |
| 809 | ||
| 810 | template<class _Rp, class _A0> | |
| 811 | template<class _Alloc> | |
| 812 | function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc&, const function& __f) | |
| 813 | { | |
| 814 | if (__f.__f_ == 0) | |
| 815 | __f_ = 0; | |
| 816 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 817 | { | |
| 818 | __f_ = (__base*)&__buf_; | |
| 819 | __f.__f_->__clone(__f_); | |
| 820 | } | |
| 821 | else | |
| 822 | __f_ = __f.__f_->__clone(); | |
| 823 | } | |
| 824 | ||
| 825 | template<class _Rp, class _A0> | |
| 826 | template <class _Fp> | |
| 827 | function<_Rp(_A0)>::function(_Fp __f, | |
| 828 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 829 | : __f_(0) | |
| 830 | { | |
| 831 | if (__function::__not_null(__f)) | |
| 832 | { | |
| 833 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0)> _FF; | |
| 834 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 835 | { | |
| 836 | __f_ = (__base*)&__buf_; | |
| 837 | ::new ((void*)__f_) _FF(__f); | |
| 838 | } | |
| 839 | else | |
| 840 | { | |
| 841 | typedef allocator<_FF> _Ap; | |
| 842 | _Ap __a; | |
| 843 | typedef __allocator_destructor<_Ap> _Dp; | |
| 844 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 845 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 846 | __f_ = __hold.release(); | |
| 847 | } | |
| 848 | } | |
| 849 | } | |
| 850 | ||
| 851 | template<class _Rp, class _A0> | |
| 852 | template <class _Fp, class _Alloc> | |
| 853 | function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 854 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 855 | : __f_(0) | |
| 856 | { | |
| 857 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 858 | if (__function::__not_null(__f)) | |
| 859 | { | |
| 860 | typedef __function::__func<_Fp, _Alloc, _Rp(_A0)> _FF; | |
| 861 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 862 | { | |
| 863 | __f_ = (__base*)&__buf_; | |
| 864 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 865 | } | |
| 866 | else | |
| 867 | { | |
| 868 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 869 | _Ap __a(__a0); | |
| 870 | typedef __allocator_destructor<_Ap> _Dp; | |
| 871 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 872 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 873 | __f_ = __hold.release(); | |
| 874 | } | |
| 875 | } | |
| 876 | } | |
| 877 | ||
| 878 | template<class _Rp, class _A0> | |
| 879 | function<_Rp(_A0)>& | |
| 880 | function<_Rp(_A0)>::operator=(const function& __f) | |
| 881 | { | |
| 882 | if (__f) | |
| 883 | function(__f).swap(*this); | |
| 884 | else | |
| 885 | *this = nullptr; | |
| 886 | return *this; | |
| 887 | } | |
| 888 | ||
| 889 | template<class _Rp, class _A0> | |
| 890 | function<_Rp(_A0)>& | |
| 891 | function<_Rp(_A0)>::operator=(nullptr_t) | |
| 892 | { | |
| 893 | __base* __t = __f_; | |
| 894 | __f_ = 0; | |
| 895 | if (__t == (__base*)&__buf_) | |
| 896 | __t->destroy(); | |
| 897 | else if (__t) | |
| 898 | __t->destroy_deallocate(); | |
| 899 | return *this; | |
| 900 | } | |
| 901 | ||
| 902 | template<class _Rp, class _A0> | |
| 903 | template <class _Fp> | |
| 904 | typename enable_if | |
| 905 | < | |
| 906 | !is_integral<_Fp>::value, | |
| 907 | function<_Rp(_A0)>& | |
| 908 | >::type | |
| 909 | function<_Rp(_A0)>::operator=(_Fp __f) | |
| 910 | { | |
| 911 | function(_VSTD::move(__f)).swap(*this); | |
| 912 | return *this; | |
| 913 | } | |
| 914 | ||
| 915 | template<class _Rp, class _A0> | |
| 916 | function<_Rp(_A0)>::~function() | |
| 917 | { | |
| 918 | if (__f_ == (__base*)&__buf_) | |
| 919 | __f_->destroy(); | |
| 920 | else if (__f_) | |
| 921 | __f_->destroy_deallocate(); | |
| 922 | } | |
| 923 | ||
| 924 | template<class _Rp, class _A0> | |
| 925 | void | |
| 926 | function<_Rp(_A0)>::swap(function& __f) | |
| 927 | { | |
| 928 | if (_VSTD::addressof(__f) == this) | |
| 929 | return; | |
| 930 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 931 | { | |
| 932 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 933 | __base* __t = (__base*)&__tempbuf; | |
| 934 | __f_->__clone(__t); | |
| 935 | __f_->destroy(); | |
| 936 | __f_ = 0; | |
| 937 | __f.__f_->__clone((__base*)&__buf_); | |
| 938 | __f.__f_->destroy(); | |
| 939 | __f.__f_ = 0; | |
| 940 | __f_ = (__base*)&__buf_; | |
| 941 | __t->__clone((__base*)&__f.__buf_); | |
| 942 | __t->destroy(); | |
| 943 | __f.__f_ = (__base*)&__f.__buf_; | |
| 944 | } | |
| 945 | else if (__f_ == (__base*)&__buf_) | |
| 946 | { | |
| 947 | __f_->__clone((__base*)&__f.__buf_); | |
| 948 | __f_->destroy(); | |
| 949 | __f_ = __f.__f_; | |
| 950 | __f.__f_ = (__base*)&__f.__buf_; | |
| 951 | } | |
| 952 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 953 | { | |
| 954 | __f.__f_->__clone((__base*)&__buf_); | |
| 955 | __f.__f_->destroy(); | |
| 956 | __f.__f_ = __f_; | |
| 957 | __f_ = (__base*)&__buf_; | |
| 958 | } | |
| 959 | else | |
| 960 | _VSTD::swap(__f_, __f.__f_); | |
| 961 | } | |
| 962 | ||
| 963 | template<class _Rp, class _A0> | |
| 964 | _Rp | |
| 965 | function<_Rp(_A0)>::operator()(_A0 __a0) const | |
| 966 | { | |
| 967 | if (__f_ == 0) | |
| 968 | __throw_bad_function_call(); | |
| 969 | return (*__f_)(__a0); | |
| 970 | } | |
| 971 | ||
| 972 | #ifndef _LIBCPP_NO_RTTI | |
| 973 | ||
| 974 | template<class _Rp, class _A0> | |
| 975 | const std::type_info& | |
| 976 | function<_Rp(_A0)>::target_type() const | |
| 977 | { | |
| 978 | if (__f_ == 0) | |
| 979 | return typeid(void); | |
| 980 | return __f_->target_type(); | |
| 981 | } | |
| 982 | ||
| 983 | template<class _Rp, class _A0> | |
| 984 | template <typename _Tp> | |
| 985 | _Tp* | |
| 986 | function<_Rp(_A0)>::target() | |
| 987 | { | |
| 988 | if (__f_ == 0) | |
| 989 | return (_Tp*)0; | |
| 990 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 991 | } | |
| 992 | ||
| 993 | template<class _Rp, class _A0> | |
| 994 | template <typename _Tp> | |
| 995 | const _Tp* | |
| 996 | function<_Rp(_A0)>::target() const | |
| 997 | { | |
| 998 | if (__f_ == 0) | |
| 999 | return (const _Tp*)0; | |
| 1000 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 1001 | } | |
| 1002 | ||
| 1003 | #endif // _LIBCPP_NO_RTTI | |
| 1004 | ||
| 1005 | template<class _Rp, class _A0, class _A1> | |
| 1006 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_A0, _A1)> | |
| 1007 | : public binary_function<_A0, _A1, _Rp> | |
| 1008 | { | |
| 1009 | typedef __function::__base<_Rp(_A0, _A1)> __base; | |
| 1010 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 1011 | __base* __f_; | |
| 1012 | ||
| 1013 | public: | |
| 1014 | typedef _Rp result_type; | |
| 1015 | ||
| 1016 | // 20.7.16.2.1, construct/copy/destroy: | |
| 1017 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 1018 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 1019 | function(const function&); | |
| 1020 | template<class _Fp> | |
| 1021 | function(_Fp, | |
| 1022 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1023 | ||
| 1024 | template<class _Alloc> | |
| 1025 | _LIBCPP_INLINE_VISIBILITY | |
| 1026 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 1027 | template<class _Alloc> | |
| 1028 | _LIBCPP_INLINE_VISIBILITY | |
| 1029 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 1030 | template<class _Alloc> | |
| 1031 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 1032 | template<class _Fp, class _Alloc> | |
| 1033 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 1034 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1035 | ||
| 1036 | function& operator=(const function&); | |
| 1037 | function& operator=(nullptr_t); | |
| 1038 | template<class _Fp> | |
| 1039 | typename enable_if | |
| 1040 | < | |
| 1041 | !is_integral<_Fp>::value, | |
| 1042 | function& | |
| 1043 | >::type | |
| 1044 | operator=(_Fp); | |
| 1045 | ||
| 1046 | ~function(); | |
| 1047 | ||
| 1048 | // 20.7.16.2.2, function modifiers: | |
| 1049 | void swap(function&); | |
| 1050 | template<class _Fp, class _Alloc> | |
| 1051 | _LIBCPP_INLINE_VISIBILITY | |
| 1052 | void assign(_Fp __f, const _Alloc& __a) | |
| 1053 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 1054 | ||
| 1055 | // 20.7.16.2.3, function capacity: | |
| 1056 | operator bool() const {return __f_;} | |
| 1057 | ||
| 1058 | private: | |
| 1059 | // deleted overloads close possible hole in the type system | |
| 1060 | template<class _R2, class _B0, class _B1> | |
| 1061 | bool operator==(const function<_R2(_B0, _B1)>&) const;// = delete; | |
| 1062 | template<class _R2, class _B0, class _B1> | |
| 1063 | bool operator!=(const function<_R2(_B0, _B1)>&) const;// = delete; | |
| 1064 | public: | |
| 1065 | // 20.7.16.2.4, function invocation: | |
| 1066 | _Rp operator()(_A0, _A1) const; | |
| 1067 | ||
| 1068 | #ifndef _LIBCPP_NO_RTTI | |
| 1069 | // 20.7.16.2.5, function target access: | |
| 1070 | const std::type_info& target_type() const; | |
| 1071 | template <typename _Tp> _Tp* target(); | |
| 1072 | template <typename _Tp> const _Tp* target() const; | |
| 1073 | #endif // _LIBCPP_NO_RTTI | |
| 1074 | }; | |
| 1075 | ||
| 1076 | template<class _Rp, class _A0, class _A1> | |
| 1077 | function<_Rp(_A0, _A1)>::function(const function& __f) | |
| 1078 | { | |
| 1079 | if (__f.__f_ == 0) | |
| 1080 | __f_ = 0; | |
| 1081 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 1082 | { | |
| 1083 | __f_ = (__base*)&__buf_; | |
| 1084 | __f.__f_->__clone(__f_); | |
| 1085 | } | |
| 1086 | else | |
| 1087 | __f_ = __f.__f_->__clone(); | |
| 1088 | } | |
| 1089 | ||
| 1090 | template<class _Rp, class _A0, class _A1> | |
| 1091 | template<class _Alloc> | |
| 1092 | function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc&, const function& __f) | |
| 1093 | { | |
| 1094 | if (__f.__f_ == 0) | |
| 1095 | __f_ = 0; | |
| 1096 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 1097 | { | |
| 1098 | __f_ = (__base*)&__buf_; | |
| 1099 | __f.__f_->__clone(__f_); | |
| 1100 | } | |
| 1101 | else | |
| 1102 | __f_ = __f.__f_->__clone(); | |
| 1103 | } | |
| 1104 | ||
| 1105 | template<class _Rp, class _A0, class _A1> | |
| 1106 | template <class _Fp> | |
| 1107 | function<_Rp(_A0, _A1)>::function(_Fp __f, | |
| 1108 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 1109 | : __f_(0) | |
| 1110 | { | |
| 1111 | if (__function::__not_null(__f)) | |
| 1112 | { | |
| 1113 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1)> _FF; | |
| 1114 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 1115 | { | |
| 1116 | __f_ = (__base*)&__buf_; | |
| 1117 | ::new ((void*)__f_) _FF(__f); | |
| 1118 | } | |
| 1119 | else | |
| 1120 | { | |
| 1121 | typedef allocator<_FF> _Ap; | |
| 1122 | _Ap __a; | |
| 1123 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1124 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1125 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 1126 | __f_ = __hold.release(); | |
| 1127 | } | |
| 1128 | } | |
| 1129 | } | |
| 1130 | ||
| 1131 | template<class _Rp, class _A0, class _A1> | |
| 1132 | template <class _Fp, class _Alloc> | |
| 1133 | function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 1134 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 1135 | : __f_(0) | |
| 1136 | { | |
| 1137 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1138 | if (__function::__not_null(__f)) | |
| 1139 | { | |
| 1140 | typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1)> _FF; | |
| 1141 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 1142 | { | |
| 1143 | __f_ = (__base*)&__buf_; | |
| 1144 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 1145 | } | |
| 1146 | else | |
| 1147 | { | |
| 1148 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 1149 | _Ap __a(__a0); | |
| 1150 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1151 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1152 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 1153 | __f_ = __hold.release(); | |
| 1154 | } | |
| 1155 | } | |
| 1156 | } | |
| 1157 | ||
| 1158 | template<class _Rp, class _A0, class _A1> | |
| 1159 | function<_Rp(_A0, _A1)>& | |
| 1160 | function<_Rp(_A0, _A1)>::operator=(const function& __f) | |
| 1161 | { | |
| 1162 | if (__f) | |
| 1163 | function(__f).swap(*this); | |
| 1164 | else | |
| 1165 | *this = nullptr; | |
| 1166 | return *this; | |
| 1167 | } | |
| 1168 | ||
| 1169 | template<class _Rp, class _A0, class _A1> | |
| 1170 | function<_Rp(_A0, _A1)>& | |
| 1171 | function<_Rp(_A0, _A1)>::operator=(nullptr_t) | |
| 1172 | { | |
| 1173 | __base* __t = __f_; | |
| 1174 | __f_ = 0; | |
| 1175 | if (__t == (__base*)&__buf_) | |
| 1176 | __t->destroy(); | |
| 1177 | else if (__t) | |
| 1178 | __t->destroy_deallocate(); | |
| 1179 | return *this; | |
| 1180 | } | |
| 1181 | ||
| 1182 | template<class _Rp, class _A0, class _A1> | |
| 1183 | template <class _Fp> | |
| 1184 | typename enable_if | |
| 1185 | < | |
| 1186 | !is_integral<_Fp>::value, | |
| 1187 | function<_Rp(_A0, _A1)>& | |
| 1188 | >::type | |
| 1189 | function<_Rp(_A0, _A1)>::operator=(_Fp __f) | |
| 1190 | { | |
| 1191 | function(_VSTD::move(__f)).swap(*this); | |
| 1192 | return *this; | |
| 1193 | } | |
| 1194 | ||
| 1195 | template<class _Rp, class _A0, class _A1> | |
| 1196 | function<_Rp(_A0, _A1)>::~function() | |
| 1197 | { | |
| 1198 | if (__f_ == (__base*)&__buf_) | |
| 1199 | __f_->destroy(); | |
| 1200 | else if (__f_) | |
| 1201 | __f_->destroy_deallocate(); | |
| 1202 | } | |
| 1203 | ||
| 1204 | template<class _Rp, class _A0, class _A1> | |
| 1205 | void | |
| 1206 | function<_Rp(_A0, _A1)>::swap(function& __f) | |
| 1207 | { | |
| 1208 | if (_VSTD::addressof(__f) == this) | |
| 1209 | return; | |
| 1210 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 1211 | { | |
| 1212 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 1213 | __base* __t = (__base*)&__tempbuf; | |
| 1214 | __f_->__clone(__t); | |
| 1215 | __f_->destroy(); | |
| 1216 | __f_ = 0; | |
| 1217 | __f.__f_->__clone((__base*)&__buf_); | |
| 1218 | __f.__f_->destroy(); | |
| 1219 | __f.__f_ = 0; | |
| 1220 | __f_ = (__base*)&__buf_; | |
| 1221 | __t->__clone((__base*)&__f.__buf_); | |
| 1222 | __t->destroy(); | |
| 1223 | __f.__f_ = (__base*)&__f.__buf_; | |
| 1224 | } | |
| 1225 | else if (__f_ == (__base*)&__buf_) | |
| 1226 | { | |
| 1227 | __f_->__clone((__base*)&__f.__buf_); | |
| 1228 | __f_->destroy(); | |
| 1229 | __f_ = __f.__f_; | |
| 1230 | __f.__f_ = (__base*)&__f.__buf_; | |
| 1231 | } | |
| 1232 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 1233 | { | |
| 1234 | __f.__f_->__clone((__base*)&__buf_); | |
| 1235 | __f.__f_->destroy(); | |
| 1236 | __f.__f_ = __f_; | |
| 1237 | __f_ = (__base*)&__buf_; | |
| 1238 | } | |
| 1239 | else | |
| 1240 | _VSTD::swap(__f_, __f.__f_); | |
| 1241 | } | |
| 1242 | ||
| 1243 | template<class _Rp, class _A0, class _A1> | |
| 1244 | _Rp | |
| 1245 | function<_Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) const | |
| 1246 | { | |
| 1247 | if (__f_ == 0) | |
| 1248 | __throw_bad_function_call(); | |
| 1249 | return (*__f_)(__a0, __a1); | |
| 1250 | } | |
| 1251 | ||
| 1252 | #ifndef _LIBCPP_NO_RTTI | |
| 1253 | ||
| 1254 | template<class _Rp, class _A0, class _A1> | |
| 1255 | const std::type_info& | |
| 1256 | function<_Rp(_A0, _A1)>::target_type() const | |
| 1257 | { | |
| 1258 | if (__f_ == 0) | |
| 1259 | return typeid(void); | |
| 1260 | return __f_->target_type(); | |
| 1261 | } | |
| 1262 | ||
| 1263 | template<class _Rp, class _A0, class _A1> | |
| 1264 | template <typename _Tp> | |
| 1265 | _Tp* | |
| 1266 | function<_Rp(_A0, _A1)>::target() | |
| 1267 | { | |
| 1268 | if (__f_ == 0) | |
| 1269 | return (_Tp*)0; | |
| 1270 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 1271 | } | |
| 1272 | ||
| 1273 | template<class _Rp, class _A0, class _A1> | |
| 1274 | template <typename _Tp> | |
| 1275 | const _Tp* | |
| 1276 | function<_Rp(_A0, _A1)>::target() const | |
| 1277 | { | |
| 1278 | if (__f_ == 0) | |
| 1279 | return (const _Tp*)0; | |
| 1280 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 1281 | } | |
| 1282 | ||
| 1283 | #endif // _LIBCPP_NO_RTTI | |
| 1284 | ||
| 1285 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1286 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_A0, _A1, _A2)> | |
| 1287 | { | |
| 1288 | typedef __function::__base<_Rp(_A0, _A1, _A2)> __base; | |
| 1289 | aligned_storage<3*sizeof(void*)>::type __buf_; | |
| 1290 | __base* __f_; | |
| 1291 | ||
| 1292 | public: | |
| 1293 | typedef _Rp result_type; | |
| 1294 | ||
| 1295 | // 20.7.16.2.1, construct/copy/destroy: | |
| 1296 | _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} | |
| 1297 | _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} | |
| 1298 | function(const function&); | |
| 1299 | template<class _Fp> | |
| 1300 | function(_Fp, | |
| 1301 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1302 | ||
| 1303 | template<class _Alloc> | |
| 1304 | _LIBCPP_INLINE_VISIBILITY | |
| 1305 | function(allocator_arg_t, const _Alloc&) : __f_(0) {} | |
| 1306 | template<class _Alloc> | |
| 1307 | _LIBCPP_INLINE_VISIBILITY | |
| 1308 | function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} | |
| 1309 | template<class _Alloc> | |
| 1310 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 1311 | template<class _Fp, class _Alloc> | |
| 1312 | function(allocator_arg_t, const _Alloc& __a, _Fp __f, | |
| 1313 | typename enable_if<!is_integral<_Fp>::value>::type* = 0); | |
| 1314 | ||
| 1315 | function& operator=(const function&); | |
| 1316 | function& operator=(nullptr_t); | |
| 1317 | template<class _Fp> | |
| 1318 | typename enable_if | |
| 1319 | < | |
| 1320 | !is_integral<_Fp>::value, | |
| 1321 | function& | |
| 1322 | >::type | |
| 1323 | operator=(_Fp); | |
| 1324 | ||
| 1325 | ~function(); | |
| 1326 | ||
| 1327 | // 20.7.16.2.2, function modifiers: | |
| 1328 | void swap(function&); | |
| 1329 | template<class _Fp, class _Alloc> | |
| 1330 | _LIBCPP_INLINE_VISIBILITY | |
| 1331 | void assign(_Fp __f, const _Alloc& __a) | |
| 1332 | {function(allocator_arg, __a, __f).swap(*this);} | |
| 1333 | ||
| 1334 | // 20.7.16.2.3, function capacity: | |
| 1335 | _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;} | |
| 1336 | ||
| 1337 | private: | |
| 1338 | // deleted overloads close possible hole in the type system | |
| 1339 | template<class _R2, class _B0, class _B1, class _B2> | |
| 1340 | bool operator==(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; | |
| 1341 | template<class _R2, class _B0, class _B1, class _B2> | |
| 1342 | bool operator!=(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; | |
| 1343 | public: | |
| 1344 | // 20.7.16.2.4, function invocation: | |
| 1345 | _Rp operator()(_A0, _A1, _A2) const; | |
| 1346 | ||
| 1347 | #ifndef _LIBCPP_NO_RTTI | |
| 1348 | // 20.7.16.2.5, function target access: | |
| 1349 | const std::type_info& target_type() const; | |
| 1350 | template <typename _Tp> _Tp* target(); | |
| 1351 | template <typename _Tp> const _Tp* target() const; | |
| 1352 | #endif // _LIBCPP_NO_RTTI | |
| 1353 | }; | |
| 1354 | ||
| 1355 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1356 | function<_Rp(_A0, _A1, _A2)>::function(const function& __f) | |
| 1357 | { | |
| 1358 | if (__f.__f_ == 0) | |
| 1359 | __f_ = 0; | |
| 1360 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 1361 | { | |
| 1362 | __f_ = (__base*)&__buf_; | |
| 1363 | __f.__f_->__clone(__f_); | |
| 1364 | } | |
| 1365 | else | |
| 1366 | __f_ = __f.__f_->__clone(); | |
| 1367 | } | |
| 1368 | ||
| 1369 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1370 | template<class _Alloc> | |
| 1371 | function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc&, | |
| 1372 | const function& __f) | |
| 1373 | { | |
| 1374 | if (__f.__f_ == 0) | |
| 1375 | __f_ = 0; | |
| 1376 | else if (__f.__f_ == (const __base*)&__f.__buf_) | |
| 1377 | { | |
| 1378 | __f_ = (__base*)&__buf_; | |
| 1379 | __f.__f_->__clone(__f_); | |
| 1380 | } | |
| 1381 | else | |
| 1382 | __f_ = __f.__f_->__clone(); | |
| 1383 | } | |
| 1384 | ||
| 1385 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1386 | template <class _Fp> | |
| 1387 | function<_Rp(_A0, _A1, _A2)>::function(_Fp __f, | |
| 1388 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 1389 | : __f_(0) | |
| 1390 | { | |
| 1391 | if (__function::__not_null(__f)) | |
| 1392 | { | |
| 1393 | typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1, _A2)> _FF; | |
| 1394 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 1395 | { | |
| 1396 | __f_ = (__base*)&__buf_; | |
| 1397 | ::new ((void*)__f_) _FF(__f); | |
| 1398 | } | |
| 1399 | else | |
| 1400 | { | |
| 1401 | typedef allocator<_FF> _Ap; | |
| 1402 | _Ap __a; | |
| 1403 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1404 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1405 | ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a)); | |
| 1406 | __f_ = __hold.release(); | |
| 1407 | } | |
| 1408 | } | |
| 1409 | } | |
| 1410 | ||
| 1411 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1412 | template <class _Fp, class _Alloc> | |
| 1413 | function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, | |
| 1414 | typename enable_if<!is_integral<_Fp>::value>::type*) | |
| 1415 | : __f_(0) | |
| 1416 | { | |
| 1417 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1418 | if (__function::__not_null(__f)) | |
| 1419 | { | |
| 1420 | typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> _FF; | |
| 1421 | if (sizeof(_FF) <= sizeof(__buf_)) | |
| 1422 | { | |
| 1423 | __f_ = (__base*)&__buf_; | |
| 1424 | ::new ((void*)__f_) _FF(__f, __a0); | |
| 1425 | } | |
| 1426 | else | |
| 1427 | { | |
| 1428 | typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; | |
| 1429 | _Ap __a(__a0); | |
| 1430 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1431 | unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1432 | ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a)); | |
| 1433 | __f_ = __hold.release(); | |
| 1434 | } | |
| 1435 | } | |
| 1436 | } | |
| 1437 | ||
| 1438 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1439 | function<_Rp(_A0, _A1, _A2)>& | |
| 1440 | function<_Rp(_A0, _A1, _A2)>::operator=(const function& __f) | |
| 1441 | { | |
| 1442 | if (__f) | |
| 1443 | function(__f).swap(*this); | |
| 1444 | else | |
| 1445 | *this = nullptr; | |
| 1446 | return *this; | |
| 1447 | } | |
| 1448 | ||
| 1449 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1450 | function<_Rp(_A0, _A1, _A2)>& | |
| 1451 | function<_Rp(_A0, _A1, _A2)>::operator=(nullptr_t) | |
| 1452 | { | |
| 1453 | __base* __t = __f_; | |
| 1454 | __f_ = 0; | |
| 1455 | if (__t == (__base*)&__buf_) | |
| 1456 | __t->destroy(); | |
| 1457 | else if (__t) | |
| 1458 | __t->destroy_deallocate(); | |
| 1459 | return *this; | |
| 1460 | } | |
| 1461 | ||
| 1462 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1463 | template <class _Fp> | |
| 1464 | typename enable_if | |
| 1465 | < | |
| 1466 | !is_integral<_Fp>::value, | |
| 1467 | function<_Rp(_A0, _A1, _A2)>& | |
| 1468 | >::type | |
| 1469 | function<_Rp(_A0, _A1, _A2)>::operator=(_Fp __f) | |
| 1470 | { | |
| 1471 | function(_VSTD::move(__f)).swap(*this); | |
| 1472 | return *this; | |
| 1473 | } | |
| 1474 | ||
| 1475 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1476 | function<_Rp(_A0, _A1, _A2)>::~function() | |
| 1477 | { | |
| 1478 | if (__f_ == (__base*)&__buf_) | |
| 1479 | __f_->destroy(); | |
| 1480 | else if (__f_) | |
| 1481 | __f_->destroy_deallocate(); | |
| 1482 | } | |
| 1483 | ||
| 1484 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1485 | void | |
| 1486 | function<_Rp(_A0, _A1, _A2)>::swap(function& __f) | |
| 1487 | { | |
| 1488 | if (_VSTD::addressof(__f) == this) | |
| 1489 | return; | |
| 1490 | if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) | |
| 1491 | { | |
| 1492 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 1493 | __base* __t = (__base*)&__tempbuf; | |
| 1494 | __f_->__clone(__t); | |
| 1495 | __f_->destroy(); | |
| 1496 | __f_ = 0; | |
| 1497 | __f.__f_->__clone((__base*)&__buf_); | |
| 1498 | __f.__f_->destroy(); | |
| 1499 | __f.__f_ = 0; | |
| 1500 | __f_ = (__base*)&__buf_; | |
| 1501 | __t->__clone((__base*)&__f.__buf_); | |
| 1502 | __t->destroy(); | |
| 1503 | __f.__f_ = (__base*)&__f.__buf_; | |
| 1504 | } | |
| 1505 | else if (__f_ == (__base*)&__buf_) | |
| 1506 | { | |
| 1507 | __f_->__clone((__base*)&__f.__buf_); | |
| 1508 | __f_->destroy(); | |
| 1509 | __f_ = __f.__f_; | |
| 1510 | __f.__f_ = (__base*)&__f.__buf_; | |
| 1511 | } | |
| 1512 | else if (__f.__f_ == (__base*)&__f.__buf_) | |
| 1513 | { | |
| 1514 | __f.__f_->__clone((__base*)&__buf_); | |
| 1515 | __f.__f_->destroy(); | |
| 1516 | __f.__f_ = __f_; | |
| 1517 | __f_ = (__base*)&__buf_; | |
| 1518 | } | |
| 1519 | else | |
| 1520 | _VSTD::swap(__f_, __f.__f_); | |
| 1521 | } | |
| 1522 | ||
| 1523 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1524 | _Rp | |
| 1525 | function<_Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) const | |
| 1526 | { | |
| 1527 | if (__f_ == 0) | |
| 1528 | __throw_bad_function_call(); | |
| 1529 | return (*__f_)(__a0, __a1, __a2); | |
| 1530 | } | |
| 1531 | ||
| 1532 | #ifndef _LIBCPP_NO_RTTI | |
| 1533 | ||
| 1534 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1535 | const std::type_info& | |
| 1536 | function<_Rp(_A0, _A1, _A2)>::target_type() const | |
| 1537 | { | |
| 1538 | if (__f_ == 0) | |
| 1539 | return typeid(void); | |
| 1540 | return __f_->target_type(); | |
| 1541 | } | |
| 1542 | ||
| 1543 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1544 | template <typename _Tp> | |
| 1545 | _Tp* | |
| 1546 | function<_Rp(_A0, _A1, _A2)>::target() | |
| 1547 | { | |
| 1548 | if (__f_ == 0) | |
| 1549 | return (_Tp*)0; | |
| 1550 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); | |
| 1551 | } | |
| 1552 | ||
| 1553 | template<class _Rp, class _A0, class _A1, class _A2> | |
| 1554 | template <typename _Tp> | |
| 1555 | const _Tp* | |
| 1556 | function<_Rp(_A0, _A1, _A2)>::target() const | |
| 1557 | { | |
| 1558 | if (__f_ == 0) | |
| 1559 | return (const _Tp*)0; | |
| 1560 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 1561 | } | |
| 1562 | ||
| 1563 | #endif // _LIBCPP_NO_RTTI | |
| 1564 | ||
| 1565 | template <class _Fp> | |
| 1566 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1567 | bool | |
| 1568 | operator==(const function<_Fp>& __f, nullptr_t) {return !__f;} | |
| 1569 | ||
| 1570 | template <class _Fp> | |
| 1571 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1572 | bool | |
| 1573 | operator==(nullptr_t, const function<_Fp>& __f) {return !__f;} | |
| 1574 | ||
| 1575 | template <class _Fp> | |
| 1576 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1577 | bool | |
| 1578 | operator!=(const function<_Fp>& __f, nullptr_t) {return (bool)__f;} | |
| 1579 | ||
| 1580 | template <class _Fp> | |
| 1581 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1582 | bool | |
| 1583 | operator!=(nullptr_t, const function<_Fp>& __f) {return (bool)__f;} | |
| 1584 | ||
| 1585 | template <class _Fp> | |
| 1586 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1587 | void | |
| 1588 | swap(function<_Fp>& __x, function<_Fp>& __y) | |
| 1589 | {return __x.swap(__y);} | |
| 1590 | ||
| 1591 | #endif // _LIBCPP_FUNCTIONAL_03 |
lib/libcxx/include/__functional_base+11-634| ... | ... | @@ -11,645 +11,22 @@ |
| 11 | 11 | #define _LIBCPP_FUNCTIONAL_BASE |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <type_traits> | |
| 15 | #include <typeinfo> | |
| 14 | #include <__functional/binary_function.h> | |
| 15 | #include <__functional/invoke.h> | |
| 16 | #include <__functional/operations.h> | |
| 17 | #include <__functional/reference_wrapper.h> | |
| 18 | #include <__functional/unary_function.h> | |
| 19 | #include <__functional/weak_result_type.h> | |
| 20 | #include <__memory/allocator_arg_t.h> | |
| 21 | #include <__memory/uses_allocator.h> | |
| 16 | 22 | #include <exception> |
| 17 | 23 | #include <new> |
| 24 | #include <type_traits> | |
| 25 | #include <typeinfo> | |
| 18 | 26 | #include <utility> |
| 19 | 27 | |
| 20 | 28 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 21 | 29 | #pragma GCC system_header |
| 22 | 30 | #endif |
| 23 | 31 | |
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Arg1, class _Arg2, class _Result> | |
| 27 | struct _LIBCPP_TEMPLATE_VIS binary_function | |
| 28 | { | |
| 29 | typedef _Arg1 first_argument_type; | |
| 30 | typedef _Arg2 second_argument_type; | |
| 31 | typedef _Result result_type; | |
| 32 | }; | |
| 33 | ||
| 34 | template <class _Tp> | |
| 35 | struct __has_result_type | |
| 36 | { | |
| 37 | private: | |
| 38 | struct __two {char __lx; char __lxx;}; | |
| 39 | template <class _Up> static __two __test(...); | |
| 40 | template <class _Up> static char __test(typename _Up::result_type* = 0); | |
| 41 | public: | |
| 42 | static const bool value = sizeof(__test<_Tp>(0)) == 1; | |
| 43 | }; | |
| 44 | ||
| 45 | #if _LIBCPP_STD_VER > 11 | |
| 46 | template <class _Tp = void> | |
| 47 | #else | |
| 48 | template <class _Tp> | |
| 49 | #endif | |
| 50 | struct _LIBCPP_TEMPLATE_VIS less : binary_function<_Tp, _Tp, bool> | |
| 51 | { | |
| 52 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 53 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 54 | {return __x < __y;} | |
| 55 | }; | |
| 56 | ||
| 57 | #if _LIBCPP_STD_VER > 11 | |
| 58 | template <> | |
| 59 | struct _LIBCPP_TEMPLATE_VIS less<void> | |
| 60 | { | |
| 61 | template <class _T1, class _T2> | |
| 62 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 63 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 64 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u))) | |
| 65 | -> decltype (_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)) | |
| 66 | { return _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u); } | |
| 67 | typedef void is_transparent; | |
| 68 | }; | |
| 69 | #endif | |
| 70 | ||
| 71 | // __weak_result_type | |
| 72 | ||
| 73 | template <class _Tp> | |
| 74 | struct __derives_from_unary_function | |
| 75 | { | |
| 76 | private: | |
| 77 | struct __two {char __lx; char __lxx;}; | |
| 78 | static __two __test(...); | |
| 79 | template <class _Ap, class _Rp> | |
| 80 | static unary_function<_Ap, _Rp> | |
| 81 | __test(const volatile unary_function<_Ap, _Rp>*); | |
| 82 | public: | |
| 83 | static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value; | |
| 84 | typedef decltype(__test((_Tp*)0)) type; | |
| 85 | }; | |
| 86 | ||
| 87 | template <class _Tp> | |
| 88 | struct __derives_from_binary_function | |
| 89 | { | |
| 90 | private: | |
| 91 | struct __two {char __lx; char __lxx;}; | |
| 92 | static __two __test(...); | |
| 93 | template <class _A1, class _A2, class _Rp> | |
| 94 | static binary_function<_A1, _A2, _Rp> | |
| 95 | __test(const volatile binary_function<_A1, _A2, _Rp>*); | |
| 96 | public: | |
| 97 | static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value; | |
| 98 | typedef decltype(__test((_Tp*)0)) type; | |
| 99 | }; | |
| 100 | ||
| 101 | template <class _Tp, bool = __derives_from_unary_function<_Tp>::value> | |
| 102 | struct __maybe_derive_from_unary_function // bool is true | |
| 103 | : public __derives_from_unary_function<_Tp>::type | |
| 104 | { | |
| 105 | }; | |
| 106 | ||
| 107 | template <class _Tp> | |
| 108 | struct __maybe_derive_from_unary_function<_Tp, false> | |
| 109 | { | |
| 110 | }; | |
| 111 | ||
| 112 | template <class _Tp, bool = __derives_from_binary_function<_Tp>::value> | |
| 113 | struct __maybe_derive_from_binary_function // bool is true | |
| 114 | : public __derives_from_binary_function<_Tp>::type | |
| 115 | { | |
| 116 | }; | |
| 117 | ||
| 118 | template <class _Tp> | |
| 119 | struct __maybe_derive_from_binary_function<_Tp, false> | |
| 120 | { | |
| 121 | }; | |
| 122 | ||
| 123 | template <class _Tp, bool = __has_result_type<_Tp>::value> | |
| 124 | struct __weak_result_type_imp // bool is true | |
| 125 | : public __maybe_derive_from_unary_function<_Tp>, | |
| 126 | public __maybe_derive_from_binary_function<_Tp> | |
| 127 | { | |
| 128 | typedef _LIBCPP_NODEBUG_TYPE typename _Tp::result_type result_type; | |
| 129 | }; | |
| 130 | ||
| 131 | template <class _Tp> | |
| 132 | struct __weak_result_type_imp<_Tp, false> | |
| 133 | : public __maybe_derive_from_unary_function<_Tp>, | |
| 134 | public __maybe_derive_from_binary_function<_Tp> | |
| 135 | { | |
| 136 | }; | |
| 137 | ||
| 138 | template <class _Tp> | |
| 139 | struct __weak_result_type | |
| 140 | : public __weak_result_type_imp<_Tp> | |
| 141 | { | |
| 142 | }; | |
| 143 | ||
| 144 | // 0 argument case | |
| 145 | ||
| 146 | template <class _Rp> | |
| 147 | struct __weak_result_type<_Rp ()> | |
| 148 | { | |
| 149 | typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; | |
| 150 | }; | |
| 151 | ||
| 152 | template <class _Rp> | |
| 153 | struct __weak_result_type<_Rp (&)()> | |
| 154 | { | |
| 155 | typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; | |
| 156 | }; | |
| 157 | ||
| 158 | template <class _Rp> | |
| 159 | struct __weak_result_type<_Rp (*)()> | |
| 160 | { | |
| 161 | typedef _LIBCPP_NODEBUG_TYPE _Rp result_type; | |
| 162 | }; | |
| 163 | ||
| 164 | // 1 argument case | |
| 165 | ||
| 166 | template <class _Rp, class _A1> | |
| 167 | struct __weak_result_type<_Rp (_A1)> | |
| 168 | : public unary_function<_A1, _Rp> | |
| 169 | { | |
| 170 | }; | |
| 171 | ||
| 172 | template <class _Rp, class _A1> | |
| 173 | struct __weak_result_type<_Rp (&)(_A1)> | |
| 174 | : public unary_function<_A1, _Rp> | |
| 175 | { | |
| 176 | }; | |
| 177 | ||
| 178 | template <class _Rp, class _A1> | |
| 179 | struct __weak_result_type<_Rp (*)(_A1)> | |
| 180 | : public unary_function<_A1, _Rp> | |
| 181 | { | |
| 182 | }; | |
| 183 | ||
| 184 | template <class _Rp, class _Cp> | |
| 185 | struct __weak_result_type<_Rp (_Cp::*)()> | |
| 186 | : public unary_function<_Cp*, _Rp> | |
| 187 | { | |
| 188 | }; | |
| 189 | ||
| 190 | template <class _Rp, class _Cp> | |
| 191 | struct __weak_result_type<_Rp (_Cp::*)() const> | |
| 192 | : public unary_function<const _Cp*, _Rp> | |
| 193 | { | |
| 194 | }; | |
| 195 | ||
| 196 | template <class _Rp, class _Cp> | |
| 197 | struct __weak_result_type<_Rp (_Cp::*)() volatile> | |
| 198 | : public unary_function<volatile _Cp*, _Rp> | |
| 199 | { | |
| 200 | }; | |
| 201 | ||
| 202 | template <class _Rp, class _Cp> | |
| 203 | struct __weak_result_type<_Rp (_Cp::*)() const volatile> | |
| 204 | : public unary_function<const volatile _Cp*, _Rp> | |
| 205 | { | |
| 206 | }; | |
| 207 | ||
| 208 | // 2 argument case | |
| 209 | ||
| 210 | template <class _Rp, class _A1, class _A2> | |
| 211 | struct __weak_result_type<_Rp (_A1, _A2)> | |
| 212 | : public binary_function<_A1, _A2, _Rp> | |
| 213 | { | |
| 214 | }; | |
| 215 | ||
| 216 | template <class _Rp, class _A1, class _A2> | |
| 217 | struct __weak_result_type<_Rp (*)(_A1, _A2)> | |
| 218 | : public binary_function<_A1, _A2, _Rp> | |
| 219 | { | |
| 220 | }; | |
| 221 | ||
| 222 | template <class _Rp, class _A1, class _A2> | |
| 223 | struct __weak_result_type<_Rp (&)(_A1, _A2)> | |
| 224 | : public binary_function<_A1, _A2, _Rp> | |
| 225 | { | |
| 226 | }; | |
| 227 | ||
| 228 | template <class _Rp, class _Cp, class _A1> | |
| 229 | struct __weak_result_type<_Rp (_Cp::*)(_A1)> | |
| 230 | : public binary_function<_Cp*, _A1, _Rp> | |
| 231 | { | |
| 232 | }; | |
| 233 | ||
| 234 | template <class _Rp, class _Cp, class _A1> | |
| 235 | struct __weak_result_type<_Rp (_Cp::*)(_A1) const> | |
| 236 | : public binary_function<const _Cp*, _A1, _Rp> | |
| 237 | { | |
| 238 | }; | |
| 239 | ||
| 240 | template <class _Rp, class _Cp, class _A1> | |
| 241 | struct __weak_result_type<_Rp (_Cp::*)(_A1) volatile> | |
| 242 | : public binary_function<volatile _Cp*, _A1, _Rp> | |
| 243 | { | |
| 244 | }; | |
| 245 | ||
| 246 | template <class _Rp, class _Cp, class _A1> | |
| 247 | struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile> | |
| 248 | : public binary_function<const volatile _Cp*, _A1, _Rp> | |
| 249 | { | |
| 250 | }; | |
| 251 | ||
| 252 | ||
| 253 | #ifndef _LIBCPP_CXX03_LANG | |
| 254 | // 3 or more arguments | |
| 255 | ||
| 256 | template <class _Rp, class _A1, class _A2, class _A3, class ..._A4> | |
| 257 | struct __weak_result_type<_Rp (_A1, _A2, _A3, _A4...)> | |
| 258 | { | |
| 259 | typedef _Rp result_type; | |
| 260 | }; | |
| 261 | ||
| 262 | template <class _Rp, class _A1, class _A2, class _A3, class ..._A4> | |
| 263 | struct __weak_result_type<_Rp (&)(_A1, _A2, _A3, _A4...)> | |
| 264 | { | |
| 265 | typedef _Rp result_type; | |
| 266 | }; | |
| 267 | ||
| 268 | template <class _Rp, class _A1, class _A2, class _A3, class ..._A4> | |
| 269 | struct __weak_result_type<_Rp (*)(_A1, _A2, _A3, _A4...)> | |
| 270 | { | |
| 271 | typedef _Rp result_type; | |
| 272 | }; | |
| 273 | ||
| 274 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 275 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...)> | |
| 276 | { | |
| 277 | typedef _Rp result_type; | |
| 278 | }; | |
| 279 | ||
| 280 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 281 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const> | |
| 282 | { | |
| 283 | typedef _Rp result_type; | |
| 284 | }; | |
| 285 | ||
| 286 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 287 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) volatile> | |
| 288 | { | |
| 289 | typedef _Rp result_type; | |
| 290 | }; | |
| 291 | ||
| 292 | template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3> | |
| 293 | struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> | |
| 294 | { | |
| 295 | typedef _Rp result_type; | |
| 296 | }; | |
| 297 | ||
| 298 | template <class _Tp, class ..._Args> | |
| 299 | struct __invoke_return | |
| 300 | { | |
| 301 | typedef decltype(_VSTD::__invoke(declval<_Tp>(), declval<_Args>()...)) type; | |
| 302 | }; | |
| 303 | ||
| 304 | #else // defined(_LIBCPP_CXX03_LANG) | |
| 305 | ||
| 306 | #include <__functional_base_03> | |
| 307 | ||
| 308 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 309 | ||
| 310 | ||
| 311 | template <class _Ret, bool = is_void<_Ret>::value> | |
| 312 | struct __invoke_void_return_wrapper | |
| 313 | { | |
| 314 | #ifndef _LIBCPP_CXX03_LANG | |
| 315 | template <class ..._Args> | |
| 316 | static _Ret __call(_Args&&... __args) { | |
| 317 | return _VSTD::__invoke(_VSTD::forward<_Args>(__args)...); | |
| 318 | } | |
| 319 | #else | |
| 320 | template <class _Fn> | |
| 321 | static _Ret __call(_Fn __f) { | |
| 322 | return _VSTD::__invoke(__f); | |
| 323 | } | |
| 324 | ||
| 325 | template <class _Fn, class _A0> | |
| 326 | static _Ret __call(_Fn __f, _A0& __a0) { | |
| 327 | return _VSTD::__invoke(__f, __a0); | |
| 328 | } | |
| 329 | ||
| 330 | template <class _Fn, class _A0, class _A1> | |
| 331 | static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) { | |
| 332 | return _VSTD::__invoke(__f, __a0, __a1); | |
| 333 | } | |
| 334 | ||
| 335 | template <class _Fn, class _A0, class _A1, class _A2> | |
| 336 | static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){ | |
| 337 | return _VSTD::__invoke(__f, __a0, __a1, __a2); | |
| 338 | } | |
| 339 | #endif | |
| 340 | }; | |
| 341 | ||
| 342 | template <class _Ret> | |
| 343 | struct __invoke_void_return_wrapper<_Ret, true> | |
| 344 | { | |
| 345 | #ifndef _LIBCPP_CXX03_LANG | |
| 346 | template <class ..._Args> | |
| 347 | static void __call(_Args&&... __args) { | |
| 348 | _VSTD::__invoke(_VSTD::forward<_Args>(__args)...); | |
| 349 | } | |
| 350 | #else | |
| 351 | template <class _Fn> | |
| 352 | static void __call(_Fn __f) { | |
| 353 | _VSTD::__invoke(__f); | |
| 354 | } | |
| 355 | ||
| 356 | template <class _Fn, class _A0> | |
| 357 | static void __call(_Fn __f, _A0& __a0) { | |
| 358 | _VSTD::__invoke(__f, __a0); | |
| 359 | } | |
| 360 | ||
| 361 | template <class _Fn, class _A0, class _A1> | |
| 362 | static void __call(_Fn __f, _A0& __a0, _A1& __a1) { | |
| 363 | _VSTD::__invoke(__f, __a0, __a1); | |
| 364 | } | |
| 365 | ||
| 366 | template <class _Fn, class _A0, class _A1, class _A2> | |
| 367 | static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) { | |
| 368 | _VSTD::__invoke(__f, __a0, __a1, __a2); | |
| 369 | } | |
| 370 | #endif | |
| 371 | }; | |
| 372 | ||
| 373 | template <class _Tp> | |
| 374 | class _LIBCPP_TEMPLATE_VIS reference_wrapper | |
| 375 | : public __weak_result_type<_Tp> | |
| 376 | { | |
| 377 | public: | |
| 378 | // types | |
| 379 | typedef _Tp type; | |
| 380 | private: | |
| 381 | type* __f_; | |
| 382 | ||
| 383 | public: | |
| 384 | // construct/copy/destroy | |
| 385 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 386 | reference_wrapper(type& __f) _NOEXCEPT | |
| 387 | : __f_(_VSTD::addressof(__f)) {} | |
| 388 | #ifndef _LIBCPP_CXX03_LANG | |
| 389 | private: reference_wrapper(type&&); public: // = delete; // do not bind to temps | |
| 390 | #endif | |
| 391 | ||
| 392 | // access | |
| 393 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 394 | operator type&() const _NOEXCEPT {return *__f_;} | |
| 395 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 396 | type& get() const _NOEXCEPT {return *__f_;} | |
| 397 | ||
| 398 | #ifndef _LIBCPP_CXX03_LANG | |
| 399 | // invoke | |
| 400 | template <class... _ArgTypes> | |
| 401 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 402 | typename __invoke_of<type&, _ArgTypes...>::type | |
| 403 | operator() (_ArgTypes&&... __args) const { | |
| 404 | return _VSTD::__invoke(get(), _VSTD::forward<_ArgTypes>(__args)...); | |
| 405 | } | |
| 406 | #else | |
| 407 | ||
| 408 | _LIBCPP_INLINE_VISIBILITY | |
| 409 | typename __invoke_return<type>::type | |
| 410 | operator() () const { | |
| 411 | return _VSTD::__invoke(get()); | |
| 412 | } | |
| 413 | ||
| 414 | template <class _A0> | |
| 415 | _LIBCPP_INLINE_VISIBILITY | |
| 416 | typename __invoke_return0<type, _A0>::type | |
| 417 | operator() (_A0& __a0) const { | |
| 418 | return _VSTD::__invoke(get(), __a0); | |
| 419 | } | |
| 420 | ||
| 421 | template <class _A0> | |
| 422 | _LIBCPP_INLINE_VISIBILITY | |
| 423 | typename __invoke_return0<type, _A0 const>::type | |
| 424 | operator() (_A0 const& __a0) const { | |
| 425 | return _VSTD::__invoke(get(), __a0); | |
| 426 | } | |
| 427 | ||
| 428 | template <class _A0, class _A1> | |
| 429 | _LIBCPP_INLINE_VISIBILITY | |
| 430 | typename __invoke_return1<type, _A0, _A1>::type | |
| 431 | operator() (_A0& __a0, _A1& __a1) const { | |
| 432 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 433 | } | |
| 434 | ||
| 435 | template <class _A0, class _A1> | |
| 436 | _LIBCPP_INLINE_VISIBILITY | |
| 437 | typename __invoke_return1<type, _A0 const, _A1>::type | |
| 438 | operator() (_A0 const& __a0, _A1& __a1) const { | |
| 439 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 440 | } | |
| 441 | ||
| 442 | template <class _A0, class _A1> | |
| 443 | _LIBCPP_INLINE_VISIBILITY | |
| 444 | typename __invoke_return1<type, _A0, _A1 const>::type | |
| 445 | operator() (_A0& __a0, _A1 const& __a1) const { | |
| 446 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 447 | } | |
| 448 | ||
| 449 | template <class _A0, class _A1> | |
| 450 | _LIBCPP_INLINE_VISIBILITY | |
| 451 | typename __invoke_return1<type, _A0 const, _A1 const>::type | |
| 452 | operator() (_A0 const& __a0, _A1 const& __a1) const { | |
| 453 | return _VSTD::__invoke(get(), __a0, __a1); | |
| 454 | } | |
| 455 | ||
| 456 | template <class _A0, class _A1, class _A2> | |
| 457 | _LIBCPP_INLINE_VISIBILITY | |
| 458 | typename __invoke_return2<type, _A0, _A1, _A2>::type | |
| 459 | operator() (_A0& __a0, _A1& __a1, _A2& __a2) const { | |
| 460 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 461 | } | |
| 462 | ||
| 463 | template <class _A0, class _A1, class _A2> | |
| 464 | _LIBCPP_INLINE_VISIBILITY | |
| 465 | typename __invoke_return2<type, _A0 const, _A1, _A2>::type | |
| 466 | operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const { | |
| 467 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 468 | } | |
| 469 | ||
| 470 | template <class _A0, class _A1, class _A2> | |
| 471 | _LIBCPP_INLINE_VISIBILITY | |
| 472 | typename __invoke_return2<type, _A0, _A1 const, _A2>::type | |
| 473 | operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 474 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 475 | } | |
| 476 | ||
| 477 | template <class _A0, class _A1, class _A2> | |
| 478 | _LIBCPP_INLINE_VISIBILITY | |
| 479 | typename __invoke_return2<type, _A0, _A1, _A2 const>::type | |
| 480 | operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 481 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 482 | } | |
| 483 | ||
| 484 | template <class _A0, class _A1, class _A2> | |
| 485 | _LIBCPP_INLINE_VISIBILITY | |
| 486 | typename __invoke_return2<type, _A0 const, _A1 const, _A2>::type | |
| 487 | operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 488 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 489 | } | |
| 490 | ||
| 491 | template <class _A0, class _A1, class _A2> | |
| 492 | _LIBCPP_INLINE_VISIBILITY | |
| 493 | typename __invoke_return2<type, _A0 const, _A1, _A2 const>::type | |
| 494 | operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 495 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 496 | } | |
| 497 | ||
| 498 | template <class _A0, class _A1, class _A2> | |
| 499 | _LIBCPP_INLINE_VISIBILITY | |
| 500 | typename __invoke_return2<type, _A0, _A1 const, _A2 const>::type | |
| 501 | operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 502 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 503 | } | |
| 504 | ||
| 505 | template <class _A0, class _A1, class _A2> | |
| 506 | _LIBCPP_INLINE_VISIBILITY | |
| 507 | typename __invoke_return2<type, _A0 const, _A1 const, _A2 const>::type | |
| 508 | operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 509 | return _VSTD::__invoke(get(), __a0, __a1, __a2); | |
| 510 | } | |
| 511 | #endif // _LIBCPP_CXX03_LANG | |
| 512 | }; | |
| 513 | ||
| 514 | ||
| 515 | template <class _Tp> | |
| 516 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 517 | reference_wrapper<_Tp> | |
| 518 | ref(_Tp& __t) _NOEXCEPT | |
| 519 | { | |
| 520 | return reference_wrapper<_Tp>(__t); | |
| 521 | } | |
| 522 | ||
| 523 | template <class _Tp> | |
| 524 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 525 | reference_wrapper<_Tp> | |
| 526 | ref(reference_wrapper<_Tp> __t) _NOEXCEPT | |
| 527 | { | |
| 528 | return _VSTD::ref(__t.get()); | |
| 529 | } | |
| 530 | ||
| 531 | template <class _Tp> | |
| 532 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 533 | reference_wrapper<const _Tp> | |
| 534 | cref(const _Tp& __t) _NOEXCEPT | |
| 535 | { | |
| 536 | return reference_wrapper<const _Tp>(__t); | |
| 537 | } | |
| 538 | ||
| 539 | template <class _Tp> | |
| 540 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 541 | reference_wrapper<const _Tp> | |
| 542 | cref(reference_wrapper<_Tp> __t) _NOEXCEPT | |
| 543 | { | |
| 544 | return _VSTD::cref(__t.get()); | |
| 545 | } | |
| 546 | ||
| 547 | #ifndef _LIBCPP_CXX03_LANG | |
| 548 | template <class _Tp> void ref(const _Tp&&) = delete; | |
| 549 | template <class _Tp> void cref(const _Tp&&) = delete; | |
| 550 | #endif | |
| 551 | ||
| 552 | #if _LIBCPP_STD_VER > 11 | |
| 553 | template <class _Tp, class, class = void> | |
| 554 | struct __is_transparent : false_type {}; | |
| 555 | ||
| 556 | template <class _Tp, class _Up> | |
| 557 | struct __is_transparent<_Tp, _Up, | |
| 558 | typename __void_t<typename _Tp::is_transparent>::type> | |
| 559 | : true_type {}; | |
| 560 | #endif | |
| 561 | ||
| 562 | // allocator_arg_t | |
| 563 | ||
| 564 | struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { explicit allocator_arg_t() = default; }; | |
| 565 | ||
| 566 | #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 567 | extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg; | |
| 568 | #else | |
| 569 | /* _LIBCPP_INLINE_VAR */ constexpr allocator_arg_t allocator_arg = allocator_arg_t(); | |
| 570 | #endif | |
| 571 | ||
| 572 | // uses_allocator | |
| 573 | ||
| 574 | template <class _Tp> | |
| 575 | struct __has_allocator_type | |
| 576 | { | |
| 577 | private: | |
| 578 | struct __two {char __lx; char __lxx;}; | |
| 579 | template <class _Up> static __two __test(...); | |
| 580 | template <class _Up> static char __test(typename _Up::allocator_type* = 0); | |
| 581 | public: | |
| 582 | static const bool value = sizeof(__test<_Tp>(0)) == 1; | |
| 583 | }; | |
| 584 | ||
| 585 | template <class _Tp, class _Alloc, bool = __has_allocator_type<_Tp>::value> | |
| 586 | struct __uses_allocator | |
| 587 | : public integral_constant<bool, | |
| 588 | is_convertible<_Alloc, typename _Tp::allocator_type>::value> | |
| 589 | { | |
| 590 | }; | |
| 591 | ||
| 592 | template <class _Tp, class _Alloc> | |
| 593 | struct __uses_allocator<_Tp, _Alloc, false> | |
| 594 | : public false_type | |
| 595 | { | |
| 596 | }; | |
| 597 | ||
| 598 | template <class _Tp, class _Alloc> | |
| 599 | struct _LIBCPP_TEMPLATE_VIS uses_allocator | |
| 600 | : public __uses_allocator<_Tp, _Alloc> | |
| 601 | { | |
| 602 | }; | |
| 603 | ||
| 604 | #if _LIBCPP_STD_VER > 14 | |
| 605 | template <class _Tp, class _Alloc> | |
| 606 | _LIBCPP_INLINE_VAR constexpr size_t uses_allocator_v = uses_allocator<_Tp, _Alloc>::value; | |
| 607 | #endif | |
| 608 | ||
| 609 | #ifndef _LIBCPP_CXX03_LANG | |
| 610 | ||
| 611 | // allocator construction | |
| 612 | ||
| 613 | template <class _Tp, class _Alloc, class ..._Args> | |
| 614 | struct __uses_alloc_ctor_imp | |
| 615 | { | |
| 616 | typedef _LIBCPP_NODEBUG_TYPE typename __uncvref<_Alloc>::type _RawAlloc; | |
| 617 | static const bool __ua = uses_allocator<_Tp, _RawAlloc>::value; | |
| 618 | static const bool __ic = | |
| 619 | is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; | |
| 620 | static const int value = __ua ? 2 - __ic : 0; | |
| 621 | }; | |
| 622 | ||
| 623 | template <class _Tp, class _Alloc, class ..._Args> | |
| 624 | struct __uses_alloc_ctor | |
| 625 | : integral_constant<int, __uses_alloc_ctor_imp<_Tp, _Alloc, _Args...>::value> | |
| 626 | {}; | |
| 627 | ||
| 628 | template <class _Tp, class _Allocator, class... _Args> | |
| 629 | inline _LIBCPP_INLINE_VISIBILITY | |
| 630 | void __user_alloc_construct_impl (integral_constant<int, 0>, _Tp *__storage, const _Allocator &, _Args &&... __args ) | |
| 631 | { | |
| 632 | new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); | |
| 633 | } | |
| 634 | ||
| 635 | // FIXME: This should have a version which takes a non-const alloc. | |
| 636 | template <class _Tp, class _Allocator, class... _Args> | |
| 637 | inline _LIBCPP_INLINE_VISIBILITY | |
| 638 | void __user_alloc_construct_impl (integral_constant<int, 1>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) | |
| 639 | { | |
| 640 | new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); | |
| 641 | } | |
| 642 | ||
| 643 | // FIXME: This should have a version which takes a non-const alloc. | |
| 644 | template <class _Tp, class _Allocator, class... _Args> | |
| 645 | inline _LIBCPP_INLINE_VISIBILITY | |
| 646 | void __user_alloc_construct_impl (integral_constant<int, 2>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) | |
| 647 | { | |
| 648 | new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); | |
| 649 | } | |
| 650 | ||
| 651 | #endif // _LIBCPP_CXX03_LANG | |
| 652 | ||
| 653 | _LIBCPP_END_NAMESPACE_STD | |
| 654 | ||
| 655 | #endif // _LIBCPP_FUNCTIONAL_BASE | |
| 32 | #endif // _LIBCPP_FUNCTIONAL_BASE |
lib/libcxx/include/__functional_base_03 deleted-223| ... | ... | @@ -1,223 +0,0 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP_FUNCTIONAL_BASE_03 | |
| 11 | #define _LIBCPP_FUNCTIONAL_BASE_03 | |
| 12 | ||
| 13 | // manual variadic expansion for <functional> | |
| 14 | ||
| 15 | // __invoke | |
| 16 | ||
| 17 | template <class _Ret, class _T1, bool _IsFunc, bool _IsBase> | |
| 18 | struct __enable_invoke_imp; | |
| 19 | ||
| 20 | template <class _Ret, class _T1> | |
| 21 | struct __enable_invoke_imp<_Ret, _T1, true, true> { | |
| 22 | typedef _Ret _Bullet1; | |
| 23 | typedef _Bullet1 type; | |
| 24 | }; | |
| 25 | ||
| 26 | template <class _Ret, class _T1> | |
| 27 | struct __enable_invoke_imp<_Ret, _T1, true, false> { | |
| 28 | typedef _Ret _Bullet2; | |
| 29 | typedef _Bullet2 type; | |
| 30 | }; | |
| 31 | ||
| 32 | template <class _Ret, class _T1> | |
| 33 | struct __enable_invoke_imp<_Ret, _T1, false, true> { | |
| 34 | typedef typename add_lvalue_reference< | |
| 35 | typename __apply_cv<_T1, _Ret>::type | |
| 36 | >::type _Bullet3; | |
| 37 | typedef _Bullet3 type; | |
| 38 | }; | |
| 39 | ||
| 40 | template <class _Ret, class _T1> | |
| 41 | struct __enable_invoke_imp<_Ret, _T1, false, false> { | |
| 42 | typedef typename add_lvalue_reference< | |
| 43 | typename __apply_cv<decltype(*declval<_T1>()), _Ret>::type | |
| 44 | >::type _Bullet4; | |
| 45 | typedef _Bullet4 type; | |
| 46 | }; | |
| 47 | ||
| 48 | template <class _Ret, class _T1> | |
| 49 | struct __enable_invoke_imp<_Ret, _T1*, false, false> { | |
| 50 | typedef typename add_lvalue_reference< | |
| 51 | typename __apply_cv<_T1, _Ret>::type | |
| 52 | >::type _Bullet4; | |
| 53 | typedef _Bullet4 type; | |
| 54 | }; | |
| 55 | ||
| 56 | template <class _Fn, class _T1, | |
| 57 | class _Traits = __member_pointer_traits<_Fn>, | |
| 58 | class _Ret = typename _Traits::_ReturnType, | |
| 59 | class _Class = typename _Traits::_ClassType> | |
| 60 | struct __enable_invoke : __enable_invoke_imp< | |
| 61 | _Ret, _T1, | |
| 62 | is_member_function_pointer<_Fn>::value, | |
| 63 | is_base_of<_Class, typename remove_reference<_T1>::type>::value> | |
| 64 | { | |
| 65 | }; | |
| 66 | ||
| 67 | __nat __invoke(__any, ...); | |
| 68 | ||
| 69 | // first bullet | |
| 70 | ||
| 71 | template <class _Fn, class _T1> | |
| 72 | inline _LIBCPP_INLINE_VISIBILITY | |
| 73 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 74 | __invoke(_Fn __f, _T1& __t1) { | |
| 75 | return (__t1.*__f)(); | |
| 76 | } | |
| 77 | ||
| 78 | template <class _Fn, class _T1, class _A0> | |
| 79 | inline _LIBCPP_INLINE_VISIBILITY | |
| 80 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 81 | __invoke(_Fn __f, _T1& __t1, _A0& __a0) { | |
| 82 | return (__t1.*__f)(__a0); | |
| 83 | } | |
| 84 | ||
| 85 | template <class _Fn, class _T1, class _A0, class _A1> | |
| 86 | inline _LIBCPP_INLINE_VISIBILITY | |
| 87 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 88 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { | |
| 89 | return (__t1.*__f)(__a0, __a1); | |
| 90 | } | |
| 91 | ||
| 92 | template <class _Fn, class _T1, class _A0, class _A1, class _A2> | |
| 93 | inline _LIBCPP_INLINE_VISIBILITY | |
| 94 | typename __enable_invoke<_Fn, _T1>::_Bullet1 | |
| 95 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { | |
| 96 | return (__t1.*__f)(__a0, __a1, __a2); | |
| 97 | } | |
| 98 | ||
| 99 | template <class _Fn, class _T1> | |
| 100 | inline _LIBCPP_INLINE_VISIBILITY | |
| 101 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 102 | __invoke(_Fn __f, _T1& __t1) { | |
| 103 | return ((*__t1).*__f)(); | |
| 104 | } | |
| 105 | ||
| 106 | template <class _Fn, class _T1, class _A0> | |
| 107 | inline _LIBCPP_INLINE_VISIBILITY | |
| 108 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 109 | __invoke(_Fn __f, _T1& __t1, _A0& __a0) { | |
| 110 | return ((*__t1).*__f)(__a0); | |
| 111 | } | |
| 112 | ||
| 113 | template <class _Fn, class _T1, class _A0, class _A1> | |
| 114 | inline _LIBCPP_INLINE_VISIBILITY | |
| 115 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 116 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { | |
| 117 | return ((*__t1).*__f)(__a0, __a1); | |
| 118 | } | |
| 119 | ||
| 120 | template <class _Fn, class _T1, class _A0, class _A1, class _A2> | |
| 121 | inline _LIBCPP_INLINE_VISIBILITY | |
| 122 | typename __enable_invoke<_Fn, _T1>::_Bullet2 | |
| 123 | __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { | |
| 124 | return ((*__t1).*__f)(__a0, __a1, __a2); | |
| 125 | } | |
| 126 | ||
| 127 | template <class _Fn, class _T1> | |
| 128 | inline _LIBCPP_INLINE_VISIBILITY | |
| 129 | typename __enable_invoke<_Fn, _T1>::_Bullet3 | |
| 130 | __invoke(_Fn __f, _T1& __t1) { | |
| 131 | return __t1.*__f; | |
| 132 | } | |
| 133 | ||
| 134 | template <class _Fn, class _T1> | |
| 135 | inline _LIBCPP_INLINE_VISIBILITY | |
| 136 | typename __enable_invoke<_Fn, _T1>::_Bullet4 | |
| 137 | __invoke(_Fn __f, _T1& __t1) { | |
| 138 | return (*__t1).*__f; | |
| 139 | } | |
| 140 | ||
| 141 | // fifth bullet | |
| 142 | ||
| 143 | template <class _Fp> | |
| 144 | inline _LIBCPP_INLINE_VISIBILITY | |
| 145 | decltype(declval<_Fp&>()()) | |
| 146 | __invoke(_Fp& __f) | |
| 147 | { | |
| 148 | return __f(); | |
| 149 | } | |
| 150 | ||
| 151 | template <class _Fp, class _A0> | |
| 152 | inline _LIBCPP_INLINE_VISIBILITY | |
| 153 | decltype(declval<_Fp&>()(declval<_A0&>())) | |
| 154 | __invoke(_Fp& __f, _A0& __a0) | |
| 155 | { | |
| 156 | return __f(__a0); | |
| 157 | } | |
| 158 | ||
| 159 | template <class _Fp, class _A0, class _A1> | |
| 160 | inline _LIBCPP_INLINE_VISIBILITY | |
| 161 | decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>())) | |
| 162 | __invoke(_Fp& __f, _A0& __a0, _A1& __a1) | |
| 163 | { | |
| 164 | return __f(__a0, __a1); | |
| 165 | } | |
| 166 | ||
| 167 | template <class _Fp, class _A0, class _A1, class _A2> | |
| 168 | inline _LIBCPP_INLINE_VISIBILITY | |
| 169 | decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>(), declval<_A2&>())) | |
| 170 | __invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2) | |
| 171 | { | |
| 172 | return __f(__a0, __a1, __a2); | |
| 173 | } | |
| 174 | ||
| 175 | template <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value> | |
| 176 | struct __invoke_return | |
| 177 | { | |
| 178 | typedef typename __weak_result_type<_Fp>::result_type type; | |
| 179 | }; | |
| 180 | ||
| 181 | template <class _Fp> | |
| 182 | struct __invoke_return<_Fp, false> | |
| 183 | { | |
| 184 | typedef decltype(_VSTD::__invoke(declval<_Fp&>())) type; | |
| 185 | }; | |
| 186 | ||
| 187 | template <class _Tp, class _A0> | |
| 188 | struct __invoke_return0 | |
| 189 | { | |
| 190 | typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>())) type; | |
| 191 | }; | |
| 192 | ||
| 193 | template <class _Rp, class _Tp, class _A0> | |
| 194 | struct __invoke_return0<_Rp _Tp::*, _A0> | |
| 195 | { | |
| 196 | typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type; | |
| 197 | }; | |
| 198 | ||
| 199 | template <class _Tp, class _A0, class _A1> | |
| 200 | struct __invoke_return1 | |
| 201 | { | |
| 202 | typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(), | |
| 203 | declval<_A1&>())) type; | |
| 204 | }; | |
| 205 | ||
| 206 | template <class _Rp, class _Class, class _A0, class _A1> | |
| 207 | struct __invoke_return1<_Rp _Class::*, _A0, _A1> { | |
| 208 | typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type; | |
| 209 | }; | |
| 210 | ||
| 211 | template <class _Tp, class _A0, class _A1, class _A2> | |
| 212 | struct __invoke_return2 | |
| 213 | { | |
| 214 | typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(), | |
| 215 | declval<_A1&>(), | |
| 216 | declval<_A2&>())) type; | |
| 217 | }; | |
| 218 | ||
| 219 | template <class _Ret, class _Class, class _A0, class _A1, class _A2> | |
| 220 | struct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> { | |
| 221 | typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type; | |
| 222 | }; | |
| 223 | #endif // _LIBCPP_FUNCTIONAL_BASE_03 |
lib/libcxx/include/__hash_table+33-33| ... | ... | @@ -10,16 +10,16 @@ |
| 10 | 10 | #ifndef _LIBCPP__HASH_TABLE |
| 11 | 11 | #define _LIBCPP__HASH_TABLE |
| 12 | 12 | |
| 13 | #include <__bits> // __libcpp_clz | |
| 13 | 14 | #include <__config> |
| 14 | #include <initializer_list> | |
| 15 | #include <memory> | |
| 16 | #include <iterator> | |
| 15 | #include <__debug> | |
| 17 | 16 | #include <algorithm> |
| 18 | 17 | #include <cmath> |
| 19 | #include <utility> | |
| 18 | #include <initializer_list> | |
| 19 | #include <iterator> | |
| 20 | #include <memory> | |
| 20 | 21 | #include <type_traits> |
| 21 | ||
| 22 | #include <__debug> | |
| 22 | #include <utility> | |
| 23 | 23 | |
| 24 | 24 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 25 | 25 | #pragma GCC system_header |
| ... | ... | @@ -89,7 +89,7 @@ struct __hash_node_base |
| 89 | 89 | }; |
| 90 | 90 | |
| 91 | 91 | template <class _Tp, class _VoidPtr> |
| 92 | struct __hash_node | |
| 92 | struct _LIBCPP_STANDALONE_DEBUG __hash_node | |
| 93 | 93 | : public __hash_node_base |
| 94 | 94 | < |
| 95 | 95 | typename __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type |
| ... | ... | @@ -317,7 +317,7 @@ public: |
| 317 | 317 | } |
| 318 | 318 | return *this; |
| 319 | 319 | } |
| 320 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 320 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 321 | 321 | |
| 322 | 322 | _LIBCPP_INLINE_VISIBILITY |
| 323 | 323 | reference operator*() const { |
| ... | ... | @@ -336,7 +336,7 @@ public: |
| 336 | 336 | _LIBCPP_INLINE_VISIBILITY |
| 337 | 337 | __hash_iterator& operator++() { |
| 338 | 338 | _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), |
| 339 | "Attempted to increment non-incrementable unordered container iterator"); | |
| 339 | "Attempted to increment a non-incrementable unordered container iterator"); | |
| 340 | 340 | __node_ = __node_->__next_; |
| 341 | 341 | return *this; |
| 342 | 342 | } |
| ... | ... | @@ -438,7 +438,7 @@ public: |
| 438 | 438 | } |
| 439 | 439 | return *this; |
| 440 | 440 | } |
| 441 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 441 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 442 | 442 | |
| 443 | 443 | _LIBCPP_INLINE_VISIBILITY |
| 444 | 444 | reference operator*() const { |
| ... | ... | @@ -456,7 +456,7 @@ public: |
| 456 | 456 | _LIBCPP_INLINE_VISIBILITY |
| 457 | 457 | __hash_const_iterator& operator++() { |
| 458 | 458 | _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), |
| 459 | "Attempted to increment non-incrementable unordered container const_iterator"); | |
| 459 | "Attempted to increment a non-incrementable unordered container const_iterator"); | |
| 460 | 460 | __node_ = __node_->__next_; |
| 461 | 461 | return *this; |
| 462 | 462 | } |
| ... | ... | @@ -550,7 +550,7 @@ public: |
| 550 | 550 | } |
| 551 | 551 | return *this; |
| 552 | 552 | } |
| 553 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 553 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 554 | 554 | |
| 555 | 555 | _LIBCPP_INLINE_VISIBILITY |
| 556 | 556 | reference operator*() const { |
| ... | ... | @@ -569,7 +569,7 @@ public: |
| 569 | 569 | _LIBCPP_INLINE_VISIBILITY |
| 570 | 570 | __hash_local_iterator& operator++() { |
| 571 | 571 | _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), |
| 572 | "Attempted to increment non-incrementable unordered container local_iterator"); | |
| 572 | "Attempted to increment a non-incrementable unordered container local_iterator"); | |
| 573 | 573 | __node_ = __node_->__next_; |
| 574 | 574 | if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) |
| 575 | 575 | __node_ = nullptr; |
| ... | ... | @@ -695,7 +695,7 @@ public: |
| 695 | 695 | } |
| 696 | 696 | return *this; |
| 697 | 697 | } |
| 698 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 698 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 699 | 699 | |
| 700 | 700 | _LIBCPP_INLINE_VISIBILITY |
| 701 | 701 | reference operator*() const { |
| ... | ... | @@ -714,7 +714,7 @@ public: |
| 714 | 714 | _LIBCPP_INLINE_VISIBILITY |
| 715 | 715 | __hash_const_local_iterator& operator++() { |
| 716 | 716 | _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), |
| 717 | "Attempted to increment non-incrementable unordered container const_local_iterator"); | |
| 717 | "Attempted to increment a non-incrementable unordered container const_local_iterator"); | |
| 718 | 718 | __node_ = __node_->__next_; |
| 719 | 719 | if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) |
| 720 | 720 | __node_ = nullptr; |
| ... | ... | @@ -741,9 +741,9 @@ public: |
| 741 | 741 | private: |
| 742 | 742 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 743 | 743 | _LIBCPP_INLINE_VISIBILITY |
| 744 | __hash_const_local_iterator(__next_pointer __node, size_t __bucket, | |
| 744 | __hash_const_local_iterator(__next_pointer __node_ptr, size_t __bucket, | |
| 745 | 745 | size_t __bucket_count, const void* __c) _NOEXCEPT |
| 746 | : __node_(__node), | |
| 746 | : __node_(__node_ptr), | |
| 747 | 747 | __bucket_(__bucket), |
| 748 | 748 | __bucket_count_(__bucket_count) |
| 749 | 749 | { |
| ... | ... | @@ -753,9 +753,9 @@ private: |
| 753 | 753 | } |
| 754 | 754 | #else |
| 755 | 755 | _LIBCPP_INLINE_VISIBILITY |
| 756 | __hash_const_local_iterator(__next_pointer __node, size_t __bucket, | |
| 756 | __hash_const_local_iterator(__next_pointer __node_ptr, size_t __bucket, | |
| 757 | 757 | size_t __bucket_count) _NOEXCEPT |
| 758 | : __node_(__node), | |
| 758 | : __node_(__node_ptr), | |
| 759 | 759 | __bucket_(__bucket), |
| 760 | 760 | __bucket_count_(__bucket_count) |
| 761 | 761 | { |
| ... | ... | @@ -1337,7 +1337,7 @@ public: |
| 1337 | 1337 | bool __addable(const const_iterator* __i, ptrdiff_t __n) const; |
| 1338 | 1338 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; |
| 1339 | 1339 | |
| 1340 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1340 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1341 | 1341 | |
| 1342 | 1342 | private: |
| 1343 | 1343 | void __rehash(size_type __n); |
| ... | ... | @@ -1645,7 +1645,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( |
| 1645 | 1645 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1646 | 1646 | try |
| 1647 | 1647 | { |
| 1648 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1648 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1649 | 1649 | const_iterator __i = __u.begin(); |
| 1650 | 1650 | while (__cache != nullptr && __u.size() != 0) |
| 1651 | 1651 | { |
| ... | ... | @@ -1662,7 +1662,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( |
| 1662 | 1662 | __deallocate_node(__cache); |
| 1663 | 1663 | throw; |
| 1664 | 1664 | } |
| 1665 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1665 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1666 | 1666 | __deallocate_node(__cache); |
| 1667 | 1667 | } |
| 1668 | 1668 | const_iterator __i = __u.begin(); |
| ... | ... | @@ -1707,7 +1707,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first |
| 1707 | 1707 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1708 | 1708 | try |
| 1709 | 1709 | { |
| 1710 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1710 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1711 | 1711 | for (; __cache != nullptr && __first != __last; ++__first) |
| 1712 | 1712 | { |
| 1713 | 1713 | __cache->__upcast()->__value_ = *__first; |
| ... | ... | @@ -1722,7 +1722,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first |
| 1722 | 1722 | __deallocate_node(__cache); |
| 1723 | 1723 | throw; |
| 1724 | 1724 | } |
| 1725 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1725 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1726 | 1726 | __deallocate_node(__cache); |
| 1727 | 1727 | } |
| 1728 | 1728 | for (; __first != __last; ++__first) |
| ... | ... | @@ -1747,7 +1747,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, |
| 1747 | 1747 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1748 | 1748 | try |
| 1749 | 1749 | { |
| 1750 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1750 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1751 | 1751 | for (; __cache != nullptr && __first != __last; ++__first) |
| 1752 | 1752 | { |
| 1753 | 1753 | __cache->__upcast()->__value_ = *__first; |
| ... | ... | @@ -1762,7 +1762,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, |
| 1762 | 1762 | __deallocate_node(__cache); |
| 1763 | 1763 | throw; |
| 1764 | 1764 | } |
| 1765 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1765 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1766 | 1766 | __deallocate_node(__cache); |
| 1767 | 1767 | } |
| 1768 | 1768 | for (; __first != __last; ++__first) |
| ... | ... | @@ -2299,7 +2299,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi( |
| 2299 | 2299 | __node_insert_multi_perform(__src_ptr, __pn); |
| 2300 | 2300 | } |
| 2301 | 2301 | } |
| 2302 | #endif // _LIBCPP_STD_VER > 14 | |
| 2302 | #endif // _LIBCPP_STD_VER > 14 | |
| 2303 | 2303 | |
| 2304 | 2304 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
| 2305 | 2305 | void |
| ... | ... | @@ -2506,11 +2506,11 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, |
| 2506 | 2506 | { |
| 2507 | 2507 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 2508 | 2508 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, |
| 2509 | "unodered container::erase(iterator, iterator) called with an iterator not" | |
| 2510 | " referring to this unodered container"); | |
| 2509 | "unordered container::erase(iterator, iterator) called with an iterator not" | |
| 2510 | " referring to this container"); | |
| 2511 | 2511 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this, |
| 2512 | "unodered container::erase(iterator, iterator) called with an iterator not" | |
| 2513 | " referring to this unodered container"); | |
| 2512 | "unordered container::erase(iterator, iterator) called with an iterator not" | |
| 2513 | " referring to this container"); | |
| 2514 | 2514 | #endif |
| 2515 | 2515 | for (const_iterator __p = __first; __first != __last; __p = __first) |
| 2516 | 2516 | { |
| ... | ... | @@ -2804,10 +2804,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, |
| 2804 | 2804 | return false; |
| 2805 | 2805 | } |
| 2806 | 2806 | |
| 2807 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2807 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2808 | 2808 | |
| 2809 | 2809 | _LIBCPP_END_NAMESPACE_STD |
| 2810 | 2810 | |
| 2811 | 2811 | _LIBCPP_POP_MACROS |
| 2812 | 2812 | |
| 2813 | #endif // _LIBCPP__HASH_TABLE | |
| 2813 | #endif // _LIBCPP__HASH_TABLE |
lib/libcxx/include/__iterator/access.h created+134| ... | ... | @@ -0,0 +1,134 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ACCESS_H | |
| 11 | #define _LIBCPP___ITERATOR_ACCESS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _Tp, size_t _Np> | |
| 26 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 27 | _Tp* | |
| 28 | begin(_Tp (&__array)[_Np]) | |
| 29 | { | |
| 30 | return __array; | |
| 31 | } | |
| 32 | ||
| 33 | template <class _Tp, size_t _Np> | |
| 34 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 35 | _Tp* | |
| 36 | end(_Tp (&__array)[_Np]) | |
| 37 | { | |
| 38 | return __array + _Np; | |
| 39 | } | |
| 40 | ||
| 41 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 42 | ||
| 43 | template <class _Cp> | |
| 44 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 45 | auto | |
| 46 | begin(_Cp& __c) -> decltype(__c.begin()) | |
| 47 | { | |
| 48 | return __c.begin(); | |
| 49 | } | |
| 50 | ||
| 51 | template <class _Cp> | |
| 52 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 53 | auto | |
| 54 | begin(const _Cp& __c) -> decltype(__c.begin()) | |
| 55 | { | |
| 56 | return __c.begin(); | |
| 57 | } | |
| 58 | ||
| 59 | template <class _Cp> | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 61 | auto | |
| 62 | end(_Cp& __c) -> decltype(__c.end()) | |
| 63 | { | |
| 64 | return __c.end(); | |
| 65 | } | |
| 66 | ||
| 67 | template <class _Cp> | |
| 68 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 69 | auto | |
| 70 | end(const _Cp& __c) -> decltype(__c.end()) | |
| 71 | { | |
| 72 | return __c.end(); | |
| 73 | } | |
| 74 | ||
| 75 | #if _LIBCPP_STD_VER > 11 | |
| 76 | ||
| 77 | template <class _Cp> | |
| 78 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 79 | auto cbegin(const _Cp& __c) -> decltype(_VSTD::begin(__c)) | |
| 80 | { | |
| 81 | return _VSTD::begin(__c); | |
| 82 | } | |
| 83 | ||
| 84 | template <class _Cp> | |
| 85 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 86 | auto cend(const _Cp& __c) -> decltype(_VSTD::end(__c)) | |
| 87 | { | |
| 88 | return _VSTD::end(__c); | |
| 89 | } | |
| 90 | ||
| 91 | #endif | |
| 92 | ||
| 93 | ||
| 94 | #else // defined(_LIBCPP_CXX03_LANG) | |
| 95 | ||
| 96 | template <class _Cp> | |
| 97 | _LIBCPP_INLINE_VISIBILITY | |
| 98 | typename _Cp::iterator | |
| 99 | begin(_Cp& __c) | |
| 100 | { | |
| 101 | return __c.begin(); | |
| 102 | } | |
| 103 | ||
| 104 | template <class _Cp> | |
| 105 | _LIBCPP_INLINE_VISIBILITY | |
| 106 | typename _Cp::const_iterator | |
| 107 | begin(const _Cp& __c) | |
| 108 | { | |
| 109 | return __c.begin(); | |
| 110 | } | |
| 111 | ||
| 112 | template <class _Cp> | |
| 113 | _LIBCPP_INLINE_VISIBILITY | |
| 114 | typename _Cp::iterator | |
| 115 | end(_Cp& __c) | |
| 116 | { | |
| 117 | return __c.end(); | |
| 118 | } | |
| 119 | ||
| 120 | template <class _Cp> | |
| 121 | _LIBCPP_INLINE_VISIBILITY | |
| 122 | typename _Cp::const_iterator | |
| 123 | end(const _Cp& __c) | |
| 124 | { | |
| 125 | return __c.end(); | |
| 126 | } | |
| 127 | ||
| 128 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 129 | ||
| 130 | _LIBCPP_END_NAMESPACE_STD | |
| 131 | ||
| 132 | _LIBCPP_POP_MACROS | |
| 133 | ||
| 134 | #endif // _LIBCPP___ITERATOR_ACCESS_H |
lib/libcxx/include/__iterator/advance.h created+200| ... | ... | @@ -0,0 +1,200 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ADVANCE_H | |
| 11 | #define _LIBCPP___ITERATOR_ADVANCE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__debug> | |
| 15 | #include <__function_like.h> | |
| 16 | #include <__iterator/concepts.h> | |
| 17 | #include <__iterator/incrementable_traits.h> | |
| 18 | #include <__iterator/iterator_traits.h> | |
| 19 | #include <__utility/move.h> | |
| 20 | #include <cstdlib> | |
| 21 | #include <concepts> | |
| 22 | #include <limits> | |
| 23 | #include <type_traits> | |
| 24 | ||
| 25 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 26 | #pragma GCC system_header | |
| 27 | #endif | |
| 28 | ||
| 29 | _LIBCPP_PUSH_MACROS | |
| 30 | #include <__undef_macros> | |
| 31 | ||
| 32 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 33 | ||
| 34 | template <class _InputIter> | |
| 35 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 36 | void __advance(_InputIter& __i, typename iterator_traits<_InputIter>::difference_type __n, input_iterator_tag) { | |
| 37 | for (; __n > 0; --__n) | |
| 38 | ++__i; | |
| 39 | } | |
| 40 | ||
| 41 | template <class _BiDirIter> | |
| 42 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 43 | void __advance(_BiDirIter& __i, typename iterator_traits<_BiDirIter>::difference_type __n, bidirectional_iterator_tag) { | |
| 44 | if (__n >= 0) | |
| 45 | for (; __n > 0; --__n) | |
| 46 | ++__i; | |
| 47 | else | |
| 48 | for (; __n < 0; ++__n) | |
| 49 | --__i; | |
| 50 | } | |
| 51 | ||
| 52 | template <class _RandIter> | |
| 53 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 54 | void __advance(_RandIter& __i, typename iterator_traits<_RandIter>::difference_type __n, random_access_iterator_tag) { | |
| 55 | __i += __n; | |
| 56 | } | |
| 57 | ||
| 58 | template < | |
| 59 | class _InputIter, class _Distance, | |
| 60 | class _IntegralDistance = decltype(_VSTD::__convert_to_integral(declval<_Distance>())), | |
| 61 | class = _EnableIf<is_integral<_IntegralDistance>::value> > | |
| 62 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 63 | void advance(_InputIter& __i, _Distance __orig_n) { | |
| 64 | typedef typename iterator_traits<_InputIter>::difference_type _Difference; | |
| 65 | _Difference __n = static_cast<_Difference>(_VSTD::__convert_to_integral(__orig_n)); | |
| 66 | _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, | |
| 67 | "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); | |
| 68 | _VSTD::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category()); | |
| 69 | } | |
| 70 | ||
| 71 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 72 | ||
| 73 | namespace ranges { | |
| 74 | // [range.iter.op.advance] | |
| 75 | struct __advance_fn final : private __function_like { | |
| 76 | private: | |
| 77 | template <class _Tp> | |
| 78 | _LIBCPP_HIDE_FROM_ABI | |
| 79 | static constexpr _Tp __magnitude_geq(_Tp __a, _Tp __b) noexcept { | |
| 80 | return __a < 0 ? (__a <= __b) : (__a >= __b); | |
| 81 | } | |
| 82 | ||
| 83 | template <class _Ip> | |
| 84 | _LIBCPP_HIDE_FROM_ABI | |
| 85 | static constexpr void __advance_forward(_Ip& __i, iter_difference_t<_Ip> __n) { | |
| 86 | while (__n > 0) { | |
| 87 | --__n; | |
| 88 | ++__i; | |
| 89 | } | |
| 90 | } | |
| 91 | ||
| 92 | template <class _Ip> | |
| 93 | _LIBCPP_HIDE_FROM_ABI | |
| 94 | static constexpr void __advance_backward(_Ip& __i, iter_difference_t<_Ip> __n) { | |
| 95 | while (__n < 0) { | |
| 96 | ++__n; | |
| 97 | --__i; | |
| 98 | } | |
| 99 | } | |
| 100 | ||
| 101 | public: | |
| 102 | constexpr explicit __advance_fn(__tag __x) noexcept : __function_like(__x) {} | |
| 103 | ||
| 104 | // Preconditions: If `I` does not model `bidirectional_iterator`, `n` is not negative. | |
| 105 | template <input_or_output_iterator _Ip> | |
| 106 | _LIBCPP_HIDE_FROM_ABI | |
| 107 | constexpr void operator()(_Ip& __i, iter_difference_t<_Ip> __n) const { | |
| 108 | _LIBCPP_ASSERT(__n >= 0 || bidirectional_iterator<_Ip>, | |
| 109 | "If `n < 0`, then `bidirectional_iterator<I>` must be true."); | |
| 110 | ||
| 111 | // If `I` models `random_access_iterator`, equivalent to `i += n`. | |
| 112 | if constexpr (random_access_iterator<_Ip>) { | |
| 113 | __i += __n; | |
| 114 | return; | |
| 115 | } else if constexpr (bidirectional_iterator<_Ip>) { | |
| 116 | // Otherwise, if `n` is non-negative, increments `i` by `n`. | |
| 117 | __advance_forward(__i, __n); | |
| 118 | // Otherwise, decrements `i` by `-n`. | |
| 119 | __advance_backward(__i, __n); | |
| 120 | return; | |
| 121 | } else { | |
| 122 | // Otherwise, if `n` is non-negative, increments `i` by `n`. | |
| 123 | __advance_forward(__i, __n); | |
| 124 | return; | |
| 125 | } | |
| 126 | } | |
| 127 | ||
| 128 | // Preconditions: Either `assignable_from<I&, S> || sized_sentinel_for<S, I>` is modeled, or [i, bound) denotes a range. | |
| 129 | template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp> | |
| 130 | _LIBCPP_HIDE_FROM_ABI | |
| 131 | constexpr void operator()(_Ip& __i, _Sp __bound) const { | |
| 132 | // If `I` and `S` model `assignable_from<I&, S>`, equivalent to `i = std::move(bound)`. | |
| 133 | if constexpr (assignable_from<_Ip&, _Sp>) { | |
| 134 | __i = _VSTD::move(__bound); | |
| 135 | } | |
| 136 | // Otherwise, if `S` and `I` model `sized_sentinel_for<S, I>`, equivalent to `ranges::advance(i, bound - i)`. | |
| 137 | else if constexpr (sized_sentinel_for<_Sp, _Ip>) { | |
| 138 | (*this)(__i, __bound - __i); | |
| 139 | } | |
| 140 | // Otherwise, while `bool(i != bound)` is true, increments `i`. | |
| 141 | else { | |
| 142 | while (__i != __bound) { | |
| 143 | ++__i; | |
| 144 | } | |
| 145 | } | |
| 146 | } | |
| 147 | ||
| 148 | // Preconditions: | |
| 149 | // * If `n > 0`, [i, bound) denotes a range. | |
| 150 | // * If `n == 0`, [i, bound) or [bound, i) denotes a range. | |
| 151 | // * If `n < 0`, [bound, i) denotes a range, `I` models `bidirectional_iterator`, and `I` and `S` model `same_as<I, S>`. | |
| 152 | // Returns: `n - M`, where `M` is the difference between the the ending and starting position. | |
| 153 | template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp> | |
| 154 | _LIBCPP_HIDE_FROM_ABI | |
| 155 | constexpr iter_difference_t<_Ip> operator()(_Ip& __i, iter_difference_t<_Ip> __n, _Sp __bound) const { | |
| 156 | _LIBCPP_ASSERT((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>), | |
| 157 | "If `n < 0`, then `bidirectional_iterator<I> && same_as<I, S>` must be true."); | |
| 158 | // If `S` and `I` model `sized_sentinel_for<S, I>`: | |
| 159 | if constexpr (sized_sentinel_for<_Sp, _Ip>) { | |
| 160 | // If |n| >= |bound - i|, equivalent to `ranges::advance(i, bound)`. | |
| 161 | if (const auto __M = __bound - __i; __magnitude_geq(__n, __M)) { | |
| 162 | (*this)(__i, __bound); | |
| 163 | return __n - __M; | |
| 164 | } | |
| 165 | ||
| 166 | // Otherwise, equivalent to `ranges::advance(i, n)`. | |
| 167 | (*this)(__i, __n); | |
| 168 | return 0; | |
| 169 | } else { | |
| 170 | // Otherwise, if `n` is non-negative, while `bool(i != bound)` is true, increments `i` but at | |
| 171 | // most `n` times. | |
| 172 | while (__i != __bound && __n > 0) { | |
| 173 | ++__i; | |
| 174 | --__n; | |
| 175 | } | |
| 176 | ||
| 177 | // Otherwise, while `bool(i != bound)` is true, decrements `i` but at most `-n` times. | |
| 178 | if constexpr (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>) { | |
| 179 | while (__i != __bound && __n < 0) { | |
| 180 | --__i; | |
| 181 | ++__n; | |
| 182 | } | |
| 183 | } | |
| 184 | return __n; | |
| 185 | } | |
| 186 | ||
| 187 | _LIBCPP_UNREACHABLE(); | |
| 188 | } | |
| 189 | }; | |
| 190 | ||
| 191 | inline constexpr auto advance = __advance_fn(__function_like::__tag()); | |
| 192 | } // namespace ranges | |
| 193 | ||
| 194 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 195 | ||
| 196 | _LIBCPP_END_NAMESPACE_STD | |
| 197 | ||
| 198 | _LIBCPP_POP_MACROS | |
| 199 | ||
| 200 | #endif // _LIBCPP___ITERATOR_ADVANCE_H |
lib/libcxx/include/__iterator/back_insert_iterator.h created+75| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/addressof.h> | |
| 17 | #include <__utility/move.h> | |
| 18 | #include <cstddef> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 30 | template <class _Container> | |
| 31 | class _LIBCPP_TEMPLATE_VIS back_insert_iterator | |
| 32 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 33 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 34 | #endif | |
| 35 | { | |
| 36 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 37 | protected: | |
| 38 | _Container* container; | |
| 39 | public: | |
| 40 | typedef output_iterator_tag iterator_category; | |
| 41 | typedef void value_type; | |
| 42 | #if _LIBCPP_STD_VER > 17 | |
| 43 | typedef ptrdiff_t difference_type; | |
| 44 | #else | |
| 45 | typedef void difference_type; | |
| 46 | #endif | |
| 47 | typedef void pointer; | |
| 48 | typedef void reference; | |
| 49 | typedef _Container container_type; | |
| 50 | ||
| 51 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit back_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} | |
| 52 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator=(const typename _Container::value_type& __value_) | |
| 53 | {container->push_back(__value_); return *this;} | |
| 54 | #ifndef _LIBCPP_CXX03_LANG | |
| 55 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator=(typename _Container::value_type&& __value_) | |
| 56 | {container->push_back(_VSTD::move(__value_)); return *this;} | |
| 57 | #endif // _LIBCPP_CXX03_LANG | |
| 58 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator*() {return *this;} | |
| 59 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator++() {return *this;} | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator operator++(int) {return *this;} | |
| 61 | }; | |
| 62 | ||
| 63 | template <class _Container> | |
| 64 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 65 | back_insert_iterator<_Container> | |
| 66 | back_inserter(_Container& __x) | |
| 67 | { | |
| 68 | return back_insert_iterator<_Container>(__x); | |
| 69 | } | |
| 70 | ||
| 71 | _LIBCPP_END_NAMESPACE_STD | |
| 72 | ||
| 73 | _LIBCPP_POP_MACROS | |
| 74 | ||
| 75 | #endif // _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H |
lib/libcxx/include/__iterator/common_iterator.h created+301| ... | ... | @@ -0,0 +1,301 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_COMMON_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_COMMON_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__debug> | |
| 15 | #include <__iterator/concepts.h> | |
| 16 | #include <__iterator/incrementable_traits.h> | |
| 17 | #include <__iterator/iter_move.h> | |
| 18 | #include <__iterator/iter_swap.h> | |
| 19 | #include <__iterator/iterator_traits.h> | |
| 20 | #include <__iterator/readable_traits.h> | |
| 21 | #include <concepts> | |
| 22 | #include <variant> | |
| 23 | ||
| 24 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 25 | #pragma GCC system_header | |
| 26 | #endif | |
| 27 | ||
| 28 | _LIBCPP_PUSH_MACROS | |
| 29 | #include <__undef_macros> | |
| 30 | ||
| 31 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 32 | ||
| 33 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 34 | ||
| 35 | template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> | |
| 36 | requires (!same_as<_Iter, _Sent> && copyable<_Iter>) | |
| 37 | class common_iterator { | |
| 38 | class __proxy { | |
| 39 | friend common_iterator; | |
| 40 | ||
| 41 | iter_value_t<_Iter> __value; | |
| 42 | // We can move __x because the only caller verifies that __x is not a reference. | |
| 43 | constexpr __proxy(iter_reference_t<_Iter>&& __x) | |
| 44 | : __value(_VSTD::move(__x)) {} | |
| 45 | ||
| 46 | public: | |
| 47 | const iter_value_t<_Iter>* operator->() const { | |
| 48 | return _VSTD::addressof(__value); | |
| 49 | } | |
| 50 | }; | |
| 51 | ||
| 52 | class __postfix_proxy { | |
| 53 | friend common_iterator; | |
| 54 | ||
| 55 | iter_value_t<_Iter> __value; | |
| 56 | constexpr __postfix_proxy(iter_reference_t<_Iter>&& __x) | |
| 57 | : __value(_VSTD::forward<iter_reference_t<_Iter>>(__x)) {} | |
| 58 | ||
| 59 | public: | |
| 60 | constexpr static bool __valid_for_iter = | |
| 61 | constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>> && | |
| 62 | move_constructible<iter_value_t<_Iter>>; | |
| 63 | ||
| 64 | const iter_value_t<_Iter>& operator*() const { | |
| 65 | return __value; | |
| 66 | } | |
| 67 | }; | |
| 68 | ||
| 69 | public: | |
| 70 | variant<_Iter, _Sent> __hold_; | |
| 71 | ||
| 72 | common_iterator() requires default_initializable<_Iter> = default; | |
| 73 | ||
| 74 | constexpr common_iterator(_Iter __i) : __hold_(in_place_type<_Iter>, _VSTD::move(__i)) {} | |
| 75 | constexpr common_iterator(_Sent __s) : __hold_(in_place_type<_Sent>, _VSTD::move(__s)) {} | |
| 76 | ||
| 77 | template<class _I2, class _S2> | |
| 78 | requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent> | |
| 79 | constexpr common_iterator(const common_iterator<_I2, _S2>& __other) | |
| 80 | : __hold_([&]() -> variant<_Iter, _Sent> { | |
| 81 | _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Constructed from valueless iterator."); | |
| 82 | if (__other.__hold_.index() == 0) | |
| 83 | return variant<_Iter, _Sent>{in_place_index<0>, _VSTD::__unchecked_get<0>(__other.__hold_)}; | |
| 84 | return variant<_Iter, _Sent>{in_place_index<1>, _VSTD::__unchecked_get<1>(__other.__hold_)}; | |
| 85 | }()) {} | |
| 86 | ||
| 87 | template<class _I2, class _S2> | |
| 88 | requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent> && | |
| 89 | assignable_from<_Iter&, const _I2&> && assignable_from<_Sent&, const _S2&> | |
| 90 | common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { | |
| 91 | _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Assigned from valueless iterator."); | |
| 92 | ||
| 93 | auto __idx = __hold_.index(); | |
| 94 | auto __other_idx = __other.__hold_.index(); | |
| 95 | ||
| 96 | // If they're the same index, just assign. | |
| 97 | if (__idx == 0 && __other_idx == 0) | |
| 98 | _VSTD::__unchecked_get<0>(__hold_) = _VSTD::__unchecked_get<0>(__other.__hold_); | |
| 99 | else if (__idx == 1 && __other_idx == 1) | |
| 100 | _VSTD::__unchecked_get<1>(__hold_) = _VSTD::__unchecked_get<1>(__other.__hold_); | |
| 101 | ||
| 102 | // Otherwise replace with the oposite element. | |
| 103 | else if (__other_idx == 1) | |
| 104 | __hold_.template emplace<1>(_VSTD::__unchecked_get<1>(__other.__hold_)); | |
| 105 | else if (__other_idx == 0) | |
| 106 | __hold_.template emplace<0>(_VSTD::__unchecked_get<0>(__other.__hold_)); | |
| 107 | ||
| 108 | return *this; | |
| 109 | } | |
| 110 | ||
| 111 | decltype(auto) operator*() | |
| 112 | { | |
| 113 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), | |
| 114 | "Cannot dereference sentinel. Common iterator not holding an iterator."); | |
| 115 | return *_VSTD::__unchecked_get<_Iter>(__hold_); | |
| 116 | } | |
| 117 | ||
| 118 | decltype(auto) operator*() const | |
| 119 | requires __dereferenceable<const _Iter> | |
| 120 | { | |
| 121 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), | |
| 122 | "Cannot dereference sentinel. Common iterator not holding an iterator."); | |
| 123 | return *_VSTD::__unchecked_get<_Iter>(__hold_); | |
| 124 | } | |
| 125 | ||
| 126 | template<class _I2 = _Iter> | |
| 127 | decltype(auto) operator->() const | |
| 128 | requires indirectly_readable<const _I2> && | |
| 129 | (requires(const _I2& __i) { __i.operator->(); } || | |
| 130 | is_reference_v<iter_reference_t<_I2>> || | |
| 131 | constructible_from<iter_value_t<_I2>, iter_reference_t<_I2>>) | |
| 132 | { | |
| 133 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), | |
| 134 | "Cannot dereference sentinel. Common iterator not holding an iterator."); | |
| 135 | ||
| 136 | if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) { | |
| 137 | return _VSTD::__unchecked_get<_Iter>(__hold_); | |
| 138 | } else if constexpr (is_reference_v<iter_reference_t<_Iter>>) { | |
| 139 | auto&& __tmp = *_VSTD::__unchecked_get<_Iter>(__hold_); | |
| 140 | return _VSTD::addressof(__tmp); | |
| 141 | } else { | |
| 142 | return __proxy(*_VSTD::__unchecked_get<_Iter>(__hold_)); | |
| 143 | } | |
| 144 | } | |
| 145 | ||
| 146 | common_iterator& operator++() { | |
| 147 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), | |
| 148 | "Cannot increment sentinel. Common iterator not holding an iterator."); | |
| 149 | ++_VSTD::__unchecked_get<_Iter>(__hold_); return *this; | |
| 150 | } | |
| 151 | ||
| 152 | decltype(auto) operator++(int) { | |
| 153 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), | |
| 154 | "Cannot increment sentinel. Common iterator not holding an iterator."); | |
| 155 | ||
| 156 | if constexpr (forward_iterator<_Iter>) { | |
| 157 | auto __tmp = *this; | |
| 158 | ++*this; | |
| 159 | return __tmp; | |
| 160 | } else if constexpr (requires (_Iter& __i) { { *__i++ } -> __referenceable; } || | |
| 161 | !__postfix_proxy::__valid_for_iter) { | |
| 162 | return _VSTD::__unchecked_get<_Iter>(__hold_)++; | |
| 163 | } else { | |
| 164 | __postfix_proxy __p(**this); | |
| 165 | ++*this; | |
| 166 | return __p; | |
| 167 | } | |
| 168 | } | |
| 169 | ||
| 170 | template<class _I2, sentinel_for<_Iter> _S2> | |
| 171 | requires sentinel_for<_Sent, _I2> | |
| 172 | friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { | |
| 173 | _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() && | |
| 174 | !__y.__hold_.valueless_by_exception(), | |
| 175 | "One or both common_iterators are valueless. (Cannot compare valueless iterators.)"); | |
| 176 | ||
| 177 | auto __x_index = __x.__hold_.index(); | |
| 178 | auto __y_index = __y.__hold_.index(); | |
| 179 | ||
| 180 | if (__x_index == __y_index) | |
| 181 | return true; | |
| 182 | ||
| 183 | if (__x_index == 0) | |
| 184 | return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_S2>(__y.__hold_); | |
| 185 | ||
| 186 | return _VSTD::__unchecked_get<_Sent>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_); | |
| 187 | } | |
| 188 | ||
| 189 | template<class _I2, sentinel_for<_Iter> _S2> | |
| 190 | requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2> | |
| 191 | friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { | |
| 192 | _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() && | |
| 193 | !__y.__hold_.valueless_by_exception(), | |
| 194 | "One or both common_iterators are valueless. (Cannot compare valueless iterators.)"); | |
| 195 | ||
| 196 | auto __x_index = __x.__hold_.index(); | |
| 197 | auto __y_index = __y.__hold_.index(); | |
| 198 | ||
| 199 | if (__x_index == 1 && __y_index == 1) | |
| 200 | return true; | |
| 201 | ||
| 202 | if (__x_index == 0 && __y_index == 0) | |
| 203 | return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_); | |
| 204 | ||
| 205 | if (__x_index == 0) | |
| 206 | return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_S2>(__y.__hold_); | |
| 207 | ||
| 208 | return _VSTD::__unchecked_get<_Sent>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_); | |
| 209 | } | |
| 210 | ||
| 211 | template<sized_sentinel_for<_Iter> _I2, sized_sentinel_for<_Iter> _S2> | |
| 212 | requires sized_sentinel_for<_Sent, _I2> | |
| 213 | friend iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { | |
| 214 | _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() && | |
| 215 | !__y.__hold_.valueless_by_exception(), | |
| 216 | "One or both common_iterators are valueless. (Cannot subtract valueless iterators.)"); | |
| 217 | ||
| 218 | auto __x_index = __x.__hold_.index(); | |
| 219 | auto __y_index = __y.__hold_.index(); | |
| 220 | ||
| 221 | if (__x_index == 1 && __y_index == 1) | |
| 222 | return 0; | |
| 223 | ||
| 224 | if (__x_index == 0 && __y_index == 0) | |
| 225 | return _VSTD::__unchecked_get<_Iter>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_); | |
| 226 | ||
| 227 | if (__x_index == 0) | |
| 228 | return _VSTD::__unchecked_get<_Iter>(__x.__hold_) - _VSTD::__unchecked_get<_S2>(__y.__hold_); | |
| 229 | ||
| 230 | return _VSTD::__unchecked_get<_Sent>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_); | |
| 231 | } | |
| 232 | ||
| 233 | friend iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i) | |
| 234 | noexcept(noexcept(ranges::iter_move(declval<const _Iter&>()))) | |
| 235 | requires input_iterator<_Iter> | |
| 236 | { | |
| 237 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_), | |
| 238 | "Cannot iter_move a sentinel. Common iterator not holding an iterator."); | |
| 239 | return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_)); | |
| 240 | } | |
| 241 | ||
| 242 | template<indirectly_swappable<_Iter> _I2, class _S2> | |
| 243 | friend void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) | |
| 244 | noexcept(noexcept(ranges::iter_swap(declval<const _Iter&>(), declval<const _I2&>()))) | |
| 245 | { | |
| 246 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_), | |
| 247 | "Cannot swap __y with a sentinel. Common iterator (__x) not holding an iterator."); | |
| 248 | _LIBCPP_ASSERT(holds_alternative<_Iter>(__y.__hold_), | |
| 249 | "Cannot swap __x with a sentinel. Common iterator (__y) not holding an iterator."); | |
| 250 | return ranges::iter_swap( _VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_Iter>(__y.__hold_)); | |
| 251 | } | |
| 252 | }; | |
| 253 | ||
| 254 | template<class _Iter, class _Sent> | |
| 255 | struct incrementable_traits<common_iterator<_Iter, _Sent>> { | |
| 256 | using difference_type = iter_difference_t<_Iter>; | |
| 257 | }; | |
| 258 | ||
| 259 | template<class _Iter> | |
| 260 | concept __denotes_forward_iter = | |
| 261 | requires { typename iterator_traits<_Iter>::iterator_category; } && | |
| 262 | derived_from<typename iterator_traits<_Iter>::iterator_category, forward_iterator_tag>; | |
| 263 | ||
| 264 | template<class _Iter, class _Sent> | |
| 265 | concept __common_iter_has_ptr_op = requires(const common_iterator<_Iter, _Sent>& __a) { | |
| 266 | __a.operator->(); | |
| 267 | }; | |
| 268 | ||
| 269 | template<class, class> | |
| 270 | struct __arrow_type_or_void { | |
| 271 | using type = void; | |
| 272 | }; | |
| 273 | ||
| 274 | template<class _Iter, class _Sent> | |
| 275 | requires __common_iter_has_ptr_op<_Iter, _Sent> | |
| 276 | struct __arrow_type_or_void<_Iter, _Sent> { | |
| 277 | using type = decltype(declval<const common_iterator<_Iter, _Sent>>().operator->()); | |
| 278 | }; | |
| 279 | ||
| 280 | template<class _Iter, class _Sent> | |
| 281 | struct iterator_traits<common_iterator<_Iter, _Sent>> { | |
| 282 | using iterator_concept = _If<forward_iterator<_Iter>, | |
| 283 | forward_iterator_tag, | |
| 284 | input_iterator_tag>; | |
| 285 | using iterator_category = _If<__denotes_forward_iter<_Iter>, | |
| 286 | forward_iterator_tag, | |
| 287 | input_iterator_tag>; | |
| 288 | using pointer = typename __arrow_type_or_void<_Iter, _Sent>::type; | |
| 289 | using value_type = iter_value_t<_Iter>; | |
| 290 | using difference_type = iter_difference_t<_Iter>; | |
| 291 | using reference = iter_reference_t<_Iter>; | |
| 292 | }; | |
| 293 | ||
| 294 | ||
| 295 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 296 | ||
| 297 | _LIBCPP_END_NAMESPACE_STD | |
| 298 | ||
| 299 | _LIBCPP_POP_MACROS | |
| 300 | ||
| 301 | #endif // _LIBCPP___ITERATOR_COMMON_ITERATOR_H |
lib/libcxx/include/__iterator/concepts.h created+272| ... | ... | @@ -0,0 +1,272 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_CONCEPTS_H | |
| 11 | #define _LIBCPP___ITERATOR_CONCEPTS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/incrementable_traits.h> | |
| 15 | #include <__iterator/iter_move.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <__iterator/readable_traits.h> | |
| 18 | #include <__memory/pointer_traits.h> | |
| 19 | #include <__utility/forward.h> | |
| 20 | #include <concepts> | |
| 21 | #include <type_traits> | |
| 22 | ||
| 23 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 24 | #pragma GCC system_header | |
| 25 | #endif | |
| 26 | ||
| 27 | _LIBCPP_PUSH_MACROS | |
| 28 | #include <__undef_macros> | |
| 29 | ||
| 30 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 31 | ||
| 32 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 33 | ||
| 34 | // clang-format off | |
| 35 | ||
| 36 | // [iterator.concept.readable] | |
| 37 | template<class _In> | |
| 38 | concept __indirectly_readable_impl = | |
| 39 | requires(const _In __i) { | |
| 40 | typename iter_value_t<_In>; | |
| 41 | typename iter_reference_t<_In>; | |
| 42 | typename iter_rvalue_reference_t<_In>; | |
| 43 | { *__i } -> same_as<iter_reference_t<_In>>; | |
| 44 | { ranges::iter_move(__i) } -> same_as<iter_rvalue_reference_t<_In>>; | |
| 45 | } && | |
| 46 | common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&> && | |
| 47 | common_reference_with<iter_reference_t<_In>&&, iter_rvalue_reference_t<_In>&&> && | |
| 48 | common_reference_with<iter_rvalue_reference_t<_In>&&, const iter_value_t<_In>&>; | |
| 49 | ||
| 50 | template<class _In> | |
| 51 | concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>; | |
| 52 | ||
| 53 | template<indirectly_readable _Tp> | |
| 54 | using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>; | |
| 55 | ||
| 56 | // [iterator.concept.writable] | |
| 57 | template<class _Out, class _Tp> | |
| 58 | concept indirectly_writable = | |
| 59 | requires(_Out&& __o, _Tp&& __t) { | |
| 60 | *__o = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving | |
| 61 | *_VSTD::forward<_Out>(__o) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving | |
| 62 | const_cast<const iter_reference_t<_Out>&&>(*__o) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving | |
| 63 | const_cast<const iter_reference_t<_Out>&&>(*_VSTD::forward<_Out>(__o)) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving | |
| 64 | }; | |
| 65 | ||
| 66 | // [iterator.concept.winc] | |
| 67 | template<class _Tp> | |
| 68 | concept __integer_like = integral<_Tp> && !same_as<_Tp, bool>; | |
| 69 | ||
| 70 | template<class _Tp> | |
| 71 | concept __signed_integer_like = signed_integral<_Tp>; | |
| 72 | ||
| 73 | template<class _Ip> | |
| 74 | concept weakly_incrementable = | |
| 75 | movable<_Ip> && | |
| 76 | requires(_Ip __i) { | |
| 77 | typename iter_difference_t<_Ip>; | |
| 78 | requires __signed_integer_like<iter_difference_t<_Ip>>; | |
| 79 | { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving | |
| 80 | __i++; // not required to be equality-preserving | |
| 81 | }; | |
| 82 | ||
| 83 | // [iterator.concept.inc] | |
| 84 | template<class _Ip> | |
| 85 | concept incrementable = | |
| 86 | regular<_Ip> && | |
| 87 | weakly_incrementable<_Ip> && | |
| 88 | requires(_Ip __i) { | |
| 89 | { __i++ } -> same_as<_Ip>; | |
| 90 | }; | |
| 91 | ||
| 92 | // [iterator.concept.iterator] | |
| 93 | template<class _Ip> | |
| 94 | concept input_or_output_iterator = | |
| 95 | requires(_Ip __i) { | |
| 96 | { *__i } -> __referenceable; | |
| 97 | } && | |
| 98 | weakly_incrementable<_Ip>; | |
| 99 | ||
| 100 | // [iterator.concept.sentinel] | |
| 101 | template<class _Sp, class _Ip> | |
| 102 | concept sentinel_for = | |
| 103 | semiregular<_Sp> && | |
| 104 | input_or_output_iterator<_Ip> && | |
| 105 | __weakly_equality_comparable_with<_Sp, _Ip>; | |
| 106 | ||
| 107 | template<class, class> | |
| 108 | inline constexpr bool disable_sized_sentinel_for = false; | |
| 109 | ||
| 110 | template<class _Sp, class _Ip> | |
| 111 | concept sized_sentinel_for = | |
| 112 | sentinel_for<_Sp, _Ip> && | |
| 113 | !disable_sized_sentinel_for<remove_cv_t<_Sp>, remove_cv_t<_Ip>> && | |
| 114 | requires(const _Ip& __i, const _Sp& __s) { | |
| 115 | { __s - __i } -> same_as<iter_difference_t<_Ip>>; | |
| 116 | { __i - __s } -> same_as<iter_difference_t<_Ip>>; | |
| 117 | }; | |
| 118 | ||
| 119 | // [iterator.concept.input] | |
| 120 | template<class _Ip> | |
| 121 | concept input_iterator = | |
| 122 | input_or_output_iterator<_Ip> && | |
| 123 | indirectly_readable<_Ip> && | |
| 124 | requires { typename _ITER_CONCEPT<_Ip>; } && | |
| 125 | derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>; | |
| 126 | ||
| 127 | // [iterator.concept.output] | |
| 128 | template<class _Ip, class _Tp> | |
| 129 | concept output_iterator = | |
| 130 | input_or_output_iterator<_Ip> && | |
| 131 | indirectly_writable<_Ip, _Tp> && | |
| 132 | requires (_Ip __it, _Tp&& __t) { | |
| 133 | *__it++ = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving | |
| 134 | }; | |
| 135 | ||
| 136 | // [iterator.concept.forward] | |
| 137 | template<class _Ip> | |
| 138 | concept forward_iterator = | |
| 139 | input_iterator<_Ip> && | |
| 140 | derived_from<_ITER_CONCEPT<_Ip>, forward_iterator_tag> && | |
| 141 | incrementable<_Ip> && | |
| 142 | sentinel_for<_Ip, _Ip>; | |
| 143 | ||
| 144 | // [iterator.concept.bidir] | |
| 145 | template<class _Ip> | |
| 146 | concept bidirectional_iterator = | |
| 147 | forward_iterator<_Ip> && | |
| 148 | derived_from<_ITER_CONCEPT<_Ip>, bidirectional_iterator_tag> && | |
| 149 | requires(_Ip __i) { | |
| 150 | { --__i } -> same_as<_Ip&>; | |
| 151 | { __i-- } -> same_as<_Ip>; | |
| 152 | }; | |
| 153 | ||
| 154 | template<class _Ip> | |
| 155 | concept random_access_iterator = | |
| 156 | bidirectional_iterator<_Ip> && | |
| 157 | derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> && | |
| 158 | totally_ordered<_Ip> && | |
| 159 | sized_sentinel_for<_Ip, _Ip> && | |
| 160 | requires(_Ip __i, const _Ip __j, const iter_difference_t<_Ip> __n) { | |
| 161 | { __i += __n } -> same_as<_Ip&>; | |
| 162 | { __j + __n } -> same_as<_Ip>; | |
| 163 | { __n + __j } -> same_as<_Ip>; | |
| 164 | { __i -= __n } -> same_as<_Ip&>; | |
| 165 | { __j - __n } -> same_as<_Ip>; | |
| 166 | { __j[__n] } -> same_as<iter_reference_t<_Ip>>; | |
| 167 | }; | |
| 168 | ||
| 169 | template<class _Ip> | |
| 170 | concept contiguous_iterator = | |
| 171 | random_access_iterator<_Ip> && | |
| 172 | derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> && | |
| 173 | is_lvalue_reference_v<iter_reference_t<_Ip>> && | |
| 174 | same_as<iter_value_t<_Ip>, remove_cvref_t<iter_reference_t<_Ip>>> && | |
| 175 | (is_pointer_v<_Ip> || requires { sizeof(__pointer_traits_element_type<_Ip>); }) && | |
| 176 | requires(const _Ip& __i) { | |
| 177 | { _VSTD::to_address(__i) } -> same_as<add_pointer_t<iter_reference_t<_Ip>>>; | |
| 178 | }; | |
| 179 | ||
| 180 | template<class _Ip> | |
| 181 | concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip __i) { __i.operator->(); }); | |
| 182 | ||
| 183 | // [indirectcallable.indirectinvocable] | |
| 184 | template<class _Fp, class _It> | |
| 185 | concept indirectly_unary_invocable = | |
| 186 | indirectly_readable<_It> && | |
| 187 | copy_constructible<_Fp> && | |
| 188 | invocable<_Fp&, iter_value_t<_It>&> && | |
| 189 | invocable<_Fp&, iter_reference_t<_It>> && | |
| 190 | invocable<_Fp&, iter_common_reference_t<_It>> && | |
| 191 | common_reference_with< | |
| 192 | invoke_result_t<_Fp&, iter_value_t<_It>&>, | |
| 193 | invoke_result_t<_Fp&, iter_reference_t<_It>>>; | |
| 194 | ||
| 195 | template<class _Fp, class _It> | |
| 196 | concept indirectly_regular_unary_invocable = | |
| 197 | indirectly_readable<_It> && | |
| 198 | copy_constructible<_Fp> && | |
| 199 | regular_invocable<_Fp&, iter_value_t<_It>&> && | |
| 200 | regular_invocable<_Fp&, iter_reference_t<_It>> && | |
| 201 | regular_invocable<_Fp&, iter_common_reference_t<_It>> && | |
| 202 | common_reference_with< | |
| 203 | invoke_result_t<_Fp&, iter_value_t<_It>&>, | |
| 204 | invoke_result_t<_Fp&, iter_reference_t<_It>>>; | |
| 205 | ||
| 206 | template<class _Fp, class _It> | |
| 207 | concept indirect_unary_predicate = | |
| 208 | indirectly_readable<_It> && | |
| 209 | copy_constructible<_Fp> && | |
| 210 | predicate<_Fp&, iter_value_t<_It>&> && | |
| 211 | predicate<_Fp&, iter_reference_t<_It>> && | |
| 212 | predicate<_Fp&, iter_common_reference_t<_It>>; | |
| 213 | ||
| 214 | template<class _Fp, class _It1, class _It2> | |
| 215 | concept indirect_binary_predicate = | |
| 216 | indirectly_readable<_It1> && indirectly_readable<_It2> && | |
| 217 | copy_constructible<_Fp> && | |
| 218 | predicate<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && | |
| 219 | predicate<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && | |
| 220 | predicate<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && | |
| 221 | predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && | |
| 222 | predicate<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; | |
| 223 | ||
| 224 | template<class _Fp, class _It1, class _It2 = _It1> | |
| 225 | concept indirect_equivalence_relation = | |
| 226 | indirectly_readable<_It1> && indirectly_readable<_It2> && | |
| 227 | copy_constructible<_Fp> && | |
| 228 | equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && | |
| 229 | equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && | |
| 230 | equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && | |
| 231 | equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && | |
| 232 | equivalence_relation<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; | |
| 233 | ||
| 234 | template<class _Fp, class _It1, class _It2 = _It1> | |
| 235 | concept indirect_strict_weak_order = | |
| 236 | indirectly_readable<_It1> && indirectly_readable<_It2> && | |
| 237 | copy_constructible<_Fp> && | |
| 238 | strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && | |
| 239 | strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && | |
| 240 | strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && | |
| 241 | strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && | |
| 242 | strict_weak_order<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; | |
| 243 | ||
| 244 | template<class _Fp, class... _Its> | |
| 245 | requires (indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...> | |
| 246 | using indirect_result_t = invoke_result_t<_Fp, iter_reference_t<_Its>...>; | |
| 247 | ||
| 248 | template<class _In, class _Out> | |
| 249 | concept indirectly_movable = | |
| 250 | indirectly_readable<_In> && | |
| 251 | indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; | |
| 252 | ||
| 253 | template<class _In, class _Out> | |
| 254 | concept indirectly_movable_storable = | |
| 255 | indirectly_movable<_In, _Out> && | |
| 256 | indirectly_writable<_Out, iter_value_t<_In>> && | |
| 257 | movable<iter_value_t<_In>> && | |
| 258 | constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> && | |
| 259 | assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>; | |
| 260 | ||
| 261 | // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle | |
| 262 | // (both iter_swap and indirectly_swappable require indirectly_readable). | |
| 263 | ||
| 264 | // clang-format on | |
| 265 | ||
| 266 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 267 | ||
| 268 | _LIBCPP_END_NAMESPACE_STD | |
| 269 | ||
| 270 | _LIBCPP_POP_MACROS | |
| 271 | ||
| 272 | #endif // _LIBCPP___ITERATOR_CONCEPTS_H |
lib/libcxx/include/__iterator/counted_iterator.h created+306| ... | ... | @@ -0,0 +1,306 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___ITERATOR_COUNTED_ITERATOR_H | |
| 10 | #define _LIBCPP___ITERATOR_COUNTED_ITERATOR_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__debug> | |
| 14 | #include <__iterator/concepts.h> | |
| 15 | #include <__iterator/default_sentinel.h> | |
| 16 | #include <__iterator/iter_move.h> | |
| 17 | #include <__iterator/iter_swap.h> | |
| 18 | #include <__iterator/incrementable_traits.h> | |
| 19 | #include <__iterator/iterator_traits.h> | |
| 20 | #include <__iterator/readable_traits.h> | |
| 21 | #include <__memory/pointer_traits.h> | |
| 22 | #include <concepts> | |
| 23 | #include <type_traits> | |
| 24 | ||
| 25 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 26 | #pragma GCC system_header | |
| 27 | #endif | |
| 28 | ||
| 29 | _LIBCPP_PUSH_MACROS | |
| 30 | #include <__undef_macros> | |
| 31 | ||
| 32 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 33 | ||
| 34 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 35 | ||
| 36 | template<class> | |
| 37 | struct __counted_iterator_concept {}; | |
| 38 | ||
| 39 | template<class _Iter> | |
| 40 | requires requires { typename _Iter::iterator_concept; } | |
| 41 | struct __counted_iterator_concept<_Iter> { | |
| 42 | using iterator_concept = typename _Iter::iterator_concept; | |
| 43 | }; | |
| 44 | ||
| 45 | template<class> | |
| 46 | struct __counted_iterator_category {}; | |
| 47 | ||
| 48 | template<class _Iter> | |
| 49 | requires requires { typename _Iter::iterator_category; } | |
| 50 | struct __counted_iterator_category<_Iter> { | |
| 51 | using iterator_category = typename _Iter::iterator_category; | |
| 52 | }; | |
| 53 | ||
| 54 | template<class> | |
| 55 | struct __counted_iterator_value_type {}; | |
| 56 | ||
| 57 | template<indirectly_readable _Iter> | |
| 58 | struct __counted_iterator_value_type<_Iter> { | |
| 59 | using value_type = iter_value_t<_Iter>; | |
| 60 | }; | |
| 61 | ||
| 62 | template<input_or_output_iterator _Iter> | |
| 63 | class counted_iterator | |
| 64 | : public __counted_iterator_concept<_Iter> | |
| 65 | , public __counted_iterator_category<_Iter> | |
| 66 | , public __counted_iterator_value_type<_Iter> | |
| 67 | { | |
| 68 | public: | |
| 69 | [[no_unique_address]] _Iter __current_ = _Iter(); | |
| 70 | iter_difference_t<_Iter> __count_ = 0; | |
| 71 | ||
| 72 | using iterator_type = _Iter; | |
| 73 | using difference_type = iter_difference_t<_Iter>; | |
| 74 | ||
| 75 | _LIBCPP_HIDE_FROM_ABI | |
| 76 | constexpr counted_iterator() requires default_initializable<_Iter> = default; | |
| 77 | ||
| 78 | _LIBCPP_HIDE_FROM_ABI | |
| 79 | constexpr counted_iterator(_Iter __iter, iter_difference_t<_Iter> __n) | |
| 80 | : __current_(_VSTD::move(__iter)), __count_(__n) { | |
| 81 | _LIBCPP_ASSERT(__n >= 0, "__n must not be negative."); | |
| 82 | } | |
| 83 | ||
| 84 | template<class _I2> | |
| 85 | requires convertible_to<const _I2&, _Iter> | |
| 86 | _LIBCPP_HIDE_FROM_ABI | |
| 87 | constexpr counted_iterator(const counted_iterator<_I2>& __other) | |
| 88 | : __current_(__other.__current_), __count_(__other.__count_) {} | |
| 89 | ||
| 90 | template<class _I2> | |
| 91 | requires assignable_from<_Iter&, const _I2&> | |
| 92 | _LIBCPP_HIDE_FROM_ABI | |
| 93 | constexpr counted_iterator& operator=(const counted_iterator<_I2>& __other) { | |
| 94 | __current_ = __other.__current_; | |
| 95 | __count_ = __other.__count_; | |
| 96 | return *this; | |
| 97 | } | |
| 98 | ||
| 99 | _LIBCPP_HIDE_FROM_ABI | |
| 100 | constexpr const _Iter& base() const& { return __current_; } | |
| 101 | ||
| 102 | _LIBCPP_HIDE_FROM_ABI | |
| 103 | constexpr _Iter base() && { return _VSTD::move(__current_); } | |
| 104 | ||
| 105 | _LIBCPP_HIDE_FROM_ABI | |
| 106 | constexpr iter_difference_t<_Iter> count() const noexcept { return __count_; } | |
| 107 | ||
| 108 | _LIBCPP_HIDE_FROM_ABI | |
| 109 | constexpr decltype(auto) operator*() { | |
| 110 | _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); | |
| 111 | return *__current_; | |
| 112 | } | |
| 113 | ||
| 114 | _LIBCPP_HIDE_FROM_ABI | |
| 115 | constexpr decltype(auto) operator*() const | |
| 116 | requires __dereferenceable<const _Iter> | |
| 117 | { | |
| 118 | _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); | |
| 119 | return *__current_; | |
| 120 | } | |
| 121 | ||
| 122 | _LIBCPP_HIDE_FROM_ABI | |
| 123 | constexpr auto operator->() const noexcept | |
| 124 | requires contiguous_iterator<_Iter> | |
| 125 | { | |
| 126 | return _VSTD::to_address(__current_); | |
| 127 | } | |
| 128 | ||
| 129 | _LIBCPP_HIDE_FROM_ABI | |
| 130 | constexpr counted_iterator& operator++() { | |
| 131 | _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); | |
| 132 | ++__current_; | |
| 133 | --__count_; | |
| 134 | return *this; | |
| 135 | } | |
| 136 | ||
| 137 | _LIBCPP_HIDE_FROM_ABI | |
| 138 | decltype(auto) operator++(int) { | |
| 139 | _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); | |
| 140 | --__count_; | |
| 141 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 142 | try { return __current_++; } | |
| 143 | catch(...) { ++__count_; throw; } | |
| 144 | #else | |
| 145 | return __current_++; | |
| 146 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 147 | } | |
| 148 | ||
| 149 | _LIBCPP_HIDE_FROM_ABI | |
| 150 | constexpr counted_iterator operator++(int) | |
| 151 | requires forward_iterator<_Iter> | |
| 152 | { | |
| 153 | _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); | |
| 154 | counted_iterator __tmp = *this; | |
| 155 | ++*this; | |
| 156 | return __tmp; | |
| 157 | } | |
| 158 | ||
| 159 | _LIBCPP_HIDE_FROM_ABI | |
| 160 | constexpr counted_iterator& operator--() | |
| 161 | requires bidirectional_iterator<_Iter> | |
| 162 | { | |
| 163 | --__current_; | |
| 164 | ++__count_; | |
| 165 | return *this; | |
| 166 | } | |
| 167 | ||
| 168 | _LIBCPP_HIDE_FROM_ABI | |
| 169 | constexpr counted_iterator operator--(int) | |
| 170 | requires bidirectional_iterator<_Iter> | |
| 171 | { | |
| 172 | counted_iterator __tmp = *this; | |
| 173 | --*this; | |
| 174 | return __tmp; | |
| 175 | } | |
| 176 | ||
| 177 | _LIBCPP_HIDE_FROM_ABI | |
| 178 | constexpr counted_iterator operator+(iter_difference_t<_Iter> __n) const | |
| 179 | requires random_access_iterator<_Iter> | |
| 180 | { | |
| 181 | return counted_iterator(__current_ + __n, __count_ - __n); | |
| 182 | } | |
| 183 | ||
| 184 | _LIBCPP_HIDE_FROM_ABI | |
| 185 | friend constexpr counted_iterator operator+( | |
| 186 | iter_difference_t<_Iter> __n, const counted_iterator& __x) | |
| 187 | requires random_access_iterator<_Iter> | |
| 188 | { | |
| 189 | return __x + __n; | |
| 190 | } | |
| 191 | ||
| 192 | _LIBCPP_HIDE_FROM_ABI | |
| 193 | constexpr counted_iterator& operator+=(iter_difference_t<_Iter> __n) | |
| 194 | requires random_access_iterator<_Iter> | |
| 195 | { | |
| 196 | _LIBCPP_ASSERT(__n <= __count_, "Cannot advance iterator past end."); | |
| 197 | __current_ += __n; | |
| 198 | __count_ -= __n; | |
| 199 | return *this; | |
| 200 | } | |
| 201 | ||
| 202 | _LIBCPP_HIDE_FROM_ABI | |
| 203 | constexpr counted_iterator operator-(iter_difference_t<_Iter> __n) const | |
| 204 | requires random_access_iterator<_Iter> | |
| 205 | { | |
| 206 | return counted_iterator(__current_ - __n, __count_ + __n); | |
| 207 | } | |
| 208 | ||
| 209 | template<common_with<_Iter> _I2> | |
| 210 | _LIBCPP_HIDE_FROM_ABI | |
| 211 | friend constexpr iter_difference_t<_I2> operator-( | |
| 212 | const counted_iterator& __lhs, const counted_iterator<_I2>& __rhs) | |
| 213 | { | |
| 214 | return __rhs.__count_ - __lhs.__count_; | |
| 215 | } | |
| 216 | ||
| 217 | _LIBCPP_HIDE_FROM_ABI | |
| 218 | friend constexpr iter_difference_t<_Iter> operator-( | |
| 219 | const counted_iterator& __lhs, default_sentinel_t) | |
| 220 | { | |
| 221 | return -__lhs.__count_; | |
| 222 | } | |
| 223 | ||
| 224 | _LIBCPP_HIDE_FROM_ABI | |
| 225 | friend constexpr iter_difference_t<_Iter> operator-( | |
| 226 | default_sentinel_t, const counted_iterator& __rhs) | |
| 227 | { | |
| 228 | return __rhs.__count_; | |
| 229 | } | |
| 230 | ||
| 231 | _LIBCPP_HIDE_FROM_ABI | |
| 232 | constexpr counted_iterator& operator-=(iter_difference_t<_Iter> __n) | |
| 233 | requires random_access_iterator<_Iter> | |
| 234 | { | |
| 235 | _LIBCPP_ASSERT(-__n <= __count_, "Attempt to subtract too large of a size: " | |
| 236 | "counted_iterator would be decremented before the " | |
| 237 | "first element of its range."); | |
| 238 | __current_ -= __n; | |
| 239 | __count_ += __n; | |
| 240 | return *this; | |
| 241 | } | |
| 242 | ||
| 243 | _LIBCPP_HIDE_FROM_ABI | |
| 244 | constexpr decltype(auto) operator[](iter_difference_t<_Iter> __n) const | |
| 245 | requires random_access_iterator<_Iter> | |
| 246 | { | |
| 247 | _LIBCPP_ASSERT(__n < __count_, "Subscript argument must be less than size."); | |
| 248 | return __current_[__n]; | |
| 249 | } | |
| 250 | ||
| 251 | template<common_with<_Iter> _I2> | |
| 252 | _LIBCPP_HIDE_FROM_ABI | |
| 253 | friend constexpr bool operator==( | |
| 254 | const counted_iterator& __lhs, const counted_iterator<_I2>& __rhs) | |
| 255 | { | |
| 256 | return __lhs.__count_ == __rhs.__count_; | |
| 257 | } | |
| 258 | ||
| 259 | _LIBCPP_HIDE_FROM_ABI | |
| 260 | friend constexpr bool operator==( | |
| 261 | const counted_iterator& __lhs, default_sentinel_t) | |
| 262 | { | |
| 263 | return __lhs.__count_ == 0; | |
| 264 | } | |
| 265 | ||
| 266 | template<common_with<_Iter> _I2> | |
| 267 | friend constexpr strong_ordering operator<=>( | |
| 268 | const counted_iterator& __lhs, const counted_iterator<_I2>& __rhs) | |
| 269 | { | |
| 270 | return __rhs.__count_ <=> __lhs.__count_; | |
| 271 | } | |
| 272 | ||
| 273 | _LIBCPP_HIDE_FROM_ABI | |
| 274 | friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const counted_iterator& __i) | |
| 275 | noexcept(noexcept(ranges::iter_move(__i.__current_))) | |
| 276 | requires input_iterator<_Iter> | |
| 277 | { | |
| 278 | _LIBCPP_ASSERT(__i.__count_ > 0, "Iterator must not be past end of range."); | |
| 279 | return ranges::iter_move(__i.__current_); | |
| 280 | } | |
| 281 | ||
| 282 | template<indirectly_swappable<_Iter> _I2> | |
| 283 | _LIBCPP_HIDE_FROM_ABI | |
| 284 | friend constexpr void iter_swap(const counted_iterator& __x, const counted_iterator<_I2>& __y) | |
| 285 | noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) | |
| 286 | { | |
| 287 | _LIBCPP_ASSERT(__x.__count_ > 0 && __y.__count_ > 0, | |
| 288 | "Iterators must not be past end of range."); | |
| 289 | return ranges::iter_swap(__x.__current_, __y.__current_); | |
| 290 | } | |
| 291 | }; | |
| 292 | ||
| 293 | template<input_iterator _Iter> | |
| 294 | requires same_as<_ITER_TRAITS<_Iter>, iterator_traits<_Iter>> | |
| 295 | struct iterator_traits<counted_iterator<_Iter>> : iterator_traits<_Iter> { | |
| 296 | using pointer = conditional_t<contiguous_iterator<_Iter>, | |
| 297 | add_pointer_t<iter_reference_t<_Iter>>, void>; | |
| 298 | }; | |
| 299 | ||
| 300 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 301 | ||
| 302 | _LIBCPP_END_NAMESPACE_STD | |
| 303 | ||
| 304 | _LIBCPP_POP_MACROS | |
| 305 | ||
| 306 | #endif // _LIBCPP___ITERATOR_COUNTED_ITERATOR_H |
lib/libcxx/include/__iterator/data.h created+56| ... | ... | @@ -0,0 +1,56 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_DATA_H | |
| 11 | #define _LIBCPP___ITERATOR_DATA_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | #include <initializer_list> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if _LIBCPP_STD_VER > 14 | |
| 27 | ||
| 28 | template <class _Cont> constexpr | |
| 29 | _LIBCPP_INLINE_VISIBILITY | |
| 30 | auto data(_Cont& __c) | |
| 31 | _NOEXCEPT_(noexcept(__c.data())) | |
| 32 | -> decltype (__c.data()) | |
| 33 | { return __c.data(); } | |
| 34 | ||
| 35 | template <class _Cont> constexpr | |
| 36 | _LIBCPP_INLINE_VISIBILITY | |
| 37 | auto data(const _Cont& __c) | |
| 38 | _NOEXCEPT_(noexcept(__c.data())) | |
| 39 | -> decltype (__c.data()) | |
| 40 | { return __c.data(); } | |
| 41 | ||
| 42 | template <class _Tp, size_t _Sz> | |
| 43 | _LIBCPP_INLINE_VISIBILITY | |
| 44 | constexpr _Tp* data(_Tp (&__array)[_Sz]) noexcept { return __array; } | |
| 45 | ||
| 46 | template <class _Ep> | |
| 47 | _LIBCPP_INLINE_VISIBILITY | |
| 48 | constexpr const _Ep* data(initializer_list<_Ep> __il) noexcept { return __il.begin(); } | |
| 49 | ||
| 50 | #endif | |
| 51 | ||
| 52 | _LIBCPP_END_NAMESPACE_STD | |
| 53 | ||
| 54 | _LIBCPP_POP_MACROS | |
| 55 | ||
| 56 | #endif // _LIBCPP___ITERATOR_DATA_H |
lib/libcxx/include/__iterator/default_sentinel.h created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_DEFAULT_SENTINEL_H | |
| 11 | #define _LIBCPP___ITERATOR_DEFAULT_SENTINEL_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 25 | ||
| 26 | struct default_sentinel_t { }; | |
| 27 | inline constexpr default_sentinel_t default_sentinel{}; | |
| 28 | ||
| 29 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 30 | ||
| 31 | _LIBCPP_END_NAMESPACE_STD | |
| 32 | ||
| 33 | _LIBCPP_POP_MACROS | |
| 34 | ||
| 35 | #endif // _LIBCPP___ITERATOR_DEFAULT_SENTINEL_H |
lib/libcxx/include/__iterator/distance.h created+56| ... | ... | @@ -0,0 +1,56 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_DISTANCE_H | |
| 11 | #define _LIBCPP___ITERATOR_DISTANCE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _InputIter> | |
| 26 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 27 | typename iterator_traits<_InputIter>::difference_type | |
| 28 | __distance(_InputIter __first, _InputIter __last, input_iterator_tag) | |
| 29 | { | |
| 30 | typename iterator_traits<_InputIter>::difference_type __r(0); | |
| 31 | for (; __first != __last; ++__first) | |
| 32 | ++__r; | |
| 33 | return __r; | |
| 34 | } | |
| 35 | ||
| 36 | template <class _RandIter> | |
| 37 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 38 | typename iterator_traits<_RandIter>::difference_type | |
| 39 | __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag) | |
| 40 | { | |
| 41 | return __last - __first; | |
| 42 | } | |
| 43 | ||
| 44 | template <class _InputIter> | |
| 45 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 46 | typename iterator_traits<_InputIter>::difference_type | |
| 47 | distance(_InputIter __first, _InputIter __last) | |
| 48 | { | |
| 49 | return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); | |
| 50 | } | |
| 51 | ||
| 52 | _LIBCPP_END_NAMESPACE_STD | |
| 53 | ||
| 54 | _LIBCPP_POP_MACROS | |
| 55 | ||
| 56 | #endif // _LIBCPP___ITERATOR_DISTANCE_H |
lib/libcxx/include/__iterator/empty.h created+49| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_EMPTY_H | |
| 11 | #define _LIBCPP___ITERATOR_EMPTY_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | #include <initializer_list> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if _LIBCPP_STD_VER > 14 | |
| 27 | ||
| 28 | template <class _Cont> | |
| 29 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 30 | constexpr auto empty(const _Cont& __c) | |
| 31 | _NOEXCEPT_(noexcept(__c.empty())) | |
| 32 | -> decltype (__c.empty()) | |
| 33 | { return __c.empty(); } | |
| 34 | ||
| 35 | template <class _Tp, size_t _Sz> | |
| 36 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 37 | constexpr bool empty(const _Tp (&)[_Sz]) noexcept { return false; } | |
| 38 | ||
| 39 | template <class _Ep> | |
| 40 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 41 | constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } | |
| 42 | ||
| 43 | #endif // _LIBCPP_STD_VER > 14 | |
| 44 | ||
| 45 | _LIBCPP_END_NAMESPACE_STD | |
| 46 | ||
| 47 | _LIBCPP_POP_MACROS | |
| 48 | ||
| 49 | #endif // _LIBCPP___ITERATOR_EMPTY_H |
lib/libcxx/include/__iterator/erase_if_container.h created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H | |
| 11 | #define _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _Container, class _Predicate> | |
| 25 | _LIBCPP_HIDE_FROM_ABI | |
| 26 | typename _Container::size_type | |
| 27 | __libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { | |
| 28 | typename _Container::size_type __old_size = __c.size(); | |
| 29 | ||
| 30 | const typename _Container::iterator __last = __c.end(); | |
| 31 | for (typename _Container::iterator __iter = __c.begin(); __iter != __last;) { | |
| 32 | if (__pred(*__iter)) | |
| 33 | __iter = __c.erase(__iter); | |
| 34 | else | |
| 35 | ++__iter; | |
| 36 | } | |
| 37 | ||
| 38 | return __old_size - __c.size(); | |
| 39 | } | |
| 40 | ||
| 41 | _LIBCPP_END_NAMESPACE_STD | |
| 42 | ||
| 43 | _LIBCPP_POP_MACROS | |
| 44 | ||
| 45 | #endif // _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H |
lib/libcxx/include/__iterator/front_insert_iterator.h created+75| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/addressof.h> | |
| 17 | #include <__utility/move.h> | |
| 18 | #include <cstddef> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 30 | template <class _Container> | |
| 31 | class _LIBCPP_TEMPLATE_VIS front_insert_iterator | |
| 32 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 33 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 34 | #endif | |
| 35 | { | |
| 36 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 37 | protected: | |
| 38 | _Container* container; | |
| 39 | public: | |
| 40 | typedef output_iterator_tag iterator_category; | |
| 41 | typedef void value_type; | |
| 42 | #if _LIBCPP_STD_VER > 17 | |
| 43 | typedef ptrdiff_t difference_type; | |
| 44 | #else | |
| 45 | typedef void difference_type; | |
| 46 | #endif | |
| 47 | typedef void pointer; | |
| 48 | typedef void reference; | |
| 49 | typedef _Container container_type; | |
| 50 | ||
| 51 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit front_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} | |
| 52 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 front_insert_iterator& operator=(const typename _Container::value_type& __value_) | |
| 53 | {container->push_front(__value_); return *this;} | |
| 54 | #ifndef _LIBCPP_CXX03_LANG | |
| 55 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 front_insert_iterator& operator=(typename _Container::value_type&& __value_) | |
| 56 | {container->push_front(_VSTD::move(__value_)); return *this;} | |
| 57 | #endif // _LIBCPP_CXX03_LANG | |
| 58 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 front_insert_iterator& operator*() {return *this;} | |
| 59 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 front_insert_iterator& operator++() {return *this;} | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 front_insert_iterator operator++(int) {return *this;} | |
| 61 | }; | |
| 62 | ||
| 63 | template <class _Container> | |
| 64 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 65 | front_insert_iterator<_Container> | |
| 66 | front_inserter(_Container& __x) | |
| 67 | { | |
| 68 | return front_insert_iterator<_Container>(__x); | |
| 69 | } | |
| 70 | ||
| 71 | _LIBCPP_END_NAMESPACE_STD | |
| 72 | ||
| 73 | _LIBCPP_POP_MACROS | |
| 74 | ||
| 75 | #endif // _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H |
lib/libcxx/include/__iterator/incrementable_traits.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H | |
| 11 | #define _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <concepts> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 27 | ||
| 28 | // [incrementable.traits] | |
| 29 | template<class> struct incrementable_traits {}; | |
| 30 | ||
| 31 | template<class _Tp> | |
| 32 | requires is_object_v<_Tp> | |
| 33 | struct incrementable_traits<_Tp*> { | |
| 34 | using difference_type = ptrdiff_t; | |
| 35 | }; | |
| 36 | ||
| 37 | template<class _Ip> | |
| 38 | struct incrementable_traits<const _Ip> : incrementable_traits<_Ip> {}; | |
| 39 | ||
| 40 | template<class _Tp> | |
| 41 | concept __has_member_difference_type = requires { typename _Tp::difference_type; }; | |
| 42 | ||
| 43 | template<__has_member_difference_type _Tp> | |
| 44 | struct incrementable_traits<_Tp> { | |
| 45 | using difference_type = typename _Tp::difference_type; | |
| 46 | }; | |
| 47 | ||
| 48 | template<class _Tp> | |
| 49 | concept __has_integral_minus = | |
| 50 | requires(const _Tp& __x, const _Tp& __y) { | |
| 51 | { __x - __y } -> integral; | |
| 52 | }; | |
| 53 | ||
| 54 | template<__has_integral_minus _Tp> | |
| 55 | requires (!__has_member_difference_type<_Tp>) | |
| 56 | struct incrementable_traits<_Tp> { | |
| 57 | using difference_type = make_signed_t<decltype(declval<_Tp>() - declval<_Tp>())>; | |
| 58 | }; | |
| 59 | ||
| 60 | template <class> | |
| 61 | struct iterator_traits; | |
| 62 | ||
| 63 | // Let `RI` be `remove_cvref_t<I>`. The type `iter_difference_t<I>` denotes | |
| 64 | // `incrementable_traits<RI>::difference_type` if `iterator_traits<RI>` names a specialization | |
| 65 | // generated from the primary template, and `iterator_traits<RI>::difference_type` otherwise. | |
| 66 | template <class _Ip> | |
| 67 | using iter_difference_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value, | |
| 68 | incrementable_traits<remove_cvref_t<_Ip> >, | |
| 69 | iterator_traits<remove_cvref_t<_Ip> > >::difference_type; | |
| 70 | ||
| 71 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 72 | ||
| 73 | _LIBCPP_END_NAMESPACE_STD | |
| 74 | ||
| 75 | _LIBCPP_POP_MACROS | |
| 76 | ||
| 77 | #endif // _LIBCPP___ITERATOR_INCREMENTABLE_TRAITS_H |
lib/libcxx/include/__iterator/insert_iterator.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_INSERT_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_INSERT_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/addressof.h> | |
| 17 | #include <__utility/move.h> | |
| 18 | #include <cstddef> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 30 | template <class _Container> | |
| 31 | class _LIBCPP_TEMPLATE_VIS insert_iterator | |
| 32 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 33 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 34 | #endif | |
| 35 | { | |
| 36 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 37 | protected: | |
| 38 | _Container* container; | |
| 39 | typename _Container::iterator iter; // FIXME: `ranges::iterator_t<Container>` in C++20 mode | |
| 40 | public: | |
| 41 | typedef output_iterator_tag iterator_category; | |
| 42 | typedef void value_type; | |
| 43 | #if _LIBCPP_STD_VER > 17 | |
| 44 | typedef ptrdiff_t difference_type; | |
| 45 | #else | |
| 46 | typedef void difference_type; | |
| 47 | #endif | |
| 48 | typedef void pointer; | |
| 49 | typedef void reference; | |
| 50 | typedef _Container container_type; | |
| 51 | ||
| 52 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator(_Container& __x, typename _Container::iterator __i) | |
| 53 | : container(_VSTD::addressof(__x)), iter(__i) {} | |
| 54 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator& operator=(const typename _Container::value_type& __value_) | |
| 55 | {iter = container->insert(iter, __value_); ++iter; return *this;} | |
| 56 | #ifndef _LIBCPP_CXX03_LANG | |
| 57 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator& operator=(typename _Container::value_type&& __value_) | |
| 58 | {iter = container->insert(iter, _VSTD::move(__value_)); ++iter; return *this;} | |
| 59 | #endif // _LIBCPP_CXX03_LANG | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator& operator*() {return *this;} | |
| 61 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator& operator++() {return *this;} | |
| 62 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator& operator++(int) {return *this;} | |
| 63 | }; | |
| 64 | ||
| 65 | template <class _Container> | |
| 66 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 67 | insert_iterator<_Container> | |
| 68 | inserter(_Container& __x, typename _Container::iterator __i) | |
| 69 | { | |
| 70 | return insert_iterator<_Container>(__x, __i); | |
| 71 | } | |
| 72 | ||
| 73 | _LIBCPP_END_NAMESPACE_STD | |
| 74 | ||
| 75 | _LIBCPP_POP_MACROS | |
| 76 | ||
| 77 | #endif // _LIBCPP___ITERATOR_INSERT_ITERATOR_H |
lib/libcxx/include/__iterator/istream_iterator.h created+103| ... | ... | @@ -0,0 +1,103 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/addressof.h> | |
| 17 | #include <iosfwd> // for forward declarations of char_traits and basic_istream | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 29 | template <class _Tp, class _CharT = char, | |
| 30 | class _Traits = char_traits<_CharT>, class _Distance = ptrdiff_t> | |
| 31 | class _LIBCPP_TEMPLATE_VIS istream_iterator | |
| 32 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 33 | : public iterator<input_iterator_tag, _Tp, _Distance, const _Tp*, const _Tp&> | |
| 34 | #endif | |
| 35 | { | |
| 36 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 37 | public: | |
| 38 | typedef input_iterator_tag iterator_category; | |
| 39 | typedef _Tp value_type; | |
| 40 | typedef _Distance difference_type; | |
| 41 | typedef const _Tp* pointer; | |
| 42 | typedef const _Tp& reference; | |
| 43 | typedef _CharT char_type; | |
| 44 | typedef _Traits traits_type; | |
| 45 | typedef basic_istream<_CharT,_Traits> istream_type; | |
| 46 | private: | |
| 47 | istream_type* __in_stream_; | |
| 48 | _Tp __value_; | |
| 49 | public: | |
| 50 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istream_iterator() : __in_stream_(nullptr), __value_() {} | |
| 51 | _LIBCPP_INLINE_VISIBILITY istream_iterator(istream_type& __s) : __in_stream_(_VSTD::addressof(__s)) | |
| 52 | { | |
| 53 | if (!(*__in_stream_ >> __value_)) | |
| 54 | __in_stream_ = nullptr; | |
| 55 | } | |
| 56 | ||
| 57 | _LIBCPP_INLINE_VISIBILITY const _Tp& operator*() const {return __value_;} | |
| 58 | _LIBCPP_INLINE_VISIBILITY const _Tp* operator->() const {return _VSTD::addressof((operator*()));} | |
| 59 | _LIBCPP_INLINE_VISIBILITY istream_iterator& operator++() | |
| 60 | { | |
| 61 | if (!(*__in_stream_ >> __value_)) | |
| 62 | __in_stream_ = nullptr; | |
| 63 | return *this; | |
| 64 | } | |
| 65 | _LIBCPP_INLINE_VISIBILITY istream_iterator operator++(int) | |
| 66 | {istream_iterator __t(*this); ++(*this); return __t;} | |
| 67 | ||
| 68 | template <class _Up, class _CharU, class _TraitsU, class _DistanceU> | |
| 69 | friend _LIBCPP_INLINE_VISIBILITY | |
| 70 | bool | |
| 71 | operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, | |
| 72 | const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); | |
| 73 | ||
| 74 | template <class _Up, class _CharU, class _TraitsU, class _DistanceU> | |
| 75 | friend _LIBCPP_INLINE_VISIBILITY | |
| 76 | bool | |
| 77 | operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, | |
| 78 | const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); | |
| 79 | }; | |
| 80 | ||
| 81 | template <class _Tp, class _CharT, class _Traits, class _Distance> | |
| 82 | inline _LIBCPP_INLINE_VISIBILITY | |
| 83 | bool | |
| 84 | operator==(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x, | |
| 85 | const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y) | |
| 86 | { | |
| 87 | return __x.__in_stream_ == __y.__in_stream_; | |
| 88 | } | |
| 89 | ||
| 90 | template <class _Tp, class _CharT, class _Traits, class _Distance> | |
| 91 | inline _LIBCPP_INLINE_VISIBILITY | |
| 92 | bool | |
| 93 | operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x, | |
| 94 | const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y) | |
| 95 | { | |
| 96 | return !(__x == __y); | |
| 97 | } | |
| 98 | ||
| 99 | _LIBCPP_END_NAMESPACE_STD | |
| 100 | ||
| 101 | _LIBCPP_POP_MACROS | |
| 102 | ||
| 103 | #endif // _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H |
lib/libcxx/include/__iterator/istreambuf_iterator.h created+110| ... | ... | @@ -0,0 +1,110 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <iosfwd> // for forward declaration of basic_streambuf | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 28 | template<class _CharT, class _Traits> | |
| 29 | class _LIBCPP_TEMPLATE_VIS istreambuf_iterator | |
| 30 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 31 | : public iterator<input_iterator_tag, _CharT, | |
| 32 | typename _Traits::off_type, _CharT*, | |
| 33 | _CharT> | |
| 34 | #endif | |
| 35 | { | |
| 36 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 37 | public: | |
| 38 | typedef input_iterator_tag iterator_category; | |
| 39 | typedef _CharT value_type; | |
| 40 | typedef typename _Traits::off_type difference_type; | |
| 41 | typedef _CharT* pointer; | |
| 42 | typedef _CharT reference; | |
| 43 | typedef _CharT char_type; | |
| 44 | typedef _Traits traits_type; | |
| 45 | typedef typename _Traits::int_type int_type; | |
| 46 | typedef basic_streambuf<_CharT,_Traits> streambuf_type; | |
| 47 | typedef basic_istream<_CharT,_Traits> istream_type; | |
| 48 | private: | |
| 49 | mutable streambuf_type* __sbuf_; | |
| 50 | ||
| 51 | class __proxy | |
| 52 | { | |
| 53 | char_type __keep_; | |
| 54 | streambuf_type* __sbuf_; | |
| 55 | _LIBCPP_INLINE_VISIBILITY __proxy(char_type __c, streambuf_type* __s) | |
| 56 | : __keep_(__c), __sbuf_(__s) {} | |
| 57 | friend class istreambuf_iterator; | |
| 58 | public: | |
| 59 | _LIBCPP_INLINE_VISIBILITY char_type operator*() const {return __keep_;} | |
| 60 | }; | |
| 61 | ||
| 62 | _LIBCPP_INLINE_VISIBILITY | |
| 63 | bool __test_for_eof() const | |
| 64 | { | |
| 65 | if (__sbuf_ && traits_type::eq_int_type(__sbuf_->sgetc(), traits_type::eof())) | |
| 66 | __sbuf_ = nullptr; | |
| 67 | return __sbuf_ == nullptr; | |
| 68 | } | |
| 69 | public: | |
| 70 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(nullptr) {} | |
| 71 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT | |
| 72 | : __sbuf_(__s.rdbuf()) {} | |
| 73 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT | |
| 74 | : __sbuf_(__s) {} | |
| 75 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(const __proxy& __p) _NOEXCEPT | |
| 76 | : __sbuf_(__p.__sbuf_) {} | |
| 77 | ||
| 78 | _LIBCPP_INLINE_VISIBILITY char_type operator*() const | |
| 79 | {return static_cast<char_type>(__sbuf_->sgetc());} | |
| 80 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator& operator++() | |
| 81 | { | |
| 82 | __sbuf_->sbumpc(); | |
| 83 | return *this; | |
| 84 | } | |
| 85 | _LIBCPP_INLINE_VISIBILITY __proxy operator++(int) | |
| 86 | { | |
| 87 | return __proxy(__sbuf_->sbumpc(), __sbuf_); | |
| 88 | } | |
| 89 | ||
| 90 | _LIBCPP_INLINE_VISIBILITY bool equal(const istreambuf_iterator& __b) const | |
| 91 | {return __test_for_eof() == __b.__test_for_eof();} | |
| 92 | }; | |
| 93 | ||
| 94 | template <class _CharT, class _Traits> | |
| 95 | inline _LIBCPP_INLINE_VISIBILITY | |
| 96 | bool operator==(const istreambuf_iterator<_CharT,_Traits>& __a, | |
| 97 | const istreambuf_iterator<_CharT,_Traits>& __b) | |
| 98 | {return __a.equal(__b);} | |
| 99 | ||
| 100 | template <class _CharT, class _Traits> | |
| 101 | inline _LIBCPP_INLINE_VISIBILITY | |
| 102 | bool operator!=(const istreambuf_iterator<_CharT,_Traits>& __a, | |
| 103 | const istreambuf_iterator<_CharT,_Traits>& __b) | |
| 104 | {return !__a.equal(__b);} | |
| 105 | ||
| 106 | _LIBCPP_END_NAMESPACE_STD | |
| 107 | ||
| 108 | _LIBCPP_POP_MACROS | |
| 109 | ||
| 110 | #endif // _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H |
lib/libcxx/include/__iterator/iter_move.h created+91| ... | ... | @@ -0,0 +1,91 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ITER_MOVE_H | |
| 11 | #define _LIBCPP___ITERATOR_ITER_MOVE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__utility/forward.h> | |
| 16 | #include <concepts> // __class_or_enum | |
| 17 | #include <type_traits> | |
| 18 | #include <utility> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 30 | ||
| 31 | namespace ranges::__iter_move { | |
| 32 | void iter_move(); | |
| 33 | ||
| 34 | template<class _Ip> | |
| 35 | concept __unqualified_iter_move = requires(_Ip&& __i) { | |
| 36 | iter_move(_VSTD::forward<_Ip>(__i)); | |
| 37 | }; | |
| 38 | ||
| 39 | // [iterator.cust.move]/1 | |
| 40 | // The name ranges::iter_move denotes a customization point object. | |
| 41 | // The expression ranges::iter_move(E) for a subexpression E is | |
| 42 | // expression-equivalent to: | |
| 43 | struct __fn { | |
| 44 | // [iterator.cust.move]/1.1 | |
| 45 | // iter_move(E), if E has class or enumeration type and iter_move(E) is a | |
| 46 | // well-formed expression when treated as an unevaluated operand, [...] | |
| 47 | template<class _Ip> | |
| 48 | requires __class_or_enum<remove_cvref_t<_Ip>> && __unqualified_iter_move<_Ip> | |
| 49 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const | |
| 50 | noexcept(noexcept(iter_move(_VSTD::forward<_Ip>(__i)))) | |
| 51 | { | |
| 52 | return iter_move(_VSTD::forward<_Ip>(__i)); | |
| 53 | } | |
| 54 | ||
| 55 | // [iterator.cust.move]/1.2 | |
| 56 | // Otherwise, if the expression *E is well-formed: | |
| 57 | // 1.2.1 if *E is an lvalue, std::move(*E); | |
| 58 | // 1.2.2 otherwise, *E. | |
| 59 | template<class _Ip> | |
| 60 | requires (!(__class_or_enum<remove_cvref_t<_Ip>> && __unqualified_iter_move<_Ip>)) && | |
| 61 | requires(_Ip&& __i) { *_VSTD::forward<_Ip>(__i); } | |
| 62 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const | |
| 63 | noexcept(noexcept(*_VSTD::forward<_Ip>(__i))) | |
| 64 | { | |
| 65 | if constexpr (is_lvalue_reference_v<decltype(*_VSTD::forward<_Ip>(__i))>) { | |
| 66 | return _VSTD::move(*_VSTD::forward<_Ip>(__i)); | |
| 67 | } else { | |
| 68 | return *_VSTD::forward<_Ip>(__i); | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | // [iterator.cust.move]/1.3 | |
| 73 | // Otherwise, ranges::iter_move(E) is ill-formed. | |
| 74 | }; | |
| 75 | } // namespace ranges::__iter_move | |
| 76 | ||
| 77 | namespace ranges::inline __cpo { | |
| 78 | inline constexpr auto iter_move = __iter_move::__fn{}; | |
| 79 | } | |
| 80 | ||
| 81 | template<__dereferenceable _Tp> | |
| 82 | requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __referenceable; } | |
| 83 | using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<_Tp&>())); | |
| 84 | ||
| 85 | #endif // !_LIBCPP_HAS_NO_RANGES | |
| 86 | ||
| 87 | _LIBCPP_END_NAMESPACE_STD | |
| 88 | ||
| 89 | _LIBCPP_POP_MACROS | |
| 90 | ||
| 91 | #endif // _LIBCPP___ITERATOR_ITER_MOVE_H |
lib/libcxx/include/__iterator/iter_swap.h created+107| ... | ... | @@ -0,0 +1,107 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___ITERATOR_ITER_SWAP_H | |
| 10 | #define _LIBCPP___ITERATOR_ITER_SWAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/iter_move.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__iterator/readable_traits.h> | |
| 17 | #include <__ranges/access.h> | |
| 18 | #include <concepts> | |
| 19 | #include <type_traits> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 31 | ||
| 32 | namespace ranges { | |
| 33 | namespace __iter_swap { | |
| 34 | template<class _I1, class _I2> | |
| 35 | void iter_swap(_I1, _I2) = delete; | |
| 36 | ||
| 37 | template<class _T1, class _T2> | |
| 38 | concept __unqualified_iter_swap = requires(_T1&& __x, _T2&& __y) { | |
| 39 | iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); | |
| 40 | }; | |
| 41 | ||
| 42 | template<class _T1, class _T2> | |
| 43 | concept __readable_swappable = | |
| 44 | indirectly_readable<_T1> && indirectly_readable<_T2> && | |
| 45 | swappable_with<iter_reference_t<_T1>, iter_reference_t<_T2>>; | |
| 46 | ||
| 47 | struct __fn { | |
| 48 | template <class _T1, class _T2> | |
| 49 | requires __unqualified_iter_swap<_T1, _T2> | |
| 50 | _LIBCPP_HIDE_FROM_ABI | |
| 51 | constexpr void operator()(_T1&& __x, _T2&& __y) const | |
| 52 | noexcept(noexcept(iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)))) | |
| 53 | { | |
| 54 | (void)iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); | |
| 55 | } | |
| 56 | ||
| 57 | template <class _T1, class _T2> | |
| 58 | requires (!__unqualified_iter_swap<_T1, _T2>) && | |
| 59 | __readable_swappable<_T1, _T2> | |
| 60 | _LIBCPP_HIDE_FROM_ABI | |
| 61 | constexpr void operator()(_T1&& __x, _T2&& __y) const | |
| 62 | noexcept(noexcept(ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)))) | |
| 63 | { | |
| 64 | ranges::swap(*_VSTD::forward<_T1>(__x), *_VSTD::forward<_T2>(__y)); | |
| 65 | } | |
| 66 | ||
| 67 | template <class _T1, class _T2> | |
| 68 | requires (!__unqualified_iter_swap<_T1, _T2> && | |
| 69 | !__readable_swappable<_T1, _T2>) && | |
| 70 | indirectly_movable_storable<_T1, _T2> && | |
| 71 | indirectly_movable_storable<_T2, _T1> | |
| 72 | _LIBCPP_HIDE_FROM_ABI | |
| 73 | constexpr void operator()(_T1&& __x, _T2&& __y) const | |
| 74 | noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) && | |
| 75 | noexcept(*__y = ranges::iter_move(__x)) && | |
| 76 | noexcept(*_VSTD::forward<_T1>(__x) = declval<iter_value_t<_T2>>())) | |
| 77 | { | |
| 78 | iter_value_t<_T2> __old(ranges::iter_move(__y)); | |
| 79 | *__y = ranges::iter_move(__x); | |
| 80 | *_VSTD::forward<_T1>(__x) = _VSTD::move(__old); | |
| 81 | } | |
| 82 | }; | |
| 83 | } // end namespace __iter_swap | |
| 84 | ||
| 85 | inline namespace __cpo { | |
| 86 | inline constexpr auto iter_swap = __iter_swap::__fn{}; | |
| 87 | } // namespace __cpo | |
| 88 | ||
| 89 | } // namespace ranges | |
| 90 | ||
| 91 | template<class _I1, class _I2 = _I1> | |
| 92 | concept indirectly_swappable = | |
| 93 | indirectly_readable<_I1> && indirectly_readable<_I2> && | |
| 94 | requires(const _I1 __i1, const _I2 __i2) { | |
| 95 | ranges::iter_swap(__i1, __i1); | |
| 96 | ranges::iter_swap(__i2, __i2); | |
| 97 | ranges::iter_swap(__i1, __i2); | |
| 98 | ranges::iter_swap(__i2, __i1); | |
| 99 | }; | |
| 100 | ||
| 101 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 102 | ||
| 103 | _LIBCPP_END_NAMESPACE_STD | |
| 104 | ||
| 105 | _LIBCPP_POP_MACROS | |
| 106 | ||
| 107 | #endif // _LIBCPP___ITERATOR_ITER_SWAP_H |
lib/libcxx/include/__iterator/iterator.h created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template<class _Category, class _Tp, class _Distance = ptrdiff_t, | |
| 26 | class _Pointer = _Tp*, class _Reference = _Tp&> | |
| 27 | struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 iterator | |
| 28 | { | |
| 29 | typedef _Tp value_type; | |
| 30 | typedef _Distance difference_type; | |
| 31 | typedef _Pointer pointer; | |
| 32 | typedef _Reference reference; | |
| 33 | typedef _Category iterator_category; | |
| 34 | }; | |
| 35 | ||
| 36 | _LIBCPP_END_NAMESPACE_STD | |
| 37 | ||
| 38 | _LIBCPP_POP_MACROS | |
| 39 | ||
| 40 | #endif // _LIBCPP___ITERATOR_ITERATOR_H |
lib/libcxx/include/__iterator/iterator_traits.h created+500| ... | ... | @@ -0,0 +1,500 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_ITERATOR_TRAITS_H | |
| 11 | #define _LIBCPP___ITERATOR_ITERATOR_TRAITS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/incrementable_traits.h> | |
| 15 | #include <__iterator/readable_traits.h> | |
| 16 | #include <concepts> | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 29 | ||
| 30 | template <class _Tp> | |
| 31 | using __with_reference = _Tp&; | |
| 32 | ||
| 33 | template <class _Tp> | |
| 34 | concept __referenceable = requires { | |
| 35 | typename __with_reference<_Tp>; | |
| 36 | }; | |
| 37 | ||
| 38 | template <class _Tp> | |
| 39 | concept __dereferenceable = requires(_Tp& __t) { | |
| 40 | { *__t } -> __referenceable; // not required to be equality-preserving | |
| 41 | }; | |
| 42 | ||
| 43 | // [iterator.traits] | |
| 44 | template<__dereferenceable _Tp> | |
| 45 | using iter_reference_t = decltype(*declval<_Tp&>()); | |
| 46 | ||
| 47 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 48 | ||
| 49 | template <class _Iter> | |
| 50 | struct _LIBCPP_TEMPLATE_VIS iterator_traits; | |
| 51 | ||
| 52 | struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {}; | |
| 53 | struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {}; | |
| 54 | struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag : public input_iterator_tag {}; | |
| 55 | struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {}; | |
| 56 | struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {}; | |
| 57 | #if _LIBCPP_STD_VER > 17 | |
| 58 | struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag : public random_access_iterator_tag {}; | |
| 59 | #endif | |
| 60 | ||
| 61 | template <class _Iter> | |
| 62 | struct __iter_traits_cache { | |
| 63 | using type = _If< | |
| 64 | __is_primary_template<iterator_traits<_Iter> >::value, | |
| 65 | _Iter, | |
| 66 | iterator_traits<_Iter> | |
| 67 | >; | |
| 68 | }; | |
| 69 | template <class _Iter> | |
| 70 | using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type; | |
| 71 | ||
| 72 | struct __iter_concept_concept_test { | |
| 73 | template <class _Iter> | |
| 74 | using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept; | |
| 75 | }; | |
| 76 | struct __iter_concept_category_test { | |
| 77 | template <class _Iter> | |
| 78 | using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category; | |
| 79 | }; | |
| 80 | struct __iter_concept_random_fallback { | |
| 81 | template <class _Iter> | |
| 82 | using _Apply = _EnableIf< | |
| 83 | __is_primary_template<iterator_traits<_Iter> >::value, | |
| 84 | random_access_iterator_tag | |
| 85 | >; | |
| 86 | }; | |
| 87 | ||
| 88 | template <class _Iter, class _Tester> struct __test_iter_concept | |
| 89 | : _IsValidExpansion<_Tester::template _Apply, _Iter>, | |
| 90 | _Tester | |
| 91 | { | |
| 92 | }; | |
| 93 | ||
| 94 | template <class _Iter> | |
| 95 | struct __iter_concept_cache { | |
| 96 | using type = _Or< | |
| 97 | __test_iter_concept<_Iter, __iter_concept_concept_test>, | |
| 98 | __test_iter_concept<_Iter, __iter_concept_category_test>, | |
| 99 | __test_iter_concept<_Iter, __iter_concept_random_fallback> | |
| 100 | >; | |
| 101 | }; | |
| 102 | ||
| 103 | template <class _Iter> | |
| 104 | using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; | |
| 105 | ||
| 106 | ||
| 107 | template <class _Tp> | |
| 108 | struct __has_iterator_typedefs | |
| 109 | { | |
| 110 | private: | |
| 111 | struct __two {char __lx; char __lxx;}; | |
| 112 | template <class _Up> static __two __test(...); | |
| 113 | template <class _Up> static char __test(typename __void_t<typename _Up::iterator_category>::type* = 0, | |
| 114 | typename __void_t<typename _Up::difference_type>::type* = 0, | |
| 115 | typename __void_t<typename _Up::value_type>::type* = 0, | |
| 116 | typename __void_t<typename _Up::reference>::type* = 0, | |
| 117 | typename __void_t<typename _Up::pointer>::type* = 0); | |
| 118 | public: | |
| 119 | static const bool value = sizeof(__test<_Tp>(0,0,0,0,0)) == 1; | |
| 120 | }; | |
| 121 | ||
| 122 | ||
| 123 | template <class _Tp> | |
| 124 | struct __has_iterator_category | |
| 125 | { | |
| 126 | private: | |
| 127 | struct __two {char __lx; char __lxx;}; | |
| 128 | template <class _Up> static __two __test(...); | |
| 129 | template <class _Up> static char __test(typename _Up::iterator_category* = nullptr); | |
| 130 | public: | |
| 131 | static const bool value = sizeof(__test<_Tp>(nullptr)) == 1; | |
| 132 | }; | |
| 133 | ||
| 134 | template <class _Tp> | |
| 135 | struct __has_iterator_concept | |
| 136 | { | |
| 137 | private: | |
| 138 | struct __two {char __lx; char __lxx;}; | |
| 139 | template <class _Up> static __two __test(...); | |
| 140 | template <class _Up> static char __test(typename _Up::iterator_concept* = nullptr); | |
| 141 | public: | |
| 142 | static const bool value = sizeof(__test<_Tp>(nullptr)) == 1; | |
| 143 | }; | |
| 144 | ||
| 145 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 146 | ||
| 147 | // The `cpp17-*-iterator` exposition-only concepts are easily confused with the Cpp17*Iterator tables, | |
| 148 | // so they've been banished to a namespace that makes it obvious they have a niche use-case. | |
| 149 | namespace __iterator_traits_detail { | |
| 150 | template<class _Ip> | |
| 151 | concept __cpp17_iterator = | |
| 152 | requires(_Ip __i) { | |
| 153 | { *__i } -> __referenceable; | |
| 154 | { ++__i } -> same_as<_Ip&>; | |
| 155 | { *__i++ } -> __referenceable; | |
| 156 | } && | |
| 157 | copyable<_Ip>; | |
| 158 | ||
| 159 | template<class _Ip> | |
| 160 | concept __cpp17_input_iterator = | |
| 161 | __cpp17_iterator<_Ip> && | |
| 162 | equality_comparable<_Ip> && | |
| 163 | requires(_Ip __i) { | |
| 164 | typename incrementable_traits<_Ip>::difference_type; | |
| 165 | typename indirectly_readable_traits<_Ip>::value_type; | |
| 166 | typename common_reference_t<iter_reference_t<_Ip>&&, | |
| 167 | typename indirectly_readable_traits<_Ip>::value_type&>; | |
| 168 | typename common_reference_t<decltype(*__i++)&&, | |
| 169 | typename indirectly_readable_traits<_Ip>::value_type&>; | |
| 170 | requires signed_integral<typename incrementable_traits<_Ip>::difference_type>; | |
| 171 | }; | |
| 172 | ||
| 173 | template<class _Ip> | |
| 174 | concept __cpp17_forward_iterator = | |
| 175 | __cpp17_input_iterator<_Ip> && | |
| 176 | constructible_from<_Ip> && | |
| 177 | is_lvalue_reference_v<iter_reference_t<_Ip>> && | |
| 178 | same_as<remove_cvref_t<iter_reference_t<_Ip>>, | |
| 179 | typename indirectly_readable_traits<_Ip>::value_type> && | |
| 180 | requires(_Ip __i) { | |
| 181 | { __i++ } -> convertible_to<_Ip const&>; | |
| 182 | { *__i++ } -> same_as<iter_reference_t<_Ip>>; | |
| 183 | }; | |
| 184 | ||
| 185 | template<class _Ip> | |
| 186 | concept __cpp17_bidirectional_iterator = | |
| 187 | __cpp17_forward_iterator<_Ip> && | |
| 188 | requires(_Ip __i) { | |
| 189 | { --__i } -> same_as<_Ip&>; | |
| 190 | { __i-- } -> convertible_to<_Ip const&>; | |
| 191 | { *__i-- } -> same_as<iter_reference_t<_Ip>>; | |
| 192 | }; | |
| 193 | ||
| 194 | template<class _Ip> | |
| 195 | concept __cpp17_random_access_iterator = | |
| 196 | __cpp17_bidirectional_iterator<_Ip> && | |
| 197 | totally_ordered<_Ip> && | |
| 198 | requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) { | |
| 199 | { __i += __n } -> same_as<_Ip&>; | |
| 200 | { __i -= __n } -> same_as<_Ip&>; | |
| 201 | { __i + __n } -> same_as<_Ip>; | |
| 202 | { __n + __i } -> same_as<_Ip>; | |
| 203 | { __i - __n } -> same_as<_Ip>; | |
| 204 | { __i - __i } -> same_as<decltype(__n)>; | |
| 205 | { __i[__n] } -> convertible_to<iter_reference_t<_Ip>>; | |
| 206 | }; | |
| 207 | } // namespace __iterator_traits_detail | |
| 208 | ||
| 209 | template<class _Ip> | |
| 210 | concept __has_member_reference = requires { typename _Ip::reference; }; | |
| 211 | ||
| 212 | template<class _Ip> | |
| 213 | concept __has_member_pointer = requires { typename _Ip::pointer; }; | |
| 214 | ||
| 215 | template<class _Ip> | |
| 216 | concept __has_member_iterator_category = requires { typename _Ip::iterator_category; }; | |
| 217 | ||
| 218 | template<class _Ip> | |
| 219 | concept __specifies_members = requires { | |
| 220 | typename _Ip::value_type; | |
| 221 | typename _Ip::difference_type; | |
| 222 | requires __has_member_reference<_Ip>; | |
| 223 | requires __has_member_iterator_category<_Ip>; | |
| 224 | }; | |
| 225 | ||
| 226 | template<class> | |
| 227 | struct __iterator_traits_member_pointer_or_void { | |
| 228 | using type = void; | |
| 229 | }; | |
| 230 | ||
| 231 | template<__has_member_pointer _Tp> | |
| 232 | struct __iterator_traits_member_pointer_or_void<_Tp> { | |
| 233 | using type = typename _Tp::pointer; | |
| 234 | }; | |
| 235 | ||
| 236 | template<class _Tp> | |
| 237 | concept __cpp17_iterator_missing_members = | |
| 238 | !__specifies_members<_Tp> && | |
| 239 | __iterator_traits_detail::__cpp17_iterator<_Tp>; | |
| 240 | ||
| 241 | template<class _Tp> | |
| 242 | concept __cpp17_input_iterator_missing_members = | |
| 243 | __cpp17_iterator_missing_members<_Tp> && | |
| 244 | __iterator_traits_detail::__cpp17_input_iterator<_Tp>; | |
| 245 | ||
| 246 | // Otherwise, `pointer` names `void`. | |
| 247 | template<class> | |
| 248 | struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; }; | |
| 249 | ||
| 250 | // [iterator.traits]/3.2.1 | |
| 251 | // If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type. | |
| 252 | template<__has_member_pointer _Ip> | |
| 253 | struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typename _Ip::pointer; }; | |
| 254 | ||
| 255 | // Otherwise, if `decltype(declval<I&>().operator->())` is well-formed, then `pointer` names that | |
| 256 | // type. | |
| 257 | template<class _Ip> | |
| 258 | requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>) | |
| 259 | struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { | |
| 260 | using type = decltype(declval<_Ip&>().operator->()); | |
| 261 | }; | |
| 262 | ||
| 263 | // Otherwise, `reference` names `iter-reference-t<I>`. | |
| 264 | template<class _Ip> | |
| 265 | struct __iterator_traits_member_reference { using type = iter_reference_t<_Ip>; }; | |
| 266 | ||
| 267 | // [iterator.traits]/3.2.2 | |
| 268 | // If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type. | |
| 269 | template<__has_member_reference _Ip> | |
| 270 | struct __iterator_traits_member_reference<_Ip> { using type = typename _Ip::reference; }; | |
| 271 | ||
| 272 | // [iterator.traits]/3.2.3.4 | |
| 273 | // input_iterator_tag | |
| 274 | template<class _Ip> | |
| 275 | struct __deduce_iterator_category { | |
| 276 | using type = input_iterator_tag; | |
| 277 | }; | |
| 278 | ||
| 279 | // [iterator.traits]/3.2.3.1 | |
| 280 | // `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise | |
| 281 | template<__iterator_traits_detail::__cpp17_random_access_iterator _Ip> | |
| 282 | struct __deduce_iterator_category<_Ip> { | |
| 283 | using type = random_access_iterator_tag; | |
| 284 | }; | |
| 285 | ||
| 286 | // [iterator.traits]/3.2.3.2 | |
| 287 | // `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise | |
| 288 | template<__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip> | |
| 289 | struct __deduce_iterator_category<_Ip> { | |
| 290 | using type = bidirectional_iterator_tag; | |
| 291 | }; | |
| 292 | ||
| 293 | // [iterator.traits]/3.2.3.3 | |
| 294 | // `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise | |
| 295 | template<__iterator_traits_detail::__cpp17_forward_iterator _Ip> | |
| 296 | struct __deduce_iterator_category<_Ip> { | |
| 297 | using type = forward_iterator_tag; | |
| 298 | }; | |
| 299 | ||
| 300 | template<class _Ip> | |
| 301 | struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {}; | |
| 302 | ||
| 303 | // [iterator.traits]/3.2.3 | |
| 304 | // If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names | |
| 305 | // that type. | |
| 306 | template<__has_member_iterator_category _Ip> | |
| 307 | struct __iterator_traits_iterator_category<_Ip> { | |
| 308 | using type = typename _Ip::iterator_category; | |
| 309 | }; | |
| 310 | ||
| 311 | // otherwise, it names void. | |
| 312 | template<class> | |
| 313 | struct __iterator_traits_difference_type { using type = void; }; | |
| 314 | ||
| 315 | // If the qualified-id `incrementable_traits<I>::difference_type` is valid and denotes a type, then | |
| 316 | // `difference_type` names that type; | |
| 317 | template<class _Ip> | |
| 318 | requires requires { typename incrementable_traits<_Ip>::difference_type; } | |
| 319 | struct __iterator_traits_difference_type<_Ip> { | |
| 320 | using type = typename incrementable_traits<_Ip>::difference_type; | |
| 321 | }; | |
| 322 | ||
| 323 | // [iterator.traits]/3.4 | |
| 324 | // Otherwise, `iterator_traits<I>` has no members by any of the above names. | |
| 325 | template<class> | |
| 326 | struct __iterator_traits {}; | |
| 327 | ||
| 328 | // [iterator.traits]/3.1 | |
| 329 | // If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and | |
| 330 | // `iterator-category`, then `iterator-traits<I>` has the following publicly accessible members: | |
| 331 | template<__specifies_members _Ip> | |
| 332 | struct __iterator_traits<_Ip> { | |
| 333 | using iterator_category = typename _Ip::iterator_category; | |
| 334 | using value_type = typename _Ip::value_type; | |
| 335 | using difference_type = typename _Ip::difference_type; | |
| 336 | using pointer = typename __iterator_traits_member_pointer_or_void<_Ip>::type; | |
| 337 | using reference = typename _Ip::reference; | |
| 338 | }; | |
| 339 | ||
| 340 | // [iterator.traits]/3.2 | |
| 341 | // Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`, | |
| 342 | // `iterator-traits<I>` has the following publicly accessible members: | |
| 343 | template<__cpp17_input_iterator_missing_members _Ip> | |
| 344 | struct __iterator_traits<_Ip> { | |
| 345 | using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type; | |
| 346 | using value_type = typename indirectly_readable_traits<_Ip>::value_type; | |
| 347 | using difference_type = typename incrementable_traits<_Ip>::difference_type; | |
| 348 | using pointer = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type; | |
| 349 | using reference = typename __iterator_traits_member_reference<_Ip>::type; | |
| 350 | }; | |
| 351 | ||
| 352 | // Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then | |
| 353 | // `iterator_traits<I>` has the following publicly accessible members: | |
| 354 | template<__cpp17_iterator_missing_members _Ip> | |
| 355 | struct __iterator_traits<_Ip> { | |
| 356 | using iterator_category = output_iterator_tag; | |
| 357 | using value_type = void; | |
| 358 | using difference_type = typename __iterator_traits_difference_type<_Ip>::type; | |
| 359 | using pointer = void; | |
| 360 | using reference = void; | |
| 361 | }; | |
| 362 | ||
| 363 | template<class _Ip> | |
| 364 | struct iterator_traits : __iterator_traits<_Ip> { | |
| 365 | using __primary_template = iterator_traits; | |
| 366 | }; | |
| 367 | ||
| 368 | #else // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 369 | ||
| 370 | template <class _Iter, bool> struct __iterator_traits {}; | |
| 371 | ||
| 372 | template <class _Iter, bool> struct __iterator_traits_impl {}; | |
| 373 | ||
| 374 | template <class _Iter> | |
| 375 | struct __iterator_traits_impl<_Iter, true> | |
| 376 | { | |
| 377 | typedef typename _Iter::difference_type difference_type; | |
| 378 | typedef typename _Iter::value_type value_type; | |
| 379 | typedef typename _Iter::pointer pointer; | |
| 380 | typedef typename _Iter::reference reference; | |
| 381 | typedef typename _Iter::iterator_category iterator_category; | |
| 382 | }; | |
| 383 | ||
| 384 | template <class _Iter> | |
| 385 | struct __iterator_traits<_Iter, true> | |
| 386 | : __iterator_traits_impl | |
| 387 | < | |
| 388 | _Iter, | |
| 389 | is_convertible<typename _Iter::iterator_category, input_iterator_tag>::value || | |
| 390 | is_convertible<typename _Iter::iterator_category, output_iterator_tag>::value | |
| 391 | > | |
| 392 | {}; | |
| 393 | ||
| 394 | // iterator_traits<Iterator> will only have the nested types if Iterator::iterator_category | |
| 395 | // exists. Else iterator_traits<Iterator> will be an empty class. This is a | |
| 396 | // conforming extension which allows some programs to compile and behave as | |
| 397 | // the client expects instead of failing at compile time. | |
| 398 | ||
| 399 | template <class _Iter> | |
| 400 | struct _LIBCPP_TEMPLATE_VIS iterator_traits | |
| 401 | : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { | |
| 402 | ||
| 403 | using __primary_template = iterator_traits; | |
| 404 | }; | |
| 405 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 406 | ||
| 407 | template<class _Tp> | |
| 408 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 409 | requires is_object_v<_Tp> | |
| 410 | #endif | |
| 411 | struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> | |
| 412 | { | |
| 413 | typedef ptrdiff_t difference_type; | |
| 414 | typedef typename remove_cv<_Tp>::type value_type; | |
| 415 | typedef _Tp* pointer; | |
| 416 | typedef _Tp& reference; | |
| 417 | typedef random_access_iterator_tag iterator_category; | |
| 418 | #if _LIBCPP_STD_VER > 17 | |
| 419 | typedef contiguous_iterator_tag iterator_concept; | |
| 420 | #endif | |
| 421 | }; | |
| 422 | ||
| 423 | template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value> | |
| 424 | struct __has_iterator_category_convertible_to | |
| 425 | : is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up> | |
| 426 | {}; | |
| 427 | ||
| 428 | template <class _Tp, class _Up> | |
| 429 | struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {}; | |
| 430 | ||
| 431 | template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value> | |
| 432 | struct __has_iterator_concept_convertible_to | |
| 433 | : is_convertible<typename _Tp::iterator_concept, _Up> | |
| 434 | {}; | |
| 435 | ||
| 436 | template <class _Tp, class _Up> | |
| 437 | struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; | |
| 438 | ||
| 439 | template <class _Tp> | |
| 440 | struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {}; | |
| 441 | ||
| 442 | template <class _Tp> | |
| 443 | struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {}; | |
| 444 | ||
| 445 | template <class _Tp> | |
| 446 | struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {}; | |
| 447 | ||
| 448 | template <class _Tp> | |
| 449 | struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {}; | |
| 450 | ||
| 451 | // __is_cpp17_contiguous_iterator determines if an iterator is known by | |
| 452 | // libc++ to be contiguous, either because it advertises itself as such | |
| 453 | // (in C++20) or because it is a pointer type or a known trivial wrapper | |
| 454 | // around a (possibly fancy) pointer type, such as __wrap_iter<T*>. | |
| 455 | // Such iterators receive special "contiguous" optimizations in | |
| 456 | // std::copy and std::sort. | |
| 457 | // | |
| 458 | #if _LIBCPP_STD_VER > 17 | |
| 459 | template <class _Tp> | |
| 460 | struct __is_cpp17_contiguous_iterator : _Or< | |
| 461 | __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>, | |
| 462 | __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag> | |
| 463 | > {}; | |
| 464 | #else | |
| 465 | template <class _Tp> | |
| 466 | struct __is_cpp17_contiguous_iterator : false_type {}; | |
| 467 | #endif | |
| 468 | ||
| 469 | // Any native pointer which is an iterator is also a contiguous iterator. | |
| 470 | template <class _Up> | |
| 471 | struct __is_cpp17_contiguous_iterator<_Up*> : true_type {}; | |
| 472 | ||
| 473 | ||
| 474 | template <class _Tp> | |
| 475 | struct __is_exactly_cpp17_input_iterator | |
| 476 | : public integral_constant<bool, | |
| 477 | __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value && | |
| 478 | !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; | |
| 479 | ||
| 480 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 481 | template<class _InputIterator> | |
| 482 | using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; | |
| 483 | ||
| 484 | template<class _InputIterator> | |
| 485 | using __iter_key_type = remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>; | |
| 486 | ||
| 487 | template<class _InputIterator> | |
| 488 | using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; | |
| 489 | ||
| 490 | template<class _InputIterator> | |
| 491 | using __iter_to_alloc_type = pair< | |
| 492 | add_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>, | |
| 493 | typename iterator_traits<_InputIterator>::value_type::second_type>; | |
| 494 | #endif // _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 495 | ||
| 496 | _LIBCPP_END_NAMESPACE_STD | |
| 497 | ||
| 498 | _LIBCPP_POP_MACROS | |
| 499 | ||
| 500 | #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H |
lib/libcxx/include/__iterator/move_iterator.h created+189| ... | ... | @@ -0,0 +1,189 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_MOVE_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_MOVE_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Iter> | |
| 27 | class _LIBCPP_TEMPLATE_VIS move_iterator | |
| 28 | { | |
| 29 | private: | |
| 30 | _Iter __i; | |
| 31 | public: | |
| 32 | typedef _Iter iterator_type; | |
| 33 | typedef typename iterator_traits<iterator_type>::value_type value_type; | |
| 34 | typedef typename iterator_traits<iterator_type>::difference_type difference_type; | |
| 35 | typedef iterator_type pointer; | |
| 36 | typedef _If<__is_cpp17_random_access_iterator<_Iter>::value, | |
| 37 | random_access_iterator_tag, | |
| 38 | typename iterator_traits<_Iter>::iterator_category> iterator_category; | |
| 39 | #if _LIBCPP_STD_VER > 17 | |
| 40 | typedef input_iterator_tag iterator_concept; | |
| 41 | #endif | |
| 42 | ||
| 43 | #ifndef _LIBCPP_CXX03_LANG | |
| 44 | typedef typename iterator_traits<iterator_type>::reference __reference; | |
| 45 | typedef typename conditional< | |
| 46 | is_reference<__reference>::value, | |
| 47 | typename remove_reference<__reference>::type&&, | |
| 48 | __reference | |
| 49 | >::type reference; | |
| 50 | #else | |
| 51 | typedef typename iterator_traits<iterator_type>::reference reference; | |
| 52 | #endif | |
| 53 | ||
| 54 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 55 | move_iterator() : __i() {} | |
| 56 | ||
| 57 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 58 | explicit move_iterator(_Iter __x) : __i(__x) {} | |
| 59 | ||
| 60 | template <class _Up, class = _EnableIf< | |
| 61 | !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value | |
| 62 | > > | |
| 63 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 64 | move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {} | |
| 65 | ||
| 66 | template <class _Up, class = _EnableIf< | |
| 67 | !is_same<_Up, _Iter>::value && | |
| 68 | is_convertible<_Up const&, _Iter>::value && | |
| 69 | is_assignable<_Iter&, _Up const&>::value | |
| 70 | > > | |
| 71 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 72 | move_iterator& operator=(const move_iterator<_Up>& __u) { | |
| 73 | __i = __u.base(); | |
| 74 | return *this; | |
| 75 | } | |
| 76 | ||
| 77 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return __i;} | |
| 78 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 79 | reference operator*() const { return static_cast<reference>(*__i); } | |
| 80 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 81 | pointer operator->() const { return __i;} | |
| 82 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 83 | move_iterator& operator++() {++__i; return *this;} | |
| 84 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 85 | move_iterator operator++(int) {move_iterator __tmp(*this); ++__i; return __tmp;} | |
| 86 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 87 | move_iterator& operator--() {--__i; return *this;} | |
| 88 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 89 | move_iterator operator--(int) {move_iterator __tmp(*this); --__i; return __tmp;} | |
| 90 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 91 | move_iterator operator+ (difference_type __n) const {return move_iterator(__i + __n);} | |
| 92 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 93 | move_iterator& operator+=(difference_type __n) {__i += __n; return *this;} | |
| 94 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 95 | move_iterator operator- (difference_type __n) const {return move_iterator(__i - __n);} | |
| 96 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 97 | move_iterator& operator-=(difference_type __n) {__i -= __n; return *this;} | |
| 98 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 99 | reference operator[](difference_type __n) const { return static_cast<reference>(__i[__n]); } | |
| 100 | }; | |
| 101 | ||
| 102 | template <class _Iter1, class _Iter2> | |
| 103 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 104 | bool | |
| 105 | operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 106 | { | |
| 107 | return __x.base() == __y.base(); | |
| 108 | } | |
| 109 | ||
| 110 | template <class _Iter1, class _Iter2> | |
| 111 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 112 | bool | |
| 113 | operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 114 | { | |
| 115 | return __x.base() < __y.base(); | |
| 116 | } | |
| 117 | ||
| 118 | template <class _Iter1, class _Iter2> | |
| 119 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 120 | bool | |
| 121 | operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 122 | { | |
| 123 | return __x.base() != __y.base(); | |
| 124 | } | |
| 125 | ||
| 126 | template <class _Iter1, class _Iter2> | |
| 127 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 128 | bool | |
| 129 | operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 130 | { | |
| 131 | return __x.base() > __y.base(); | |
| 132 | } | |
| 133 | ||
| 134 | template <class _Iter1, class _Iter2> | |
| 135 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 136 | bool | |
| 137 | operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 138 | { | |
| 139 | return __x.base() >= __y.base(); | |
| 140 | } | |
| 141 | ||
| 142 | template <class _Iter1, class _Iter2> | |
| 143 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 144 | bool | |
| 145 | operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 146 | { | |
| 147 | return __x.base() <= __y.base(); | |
| 148 | } | |
| 149 | ||
| 150 | #ifndef _LIBCPP_CXX03_LANG | |
| 151 | template <class _Iter1, class _Iter2> | |
| 152 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 153 | auto | |
| 154 | operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 155 | -> decltype(__x.base() - __y.base()) | |
| 156 | { | |
| 157 | return __x.base() - __y.base(); | |
| 158 | } | |
| 159 | #else | |
| 160 | template <class _Iter1, class _Iter2> | |
| 161 | inline _LIBCPP_INLINE_VISIBILITY | |
| 162 | typename move_iterator<_Iter1>::difference_type | |
| 163 | operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 164 | { | |
| 165 | return __x.base() - __y.base(); | |
| 166 | } | |
| 167 | #endif | |
| 168 | ||
| 169 | template <class _Iter> | |
| 170 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 171 | move_iterator<_Iter> | |
| 172 | operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) | |
| 173 | { | |
| 174 | return move_iterator<_Iter>(__x.base() + __n); | |
| 175 | } | |
| 176 | ||
| 177 | template <class _Iter> | |
| 178 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 179 | move_iterator<_Iter> | |
| 180 | make_move_iterator(_Iter __i) | |
| 181 | { | |
| 182 | return move_iterator<_Iter>(__i); | |
| 183 | } | |
| 184 | ||
| 185 | _LIBCPP_END_NAMESPACE_STD | |
| 186 | ||
| 187 | _LIBCPP_POP_MACROS | |
| 188 | ||
| 189 | #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H |
lib/libcxx/include/__iterator/next.h created+87| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_NEXT_H | |
| 11 | #define _LIBCPP___ITERATOR_NEXT_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__debug> | |
| 15 | #include <__function_like.h> | |
| 16 | #include <__iterator/advance.h> | |
| 17 | #include <__iterator/concepts.h> | |
| 18 | #include <__iterator/incrementable_traits.h> | |
| 19 | #include <__iterator/iterator_traits.h> | |
| 20 | #include <type_traits> | |
| 21 | ||
| 22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 23 | #pragma GCC system_header | |
| 24 | #endif | |
| 25 | ||
| 26 | _LIBCPP_PUSH_MACROS | |
| 27 | #include <__undef_macros> | |
| 28 | ||
| 29 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 30 | ||
| 31 | template <class _InputIter> | |
| 32 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 33 | typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type | |
| 34 | next(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { | |
| 35 | _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, | |
| 36 | "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); | |
| 37 | ||
| 38 | _VSTD::advance(__x, __n); | |
| 39 | return __x; | |
| 40 | } | |
| 41 | ||
| 42 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 43 | ||
| 44 | namespace ranges { | |
| 45 | struct __next_fn final : private __function_like { | |
| 46 | _LIBCPP_HIDE_FROM_ABI | |
| 47 | constexpr explicit __next_fn(__tag __x) noexcept : __function_like(__x) {} | |
| 48 | ||
| 49 | template <input_or_output_iterator _Ip> | |
| 50 | _LIBCPP_HIDE_FROM_ABI | |
| 51 | constexpr _Ip operator()(_Ip __x) const { | |
| 52 | ++__x; | |
| 53 | return __x; | |
| 54 | } | |
| 55 | ||
| 56 | template <input_or_output_iterator _Ip> | |
| 57 | _LIBCPP_HIDE_FROM_ABI | |
| 58 | constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n) const { | |
| 59 | ranges::advance(__x, __n); | |
| 60 | return __x; | |
| 61 | } | |
| 62 | ||
| 63 | template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp> | |
| 64 | _LIBCPP_HIDE_FROM_ABI | |
| 65 | constexpr _Ip operator()(_Ip __x, _Sp __bound) const { | |
| 66 | ranges::advance(__x, __bound); | |
| 67 | return __x; | |
| 68 | } | |
| 69 | ||
| 70 | template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp> | |
| 71 | _LIBCPP_HIDE_FROM_ABI | |
| 72 | constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n, _Sp __bound) const { | |
| 73 | ranges::advance(__x, __n, __bound); | |
| 74 | return __x; | |
| 75 | } | |
| 76 | }; | |
| 77 | ||
| 78 | inline constexpr auto next = __next_fn(__function_like::__tag()); | |
| 79 | } // namespace ranges | |
| 80 | ||
| 81 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 82 | ||
| 83 | _LIBCPP_END_NAMESPACE_STD | |
| 84 | ||
| 85 | _LIBCPP_POP_MACROS | |
| 86 | ||
| 87 | #endif // _LIBCPP___ITERATOR_PRIMITIVES_H |
lib/libcxx/include/__iterator/ostream_iterator.h created+75| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_OSTREAM_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_OSTREAM_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/addressof.h> | |
| 17 | #include <iosfwd> // for forward declarations of char_traits and basic_ostream | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 29 | template <class _Tp, class _CharT = char, class _Traits = char_traits<_CharT> > | |
| 30 | class _LIBCPP_TEMPLATE_VIS ostream_iterator | |
| 31 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 32 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 33 | #endif | |
| 34 | { | |
| 35 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 36 | public: | |
| 37 | typedef output_iterator_tag iterator_category; | |
| 38 | typedef void value_type; | |
| 39 | #if _LIBCPP_STD_VER > 17 | |
| 40 | typedef ptrdiff_t difference_type; | |
| 41 | #else | |
| 42 | typedef void difference_type; | |
| 43 | #endif | |
| 44 | typedef void pointer; | |
| 45 | typedef void reference; | |
| 46 | typedef _CharT char_type; | |
| 47 | typedef _Traits traits_type; | |
| 48 | typedef basic_ostream<_CharT, _Traits> ostream_type; | |
| 49 | ||
| 50 | private: | |
| 51 | ostream_type* __out_stream_; | |
| 52 | const char_type* __delim_; | |
| 53 | public: | |
| 54 | _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s) _NOEXCEPT | |
| 55 | : __out_stream_(_VSTD::addressof(__s)), __delim_(nullptr) {} | |
| 56 | _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s, const _CharT* __delimiter) _NOEXCEPT | |
| 57 | : __out_stream_(_VSTD::addressof(__s)), __delim_(__delimiter) {} | |
| 58 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator=(const _Tp& __value_) | |
| 59 | { | |
| 60 | *__out_stream_ << __value_; | |
| 61 | if (__delim_) | |
| 62 | *__out_stream_ << __delim_; | |
| 63 | return *this; | |
| 64 | } | |
| 65 | ||
| 66 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator*() {return *this;} | |
| 67 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator++() {return *this;} | |
| 68 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator++(int) {return *this;} | |
| 69 | }; | |
| 70 | ||
| 71 | _LIBCPP_END_NAMESPACE_STD | |
| 72 | ||
| 73 | _LIBCPP_POP_MACROS | |
| 74 | ||
| 75 | #endif // _LIBCPP___ITERATOR_OSTREAM_ITERATOR_H |
lib/libcxx/include/__iterator/ostreambuf_iterator.h created+81| ... | ... | @@ -0,0 +1,81 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_OSTREAMBUF_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_OSTREAMBUF_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <iosfwd> // for forward declaration of basic_streambuf | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 28 | template <class _CharT, class _Traits> | |
| 29 | class _LIBCPP_TEMPLATE_VIS ostreambuf_iterator | |
| 30 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 31 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 32 | #endif | |
| 33 | { | |
| 34 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 35 | public: | |
| 36 | typedef output_iterator_tag iterator_category; | |
| 37 | typedef void value_type; | |
| 38 | #if _LIBCPP_STD_VER > 17 | |
| 39 | typedef ptrdiff_t difference_type; | |
| 40 | #else | |
| 41 | typedef void difference_type; | |
| 42 | #endif | |
| 43 | typedef void pointer; | |
| 44 | typedef void reference; | |
| 45 | typedef _CharT char_type; | |
| 46 | typedef _Traits traits_type; | |
| 47 | typedef basic_streambuf<_CharT, _Traits> streambuf_type; | |
| 48 | typedef basic_ostream<_CharT, _Traits> ostream_type; | |
| 49 | ||
| 50 | private: | |
| 51 | streambuf_type* __sbuf_; | |
| 52 | public: | |
| 53 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(ostream_type& __s) _NOEXCEPT | |
| 54 | : __sbuf_(__s.rdbuf()) {} | |
| 55 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(streambuf_type* __s) _NOEXCEPT | |
| 56 | : __sbuf_(__s) {} | |
| 57 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator=(_CharT __c) | |
| 58 | { | |
| 59 | if (__sbuf_ && traits_type::eq_int_type(__sbuf_->sputc(__c), traits_type::eof())) | |
| 60 | __sbuf_ = nullptr; | |
| 61 | return *this; | |
| 62 | } | |
| 63 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator*() {return *this;} | |
| 64 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator++() {return *this;} | |
| 65 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator++(int) {return *this;} | |
| 66 | _LIBCPP_INLINE_VISIBILITY bool failed() const _NOEXCEPT {return __sbuf_ == nullptr;} | |
| 67 | ||
| 68 | template <class _Ch, class _Tr> | |
| 69 | friend | |
| 70 | _LIBCPP_HIDDEN | |
| 71 | ostreambuf_iterator<_Ch, _Tr> | |
| 72 | __pad_and_output(ostreambuf_iterator<_Ch, _Tr> __s, | |
| 73 | const _Ch* __ob, const _Ch* __op, const _Ch* __oe, | |
| 74 | ios_base& __iob, _Ch __fl); | |
| 75 | }; | |
| 76 | ||
| 77 | _LIBCPP_END_NAMESPACE_STD | |
| 78 | ||
| 79 | _LIBCPP_POP_MACROS | |
| 80 | ||
| 81 | #endif // _LIBCPP___ITERATOR_OSTREAMBUF_ITERATOR_H |
lib/libcxx/include/__iterator/prev.h created+79| ... | ... | @@ -0,0 +1,79 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_PREV_H | |
| 11 | #define _LIBCPP___ITERATOR_PREV_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__debug> | |
| 15 | #include <__function_like.h> | |
| 16 | #include <__iterator/advance.h> | |
| 17 | #include <__iterator/concepts.h> | |
| 18 | #include <__iterator/incrementable_traits.h> | |
| 19 | #include <__iterator/iterator_traits.h> | |
| 20 | #include <type_traits> | |
| 21 | ||
| 22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 23 | #pragma GCC system_header | |
| 24 | #endif | |
| 25 | ||
| 26 | _LIBCPP_PUSH_MACROS | |
| 27 | #include <__undef_macros> | |
| 28 | ||
| 29 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 30 | ||
| 31 | template <class _InputIter> | |
| 32 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 33 | typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type | |
| 34 | prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { | |
| 35 | _LIBCPP_ASSERT(__n <= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, | |
| 36 | "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); | |
| 37 | _VSTD::advance(__x, -__n); | |
| 38 | return __x; | |
| 39 | } | |
| 40 | ||
| 41 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 42 | ||
| 43 | namespace ranges { | |
| 44 | struct __prev_fn final : private __function_like { | |
| 45 | _LIBCPP_HIDE_FROM_ABI | |
| 46 | constexpr explicit __prev_fn(__tag __x) noexcept : __function_like(__x) {} | |
| 47 | ||
| 48 | template <bidirectional_iterator _Ip> | |
| 49 | _LIBCPP_HIDE_FROM_ABI | |
| 50 | constexpr _Ip operator()(_Ip __x) const { | |
| 51 | --__x; | |
| 52 | return __x; | |
| 53 | } | |
| 54 | ||
| 55 | template <bidirectional_iterator _Ip> | |
| 56 | _LIBCPP_HIDE_FROM_ABI | |
| 57 | constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n) const { | |
| 58 | ranges::advance(__x, -__n); | |
| 59 | return __x; | |
| 60 | } | |
| 61 | ||
| 62 | template <bidirectional_iterator _Ip> | |
| 63 | _LIBCPP_HIDE_FROM_ABI | |
| 64 | constexpr _Ip operator()(_Ip __x, iter_difference_t<_Ip> __n, _Ip __bound) const { | |
| 65 | ranges::advance(__x, -__n, __bound); | |
| 66 | return __x; | |
| 67 | } | |
| 68 | }; | |
| 69 | ||
| 70 | inline constexpr auto prev = __prev_fn(__function_like::__tag()); | |
| 71 | } // namespace ranges | |
| 72 | ||
| 73 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 74 | ||
| 75 | _LIBCPP_END_NAMESPACE_STD | |
| 76 | ||
| 77 | _LIBCPP_POP_MACROS | |
| 78 | ||
| 79 | #endif // _LIBCPP___ITERATOR_PREV_H |
lib/libcxx/include/__iterator/projected.h created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___ITERATOR_PROJECTED_H | |
| 10 | #define _LIBCPP___ITERATOR_PROJECTED_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/incrementable_traits.h> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 27 | ||
| 28 | template<indirectly_readable _It, indirectly_regular_unary_invocable<_It> _Proj> | |
| 29 | struct projected { | |
| 30 | using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>; | |
| 31 | indirect_result_t<_Proj&, _It> operator*() const; // not defined | |
| 32 | }; | |
| 33 | ||
| 34 | template<weakly_incrementable _It, class _Proj> | |
| 35 | struct incrementable_traits<projected<_It, _Proj>> { | |
| 36 | using difference_type = iter_difference_t<_It>; | |
| 37 | }; | |
| 38 | ||
| 39 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 40 | ||
| 41 | _LIBCPP_END_NAMESPACE_STD | |
| 42 | ||
| 43 | _LIBCPP_POP_MACROS | |
| 44 | ||
| 45 | #endif // _LIBCPP___ITERATOR_PROJECTED_H |
lib/libcxx/include/__iterator/readable_traits.h created+91| ... | ... | @@ -0,0 +1,91 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_READABLE_TRAITS_H | |
| 11 | #define _LIBCPP___ITERATOR_READABLE_TRAITS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <concepts> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 27 | ||
| 28 | // [readable.traits] | |
| 29 | template<class> struct __cond_value_type {}; | |
| 30 | ||
| 31 | template<class _Tp> | |
| 32 | requires is_object_v<_Tp> | |
| 33 | struct __cond_value_type<_Tp> { using value_type = remove_cv_t<_Tp>; }; | |
| 34 | ||
| 35 | template<class _Tp> | |
| 36 | concept __has_member_value_type = requires { typename _Tp::value_type; }; | |
| 37 | ||
| 38 | template<class _Tp> | |
| 39 | concept __has_member_element_type = requires { typename _Tp::element_type; }; | |
| 40 | ||
| 41 | template<class> struct indirectly_readable_traits {}; | |
| 42 | ||
| 43 | template<class _Ip> | |
| 44 | requires is_array_v<_Ip> | |
| 45 | struct indirectly_readable_traits<_Ip> { | |
| 46 | using value_type = remove_cv_t<remove_extent_t<_Ip>>; | |
| 47 | }; | |
| 48 | ||
| 49 | template<class _Ip> | |
| 50 | struct indirectly_readable_traits<const _Ip> : indirectly_readable_traits<_Ip> {}; | |
| 51 | ||
| 52 | template<class _Tp> | |
| 53 | struct indirectly_readable_traits<_Tp*> : __cond_value_type<_Tp> {}; | |
| 54 | ||
| 55 | template<__has_member_value_type _Tp> | |
| 56 | struct indirectly_readable_traits<_Tp> | |
| 57 | : __cond_value_type<typename _Tp::value_type> {}; | |
| 58 | ||
| 59 | template<__has_member_element_type _Tp> | |
| 60 | struct indirectly_readable_traits<_Tp> | |
| 61 | : __cond_value_type<typename _Tp::element_type> {}; | |
| 62 | ||
| 63 | // Pre-emptively applies LWG3541 | |
| 64 | template<__has_member_value_type _Tp> | |
| 65 | requires __has_member_element_type<_Tp> | |
| 66 | struct indirectly_readable_traits<_Tp> {}; | |
| 67 | template<__has_member_value_type _Tp> | |
| 68 | requires __has_member_element_type<_Tp> && | |
| 69 | same_as<remove_cv_t<typename _Tp::element_type>, | |
| 70 | remove_cv_t<typename _Tp::value_type>> | |
| 71 | struct indirectly_readable_traits<_Tp> | |
| 72 | : __cond_value_type<typename _Tp::value_type> {}; | |
| 73 | ||
| 74 | template <class> | |
| 75 | struct iterator_traits; | |
| 76 | ||
| 77 | // Let `RI` be `remove_cvref_t<I>`. The type `iter_value_t<I>` denotes | |
| 78 | // `indirectly_readable_traits<RI>::value_type` if `iterator_traits<RI>` names a specialization | |
| 79 | // generated from the primary template, and `iterator_traits<RI>::value_type` otherwise. | |
| 80 | template <class _Ip> | |
| 81 | using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value, | |
| 82 | indirectly_readable_traits<remove_cvref_t<_Ip> >, | |
| 83 | iterator_traits<remove_cvref_t<_Ip> > >::value_type; | |
| 84 | ||
| 85 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 86 | ||
| 87 | _LIBCPP_END_NAMESPACE_STD | |
| 88 | ||
| 89 | _LIBCPP_POP_MACROS | |
| 90 | ||
| 91 | #endif // _LIBCPP___ITERATOR_READABLE_TRAITS_H |
lib/libcxx/include/__iterator/reverse_access.h created+109| ... | ... | @@ -0,0 +1,109 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_REVERSE_ACCESS_H | |
| 11 | #define _LIBCPP___ITERATOR_REVERSE_ACCESS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/reverse_iterator.h> | |
| 15 | #include <cstddef> | |
| 16 | #include <initializer_list> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 28 | ||
| 29 | #if _LIBCPP_STD_VER > 11 | |
| 30 | ||
| 31 | template <class _Tp, size_t _Np> | |
| 32 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 33 | reverse_iterator<_Tp*> rbegin(_Tp (&__array)[_Np]) | |
| 34 | { | |
| 35 | return reverse_iterator<_Tp*>(__array + _Np); | |
| 36 | } | |
| 37 | ||
| 38 | template <class _Tp, size_t _Np> | |
| 39 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 40 | reverse_iterator<_Tp*> rend(_Tp (&__array)[_Np]) | |
| 41 | { | |
| 42 | return reverse_iterator<_Tp*>(__array); | |
| 43 | } | |
| 44 | ||
| 45 | template <class _Ep> | |
| 46 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 47 | reverse_iterator<const _Ep*> rbegin(initializer_list<_Ep> __il) | |
| 48 | { | |
| 49 | return reverse_iterator<const _Ep*>(__il.end()); | |
| 50 | } | |
| 51 | ||
| 52 | template <class _Ep> | |
| 53 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 54 | reverse_iterator<const _Ep*> rend(initializer_list<_Ep> __il) | |
| 55 | { | |
| 56 | return reverse_iterator<const _Ep*>(__il.begin()); | |
| 57 | } | |
| 58 | ||
| 59 | template <class _Cp> | |
| 60 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 61 | auto rbegin(_Cp& __c) -> decltype(__c.rbegin()) | |
| 62 | { | |
| 63 | return __c.rbegin(); | |
| 64 | } | |
| 65 | ||
| 66 | template <class _Cp> | |
| 67 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 68 | auto rbegin(const _Cp& __c) -> decltype(__c.rbegin()) | |
| 69 | { | |
| 70 | return __c.rbegin(); | |
| 71 | } | |
| 72 | ||
| 73 | template <class _Cp> | |
| 74 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 75 | auto rend(_Cp& __c) -> decltype(__c.rend()) | |
| 76 | { | |
| 77 | return __c.rend(); | |
| 78 | } | |
| 79 | ||
| 80 | template <class _Cp> | |
| 81 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 82 | auto rend(const _Cp& __c) -> decltype(__c.rend()) | |
| 83 | { | |
| 84 | return __c.rend(); | |
| 85 | } | |
| 86 | ||
| 87 | template <class _Cp> | |
| 88 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 89 | auto crbegin(const _Cp& __c) -> decltype(_VSTD::rbegin(__c)) | |
| 90 | { | |
| 91 | return _VSTD::rbegin(__c); | |
| 92 | } | |
| 93 | ||
| 94 | template <class _Cp> | |
| 95 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 96 | auto crend(const _Cp& __c) -> decltype(_VSTD::rend(__c)) | |
| 97 | { | |
| 98 | return _VSTD::rend(__c); | |
| 99 | } | |
| 100 | ||
| 101 | #endif | |
| 102 | ||
| 103 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 104 | ||
| 105 | _LIBCPP_END_NAMESPACE_STD | |
| 106 | ||
| 107 | _LIBCPP_POP_MACROS | |
| 108 | ||
| 109 | #endif // _LIBCPP___ITERATOR_REVERSE_ACCESS_H |
lib/libcxx/include/__iterator/reverse_iterator.h created+239| ... | ... | @@ -0,0 +1,239 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_REVERSE_ITERATOR_H | |
| 11 | #define _LIBCPP___ITERATOR_REVERSE_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__iterator/iterator.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/addressof.h> | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _Tp, class = void> | |
| 29 | struct __is_stashing_iterator : false_type {}; | |
| 30 | ||
| 31 | template <class _Tp> | |
| 32 | struct __is_stashing_iterator<_Tp, typename __void_t<typename _Tp::__stashing_iterator_tag>::type> | |
| 33 | : true_type {}; | |
| 34 | ||
| 35 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 36 | template <class _Iter> | |
| 37 | class _LIBCPP_TEMPLATE_VIS reverse_iterator | |
| 38 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 39 | : public iterator<typename iterator_traits<_Iter>::iterator_category, | |
| 40 | typename iterator_traits<_Iter>::value_type, | |
| 41 | typename iterator_traits<_Iter>::difference_type, | |
| 42 | typename iterator_traits<_Iter>::pointer, | |
| 43 | typename iterator_traits<_Iter>::reference> | |
| 44 | #endif | |
| 45 | { | |
| 46 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 47 | private: | |
| 48 | #ifndef _LIBCPP_ABI_NO_ITERATOR_BASES | |
| 49 | _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break | |
| 50 | #endif | |
| 51 | ||
| 52 | static_assert(!__is_stashing_iterator<_Iter>::value, | |
| 53 | "The specified iterator type cannot be used with reverse_iterator; " | |
| 54 | "Using stashing iterators with reverse_iterator causes undefined behavior"); | |
| 55 | ||
| 56 | protected: | |
| 57 | _Iter current; | |
| 58 | public: | |
| 59 | typedef _Iter iterator_type; | |
| 60 | typedef typename iterator_traits<_Iter>::difference_type difference_type; | |
| 61 | typedef typename iterator_traits<_Iter>::reference reference; | |
| 62 | typedef typename iterator_traits<_Iter>::pointer pointer; | |
| 63 | typedef _If<__is_cpp17_random_access_iterator<_Iter>::value, | |
| 64 | random_access_iterator_tag, | |
| 65 | typename iterator_traits<_Iter>::iterator_category> iterator_category; | |
| 66 | typedef typename iterator_traits<_Iter>::value_type value_type; | |
| 67 | ||
| 68 | #if _LIBCPP_STD_VER > 17 | |
| 69 | typedef _If<__is_cpp17_random_access_iterator<_Iter>::value, | |
| 70 | random_access_iterator_tag, | |
| 71 | bidirectional_iterator_tag> iterator_concept; | |
| 72 | #endif | |
| 73 | ||
| 74 | #ifndef _LIBCPP_ABI_NO_ITERATOR_BASES | |
| 75 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 76 | reverse_iterator() : __t(), current() {} | |
| 77 | ||
| 78 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 79 | explicit reverse_iterator(_Iter __x) : __t(__x), current(__x) {} | |
| 80 | ||
| 81 | template <class _Up, class = _EnableIf< | |
| 82 | !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value | |
| 83 | > > | |
| 84 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 85 | reverse_iterator(const reverse_iterator<_Up>& __u) | |
| 86 | : __t(__u.base()), current(__u.base()) | |
| 87 | { } | |
| 88 | ||
| 89 | template <class _Up, class = _EnableIf< | |
| 90 | !is_same<_Up, _Iter>::value && | |
| 91 | is_convertible<_Up const&, _Iter>::value && | |
| 92 | is_assignable<_Up const&, _Iter>::value | |
| 93 | > > | |
| 94 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 95 | reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { | |
| 96 | __t = current = __u.base(); | |
| 97 | return *this; | |
| 98 | } | |
| 99 | #else | |
| 100 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 101 | reverse_iterator() : current() {} | |
| 102 | ||
| 103 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 104 | explicit reverse_iterator(_Iter __x) : current(__x) {} | |
| 105 | ||
| 106 | template <class _Up, class = _EnableIf< | |
| 107 | !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value | |
| 108 | > > | |
| 109 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 110 | reverse_iterator(const reverse_iterator<_Up>& __u) | |
| 111 | : current(__u.base()) | |
| 112 | { } | |
| 113 | ||
| 114 | template <class _Up, class = _EnableIf< | |
| 115 | !is_same<_Up, _Iter>::value && | |
| 116 | is_convertible<_Up const&, _Iter>::value && | |
| 117 | is_assignable<_Up const&, _Iter>::value | |
| 118 | > > | |
| 119 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 120 | reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { | |
| 121 | current = __u.base(); | |
| 122 | return *this; | |
| 123 | } | |
| 124 | #endif | |
| 125 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 126 | _Iter base() const {return current;} | |
| 127 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 128 | reference operator*() const {_Iter __tmp = current; return *--__tmp;} | |
| 129 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 130 | pointer operator->() const {return _VSTD::addressof(operator*());} | |
| 131 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 132 | reverse_iterator& operator++() {--current; return *this;} | |
| 133 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 134 | reverse_iterator operator++(int) {reverse_iterator __tmp(*this); --current; return __tmp;} | |
| 135 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 136 | reverse_iterator& operator--() {++current; return *this;} | |
| 137 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 138 | reverse_iterator operator--(int) {reverse_iterator __tmp(*this); ++current; return __tmp;} | |
| 139 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 140 | reverse_iterator operator+ (difference_type __n) const {return reverse_iterator(current - __n);} | |
| 141 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 142 | reverse_iterator& operator+=(difference_type __n) {current -= __n; return *this;} | |
| 143 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 144 | reverse_iterator operator- (difference_type __n) const {return reverse_iterator(current + __n);} | |
| 145 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 146 | reverse_iterator& operator-=(difference_type __n) {current += __n; return *this;} | |
| 147 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 148 | reference operator[](difference_type __n) const {return *(*this + __n);} | |
| 149 | }; | |
| 150 | ||
| 151 | template <class _Iter1, class _Iter2> | |
| 152 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 153 | bool | |
| 154 | operator==(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 155 | { | |
| 156 | return __x.base() == __y.base(); | |
| 157 | } | |
| 158 | ||
| 159 | template <class _Iter1, class _Iter2> | |
| 160 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 161 | bool | |
| 162 | operator<(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 163 | { | |
| 164 | return __x.base() > __y.base(); | |
| 165 | } | |
| 166 | ||
| 167 | template <class _Iter1, class _Iter2> | |
| 168 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 169 | bool | |
| 170 | operator!=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 171 | { | |
| 172 | return __x.base() != __y.base(); | |
| 173 | } | |
| 174 | ||
| 175 | template <class _Iter1, class _Iter2> | |
| 176 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 177 | bool | |
| 178 | operator>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 179 | { | |
| 180 | return __x.base() < __y.base(); | |
| 181 | } | |
| 182 | ||
| 183 | template <class _Iter1, class _Iter2> | |
| 184 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 185 | bool | |
| 186 | operator>=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 187 | { | |
| 188 | return __x.base() <= __y.base(); | |
| 189 | } | |
| 190 | ||
| 191 | template <class _Iter1, class _Iter2> | |
| 192 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 193 | bool | |
| 194 | operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 195 | { | |
| 196 | return __x.base() >= __y.base(); | |
| 197 | } | |
| 198 | ||
| 199 | #ifndef _LIBCPP_CXX03_LANG | |
| 200 | template <class _Iter1, class _Iter2> | |
| 201 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 202 | auto | |
| 203 | operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 204 | -> decltype(__y.base() - __x.base()) | |
| 205 | { | |
| 206 | return __y.base() - __x.base(); | |
| 207 | } | |
| 208 | #else | |
| 209 | template <class _Iter1, class _Iter2> | |
| 210 | inline _LIBCPP_INLINE_VISIBILITY | |
| 211 | typename reverse_iterator<_Iter1>::difference_type | |
| 212 | operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 213 | { | |
| 214 | return __y.base() - __x.base(); | |
| 215 | } | |
| 216 | #endif | |
| 217 | ||
| 218 | template <class _Iter> | |
| 219 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 220 | reverse_iterator<_Iter> | |
| 221 | operator+(typename reverse_iterator<_Iter>::difference_type __n, const reverse_iterator<_Iter>& __x) | |
| 222 | { | |
| 223 | return reverse_iterator<_Iter>(__x.base() - __n); | |
| 224 | } | |
| 225 | ||
| 226 | #if _LIBCPP_STD_VER > 11 | |
| 227 | template <class _Iter> | |
| 228 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 229 | reverse_iterator<_Iter> make_reverse_iterator(_Iter __i) | |
| 230 | { | |
| 231 | return reverse_iterator<_Iter>(__i); | |
| 232 | } | |
| 233 | #endif | |
| 234 | ||
| 235 | _LIBCPP_END_NAMESPACE_STD | |
| 236 | ||
| 237 | _LIBCPP_POP_MACROS | |
| 238 | ||
| 239 | #endif // _LIBCPP___ITERATOR_REVERSE_ITERATOR_H |
lib/libcxx/include/__iterator/size.h created+58| ... | ... | @@ -0,0 +1,58 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_SIZE_H | |
| 11 | #define _LIBCPP___ITERATOR_SIZE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if _LIBCPP_STD_VER > 14 | |
| 27 | ||
| 28 | template <class _Cont> | |
| 29 | _LIBCPP_INLINE_VISIBILITY | |
| 30 | constexpr auto size(const _Cont& __c) | |
| 31 | _NOEXCEPT_(noexcept(__c.size())) | |
| 32 | -> decltype (__c.size()) | |
| 33 | { return __c.size(); } | |
| 34 | ||
| 35 | template <class _Tp, size_t _Sz> | |
| 36 | _LIBCPP_INLINE_VISIBILITY | |
| 37 | constexpr size_t size(const _Tp (&)[_Sz]) noexcept { return _Sz; } | |
| 38 | ||
| 39 | #if _LIBCPP_STD_VER > 17 | |
| 40 | template <class _Cont> | |
| 41 | _LIBCPP_INLINE_VISIBILITY | |
| 42 | constexpr auto ssize(const _Cont& __c) | |
| 43 | _NOEXCEPT_(noexcept(static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(__c.size())>>>(__c.size()))) | |
| 44 | -> common_type_t<ptrdiff_t, make_signed_t<decltype(__c.size())>> | |
| 45 | { return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(__c.size())>>>(__c.size()); } | |
| 46 | ||
| 47 | template <class _Tp, ptrdiff_t _Sz> | |
| 48 | _LIBCPP_INLINE_VISIBILITY | |
| 49 | constexpr ptrdiff_t ssize(const _Tp (&)[_Sz]) noexcept { return _Sz; } | |
| 50 | #endif | |
| 51 | ||
| 52 | #endif // _LIBCPP_STD_VER > 14 | |
| 53 | ||
| 54 | _LIBCPP_END_NAMESPACE_STD | |
| 55 | ||
| 56 | _LIBCPP_POP_MACROS | |
| 57 | ||
| 58 | #endif // _LIBCPP___ITERATOR_SIZE_H |
lib/libcxx/include/__iterator/wrap_iter.h created+300| ... | ... | @@ -0,0 +1,300 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___ITERATOR_WRAP_ITER_H | |
| 11 | #define _LIBCPP___ITERATOR_WRAP_ITER_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__debug> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/pointer_traits.h> // __to_address | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _Iter> | |
| 29 | class __wrap_iter | |
| 30 | { | |
| 31 | public: | |
| 32 | typedef _Iter iterator_type; | |
| 33 | typedef typename iterator_traits<iterator_type>::value_type value_type; | |
| 34 | typedef typename iterator_traits<iterator_type>::difference_type difference_type; | |
| 35 | typedef typename iterator_traits<iterator_type>::pointer pointer; | |
| 36 | typedef typename iterator_traits<iterator_type>::reference reference; | |
| 37 | typedef typename iterator_traits<iterator_type>::iterator_category iterator_category; | |
| 38 | #if _LIBCPP_STD_VER > 17 | |
| 39 | typedef contiguous_iterator_tag iterator_concept; | |
| 40 | #endif | |
| 41 | ||
| 42 | private: | |
| 43 | iterator_type __i; | |
| 44 | public: | |
| 45 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter() _NOEXCEPT | |
| 46 | #if _LIBCPP_STD_VER > 11 | |
| 47 | : __i{} | |
| 48 | #endif | |
| 49 | { | |
| 50 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 51 | __get_db()->__insert_i(this); | |
| 52 | #endif | |
| 53 | } | |
| 54 | template <class _Up> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 55 | __wrap_iter(const __wrap_iter<_Up>& __u, | |
| 56 | typename enable_if<is_convertible<_Up, iterator_type>::value>::type* = nullptr) _NOEXCEPT | |
| 57 | : __i(__u.base()) | |
| 58 | { | |
| 59 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 60 | __get_db()->__iterator_copy(this, &__u); | |
| 61 | #endif | |
| 62 | } | |
| 63 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 64 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 65 | __wrap_iter(const __wrap_iter& __x) | |
| 66 | : __i(__x.base()) | |
| 67 | { | |
| 68 | __get_db()->__iterator_copy(this, &__x); | |
| 69 | } | |
| 70 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 71 | __wrap_iter& operator=(const __wrap_iter& __x) | |
| 72 | { | |
| 73 | if (this != &__x) | |
| 74 | { | |
| 75 | __get_db()->__iterator_copy(this, &__x); | |
| 76 | __i = __x.__i; | |
| 77 | } | |
| 78 | return *this; | |
| 79 | } | |
| 80 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 81 | ~__wrap_iter() | |
| 82 | { | |
| 83 | __get_db()->__erase_i(this); | |
| 84 | } | |
| 85 | #endif | |
| 86 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator*() const _NOEXCEPT | |
| 87 | { | |
| 88 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 89 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), | |
| 90 | "Attempted to dereference a non-dereferenceable iterator"); | |
| 91 | #endif | |
| 92 | return *__i; | |
| 93 | } | |
| 94 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG pointer operator->() const _NOEXCEPT | |
| 95 | { | |
| 96 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 97 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), | |
| 98 | "Attempted to dereference a non-dereferenceable iterator"); | |
| 99 | #endif | |
| 100 | return _VSTD::__to_address(__i); | |
| 101 | } | |
| 102 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator++() _NOEXCEPT | |
| 103 | { | |
| 104 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 105 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), | |
| 106 | "Attempted to increment a non-incrementable iterator"); | |
| 107 | #endif | |
| 108 | ++__i; | |
| 109 | return *this; | |
| 110 | } | |
| 111 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator++(int) _NOEXCEPT | |
| 112 | {__wrap_iter __tmp(*this); ++(*this); return __tmp;} | |
| 113 | ||
| 114 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator--() _NOEXCEPT | |
| 115 | { | |
| 116 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 117 | _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), | |
| 118 | "Attempted to decrement a non-decrementable iterator"); | |
| 119 | #endif | |
| 120 | --__i; | |
| 121 | return *this; | |
| 122 | } | |
| 123 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator--(int) _NOEXCEPT | |
| 124 | {__wrap_iter __tmp(*this); --(*this); return __tmp;} | |
| 125 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator+ (difference_type __n) const _NOEXCEPT | |
| 126 | {__wrap_iter __w(*this); __w += __n; return __w;} | |
| 127 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator+=(difference_type __n) _NOEXCEPT | |
| 128 | { | |
| 129 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 130 | _LIBCPP_ASSERT(__get_const_db()->__addable(this, __n), | |
| 131 | "Attempted to add/subtract an iterator outside its valid range"); | |
| 132 | #endif | |
| 133 | __i += __n; | |
| 134 | return *this; | |
| 135 | } | |
| 136 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator- (difference_type __n) const _NOEXCEPT | |
| 137 | {return *this + (-__n);} | |
| 138 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator-=(difference_type __n) _NOEXCEPT | |
| 139 | {*this += -__n; return *this;} | |
| 140 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator[](difference_type __n) const _NOEXCEPT | |
| 141 | { | |
| 142 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 143 | _LIBCPP_ASSERT(__get_const_db()->__subscriptable(this, __n), | |
| 144 | "Attempted to subscript an iterator outside its valid range"); | |
| 145 | #endif | |
| 146 | return __i[__n]; | |
| 147 | } | |
| 148 | ||
| 149 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG iterator_type base() const _NOEXCEPT {return __i;} | |
| 150 | ||
| 151 | private: | |
| 152 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 153 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(const void* __p, iterator_type __x) : __i(__x) | |
| 154 | { | |
| 155 | __get_db()->__insert_ic(this, __p); | |
| 156 | } | |
| 157 | #else | |
| 158 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(iterator_type __x) _NOEXCEPT : __i(__x) {} | |
| 159 | #endif | |
| 160 | ||
| 161 | template <class _Up> friend class __wrap_iter; | |
| 162 | template <class _CharT, class _Traits, class _Alloc> friend class basic_string; | |
| 163 | template <class _Tp, class _Alloc> friend class _LIBCPP_TEMPLATE_VIS vector; | |
| 164 | template <class _Tp, size_t> friend class _LIBCPP_TEMPLATE_VIS span; | |
| 165 | }; | |
| 166 | ||
| 167 | template <class _Iter1> | |
| 168 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 169 | bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 170 | { | |
| 171 | return __x.base() == __y.base(); | |
| 172 | } | |
| 173 | ||
| 174 | template <class _Iter1, class _Iter2> | |
| 175 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 176 | bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 177 | { | |
| 178 | return __x.base() == __y.base(); | |
| 179 | } | |
| 180 | ||
| 181 | template <class _Iter1> | |
| 182 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 183 | bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 184 | { | |
| 185 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 186 | _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), | |
| 187 | "Attempted to compare incomparable iterators"); | |
| 188 | #endif | |
| 189 | return __x.base() < __y.base(); | |
| 190 | } | |
| 191 | ||
| 192 | template <class _Iter1, class _Iter2> | |
| 193 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 194 | bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 195 | { | |
| 196 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 197 | _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), | |
| 198 | "Attempted to compare incomparable iterators"); | |
| 199 | #endif | |
| 200 | return __x.base() < __y.base(); | |
| 201 | } | |
| 202 | ||
| 203 | template <class _Iter1> | |
| 204 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 205 | bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 206 | { | |
| 207 | return !(__x == __y); | |
| 208 | } | |
| 209 | ||
| 210 | template <class _Iter1, class _Iter2> | |
| 211 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 212 | bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 213 | { | |
| 214 | return !(__x == __y); | |
| 215 | } | |
| 216 | ||
| 217 | template <class _Iter1> | |
| 218 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 219 | bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 220 | { | |
| 221 | return __y < __x; | |
| 222 | } | |
| 223 | ||
| 224 | template <class _Iter1, class _Iter2> | |
| 225 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 226 | bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 227 | { | |
| 228 | return __y < __x; | |
| 229 | } | |
| 230 | ||
| 231 | template <class _Iter1> | |
| 232 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 233 | bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 234 | { | |
| 235 | return !(__x < __y); | |
| 236 | } | |
| 237 | ||
| 238 | template <class _Iter1, class _Iter2> | |
| 239 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 240 | bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 241 | { | |
| 242 | return !(__x < __y); | |
| 243 | } | |
| 244 | ||
| 245 | template <class _Iter1> | |
| 246 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 247 | bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 248 | { | |
| 249 | return !(__y < __x); | |
| 250 | } | |
| 251 | ||
| 252 | template <class _Iter1, class _Iter2> | |
| 253 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 254 | bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 255 | { | |
| 256 | return !(__y < __x); | |
| 257 | } | |
| 258 | ||
| 259 | template <class _Iter1, class _Iter2> | |
| 260 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 261 | #ifndef _LIBCPP_CXX03_LANG | |
| 262 | auto operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 263 | -> decltype(__x.base() - __y.base()) | |
| 264 | #else | |
| 265 | typename __wrap_iter<_Iter1>::difference_type | |
| 266 | operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 267 | #endif // C++03 | |
| 268 | { | |
| 269 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 270 | _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), | |
| 271 | "Attempted to subtract incompatible iterators"); | |
| 272 | #endif | |
| 273 | return __x.base() - __y.base(); | |
| 274 | } | |
| 275 | ||
| 276 | template <class _Iter1> | |
| 277 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 278 | __wrap_iter<_Iter1> operator+(typename __wrap_iter<_Iter1>::difference_type __n, __wrap_iter<_Iter1> __x) _NOEXCEPT | |
| 279 | { | |
| 280 | __x += __n; | |
| 281 | return __x; | |
| 282 | } | |
| 283 | ||
| 284 | #if _LIBCPP_STD_VER <= 17 | |
| 285 | template <class _It> | |
| 286 | struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {}; | |
| 287 | #endif | |
| 288 | ||
| 289 | template <class _Iter> | |
| 290 | _LIBCPP_CONSTEXPR | |
| 291 | decltype(_VSTD::__to_address(declval<_Iter>())) | |
| 292 | __to_address(__wrap_iter<_Iter> __w) _NOEXCEPT { | |
| 293 | return _VSTD::__to_address(__w.base()); | |
| 294 | } | |
| 295 | ||
| 296 | _LIBCPP_END_NAMESPACE_STD | |
| 297 | ||
| 298 | _LIBCPP_POP_MACROS | |
| 299 | ||
| 300 | #endif // _LIBCPP___ITERATOR_WRAP_ITER_H |
lib/libcxx/include/__libcpp_version+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | 12000 | |
| 1 | 13000 |
lib/libcxx/include/__locale+13-13| ... | ... | @@ -10,8 +10,8 @@ |
| 10 | 10 | #ifndef _LIBCPP___LOCALE |
| 11 | 11 | #define _LIBCPP___LOCALE |
| 12 | 12 | |
| 13 | #include <__config> | |
| 14 | 13 | #include <__availability> |
| 14 | #include <__config> | |
| 15 | 15 | #include <string> |
| 16 | 16 | #include <memory> |
| 17 | 17 | #include <utility> |
| ... | ... | @@ -1161,7 +1161,7 @@ protected: |
| 1161 | 1161 | virtual int do_max_length() const _NOEXCEPT; |
| 1162 | 1162 | }; |
| 1163 | 1163 | |
| 1164 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1164 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1165 | 1165 | |
| 1166 | 1166 | // template <> class codecvt<char16_t, char8_t, mbstate_t> // C++20 |
| 1167 | 1167 | |
| ... | ... | @@ -1337,7 +1337,7 @@ protected: |
| 1337 | 1337 | virtual int do_max_length() const _NOEXCEPT; |
| 1338 | 1338 | }; |
| 1339 | 1339 | |
| 1340 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1340 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1341 | 1341 | |
| 1342 | 1342 | // template <> class codecvt<char32_t, char8_t, mbstate_t> // C++20 |
| 1343 | 1343 | |
| ... | ... | @@ -1455,7 +1455,7 @@ _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VI |
| 1455 | 1455 | _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>) |
| 1456 | 1456 | _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char, mbstate_t>) // deprecated in C++20 |
| 1457 | 1457 | _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char, mbstate_t>) // deprecated in C++20 |
| 1458 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1458 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1459 | 1459 | _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char8_t, mbstate_t>) // C++20 |
| 1460 | 1460 | _LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char8_t, mbstate_t>) // C++20 |
| 1461 | 1461 | #endif |
| ... | ... | @@ -1484,14 +1484,14 @@ struct __narrow_to_utf8<8> |
| 1484 | 1484 | |
| 1485 | 1485 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 1486 | 1486 | template <> |
| 1487 | struct _LIBCPP_TEMPLATE_VIS __narrow_to_utf8<16> | |
| 1487 | struct _LIBCPP_TYPE_VIS __narrow_to_utf8<16> | |
| 1488 | 1488 | : public codecvt<char16_t, char, mbstate_t> |
| 1489 | 1489 | { |
| 1490 | 1490 | _LIBCPP_INLINE_VISIBILITY |
| 1491 | 1491 | __narrow_to_utf8() : codecvt<char16_t, char, mbstate_t>(1) {} |
| 1492 | 1492 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 1493 | 1493 | |
| 1494 | _LIBCPP_EXPORTED_FROM_ABI ~__narrow_to_utf8(); | |
| 1494 | ~__narrow_to_utf8(); | |
| 1495 | 1495 | |
| 1496 | 1496 | template <class _OutputIterator, class _CharT> |
| 1497 | 1497 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1520,14 +1520,14 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 1520 | 1520 | |
| 1521 | 1521 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 1522 | 1522 | template <> |
| 1523 | struct _LIBCPP_TEMPLATE_VIS __narrow_to_utf8<32> | |
| 1523 | struct _LIBCPP_TYPE_VIS __narrow_to_utf8<32> | |
| 1524 | 1524 | : public codecvt<char32_t, char, mbstate_t> |
| 1525 | 1525 | { |
| 1526 | 1526 | _LIBCPP_INLINE_VISIBILITY |
| 1527 | 1527 | __narrow_to_utf8() : codecvt<char32_t, char, mbstate_t>(1) {} |
| 1528 | 1528 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 1529 | 1529 | |
| 1530 | _LIBCPP_EXPORTED_FROM_ABI ~__narrow_to_utf8(); | |
| 1530 | ~__narrow_to_utf8(); | |
| 1531 | 1531 | |
| 1532 | 1532 | template <class _OutputIterator, class _CharT> |
| 1533 | 1533 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1578,14 +1578,14 @@ struct __widen_from_utf8<8> |
| 1578 | 1578 | |
| 1579 | 1579 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 1580 | 1580 | template <> |
| 1581 | struct _LIBCPP_TEMPLATE_VIS __widen_from_utf8<16> | |
| 1581 | struct _LIBCPP_TYPE_VIS __widen_from_utf8<16> | |
| 1582 | 1582 | : public codecvt<char16_t, char, mbstate_t> |
| 1583 | 1583 | { |
| 1584 | 1584 | _LIBCPP_INLINE_VISIBILITY |
| 1585 | 1585 | __widen_from_utf8() : codecvt<char16_t, char, mbstate_t>(1) {} |
| 1586 | 1586 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 1587 | 1587 | |
| 1588 | _LIBCPP_EXPORTED_FROM_ABI ~__widen_from_utf8(); | |
| 1588 | ~__widen_from_utf8(); | |
| 1589 | 1589 | |
| 1590 | 1590 | template <class _OutputIterator> |
| 1591 | 1591 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1614,14 +1614,14 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 1614 | 1614 | |
| 1615 | 1615 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 1616 | 1616 | template <> |
| 1617 | struct _LIBCPP_TEMPLATE_VIS __widen_from_utf8<32> | |
| 1617 | struct _LIBCPP_TYPE_VIS __widen_from_utf8<32> | |
| 1618 | 1618 | : public codecvt<char32_t, char, mbstate_t> |
| 1619 | 1619 | { |
| 1620 | 1620 | _LIBCPP_INLINE_VISIBILITY |
| 1621 | 1621 | __widen_from_utf8() : codecvt<char32_t, char, mbstate_t>(1) {} |
| 1622 | 1622 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 1623 | 1623 | |
| 1624 | _LIBCPP_EXPORTED_FROM_ABI ~__widen_from_utf8(); | |
| 1624 | ~__widen_from_utf8(); | |
| 1625 | 1625 | |
| 1626 | 1626 | template <class _OutputIterator> |
| 1627 | 1627 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1756,4 +1756,4 @@ private: |
| 1756 | 1756 | |
| 1757 | 1757 | _LIBCPP_END_NAMESPACE_STD |
| 1758 | 1758 | |
| 1759 | #endif // _LIBCPP___LOCALE | |
| 1759 | #endif // _LIBCPP___LOCALE |
lib/libcxx/include/__memory/addressof.h created+96| ... | ... | @@ -0,0 +1,96 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_ADDRESSOF_H | |
| 11 | #define _LIBCPP___MEMORY_ADDRESSOF_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF | |
| 25 | ||
| 26 | template <class _Tp> | |
| 27 | inline _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 28 | _LIBCPP_NO_CFI _LIBCPP_INLINE_VISIBILITY | |
| 29 | _Tp* | |
| 30 | addressof(_Tp& __x) _NOEXCEPT | |
| 31 | { | |
| 32 | return __builtin_addressof(__x); | |
| 33 | } | |
| 34 | ||
| 35 | #else | |
| 36 | ||
| 37 | template <class _Tp> | |
| 38 | inline _LIBCPP_NO_CFI _LIBCPP_INLINE_VISIBILITY | |
| 39 | _Tp* | |
| 40 | addressof(_Tp& __x) _NOEXCEPT | |
| 41 | { | |
| 42 | return reinterpret_cast<_Tp *>( | |
| 43 | const_cast<char *>(&reinterpret_cast<const volatile char &>(__x))); | |
| 44 | } | |
| 45 | ||
| 46 | #endif // _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF | |
| 47 | ||
| 48 | #if defined(_LIBCPP_HAS_OBJC_ARC) && !defined(_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF) | |
| 49 | // Objective-C++ Automatic Reference Counting uses qualified pointers | |
| 50 | // that require special addressof() signatures. When | |
| 51 | // _LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF is defined, the compiler | |
| 52 | // itself is providing these definitions. Otherwise, we provide them. | |
| 53 | template <class _Tp> | |
| 54 | inline _LIBCPP_INLINE_VISIBILITY | |
| 55 | __strong _Tp* | |
| 56 | addressof(__strong _Tp& __x) _NOEXCEPT | |
| 57 | { | |
| 58 | return &__x; | |
| 59 | } | |
| 60 | ||
| 61 | #ifdef _LIBCPP_HAS_OBJC_ARC_WEAK | |
| 62 | template <class _Tp> | |
| 63 | inline _LIBCPP_INLINE_VISIBILITY | |
| 64 | __weak _Tp* | |
| 65 | addressof(__weak _Tp& __x) _NOEXCEPT | |
| 66 | { | |
| 67 | return &__x; | |
| 68 | } | |
| 69 | #endif | |
| 70 | ||
| 71 | template <class _Tp> | |
| 72 | inline _LIBCPP_INLINE_VISIBILITY | |
| 73 | __autoreleasing _Tp* | |
| 74 | addressof(__autoreleasing _Tp& __x) _NOEXCEPT | |
| 75 | { | |
| 76 | return &__x; | |
| 77 | } | |
| 78 | ||
| 79 | template <class _Tp> | |
| 80 | inline _LIBCPP_INLINE_VISIBILITY | |
| 81 | __unsafe_unretained _Tp* | |
| 82 | addressof(__unsafe_unretained _Tp& __x) _NOEXCEPT | |
| 83 | { | |
| 84 | return &__x; | |
| 85 | } | |
| 86 | #endif | |
| 87 | ||
| 88 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 89 | template <class _Tp> _Tp* addressof(const _Tp&&) noexcept = delete; | |
| 90 | #endif | |
| 91 | ||
| 92 | _LIBCPP_END_NAMESPACE_STD | |
| 93 | ||
| 94 | _LIBCPP_POP_MACROS | |
| 95 | ||
| 96 | #endif // _LIBCPP___MEMORY_ADDRESSOF_H |
lib/libcxx/include/__memory/allocation_guard.h created+89| ... | ... | @@ -0,0 +1,89 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_ALLOCATION_GUARD_H | |
| 11 | #define _LIBCPP___MEMORY_ALLOCATION_GUARD_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__memory/allocator_traits.h> | |
| 15 | #include <cstddef> | |
| 16 | #include <utility> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | // Helper class to allocate memory using an Allocator in an exception safe | |
| 29 | // manner. | |
| 30 | // | |
| 31 | // The intended usage of this class is as follows: | |
| 32 | // | |
| 33 | // 0 | |
| 34 | // 1 __allocation_guard<SomeAllocator> guard(alloc, 10); | |
| 35 | // 2 do_some_initialization_that_may_throw(guard.__get()); | |
| 36 | // 3 save_allocated_pointer_in_a_noexcept_operation(guard.__release_ptr()); | |
| 37 | // 4 | |
| 38 | // | |
| 39 | // If line (2) throws an exception during initialization of the memory, the | |
| 40 | // guard's destructor will be called, and the memory will be released using | |
| 41 | // Allocator deallocation. Otherwise, we release the memory from the guard on | |
| 42 | // line (3) in an operation that can't throw -- after that, the guard is not | |
| 43 | // responsible for the memory anymore. | |
| 44 | // | |
| 45 | // This is similar to a unique_ptr, except it's easier to use with a | |
| 46 | // custom allocator. | |
| 47 | template<class _Alloc> | |
| 48 | struct __allocation_guard { | |
| 49 | using _Pointer = typename allocator_traits<_Alloc>::pointer; | |
| 50 | using _Size = typename allocator_traits<_Alloc>::size_type; | |
| 51 | ||
| 52 | template<class _AllocT> // we perform the allocator conversion inside the constructor | |
| 53 | _LIBCPP_HIDE_FROM_ABI | |
| 54 | explicit __allocation_guard(_AllocT __alloc, _Size __n) | |
| 55 | : __alloc_(_VSTD::move(__alloc)) | |
| 56 | , __n_(__n) | |
| 57 | , __ptr_(allocator_traits<_Alloc>::allocate(__alloc_, __n_)) // initialization order is important | |
| 58 | { } | |
| 59 | ||
| 60 | _LIBCPP_HIDE_FROM_ABI | |
| 61 | ~__allocation_guard() _NOEXCEPT { | |
| 62 | if (__ptr_ != nullptr) { | |
| 63 | allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); | |
| 64 | } | |
| 65 | } | |
| 66 | ||
| 67 | _LIBCPP_HIDE_FROM_ABI | |
| 68 | _Pointer __release_ptr() _NOEXCEPT { // not called __release() because it's a keyword in objective-c++ | |
| 69 | _Pointer __tmp = __ptr_; | |
| 70 | __ptr_ = nullptr; | |
| 71 | return __tmp; | |
| 72 | } | |
| 73 | ||
| 74 | _LIBCPP_HIDE_FROM_ABI | |
| 75 | _Pointer __get() const _NOEXCEPT { | |
| 76 | return __ptr_; | |
| 77 | } | |
| 78 | ||
| 79 | private: | |
| 80 | _Alloc __alloc_; | |
| 81 | _Size __n_; | |
| 82 | _Pointer __ptr_; | |
| 83 | }; | |
| 84 | ||
| 85 | _LIBCPP_END_NAMESPACE_STD | |
| 86 | ||
| 87 | _LIBCPP_POP_MACROS | |
| 88 | ||
| 89 | #endif // _LIBCPP___MEMORY_ALLOCATION_GUARD_H |
lib/libcxx/include/__memory/allocator.h created+254| ... | ... | @@ -0,0 +1,254 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_ALLOCATOR_H | |
| 11 | #define _LIBCPP___MEMORY_ALLOCATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__memory/allocator_traits.h> | |
| 15 | #include <__utility/forward.h> | |
| 16 | #include <cstddef> | |
| 17 | #include <new> | |
| 18 | #include <stdexcept> | |
| 19 | #include <type_traits> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | template <class _Tp> class allocator; | |
| 31 | ||
| 32 | #if _LIBCPP_STD_VER <= 17 | |
| 33 | template <> | |
| 34 | class _LIBCPP_TEMPLATE_VIS allocator<void> | |
| 35 | { | |
| 36 | public: | |
| 37 | _LIBCPP_DEPRECATED_IN_CXX17 typedef void* pointer; | |
| 38 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; | |
| 39 | _LIBCPP_DEPRECATED_IN_CXX17 typedef void value_type; | |
| 40 | ||
| 41 | template <class _Up> struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;}; | |
| 42 | }; | |
| 43 | ||
| 44 | template <> | |
| 45 | class _LIBCPP_TEMPLATE_VIS allocator<const void> | |
| 46 | { | |
| 47 | public: | |
| 48 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* pointer; | |
| 49 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; | |
| 50 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const void value_type; | |
| 51 | ||
| 52 | template <class _Up> struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;}; | |
| 53 | }; | |
| 54 | #endif | |
| 55 | ||
| 56 | // This class provides a non-trivial default constructor to the class that derives from it | |
| 57 | // if the condition is satisfied. | |
| 58 | // | |
| 59 | // The second template parameter exists to allow giving a unique type to __non_trivial_if, | |
| 60 | // which makes it possible to avoid breaking the ABI when making this a base class of an | |
| 61 | // existing class. Without that, imagine we have classes D1 and D2, both of which used to | |
| 62 | // have no base classes, but which now derive from __non_trivial_if. The layout of a class | |
| 63 | // that inherits from both D1 and D2 will change because the two __non_trivial_if base | |
| 64 | // classes are not allowed to share the same address. | |
| 65 | // | |
| 66 | // By making those __non_trivial_if base classes unique, we work around this problem and | |
| 67 | // it is safe to start deriving from __non_trivial_if in existing classes. | |
| 68 | template <bool _Cond, class _Unique> | |
| 69 | struct __non_trivial_if { }; | |
| 70 | ||
| 71 | template <class _Unique> | |
| 72 | struct __non_trivial_if<true, _Unique> { | |
| 73 | _LIBCPP_INLINE_VISIBILITY | |
| 74 | _LIBCPP_CONSTEXPR __non_trivial_if() _NOEXCEPT { } | |
| 75 | }; | |
| 76 | ||
| 77 | // allocator | |
| 78 | // | |
| 79 | // Note: For ABI compatibility between C++20 and previous standards, we make | |
| 80 | // allocator<void> trivial in C++20. | |
| 81 | ||
| 82 | template <class _Tp> | |
| 83 | class _LIBCPP_TEMPLATE_VIS allocator | |
| 84 | : private __non_trivial_if<!is_void<_Tp>::value, allocator<_Tp> > | |
| 85 | { | |
| 86 | public: | |
| 87 | typedef size_t size_type; | |
| 88 | typedef ptrdiff_t difference_type; | |
| 89 | typedef _Tp value_type; | |
| 90 | typedef true_type propagate_on_container_move_assignment; | |
| 91 | typedef true_type is_always_equal; | |
| 92 | ||
| 93 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 94 | allocator() _NOEXCEPT _LIBCPP_DEFAULT | |
| 95 | ||
| 96 | template <class _Up> | |
| 97 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 98 | allocator(const allocator<_Up>&) _NOEXCEPT { } | |
| 99 | ||
| 100 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 101 | _Tp* allocate(size_t __n) { | |
| 102 | if (__n > allocator_traits<allocator>::max_size(*this)) | |
| 103 | __throw_length_error("allocator<T>::allocate(size_t n)" | |
| 104 | " 'n' exceeds maximum supported size"); | |
| 105 | if (__libcpp_is_constant_evaluated()) { | |
| 106 | return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); | |
| 107 | } else { | |
| 108 | return static_cast<_Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); | |
| 109 | } | |
| 110 | } | |
| 111 | ||
| 112 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 113 | void deallocate(_Tp* __p, size_t __n) _NOEXCEPT { | |
| 114 | if (__libcpp_is_constant_evaluated()) { | |
| 115 | ::operator delete(__p); | |
| 116 | } else { | |
| 117 | _VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); | |
| 118 | } | |
| 119 | } | |
| 120 | ||
| 121 | // C++20 Removed members | |
| 122 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) | |
| 123 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp* pointer; | |
| 124 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; | |
| 125 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp& reference; | |
| 126 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& const_reference; | |
| 127 | ||
| 128 | template <class _Up> | |
| 129 | struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { | |
| 130 | typedef allocator<_Up> other; | |
| 131 | }; | |
| 132 | ||
| 133 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 134 | pointer address(reference __x) const _NOEXCEPT { | |
| 135 | return _VSTD::addressof(__x); | |
| 136 | } | |
| 137 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 138 | const_pointer address(const_reference __x) const _NOEXCEPT { | |
| 139 | return _VSTD::addressof(__x); | |
| 140 | } | |
| 141 | ||
| 142 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_IN_CXX17 | |
| 143 | _Tp* allocate(size_t __n, const void*) { | |
| 144 | return allocate(__n); | |
| 145 | } | |
| 146 | ||
| 147 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT { | |
| 148 | return size_type(~0) / sizeof(_Tp); | |
| 149 | } | |
| 150 | ||
| 151 | template <class _Up, class... _Args> | |
| 152 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 153 | void construct(_Up* __p, _Args&&... __args) { | |
| 154 | ::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); | |
| 155 | } | |
| 156 | ||
| 157 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 158 | void destroy(pointer __p) { | |
| 159 | __p->~_Tp(); | |
| 160 | } | |
| 161 | #endif | |
| 162 | }; | |
| 163 | ||
| 164 | template <class _Tp> | |
| 165 | class _LIBCPP_TEMPLATE_VIS allocator<const _Tp> | |
| 166 | : private __non_trivial_if<!is_void<_Tp>::value, allocator<const _Tp> > | |
| 167 | { | |
| 168 | public: | |
| 169 | typedef size_t size_type; | |
| 170 | typedef ptrdiff_t difference_type; | |
| 171 | typedef const _Tp value_type; | |
| 172 | typedef true_type propagate_on_container_move_assignment; | |
| 173 | typedef true_type is_always_equal; | |
| 174 | ||
| 175 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 176 | allocator() _NOEXCEPT _LIBCPP_DEFAULT | |
| 177 | ||
| 178 | template <class _Up> | |
| 179 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 180 | allocator(const allocator<_Up>&) _NOEXCEPT { } | |
| 181 | ||
| 182 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 183 | const _Tp* allocate(size_t __n) { | |
| 184 | if (__n > allocator_traits<allocator>::max_size(*this)) | |
| 185 | __throw_length_error("allocator<const T>::allocate(size_t n)" | |
| 186 | " 'n' exceeds maximum supported size"); | |
| 187 | if (__libcpp_is_constant_evaluated()) { | |
| 188 | return static_cast<const _Tp*>(::operator new(__n * sizeof(_Tp))); | |
| 189 | } else { | |
| 190 | return static_cast<const _Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); | |
| 191 | } | |
| 192 | } | |
| 193 | ||
| 194 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 195 | void deallocate(const _Tp* __p, size_t __n) { | |
| 196 | if (__libcpp_is_constant_evaluated()) { | |
| 197 | ::operator delete(const_cast<_Tp*>(__p)); | |
| 198 | } else { | |
| 199 | _VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); | |
| 200 | } | |
| 201 | } | |
| 202 | ||
| 203 | // C++20 Removed members | |
| 204 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) | |
| 205 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* pointer; | |
| 206 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; | |
| 207 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& reference; | |
| 208 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& const_reference; | |
| 209 | ||
| 210 | template <class _Up> | |
| 211 | struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { | |
| 212 | typedef allocator<_Up> other; | |
| 213 | }; | |
| 214 | ||
| 215 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 216 | const_pointer address(const_reference __x) const _NOEXCEPT { | |
| 217 | return _VSTD::addressof(__x); | |
| 218 | } | |
| 219 | ||
| 220 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_IN_CXX17 | |
| 221 | const _Tp* allocate(size_t __n, const void*) { | |
| 222 | return allocate(__n); | |
| 223 | } | |
| 224 | ||
| 225 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT { | |
| 226 | return size_type(~0) / sizeof(_Tp); | |
| 227 | } | |
| 228 | ||
| 229 | template <class _Up, class... _Args> | |
| 230 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 231 | void construct(_Up* __p, _Args&&... __args) { | |
| 232 | ::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); | |
| 233 | } | |
| 234 | ||
| 235 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 236 | void destroy(pointer __p) { | |
| 237 | __p->~_Tp(); | |
| 238 | } | |
| 239 | #endif | |
| 240 | }; | |
| 241 | ||
| 242 | template <class _Tp, class _Up> | |
| 243 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 244 | bool operator==(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return true;} | |
| 245 | ||
| 246 | template <class _Tp, class _Up> | |
| 247 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 248 | bool operator!=(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return false;} | |
| 249 | ||
| 250 | _LIBCPP_END_NAMESPACE_STD | |
| 251 | ||
| 252 | _LIBCPP_POP_MACROS | |
| 253 | ||
| 254 | #endif // _LIBCPP___MEMORY_ALLOCATOR_H |
lib/libcxx/include/__memory/allocator_arg_t.h created+78| ... | ... | @@ -0,0 +1,78 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___FUNCTIONAL___ALLOCATOR_ARG_T_H | |
| 11 | #define _LIBCPP___FUNCTIONAL___ALLOCATOR_ARG_T_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__memory/uses_allocator.h> | |
| 15 | #include <__utility/forward.h> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { explicit allocator_arg_t() = default; }; | |
| 25 | ||
| 26 | #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 27 | extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg; | |
| 28 | #else | |
| 29 | /* _LIBCPP_INLINE_VAR */ constexpr allocator_arg_t allocator_arg = allocator_arg_t(); | |
| 30 | #endif | |
| 31 | ||
| 32 | #ifndef _LIBCPP_CXX03_LANG | |
| 33 | ||
| 34 | // allocator construction | |
| 35 | ||
| 36 | template <class _Tp, class _Alloc, class ..._Args> | |
| 37 | struct __uses_alloc_ctor_imp | |
| 38 | { | |
| 39 | typedef _LIBCPP_NODEBUG_TYPE typename __uncvref<_Alloc>::type _RawAlloc; | |
| 40 | static const bool __ua = uses_allocator<_Tp, _RawAlloc>::value; | |
| 41 | static const bool __ic = | |
| 42 | is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; | |
| 43 | static const int value = __ua ? 2 - __ic : 0; | |
| 44 | }; | |
| 45 | ||
| 46 | template <class _Tp, class _Alloc, class ..._Args> | |
| 47 | struct __uses_alloc_ctor | |
| 48 | : integral_constant<int, __uses_alloc_ctor_imp<_Tp, _Alloc, _Args...>::value> | |
| 49 | {}; | |
| 50 | ||
| 51 | template <class _Tp, class _Allocator, class... _Args> | |
| 52 | inline _LIBCPP_INLINE_VISIBILITY | |
| 53 | void __user_alloc_construct_impl (integral_constant<int, 0>, _Tp *__storage, const _Allocator &, _Args &&... __args ) | |
| 54 | { | |
| 55 | new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); | |
| 56 | } | |
| 57 | ||
| 58 | // FIXME: This should have a version which takes a non-const alloc. | |
| 59 | template <class _Tp, class _Allocator, class... _Args> | |
| 60 | inline _LIBCPP_INLINE_VISIBILITY | |
| 61 | void __user_alloc_construct_impl (integral_constant<int, 1>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) | |
| 62 | { | |
| 63 | new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); | |
| 64 | } | |
| 65 | ||
| 66 | // FIXME: This should have a version which takes a non-const alloc. | |
| 67 | template <class _Tp, class _Allocator, class... _Args> | |
| 68 | inline _LIBCPP_INLINE_VISIBILITY | |
| 69 | void __user_alloc_construct_impl (integral_constant<int, 2>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) | |
| 70 | { | |
| 71 | new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); | |
| 72 | } | |
| 73 | ||
| 74 | #endif // _LIBCPP_CXX03_LANG | |
| 75 | ||
| 76 | _LIBCPP_END_NAMESPACE_STD | |
| 77 | ||
| 78 | #endif // _LIBCPP___FUNCTIONAL___ALLOCATOR_ARG_T_H |
lib/libcxx/include/__memory/allocator_traits.h+8-4| ... | ... | @@ -11,8 +11,10 @@ |
| 11 | 11 | #define _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <__memory/base.h> | |
| 14 | #include <__memory/construct_at.h> | |
| 15 | 15 | #include <__memory/pointer_traits.h> |
| 16 | #include <__utility/forward.h> | |
| 17 | #include <limits> | |
| 16 | 18 | #include <type_traits> |
| 17 | 19 | |
| 18 | 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -253,7 +255,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits |
| 253 | 255 | struct rebind_traits { |
| 254 | 256 | using other = allocator_traits<typename rebind_alloc<_Tp>::other>; |
| 255 | 257 | }; |
| 256 | #endif // _LIBCPP_CXX03_LANG | |
| 258 | #endif // _LIBCPP_CXX03_LANG | |
| 257 | 259 | |
| 258 | 260 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 |
| 259 | 261 | static pointer allocate(allocator_type& __a, size_type __n) { |
| ... | ... | @@ -360,8 +362,10 @@ struct __rebind_alloc_helper { |
| 360 | 362 | template <class _Tp> |
| 361 | 363 | struct __is_default_allocator : false_type { }; |
| 362 | 364 | |
| 365 | template <class> class allocator; | |
| 366 | ||
| 363 | 367 | template <class _Tp> |
| 364 | struct __is_default_allocator<_VSTD::allocator<_Tp> > : true_type { }; | |
| 368 | struct __is_default_allocator<allocator<_Tp> > : true_type { }; | |
| 365 | 369 | |
| 366 | 370 | // __is_cpp17_move_insertable |
| 367 | 371 | template <class _Alloc, class = void> |
| ... | ... | @@ -398,4 +402,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 398 | 402 | |
| 399 | 403 | _LIBCPP_POP_MACROS |
| 400 | 404 | |
| 401 | #endif // _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H | |
| 405 | #endif // _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H |
lib/libcxx/include/__memory/auto_ptr.h created+86| ... | ... | @@ -0,0 +1,86 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_AUTO_PTR_H | |
| 11 | #define _LIBCPP___MEMORY_AUTO_PTR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__nullptr> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _Tp> | |
| 26 | struct _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr_ref | |
| 27 | { | |
| 28 | _Tp* __ptr_; | |
| 29 | }; | |
| 30 | ||
| 31 | template<class _Tp> | |
| 32 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr | |
| 33 | { | |
| 34 | private: | |
| 35 | _Tp* __ptr_; | |
| 36 | public: | |
| 37 | typedef _Tp element_type; | |
| 38 | ||
| 39 | _LIBCPP_INLINE_VISIBILITY explicit auto_ptr(_Tp* __p = 0) _NOEXCEPT : __ptr_(__p) {} | |
| 40 | _LIBCPP_INLINE_VISIBILITY auto_ptr(auto_ptr& __p) _NOEXCEPT : __ptr_(__p.release()) {} | |
| 41 | template<class _Up> _LIBCPP_INLINE_VISIBILITY auto_ptr(auto_ptr<_Up>& __p) _NOEXCEPT | |
| 42 | : __ptr_(__p.release()) {} | |
| 43 | _LIBCPP_INLINE_VISIBILITY auto_ptr& operator=(auto_ptr& __p) _NOEXCEPT | |
| 44 | {reset(__p.release()); return *this;} | |
| 45 | template<class _Up> _LIBCPP_INLINE_VISIBILITY auto_ptr& operator=(auto_ptr<_Up>& __p) _NOEXCEPT | |
| 46 | {reset(__p.release()); return *this;} | |
| 47 | _LIBCPP_INLINE_VISIBILITY auto_ptr& operator=(auto_ptr_ref<_Tp> __p) _NOEXCEPT | |
| 48 | {reset(__p.__ptr_); return *this;} | |
| 49 | _LIBCPP_INLINE_VISIBILITY ~auto_ptr() _NOEXCEPT {delete __ptr_;} | |
| 50 | ||
| 51 | _LIBCPP_INLINE_VISIBILITY _Tp& operator*() const _NOEXCEPT | |
| 52 | {return *__ptr_;} | |
| 53 | _LIBCPP_INLINE_VISIBILITY _Tp* operator->() const _NOEXCEPT {return __ptr_;} | |
| 54 | _LIBCPP_INLINE_VISIBILITY _Tp* get() const _NOEXCEPT {return __ptr_;} | |
| 55 | _LIBCPP_INLINE_VISIBILITY _Tp* release() _NOEXCEPT | |
| 56 | { | |
| 57 | _Tp* __t = __ptr_; | |
| 58 | __ptr_ = nullptr; | |
| 59 | return __t; | |
| 60 | } | |
| 61 | _LIBCPP_INLINE_VISIBILITY void reset(_Tp* __p = 0) _NOEXCEPT | |
| 62 | { | |
| 63 | if (__ptr_ != __p) | |
| 64 | delete __ptr_; | |
| 65 | __ptr_ = __p; | |
| 66 | } | |
| 67 | ||
| 68 | _LIBCPP_INLINE_VISIBILITY auto_ptr(auto_ptr_ref<_Tp> __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} | |
| 69 | template<class _Up> _LIBCPP_INLINE_VISIBILITY operator auto_ptr_ref<_Up>() _NOEXCEPT | |
| 70 | {auto_ptr_ref<_Up> __t; __t.__ptr_ = release(); return __t;} | |
| 71 | template<class _Up> _LIBCPP_INLINE_VISIBILITY operator auto_ptr<_Up>() _NOEXCEPT | |
| 72 | {return auto_ptr<_Up>(release());} | |
| 73 | }; | |
| 74 | ||
| 75 | template <> | |
| 76 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr<void> | |
| 77 | { | |
| 78 | public: | |
| 79 | typedef void element_type; | |
| 80 | }; | |
| 81 | ||
| 82 | _LIBCPP_END_NAMESPACE_STD | |
| 83 | ||
| 84 | _LIBCPP_POP_MACROS | |
| 85 | ||
| 86 | #endif // _LIBCPP___MEMORY_AUTO_PTR_H |
lib/libcxx/include/__memory/base.h deleted-127| ... | ... | @@ -1,127 +0,0 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_BASE_H | |
| 11 | #define _LIBCPP___MEMORY_BASE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__debug> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | // addressof | |
| 27 | #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF | |
| 28 | ||
| 29 | template <class _Tp> | |
| 30 | inline _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 31 | _LIBCPP_NO_CFI _LIBCPP_INLINE_VISIBILITY | |
| 32 | _Tp* | |
| 33 | addressof(_Tp& __x) _NOEXCEPT | |
| 34 | { | |
| 35 | return __builtin_addressof(__x); | |
| 36 | } | |
| 37 | ||
| 38 | #else | |
| 39 | ||
| 40 | template <class _Tp> | |
| 41 | inline _LIBCPP_NO_CFI _LIBCPP_INLINE_VISIBILITY | |
| 42 | _Tp* | |
| 43 | addressof(_Tp& __x) _NOEXCEPT | |
| 44 | { | |
| 45 | return reinterpret_cast<_Tp *>( | |
| 46 | const_cast<char *>(&reinterpret_cast<const volatile char &>(__x))); | |
| 47 | } | |
| 48 | ||
| 49 | #endif // _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF | |
| 50 | ||
| 51 | #if defined(_LIBCPP_HAS_OBJC_ARC) && !defined(_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF) | |
| 52 | // Objective-C++ Automatic Reference Counting uses qualified pointers | |
| 53 | // that require special addressof() signatures. When | |
| 54 | // _LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF is defined, the compiler | |
| 55 | // itself is providing these definitions. Otherwise, we provide them. | |
| 56 | template <class _Tp> | |
| 57 | inline _LIBCPP_INLINE_VISIBILITY | |
| 58 | __strong _Tp* | |
| 59 | addressof(__strong _Tp& __x) _NOEXCEPT | |
| 60 | { | |
| 61 | return &__x; | |
| 62 | } | |
| 63 | ||
| 64 | #ifdef _LIBCPP_HAS_OBJC_ARC_WEAK | |
| 65 | template <class _Tp> | |
| 66 | inline _LIBCPP_INLINE_VISIBILITY | |
| 67 | __weak _Tp* | |
| 68 | addressof(__weak _Tp& __x) _NOEXCEPT | |
| 69 | { | |
| 70 | return &__x; | |
| 71 | } | |
| 72 | #endif | |
| 73 | ||
| 74 | template <class _Tp> | |
| 75 | inline _LIBCPP_INLINE_VISIBILITY | |
| 76 | __autoreleasing _Tp* | |
| 77 | addressof(__autoreleasing _Tp& __x) _NOEXCEPT | |
| 78 | { | |
| 79 | return &__x; | |
| 80 | } | |
| 81 | ||
| 82 | template <class _Tp> | |
| 83 | inline _LIBCPP_INLINE_VISIBILITY | |
| 84 | __unsafe_unretained _Tp* | |
| 85 | addressof(__unsafe_unretained _Tp& __x) _NOEXCEPT | |
| 86 | { | |
| 87 | return &__x; | |
| 88 | } | |
| 89 | #endif | |
| 90 | ||
| 91 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 92 | template <class _Tp> _Tp* addressof(const _Tp&&) noexcept = delete; | |
| 93 | #endif | |
| 94 | ||
| 95 | // construct_at | |
| 96 | ||
| 97 | #if _LIBCPP_STD_VER > 17 | |
| 98 | ||
| 99 | template<class _Tp, class ..._Args, class = decltype( | |
| 100 | ::new (_VSTD::declval<void*>()) _Tp(_VSTD::declval<_Args>()...) | |
| 101 | )> | |
| 102 | _LIBCPP_INLINE_VISIBILITY | |
| 103 | constexpr _Tp* construct_at(_Tp* __location, _Args&& ...__args) { | |
| 104 | _LIBCPP_ASSERT(__location, "null pointer given to construct_at"); | |
| 105 | return ::new ((void*)__location) _Tp(_VSTD::forward<_Args>(__args)...); | |
| 106 | } | |
| 107 | ||
| 108 | #endif | |
| 109 | ||
| 110 | // destroy_at | |
| 111 | ||
| 112 | #if _LIBCPP_STD_VER > 14 | |
| 113 | ||
| 114 | template <class _Tp> | |
| 115 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 116 | void destroy_at(_Tp* __loc) { | |
| 117 | _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at"); | |
| 118 | __loc->~_Tp(); | |
| 119 | } | |
| 120 | ||
| 121 | #endif | |
| 122 | ||
| 123 | _LIBCPP_END_NAMESPACE_STD | |
| 124 | ||
| 125 | _LIBCPP_POP_MACROS | |
| 126 | ||
| 127 | #endif // _LIBCPP___MEMORY_BASE_H |
lib/libcxx/include/__memory/compressed_pair.h created+201| ... | ... | @@ -0,0 +1,201 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_COMPRESSED_PAIR_H | |
| 11 | #define _LIBCPP___MEMORY_COMPRESSED_PAIR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__utility/forward.h> | |
| 15 | #include <tuple> // needed in c++03 for some constructors | |
| 16 | #include <type_traits> | |
| 17 | #include <utility> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | // Tag used to default initialize one or both of the pair's elements. | |
| 29 | struct __default_init_tag {}; | |
| 30 | struct __value_init_tag {}; | |
| 31 | ||
| 32 | template <class _Tp, int _Idx, | |
| 33 | bool _CanBeEmptyBase = | |
| 34 | is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::value> | |
| 35 | struct __compressed_pair_elem { | |
| 36 | typedef _Tp _ParamT; | |
| 37 | typedef _Tp& reference; | |
| 38 | typedef const _Tp& const_reference; | |
| 39 | ||
| 40 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 41 | __compressed_pair_elem(__default_init_tag) {} | |
| 42 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 43 | __compressed_pair_elem(__value_init_tag) : __value_() {} | |
| 44 | ||
| 45 | template <class _Up, class = typename enable_if< | |
| 46 | !is_same<__compressed_pair_elem, typename decay<_Up>::type>::value | |
| 47 | >::type> | |
| 48 | _LIBCPP_INLINE_VISIBILITY | |
| 49 | _LIBCPP_CONSTEXPR explicit | |
| 50 | __compressed_pair_elem(_Up&& __u) | |
| 51 | : __value_(_VSTD::forward<_Up>(__u)) | |
| 52 | { | |
| 53 | } | |
| 54 | ||
| 55 | ||
| 56 | #ifndef _LIBCPP_CXX03_LANG | |
| 57 | template <class... _Args, size_t... _Indexes> | |
| 58 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 59 | __compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args, | |
| 60 | __tuple_indices<_Indexes...>) | |
| 61 | : __value_(_VSTD::forward<_Args>(_VSTD::get<_Indexes>(__args))...) {} | |
| 62 | #endif | |
| 63 | ||
| 64 | ||
| 65 | _LIBCPP_INLINE_VISIBILITY reference __get() _NOEXCEPT { return __value_; } | |
| 66 | _LIBCPP_INLINE_VISIBILITY | |
| 67 | const_reference __get() const _NOEXCEPT { return __value_; } | |
| 68 | ||
| 69 | private: | |
| 70 | _Tp __value_; | |
| 71 | }; | |
| 72 | ||
| 73 | template <class _Tp, int _Idx> | |
| 74 | struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { | |
| 75 | typedef _Tp _ParamT; | |
| 76 | typedef _Tp& reference; | |
| 77 | typedef const _Tp& const_reference; | |
| 78 | typedef _Tp __value_type; | |
| 79 | ||
| 80 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __compressed_pair_elem() = default; | |
| 81 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 82 | __compressed_pair_elem(__default_init_tag) {} | |
| 83 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 84 | __compressed_pair_elem(__value_init_tag) : __value_type() {} | |
| 85 | ||
| 86 | template <class _Up, class = typename enable_if< | |
| 87 | !is_same<__compressed_pair_elem, typename decay<_Up>::type>::value | |
| 88 | >::type> | |
| 89 | _LIBCPP_INLINE_VISIBILITY | |
| 90 | _LIBCPP_CONSTEXPR explicit | |
| 91 | __compressed_pair_elem(_Up&& __u) | |
| 92 | : __value_type(_VSTD::forward<_Up>(__u)) | |
| 93 | {} | |
| 94 | ||
| 95 | #ifndef _LIBCPP_CXX03_LANG | |
| 96 | template <class... _Args, size_t... _Indexes> | |
| 97 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 98 | __compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args, | |
| 99 | __tuple_indices<_Indexes...>) | |
| 100 | : __value_type(_VSTD::forward<_Args>(_VSTD::get<_Indexes>(__args))...) {} | |
| 101 | #endif | |
| 102 | ||
| 103 | _LIBCPP_INLINE_VISIBILITY reference __get() _NOEXCEPT { return *this; } | |
| 104 | _LIBCPP_INLINE_VISIBILITY | |
| 105 | const_reference __get() const _NOEXCEPT { return *this; } | |
| 106 | }; | |
| 107 | ||
| 108 | template <class _T1, class _T2> | |
| 109 | class __compressed_pair : private __compressed_pair_elem<_T1, 0>, | |
| 110 | private __compressed_pair_elem<_T2, 1> { | |
| 111 | public: | |
| 112 | // NOTE: This static assert should never fire because __compressed_pair | |
| 113 | // is *almost never* used in a scenario where it's possible for T1 == T2. | |
| 114 | // (The exception is std::function where it is possible that the function | |
| 115 | // object and the allocator have the same type). | |
| 116 | static_assert((!is_same<_T1, _T2>::value), | |
| 117 | "__compressed_pair cannot be instantiated when T1 and T2 are the same type; " | |
| 118 | "The current implementation is NOT ABI-compatible with the previous " | |
| 119 | "implementation for this configuration"); | |
| 120 | ||
| 121 | typedef _LIBCPP_NODEBUG_TYPE __compressed_pair_elem<_T1, 0> _Base1; | |
| 122 | typedef _LIBCPP_NODEBUG_TYPE __compressed_pair_elem<_T2, 1> _Base2; | |
| 123 | ||
| 124 | template <bool _Dummy = true, | |
| 125 | class = typename enable_if< | |
| 126 | __dependent_type<is_default_constructible<_T1>, _Dummy>::value && | |
| 127 | __dependent_type<is_default_constructible<_T2>, _Dummy>::value | |
| 128 | >::type | |
| 129 | > | |
| 130 | _LIBCPP_INLINE_VISIBILITY | |
| 131 | _LIBCPP_CONSTEXPR __compressed_pair() : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {} | |
| 132 | ||
| 133 | template <class _U1, class _U2> | |
| 134 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 135 | __compressed_pair(_U1&& __t1, _U2&& __t2) | |
| 136 | : _Base1(_VSTD::forward<_U1>(__t1)), _Base2(_VSTD::forward<_U2>(__t2)) {} | |
| 137 | ||
| 138 | #ifndef _LIBCPP_CXX03_LANG | |
| 139 | template <class... _Args1, class... _Args2> | |
| 140 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 141 | __compressed_pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, | |
| 142 | tuple<_Args2...> __second_args) | |
| 143 | : _Base1(__pc, _VSTD::move(__first_args), | |
| 144 | typename __make_tuple_indices<sizeof...(_Args1)>::type()), | |
| 145 | _Base2(__pc, _VSTD::move(__second_args), | |
| 146 | typename __make_tuple_indices<sizeof...(_Args2)>::type()) {} | |
| 147 | #endif | |
| 148 | ||
| 149 | _LIBCPP_INLINE_VISIBILITY | |
| 150 | typename _Base1::reference first() _NOEXCEPT { | |
| 151 | return static_cast<_Base1&>(*this).__get(); | |
| 152 | } | |
| 153 | ||
| 154 | _LIBCPP_INLINE_VISIBILITY | |
| 155 | typename _Base1::const_reference first() const _NOEXCEPT { | |
| 156 | return static_cast<_Base1 const&>(*this).__get(); | |
| 157 | } | |
| 158 | ||
| 159 | _LIBCPP_INLINE_VISIBILITY | |
| 160 | typename _Base2::reference second() _NOEXCEPT { | |
| 161 | return static_cast<_Base2&>(*this).__get(); | |
| 162 | } | |
| 163 | ||
| 164 | _LIBCPP_INLINE_VISIBILITY | |
| 165 | typename _Base2::const_reference second() const _NOEXCEPT { | |
| 166 | return static_cast<_Base2 const&>(*this).__get(); | |
| 167 | } | |
| 168 | ||
| 169 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 170 | static _Base1* __get_first_base(__compressed_pair* __pair) _NOEXCEPT { | |
| 171 | return static_cast<_Base1*>(__pair); | |
| 172 | } | |
| 173 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 174 | static _Base2* __get_second_base(__compressed_pair* __pair) _NOEXCEPT { | |
| 175 | return static_cast<_Base2*>(__pair); | |
| 176 | } | |
| 177 | ||
| 178 | _LIBCPP_INLINE_VISIBILITY | |
| 179 | void swap(__compressed_pair& __x) | |
| 180 | _NOEXCEPT_(__is_nothrow_swappable<_T1>::value && | |
| 181 | __is_nothrow_swappable<_T2>::value) | |
| 182 | { | |
| 183 | using _VSTD::swap; | |
| 184 | swap(first(), __x.first()); | |
| 185 | swap(second(), __x.second()); | |
| 186 | } | |
| 187 | }; | |
| 188 | ||
| 189 | template <class _T1, class _T2> | |
| 190 | inline _LIBCPP_INLINE_VISIBILITY | |
| 191 | void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) | |
| 192 | _NOEXCEPT_(__is_nothrow_swappable<_T1>::value && | |
| 193 | __is_nothrow_swappable<_T2>::value) { | |
| 194 | __x.swap(__y); | |
| 195 | } | |
| 196 | ||
| 197 | _LIBCPP_END_NAMESPACE_STD | |
| 198 | ||
| 199 | _LIBCPP_POP_MACROS | |
| 200 | ||
| 201 | #endif // _LIBCPP___MEMORY_COMPRESSED_PAIR_H |
lib/libcxx/include/__memory/construct_at.h created+59| ... | ... | @@ -0,0 +1,59 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_CONSTRUCT_AT_H | |
| 11 | #define _LIBCPP___MEMORY_CONSTRUCT_AT_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__debug> | |
| 15 | #include <__utility/forward.h> | |
| 16 | #include <utility> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | // construct_at | |
| 28 | ||
| 29 | #if _LIBCPP_STD_VER > 17 | |
| 30 | ||
| 31 | template<class _Tp, class ..._Args, class = decltype( | |
| 32 | ::new (declval<void*>()) _Tp(declval<_Args>()...) | |
| 33 | )> | |
| 34 | _LIBCPP_INLINE_VISIBILITY | |
| 35 | constexpr _Tp* construct_at(_Tp* __location, _Args&& ...__args) { | |
| 36 | _LIBCPP_ASSERT(__location, "null pointer given to construct_at"); | |
| 37 | return ::new ((void*)__location) _Tp(_VSTD::forward<_Args>(__args)...); | |
| 38 | } | |
| 39 | ||
| 40 | #endif | |
| 41 | ||
| 42 | // destroy_at | |
| 43 | ||
| 44 | #if _LIBCPP_STD_VER > 14 | |
| 45 | ||
| 46 | template <class _Tp> | |
| 47 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 48 | void destroy_at(_Tp* __loc) { | |
| 49 | _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at"); | |
| 50 | __loc->~_Tp(); | |
| 51 | } | |
| 52 | ||
| 53 | #endif | |
| 54 | ||
| 55 | _LIBCPP_END_NAMESPACE_STD | |
| 56 | ||
| 57 | _LIBCPP_POP_MACROS | |
| 58 | ||
| 59 | #endif // _LIBCPP___MEMORY_CONSTRUCT_AT_H |
lib/libcxx/include/__memory/pointer_safety.h created+57| ... | ... | @@ -0,0 +1,57 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_POINTER_SAFETY_H | |
| 11 | #define _LIBCPP___MEMORY_POINTER_SAFETY_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 26 | ||
| 27 | enum class pointer_safety : unsigned char { | |
| 28 | relaxed, | |
| 29 | preferred, | |
| 30 | strict | |
| 31 | }; | |
| 32 | ||
| 33 | inline _LIBCPP_INLINE_VISIBILITY | |
| 34 | pointer_safety get_pointer_safety() _NOEXCEPT { | |
| 35 | return pointer_safety::relaxed; | |
| 36 | } | |
| 37 | ||
| 38 | _LIBCPP_FUNC_VIS void declare_reachable(void* __p); | |
| 39 | _LIBCPP_FUNC_VIS void declare_no_pointers(char* __p, size_t __n); | |
| 40 | _LIBCPP_FUNC_VIS void undeclare_no_pointers(char* __p, size_t __n); | |
| 41 | _LIBCPP_FUNC_VIS void* __undeclare_reachable(void* __p); | |
| 42 | ||
| 43 | template <class _Tp> | |
| 44 | inline _LIBCPP_INLINE_VISIBILITY | |
| 45 | _Tp* | |
| 46 | undeclare_reachable(_Tp* __p) | |
| 47 | { | |
| 48 | return static_cast<_Tp*>(__undeclare_reachable(__p)); | |
| 49 | } | |
| 50 | ||
| 51 | #endif // !C++03 | |
| 52 | ||
| 53 | _LIBCPP_END_NAMESPACE_STD | |
| 54 | ||
| 55 | _LIBCPP_POP_MACROS | |
| 56 | ||
| 57 | #endif // _LIBCPP___MEMORY_POINTER_SAFETY_H |
lib/libcxx/include/__memory/pointer_traits.h+49-2| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | #define _LIBCPP___MEMORY_POINTER_TRAITS_H |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <__memory/addressof.h> | |
| 14 | 15 | #include <type_traits> |
| 15 | 16 | |
| 16 | 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -120,7 +121,7 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits |
| 120 | 121 | #else |
| 121 | 122 | template <class _Up> struct rebind |
| 122 | 123 | {typedef typename __pointer_traits_rebind<pointer, _Up>::type other;}; |
| 123 | #endif // _LIBCPP_CXX03_LANG | |
| 124 | #endif // _LIBCPP_CXX03_LANG | |
| 124 | 125 | |
| 125 | 126 | private: |
| 126 | 127 | struct __nat {}; |
| ... | ... | @@ -162,8 +163,54 @@ struct __rebind_pointer { |
| 162 | 163 | #endif |
| 163 | 164 | }; |
| 164 | 165 | |
| 166 | // to_address | |
| 167 | ||
| 168 | template <class _Pointer, class = void> | |
| 169 | struct __to_address_helper; | |
| 170 | ||
| 171 | template <class _Tp> | |
| 172 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 173 | _Tp* __to_address(_Tp* __p) _NOEXCEPT { | |
| 174 | static_assert(!is_function<_Tp>::value, "_Tp is a function type"); | |
| 175 | return __p; | |
| 176 | } | |
| 177 | ||
| 178 | // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers | |
| 179 | template <class _Pointer, class = _EnableIf<!is_pointer<_Pointer>::value> > | |
| 180 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 181 | typename decay<decltype(__to_address_helper<_Pointer>::__call(declval<const _Pointer&>()))>::type | |
| 182 | __to_address(const _Pointer& __p) _NOEXCEPT { | |
| 183 | return __to_address_helper<_Pointer>::__call(__p); | |
| 184 | } | |
| 185 | ||
| 186 | template <class _Pointer, class> | |
| 187 | struct __to_address_helper { | |
| 188 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 189 | static decltype(_VSTD::__to_address(declval<const _Pointer&>().operator->())) | |
| 190 | __call(const _Pointer&__p) _NOEXCEPT { | |
| 191 | return _VSTD::__to_address(__p.operator->()); | |
| 192 | } | |
| 193 | }; | |
| 194 | ||
| 195 | template <class _Pointer> | |
| 196 | struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(declval<const _Pointer&>()))> { | |
| 197 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 198 | static decltype(pointer_traits<_Pointer>::to_address(declval<const _Pointer&>())) | |
| 199 | __call(const _Pointer&__p) _NOEXCEPT { | |
| 200 | return pointer_traits<_Pointer>::to_address(__p); | |
| 201 | } | |
| 202 | }; | |
| 203 | ||
| 204 | #if _LIBCPP_STD_VER > 17 | |
| 205 | template <class _Pointer> | |
| 206 | inline _LIBCPP_INLINE_VISIBILITY constexpr | |
| 207 | auto to_address(const _Pointer& __p) noexcept { | |
| 208 | return _VSTD::__to_address(__p); | |
| 209 | } | |
| 210 | #endif | |
| 211 | ||
| 165 | 212 | _LIBCPP_END_NAMESPACE_STD |
| 166 | 213 | |
| 167 | 214 | _LIBCPP_POP_MACROS |
| 168 | 215 | |
| 169 | #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H | |
| 216 | #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H |
lib/libcxx/include/__memory/raw_storage_iterator.h created+73| ... | ... | @@ -0,0 +1,73 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_RAW_STORAGE_ITERATOR_H | |
| 11 | #define _LIBCPP___MEMORY_RAW_STORAGE_ITERATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__memory/addressof.h> | |
| 15 | #include <cstddef> | |
| 16 | #include <iterator> | |
| 17 | #include <utility> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR) | |
| 29 | ||
| 30 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 31 | template <class _OutputIterator, class _Tp> | |
| 32 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 raw_storage_iterator | |
| 33 | #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) | |
| 34 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 35 | #endif | |
| 36 | { | |
| 37 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 38 | private: | |
| 39 | _OutputIterator __x_; | |
| 40 | public: | |
| 41 | typedef output_iterator_tag iterator_category; | |
| 42 | typedef void value_type; | |
| 43 | #if _LIBCPP_STD_VER > 17 | |
| 44 | typedef ptrdiff_t difference_type; | |
| 45 | #else | |
| 46 | typedef void difference_type; | |
| 47 | #endif | |
| 48 | typedef void pointer; | |
| 49 | typedef void reference; | |
| 50 | ||
| 51 | _LIBCPP_INLINE_VISIBILITY explicit raw_storage_iterator(_OutputIterator __x) : __x_(__x) {} | |
| 52 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator*() {return *this;} | |
| 53 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(const _Tp& __element) | |
| 54 | {::new ((void*)_VSTD::addressof(*__x_)) _Tp(__element); return *this;} | |
| 55 | #if _LIBCPP_STD_VER >= 14 | |
| 56 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(_Tp&& __element) | |
| 57 | {::new ((void*)_VSTD::addressof(*__x_)) _Tp(_VSTD::move(__element)); return *this;} | |
| 58 | #endif | |
| 59 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator++() {++__x_; return *this;} | |
| 60 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator operator++(int) | |
| 61 | {raw_storage_iterator __t(*this); ++__x_; return __t;} | |
| 62 | #if _LIBCPP_STD_VER >= 14 | |
| 63 | _LIBCPP_INLINE_VISIBILITY _OutputIterator base() const { return __x_; } | |
| 64 | #endif | |
| 65 | }; | |
| 66 | ||
| 67 | #endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR) | |
| 68 | ||
| 69 | _LIBCPP_END_NAMESPACE_STD | |
| 70 | ||
| 71 | _LIBCPP_POP_MACROS | |
| 72 | ||
| 73 | #endif // _LIBCPP___MEMORY_RAW_STORAGE_ITERATOR_H |
lib/libcxx/include/__memory/shared_ptr.h created+1879| ... | ... | @@ -0,0 +1,1879 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_SHARED_PTR_H | |
| 11 | #define _LIBCPP___MEMORY_SHARED_PTR_H | |
| 12 | ||
| 13 | #include <__availability> | |
| 14 | #include <__config> | |
| 15 | #include <__functional_base> | |
| 16 | #include <__functional/binary_function.h> | |
| 17 | #include <__functional/operations.h> | |
| 18 | #include <__functional/reference_wrapper.h> | |
| 19 | #include <__memory/addressof.h> | |
| 20 | #include <__memory/allocation_guard.h> | |
| 21 | #include <__memory/allocator_traits.h> | |
| 22 | #include <__memory/allocator.h> | |
| 23 | #include <__memory/compressed_pair.h> | |
| 24 | #include <__memory/pointer_traits.h> | |
| 25 | #include <__memory/unique_ptr.h> | |
| 26 | #include <__utility/forward.h> | |
| 27 | #include <cstddef> | |
| 28 | #include <cstdlib> // abort | |
| 29 | #include <iosfwd> | |
| 30 | #include <stdexcept> | |
| 31 | #include <typeinfo> | |
| 32 | #include <type_traits> | |
| 33 | #include <utility> | |
| 34 | #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) | |
| 35 | # include <atomic> | |
| 36 | #endif | |
| 37 | ||
| 38 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 39 | # include <__memory/auto_ptr.h> | |
| 40 | #endif | |
| 41 | ||
| 42 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 43 | #pragma GCC system_header | |
| 44 | #endif | |
| 45 | ||
| 46 | _LIBCPP_PUSH_MACROS | |
| 47 | #include <__undef_macros> | |
| 48 | ||
| 49 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 50 | ||
| 51 | template <class _Alloc> | |
| 52 | class __allocator_destructor | |
| 53 | { | |
| 54 | typedef _LIBCPP_NODEBUG_TYPE allocator_traits<_Alloc> __alloc_traits; | |
| 55 | public: | |
| 56 | typedef _LIBCPP_NODEBUG_TYPE typename __alloc_traits::pointer pointer; | |
| 57 | typedef _LIBCPP_NODEBUG_TYPE typename __alloc_traits::size_type size_type; | |
| 58 | private: | |
| 59 | _Alloc& __alloc_; | |
| 60 | size_type __s_; | |
| 61 | public: | |
| 62 | _LIBCPP_INLINE_VISIBILITY __allocator_destructor(_Alloc& __a, size_type __s) | |
| 63 | _NOEXCEPT | |
| 64 | : __alloc_(__a), __s_(__s) {} | |
| 65 | _LIBCPP_INLINE_VISIBILITY | |
| 66 | void operator()(pointer __p) _NOEXCEPT | |
| 67 | {__alloc_traits::deallocate(__alloc_, __p, __s_);} | |
| 68 | }; | |
| 69 | ||
| 70 | // NOTE: Relaxed and acq/rel atomics (for increment and decrement respectively) | |
| 71 | // should be sufficient for thread safety. | |
| 72 | // See https://llvm.org/PR22803 | |
| 73 | #if defined(__clang__) && __has_builtin(__atomic_add_fetch) \ | |
| 74 | && defined(__ATOMIC_RELAXED) \ | |
| 75 | && defined(__ATOMIC_ACQ_REL) | |
| 76 | # define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT | |
| 77 | #elif defined(_LIBCPP_COMPILER_GCC) | |
| 78 | # define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT | |
| 79 | #endif | |
| 80 | ||
| 81 | template <class _ValueType> | |
| 82 | inline _LIBCPP_INLINE_VISIBILITY | |
| 83 | _ValueType __libcpp_relaxed_load(_ValueType const* __value) { | |
| 84 | #if !defined(_LIBCPP_HAS_NO_THREADS) && \ | |
| 85 | defined(__ATOMIC_RELAXED) && \ | |
| 86 | (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) | |
| 87 | return __atomic_load_n(__value, __ATOMIC_RELAXED); | |
| 88 | #else | |
| 89 | return *__value; | |
| 90 | #endif | |
| 91 | } | |
| 92 | ||
| 93 | template <class _ValueType> | |
| 94 | inline _LIBCPP_INLINE_VISIBILITY | |
| 95 | _ValueType __libcpp_acquire_load(_ValueType const* __value) { | |
| 96 | #if !defined(_LIBCPP_HAS_NO_THREADS) && \ | |
| 97 | defined(__ATOMIC_ACQUIRE) && \ | |
| 98 | (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) | |
| 99 | return __atomic_load_n(__value, __ATOMIC_ACQUIRE); | |
| 100 | #else | |
| 101 | return *__value; | |
| 102 | #endif | |
| 103 | } | |
| 104 | ||
| 105 | template <class _Tp> | |
| 106 | inline _LIBCPP_INLINE_VISIBILITY _Tp | |
| 107 | __libcpp_atomic_refcount_increment(_Tp& __t) _NOEXCEPT | |
| 108 | { | |
| 109 | #if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS) | |
| 110 | return __atomic_add_fetch(&__t, 1, __ATOMIC_RELAXED); | |
| 111 | #else | |
| 112 | return __t += 1; | |
| 113 | #endif | |
| 114 | } | |
| 115 | ||
| 116 | template <class _Tp> | |
| 117 | inline _LIBCPP_INLINE_VISIBILITY _Tp | |
| 118 | __libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT | |
| 119 | { | |
| 120 | #if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS) | |
| 121 | return __atomic_add_fetch(&__t, -1, __ATOMIC_ACQ_REL); | |
| 122 | #else | |
| 123 | return __t -= 1; | |
| 124 | #endif | |
| 125 | } | |
| 126 | ||
| 127 | class _LIBCPP_EXCEPTION_ABI bad_weak_ptr | |
| 128 | : public std::exception | |
| 129 | { | |
| 130 | public: | |
| 131 | bad_weak_ptr() _NOEXCEPT = default; | |
| 132 | bad_weak_ptr(const bad_weak_ptr&) _NOEXCEPT = default; | |
| 133 | virtual ~bad_weak_ptr() _NOEXCEPT; | |
| 134 | virtual const char* what() const _NOEXCEPT; | |
| 135 | }; | |
| 136 | ||
| 137 | _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY | |
| 138 | void __throw_bad_weak_ptr() | |
| 139 | { | |
| 140 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 141 | throw bad_weak_ptr(); | |
| 142 | #else | |
| 143 | _VSTD::abort(); | |
| 144 | #endif | |
| 145 | } | |
| 146 | ||
| 147 | template<class _Tp> class _LIBCPP_TEMPLATE_VIS weak_ptr; | |
| 148 | ||
| 149 | class _LIBCPP_TYPE_VIS __shared_count | |
| 150 | { | |
| 151 | __shared_count(const __shared_count&); | |
| 152 | __shared_count& operator=(const __shared_count&); | |
| 153 | ||
| 154 | protected: | |
| 155 | long __shared_owners_; | |
| 156 | virtual ~__shared_count(); | |
| 157 | private: | |
| 158 | virtual void __on_zero_shared() _NOEXCEPT = 0; | |
| 159 | ||
| 160 | public: | |
| 161 | _LIBCPP_INLINE_VISIBILITY | |
| 162 | explicit __shared_count(long __refs = 0) _NOEXCEPT | |
| 163 | : __shared_owners_(__refs) {} | |
| 164 | ||
| 165 | #if defined(_LIBCPP_BUILDING_LIBRARY) && \ | |
| 166 | defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) | |
| 167 | void __add_shared() _NOEXCEPT; | |
| 168 | bool __release_shared() _NOEXCEPT; | |
| 169 | #else | |
| 170 | _LIBCPP_INLINE_VISIBILITY | |
| 171 | void __add_shared() _NOEXCEPT { | |
| 172 | __libcpp_atomic_refcount_increment(__shared_owners_); | |
| 173 | } | |
| 174 | _LIBCPP_INLINE_VISIBILITY | |
| 175 | bool __release_shared() _NOEXCEPT { | |
| 176 | if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) { | |
| 177 | __on_zero_shared(); | |
| 178 | return true; | |
| 179 | } | |
| 180 | return false; | |
| 181 | } | |
| 182 | #endif | |
| 183 | _LIBCPP_INLINE_VISIBILITY | |
| 184 | long use_count() const _NOEXCEPT { | |
| 185 | return __libcpp_relaxed_load(&__shared_owners_) + 1; | |
| 186 | } | |
| 187 | }; | |
| 188 | ||
| 189 | class _LIBCPP_TYPE_VIS __shared_weak_count | |
| 190 | : private __shared_count | |
| 191 | { | |
| 192 | long __shared_weak_owners_; | |
| 193 | ||
| 194 | public: | |
| 195 | _LIBCPP_INLINE_VISIBILITY | |
| 196 | explicit __shared_weak_count(long __refs = 0) _NOEXCEPT | |
| 197 | : __shared_count(__refs), | |
| 198 | __shared_weak_owners_(__refs) {} | |
| 199 | protected: | |
| 200 | virtual ~__shared_weak_count(); | |
| 201 | ||
| 202 | public: | |
| 203 | #if defined(_LIBCPP_BUILDING_LIBRARY) && \ | |
| 204 | defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) | |
| 205 | void __add_shared() _NOEXCEPT; | |
| 206 | void __add_weak() _NOEXCEPT; | |
| 207 | void __release_shared() _NOEXCEPT; | |
| 208 | #else | |
| 209 | _LIBCPP_INLINE_VISIBILITY | |
| 210 | void __add_shared() _NOEXCEPT { | |
| 211 | __shared_count::__add_shared(); | |
| 212 | } | |
| 213 | _LIBCPP_INLINE_VISIBILITY | |
| 214 | void __add_weak() _NOEXCEPT { | |
| 215 | __libcpp_atomic_refcount_increment(__shared_weak_owners_); | |
| 216 | } | |
| 217 | _LIBCPP_INLINE_VISIBILITY | |
| 218 | void __release_shared() _NOEXCEPT { | |
| 219 | if (__shared_count::__release_shared()) | |
| 220 | __release_weak(); | |
| 221 | } | |
| 222 | #endif | |
| 223 | void __release_weak() _NOEXCEPT; | |
| 224 | _LIBCPP_INLINE_VISIBILITY | |
| 225 | long use_count() const _NOEXCEPT {return __shared_count::use_count();} | |
| 226 | __shared_weak_count* lock() _NOEXCEPT; | |
| 227 | ||
| 228 | virtual const void* __get_deleter(const type_info&) const _NOEXCEPT; | |
| 229 | private: | |
| 230 | virtual void __on_zero_shared_weak() _NOEXCEPT = 0; | |
| 231 | }; | |
| 232 | ||
| 233 | template <class _Tp, class _Dp, class _Alloc> | |
| 234 | class __shared_ptr_pointer | |
| 235 | : public __shared_weak_count | |
| 236 | { | |
| 237 | __compressed_pair<__compressed_pair<_Tp, _Dp>, _Alloc> __data_; | |
| 238 | public: | |
| 239 | _LIBCPP_INLINE_VISIBILITY | |
| 240 | __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a) | |
| 241 | : __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {} | |
| 242 | ||
| 243 | #ifndef _LIBCPP_NO_RTTI | |
| 244 | virtual const void* __get_deleter(const type_info&) const _NOEXCEPT; | |
| 245 | #endif | |
| 246 | ||
| 247 | private: | |
| 248 | virtual void __on_zero_shared() _NOEXCEPT; | |
| 249 | virtual void __on_zero_shared_weak() _NOEXCEPT; | |
| 250 | }; | |
| 251 | ||
| 252 | #ifndef _LIBCPP_NO_RTTI | |
| 253 | ||
| 254 | template <class _Tp, class _Dp, class _Alloc> | |
| 255 | const void* | |
| 256 | __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) const _NOEXCEPT | |
| 257 | { | |
| 258 | return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : nullptr; | |
| 259 | } | |
| 260 | ||
| 261 | #endif // _LIBCPP_NO_RTTI | |
| 262 | ||
| 263 | template <class _Tp, class _Dp, class _Alloc> | |
| 264 | void | |
| 265 | __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared() _NOEXCEPT | |
| 266 | { | |
| 267 | __data_.first().second()(__data_.first().first()); | |
| 268 | __data_.first().second().~_Dp(); | |
| 269 | } | |
| 270 | ||
| 271 | template <class _Tp, class _Dp, class _Alloc> | |
| 272 | void | |
| 273 | __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT | |
| 274 | { | |
| 275 | typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_pointer>::type _Al; | |
| 276 | typedef allocator_traits<_Al> _ATraits; | |
| 277 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; | |
| 278 | ||
| 279 | _Al __a(__data_.second()); | |
| 280 | __data_.second().~_Alloc(); | |
| 281 | __a.deallocate(_PTraits::pointer_to(*this), 1); | |
| 282 | } | |
| 283 | ||
| 284 | template <class _Tp, class _Alloc> | |
| 285 | struct __shared_ptr_emplace | |
| 286 | : __shared_weak_count | |
| 287 | { | |
| 288 | template<class ..._Args> | |
| 289 | _LIBCPP_HIDE_FROM_ABI | |
| 290 | explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...__args) | |
| 291 | : __storage_(_VSTD::move(__a)) | |
| 292 | { | |
| 293 | #if _LIBCPP_STD_VER > 17 | |
| 294 | using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; | |
| 295 | _TpAlloc __tmp(*__get_alloc()); | |
| 296 | allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); | |
| 297 | #else | |
| 298 | ::new ((void*)__get_elem()) _Tp(_VSTD::forward<_Args>(__args)...); | |
| 299 | #endif | |
| 300 | } | |
| 301 | ||
| 302 | _LIBCPP_HIDE_FROM_ABI | |
| 303 | _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); } | |
| 304 | ||
| 305 | _LIBCPP_HIDE_FROM_ABI | |
| 306 | _Tp* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); } | |
| 307 | ||
| 308 | private: | |
| 309 | virtual void __on_zero_shared() _NOEXCEPT { | |
| 310 | #if _LIBCPP_STD_VER > 17 | |
| 311 | using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; | |
| 312 | _TpAlloc __tmp(*__get_alloc()); | |
| 313 | allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); | |
| 314 | #else | |
| 315 | __get_elem()->~_Tp(); | |
| 316 | #endif | |
| 317 | } | |
| 318 | ||
| 319 | virtual void __on_zero_shared_weak() _NOEXCEPT { | |
| 320 | using _ControlBlockAlloc = typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type; | |
| 321 | using _ControlBlockPointer = typename allocator_traits<_ControlBlockAlloc>::pointer; | |
| 322 | _ControlBlockAlloc __tmp(*__get_alloc()); | |
| 323 | __storage_.~_Storage(); | |
| 324 | allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, | |
| 325 | pointer_traits<_ControlBlockPointer>::pointer_to(*this), 1); | |
| 326 | } | |
| 327 | ||
| 328 | // This class implements the control block for non-array shared pointers created | |
| 329 | // through `std::allocate_shared` and `std::make_shared`. | |
| 330 | // | |
| 331 | // In previous versions of the library, we used a compressed pair to store | |
| 332 | // both the _Alloc and the _Tp. This implies using EBO, which is incompatible | |
| 333 | // with Allocator construction for _Tp. To allow implementing P0674 in C++20, | |
| 334 | // we now use a properly aligned char buffer while making sure that we maintain | |
| 335 | // the same layout that we had when we used a compressed pair. | |
| 336 | using _CompressedPair = __compressed_pair<_Alloc, _Tp>; | |
| 337 | struct _ALIGNAS_TYPE(_CompressedPair) _Storage { | |
| 338 | char __blob_[sizeof(_CompressedPair)]; | |
| 339 | ||
| 340 | _LIBCPP_HIDE_FROM_ABI explicit _Storage(_Alloc&& __a) { | |
| 341 | ::new ((void*)__get_alloc()) _Alloc(_VSTD::move(__a)); | |
| 342 | } | |
| 343 | _LIBCPP_HIDE_FROM_ABI ~_Storage() { | |
| 344 | __get_alloc()->~_Alloc(); | |
| 345 | } | |
| 346 | _Alloc* __get_alloc() _NOEXCEPT { | |
| 347 | _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); | |
| 348 | typename _CompressedPair::_Base1* __first = _CompressedPair::__get_first_base(__as_pair); | |
| 349 | _Alloc *__alloc = reinterpret_cast<_Alloc*>(__first); | |
| 350 | return __alloc; | |
| 351 | } | |
| 352 | _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { | |
| 353 | _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); | |
| 354 | typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair); | |
| 355 | _Tp *__elem = reinterpret_cast<_Tp*>(__second); | |
| 356 | return __elem; | |
| 357 | } | |
| 358 | }; | |
| 359 | ||
| 360 | static_assert(_LIBCPP_ALIGNOF(_Storage) == _LIBCPP_ALIGNOF(_CompressedPair), ""); | |
| 361 | static_assert(sizeof(_Storage) == sizeof(_CompressedPair), ""); | |
| 362 | _Storage __storage_; | |
| 363 | }; | |
| 364 | ||
| 365 | struct __shared_ptr_dummy_rebind_allocator_type; | |
| 366 | template <> | |
| 367 | class _LIBCPP_TEMPLATE_VIS allocator<__shared_ptr_dummy_rebind_allocator_type> | |
| 368 | { | |
| 369 | public: | |
| 370 | template <class _Other> | |
| 371 | struct rebind | |
| 372 | { | |
| 373 | typedef allocator<_Other> other; | |
| 374 | }; | |
| 375 | }; | |
| 376 | ||
| 377 | template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; | |
| 378 | ||
| 379 | template<class _Tp, class _Up> | |
| 380 | struct __compatible_with | |
| 381 | #if _LIBCPP_STD_VER > 14 | |
| 382 | : is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {}; | |
| 383 | #else | |
| 384 | : is_convertible<_Tp*, _Up*> {}; | |
| 385 | #endif // _LIBCPP_STD_VER > 14 | |
| 386 | ||
| 387 | template <class _Ptr, class = void> | |
| 388 | struct __is_deletable : false_type { }; | |
| 389 | template <class _Ptr> | |
| 390 | struct __is_deletable<_Ptr, decltype(delete declval<_Ptr>())> : true_type { }; | |
| 391 | ||
| 392 | template <class _Ptr, class = void> | |
| 393 | struct __is_array_deletable : false_type { }; | |
| 394 | template <class _Ptr> | |
| 395 | struct __is_array_deletable<_Ptr, decltype(delete[] declval<_Ptr>())> : true_type { }; | |
| 396 | ||
| 397 | template <class _Dp, class _Pt, | |
| 398 | class = decltype(declval<_Dp>()(declval<_Pt>()))> | |
| 399 | static true_type __well_formed_deleter_test(int); | |
| 400 | ||
| 401 | template <class, class> | |
| 402 | static false_type __well_formed_deleter_test(...); | |
| 403 | ||
| 404 | template <class _Dp, class _Pt> | |
| 405 | struct __well_formed_deleter : decltype(__well_formed_deleter_test<_Dp, _Pt>(0)) {}; | |
| 406 | ||
| 407 | template<class _Dp, class _Tp, class _Yp> | |
| 408 | struct __shared_ptr_deleter_ctor_reqs | |
| 409 | { | |
| 410 | static const bool value = __compatible_with<_Tp, _Yp>::value && | |
| 411 | is_move_constructible<_Dp>::value && | |
| 412 | __well_formed_deleter<_Dp, _Tp*>::value; | |
| 413 | }; | |
| 414 | ||
| 415 | #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) | |
| 416 | # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) | |
| 417 | #else | |
| 418 | # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI | |
| 419 | #endif | |
| 420 | ||
| 421 | template<class _Tp> | |
| 422 | class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr | |
| 423 | { | |
| 424 | public: | |
| 425 | #if _LIBCPP_STD_VER > 14 | |
| 426 | typedef weak_ptr<_Tp> weak_type; | |
| 427 | typedef remove_extent_t<_Tp> element_type; | |
| 428 | #else | |
| 429 | typedef _Tp element_type; | |
| 430 | #endif | |
| 431 | ||
| 432 | private: | |
| 433 | element_type* __ptr_; | |
| 434 | __shared_weak_count* __cntrl_; | |
| 435 | ||
| 436 | struct __nat {int __for_bool_;}; | |
| 437 | public: | |
| 438 | _LIBCPP_INLINE_VISIBILITY | |
| 439 | _LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT; | |
| 440 | _LIBCPP_INLINE_VISIBILITY | |
| 441 | _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT; | |
| 442 | ||
| 443 | template<class _Yp, class = _EnableIf< | |
| 444 | _And< | |
| 445 | __compatible_with<_Yp, _Tp> | |
| 446 | // In C++03 we get errors when trying to do SFINAE with the | |
| 447 | // delete operator, so we always pretend that it's deletable. | |
| 448 | // The same happens on GCC. | |
| 449 | #if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_COMPILER_GCC) | |
| 450 | , _If<is_array<_Tp>::value, __is_array_deletable<_Yp*>, __is_deletable<_Yp*> > | |
| 451 | #endif | |
| 452 | >::value | |
| 453 | > > | |
| 454 | explicit shared_ptr(_Yp* __p) : __ptr_(__p) { | |
| 455 | unique_ptr<_Yp> __hold(__p); | |
| 456 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 457 | typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT > _CntrlBlk; | |
| 458 | __cntrl_ = new _CntrlBlk(__p, __shared_ptr_default_delete<_Tp, _Yp>(), _AllocT()); | |
| 459 | __hold.release(); | |
| 460 | __enable_weak_this(__p, __p); | |
| 461 | } | |
| 462 | ||
| 463 | template<class _Yp, class _Dp> | |
| 464 | shared_ptr(_Yp* __p, _Dp __d, | |
| 465 | typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type = __nat()); | |
| 466 | template<class _Yp, class _Dp, class _Alloc> | |
| 467 | shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, | |
| 468 | typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type = __nat()); | |
| 469 | template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d); | |
| 470 | template <class _Dp, class _Alloc> shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a); | |
| 471 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT; | |
| 472 | _LIBCPP_INLINE_VISIBILITY | |
| 473 | shared_ptr(const shared_ptr& __r) _NOEXCEPT; | |
| 474 | template<class _Yp> | |
| 475 | _LIBCPP_INLINE_VISIBILITY | |
| 476 | shared_ptr(const shared_ptr<_Yp>& __r, | |
| 477 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) | |
| 478 | _NOEXCEPT; | |
| 479 | _LIBCPP_INLINE_VISIBILITY | |
| 480 | shared_ptr(shared_ptr&& __r) _NOEXCEPT; | |
| 481 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r, | |
| 482 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) | |
| 483 | _NOEXCEPT; | |
| 484 | template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r, | |
| 485 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type= __nat()); | |
| 486 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 487 | template<class _Yp> | |
| 488 | shared_ptr(auto_ptr<_Yp>&& __r, | |
| 489 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat()); | |
| 490 | #endif | |
| 491 | template <class _Yp, class _Dp> | |
| 492 | shared_ptr(unique_ptr<_Yp, _Dp>&&, | |
| 493 | typename enable_if | |
| 494 | < | |
| 495 | !is_lvalue_reference<_Dp>::value && | |
| 496 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 497 | __nat | |
| 498 | >::type = __nat()); | |
| 499 | template <class _Yp, class _Dp> | |
| 500 | shared_ptr(unique_ptr<_Yp, _Dp>&&, | |
| 501 | typename enable_if | |
| 502 | < | |
| 503 | is_lvalue_reference<_Dp>::value && | |
| 504 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 505 | __nat | |
| 506 | >::type = __nat()); | |
| 507 | ||
| 508 | ~shared_ptr(); | |
| 509 | ||
| 510 | _LIBCPP_INLINE_VISIBILITY | |
| 511 | shared_ptr& operator=(const shared_ptr& __r) _NOEXCEPT; | |
| 512 | template<class _Yp> | |
| 513 | typename enable_if | |
| 514 | < | |
| 515 | __compatible_with<_Yp, element_type>::value, | |
| 516 | shared_ptr& | |
| 517 | >::type | |
| 518 | _LIBCPP_INLINE_VISIBILITY | |
| 519 | operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT; | |
| 520 | _LIBCPP_INLINE_VISIBILITY | |
| 521 | shared_ptr& operator=(shared_ptr&& __r) _NOEXCEPT; | |
| 522 | template<class _Yp> | |
| 523 | typename enable_if | |
| 524 | < | |
| 525 | __compatible_with<_Yp, element_type>::value, | |
| 526 | shared_ptr& | |
| 527 | >::type | |
| 528 | _LIBCPP_INLINE_VISIBILITY | |
| 529 | operator=(shared_ptr<_Yp>&& __r); | |
| 530 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 531 | template<class _Yp> | |
| 532 | _LIBCPP_INLINE_VISIBILITY | |
| 533 | typename enable_if | |
| 534 | < | |
| 535 | !is_array<_Yp>::value && | |
| 536 | is_convertible<_Yp*, element_type*>::value, | |
| 537 | shared_ptr | |
| 538 | >::type& | |
| 539 | operator=(auto_ptr<_Yp>&& __r); | |
| 540 | #endif | |
| 541 | template <class _Yp, class _Dp> | |
| 542 | typename enable_if | |
| 543 | < | |
| 544 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 545 | shared_ptr& | |
| 546 | >::type | |
| 547 | _LIBCPP_INLINE_VISIBILITY | |
| 548 | operator=(unique_ptr<_Yp, _Dp>&& __r); | |
| 549 | ||
| 550 | _LIBCPP_INLINE_VISIBILITY | |
| 551 | void swap(shared_ptr& __r) _NOEXCEPT; | |
| 552 | _LIBCPP_INLINE_VISIBILITY | |
| 553 | void reset() _NOEXCEPT; | |
| 554 | template<class _Yp> | |
| 555 | typename enable_if | |
| 556 | < | |
| 557 | __compatible_with<_Yp, element_type>::value, | |
| 558 | void | |
| 559 | >::type | |
| 560 | _LIBCPP_INLINE_VISIBILITY | |
| 561 | reset(_Yp* __p); | |
| 562 | template<class _Yp, class _Dp> | |
| 563 | typename enable_if | |
| 564 | < | |
| 565 | __compatible_with<_Yp, element_type>::value, | |
| 566 | void | |
| 567 | >::type | |
| 568 | _LIBCPP_INLINE_VISIBILITY | |
| 569 | reset(_Yp* __p, _Dp __d); | |
| 570 | template<class _Yp, class _Dp, class _Alloc> | |
| 571 | typename enable_if | |
| 572 | < | |
| 573 | __compatible_with<_Yp, element_type>::value, | |
| 574 | void | |
| 575 | >::type | |
| 576 | _LIBCPP_INLINE_VISIBILITY | |
| 577 | reset(_Yp* __p, _Dp __d, _Alloc __a); | |
| 578 | ||
| 579 | _LIBCPP_INLINE_VISIBILITY | |
| 580 | element_type* get() const _NOEXCEPT {return __ptr_;} | |
| 581 | _LIBCPP_INLINE_VISIBILITY | |
| 582 | typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT | |
| 583 | {return *__ptr_;} | |
| 584 | _LIBCPP_INLINE_VISIBILITY | |
| 585 | element_type* operator->() const _NOEXCEPT | |
| 586 | { | |
| 587 | static_assert(!is_array<_Tp>::value, | |
| 588 | "std::shared_ptr<T>::operator-> is only valid when T is not an array type."); | |
| 589 | return __ptr_; | |
| 590 | } | |
| 591 | _LIBCPP_INLINE_VISIBILITY | |
| 592 | long use_count() const _NOEXCEPT {return __cntrl_ ? __cntrl_->use_count() : 0;} | |
| 593 | _LIBCPP_INLINE_VISIBILITY | |
| 594 | bool unique() const _NOEXCEPT {return use_count() == 1;} | |
| 595 | _LIBCPP_INLINE_VISIBILITY | |
| 596 | explicit operator bool() const _NOEXCEPT {return get() != nullptr;} | |
| 597 | template <class _Up> | |
| 598 | _LIBCPP_INLINE_VISIBILITY | |
| 599 | bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT | |
| 600 | {return __cntrl_ < __p.__cntrl_;} | |
| 601 | template <class _Up> | |
| 602 | _LIBCPP_INLINE_VISIBILITY | |
| 603 | bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT | |
| 604 | {return __cntrl_ < __p.__cntrl_;} | |
| 605 | _LIBCPP_INLINE_VISIBILITY | |
| 606 | bool | |
| 607 | __owner_equivalent(const shared_ptr& __p) const | |
| 608 | {return __cntrl_ == __p.__cntrl_;} | |
| 609 | ||
| 610 | #if _LIBCPP_STD_VER > 14 | |
| 611 | typename add_lvalue_reference<element_type>::type | |
| 612 | _LIBCPP_INLINE_VISIBILITY | |
| 613 | operator[](ptrdiff_t __i) const | |
| 614 | { | |
| 615 | static_assert(is_array<_Tp>::value, | |
| 616 | "std::shared_ptr<T>::operator[] is only valid when T is an array type."); | |
| 617 | return __ptr_[__i]; | |
| 618 | } | |
| 619 | #endif | |
| 620 | ||
| 621 | #ifndef _LIBCPP_NO_RTTI | |
| 622 | template <class _Dp> | |
| 623 | _LIBCPP_INLINE_VISIBILITY | |
| 624 | _Dp* __get_deleter() const _NOEXCEPT | |
| 625 | {return static_cast<_Dp*>(__cntrl_ | |
| 626 | ? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp))) | |
| 627 | : nullptr);} | |
| 628 | #endif // _LIBCPP_NO_RTTI | |
| 629 | ||
| 630 | template<class _Yp, class _CntrlBlk> | |
| 631 | static shared_ptr<_Tp> | |
| 632 | __create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl) _NOEXCEPT | |
| 633 | { | |
| 634 | shared_ptr<_Tp> __r; | |
| 635 | __r.__ptr_ = __p; | |
| 636 | __r.__cntrl_ = __cntrl; | |
| 637 | __r.__enable_weak_this(__r.__ptr_, __r.__ptr_); | |
| 638 | return __r; | |
| 639 | } | |
| 640 | ||
| 641 | private: | |
| 642 | template <class _Yp, bool = is_function<_Yp>::value> | |
| 643 | struct __shared_ptr_default_allocator | |
| 644 | { | |
| 645 | typedef allocator<_Yp> type; | |
| 646 | }; | |
| 647 | ||
| 648 | template <class _Yp> | |
| 649 | struct __shared_ptr_default_allocator<_Yp, true> | |
| 650 | { | |
| 651 | typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type; | |
| 652 | }; | |
| 653 | ||
| 654 | template <class _Yp, class _OrigPtr> | |
| 655 | _LIBCPP_INLINE_VISIBILITY | |
| 656 | typename enable_if<is_convertible<_OrigPtr*, | |
| 657 | const enable_shared_from_this<_Yp>* | |
| 658 | >::value, | |
| 659 | void>::type | |
| 660 | __enable_weak_this(const enable_shared_from_this<_Yp>* __e, | |
| 661 | _OrigPtr* __ptr) _NOEXCEPT | |
| 662 | { | |
| 663 | typedef typename remove_cv<_Yp>::type _RawYp; | |
| 664 | if (__e && __e->__weak_this_.expired()) | |
| 665 | { | |
| 666 | __e->__weak_this_ = shared_ptr<_RawYp>(*this, | |
| 667 | const_cast<_RawYp*>(static_cast<const _Yp*>(__ptr))); | |
| 668 | } | |
| 669 | } | |
| 670 | ||
| 671 | _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {} | |
| 672 | ||
| 673 | template <class, class _Yp> | |
| 674 | struct __shared_ptr_default_delete | |
| 675 | : default_delete<_Yp> {}; | |
| 676 | ||
| 677 | template <class _Yp, class _Un, size_t _Sz> | |
| 678 | struct __shared_ptr_default_delete<_Yp[_Sz], _Un> | |
| 679 | : default_delete<_Yp[]> {}; | |
| 680 | ||
| 681 | template <class _Yp, class _Un> | |
| 682 | struct __shared_ptr_default_delete<_Yp[], _Un> | |
| 683 | : default_delete<_Yp[]> {}; | |
| 684 | ||
| 685 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr; | |
| 686 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; | |
| 687 | }; | |
| 688 | ||
| 689 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 690 | template<class _Tp> | |
| 691 | shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>; | |
| 692 | template<class _Tp, class _Dp> | |
| 693 | shared_ptr(unique_ptr<_Tp, _Dp>) -> shared_ptr<_Tp>; | |
| 694 | #endif | |
| 695 | ||
| 696 | template<class _Tp> | |
| 697 | inline | |
| 698 | _LIBCPP_CONSTEXPR | |
| 699 | shared_ptr<_Tp>::shared_ptr() _NOEXCEPT | |
| 700 | : __ptr_(nullptr), | |
| 701 | __cntrl_(nullptr) | |
| 702 | { | |
| 703 | } | |
| 704 | ||
| 705 | template<class _Tp> | |
| 706 | inline | |
| 707 | _LIBCPP_CONSTEXPR | |
| 708 | shared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT | |
| 709 | : __ptr_(nullptr), | |
| 710 | __cntrl_(nullptr) | |
| 711 | { | |
| 712 | } | |
| 713 | ||
| 714 | template<class _Tp> | |
| 715 | template<class _Yp, class _Dp> | |
| 716 | shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, | |
| 717 | typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type) | |
| 718 | : __ptr_(__p) | |
| 719 | { | |
| 720 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 721 | try | |
| 722 | { | |
| 723 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 724 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 725 | typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; | |
| 726 | #ifndef _LIBCPP_CXX03_LANG | |
| 727 | __cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT()); | |
| 728 | #else | |
| 729 | __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); | |
| 730 | #endif // not _LIBCPP_CXX03_LANG | |
| 731 | __enable_weak_this(__p, __p); | |
| 732 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 733 | } | |
| 734 | catch (...) | |
| 735 | { | |
| 736 | __d(__p); | |
| 737 | throw; | |
| 738 | } | |
| 739 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 740 | } | |
| 741 | ||
| 742 | template<class _Tp> | |
| 743 | template<class _Dp> | |
| 744 | shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d) | |
| 745 | : __ptr_(nullptr) | |
| 746 | { | |
| 747 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 748 | try | |
| 749 | { | |
| 750 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 751 | typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; | |
| 752 | typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT > _CntrlBlk; | |
| 753 | #ifndef _LIBCPP_CXX03_LANG | |
| 754 | __cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT()); | |
| 755 | #else | |
| 756 | __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); | |
| 757 | #endif // not _LIBCPP_CXX03_LANG | |
| 758 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 759 | } | |
| 760 | catch (...) | |
| 761 | { | |
| 762 | __d(__p); | |
| 763 | throw; | |
| 764 | } | |
| 765 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 766 | } | |
| 767 | ||
| 768 | template<class _Tp> | |
| 769 | template<class _Yp, class _Dp, class _Alloc> | |
| 770 | shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, | |
| 771 | typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type) | |
| 772 | : __ptr_(__p) | |
| 773 | { | |
| 774 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 775 | try | |
| 776 | { | |
| 777 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 778 | typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk; | |
| 779 | typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; | |
| 780 | typedef __allocator_destructor<_A2> _D2; | |
| 781 | _A2 __a2(__a); | |
| 782 | unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); | |
| 783 | ::new ((void*)_VSTD::addressof(*__hold2.get())) | |
| 784 | #ifndef _LIBCPP_CXX03_LANG | |
| 785 | _CntrlBlk(__p, _VSTD::move(__d), __a); | |
| 786 | #else | |
| 787 | _CntrlBlk(__p, __d, __a); | |
| 788 | #endif // not _LIBCPP_CXX03_LANG | |
| 789 | __cntrl_ = _VSTD::addressof(*__hold2.release()); | |
| 790 | __enable_weak_this(__p, __p); | |
| 791 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 792 | } | |
| 793 | catch (...) | |
| 794 | { | |
| 795 | __d(__p); | |
| 796 | throw; | |
| 797 | } | |
| 798 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 799 | } | |
| 800 | ||
| 801 | template<class _Tp> | |
| 802 | template<class _Dp, class _Alloc> | |
| 803 | shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a) | |
| 804 | : __ptr_(nullptr) | |
| 805 | { | |
| 806 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 807 | try | |
| 808 | { | |
| 809 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 810 | typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk; | |
| 811 | typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; | |
| 812 | typedef __allocator_destructor<_A2> _D2; | |
| 813 | _A2 __a2(__a); | |
| 814 | unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); | |
| 815 | ::new ((void*)_VSTD::addressof(*__hold2.get())) | |
| 816 | #ifndef _LIBCPP_CXX03_LANG | |
| 817 | _CntrlBlk(__p, _VSTD::move(__d), __a); | |
| 818 | #else | |
| 819 | _CntrlBlk(__p, __d, __a); | |
| 820 | #endif // not _LIBCPP_CXX03_LANG | |
| 821 | __cntrl_ = _VSTD::addressof(*__hold2.release()); | |
| 822 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 823 | } | |
| 824 | catch (...) | |
| 825 | { | |
| 826 | __d(__p); | |
| 827 | throw; | |
| 828 | } | |
| 829 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 830 | } | |
| 831 | ||
| 832 | template<class _Tp> | |
| 833 | template<class _Yp> | |
| 834 | inline | |
| 835 | shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, element_type *__p) _NOEXCEPT | |
| 836 | : __ptr_(__p), | |
| 837 | __cntrl_(__r.__cntrl_) | |
| 838 | { | |
| 839 | if (__cntrl_) | |
| 840 | __cntrl_->__add_shared(); | |
| 841 | } | |
| 842 | ||
| 843 | template<class _Tp> | |
| 844 | inline | |
| 845 | shared_ptr<_Tp>::shared_ptr(const shared_ptr& __r) _NOEXCEPT | |
| 846 | : __ptr_(__r.__ptr_), | |
| 847 | __cntrl_(__r.__cntrl_) | |
| 848 | { | |
| 849 | if (__cntrl_) | |
| 850 | __cntrl_->__add_shared(); | |
| 851 | } | |
| 852 | ||
| 853 | template<class _Tp> | |
| 854 | template<class _Yp> | |
| 855 | inline | |
| 856 | shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, | |
| 857 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) | |
| 858 | _NOEXCEPT | |
| 859 | : __ptr_(__r.__ptr_), | |
| 860 | __cntrl_(__r.__cntrl_) | |
| 861 | { | |
| 862 | if (__cntrl_) | |
| 863 | __cntrl_->__add_shared(); | |
| 864 | } | |
| 865 | ||
| 866 | template<class _Tp> | |
| 867 | inline | |
| 868 | shared_ptr<_Tp>::shared_ptr(shared_ptr&& __r) _NOEXCEPT | |
| 869 | : __ptr_(__r.__ptr_), | |
| 870 | __cntrl_(__r.__cntrl_) | |
| 871 | { | |
| 872 | __r.__ptr_ = nullptr; | |
| 873 | __r.__cntrl_ = nullptr; | |
| 874 | } | |
| 875 | ||
| 876 | template<class _Tp> | |
| 877 | template<class _Yp> | |
| 878 | inline | |
| 879 | shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r, | |
| 880 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) | |
| 881 | _NOEXCEPT | |
| 882 | : __ptr_(__r.__ptr_), | |
| 883 | __cntrl_(__r.__cntrl_) | |
| 884 | { | |
| 885 | __r.__ptr_ = nullptr; | |
| 886 | __r.__cntrl_ = nullptr; | |
| 887 | } | |
| 888 | ||
| 889 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 890 | template<class _Tp> | |
| 891 | template<class _Yp> | |
| 892 | shared_ptr<_Tp>::shared_ptr(auto_ptr<_Yp>&& __r, | |
| 893 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type) | |
| 894 | : __ptr_(__r.get()) | |
| 895 | { | |
| 896 | typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk; | |
| 897 | __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<_Yp>()); | |
| 898 | __enable_weak_this(__r.get(), __r.get()); | |
| 899 | __r.release(); | |
| 900 | } | |
| 901 | #endif | |
| 902 | ||
| 903 | template<class _Tp> | |
| 904 | template <class _Yp, class _Dp> | |
| 905 | shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, | |
| 906 | typename enable_if | |
| 907 | < | |
| 908 | !is_lvalue_reference<_Dp>::value && | |
| 909 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 910 | __nat | |
| 911 | >::type) | |
| 912 | : __ptr_(__r.get()) | |
| 913 | { | |
| 914 | #if _LIBCPP_STD_VER > 11 | |
| 915 | if (__ptr_ == nullptr) | |
| 916 | __cntrl_ = nullptr; | |
| 917 | else | |
| 918 | #endif | |
| 919 | { | |
| 920 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 921 | typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT > _CntrlBlk; | |
| 922 | __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); | |
| 923 | __enable_weak_this(__r.get(), __r.get()); | |
| 924 | } | |
| 925 | __r.release(); | |
| 926 | } | |
| 927 | ||
| 928 | template<class _Tp> | |
| 929 | template <class _Yp, class _Dp> | |
| 930 | shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, | |
| 931 | typename enable_if | |
| 932 | < | |
| 933 | is_lvalue_reference<_Dp>::value && | |
| 934 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 935 | __nat | |
| 936 | >::type) | |
| 937 | : __ptr_(__r.get()) | |
| 938 | { | |
| 939 | #if _LIBCPP_STD_VER > 11 | |
| 940 | if (__ptr_ == nullptr) | |
| 941 | __cntrl_ = nullptr; | |
| 942 | else | |
| 943 | #endif | |
| 944 | { | |
| 945 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 946 | typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, | |
| 947 | reference_wrapper<typename remove_reference<_Dp>::type>, | |
| 948 | _AllocT > _CntrlBlk; | |
| 949 | __cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT()); | |
| 950 | __enable_weak_this(__r.get(), __r.get()); | |
| 951 | } | |
| 952 | __r.release(); | |
| 953 | } | |
| 954 | ||
| 955 | template<class _Tp> | |
| 956 | shared_ptr<_Tp>::~shared_ptr() | |
| 957 | { | |
| 958 | if (__cntrl_) | |
| 959 | __cntrl_->__release_shared(); | |
| 960 | } | |
| 961 | ||
| 962 | template<class _Tp> | |
| 963 | inline | |
| 964 | shared_ptr<_Tp>& | |
| 965 | shared_ptr<_Tp>::operator=(const shared_ptr& __r) _NOEXCEPT | |
| 966 | { | |
| 967 | shared_ptr(__r).swap(*this); | |
| 968 | return *this; | |
| 969 | } | |
| 970 | ||
| 971 | template<class _Tp> | |
| 972 | template<class _Yp> | |
| 973 | inline | |
| 974 | typename enable_if | |
| 975 | < | |
| 976 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 977 | shared_ptr<_Tp>& | |
| 978 | >::type | |
| 979 | shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT | |
| 980 | { | |
| 981 | shared_ptr(__r).swap(*this); | |
| 982 | return *this; | |
| 983 | } | |
| 984 | ||
| 985 | template<class _Tp> | |
| 986 | inline | |
| 987 | shared_ptr<_Tp>& | |
| 988 | shared_ptr<_Tp>::operator=(shared_ptr&& __r) _NOEXCEPT | |
| 989 | { | |
| 990 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 991 | return *this; | |
| 992 | } | |
| 993 | ||
| 994 | template<class _Tp> | |
| 995 | template<class _Yp> | |
| 996 | inline | |
| 997 | typename enable_if | |
| 998 | < | |
| 999 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 1000 | shared_ptr<_Tp>& | |
| 1001 | >::type | |
| 1002 | shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r) | |
| 1003 | { | |
| 1004 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 1005 | return *this; | |
| 1006 | } | |
| 1007 | ||
| 1008 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 1009 | template<class _Tp> | |
| 1010 | template<class _Yp> | |
| 1011 | inline | |
| 1012 | typename enable_if | |
| 1013 | < | |
| 1014 | !is_array<_Yp>::value && | |
| 1015 | is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, | |
| 1016 | shared_ptr<_Tp> | |
| 1017 | >::type& | |
| 1018 | shared_ptr<_Tp>::operator=(auto_ptr<_Yp>&& __r) | |
| 1019 | { | |
| 1020 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 1021 | return *this; | |
| 1022 | } | |
| 1023 | #endif | |
| 1024 | ||
| 1025 | template<class _Tp> | |
| 1026 | template <class _Yp, class _Dp> | |
| 1027 | inline | |
| 1028 | typename enable_if | |
| 1029 | < | |
| 1030 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, | |
| 1031 | typename shared_ptr<_Tp>::element_type*>::value, | |
| 1032 | shared_ptr<_Tp>& | |
| 1033 | >::type | |
| 1034 | shared_ptr<_Tp>::operator=(unique_ptr<_Yp, _Dp>&& __r) | |
| 1035 | { | |
| 1036 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 1037 | return *this; | |
| 1038 | } | |
| 1039 | ||
| 1040 | template<class _Tp> | |
| 1041 | inline | |
| 1042 | void | |
| 1043 | shared_ptr<_Tp>::swap(shared_ptr& __r) _NOEXCEPT | |
| 1044 | { | |
| 1045 | _VSTD::swap(__ptr_, __r.__ptr_); | |
| 1046 | _VSTD::swap(__cntrl_, __r.__cntrl_); | |
| 1047 | } | |
| 1048 | ||
| 1049 | template<class _Tp> | |
| 1050 | inline | |
| 1051 | void | |
| 1052 | shared_ptr<_Tp>::reset() _NOEXCEPT | |
| 1053 | { | |
| 1054 | shared_ptr().swap(*this); | |
| 1055 | } | |
| 1056 | ||
| 1057 | template<class _Tp> | |
| 1058 | template<class _Yp> | |
| 1059 | inline | |
| 1060 | typename enable_if | |
| 1061 | < | |
| 1062 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 1063 | void | |
| 1064 | >::type | |
| 1065 | shared_ptr<_Tp>::reset(_Yp* __p) | |
| 1066 | { | |
| 1067 | shared_ptr(__p).swap(*this); | |
| 1068 | } | |
| 1069 | ||
| 1070 | template<class _Tp> | |
| 1071 | template<class _Yp, class _Dp> | |
| 1072 | inline | |
| 1073 | typename enable_if | |
| 1074 | < | |
| 1075 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 1076 | void | |
| 1077 | >::type | |
| 1078 | shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d) | |
| 1079 | { | |
| 1080 | shared_ptr(__p, __d).swap(*this); | |
| 1081 | } | |
| 1082 | ||
| 1083 | template<class _Tp> | |
| 1084 | template<class _Yp, class _Dp, class _Alloc> | |
| 1085 | inline | |
| 1086 | typename enable_if | |
| 1087 | < | |
| 1088 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 1089 | void | |
| 1090 | >::type | |
| 1091 | shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a) | |
| 1092 | { | |
| 1093 | shared_ptr(__p, __d, __a).swap(*this); | |
| 1094 | } | |
| 1095 | ||
| 1096 | // | |
| 1097 | // std::allocate_shared and std::make_shared | |
| 1098 | // | |
| 1099 | template<class _Tp, class _Alloc, class ..._Args, class = _EnableIf<!is_array<_Tp>::value> > | |
| 1100 | _LIBCPP_HIDE_FROM_ABI | |
| 1101 | shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&& ...__args) | |
| 1102 | { | |
| 1103 | using _ControlBlock = __shared_ptr_emplace<_Tp, _Alloc>; | |
| 1104 | using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type; | |
| 1105 | __allocation_guard<_ControlBlockAllocator> __guard(__a, 1); | |
| 1106 | ::new ((void*)_VSTD::addressof(*__guard.__get())) _ControlBlock(__a, _VSTD::forward<_Args>(__args)...); | |
| 1107 | auto __control_block = __guard.__release_ptr(); | |
| 1108 | return shared_ptr<_Tp>::__create_with_control_block((*__control_block).__get_elem(), _VSTD::addressof(*__control_block)); | |
| 1109 | } | |
| 1110 | ||
| 1111 | template<class _Tp, class ..._Args, class = _EnableIf<!is_array<_Tp>::value> > | |
| 1112 | _LIBCPP_HIDE_FROM_ABI | |
| 1113 | shared_ptr<_Tp> make_shared(_Args&& ...__args) | |
| 1114 | { | |
| 1115 | return _VSTD::allocate_shared<_Tp>(allocator<_Tp>(), _VSTD::forward<_Args>(__args)...); | |
| 1116 | } | |
| 1117 | ||
| 1118 | template<class _Tp, class _Up> | |
| 1119 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1120 | bool | |
| 1121 | operator==(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 1122 | { | |
| 1123 | return __x.get() == __y.get(); | |
| 1124 | } | |
| 1125 | ||
| 1126 | template<class _Tp, class _Up> | |
| 1127 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1128 | bool | |
| 1129 | operator!=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 1130 | { | |
| 1131 | return !(__x == __y); | |
| 1132 | } | |
| 1133 | ||
| 1134 | template<class _Tp, class _Up> | |
| 1135 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1136 | bool | |
| 1137 | operator<(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 1138 | { | |
| 1139 | #if _LIBCPP_STD_VER <= 11 | |
| 1140 | typedef typename common_type<_Tp*, _Up*>::type _Vp; | |
| 1141 | return less<_Vp>()(__x.get(), __y.get()); | |
| 1142 | #else | |
| 1143 | return less<>()(__x.get(), __y.get()); | |
| 1144 | #endif | |
| 1145 | ||
| 1146 | } | |
| 1147 | ||
| 1148 | template<class _Tp, class _Up> | |
| 1149 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1150 | bool | |
| 1151 | operator>(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 1152 | { | |
| 1153 | return __y < __x; | |
| 1154 | } | |
| 1155 | ||
| 1156 | template<class _Tp, class _Up> | |
| 1157 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1158 | bool | |
| 1159 | operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 1160 | { | |
| 1161 | return !(__y < __x); | |
| 1162 | } | |
| 1163 | ||
| 1164 | template<class _Tp, class _Up> | |
| 1165 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1166 | bool | |
| 1167 | operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 1168 | { | |
| 1169 | return !(__x < __y); | |
| 1170 | } | |
| 1171 | ||
| 1172 | template<class _Tp> | |
| 1173 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1174 | bool | |
| 1175 | operator==(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 1176 | { | |
| 1177 | return !__x; | |
| 1178 | } | |
| 1179 | ||
| 1180 | template<class _Tp> | |
| 1181 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1182 | bool | |
| 1183 | operator==(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 1184 | { | |
| 1185 | return !__x; | |
| 1186 | } | |
| 1187 | ||
| 1188 | template<class _Tp> | |
| 1189 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1190 | bool | |
| 1191 | operator!=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 1192 | { | |
| 1193 | return static_cast<bool>(__x); | |
| 1194 | } | |
| 1195 | ||
| 1196 | template<class _Tp> | |
| 1197 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1198 | bool | |
| 1199 | operator!=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 1200 | { | |
| 1201 | return static_cast<bool>(__x); | |
| 1202 | } | |
| 1203 | ||
| 1204 | template<class _Tp> | |
| 1205 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1206 | bool | |
| 1207 | operator<(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 1208 | { | |
| 1209 | return less<_Tp*>()(__x.get(), nullptr); | |
| 1210 | } | |
| 1211 | ||
| 1212 | template<class _Tp> | |
| 1213 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1214 | bool | |
| 1215 | operator<(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 1216 | { | |
| 1217 | return less<_Tp*>()(nullptr, __x.get()); | |
| 1218 | } | |
| 1219 | ||
| 1220 | template<class _Tp> | |
| 1221 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1222 | bool | |
| 1223 | operator>(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 1224 | { | |
| 1225 | return nullptr < __x; | |
| 1226 | } | |
| 1227 | ||
| 1228 | template<class _Tp> | |
| 1229 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1230 | bool | |
| 1231 | operator>(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 1232 | { | |
| 1233 | return __x < nullptr; | |
| 1234 | } | |
| 1235 | ||
| 1236 | template<class _Tp> | |
| 1237 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1238 | bool | |
| 1239 | operator<=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 1240 | { | |
| 1241 | return !(nullptr < __x); | |
| 1242 | } | |
| 1243 | ||
| 1244 | template<class _Tp> | |
| 1245 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1246 | bool | |
| 1247 | operator<=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 1248 | { | |
| 1249 | return !(__x < nullptr); | |
| 1250 | } | |
| 1251 | ||
| 1252 | template<class _Tp> | |
| 1253 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1254 | bool | |
| 1255 | operator>=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 1256 | { | |
| 1257 | return !(__x < nullptr); | |
| 1258 | } | |
| 1259 | ||
| 1260 | template<class _Tp> | |
| 1261 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1262 | bool | |
| 1263 | operator>=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 1264 | { | |
| 1265 | return !(nullptr < __x); | |
| 1266 | } | |
| 1267 | ||
| 1268 | template<class _Tp> | |
| 1269 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1270 | void | |
| 1271 | swap(shared_ptr<_Tp>& __x, shared_ptr<_Tp>& __y) _NOEXCEPT | |
| 1272 | { | |
| 1273 | __x.swap(__y); | |
| 1274 | } | |
| 1275 | ||
| 1276 | template<class _Tp, class _Up> | |
| 1277 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1278 | shared_ptr<_Tp> | |
| 1279 | static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 1280 | { | |
| 1281 | return shared_ptr<_Tp>(__r, | |
| 1282 | static_cast< | |
| 1283 | typename shared_ptr<_Tp>::element_type*>(__r.get())); | |
| 1284 | } | |
| 1285 | ||
| 1286 | template<class _Tp, class _Up> | |
| 1287 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1288 | shared_ptr<_Tp> | |
| 1289 | dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 1290 | { | |
| 1291 | typedef typename shared_ptr<_Tp>::element_type _ET; | |
| 1292 | _ET* __p = dynamic_cast<_ET*>(__r.get()); | |
| 1293 | return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>(); | |
| 1294 | } | |
| 1295 | ||
| 1296 | template<class _Tp, class _Up> | |
| 1297 | shared_ptr<_Tp> | |
| 1298 | const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 1299 | { | |
| 1300 | typedef typename shared_ptr<_Tp>::element_type _RTp; | |
| 1301 | return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get())); | |
| 1302 | } | |
| 1303 | ||
| 1304 | template<class _Tp, class _Up> | |
| 1305 | shared_ptr<_Tp> | |
| 1306 | reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 1307 | { | |
| 1308 | return shared_ptr<_Tp>(__r, | |
| 1309 | reinterpret_cast< | |
| 1310 | typename shared_ptr<_Tp>::element_type*>(__r.get())); | |
| 1311 | } | |
| 1312 | ||
| 1313 | #ifndef _LIBCPP_NO_RTTI | |
| 1314 | ||
| 1315 | template<class _Dp, class _Tp> | |
| 1316 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1317 | _Dp* | |
| 1318 | get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT | |
| 1319 | { | |
| 1320 | return __p.template __get_deleter<_Dp>(); | |
| 1321 | } | |
| 1322 | ||
| 1323 | #endif // _LIBCPP_NO_RTTI | |
| 1324 | ||
| 1325 | template<class _Tp> | |
| 1326 | class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr | |
| 1327 | { | |
| 1328 | public: | |
| 1329 | typedef _Tp element_type; | |
| 1330 | private: | |
| 1331 | element_type* __ptr_; | |
| 1332 | __shared_weak_count* __cntrl_; | |
| 1333 | ||
| 1334 | public: | |
| 1335 | _LIBCPP_INLINE_VISIBILITY | |
| 1336 | _LIBCPP_CONSTEXPR weak_ptr() _NOEXCEPT; | |
| 1337 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(shared_ptr<_Yp> const& __r, | |
| 1338 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0) | |
| 1339 | _NOEXCEPT; | |
| 1340 | _LIBCPP_INLINE_VISIBILITY | |
| 1341 | weak_ptr(weak_ptr const& __r) _NOEXCEPT; | |
| 1342 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp> const& __r, | |
| 1343 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0) | |
| 1344 | _NOEXCEPT; | |
| 1345 | ||
| 1346 | _LIBCPP_INLINE_VISIBILITY | |
| 1347 | weak_ptr(weak_ptr&& __r) _NOEXCEPT; | |
| 1348 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp>&& __r, | |
| 1349 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0) | |
| 1350 | _NOEXCEPT; | |
| 1351 | ~weak_ptr(); | |
| 1352 | ||
| 1353 | _LIBCPP_INLINE_VISIBILITY | |
| 1354 | weak_ptr& operator=(weak_ptr const& __r) _NOEXCEPT; | |
| 1355 | template<class _Yp> | |
| 1356 | typename enable_if | |
| 1357 | < | |
| 1358 | is_convertible<_Yp*, element_type*>::value, | |
| 1359 | weak_ptr& | |
| 1360 | >::type | |
| 1361 | _LIBCPP_INLINE_VISIBILITY | |
| 1362 | operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT; | |
| 1363 | ||
| 1364 | _LIBCPP_INLINE_VISIBILITY | |
| 1365 | weak_ptr& operator=(weak_ptr&& __r) _NOEXCEPT; | |
| 1366 | template<class _Yp> | |
| 1367 | typename enable_if | |
| 1368 | < | |
| 1369 | is_convertible<_Yp*, element_type*>::value, | |
| 1370 | weak_ptr& | |
| 1371 | >::type | |
| 1372 | _LIBCPP_INLINE_VISIBILITY | |
| 1373 | operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT; | |
| 1374 | ||
| 1375 | template<class _Yp> | |
| 1376 | typename enable_if | |
| 1377 | < | |
| 1378 | is_convertible<_Yp*, element_type*>::value, | |
| 1379 | weak_ptr& | |
| 1380 | >::type | |
| 1381 | _LIBCPP_INLINE_VISIBILITY | |
| 1382 | operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT; | |
| 1383 | ||
| 1384 | _LIBCPP_INLINE_VISIBILITY | |
| 1385 | void swap(weak_ptr& __r) _NOEXCEPT; | |
| 1386 | _LIBCPP_INLINE_VISIBILITY | |
| 1387 | void reset() _NOEXCEPT; | |
| 1388 | ||
| 1389 | _LIBCPP_INLINE_VISIBILITY | |
| 1390 | long use_count() const _NOEXCEPT | |
| 1391 | {return __cntrl_ ? __cntrl_->use_count() : 0;} | |
| 1392 | _LIBCPP_INLINE_VISIBILITY | |
| 1393 | bool expired() const _NOEXCEPT | |
| 1394 | {return __cntrl_ == nullptr || __cntrl_->use_count() == 0;} | |
| 1395 | shared_ptr<_Tp> lock() const _NOEXCEPT; | |
| 1396 | template<class _Up> | |
| 1397 | _LIBCPP_INLINE_VISIBILITY | |
| 1398 | bool owner_before(const shared_ptr<_Up>& __r) const _NOEXCEPT | |
| 1399 | {return __cntrl_ < __r.__cntrl_;} | |
| 1400 | template<class _Up> | |
| 1401 | _LIBCPP_INLINE_VISIBILITY | |
| 1402 | bool owner_before(const weak_ptr<_Up>& __r) const _NOEXCEPT | |
| 1403 | {return __cntrl_ < __r.__cntrl_;} | |
| 1404 | ||
| 1405 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; | |
| 1406 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr; | |
| 1407 | }; | |
| 1408 | ||
| 1409 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 1410 | template<class _Tp> | |
| 1411 | weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>; | |
| 1412 | #endif | |
| 1413 | ||
| 1414 | template<class _Tp> | |
| 1415 | inline | |
| 1416 | _LIBCPP_CONSTEXPR | |
| 1417 | weak_ptr<_Tp>::weak_ptr() _NOEXCEPT | |
| 1418 | : __ptr_(nullptr), | |
| 1419 | __cntrl_(nullptr) | |
| 1420 | { | |
| 1421 | } | |
| 1422 | ||
| 1423 | template<class _Tp> | |
| 1424 | inline | |
| 1425 | weak_ptr<_Tp>::weak_ptr(weak_ptr const& __r) _NOEXCEPT | |
| 1426 | : __ptr_(__r.__ptr_), | |
| 1427 | __cntrl_(__r.__cntrl_) | |
| 1428 | { | |
| 1429 | if (__cntrl_) | |
| 1430 | __cntrl_->__add_weak(); | |
| 1431 | } | |
| 1432 | ||
| 1433 | template<class _Tp> | |
| 1434 | template<class _Yp> | |
| 1435 | inline | |
| 1436 | weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r, | |
| 1437 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type) | |
| 1438 | _NOEXCEPT | |
| 1439 | : __ptr_(__r.__ptr_), | |
| 1440 | __cntrl_(__r.__cntrl_) | |
| 1441 | { | |
| 1442 | if (__cntrl_) | |
| 1443 | __cntrl_->__add_weak(); | |
| 1444 | } | |
| 1445 | ||
| 1446 | template<class _Tp> | |
| 1447 | template<class _Yp> | |
| 1448 | inline | |
| 1449 | weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp> const& __r, | |
| 1450 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type) | |
| 1451 | _NOEXCEPT | |
| 1452 | : __ptr_(__r.__ptr_), | |
| 1453 | __cntrl_(__r.__cntrl_) | |
| 1454 | { | |
| 1455 | if (__cntrl_) | |
| 1456 | __cntrl_->__add_weak(); | |
| 1457 | } | |
| 1458 | ||
| 1459 | template<class _Tp> | |
| 1460 | inline | |
| 1461 | weak_ptr<_Tp>::weak_ptr(weak_ptr&& __r) _NOEXCEPT | |
| 1462 | : __ptr_(__r.__ptr_), | |
| 1463 | __cntrl_(__r.__cntrl_) | |
| 1464 | { | |
| 1465 | __r.__ptr_ = nullptr; | |
| 1466 | __r.__cntrl_ = nullptr; | |
| 1467 | } | |
| 1468 | ||
| 1469 | template<class _Tp> | |
| 1470 | template<class _Yp> | |
| 1471 | inline | |
| 1472 | weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp>&& __r, | |
| 1473 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type) | |
| 1474 | _NOEXCEPT | |
| 1475 | : __ptr_(__r.__ptr_), | |
| 1476 | __cntrl_(__r.__cntrl_) | |
| 1477 | { | |
| 1478 | __r.__ptr_ = nullptr; | |
| 1479 | __r.__cntrl_ = nullptr; | |
| 1480 | } | |
| 1481 | ||
| 1482 | template<class _Tp> | |
| 1483 | weak_ptr<_Tp>::~weak_ptr() | |
| 1484 | { | |
| 1485 | if (__cntrl_) | |
| 1486 | __cntrl_->__release_weak(); | |
| 1487 | } | |
| 1488 | ||
| 1489 | template<class _Tp> | |
| 1490 | inline | |
| 1491 | weak_ptr<_Tp>& | |
| 1492 | weak_ptr<_Tp>::operator=(weak_ptr const& __r) _NOEXCEPT | |
| 1493 | { | |
| 1494 | weak_ptr(__r).swap(*this); | |
| 1495 | return *this; | |
| 1496 | } | |
| 1497 | ||
| 1498 | template<class _Tp> | |
| 1499 | template<class _Yp> | |
| 1500 | inline | |
| 1501 | typename enable_if | |
| 1502 | < | |
| 1503 | is_convertible<_Yp*, _Tp*>::value, | |
| 1504 | weak_ptr<_Tp>& | |
| 1505 | >::type | |
| 1506 | weak_ptr<_Tp>::operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT | |
| 1507 | { | |
| 1508 | weak_ptr(__r).swap(*this); | |
| 1509 | return *this; | |
| 1510 | } | |
| 1511 | ||
| 1512 | template<class _Tp> | |
| 1513 | inline | |
| 1514 | weak_ptr<_Tp>& | |
| 1515 | weak_ptr<_Tp>::operator=(weak_ptr&& __r) _NOEXCEPT | |
| 1516 | { | |
| 1517 | weak_ptr(_VSTD::move(__r)).swap(*this); | |
| 1518 | return *this; | |
| 1519 | } | |
| 1520 | ||
| 1521 | template<class _Tp> | |
| 1522 | template<class _Yp> | |
| 1523 | inline | |
| 1524 | typename enable_if | |
| 1525 | < | |
| 1526 | is_convertible<_Yp*, _Tp*>::value, | |
| 1527 | weak_ptr<_Tp>& | |
| 1528 | >::type | |
| 1529 | weak_ptr<_Tp>::operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT | |
| 1530 | { | |
| 1531 | weak_ptr(_VSTD::move(__r)).swap(*this); | |
| 1532 | return *this; | |
| 1533 | } | |
| 1534 | ||
| 1535 | template<class _Tp> | |
| 1536 | template<class _Yp> | |
| 1537 | inline | |
| 1538 | typename enable_if | |
| 1539 | < | |
| 1540 | is_convertible<_Yp*, _Tp*>::value, | |
| 1541 | weak_ptr<_Tp>& | |
| 1542 | >::type | |
| 1543 | weak_ptr<_Tp>::operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT | |
| 1544 | { | |
| 1545 | weak_ptr(__r).swap(*this); | |
| 1546 | return *this; | |
| 1547 | } | |
| 1548 | ||
| 1549 | template<class _Tp> | |
| 1550 | inline | |
| 1551 | void | |
| 1552 | weak_ptr<_Tp>::swap(weak_ptr& __r) _NOEXCEPT | |
| 1553 | { | |
| 1554 | _VSTD::swap(__ptr_, __r.__ptr_); | |
| 1555 | _VSTD::swap(__cntrl_, __r.__cntrl_); | |
| 1556 | } | |
| 1557 | ||
| 1558 | template<class _Tp> | |
| 1559 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1560 | void | |
| 1561 | swap(weak_ptr<_Tp>& __x, weak_ptr<_Tp>& __y) _NOEXCEPT | |
| 1562 | { | |
| 1563 | __x.swap(__y); | |
| 1564 | } | |
| 1565 | ||
| 1566 | template<class _Tp> | |
| 1567 | inline | |
| 1568 | void | |
| 1569 | weak_ptr<_Tp>::reset() _NOEXCEPT | |
| 1570 | { | |
| 1571 | weak_ptr().swap(*this); | |
| 1572 | } | |
| 1573 | ||
| 1574 | template<class _Tp> | |
| 1575 | template<class _Yp> | |
| 1576 | shared_ptr<_Tp>::shared_ptr(const weak_ptr<_Yp>& __r, | |
| 1577 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type) | |
| 1578 | : __ptr_(__r.__ptr_), | |
| 1579 | __cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_) | |
| 1580 | { | |
| 1581 | if (__cntrl_ == nullptr) | |
| 1582 | __throw_bad_weak_ptr(); | |
| 1583 | } | |
| 1584 | ||
| 1585 | template<class _Tp> | |
| 1586 | shared_ptr<_Tp> | |
| 1587 | weak_ptr<_Tp>::lock() const _NOEXCEPT | |
| 1588 | { | |
| 1589 | shared_ptr<_Tp> __r; | |
| 1590 | __r.__cntrl_ = __cntrl_ ? __cntrl_->lock() : __cntrl_; | |
| 1591 | if (__r.__cntrl_) | |
| 1592 | __r.__ptr_ = __ptr_; | |
| 1593 | return __r; | |
| 1594 | } | |
| 1595 | ||
| 1596 | #if _LIBCPP_STD_VER > 14 | |
| 1597 | template <class _Tp = void> struct owner_less; | |
| 1598 | #else | |
| 1599 | template <class _Tp> struct owner_less; | |
| 1600 | #endif | |
| 1601 | ||
| 1602 | ||
| 1603 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 1604 | template <class _Tp> | |
| 1605 | struct _LIBCPP_TEMPLATE_VIS owner_less<shared_ptr<_Tp> > | |
| 1606 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 1607 | : binary_function<shared_ptr<_Tp>, shared_ptr<_Tp>, bool> | |
| 1608 | #endif | |
| 1609 | { | |
| 1610 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 1611 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 1612 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 1613 | _LIBCPP_DEPRECATED_IN_CXX17 typedef shared_ptr<_Tp> first_argument_type; | |
| 1614 | _LIBCPP_DEPRECATED_IN_CXX17 typedef shared_ptr<_Tp> second_argument_type; | |
| 1615 | #endif | |
| 1616 | _LIBCPP_INLINE_VISIBILITY | |
| 1617 | bool operator()(shared_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 1618 | {return __x.owner_before(__y);} | |
| 1619 | _LIBCPP_INLINE_VISIBILITY | |
| 1620 | bool operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 1621 | {return __x.owner_before(__y);} | |
| 1622 | _LIBCPP_INLINE_VISIBILITY | |
| 1623 | bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 1624 | {return __x.owner_before(__y);} | |
| 1625 | }; | |
| 1626 | ||
| 1627 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 1628 | template <class _Tp> | |
| 1629 | struct _LIBCPP_TEMPLATE_VIS owner_less<weak_ptr<_Tp> > | |
| 1630 | #if !defined(_LIBCPP_ABI_NO_BINDER_BASES) | |
| 1631 | : binary_function<weak_ptr<_Tp>, weak_ptr<_Tp>, bool> | |
| 1632 | #endif | |
| 1633 | { | |
| 1634 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 1635 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 1636 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 1637 | _LIBCPP_DEPRECATED_IN_CXX17 typedef weak_ptr<_Tp> first_argument_type; | |
| 1638 | _LIBCPP_DEPRECATED_IN_CXX17 typedef weak_ptr<_Tp> second_argument_type; | |
| 1639 | #endif | |
| 1640 | _LIBCPP_INLINE_VISIBILITY | |
| 1641 | bool operator()( weak_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 1642 | {return __x.owner_before(__y);} | |
| 1643 | _LIBCPP_INLINE_VISIBILITY | |
| 1644 | bool operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 1645 | {return __x.owner_before(__y);} | |
| 1646 | _LIBCPP_INLINE_VISIBILITY | |
| 1647 | bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 1648 | {return __x.owner_before(__y);} | |
| 1649 | }; | |
| 1650 | ||
| 1651 | #if _LIBCPP_STD_VER > 14 | |
| 1652 | template <> | |
| 1653 | struct _LIBCPP_TEMPLATE_VIS owner_less<void> | |
| 1654 | { | |
| 1655 | template <class _Tp, class _Up> | |
| 1656 | _LIBCPP_INLINE_VISIBILITY | |
| 1657 | bool operator()( shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const _NOEXCEPT | |
| 1658 | {return __x.owner_before(__y);} | |
| 1659 | template <class _Tp, class _Up> | |
| 1660 | _LIBCPP_INLINE_VISIBILITY | |
| 1661 | bool operator()( shared_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const _NOEXCEPT | |
| 1662 | {return __x.owner_before(__y);} | |
| 1663 | template <class _Tp, class _Up> | |
| 1664 | _LIBCPP_INLINE_VISIBILITY | |
| 1665 | bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const _NOEXCEPT | |
| 1666 | {return __x.owner_before(__y);} | |
| 1667 | template <class _Tp, class _Up> | |
| 1668 | _LIBCPP_INLINE_VISIBILITY | |
| 1669 | bool operator()( weak_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const _NOEXCEPT | |
| 1670 | {return __x.owner_before(__y);} | |
| 1671 | typedef void is_transparent; | |
| 1672 | }; | |
| 1673 | #endif | |
| 1674 | ||
| 1675 | template<class _Tp> | |
| 1676 | class _LIBCPP_TEMPLATE_VIS enable_shared_from_this | |
| 1677 | { | |
| 1678 | mutable weak_ptr<_Tp> __weak_this_; | |
| 1679 | protected: | |
| 1680 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1681 | enable_shared_from_this() _NOEXCEPT {} | |
| 1682 | _LIBCPP_INLINE_VISIBILITY | |
| 1683 | enable_shared_from_this(enable_shared_from_this const&) _NOEXCEPT {} | |
| 1684 | _LIBCPP_INLINE_VISIBILITY | |
| 1685 | enable_shared_from_this& operator=(enable_shared_from_this const&) _NOEXCEPT | |
| 1686 | {return *this;} | |
| 1687 | _LIBCPP_INLINE_VISIBILITY | |
| 1688 | ~enable_shared_from_this() {} | |
| 1689 | public: | |
| 1690 | _LIBCPP_INLINE_VISIBILITY | |
| 1691 | shared_ptr<_Tp> shared_from_this() | |
| 1692 | {return shared_ptr<_Tp>(__weak_this_);} | |
| 1693 | _LIBCPP_INLINE_VISIBILITY | |
| 1694 | shared_ptr<_Tp const> shared_from_this() const | |
| 1695 | {return shared_ptr<const _Tp>(__weak_this_);} | |
| 1696 | ||
| 1697 | #if _LIBCPP_STD_VER > 14 | |
| 1698 | _LIBCPP_INLINE_VISIBILITY | |
| 1699 | weak_ptr<_Tp> weak_from_this() _NOEXCEPT | |
| 1700 | { return __weak_this_; } | |
| 1701 | ||
| 1702 | _LIBCPP_INLINE_VISIBILITY | |
| 1703 | weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT | |
| 1704 | { return __weak_this_; } | |
| 1705 | #endif // _LIBCPP_STD_VER > 14 | |
| 1706 | ||
| 1707 | template <class _Up> friend class shared_ptr; | |
| 1708 | }; | |
| 1709 | ||
| 1710 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS hash; | |
| 1711 | ||
| 1712 | template <class _Tp> | |
| 1713 | struct _LIBCPP_TEMPLATE_VIS hash<shared_ptr<_Tp> > | |
| 1714 | { | |
| 1715 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 1716 | _LIBCPP_DEPRECATED_IN_CXX17 typedef shared_ptr<_Tp> argument_type; | |
| 1717 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 1718 | #endif | |
| 1719 | ||
| 1720 | _LIBCPP_INLINE_VISIBILITY | |
| 1721 | size_t operator()(const shared_ptr<_Tp>& __ptr) const _NOEXCEPT | |
| 1722 | { | |
| 1723 | return hash<typename shared_ptr<_Tp>::element_type*>()(__ptr.get()); | |
| 1724 | } | |
| 1725 | }; | |
| 1726 | ||
| 1727 | template<class _CharT, class _Traits, class _Yp> | |
| 1728 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1729 | basic_ostream<_CharT, _Traits>& | |
| 1730 | operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p); | |
| 1731 | ||
| 1732 | ||
| 1733 | #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) | |
| 1734 | ||
| 1735 | class _LIBCPP_TYPE_VIS __sp_mut | |
| 1736 | { | |
| 1737 | void* __lx; | |
| 1738 | public: | |
| 1739 | void lock() _NOEXCEPT; | |
| 1740 | void unlock() _NOEXCEPT; | |
| 1741 | ||
| 1742 | private: | |
| 1743 | _LIBCPP_CONSTEXPR __sp_mut(void*) _NOEXCEPT; | |
| 1744 | __sp_mut(const __sp_mut&); | |
| 1745 | __sp_mut& operator=(const __sp_mut&); | |
| 1746 | ||
| 1747 | friend _LIBCPP_FUNC_VIS __sp_mut& __get_sp_mut(const void*); | |
| 1748 | }; | |
| 1749 | ||
| 1750 | _LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1751 | __sp_mut& __get_sp_mut(const void*); | |
| 1752 | ||
| 1753 | template <class _Tp> | |
| 1754 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1755 | bool | |
| 1756 | atomic_is_lock_free(const shared_ptr<_Tp>*) | |
| 1757 | { | |
| 1758 | return false; | |
| 1759 | } | |
| 1760 | ||
| 1761 | template <class _Tp> | |
| 1762 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1763 | shared_ptr<_Tp> | |
| 1764 | atomic_load(const shared_ptr<_Tp>* __p) | |
| 1765 | { | |
| 1766 | __sp_mut& __m = __get_sp_mut(__p); | |
| 1767 | __m.lock(); | |
| 1768 | shared_ptr<_Tp> __q = *__p; | |
| 1769 | __m.unlock(); | |
| 1770 | return __q; | |
| 1771 | } | |
| 1772 | ||
| 1773 | template <class _Tp> | |
| 1774 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1775 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1776 | shared_ptr<_Tp> | |
| 1777 | atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order) | |
| 1778 | { | |
| 1779 | return atomic_load(__p); | |
| 1780 | } | |
| 1781 | ||
| 1782 | template <class _Tp> | |
| 1783 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1784 | void | |
| 1785 | atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) | |
| 1786 | { | |
| 1787 | __sp_mut& __m = __get_sp_mut(__p); | |
| 1788 | __m.lock(); | |
| 1789 | __p->swap(__r); | |
| 1790 | __m.unlock(); | |
| 1791 | } | |
| 1792 | ||
| 1793 | template <class _Tp> | |
| 1794 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1795 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1796 | void | |
| 1797 | atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) | |
| 1798 | { | |
| 1799 | atomic_store(__p, __r); | |
| 1800 | } | |
| 1801 | ||
| 1802 | template <class _Tp> | |
| 1803 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1804 | shared_ptr<_Tp> | |
| 1805 | atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) | |
| 1806 | { | |
| 1807 | __sp_mut& __m = __get_sp_mut(__p); | |
| 1808 | __m.lock(); | |
| 1809 | __p->swap(__r); | |
| 1810 | __m.unlock(); | |
| 1811 | return __r; | |
| 1812 | } | |
| 1813 | ||
| 1814 | template <class _Tp> | |
| 1815 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1816 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1817 | shared_ptr<_Tp> | |
| 1818 | atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) | |
| 1819 | { | |
| 1820 | return atomic_exchange(__p, __r); | |
| 1821 | } | |
| 1822 | ||
| 1823 | template <class _Tp> | |
| 1824 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1825 | bool | |
| 1826 | atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) | |
| 1827 | { | |
| 1828 | shared_ptr<_Tp> __temp; | |
| 1829 | __sp_mut& __m = __get_sp_mut(__p); | |
| 1830 | __m.lock(); | |
| 1831 | if (__p->__owner_equivalent(*__v)) | |
| 1832 | { | |
| 1833 | _VSTD::swap(__temp, *__p); | |
| 1834 | *__p = __w; | |
| 1835 | __m.unlock(); | |
| 1836 | return true; | |
| 1837 | } | |
| 1838 | _VSTD::swap(__temp, *__v); | |
| 1839 | *__v = *__p; | |
| 1840 | __m.unlock(); | |
| 1841 | return false; | |
| 1842 | } | |
| 1843 | ||
| 1844 | template <class _Tp> | |
| 1845 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1846 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1847 | bool | |
| 1848 | atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) | |
| 1849 | { | |
| 1850 | return atomic_compare_exchange_strong(__p, __v, __w); | |
| 1851 | } | |
| 1852 | ||
| 1853 | template <class _Tp> | |
| 1854 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1855 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1856 | bool | |
| 1857 | atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, | |
| 1858 | shared_ptr<_Tp> __w, memory_order, memory_order) | |
| 1859 | { | |
| 1860 | return atomic_compare_exchange_strong(__p, __v, __w); | |
| 1861 | } | |
| 1862 | ||
| 1863 | template <class _Tp> | |
| 1864 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1865 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 1866 | bool | |
| 1867 | atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, | |
| 1868 | shared_ptr<_Tp> __w, memory_order, memory_order) | |
| 1869 | { | |
| 1870 | return atomic_compare_exchange_weak(__p, __v, __w); | |
| 1871 | } | |
| 1872 | ||
| 1873 | #endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) | |
| 1874 | ||
| 1875 | _LIBCPP_END_NAMESPACE_STD | |
| 1876 | ||
| 1877 | _LIBCPP_POP_MACROS | |
| 1878 | ||
| 1879 | #endif // _LIBCPP___MEMORY_SHARED_PTR_H |
lib/libcxx/include/__memory/temporary_buffer.h created+89| ... | ... | @@ -0,0 +1,89 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_TEMPORARY_BUFFER_H | |
| 11 | #define _LIBCPP___MEMORY_TEMPORARY_BUFFER_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | #include <new> | |
| 16 | #include <utility> // pair | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | template <class _Tp> | |
| 28 | _LIBCPP_NODISCARD_EXT _LIBCPP_NO_CFI | |
| 29 | pair<_Tp*, ptrdiff_t> | |
| 30 | get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT | |
| 31 | { | |
| 32 | pair<_Tp*, ptrdiff_t> __r(0, 0); | |
| 33 | const ptrdiff_t __m = (~ptrdiff_t(0) ^ | |
| 34 | ptrdiff_t(ptrdiff_t(1) << (sizeof(ptrdiff_t) * __CHAR_BIT__ - 1))) | |
| 35 | / sizeof(_Tp); | |
| 36 | if (__n > __m) | |
| 37 | __n = __m; | |
| 38 | while (__n > 0) | |
| 39 | { | |
| 40 | #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) | |
| 41 | if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) | |
| 42 | { | |
| 43 | align_val_t __al = | |
| 44 | align_val_t(alignment_of<_Tp>::value); | |
| 45 | __r.first = static_cast<_Tp*>(::operator new( | |
| 46 | __n * sizeof(_Tp), __al, nothrow)); | |
| 47 | } else { | |
| 48 | __r.first = static_cast<_Tp*>(::operator new( | |
| 49 | __n * sizeof(_Tp), nothrow)); | |
| 50 | } | |
| 51 | #else | |
| 52 | if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) | |
| 53 | { | |
| 54 | // Since aligned operator new is unavailable, return an empty | |
| 55 | // buffer rather than one with invalid alignment. | |
| 56 | return __r; | |
| 57 | } | |
| 58 | ||
| 59 | __r.first = static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), nothrow)); | |
| 60 | #endif | |
| 61 | ||
| 62 | if (__r.first) | |
| 63 | { | |
| 64 | __r.second = __n; | |
| 65 | break; | |
| 66 | } | |
| 67 | __n /= 2; | |
| 68 | } | |
| 69 | return __r; | |
| 70 | } | |
| 71 | ||
| 72 | template <class _Tp> | |
| 73 | inline _LIBCPP_INLINE_VISIBILITY | |
| 74 | void return_temporary_buffer(_Tp* __p) _NOEXCEPT | |
| 75 | { | |
| 76 | _VSTD::__libcpp_deallocate_unsized((void*)__p, _LIBCPP_ALIGNOF(_Tp)); | |
| 77 | } | |
| 78 | ||
| 79 | struct __return_temporary_buffer | |
| 80 | { | |
| 81 | template <class _Tp> | |
| 82 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) const {_VSTD::return_temporary_buffer(__p);} | |
| 83 | }; | |
| 84 | ||
| 85 | _LIBCPP_END_NAMESPACE_STD | |
| 86 | ||
| 87 | _LIBCPP_POP_MACROS | |
| 88 | ||
| 89 | #endif // _LIBCPP___MEMORY_TEMPORARY_BUFFER_H |
lib/libcxx/include/__memory/uninitialized_algorithms.h created+261| ... | ... | @@ -0,0 +1,261 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H | |
| 11 | #define _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__memory/addressof.h> | |
| 15 | #include <__memory/construct_at.h> | |
| 16 | #include <iterator> | |
| 17 | #include <utility> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | template <class _InputIterator, class _ForwardIterator> | |
| 29 | _ForwardIterator | |
| 30 | uninitialized_copy(_InputIterator __f, _InputIterator __l, _ForwardIterator __r) | |
| 31 | { | |
| 32 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 33 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 34 | _ForwardIterator __s = __r; | |
| 35 | try | |
| 36 | { | |
| 37 | #endif | |
| 38 | for (; __f != __l; ++__f, (void) ++__r) | |
| 39 | ::new ((void*)_VSTD::addressof(*__r)) value_type(*__f); | |
| 40 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 41 | } | |
| 42 | catch (...) | |
| 43 | { | |
| 44 | for (; __s != __r; ++__s) | |
| 45 | __s->~value_type(); | |
| 46 | throw; | |
| 47 | } | |
| 48 | #endif | |
| 49 | return __r; | |
| 50 | } | |
| 51 | ||
| 52 | template <class _InputIterator, class _Size, class _ForwardIterator> | |
| 53 | _ForwardIterator | |
| 54 | uninitialized_copy_n(_InputIterator __f, _Size __n, _ForwardIterator __r) | |
| 55 | { | |
| 56 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 57 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 58 | _ForwardIterator __s = __r; | |
| 59 | try | |
| 60 | { | |
| 61 | #endif | |
| 62 | for (; __n > 0; ++__f, (void) ++__r, (void) --__n) | |
| 63 | ::new ((void*)_VSTD::addressof(*__r)) value_type(*__f); | |
| 64 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 65 | } | |
| 66 | catch (...) | |
| 67 | { | |
| 68 | for (; __s != __r; ++__s) | |
| 69 | __s->~value_type(); | |
| 70 | throw; | |
| 71 | } | |
| 72 | #endif | |
| 73 | return __r; | |
| 74 | } | |
| 75 | ||
| 76 | template <class _ForwardIterator, class _Tp> | |
| 77 | void | |
| 78 | uninitialized_fill(_ForwardIterator __f, _ForwardIterator __l, const _Tp& __x) | |
| 79 | { | |
| 80 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 81 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 82 | _ForwardIterator __s = __f; | |
| 83 | try | |
| 84 | { | |
| 85 | #endif | |
| 86 | for (; __f != __l; ++__f) | |
| 87 | ::new ((void*)_VSTD::addressof(*__f)) value_type(__x); | |
| 88 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 89 | } | |
| 90 | catch (...) | |
| 91 | { | |
| 92 | for (; __s != __f; ++__s) | |
| 93 | __s->~value_type(); | |
| 94 | throw; | |
| 95 | } | |
| 96 | #endif | |
| 97 | } | |
| 98 | ||
| 99 | template <class _ForwardIterator, class _Size, class _Tp> | |
| 100 | _ForwardIterator | |
| 101 | uninitialized_fill_n(_ForwardIterator __f, _Size __n, const _Tp& __x) | |
| 102 | { | |
| 103 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 104 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 105 | _ForwardIterator __s = __f; | |
| 106 | try | |
| 107 | { | |
| 108 | #endif | |
| 109 | for (; __n > 0; ++__f, (void) --__n) | |
| 110 | ::new ((void*)_VSTD::addressof(*__f)) value_type(__x); | |
| 111 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 112 | } | |
| 113 | catch (...) | |
| 114 | { | |
| 115 | for (; __s != __f; ++__s) | |
| 116 | __s->~value_type(); | |
| 117 | throw; | |
| 118 | } | |
| 119 | #endif | |
| 120 | return __f; | |
| 121 | } | |
| 122 | ||
| 123 | #if _LIBCPP_STD_VER > 14 | |
| 124 | ||
| 125 | template <class _ForwardIterator> | |
| 126 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 127 | void destroy(_ForwardIterator __first, _ForwardIterator __last) { | |
| 128 | for (; __first != __last; ++__first) | |
| 129 | _VSTD::destroy_at(_VSTD::addressof(*__first)); | |
| 130 | } | |
| 131 | ||
| 132 | template <class _ForwardIterator, class _Size> | |
| 133 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 134 | _ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) { | |
| 135 | for (; __n > 0; (void)++__first, --__n) | |
| 136 | _VSTD::destroy_at(_VSTD::addressof(*__first)); | |
| 137 | return __first; | |
| 138 | } | |
| 139 | ||
| 140 | template <class _ForwardIterator> | |
| 141 | inline _LIBCPP_INLINE_VISIBILITY | |
| 142 | void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) { | |
| 143 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 144 | auto __idx = __first; | |
| 145 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 146 | try { | |
| 147 | #endif | |
| 148 | for (; __idx != __last; ++__idx) | |
| 149 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt; | |
| 150 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 151 | } catch (...) { | |
| 152 | _VSTD::destroy(__first, __idx); | |
| 153 | throw; | |
| 154 | } | |
| 155 | #endif | |
| 156 | } | |
| 157 | ||
| 158 | template <class _ForwardIterator, class _Size> | |
| 159 | inline _LIBCPP_INLINE_VISIBILITY | |
| 160 | _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { | |
| 161 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 162 | auto __idx = __first; | |
| 163 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 164 | try { | |
| 165 | #endif | |
| 166 | for (; __n > 0; (void)++__idx, --__n) | |
| 167 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt; | |
| 168 | return __idx; | |
| 169 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 170 | } catch (...) { | |
| 171 | _VSTD::destroy(__first, __idx); | |
| 172 | throw; | |
| 173 | } | |
| 174 | #endif | |
| 175 | } | |
| 176 | ||
| 177 | ||
| 178 | template <class _ForwardIterator> | |
| 179 | inline _LIBCPP_INLINE_VISIBILITY | |
| 180 | void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) { | |
| 181 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 182 | auto __idx = __first; | |
| 183 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 184 | try { | |
| 185 | #endif | |
| 186 | for (; __idx != __last; ++__idx) | |
| 187 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(); | |
| 188 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 189 | } catch (...) { | |
| 190 | _VSTD::destroy(__first, __idx); | |
| 191 | throw; | |
| 192 | } | |
| 193 | #endif | |
| 194 | } | |
| 195 | ||
| 196 | template <class _ForwardIterator, class _Size> | |
| 197 | inline _LIBCPP_INLINE_VISIBILITY | |
| 198 | _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { | |
| 199 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 200 | auto __idx = __first; | |
| 201 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 202 | try { | |
| 203 | #endif | |
| 204 | for (; __n > 0; (void)++__idx, --__n) | |
| 205 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(); | |
| 206 | return __idx; | |
| 207 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 208 | } catch (...) { | |
| 209 | _VSTD::destroy(__first, __idx); | |
| 210 | throw; | |
| 211 | } | |
| 212 | #endif | |
| 213 | } | |
| 214 | ||
| 215 | ||
| 216 | template <class _InputIt, class _ForwardIt> | |
| 217 | inline _LIBCPP_INLINE_VISIBILITY | |
| 218 | _ForwardIt uninitialized_move(_InputIt __first, _InputIt __last, _ForwardIt __first_res) { | |
| 219 | using _Vt = typename iterator_traits<_ForwardIt>::value_type; | |
| 220 | auto __idx = __first_res; | |
| 221 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 222 | try { | |
| 223 | #endif | |
| 224 | for (; __first != __last; (void)++__idx, ++__first) | |
| 225 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(_VSTD::move(*__first)); | |
| 226 | return __idx; | |
| 227 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 228 | } catch (...) { | |
| 229 | _VSTD::destroy(__first_res, __idx); | |
| 230 | throw; | |
| 231 | } | |
| 232 | #endif | |
| 233 | } | |
| 234 | ||
| 235 | template <class _InputIt, class _Size, class _ForwardIt> | |
| 236 | inline _LIBCPP_INLINE_VISIBILITY | |
| 237 | pair<_InputIt, _ForwardIt> | |
| 238 | uninitialized_move_n(_InputIt __first, _Size __n, _ForwardIt __first_res) { | |
| 239 | using _Vt = typename iterator_traits<_ForwardIt>::value_type; | |
| 240 | auto __idx = __first_res; | |
| 241 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 242 | try { | |
| 243 | #endif | |
| 244 | for (; __n > 0; ++__idx, (void)++__first, --__n) | |
| 245 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(_VSTD::move(*__first)); | |
| 246 | return {__first, __idx}; | |
| 247 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 248 | } catch (...) { | |
| 249 | _VSTD::destroy(__first_res, __idx); | |
| 250 | throw; | |
| 251 | } | |
| 252 | #endif | |
| 253 | } | |
| 254 | ||
| 255 | #endif // _LIBCPP_STD_VER > 14 | |
| 256 | ||
| 257 | _LIBCPP_END_NAMESPACE_STD | |
| 258 | ||
| 259 | _LIBCPP_POP_MACROS | |
| 260 | ||
| 261 | #endif // _LIBCPP___MEMORY_UNINITIALIZED_ALGORITHMS_H |
lib/libcxx/include/__memory/unique_ptr.h created+773| ... | ... | @@ -0,0 +1,773 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H | |
| 11 | #define _LIBCPP___MEMORY_UNIQUE_PTR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional_base> | |
| 15 | #include <__functional/hash.h> | |
| 16 | #include <__functional/operations.h> | |
| 17 | #include <__memory/allocator_traits.h> // __pointer | |
| 18 | #include <__memory/compressed_pair.h> | |
| 19 | #include <__utility/forward.h> | |
| 20 | #include <cstddef> | |
| 21 | #include <type_traits> | |
| 22 | #include <utility> | |
| 23 | ||
| 24 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 25 | # include <__memory/auto_ptr.h> | |
| 26 | #endif | |
| 27 | ||
| 28 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 29 | #pragma GCC system_header | |
| 30 | #endif | |
| 31 | ||
| 32 | _LIBCPP_PUSH_MACROS | |
| 33 | #include <__undef_macros> | |
| 34 | ||
| 35 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 36 | ||
| 37 | template <class _Tp> | |
| 38 | struct _LIBCPP_TEMPLATE_VIS default_delete { | |
| 39 | static_assert(!is_function<_Tp>::value, | |
| 40 | "default_delete cannot be instantiated for function types"); | |
| 41 | #ifndef _LIBCPP_CXX03_LANG | |
| 42 | _LIBCPP_INLINE_VISIBILITY constexpr default_delete() _NOEXCEPT = default; | |
| 43 | #else | |
| 44 | _LIBCPP_INLINE_VISIBILITY default_delete() {} | |
| 45 | #endif | |
| 46 | template <class _Up> | |
| 47 | _LIBCPP_INLINE_VISIBILITY | |
| 48 | default_delete(const default_delete<_Up>&, | |
| 49 | typename enable_if<is_convertible<_Up*, _Tp*>::value>::type* = | |
| 50 | 0) _NOEXCEPT {} | |
| 51 | ||
| 52 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __ptr) const _NOEXCEPT { | |
| 53 | static_assert(sizeof(_Tp) > 0, | |
| 54 | "default_delete can not delete incomplete type"); | |
| 55 | static_assert(!is_void<_Tp>::value, | |
| 56 | "default_delete can not delete incomplete type"); | |
| 57 | delete __ptr; | |
| 58 | } | |
| 59 | }; | |
| 60 | ||
| 61 | template <class _Tp> | |
| 62 | struct _LIBCPP_TEMPLATE_VIS default_delete<_Tp[]> { | |
| 63 | private: | |
| 64 | template <class _Up> | |
| 65 | struct _EnableIfConvertible | |
| 66 | : enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value> {}; | |
| 67 | ||
| 68 | public: | |
| 69 | #ifndef _LIBCPP_CXX03_LANG | |
| 70 | _LIBCPP_INLINE_VISIBILITY constexpr default_delete() _NOEXCEPT = default; | |
| 71 | #else | |
| 72 | _LIBCPP_INLINE_VISIBILITY default_delete() {} | |
| 73 | #endif | |
| 74 | ||
| 75 | template <class _Up> | |
| 76 | _LIBCPP_INLINE_VISIBILITY | |
| 77 | default_delete(const default_delete<_Up[]>&, | |
| 78 | typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPT {} | |
| 79 | ||
| 80 | template <class _Up> | |
| 81 | _LIBCPP_INLINE_VISIBILITY | |
| 82 | typename _EnableIfConvertible<_Up>::type | |
| 83 | operator()(_Up* __ptr) const _NOEXCEPT { | |
| 84 | static_assert(sizeof(_Tp) > 0, | |
| 85 | "default_delete can not delete incomplete type"); | |
| 86 | static_assert(!is_void<_Tp>::value, | |
| 87 | "default_delete can not delete void type"); | |
| 88 | delete[] __ptr; | |
| 89 | } | |
| 90 | }; | |
| 91 | ||
| 92 | template <class _Deleter> | |
| 93 | struct __unique_ptr_deleter_sfinae { | |
| 94 | static_assert(!is_reference<_Deleter>::value, "incorrect specialization"); | |
| 95 | typedef const _Deleter& __lval_ref_type; | |
| 96 | typedef _Deleter&& __good_rval_ref_type; | |
| 97 | typedef true_type __enable_rval_overload; | |
| 98 | }; | |
| 99 | ||
| 100 | template <class _Deleter> | |
| 101 | struct __unique_ptr_deleter_sfinae<_Deleter const&> { | |
| 102 | typedef const _Deleter& __lval_ref_type; | |
| 103 | typedef const _Deleter&& __bad_rval_ref_type; | |
| 104 | typedef false_type __enable_rval_overload; | |
| 105 | }; | |
| 106 | ||
| 107 | template <class _Deleter> | |
| 108 | struct __unique_ptr_deleter_sfinae<_Deleter&> { | |
| 109 | typedef _Deleter& __lval_ref_type; | |
| 110 | typedef _Deleter&& __bad_rval_ref_type; | |
| 111 | typedef false_type __enable_rval_overload; | |
| 112 | }; | |
| 113 | ||
| 114 | #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI) | |
| 115 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) | |
| 116 | #else | |
| 117 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI | |
| 118 | #endif | |
| 119 | ||
| 120 | template <class _Tp, class _Dp = default_delete<_Tp> > | |
| 121 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { | |
| 122 | public: | |
| 123 | typedef _Tp element_type; | |
| 124 | typedef _Dp deleter_type; | |
| 125 | typedef _LIBCPP_NODEBUG_TYPE typename __pointer<_Tp, deleter_type>::type pointer; | |
| 126 | ||
| 127 | static_assert(!is_rvalue_reference<deleter_type>::value, | |
| 128 | "the specified deleter type cannot be an rvalue reference"); | |
| 129 | ||
| 130 | private: | |
| 131 | __compressed_pair<pointer, deleter_type> __ptr_; | |
| 132 | ||
| 133 | struct __nat { int __for_bool_; }; | |
| 134 | ||
| 135 | typedef _LIBCPP_NODEBUG_TYPE __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; | |
| 136 | ||
| 137 | template <bool _Dummy> | |
| 138 | using _LValRefType _LIBCPP_NODEBUG_TYPE = | |
| 139 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; | |
| 140 | ||
| 141 | template <bool _Dummy> | |
| 142 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 143 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; | |
| 144 | ||
| 145 | template <bool _Dummy> | |
| 146 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 147 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; | |
| 148 | ||
| 149 | template <bool _Dummy, class _Deleter = typename __dependent_type< | |
| 150 | __identity<deleter_type>, _Dummy>::type> | |
| 151 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE = | |
| 152 | typename enable_if<is_default_constructible<_Deleter>::value && | |
| 153 | !is_pointer<_Deleter>::value>::type; | |
| 154 | ||
| 155 | template <class _ArgType> | |
| 156 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE = | |
| 157 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; | |
| 158 | ||
| 159 | template <class _UPtr, class _Up> | |
| 160 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 161 | is_convertible<typename _UPtr::pointer, pointer>::value && | |
| 162 | !is_array<_Up>::value | |
| 163 | >::type; | |
| 164 | ||
| 165 | template <class _UDel> | |
| 166 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 167 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || | |
| 168 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) | |
| 169 | >::type; | |
| 170 | ||
| 171 | template <class _UDel> | |
| 172 | using _EnableIfDeleterAssignable = typename enable_if< | |
| 173 | is_assignable<_Dp&, _UDel&&>::value | |
| 174 | >::type; | |
| 175 | ||
| 176 | public: | |
| 177 | template <bool _Dummy = true, | |
| 178 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 179 | _LIBCPP_INLINE_VISIBILITY | |
| 180 | _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 181 | ||
| 182 | template <bool _Dummy = true, | |
| 183 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 184 | _LIBCPP_INLINE_VISIBILITY | |
| 185 | _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 186 | ||
| 187 | template <bool _Dummy = true, | |
| 188 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 189 | _LIBCPP_INLINE_VISIBILITY | |
| 190 | explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __default_init_tag()) {} | |
| 191 | ||
| 192 | template <bool _Dummy = true, | |
| 193 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > | |
| 194 | _LIBCPP_INLINE_VISIBILITY | |
| 195 | unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT | |
| 196 | : __ptr_(__p, __d) {} | |
| 197 | ||
| 198 | template <bool _Dummy = true, | |
| 199 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > | |
| 200 | _LIBCPP_INLINE_VISIBILITY | |
| 201 | unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT | |
| 202 | : __ptr_(__p, _VSTD::move(__d)) { | |
| 203 | static_assert(!is_reference<deleter_type>::value, | |
| 204 | "rvalue deleter bound to reference"); | |
| 205 | } | |
| 206 | ||
| 207 | template <bool _Dummy = true, | |
| 208 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > > | |
| 209 | _LIBCPP_INLINE_VISIBILITY | |
| 210 | unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete; | |
| 211 | ||
| 212 | _LIBCPP_INLINE_VISIBILITY | |
| 213 | unique_ptr(unique_ptr&& __u) _NOEXCEPT | |
| 214 | : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { | |
| 215 | } | |
| 216 | ||
| 217 | template <class _Up, class _Ep, | |
| 218 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 219 | class = _EnableIfDeleterConvertible<_Ep> | |
| 220 | > | |
| 221 | _LIBCPP_INLINE_VISIBILITY | |
| 222 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT | |
| 223 | : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {} | |
| 224 | ||
| 225 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 226 | template <class _Up> | |
| 227 | _LIBCPP_INLINE_VISIBILITY | |
| 228 | unique_ptr(auto_ptr<_Up>&& __p, | |
| 229 | typename enable_if<is_convertible<_Up*, _Tp*>::value && | |
| 230 | is_same<_Dp, default_delete<_Tp> >::value, | |
| 231 | __nat>::type = __nat()) _NOEXCEPT | |
| 232 | : __ptr_(__p.release(), __default_init_tag()) {} | |
| 233 | #endif | |
| 234 | ||
| 235 | _LIBCPP_INLINE_VISIBILITY | |
| 236 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { | |
| 237 | reset(__u.release()); | |
| 238 | __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter()); | |
| 239 | return *this; | |
| 240 | } | |
| 241 | ||
| 242 | template <class _Up, class _Ep, | |
| 243 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 244 | class = _EnableIfDeleterAssignable<_Ep> | |
| 245 | > | |
| 246 | _LIBCPP_INLINE_VISIBILITY | |
| 247 | unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { | |
| 248 | reset(__u.release()); | |
| 249 | __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); | |
| 250 | return *this; | |
| 251 | } | |
| 252 | ||
| 253 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 254 | template <class _Up> | |
| 255 | _LIBCPP_INLINE_VISIBILITY | |
| 256 | typename enable_if<is_convertible<_Up*, _Tp*>::value && | |
| 257 | is_same<_Dp, default_delete<_Tp> >::value, | |
| 258 | unique_ptr&>::type | |
| 259 | operator=(auto_ptr<_Up> __p) { | |
| 260 | reset(__p.release()); | |
| 261 | return *this; | |
| 262 | } | |
| 263 | #endif | |
| 264 | ||
| 265 | #ifdef _LIBCPP_CXX03_LANG | |
| 266 | unique_ptr(unique_ptr const&) = delete; | |
| 267 | unique_ptr& operator=(unique_ptr const&) = delete; | |
| 268 | #endif | |
| 269 | ||
| 270 | ||
| 271 | _LIBCPP_INLINE_VISIBILITY | |
| 272 | ~unique_ptr() { reset(); } | |
| 273 | ||
| 274 | _LIBCPP_INLINE_VISIBILITY | |
| 275 | unique_ptr& operator=(nullptr_t) _NOEXCEPT { | |
| 276 | reset(); | |
| 277 | return *this; | |
| 278 | } | |
| 279 | ||
| 280 | _LIBCPP_INLINE_VISIBILITY | |
| 281 | typename add_lvalue_reference<_Tp>::type | |
| 282 | operator*() const { | |
| 283 | return *__ptr_.first(); | |
| 284 | } | |
| 285 | _LIBCPP_INLINE_VISIBILITY | |
| 286 | pointer operator->() const _NOEXCEPT { | |
| 287 | return __ptr_.first(); | |
| 288 | } | |
| 289 | _LIBCPP_INLINE_VISIBILITY | |
| 290 | pointer get() const _NOEXCEPT { | |
| 291 | return __ptr_.first(); | |
| 292 | } | |
| 293 | _LIBCPP_INLINE_VISIBILITY | |
| 294 | deleter_type& get_deleter() _NOEXCEPT { | |
| 295 | return __ptr_.second(); | |
| 296 | } | |
| 297 | _LIBCPP_INLINE_VISIBILITY | |
| 298 | const deleter_type& get_deleter() const _NOEXCEPT { | |
| 299 | return __ptr_.second(); | |
| 300 | } | |
| 301 | _LIBCPP_INLINE_VISIBILITY | |
| 302 | explicit operator bool() const _NOEXCEPT { | |
| 303 | return __ptr_.first() != nullptr; | |
| 304 | } | |
| 305 | ||
| 306 | _LIBCPP_INLINE_VISIBILITY | |
| 307 | pointer release() _NOEXCEPT { | |
| 308 | pointer __t = __ptr_.first(); | |
| 309 | __ptr_.first() = pointer(); | |
| 310 | return __t; | |
| 311 | } | |
| 312 | ||
| 313 | _LIBCPP_INLINE_VISIBILITY | |
| 314 | void reset(pointer __p = pointer()) _NOEXCEPT { | |
| 315 | pointer __tmp = __ptr_.first(); | |
| 316 | __ptr_.first() = __p; | |
| 317 | if (__tmp) | |
| 318 | __ptr_.second()(__tmp); | |
| 319 | } | |
| 320 | ||
| 321 | _LIBCPP_INLINE_VISIBILITY | |
| 322 | void swap(unique_ptr& __u) _NOEXCEPT { | |
| 323 | __ptr_.swap(__u.__ptr_); | |
| 324 | } | |
| 325 | }; | |
| 326 | ||
| 327 | ||
| 328 | template <class _Tp, class _Dp> | |
| 329 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> { | |
| 330 | public: | |
| 331 | typedef _Tp element_type; | |
| 332 | typedef _Dp deleter_type; | |
| 333 | typedef typename __pointer<_Tp, deleter_type>::type pointer; | |
| 334 | ||
| 335 | private: | |
| 336 | __compressed_pair<pointer, deleter_type> __ptr_; | |
| 337 | ||
| 338 | template <class _From> | |
| 339 | struct _CheckArrayPointerConversion : is_same<_From, pointer> {}; | |
| 340 | ||
| 341 | template <class _FromElem> | |
| 342 | struct _CheckArrayPointerConversion<_FromElem*> | |
| 343 | : integral_constant<bool, | |
| 344 | is_same<_FromElem*, pointer>::value || | |
| 345 | (is_same<pointer, element_type*>::value && | |
| 346 | is_convertible<_FromElem(*)[], element_type(*)[]>::value) | |
| 347 | > | |
| 348 | {}; | |
| 349 | ||
| 350 | typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; | |
| 351 | ||
| 352 | template <bool _Dummy> | |
| 353 | using _LValRefType _LIBCPP_NODEBUG_TYPE = | |
| 354 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; | |
| 355 | ||
| 356 | template <bool _Dummy> | |
| 357 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 358 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; | |
| 359 | ||
| 360 | template <bool _Dummy> | |
| 361 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 362 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; | |
| 363 | ||
| 364 | template <bool _Dummy, class _Deleter = typename __dependent_type< | |
| 365 | __identity<deleter_type>, _Dummy>::type> | |
| 366 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE = | |
| 367 | typename enable_if<is_default_constructible<_Deleter>::value && | |
| 368 | !is_pointer<_Deleter>::value>::type; | |
| 369 | ||
| 370 | template <class _ArgType> | |
| 371 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE = | |
| 372 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; | |
| 373 | ||
| 374 | template <class _Pp> | |
| 375 | using _EnableIfPointerConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 376 | _CheckArrayPointerConversion<_Pp>::value | |
| 377 | >::type; | |
| 378 | ||
| 379 | template <class _UPtr, class _Up, | |
| 380 | class _ElemT = typename _UPtr::element_type> | |
| 381 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 382 | is_array<_Up>::value && | |
| 383 | is_same<pointer, element_type*>::value && | |
| 384 | is_same<typename _UPtr::pointer, _ElemT*>::value && | |
| 385 | is_convertible<_ElemT(*)[], element_type(*)[]>::value | |
| 386 | >::type; | |
| 387 | ||
| 388 | template <class _UDel> | |
| 389 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 390 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || | |
| 391 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) | |
| 392 | >::type; | |
| 393 | ||
| 394 | template <class _UDel> | |
| 395 | using _EnableIfDeleterAssignable _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 396 | is_assignable<_Dp&, _UDel&&>::value | |
| 397 | >::type; | |
| 398 | ||
| 399 | public: | |
| 400 | template <bool _Dummy = true, | |
| 401 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 402 | _LIBCPP_INLINE_VISIBILITY | |
| 403 | _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 404 | ||
| 405 | template <bool _Dummy = true, | |
| 406 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 407 | _LIBCPP_INLINE_VISIBILITY | |
| 408 | _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 409 | ||
| 410 | template <class _Pp, bool _Dummy = true, | |
| 411 | class = _EnableIfDeleterDefaultConstructible<_Dummy>, | |
| 412 | class = _EnableIfPointerConvertible<_Pp> > | |
| 413 | _LIBCPP_INLINE_VISIBILITY | |
| 414 | explicit unique_ptr(_Pp __p) _NOEXCEPT | |
| 415 | : __ptr_(__p, __default_init_tag()) {} | |
| 416 | ||
| 417 | template <class _Pp, bool _Dummy = true, | |
| 418 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >, | |
| 419 | class = _EnableIfPointerConvertible<_Pp> > | |
| 420 | _LIBCPP_INLINE_VISIBILITY | |
| 421 | unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPT | |
| 422 | : __ptr_(__p, __d) {} | |
| 423 | ||
| 424 | template <bool _Dummy = true, | |
| 425 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > | |
| 426 | _LIBCPP_INLINE_VISIBILITY | |
| 427 | unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPT | |
| 428 | : __ptr_(nullptr, __d) {} | |
| 429 | ||
| 430 | template <class _Pp, bool _Dummy = true, | |
| 431 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >, | |
| 432 | class = _EnableIfPointerConvertible<_Pp> > | |
| 433 | _LIBCPP_INLINE_VISIBILITY | |
| 434 | unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT | |
| 435 | : __ptr_(__p, _VSTD::move(__d)) { | |
| 436 | static_assert(!is_reference<deleter_type>::value, | |
| 437 | "rvalue deleter bound to reference"); | |
| 438 | } | |
| 439 | ||
| 440 | template <bool _Dummy = true, | |
| 441 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > | |
| 442 | _LIBCPP_INLINE_VISIBILITY | |
| 443 | unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPT | |
| 444 | : __ptr_(nullptr, _VSTD::move(__d)) { | |
| 445 | static_assert(!is_reference<deleter_type>::value, | |
| 446 | "rvalue deleter bound to reference"); | |
| 447 | } | |
| 448 | ||
| 449 | template <class _Pp, bool _Dummy = true, | |
| 450 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >, | |
| 451 | class = _EnableIfPointerConvertible<_Pp> > | |
| 452 | _LIBCPP_INLINE_VISIBILITY | |
| 453 | unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete; | |
| 454 | ||
| 455 | _LIBCPP_INLINE_VISIBILITY | |
| 456 | unique_ptr(unique_ptr&& __u) _NOEXCEPT | |
| 457 | : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { | |
| 458 | } | |
| 459 | ||
| 460 | _LIBCPP_INLINE_VISIBILITY | |
| 461 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { | |
| 462 | reset(__u.release()); | |
| 463 | __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter()); | |
| 464 | return *this; | |
| 465 | } | |
| 466 | ||
| 467 | template <class _Up, class _Ep, | |
| 468 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 469 | class = _EnableIfDeleterConvertible<_Ep> | |
| 470 | > | |
| 471 | _LIBCPP_INLINE_VISIBILITY | |
| 472 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT | |
| 473 | : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) { | |
| 474 | } | |
| 475 | ||
| 476 | template <class _Up, class _Ep, | |
| 477 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 478 | class = _EnableIfDeleterAssignable<_Ep> | |
| 479 | > | |
| 480 | _LIBCPP_INLINE_VISIBILITY | |
| 481 | unique_ptr& | |
| 482 | operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { | |
| 483 | reset(__u.release()); | |
| 484 | __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); | |
| 485 | return *this; | |
| 486 | } | |
| 487 | ||
| 488 | #ifdef _LIBCPP_CXX03_LANG | |
| 489 | unique_ptr(unique_ptr const&) = delete; | |
| 490 | unique_ptr& operator=(unique_ptr const&) = delete; | |
| 491 | #endif | |
| 492 | ||
| 493 | public: | |
| 494 | _LIBCPP_INLINE_VISIBILITY | |
| 495 | ~unique_ptr() { reset(); } | |
| 496 | ||
| 497 | _LIBCPP_INLINE_VISIBILITY | |
| 498 | unique_ptr& operator=(nullptr_t) _NOEXCEPT { | |
| 499 | reset(); | |
| 500 | return *this; | |
| 501 | } | |
| 502 | ||
| 503 | _LIBCPP_INLINE_VISIBILITY | |
| 504 | typename add_lvalue_reference<_Tp>::type | |
| 505 | operator[](size_t __i) const { | |
| 506 | return __ptr_.first()[__i]; | |
| 507 | } | |
| 508 | _LIBCPP_INLINE_VISIBILITY | |
| 509 | pointer get() const _NOEXCEPT { | |
| 510 | return __ptr_.first(); | |
| 511 | } | |
| 512 | ||
| 513 | _LIBCPP_INLINE_VISIBILITY | |
| 514 | deleter_type& get_deleter() _NOEXCEPT { | |
| 515 | return __ptr_.second(); | |
| 516 | } | |
| 517 | ||
| 518 | _LIBCPP_INLINE_VISIBILITY | |
| 519 | const deleter_type& get_deleter() const _NOEXCEPT { | |
| 520 | return __ptr_.second(); | |
| 521 | } | |
| 522 | _LIBCPP_INLINE_VISIBILITY | |
| 523 | explicit operator bool() const _NOEXCEPT { | |
| 524 | return __ptr_.first() != nullptr; | |
| 525 | } | |
| 526 | ||
| 527 | _LIBCPP_INLINE_VISIBILITY | |
| 528 | pointer release() _NOEXCEPT { | |
| 529 | pointer __t = __ptr_.first(); | |
| 530 | __ptr_.first() = pointer(); | |
| 531 | return __t; | |
| 532 | } | |
| 533 | ||
| 534 | template <class _Pp> | |
| 535 | _LIBCPP_INLINE_VISIBILITY | |
| 536 | typename enable_if< | |
| 537 | _CheckArrayPointerConversion<_Pp>::value | |
| 538 | >::type | |
| 539 | reset(_Pp __p) _NOEXCEPT { | |
| 540 | pointer __tmp = __ptr_.first(); | |
| 541 | __ptr_.first() = __p; | |
| 542 | if (__tmp) | |
| 543 | __ptr_.second()(__tmp); | |
| 544 | } | |
| 545 | ||
| 546 | _LIBCPP_INLINE_VISIBILITY | |
| 547 | void reset(nullptr_t = nullptr) _NOEXCEPT { | |
| 548 | pointer __tmp = __ptr_.first(); | |
| 549 | __ptr_.first() = nullptr; | |
| 550 | if (__tmp) | |
| 551 | __ptr_.second()(__tmp); | |
| 552 | } | |
| 553 | ||
| 554 | _LIBCPP_INLINE_VISIBILITY | |
| 555 | void swap(unique_ptr& __u) _NOEXCEPT { | |
| 556 | __ptr_.swap(__u.__ptr_); | |
| 557 | } | |
| 558 | ||
| 559 | }; | |
| 560 | ||
| 561 | template <class _Tp, class _Dp> | |
| 562 | inline _LIBCPP_INLINE_VISIBILITY | |
| 563 | typename enable_if< | |
| 564 | __is_swappable<_Dp>::value, | |
| 565 | void | |
| 566 | >::type | |
| 567 | swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT {__x.swap(__y);} | |
| 568 | ||
| 569 | template <class _T1, class _D1, class _T2, class _D2> | |
| 570 | inline _LIBCPP_INLINE_VISIBILITY | |
| 571 | bool | |
| 572 | operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() == __y.get();} | |
| 573 | ||
| 574 | template <class _T1, class _D1, class _T2, class _D2> | |
| 575 | inline _LIBCPP_INLINE_VISIBILITY | |
| 576 | bool | |
| 577 | operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x == __y);} | |
| 578 | ||
| 579 | template <class _T1, class _D1, class _T2, class _D2> | |
| 580 | inline _LIBCPP_INLINE_VISIBILITY | |
| 581 | bool | |
| 582 | operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) | |
| 583 | { | |
| 584 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; | |
| 585 | typedef typename unique_ptr<_T2, _D2>::pointer _P2; | |
| 586 | typedef typename common_type<_P1, _P2>::type _Vp; | |
| 587 | return less<_Vp>()(__x.get(), __y.get()); | |
| 588 | } | |
| 589 | ||
| 590 | template <class _T1, class _D1, class _T2, class _D2> | |
| 591 | inline _LIBCPP_INLINE_VISIBILITY | |
| 592 | bool | |
| 593 | operator> (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __y < __x;} | |
| 594 | ||
| 595 | template <class _T1, class _D1, class _T2, class _D2> | |
| 596 | inline _LIBCPP_INLINE_VISIBILITY | |
| 597 | bool | |
| 598 | operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__y < __x);} | |
| 599 | ||
| 600 | template <class _T1, class _D1, class _T2, class _D2> | |
| 601 | inline _LIBCPP_INLINE_VISIBILITY | |
| 602 | bool | |
| 603 | operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} | |
| 604 | ||
| 605 | template <class _T1, class _D1> | |
| 606 | inline _LIBCPP_INLINE_VISIBILITY | |
| 607 | bool | |
| 608 | operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT | |
| 609 | { | |
| 610 | return !__x; | |
| 611 | } | |
| 612 | ||
| 613 | template <class _T1, class _D1> | |
| 614 | inline _LIBCPP_INLINE_VISIBILITY | |
| 615 | bool | |
| 616 | operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT | |
| 617 | { | |
| 618 | return !__x; | |
| 619 | } | |
| 620 | ||
| 621 | template <class _T1, class _D1> | |
| 622 | inline _LIBCPP_INLINE_VISIBILITY | |
| 623 | bool | |
| 624 | operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT | |
| 625 | { | |
| 626 | return static_cast<bool>(__x); | |
| 627 | } | |
| 628 | ||
| 629 | template <class _T1, class _D1> | |
| 630 | inline _LIBCPP_INLINE_VISIBILITY | |
| 631 | bool | |
| 632 | operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT | |
| 633 | { | |
| 634 | return static_cast<bool>(__x); | |
| 635 | } | |
| 636 | ||
| 637 | template <class _T1, class _D1> | |
| 638 | inline _LIBCPP_INLINE_VISIBILITY | |
| 639 | bool | |
| 640 | operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 641 | { | |
| 642 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; | |
| 643 | return less<_P1>()(__x.get(), nullptr); | |
| 644 | } | |
| 645 | ||
| 646 | template <class _T1, class _D1> | |
| 647 | inline _LIBCPP_INLINE_VISIBILITY | |
| 648 | bool | |
| 649 | operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 650 | { | |
| 651 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; | |
| 652 | return less<_P1>()(nullptr, __x.get()); | |
| 653 | } | |
| 654 | ||
| 655 | template <class _T1, class _D1> | |
| 656 | inline _LIBCPP_INLINE_VISIBILITY | |
| 657 | bool | |
| 658 | operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 659 | { | |
| 660 | return nullptr < __x; | |
| 661 | } | |
| 662 | ||
| 663 | template <class _T1, class _D1> | |
| 664 | inline _LIBCPP_INLINE_VISIBILITY | |
| 665 | bool | |
| 666 | operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 667 | { | |
| 668 | return __x < nullptr; | |
| 669 | } | |
| 670 | ||
| 671 | template <class _T1, class _D1> | |
| 672 | inline _LIBCPP_INLINE_VISIBILITY | |
| 673 | bool | |
| 674 | operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 675 | { | |
| 676 | return !(nullptr < __x); | |
| 677 | } | |
| 678 | ||
| 679 | template <class _T1, class _D1> | |
| 680 | inline _LIBCPP_INLINE_VISIBILITY | |
| 681 | bool | |
| 682 | operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 683 | { | |
| 684 | return !(__x < nullptr); | |
| 685 | } | |
| 686 | ||
| 687 | template <class _T1, class _D1> | |
| 688 | inline _LIBCPP_INLINE_VISIBILITY | |
| 689 | bool | |
| 690 | operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 691 | { | |
| 692 | return !(__x < nullptr); | |
| 693 | } | |
| 694 | ||
| 695 | template <class _T1, class _D1> | |
| 696 | inline _LIBCPP_INLINE_VISIBILITY | |
| 697 | bool | |
| 698 | operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 699 | { | |
| 700 | return !(nullptr < __x); | |
| 701 | } | |
| 702 | ||
| 703 | #if _LIBCPP_STD_VER > 11 | |
| 704 | ||
| 705 | template<class _Tp> | |
| 706 | struct __unique_if | |
| 707 | { | |
| 708 | typedef unique_ptr<_Tp> __unique_single; | |
| 709 | }; | |
| 710 | ||
| 711 | template<class _Tp> | |
| 712 | struct __unique_if<_Tp[]> | |
| 713 | { | |
| 714 | typedef unique_ptr<_Tp[]> __unique_array_unknown_bound; | |
| 715 | }; | |
| 716 | ||
| 717 | template<class _Tp, size_t _Np> | |
| 718 | struct __unique_if<_Tp[_Np]> | |
| 719 | { | |
| 720 | typedef void __unique_array_known_bound; | |
| 721 | }; | |
| 722 | ||
| 723 | template<class _Tp, class... _Args> | |
| 724 | inline _LIBCPP_INLINE_VISIBILITY | |
| 725 | typename __unique_if<_Tp>::__unique_single | |
| 726 | make_unique(_Args&&... __args) | |
| 727 | { | |
| 728 | return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...)); | |
| 729 | } | |
| 730 | ||
| 731 | template<class _Tp> | |
| 732 | inline _LIBCPP_INLINE_VISIBILITY | |
| 733 | typename __unique_if<_Tp>::__unique_array_unknown_bound | |
| 734 | make_unique(size_t __n) | |
| 735 | { | |
| 736 | typedef typename remove_extent<_Tp>::type _Up; | |
| 737 | return unique_ptr<_Tp>(new _Up[__n]()); | |
| 738 | } | |
| 739 | ||
| 740 | template<class _Tp, class... _Args> | |
| 741 | typename __unique_if<_Tp>::__unique_array_known_bound | |
| 742 | make_unique(_Args&&...) = delete; | |
| 743 | ||
| 744 | #endif // _LIBCPP_STD_VER > 11 | |
| 745 | ||
| 746 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS hash; | |
| 747 | ||
| 748 | template <class _Tp, class _Dp> | |
| 749 | #ifdef _LIBCPP_CXX03_LANG | |
| 750 | struct _LIBCPP_TEMPLATE_VIS hash<unique_ptr<_Tp, _Dp> > | |
| 751 | #else | |
| 752 | struct _LIBCPP_TEMPLATE_VIS hash<__enable_hash_helper< | |
| 753 | unique_ptr<_Tp, _Dp>, typename unique_ptr<_Tp, _Dp>::pointer> > | |
| 754 | #endif | |
| 755 | { | |
| 756 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 757 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unique_ptr<_Tp, _Dp> argument_type; | |
| 758 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 759 | #endif | |
| 760 | ||
| 761 | _LIBCPP_INLINE_VISIBILITY | |
| 762 | size_t operator()(const unique_ptr<_Tp, _Dp>& __ptr) const | |
| 763 | { | |
| 764 | typedef typename unique_ptr<_Tp, _Dp>::pointer pointer; | |
| 765 | return hash<pointer>()(__ptr.get()); | |
| 766 | } | |
| 767 | }; | |
| 768 | ||
| 769 | _LIBCPP_END_NAMESPACE_STD | |
| 770 | ||
| 771 | _LIBCPP_POP_MACROS | |
| 772 | ||
| 773 | #endif // _LIBCPP___MEMORY_UNIQUE_PTR_H |
lib/libcxx/include/__memory/uses_allocator.h created+60| ... | ... | @@ -0,0 +1,60 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_USES_ALLOCATOR_H | |
| 11 | #define _LIBCPP___MEMORY_USES_ALLOCATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | template <class _Tp> | |
| 24 | struct __has_allocator_type | |
| 25 | { | |
| 26 | private: | |
| 27 | struct __two {char __lx; char __lxx;}; | |
| 28 | template <class _Up> static __two __test(...); | |
| 29 | template <class _Up> static char __test(typename _Up::allocator_type* = 0); | |
| 30 | public: | |
| 31 | static const bool value = sizeof(__test<_Tp>(0)) == 1; | |
| 32 | }; | |
| 33 | ||
| 34 | template <class _Tp, class _Alloc, bool = __has_allocator_type<_Tp>::value> | |
| 35 | struct __uses_allocator | |
| 36 | : public integral_constant<bool, | |
| 37 | is_convertible<_Alloc, typename _Tp::allocator_type>::value> | |
| 38 | { | |
| 39 | }; | |
| 40 | ||
| 41 | template <class _Tp, class _Alloc> | |
| 42 | struct __uses_allocator<_Tp, _Alloc, false> | |
| 43 | : public false_type | |
| 44 | { | |
| 45 | }; | |
| 46 | ||
| 47 | template <class _Tp, class _Alloc> | |
| 48 | struct _LIBCPP_TEMPLATE_VIS uses_allocator | |
| 49 | : public __uses_allocator<_Tp, _Alloc> | |
| 50 | { | |
| 51 | }; | |
| 52 | ||
| 53 | #if _LIBCPP_STD_VER > 14 | |
| 54 | template <class _Tp, class _Alloc> | |
| 55 | _LIBCPP_INLINE_VAR constexpr size_t uses_allocator_v = uses_allocator<_Tp, _Alloc>::value; | |
| 56 | #endif | |
| 57 | ||
| 58 | _LIBCPP_END_NAMESPACE_STD | |
| 59 | ||
| 60 | #endif // _LIBCPP___MEMORY_USES_ALLOCATOR_H |
lib/libcxx/include/__memory/utilities.h deleted-88| ... | ... | @@ -1,88 +0,0 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___MEMORY_UTILITIES_H | |
| 11 | #define _LIBCPP___MEMORY_UTILITIES_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__memory/allocator_traits.h> | |
| 15 | #include <cstddef> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | // Helper class to allocate memory using an Allocator in an exception safe | |
| 28 | // manner. | |
| 29 | // | |
| 30 | // The intended usage of this class is as follows: | |
| 31 | // | |
| 32 | // 0 | |
| 33 | // 1 __allocation_guard<SomeAllocator> guard(alloc, 10); | |
| 34 | // 2 do_some_initialization_that_may_throw(guard.__get()); | |
| 35 | // 3 save_allocated_pointer_in_a_noexcept_operation(guard.__release_ptr()); | |
| 36 | // 4 | |
| 37 | // | |
| 38 | // If line (2) throws an exception during initialization of the memory, the | |
| 39 | // guard's destructor will be called, and the memory will be released using | |
| 40 | // Allocator deallocation. Otherwise, we release the memory from the guard on | |
| 41 | // line (3) in an operation that can't throw -- after that, the guard is not | |
| 42 | // responsible for the memory anymore. | |
| 43 | // | |
| 44 | // This is similar to a unique_ptr, except it's easier to use with a | |
| 45 | // custom allocator. | |
| 46 | template<class _Alloc> | |
| 47 | struct __allocation_guard { | |
| 48 | using _Pointer = typename allocator_traits<_Alloc>::pointer; | |
| 49 | using _Size = typename allocator_traits<_Alloc>::size_type; | |
| 50 | ||
| 51 | template<class _AllocT> // we perform the allocator conversion inside the constructor | |
| 52 | _LIBCPP_HIDE_FROM_ABI | |
| 53 | explicit __allocation_guard(_AllocT __alloc, _Size __n) | |
| 54 | : __alloc_(_VSTD::move(__alloc)) | |
| 55 | , __n_(__n) | |
| 56 | , __ptr_(allocator_traits<_Alloc>::allocate(__alloc_, __n_)) // initialization order is important | |
| 57 | { } | |
| 58 | ||
| 59 | _LIBCPP_HIDE_FROM_ABI | |
| 60 | ~__allocation_guard() _NOEXCEPT { | |
| 61 | if (__ptr_ != nullptr) { | |
| 62 | allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 66 | _LIBCPP_HIDE_FROM_ABI | |
| 67 | _Pointer __release_ptr() _NOEXCEPT { // not called __release() because it's a keyword in objective-c++ | |
| 68 | _Pointer __tmp = __ptr_; | |
| 69 | __ptr_ = nullptr; | |
| 70 | return __tmp; | |
| 71 | } | |
| 72 | ||
| 73 | _LIBCPP_HIDE_FROM_ABI | |
| 74 | _Pointer __get() const _NOEXCEPT { | |
| 75 | return __ptr_; | |
| 76 | } | |
| 77 | ||
| 78 | private: | |
| 79 | _Alloc __alloc_; | |
| 80 | _Size __n_; | |
| 81 | _Pointer __ptr_; | |
| 82 | }; | |
| 83 | ||
| 84 | _LIBCPP_END_NAMESPACE_STD | |
| 85 | ||
| 86 | _LIBCPP_POP_MACROS | |
| 87 | ||
| 88 | #endif // _LIBCPP___MEMORY_UTILITIES_H |
lib/libcxx/include/__mutex_base+3-5| ... | ... | @@ -11,10 +11,9 @@ |
| 11 | 11 | #define _LIBCPP___MUTEX_BASE |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <__threading_support> | |
| 14 | 15 | #include <chrono> |
| 15 | 16 | #include <system_error> |
| 16 | #include <__threading_support> | |
| 17 | ||
| 18 | 17 | #include <time.h> |
| 19 | 18 | |
| 20 | 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -190,8 +189,7 @@ public: |
| 190 | 189 | _LIBCPP_INLINE_VISIBILITY |
| 191 | 190 | bool owns_lock() const _NOEXCEPT {return __owns_;} |
| 192 | 191 | _LIBCPP_INLINE_VISIBILITY |
| 193 | _LIBCPP_EXPLICIT | |
| 194 | operator bool () const _NOEXCEPT {return __owns_;} | |
| 192 | explicit operator bool() const _NOEXCEPT {return __owns_;} | |
| 195 | 193 | _LIBCPP_INLINE_VISIBILITY |
| 196 | 194 | mutex_type* mutex() const _NOEXCEPT {return __m_;} |
| 197 | 195 | }; |
| ... | ... | @@ -526,4 +524,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 526 | 524 | |
| 527 | 525 | _LIBCPP_POP_MACROS |
| 528 | 526 | |
| 529 | #endif // _LIBCPP___MUTEX_BASE | |
| 527 | #endif // _LIBCPP___MUTEX_BASE |
lib/libcxx/include/__node_handle+2-1| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | #define _LIBCPP___NODE_HANDLE |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <__debug> | |
| 14 | 15 | #include <memory> |
| 15 | 16 | #include <optional> |
| 16 | 17 | |
| ... | ... | @@ -205,4 +206,4 @@ struct _LIBCPP_TEMPLATE_VIS __insert_return_type |
| 205 | 206 | _LIBCPP_END_NAMESPACE_STD |
| 206 | 207 | _LIBCPP_POP_MACROS |
| 207 | 208 | |
| 208 | #endif | |
| 209 | #endif // _LIBCPP___NODE_HANDLE |
lib/libcxx/include/__nullptr+2-2| ... | ... | @@ -56,6 +56,6 @@ namespace std |
| 56 | 56 | typedef decltype(nullptr) nullptr_t; |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | #endif // _LIBCPP_HAS_NO_NULLPTR | |
| 59 | #endif // _LIBCPP_HAS_NO_NULLPTR | |
| 60 | 60 | |
| 61 | #endif // _LIBCPP_NULLPTR | |
| 61 | #endif // _LIBCPP_NULLPTR |
lib/libcxx/include/__random/uniform_int_distribution.h created+316| ... | ... | @@ -0,0 +1,316 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H | |
| 10 | #define _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H | |
| 11 | ||
| 12 | #include <__bits> | |
| 13 | #include <__config> | |
| 14 | #include <cstddef> | |
| 15 | #include <cstdint> | |
| 16 | #include <iosfwd> | |
| 17 | #include <limits> | |
| 18 | #include <type_traits> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | // __independent_bits_engine | |
| 30 | ||
| 31 | template <unsigned long long _Xp, size_t _Rp> | |
| 32 | struct __log2_imp | |
| 33 | { | |
| 34 | static const size_t value = _Xp & ((unsigned long long)(1) << _Rp) ? _Rp | |
| 35 | : __log2_imp<_Xp, _Rp - 1>::value; | |
| 36 | }; | |
| 37 | ||
| 38 | template <unsigned long long _Xp> | |
| 39 | struct __log2_imp<_Xp, 0> | |
| 40 | { | |
| 41 | static const size_t value = 0; | |
| 42 | }; | |
| 43 | ||
| 44 | template <size_t _Rp> | |
| 45 | struct __log2_imp<0, _Rp> | |
| 46 | { | |
| 47 | static const size_t value = _Rp + 1; | |
| 48 | }; | |
| 49 | ||
| 50 | template <class _UIntType, _UIntType _Xp> | |
| 51 | struct __log2 | |
| 52 | { | |
| 53 | static const size_t value = __log2_imp<_Xp, | |
| 54 | sizeof(_UIntType) * __CHAR_BIT__ - 1>::value; | |
| 55 | }; | |
| 56 | ||
| 57 | template<class _Engine, class _UIntType> | |
| 58 | class __independent_bits_engine | |
| 59 | { | |
| 60 | public: | |
| 61 | // types | |
| 62 | typedef _UIntType result_type; | |
| 63 | ||
| 64 | private: | |
| 65 | typedef typename _Engine::result_type _Engine_result_type; | |
| 66 | typedef typename conditional | |
| 67 | < | |
| 68 | sizeof(_Engine_result_type) <= sizeof(result_type), | |
| 69 | result_type, | |
| 70 | _Engine_result_type | |
| 71 | >::type _Working_result_type; | |
| 72 | ||
| 73 | _Engine& __e_; | |
| 74 | size_t __w_; | |
| 75 | size_t __w0_; | |
| 76 | size_t __n_; | |
| 77 | size_t __n0_; | |
| 78 | _Working_result_type __y0_; | |
| 79 | _Working_result_type __y1_; | |
| 80 | _Engine_result_type __mask0_; | |
| 81 | _Engine_result_type __mask1_; | |
| 82 | ||
| 83 | #ifdef _LIBCPP_CXX03_LANG | |
| 84 | static const _Working_result_type _Rp = _Engine::_Max - _Engine::_Min | |
| 85 | + _Working_result_type(1); | |
| 86 | #else | |
| 87 | static _LIBCPP_CONSTEXPR const _Working_result_type _Rp = _Engine::max() - _Engine::min() | |
| 88 | + _Working_result_type(1); | |
| 89 | #endif | |
| 90 | static _LIBCPP_CONSTEXPR const size_t __m = __log2<_Working_result_type, _Rp>::value; | |
| 91 | static _LIBCPP_CONSTEXPR const size_t _WDt = numeric_limits<_Working_result_type>::digits; | |
| 92 | static _LIBCPP_CONSTEXPR const size_t _EDt = numeric_limits<_Engine_result_type>::digits; | |
| 93 | ||
| 94 | public: | |
| 95 | // constructors and seeding functions | |
| 96 | __independent_bits_engine(_Engine& __e, size_t __w); | |
| 97 | ||
| 98 | // generating functions | |
| 99 | result_type operator()() {return __eval(integral_constant<bool, _Rp != 0>());} | |
| 100 | ||
| 101 | private: | |
| 102 | result_type __eval(false_type); | |
| 103 | result_type __eval(true_type); | |
| 104 | }; | |
| 105 | ||
| 106 | template<class _Engine, class _UIntType> | |
| 107 | __independent_bits_engine<_Engine, _UIntType> | |
| 108 | ::__independent_bits_engine(_Engine& __e, size_t __w) | |
| 109 | : __e_(__e), | |
| 110 | __w_(__w) | |
| 111 | { | |
| 112 | __n_ = __w_ / __m + (__w_ % __m != 0); | |
| 113 | __w0_ = __w_ / __n_; | |
| 114 | if (_Rp == 0) | |
| 115 | __y0_ = _Rp; | |
| 116 | else if (__w0_ < _WDt) | |
| 117 | __y0_ = (_Rp >> __w0_) << __w0_; | |
| 118 | else | |
| 119 | __y0_ = 0; | |
| 120 | if (_Rp - __y0_ > __y0_ / __n_) | |
| 121 | { | |
| 122 | ++__n_; | |
| 123 | __w0_ = __w_ / __n_; | |
| 124 | if (__w0_ < _WDt) | |
| 125 | __y0_ = (_Rp >> __w0_) << __w0_; | |
| 126 | else | |
| 127 | __y0_ = 0; | |
| 128 | } | |
| 129 | __n0_ = __n_ - __w_ % __n_; | |
| 130 | if (__w0_ < _WDt - 1) | |
| 131 | __y1_ = (_Rp >> (__w0_ + 1)) << (__w0_ + 1); | |
| 132 | else | |
| 133 | __y1_ = 0; | |
| 134 | __mask0_ = __w0_ > 0 ? _Engine_result_type(~0) >> (_EDt - __w0_) : | |
| 135 | _Engine_result_type(0); | |
| 136 | __mask1_ = __w0_ < _EDt - 1 ? | |
| 137 | _Engine_result_type(~0) >> (_EDt - (__w0_ + 1)) : | |
| 138 | _Engine_result_type(~0); | |
| 139 | } | |
| 140 | ||
| 141 | template<class _Engine, class _UIntType> | |
| 142 | inline | |
| 143 | _UIntType | |
| 144 | __independent_bits_engine<_Engine, _UIntType>::__eval(false_type) | |
| 145 | { | |
| 146 | return static_cast<result_type>(__e_() & __mask0_); | |
| 147 | } | |
| 148 | ||
| 149 | template<class _Engine, class _UIntType> | |
| 150 | _UIntType | |
| 151 | __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) | |
| 152 | { | |
| 153 | const size_t _WRt = numeric_limits<result_type>::digits; | |
| 154 | result_type _Sp = 0; | |
| 155 | for (size_t __k = 0; __k < __n0_; ++__k) | |
| 156 | { | |
| 157 | _Engine_result_type __u; | |
| 158 | do | |
| 159 | { | |
| 160 | __u = __e_() - _Engine::min(); | |
| 161 | } while (__u >= __y0_); | |
| 162 | if (__w0_ < _WRt) | |
| 163 | _Sp <<= __w0_; | |
| 164 | else | |
| 165 | _Sp = 0; | |
| 166 | _Sp += __u & __mask0_; | |
| 167 | } | |
| 168 | for (size_t __k = __n0_; __k < __n_; ++__k) | |
| 169 | { | |
| 170 | _Engine_result_type __u; | |
| 171 | do | |
| 172 | { | |
| 173 | __u = __e_() - _Engine::min(); | |
| 174 | } while (__u >= __y1_); | |
| 175 | if (__w0_ < _WRt - 1) | |
| 176 | _Sp <<= __w0_ + 1; | |
| 177 | else | |
| 178 | _Sp = 0; | |
| 179 | _Sp += __u & __mask1_; | |
| 180 | } | |
| 181 | return _Sp; | |
| 182 | } | |
| 183 | ||
| 184 | template<class _IntType = int> | |
| 185 | class uniform_int_distribution | |
| 186 | { | |
| 187 | public: | |
| 188 | // types | |
| 189 | typedef _IntType result_type; | |
| 190 | ||
| 191 | class param_type | |
| 192 | { | |
| 193 | result_type __a_; | |
| 194 | result_type __b_; | |
| 195 | public: | |
| 196 | typedef uniform_int_distribution distribution_type; | |
| 197 | ||
| 198 | explicit param_type(result_type __a = 0, | |
| 199 | result_type __b = numeric_limits<result_type>::max()) | |
| 200 | : __a_(__a), __b_(__b) {} | |
| 201 | ||
| 202 | result_type a() const {return __a_;} | |
| 203 | result_type b() const {return __b_;} | |
| 204 | ||
| 205 | friend bool operator==(const param_type& __x, const param_type& __y) | |
| 206 | {return __x.__a_ == __y.__a_ && __x.__b_ == __y.__b_;} | |
| 207 | friend bool operator!=(const param_type& __x, const param_type& __y) | |
| 208 | {return !(__x == __y);} | |
| 209 | }; | |
| 210 | ||
| 211 | private: | |
| 212 | param_type __p_; | |
| 213 | ||
| 214 | public: | |
| 215 | // constructors and reset functions | |
| 216 | #ifndef _LIBCPP_CXX03_LANG | |
| 217 | uniform_int_distribution() : uniform_int_distribution(0) {} | |
| 218 | explicit uniform_int_distribution( | |
| 219 | result_type __a, result_type __b = numeric_limits<result_type>::max()) | |
| 220 | : __p_(param_type(__a, __b)) {} | |
| 221 | #else | |
| 222 | explicit uniform_int_distribution( | |
| 223 | result_type __a = 0, | |
| 224 | result_type __b = numeric_limits<result_type>::max()) | |
| 225 | : __p_(param_type(__a, __b)) {} | |
| 226 | #endif | |
| 227 | explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} | |
| 228 | void reset() {} | |
| 229 | ||
| 230 | // generating functions | |
| 231 | template<class _URNG> result_type operator()(_URNG& __g) | |
| 232 | {return (*this)(__g, __p_);} | |
| 233 | template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); | |
| 234 | ||
| 235 | // property functions | |
| 236 | result_type a() const {return __p_.a();} | |
| 237 | result_type b() const {return __p_.b();} | |
| 238 | ||
| 239 | param_type param() const {return __p_;} | |
| 240 | void param(const param_type& __p) {__p_ = __p;} | |
| 241 | ||
| 242 | result_type min() const {return a();} | |
| 243 | result_type max() const {return b();} | |
| 244 | ||
| 245 | friend bool operator==(const uniform_int_distribution& __x, | |
| 246 | const uniform_int_distribution& __y) | |
| 247 | {return __x.__p_ == __y.__p_;} | |
| 248 | friend bool operator!=(const uniform_int_distribution& __x, | |
| 249 | const uniform_int_distribution& __y) | |
| 250 | {return !(__x == __y);} | |
| 251 | }; | |
| 252 | ||
| 253 | template<class _IntType> | |
| 254 | template<class _URNG> | |
| 255 | typename uniform_int_distribution<_IntType>::result_type | |
| 256 | uniform_int_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p) | |
| 257 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 258 | { | |
| 259 | typedef typename conditional<sizeof(result_type) <= sizeof(uint32_t), | |
| 260 | uint32_t, uint64_t>::type _UIntType; | |
| 261 | const _UIntType _Rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1); | |
| 262 | if (_Rp == 1) | |
| 263 | return __p.a(); | |
| 264 | const size_t _Dt = numeric_limits<_UIntType>::digits; | |
| 265 | typedef __independent_bits_engine<_URNG, _UIntType> _Eng; | |
| 266 | if (_Rp == 0) | |
| 267 | return static_cast<result_type>(_Eng(__g, _Dt)()); | |
| 268 | size_t __w = _Dt - __libcpp_clz(_Rp) - 1; | |
| 269 | if ((_Rp & (numeric_limits<_UIntType>::max() >> (_Dt - __w))) != 0) | |
| 270 | ++__w; | |
| 271 | _Eng __e(__g, __w); | |
| 272 | _UIntType __u; | |
| 273 | do | |
| 274 | { | |
| 275 | __u = __e(); | |
| 276 | } while (__u >= _Rp); | |
| 277 | return static_cast<result_type>(__u + __p.a()); | |
| 278 | } | |
| 279 | ||
| 280 | template <class _CharT, class _Traits, class _IT> | |
| 281 | basic_ostream<_CharT, _Traits>& | |
| 282 | operator<<(basic_ostream<_CharT, _Traits>& __os, | |
| 283 | const uniform_int_distribution<_IT>& __x) | |
| 284 | { | |
| 285 | __save_flags<_CharT, _Traits> __lx(__os); | |
| 286 | typedef basic_ostream<_CharT, _Traits> _Ostream; | |
| 287 | __os.flags(_Ostream::dec | _Ostream::left); | |
| 288 | _CharT __sp = __os.widen(' '); | |
| 289 | __os.fill(__sp); | |
| 290 | return __os << __x.a() << __sp << __x.b(); | |
| 291 | } | |
| 292 | ||
| 293 | template <class _CharT, class _Traits, class _IT> | |
| 294 | basic_istream<_CharT, _Traits>& | |
| 295 | operator>>(basic_istream<_CharT, _Traits>& __is, | |
| 296 | uniform_int_distribution<_IT>& __x) | |
| 297 | { | |
| 298 | typedef uniform_int_distribution<_IT> _Eng; | |
| 299 | typedef typename _Eng::result_type result_type; | |
| 300 | typedef typename _Eng::param_type param_type; | |
| 301 | __save_flags<_CharT, _Traits> __lx(__is); | |
| 302 | typedef basic_istream<_CharT, _Traits> _Istream; | |
| 303 | __is.flags(_Istream::dec | _Istream::skipws); | |
| 304 | result_type __a; | |
| 305 | result_type __b; | |
| 306 | __is >> __a >> __b; | |
| 307 | if (!__is.fail()) | |
| 308 | __x.param(param_type(__a, __b)); | |
| 309 | return __is; | |
| 310 | } | |
| 311 | ||
| 312 | _LIBCPP_END_NAMESPACE_STD | |
| 313 | ||
| 314 | _LIBCPP_POP_MACROS | |
| 315 | ||
| 316 | #endif // _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H |
lib/libcxx/include/__ranges/access.h created+222| ... | ... | @@ -0,0 +1,222 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===------------------------ __ranges/access.h ---------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_ACCESS_H | |
| 10 | #define _LIBCPP___RANGES_ACCESS_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/readable_traits.h> | |
| 15 | #include <__ranges/enable_borrowed_range.h> | |
| 16 | #include <__utility/__decay_copy.h> | |
| 17 | #include <__utility/forward.h> | |
| 18 | #include <concepts> | |
| 19 | #include <type_traits> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 31 | ||
| 32 | // clang-format off | |
| 33 | ||
| 34 | namespace ranges { | |
| 35 | template <class _Tp> | |
| 36 | concept __can_borrow = | |
| 37 | is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp> >; | |
| 38 | ||
| 39 | template<class _Tp> | |
| 40 | concept __is_complete = requires { sizeof(_Tp); }; | |
| 41 | } // namespace ranges | |
| 42 | ||
| 43 | // [range.access.begin] | |
| 44 | namespace ranges::__begin { | |
| 45 | template <class _Tp> | |
| 46 | concept __member_begin = | |
| 47 | __can_borrow<_Tp> && | |
| 48 | requires(_Tp&& __t) { | |
| 49 | { _VSTD::__decay_copy(__t.begin()) } -> input_or_output_iterator; | |
| 50 | }; | |
| 51 | ||
| 52 | void begin(auto&) = delete; | |
| 53 | void begin(const auto&) = delete; | |
| 54 | ||
| 55 | template <class _Tp> | |
| 56 | concept __unqualified_begin = | |
| 57 | !__member_begin<_Tp> && | |
| 58 | __can_borrow<_Tp> && | |
| 59 | __class_or_enum<remove_cvref_t<_Tp> > && | |
| 60 | requires(_Tp && __t) { | |
| 61 | { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator; | |
| 62 | }; | |
| 63 | ||
| 64 | struct __fn { | |
| 65 | template <class _Tp> | |
| 66 | requires is_array_v<remove_cv_t<_Tp>> | |
| 67 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const noexcept { | |
| 68 | constexpr bool __complete = __is_complete<iter_value_t<_Tp> >; | |
| 69 | if constexpr (__complete) { // used to disable cryptic diagnostic | |
| 70 | return __t + 0; | |
| 71 | } | |
| 72 | else { | |
| 73 | static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."); | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 77 | template <class _Tp> | |
| 78 | requires __member_begin<_Tp> | |
| 79 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const | |
| 80 | noexcept(noexcept(_VSTD::__decay_copy(__t.begin()))) | |
| 81 | { | |
| 82 | return __t.begin(); | |
| 83 | } | |
| 84 | ||
| 85 | template <class _Tp> | |
| 86 | requires __unqualified_begin<_Tp> | |
| 87 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const | |
| 88 | noexcept(noexcept(_VSTD::__decay_copy(begin(__t)))) | |
| 89 | { | |
| 90 | return begin(__t); | |
| 91 | } | |
| 92 | ||
| 93 | void operator()(auto&&) const = delete; | |
| 94 | }; | |
| 95 | } // namespace ranges::__begin | |
| 96 | ||
| 97 | namespace ranges { | |
| 98 | inline namespace __cpo { | |
| 99 | inline constexpr auto begin = __begin::__fn{}; | |
| 100 | } // namespace __cpo | |
| 101 | ||
| 102 | template <class _Tp> | |
| 103 | using iterator_t = decltype(ranges::begin(declval<_Tp&>())); | |
| 104 | } // namespace ranges | |
| 105 | ||
| 106 | // [range.access.end] | |
| 107 | namespace ranges::__end { | |
| 108 | template <class _Tp> | |
| 109 | concept __member_end = | |
| 110 | __can_borrow<_Tp> && | |
| 111 | requires(_Tp&& __t) { | |
| 112 | typename iterator_t<_Tp>; | |
| 113 | { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for<iterator_t<_Tp> >; | |
| 114 | }; | |
| 115 | ||
| 116 | void end(auto&) = delete; | |
| 117 | void end(const auto&) = delete; | |
| 118 | ||
| 119 | template <class _Tp> | |
| 120 | concept __unqualified_end = | |
| 121 | !__member_end<_Tp> && | |
| 122 | __can_borrow<_Tp> && | |
| 123 | __class_or_enum<remove_cvref_t<_Tp> > && | |
| 124 | requires(_Tp && __t) { | |
| 125 | typename iterator_t<_Tp>; | |
| 126 | { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for<iterator_t<_Tp> >; | |
| 127 | }; | |
| 128 | ||
| 129 | class __fn { | |
| 130 | public: | |
| 131 | template <class _Tp, size_t _Np> | |
| 132 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept { | |
| 133 | constexpr bool __complete = __is_complete<remove_cv_t<_Tp> >; | |
| 134 | if constexpr (__complete) { // used to disable cryptic diagnostic | |
| 135 | return __t + _Np; | |
| 136 | } | |
| 137 | else { | |
| 138 | static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."); | |
| 139 | } | |
| 140 | } | |
| 141 | ||
| 142 | template <class _Tp> | |
| 143 | requires __member_end<_Tp> | |
| 144 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const | |
| 145 | noexcept(noexcept(_VSTD::__decay_copy(__t.end()))) | |
| 146 | { | |
| 147 | return _VSTD::forward<_Tp>(__t).end(); | |
| 148 | } | |
| 149 | ||
| 150 | template <class _Tp> | |
| 151 | requires __unqualified_end<_Tp> | |
| 152 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const | |
| 153 | noexcept(noexcept(_VSTD::__decay_copy(end(__t)))) | |
| 154 | { | |
| 155 | return end(__t); | |
| 156 | } | |
| 157 | ||
| 158 | void operator()(auto&&) const = delete; | |
| 159 | }; | |
| 160 | } // namespace ranges::__end | |
| 161 | ||
| 162 | namespace ranges::inline __cpo { | |
| 163 | inline constexpr auto end = __end::__fn{}; | |
| 164 | } // namespace ranges::__cpo | |
| 165 | ||
| 166 | namespace ranges::__cbegin { | |
| 167 | struct __fn { | |
| 168 | template <class _Tp> | |
| 169 | requires invocable<decltype(ranges::begin), _Tp const&> | |
| 170 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const | |
| 171 | noexcept(noexcept(ranges::begin(_VSTD::as_const(__t)))) | |
| 172 | { | |
| 173 | return ranges::begin(_VSTD::as_const(__t)); | |
| 174 | } | |
| 175 | ||
| 176 | template <class _Tp> | |
| 177 | requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::begin), _Tp const&&> | |
| 178 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const | |
| 179 | noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t)))) | |
| 180 | { | |
| 181 | return ranges::begin(static_cast<_Tp const&&>(__t)); | |
| 182 | } | |
| 183 | }; | |
| 184 | } // namespace ranges::__cbegin | |
| 185 | ||
| 186 | namespace ranges::inline __cpo { | |
| 187 | inline constexpr auto cbegin = __cbegin::__fn{}; | |
| 188 | } // namespace ranges::__cpo | |
| 189 | ||
| 190 | namespace ranges::__cend { | |
| 191 | struct __fn { | |
| 192 | template <class _Tp> | |
| 193 | requires invocable<decltype(ranges::end), _Tp const&> | |
| 194 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const | |
| 195 | noexcept(noexcept(ranges::end(_VSTD::as_const(__t)))) | |
| 196 | { | |
| 197 | return ranges::end(_VSTD::as_const(__t)); | |
| 198 | } | |
| 199 | ||
| 200 | template <class _Tp> | |
| 201 | requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::end), _Tp const&&> | |
| 202 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const | |
| 203 | noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t)))) | |
| 204 | { | |
| 205 | return ranges::end(static_cast<_Tp const&&>(__t)); | |
| 206 | } | |
| 207 | }; | |
| 208 | } // namespace ranges::__cend | |
| 209 | ||
| 210 | namespace ranges::inline __cpo { | |
| 211 | inline constexpr auto cend = __cend::__fn{}; | |
| 212 | } // namespace ranges::__cpo | |
| 213 | ||
| 214 | // clang-format off | |
| 215 | ||
| 216 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 217 | ||
| 218 | _LIBCPP_END_NAMESPACE_STD | |
| 219 | ||
| 220 | _LIBCPP_POP_MACROS | |
| 221 | ||
| 222 | #endif // _LIBCPP___RANGES_ACCESS_H |
lib/libcxx/include/__ranges/all.h created+86| ... | ... | @@ -0,0 +1,86 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_ALL_H | |
| 10 | #define _LIBCPP___RANGES_ALL_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__ranges/access.h> | |
| 16 | #include <__ranges/concepts.h> | |
| 17 | #include <__ranges/ref_view.h> | |
| 18 | #include <__ranges/subrange.h> | |
| 19 | #include <__utility/__decay_copy.h> | |
| 20 | #include <__utility/declval.h> | |
| 21 | #include <__utility/forward.h> | |
| 22 | #include <type_traits> | |
| 23 | ||
| 24 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 25 | #pragma GCC system_header | |
| 26 | #endif | |
| 27 | ||
| 28 | _LIBCPP_PUSH_MACROS | |
| 29 | #include <__undef_macros> | |
| 30 | ||
| 31 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 32 | ||
| 33 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 34 | ||
| 35 | namespace views { | |
| 36 | ||
| 37 | namespace __all { | |
| 38 | struct __fn { | |
| 39 | template<class _Tp> | |
| 40 | requires ranges::view<decay_t<_Tp>> | |
| 41 | _LIBCPP_HIDE_FROM_ABI | |
| 42 | constexpr auto operator()(_Tp&& __t) const | |
| 43 | noexcept(noexcept(_VSTD::__decay_copy(_VSTD::forward<_Tp>(__t)))) | |
| 44 | { | |
| 45 | return _VSTD::forward<_Tp>(__t); | |
| 46 | } | |
| 47 | ||
| 48 | template<class _Tp> | |
| 49 | requires (!ranges::view<decay_t<_Tp>>) && | |
| 50 | requires (_Tp&& __t) { ranges::ref_view{_VSTD::forward<_Tp>(__t)}; } | |
| 51 | _LIBCPP_HIDE_FROM_ABI | |
| 52 | constexpr auto operator()(_Tp&& __t) const | |
| 53 | noexcept(noexcept(ranges::ref_view{_VSTD::forward<_Tp>(__t)})) | |
| 54 | { | |
| 55 | return ranges::ref_view{_VSTD::forward<_Tp>(__t)}; | |
| 56 | } | |
| 57 | ||
| 58 | template<class _Tp> | |
| 59 | requires (!ranges::view<decay_t<_Tp>> && | |
| 60 | !requires (_Tp&& __t) { ranges::ref_view{_VSTD::forward<_Tp>(__t)}; } && | |
| 61 | requires (_Tp&& __t) { ranges::subrange{_VSTD::forward<_Tp>(__t)}; }) | |
| 62 | _LIBCPP_HIDE_FROM_ABI | |
| 63 | constexpr auto operator()(_Tp&& __t) const | |
| 64 | noexcept(noexcept(ranges::subrange{_VSTD::forward<_Tp>(__t)})) | |
| 65 | { | |
| 66 | return ranges::subrange{_VSTD::forward<_Tp>(__t)}; | |
| 67 | } | |
| 68 | }; | |
| 69 | } | |
| 70 | ||
| 71 | inline namespace __cpo { | |
| 72 | inline constexpr auto all = __all::__fn{}; | |
| 73 | } // namespace __cpo | |
| 74 | ||
| 75 | template<ranges::viewable_range _Range> | |
| 76 | using all_t = decltype(views::all(declval<_Range>())); | |
| 77 | ||
| 78 | } // namespace views | |
| 79 | ||
| 80 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 81 | ||
| 82 | _LIBCPP_END_NAMESPACE_STD | |
| 83 | ||
| 84 | _LIBCPP_POP_MACROS | |
| 85 | ||
| 86 | #endif // _LIBCPP___RANGES_ALL_H |
lib/libcxx/include/__ranges/common_view.h created+113| ... | ... | @@ -0,0 +1,113 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_COMMON_VIEW_H | |
| 10 | #define _LIBCPP___RANGES_COMMON_VIEW_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/common_iterator.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__ranges/access.h> | |
| 16 | #include <__ranges/all.h> | |
| 17 | #include <__ranges/concepts.h> | |
| 18 | #include <__ranges/enable_borrowed_range.h> | |
| 19 | #include <__ranges/size.h> | |
| 20 | #include <__ranges/view_interface.h> | |
| 21 | #include <concepts> | |
| 22 | #include <type_traits> | |
| 23 | ||
| 24 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 25 | #pragma GCC system_header | |
| 26 | #endif | |
| 27 | ||
| 28 | _LIBCPP_PUSH_MACROS | |
| 29 | #include <__undef_macros> | |
| 30 | ||
| 31 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 32 | ||
| 33 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 34 | ||
| 35 | namespace ranges { | |
| 36 | ||
| 37 | template<view _View> | |
| 38 | requires (!common_range<_View> && copyable<iterator_t<_View>>) | |
| 39 | class common_view : public view_interface<common_view<_View>> { | |
| 40 | _View __base_ = _View(); | |
| 41 | ||
| 42 | public: | |
| 43 | _LIBCPP_HIDE_FROM_ABI | |
| 44 | common_view() requires default_initializable<_View> = default; | |
| 45 | ||
| 46 | _LIBCPP_HIDE_FROM_ABI | |
| 47 | constexpr explicit common_view(_View __v) : __base_(_VSTD::move(__v)) { } | |
| 48 | ||
| 49 | _LIBCPP_HIDE_FROM_ABI | |
| 50 | constexpr _View base() const& requires copy_constructible<_View> { return __base_; } | |
| 51 | ||
| 52 | _LIBCPP_HIDE_FROM_ABI | |
| 53 | constexpr _View base() && { return _VSTD::move(__base_); } | |
| 54 | ||
| 55 | _LIBCPP_HIDE_FROM_ABI | |
| 56 | constexpr auto begin() { | |
| 57 | if constexpr (random_access_range<_View> && sized_range<_View>) | |
| 58 | return ranges::begin(__base_); | |
| 59 | else | |
| 60 | return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::begin(__base_)); | |
| 61 | } | |
| 62 | ||
| 63 | _LIBCPP_HIDE_FROM_ABI | |
| 64 | constexpr auto begin() const requires range<const _View> { | |
| 65 | if constexpr (random_access_range<const _View> && sized_range<const _View>) | |
| 66 | return ranges::begin(__base_); | |
| 67 | else | |
| 68 | return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::begin(__base_)); | |
| 69 | } | |
| 70 | ||
| 71 | _LIBCPP_HIDE_FROM_ABI | |
| 72 | constexpr auto end() { | |
| 73 | if constexpr (random_access_range<_View> && sized_range<_View>) | |
| 74 | return ranges::begin(__base_) + ranges::size(__base_); | |
| 75 | else | |
| 76 | return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::end(__base_)); | |
| 77 | } | |
| 78 | ||
| 79 | _LIBCPP_HIDE_FROM_ABI | |
| 80 | constexpr auto end() const requires range<const _View> { | |
| 81 | if constexpr (random_access_range<const _View> && sized_range<const _View>) | |
| 82 | return ranges::begin(__base_) + ranges::size(__base_); | |
| 83 | else | |
| 84 | return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::end(__base_)); | |
| 85 | } | |
| 86 | ||
| 87 | _LIBCPP_HIDE_FROM_ABI | |
| 88 | constexpr auto size() requires sized_range<_View> { | |
| 89 | return ranges::size(__base_); | |
| 90 | } | |
| 91 | ||
| 92 | _LIBCPP_HIDE_FROM_ABI | |
| 93 | constexpr auto size() const requires sized_range<const _View> { | |
| 94 | return ranges::size(__base_); | |
| 95 | } | |
| 96 | }; | |
| 97 | ||
| 98 | template<class _Range> | |
| 99 | common_view(_Range&&) | |
| 100 | -> common_view<views::all_t<_Range>>; | |
| 101 | ||
| 102 | template<class _View> | |
| 103 | inline constexpr bool enable_borrowed_range<common_view<_View>> = enable_borrowed_range<_View>; | |
| 104 | ||
| 105 | } // namespace ranges | |
| 106 | ||
| 107 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 108 | ||
| 109 | _LIBCPP_END_NAMESPACE_STD | |
| 110 | ||
| 111 | _LIBCPP_POP_MACROS | |
| 112 | ||
| 113 | #endif // _LIBCPP___RANGES_COMMON_VIEW_H |
lib/libcxx/include/__ranges/concepts.h created+138| ... | ... | @@ -0,0 +1,138 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===--------------------- __ranges/concepts.h ----------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_CONCEPTS_H | |
| 10 | #define _LIBCPP___RANGES_CONCEPTS_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/incrementable_traits.h> | |
| 15 | #include <__iterator/iter_move.h> | |
| 16 | #include <__iterator/iterator_traits.h> | |
| 17 | #include <__iterator/readable_traits.h> | |
| 18 | #include <__ranges/access.h> | |
| 19 | #include <__ranges/enable_borrowed_range.h> | |
| 20 | #include <__ranges/data.h> | |
| 21 | #include <__ranges/enable_view.h> | |
| 22 | #include <__ranges/size.h> | |
| 23 | #include <concepts> | |
| 24 | #include <type_traits> | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 27 | #pragma GCC system_header | |
| 28 | #endif | |
| 29 | ||
| 30 | _LIBCPP_PUSH_MACROS | |
| 31 | #include <__undef_macros> | |
| 32 | ||
| 33 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 34 | ||
| 35 | // clang-format off | |
| 36 | ||
| 37 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 38 | ||
| 39 | namespace ranges { | |
| 40 | // [range.range] | |
| 41 | template <class _Tp> | |
| 42 | concept range = requires(_Tp& __t) { | |
| 43 | ranges::begin(__t); // sometimes equality-preserving | |
| 44 | ranges::end(__t); | |
| 45 | }; | |
| 46 | ||
| 47 | template<class _Range> | |
| 48 | concept borrowed_range = range<_Range> && | |
| 49 | (is_lvalue_reference_v<_Range> || enable_borrowed_range<remove_cvref_t<_Range>>); | |
| 50 | ||
| 51 | // `iterator_t` defined in <__ranges/access.h> | |
| 52 | ||
| 53 | template <range _Rp> | |
| 54 | using sentinel_t = decltype(ranges::end(declval<_Rp&>())); | |
| 55 | ||
| 56 | template <range _Rp> | |
| 57 | using range_difference_t = iter_difference_t<iterator_t<_Rp>>; | |
| 58 | ||
| 59 | template <range _Rp> | |
| 60 | using range_value_t = iter_value_t<iterator_t<_Rp>>; | |
| 61 | ||
| 62 | template <range _Rp> | |
| 63 | using range_reference_t = iter_reference_t<iterator_t<_Rp>>; | |
| 64 | ||
| 65 | template <range _Rp> | |
| 66 | using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>; | |
| 67 | ||
| 68 | // [range.sized] | |
| 69 | template <class _Tp> | |
| 70 | concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); }; | |
| 71 | ||
| 72 | template<sized_range _Rp> | |
| 73 | using range_size_t = decltype(ranges::size(declval<_Rp&>())); | |
| 74 | ||
| 75 | // `disable_sized_range` defined in `<__ranges/size.h>` | |
| 76 | ||
| 77 | // [range.view], views | |
| 78 | ||
| 79 | // `enable_view` defined in <__ranges/enable_view.h> | |
| 80 | // `view_base` defined in <__ranges/enable_view.h> | |
| 81 | ||
| 82 | template <class _Tp> | |
| 83 | concept view = | |
| 84 | range<_Tp> && | |
| 85 | movable<_Tp> && | |
| 86 | enable_view<_Tp>; | |
| 87 | ||
| 88 | template<class _Range> | |
| 89 | concept __simple_view = | |
| 90 | view<_Range> && range<const _Range> && | |
| 91 | same_as<iterator_t<_Range>, iterator_t<const _Range>> && | |
| 92 | same_as<sentinel_t<_Range>, iterator_t<const _Range>>; | |
| 93 | ||
| 94 | // [range.refinements], other range refinements | |
| 95 | template <class _Rp, class _Tp> | |
| 96 | concept output_range = range<_Rp> && output_iterator<iterator_t<_Rp>, _Tp>; | |
| 97 | ||
| 98 | template <class _Tp> | |
| 99 | concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>; | |
| 100 | ||
| 101 | template <class _Tp> | |
| 102 | concept forward_range = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>; | |
| 103 | ||
| 104 | template <class _Tp> | |
| 105 | concept bidirectional_range = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>; | |
| 106 | ||
| 107 | template <class _Tp> | |
| 108 | concept random_access_range = | |
| 109 | bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>; | |
| 110 | ||
| 111 | template<class _Tp> | |
| 112 | concept contiguous_range = | |
| 113 | random_access_range<_Tp> && | |
| 114 | contiguous_iterator<iterator_t<_Tp>> && | |
| 115 | requires(_Tp& __t) { | |
| 116 | { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>; | |
| 117 | }; | |
| 118 | ||
| 119 | template <class _Tp> | |
| 120 | concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>; | |
| 121 | ||
| 122 | template<class _Tp> | |
| 123 | concept viewable_range = | |
| 124 | range<_Tp> && ( | |
| 125 | (view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>) || | |
| 126 | (!view<remove_cvref_t<_Tp>> && borrowed_range<_Tp>) | |
| 127 | ); | |
| 128 | } // namespace ranges | |
| 129 | ||
| 130 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 131 | ||
| 132 | // clang-format on | |
| 133 | ||
| 134 | _LIBCPP_END_NAMESPACE_STD | |
| 135 | ||
| 136 | _LIBCPP_POP_MACROS | |
| 137 | ||
| 138 | #endif // _LIBCPP___RANGES_CONCEPTS_H |
lib/libcxx/include/__ranges/copyable_box.h created+175| ... | ... | @@ -0,0 +1,175 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___RANGES_COPYABLE_BOX_H | |
| 11 | #define _LIBCPP___RANGES_COPYABLE_BOX_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__memory/addressof.h> | |
| 15 | #include <__memory/construct_at.h> | |
| 16 | #include <__utility/move.h> | |
| 17 | #include <concepts> | |
| 18 | #include <optional> | |
| 19 | #include <type_traits> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 31 | ||
| 32 | // __copyable_box allows turning a type that is copy-constructible (but maybe not copy-assignable) into | |
| 33 | // a type that is both copy-constructible and copy-assignable. It does that by introducing an empty state | |
| 34 | // and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary | |
| 35 | // to handle the case where the copy construction fails after destroying the object. | |
| 36 | // | |
| 37 | // In some cases, we can completely avoid the use of an empty state; we provide a specialization of | |
| 38 | // __copyable_box that does this, see below for the details. | |
| 39 | ||
| 40 | template<class _Tp> | |
| 41 | concept __copy_constructible_object = copy_constructible<_Tp> && is_object_v<_Tp>; | |
| 42 | ||
| 43 | namespace ranges { | |
| 44 | // Primary template - uses std::optional and introduces an empty state in case assignment fails. | |
| 45 | template<__copy_constructible_object _Tp> | |
| 46 | class __copyable_box { | |
| 47 | [[no_unique_address]] optional<_Tp> __val_; | |
| 48 | ||
| 49 | public: | |
| 50 | template<class ..._Args> | |
| 51 | requires is_constructible_v<_Tp, _Args...> | |
| 52 | _LIBCPP_HIDE_FROM_ABI | |
| 53 | constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) | |
| 54 | noexcept(is_nothrow_constructible_v<_Tp, _Args...>) | |
| 55 | : __val_(in_place, _VSTD::forward<_Args>(__args)...) | |
| 56 | { } | |
| 57 | ||
| 58 | _LIBCPP_HIDE_FROM_ABI | |
| 59 | constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) | |
| 60 | requires default_initializable<_Tp> | |
| 61 | : __val_(in_place) | |
| 62 | { } | |
| 63 | ||
| 64 | _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; | |
| 65 | _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; | |
| 66 | ||
| 67 | _LIBCPP_HIDE_FROM_ABI | |
| 68 | constexpr __copyable_box& operator=(__copyable_box const& __other) | |
| 69 | noexcept(is_nothrow_copy_constructible_v<_Tp>) | |
| 70 | { | |
| 71 | if (this != _VSTD::addressof(__other)) { | |
| 72 | if (__other.__has_value()) __val_.emplace(*__other); | |
| 73 | else __val_.reset(); | |
| 74 | } | |
| 75 | return *this; | |
| 76 | } | |
| 77 | ||
| 78 | _LIBCPP_HIDE_FROM_ABI | |
| 79 | __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; | |
| 80 | ||
| 81 | _LIBCPP_HIDE_FROM_ABI | |
| 82 | constexpr __copyable_box& operator=(__copyable_box&& __other) | |
| 83 | noexcept(is_nothrow_move_constructible_v<_Tp>) | |
| 84 | { | |
| 85 | if (this != _VSTD::addressof(__other)) { | |
| 86 | if (__other.__has_value()) __val_.emplace(_VSTD::move(*__other)); | |
| 87 | else __val_.reset(); | |
| 88 | } | |
| 89 | return *this; | |
| 90 | } | |
| 91 | ||
| 92 | _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; } | |
| 93 | _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; } | |
| 94 | _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); } | |
| 95 | }; | |
| 96 | ||
| 97 | // This partial specialization implements an optimization for when we know we don't need to store | |
| 98 | // an empty state to represent failure to perform an assignment. For copy-assignment, this happens: | |
| 99 | // | |
| 100 | // 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator | |
| 101 | // directly and avoid using std::optional. | |
| 102 | // 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as | |
| 103 | // destroy-and-then-construct and we know it will never fail, so we don't need an empty state. | |
| 104 | // | |
| 105 | // The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and | |
| 106 | // nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled | |
| 107 | // whenever we can apply any of these optimizations for both the copy assignment and the move assignment | |
| 108 | // operator. | |
| 109 | template<class _Tp> | |
| 110 | concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>; | |
| 111 | ||
| 112 | template<class _Tp> | |
| 113 | concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>; | |
| 114 | ||
| 115 | template<__copy_constructible_object _Tp> | |
| 116 | requires __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp> | |
| 117 | class __copyable_box<_Tp> { | |
| 118 | [[no_unique_address]] _Tp __val_; | |
| 119 | ||
| 120 | public: | |
| 121 | template<class ..._Args> | |
| 122 | requires is_constructible_v<_Tp, _Args...> | |
| 123 | _LIBCPP_HIDE_FROM_ABI | |
| 124 | constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) | |
| 125 | noexcept(is_nothrow_constructible_v<_Tp, _Args...>) | |
| 126 | : __val_(_VSTD::forward<_Args>(__args)...) | |
| 127 | { } | |
| 128 | ||
| 129 | _LIBCPP_HIDE_FROM_ABI | |
| 130 | constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) | |
| 131 | requires default_initializable<_Tp> | |
| 132 | : __val_() | |
| 133 | { } | |
| 134 | ||
| 135 | _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; | |
| 136 | _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; | |
| 137 | ||
| 138 | // Implementation of assignment operators in case we perform optimization (1) | |
| 139 | _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box const&) requires copyable<_Tp> = default; | |
| 140 | _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; | |
| 141 | ||
| 142 | // Implementation of assignment operators in case we perform optimization (2) | |
| 143 | _LIBCPP_HIDE_FROM_ABI | |
| 144 | constexpr __copyable_box& operator=(__copyable_box const& __other) noexcept { | |
| 145 | static_assert(is_nothrow_copy_constructible_v<_Tp>); | |
| 146 | if (this != _VSTD::addressof(__other)) { | |
| 147 | _VSTD::destroy_at(_VSTD::addressof(__val_)); | |
| 148 | _VSTD::construct_at(_VSTD::addressof(__val_), __other.__val_); | |
| 149 | } | |
| 150 | return *this; | |
| 151 | } | |
| 152 | ||
| 153 | _LIBCPP_HIDE_FROM_ABI | |
| 154 | constexpr __copyable_box& operator=(__copyable_box&& __other) noexcept { | |
| 155 | static_assert(is_nothrow_move_constructible_v<_Tp>); | |
| 156 | if (this != _VSTD::addressof(__other)) { | |
| 157 | _VSTD::destroy_at(_VSTD::addressof(__val_)); | |
| 158 | _VSTD::construct_at(_VSTD::addressof(__val_), _VSTD::move(__other.__val_)); | |
| 159 | } | |
| 160 | return *this; | |
| 161 | } | |
| 162 | ||
| 163 | _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; } | |
| 164 | _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; } | |
| 165 | _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; } | |
| 166 | }; | |
| 167 | } // namespace ranges | |
| 168 | ||
| 169 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 170 | ||
| 171 | _LIBCPP_END_NAMESPACE_STD | |
| 172 | ||
| 173 | _LIBCPP_POP_MACROS | |
| 174 | ||
| 175 | #endif // _LIBCPP___RANGES_COPYABLE_BOX_H |
lib/libcxx/include/__ranges/dangling.h created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___RANGES_DANGLING_H | |
| 11 | #define _LIBCPP___RANGES_DANGLING_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__ranges/access.h> | |
| 15 | #include <__ranges/concepts.h> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 28 | ||
| 29 | namespace ranges { | |
| 30 | struct dangling { | |
| 31 | dangling() = default; | |
| 32 | _LIBCPP_HIDE_FROM_ABI constexpr dangling(auto&&...) noexcept {} | |
| 33 | }; | |
| 34 | ||
| 35 | template <range _Rp> | |
| 36 | using borrowed_iterator_t = _If<borrowed_range<_Rp>, iterator_t<_Rp>, dangling>; | |
| 37 | ||
| 38 | // borrowed_subrange_t defined in <__ranges/subrange.h> | |
| 39 | } // namespace ranges | |
| 40 | ||
| 41 | #endif // !_LIBCPP_HAS_NO_RANGES | |
| 42 | ||
| 43 | _LIBCPP_END_NAMESPACE_STD | |
| 44 | ||
| 45 | _LIBCPP_POP_MACROS | |
| 46 | ||
| 47 | #endif // _LIBCPP___RANGES_DANGLING_H |
lib/libcxx/include/__ranges/data.h created+86| ... | ... | @@ -0,0 +1,86 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===------------------------ __ranges/data.h ------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_DATA_H | |
| 10 | #define _LIBCPP___RANGES_DATA_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__memory/pointer_traits.h> | |
| 16 | #include <__ranges/access.h> | |
| 17 | #include <__utility/forward.h> | |
| 18 | #include <concepts> | |
| 19 | #include <type_traits> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 31 | ||
| 32 | // clang-format off | |
| 33 | namespace ranges { | |
| 34 | // [range.prim.data] | |
| 35 | namespace __data { | |
| 36 | template <class _Tp> | |
| 37 | concept __ptr_to_object = is_pointer_v<_Tp> && is_object_v<remove_pointer_t<_Tp>>; | |
| 38 | ||
| 39 | template <class _Tp> | |
| 40 | concept __member_data = | |
| 41 | requires(_Tp&& __t) { | |
| 42 | { _VSTD::forward<_Tp>(__t) } -> __can_borrow; | |
| 43 | { __t.data() } -> __ptr_to_object; | |
| 44 | }; | |
| 45 | ||
| 46 | template <class _Tp> | |
| 47 | concept __ranges_begin_invocable = | |
| 48 | !__member_data<_Tp> && | |
| 49 | requires(_Tp&& __t) { | |
| 50 | { _VSTD::forward<_Tp>(__t) } -> __can_borrow; | |
| 51 | { ranges::begin(_VSTD::forward<_Tp>(__t)) } -> contiguous_iterator; | |
| 52 | }; | |
| 53 | ||
| 54 | struct __fn { | |
| 55 | template <__member_data _Tp> | |
| 56 | requires __can_borrow<_Tp> | |
| 57 | _LIBCPP_HIDE_FROM_ABI | |
| 58 | constexpr __ptr_to_object auto operator()(_Tp&& __t) const | |
| 59 | noexcept(noexcept(__t.data())) { | |
| 60 | return __t.data(); | |
| 61 | } | |
| 62 | ||
| 63 | template<__ranges_begin_invocable _Tp> | |
| 64 | requires __can_borrow<_Tp> | |
| 65 | _LIBCPP_HIDE_FROM_ABI | |
| 66 | constexpr __ptr_to_object auto operator()(_Tp&& __t) const | |
| 67 | noexcept(noexcept(_VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t))))) { | |
| 68 | return _VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t))); | |
| 69 | } | |
| 70 | }; | |
| 71 | } // end namespace __data | |
| 72 | ||
| 73 | inline namespace __cpo { | |
| 74 | inline constexpr const auto data = __data::__fn{}; | |
| 75 | } // namespace __cpo | |
| 76 | } // namespace ranges | |
| 77 | ||
| 78 | // clang-format off | |
| 79 | ||
| 80 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 81 | ||
| 82 | _LIBCPP_END_NAMESPACE_STD | |
| 83 | ||
| 84 | _LIBCPP_POP_MACROS | |
| 85 | ||
| 86 | #endif // _LIBCPP___RANGES_DATA_H |
lib/libcxx/include/__ranges/drop_view.h created+131| ... | ... | @@ -0,0 +1,131 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_DROP_VIEW_H | |
| 10 | #define _LIBCPP___RANGES_DROP_VIEW_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__iterator/next.h> | |
| 16 | #include <__ranges/access.h> | |
| 17 | #include <__ranges/all.h> | |
| 18 | #include <__ranges/concepts.h> | |
| 19 | #include <__ranges/enable_borrowed_range.h> | |
| 20 | #include <__ranges/non_propagating_cache.h> | |
| 21 | #include <__ranges/size.h> | |
| 22 | #include <__ranges/view_interface.h> | |
| 23 | #include <__utility/move.h> | |
| 24 | #include <concepts> | |
| 25 | #include <type_traits> | |
| 26 | ||
| 27 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 28 | #pragma GCC system_header | |
| 29 | #endif | |
| 30 | ||
| 31 | _LIBCPP_PUSH_MACROS | |
| 32 | #include <__undef_macros> | |
| 33 | ||
| 34 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 35 | ||
| 36 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 37 | ||
| 38 | namespace ranges { | |
| 39 | template<view _View> | |
| 40 | class drop_view | |
| 41 | : public view_interface<drop_view<_View>> | |
| 42 | { | |
| 43 | // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an | |
| 44 | // amortized O(1) begin() method. If this is an input_range, then we cannot cache | |
| 45 | // begin because begin is not equality preserving. | |
| 46 | // Note: drop_view<input-range>::begin() is still trivially amortized O(1) because | |
| 47 | // one can't call begin() on it more than once. | |
| 48 | static constexpr bool _UseCache = forward_range<_View> && !(random_access_range<_View> && sized_range<_View>); | |
| 49 | using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; | |
| 50 | [[no_unique_address]] _Cache __cached_begin_ = _Cache(); | |
| 51 | range_difference_t<_View> __count_ = 0; | |
| 52 | _View __base_ = _View(); | |
| 53 | ||
| 54 | public: | |
| 55 | drop_view() requires default_initializable<_View> = default; | |
| 56 | ||
| 57 | _LIBCPP_HIDE_FROM_ABI | |
| 58 | constexpr drop_view(_View __base, range_difference_t<_View> __count) | |
| 59 | : __count_(__count) | |
| 60 | , __base_(_VSTD::move(__base)) | |
| 61 | { | |
| 62 | _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero."); | |
| 63 | } | |
| 64 | ||
| 65 | _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } | |
| 66 | _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return _VSTD::move(__base_); } | |
| 67 | ||
| 68 | _LIBCPP_HIDE_FROM_ABI | |
| 69 | constexpr auto begin() | |
| 70 | requires (!(__simple_view<_View> && | |
| 71 | random_access_range<const _View> && sized_range<const _View>)) | |
| 72 | { | |
| 73 | if constexpr (_UseCache) | |
| 74 | if (__cached_begin_.__has_value()) | |
| 75 | return *__cached_begin_; | |
| 76 | ||
| 77 | auto __tmp = ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); | |
| 78 | if constexpr (_UseCache) | |
| 79 | __cached_begin_.__set(__tmp); | |
| 80 | return __tmp; | |
| 81 | } | |
| 82 | ||
| 83 | _LIBCPP_HIDE_FROM_ABI | |
| 84 | constexpr auto begin() const | |
| 85 | requires random_access_range<const _View> && sized_range<const _View> | |
| 86 | { | |
| 87 | return ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); | |
| 88 | } | |
| 89 | ||
| 90 | _LIBCPP_HIDE_FROM_ABI | |
| 91 | constexpr auto end() | |
| 92 | requires (!__simple_view<_View>) | |
| 93 | { return ranges::end(__base_); } | |
| 94 | ||
| 95 | _LIBCPP_HIDE_FROM_ABI | |
| 96 | constexpr auto end() const | |
| 97 | requires range<const _View> | |
| 98 | { return ranges::end(__base_); } | |
| 99 | ||
| 100 | _LIBCPP_HIDE_FROM_ABI | |
| 101 | static constexpr auto __size(auto& __self) { | |
| 102 | const auto __s = ranges::size(__self.__base_); | |
| 103 | const auto __c = static_cast<decltype(__s)>(__self.__count_); | |
| 104 | return __s < __c ? 0 : __s - __c; | |
| 105 | } | |
| 106 | ||
| 107 | _LIBCPP_HIDE_FROM_ABI | |
| 108 | constexpr auto size() | |
| 109 | requires sized_range<_View> | |
| 110 | { return __size(*this); } | |
| 111 | ||
| 112 | _LIBCPP_HIDE_FROM_ABI | |
| 113 | constexpr auto size() const | |
| 114 | requires sized_range<const _View> | |
| 115 | { return __size(*this); } | |
| 116 | }; | |
| 117 | ||
| 118 | template<class _Range> | |
| 119 | drop_view(_Range&&, range_difference_t<_Range>) -> drop_view<views::all_t<_Range>>; | |
| 120 | ||
| 121 | template<class _Tp> | |
| 122 | inline constexpr bool enable_borrowed_range<drop_view<_Tp>> = enable_borrowed_range<_Tp>; | |
| 123 | } // namespace ranges | |
| 124 | ||
| 125 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 126 | ||
| 127 | _LIBCPP_END_NAMESPACE_STD | |
| 128 | ||
| 129 | _LIBCPP_POP_MACROS | |
| 130 | ||
| 131 | #endif // _LIBCPP___RANGES_DROP_VIEW_H |
lib/libcxx/include/__ranges/empty.h created+86| ... | ... | @@ -0,0 +1,86 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_EMPTY_H | |
| 10 | #define _LIBCPP___RANGES_EMPTY_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__ranges/access.h> | |
| 15 | #include <__ranges/size.h> | |
| 16 | #include <__utility/forward.h> | |
| 17 | #include <type_traits> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 29 | ||
| 30 | // clang-format off | |
| 31 | namespace ranges { | |
| 32 | // [range.prim.empty] | |
| 33 | namespace __empty { | |
| 34 | template <class _Tp> | |
| 35 | concept __member_empty = requires(_Tp&& __t) { | |
| 36 | bool(_VSTD::forward<_Tp>(__t).empty()); | |
| 37 | }; | |
| 38 | ||
| 39 | template<class _Tp> | |
| 40 | concept __can_invoke_size = | |
| 41 | !__member_empty<_Tp> && | |
| 42 | requires(_Tp&& __t) { ranges::size(_VSTD::forward<_Tp>(__t)); }; | |
| 43 | ||
| 44 | template <class _Tp> | |
| 45 | concept __can_compare_begin_end = | |
| 46 | !__member_empty<_Tp> && | |
| 47 | !__can_invoke_size<_Tp> && | |
| 48 | requires(_Tp&& __t) { | |
| 49 | bool(ranges::begin(__t) == ranges::end(__t)); | |
| 50 | { ranges::begin(__t) } -> forward_iterator; | |
| 51 | }; | |
| 52 | ||
| 53 | struct __fn { | |
| 54 | template <__member_empty _Tp> | |
| 55 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const | |
| 56 | noexcept(noexcept(bool(__t.empty()))) { | |
| 57 | return __t.empty(); | |
| 58 | } | |
| 59 | ||
| 60 | template <__can_invoke_size _Tp> | |
| 61 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const | |
| 62 | noexcept(noexcept(ranges::size(_VSTD::forward<_Tp>(__t)))) { | |
| 63 | return ranges::size(_VSTD::forward<_Tp>(__t)) == 0; | |
| 64 | } | |
| 65 | ||
| 66 | template<__can_compare_begin_end _Tp> | |
| 67 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const | |
| 68 | noexcept(noexcept(bool(ranges::begin(__t) == ranges::end(__t)))) { | |
| 69 | return ranges::begin(__t) == ranges::end(__t); | |
| 70 | } | |
| 71 | }; | |
| 72 | } | |
| 73 | ||
| 74 | inline namespace __cpo { | |
| 75 | inline constexpr auto empty = __empty::__fn{}; | |
| 76 | } // namespace __cpo | |
| 77 | } // namespace ranges | |
| 78 | // clang-format off | |
| 79 | ||
| 80 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 81 | ||
| 82 | _LIBCPP_END_NAMESPACE_STD | |
| 83 | ||
| 84 | _LIBCPP_POP_MACROS | |
| 85 | ||
| 86 | #endif // _LIBCPP___RANGES_EMPTY_H |
lib/libcxx/include/__ranges/empty_view.h created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_EMPTY_VIEW_H | |
| 10 | #define _LIBCPP___RANGES_EMPTY_VIEW_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__ranges/view_interface.h> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 26 | ||
| 27 | namespace ranges { | |
| 28 | template<class _Tp> | |
| 29 | requires is_object_v<_Tp> | |
| 30 | class empty_view : public view_interface<empty_view<_Tp>> { | |
| 31 | public: | |
| 32 | _LIBCPP_HIDE_FROM_ABI static constexpr _Tp* begin() noexcept { return nullptr; } | |
| 33 | _LIBCPP_HIDE_FROM_ABI static constexpr _Tp* end() noexcept { return nullptr; } | |
| 34 | _LIBCPP_HIDE_FROM_ABI static constexpr _Tp* data() noexcept { return nullptr; } | |
| 35 | _LIBCPP_HIDE_FROM_ABI static constexpr size_t size() noexcept { return 0; } | |
| 36 | _LIBCPP_HIDE_FROM_ABI static constexpr bool empty() noexcept { return true; } | |
| 37 | }; | |
| 38 | } // namespace ranges | |
| 39 | ||
| 40 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 41 | ||
| 42 | _LIBCPP_END_NAMESPACE_STD | |
| 43 | ||
| 44 | _LIBCPP_POP_MACROS | |
| 45 | ||
| 46 | #endif // _LIBCPP___RANGES_EMPTY_VIEW_H |
lib/libcxx/include/__ranges/enable_borrowed_range.h created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===------------------ __ranges/enable_borrowed_range.h ------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H | |
| 11 | #define _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H | |
| 12 | ||
| 13 | // These customization variables are used in <span> and <string_view>. The | |
| 14 | // separate header is used to avoid including the entire <ranges> header in | |
| 15 | // <span> and <string_view>. | |
| 16 | ||
| 17 | #include <__config> | |
| 18 | ||
| 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 20 | #pragma GCC system_header | |
| 21 | #endif | |
| 22 | ||
| 23 | _LIBCPP_PUSH_MACROS | |
| 24 | #include <__undef_macros> | |
| 25 | ||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 27 | ||
| 28 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) | |
| 29 | ||
| 30 | namespace ranges | |
| 31 | { | |
| 32 | ||
| 33 | // [range.range], ranges | |
| 34 | ||
| 35 | template <class> | |
| 36 | inline constexpr bool enable_borrowed_range = false; | |
| 37 | ||
| 38 | } // namespace ranges | |
| 39 | ||
| 40 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) | |
| 41 | ||
| 42 | _LIBCPP_END_NAMESPACE_STD | |
| 43 | ||
| 44 | _LIBCPP_POP_MACROS | |
| 45 | ||
| 46 | #endif // _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H |
lib/libcxx/include/__ranges/enable_view.h created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___RANGES_ENABLE_VIEW_H | |
| 11 | #define _LIBCPP___RANGES_ENABLE_VIEW_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <concepts> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 26 | ||
| 27 | namespace ranges { | |
| 28 | ||
| 29 | struct view_base { }; | |
| 30 | ||
| 31 | template <class _Tp> | |
| 32 | inline constexpr bool enable_view = derived_from<_Tp, view_base>; | |
| 33 | ||
| 34 | } // end namespace ranges | |
| 35 | ||
| 36 | #endif // !_LIBCPP_HAS_NO_RANGES | |
| 37 | ||
| 38 | _LIBCPP_END_NAMESPACE_STD | |
| 39 | ||
| 40 | _LIBCPP_POP_MACROS | |
| 41 | ||
| 42 | #endif // _LIBCPP___RANGES_ENABLE_VIEW_H |
lib/libcxx/include/__ranges/non_propagating_cache.h created+99| ... | ... | @@ -0,0 +1,99 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_NON_PROPAGATING_CACHE_H | |
| 10 | #define _LIBCPP___RANGES_NON_PROPAGATING_CACHE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> // indirectly_readable | |
| 14 | #include <__iterator/iterator_traits.h> // iter_reference_t | |
| 15 | #include <__memory/addressof.h> | |
| 16 | #include <concepts> // constructible_from | |
| 17 | #include <optional> | |
| 18 | #include <type_traits> | |
| 19 | ||
| 20 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 21 | #pragma GCC system_header | |
| 22 | #endif | |
| 23 | ||
| 24 | _LIBCPP_PUSH_MACROS | |
| 25 | #include <__undef_macros> | |
| 26 | ||
| 27 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 28 | ||
| 29 | // clang-format off | |
| 30 | ||
| 31 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 32 | ||
| 33 | namespace ranges { | |
| 34 | // __non_propagating_cache is a helper type that allows storing an optional value in it, | |
| 35 | // but which does not copy the source's value when it is copy constructed/assigned to, | |
| 36 | // and which resets the source's value when it is moved-from. | |
| 37 | // | |
| 38 | // This type is used as an implementation detail of some views that need to cache the | |
| 39 | // result of `begin()` in order to provide an amortized O(1) begin() method. Typically, | |
| 40 | // we don't want to propagate the value of the cache upon copy because the cached iterator | |
| 41 | // may refer to internal details of the source view. | |
| 42 | template<class _Tp> | |
| 43 | requires is_object_v<_Tp> | |
| 44 | class _LIBCPP_TEMPLATE_VIS __non_propagating_cache { | |
| 45 | optional<_Tp> __value_ = nullopt; | |
| 46 | ||
| 47 | public: | |
| 48 | _LIBCPP_HIDE_FROM_ABI __non_propagating_cache() = default; | |
| 49 | ||
| 50 | _LIBCPP_HIDE_FROM_ABI | |
| 51 | constexpr __non_propagating_cache(__non_propagating_cache const&) noexcept | |
| 52 | : __value_(nullopt) | |
| 53 | { } | |
| 54 | ||
| 55 | _LIBCPP_HIDE_FROM_ABI | |
| 56 | constexpr __non_propagating_cache(__non_propagating_cache&& __other) noexcept | |
| 57 | : __value_(nullopt) | |
| 58 | { | |
| 59 | __other.__value_.reset(); | |
| 60 | } | |
| 61 | ||
| 62 | _LIBCPP_HIDE_FROM_ABI | |
| 63 | constexpr __non_propagating_cache& operator=(__non_propagating_cache const& __other) noexcept { | |
| 64 | if (this != _VSTD::addressof(__other)) { | |
| 65 | __value_.reset(); | |
| 66 | } | |
| 67 | return *this; | |
| 68 | } | |
| 69 | ||
| 70 | _LIBCPP_HIDE_FROM_ABI | |
| 71 | constexpr __non_propagating_cache& operator=(__non_propagating_cache&& __other) noexcept { | |
| 72 | __value_.reset(); | |
| 73 | __other.__value_.reset(); | |
| 74 | return *this; | |
| 75 | } | |
| 76 | ||
| 77 | _LIBCPP_HIDE_FROM_ABI | |
| 78 | constexpr _Tp& operator*() { return *__value_; } | |
| 79 | _LIBCPP_HIDE_FROM_ABI | |
| 80 | constexpr _Tp const& operator*() const { return *__value_; } | |
| 81 | ||
| 82 | _LIBCPP_HIDE_FROM_ABI | |
| 83 | constexpr bool __has_value() const { return __value_.has_value(); } | |
| 84 | _LIBCPP_HIDE_FROM_ABI | |
| 85 | constexpr void __set(_Tp const& __value) { __value_.emplace(__value); } | |
| 86 | _LIBCPP_HIDE_FROM_ABI | |
| 87 | constexpr void __set(_Tp&& __value) { __value_.emplace(_VSTD::move(__value)); } | |
| 88 | }; | |
| 89 | ||
| 90 | struct __empty_cache { }; | |
| 91 | } // namespace ranges | |
| 92 | ||
| 93 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) | |
| 94 | ||
| 95 | _LIBCPP_END_NAMESPACE_STD | |
| 96 | ||
| 97 | _LIBCPP_POP_MACROS | |
| 98 | ||
| 99 | #endif // _LIBCPP___RANGES_NON_PROPAGATING_CACHE_H |
lib/libcxx/include/__ranges/ref_view.h created+87| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_REF_VIEW_H | |
| 10 | #define _LIBCPP___RANGES_REF_VIEW_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/incrementable_traits.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__memory/addressof.h> | |
| 17 | #include <__ranges/access.h> | |
| 18 | #include <__ranges/concepts.h> | |
| 19 | #include <__ranges/data.h> | |
| 20 | #include <__ranges/empty.h> | |
| 21 | #include <__ranges/size.h> | |
| 22 | #include <__ranges/view_interface.h> | |
| 23 | #include <concepts> | |
| 24 | #include <type_traits> | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 27 | #pragma GCC system_header | |
| 28 | #endif | |
| 29 | ||
| 30 | _LIBCPP_PUSH_MACROS | |
| 31 | #include <__undef_macros> | |
| 32 | ||
| 33 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 34 | ||
| 35 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 36 | ||
| 37 | namespace ranges { | |
| 38 | template<range _Range> | |
| 39 | requires is_object_v<_Range> | |
| 40 | class ref_view : public view_interface<ref_view<_Range>> { | |
| 41 | _Range *__range_; | |
| 42 | ||
| 43 | static void __fun(_Range&); | |
| 44 | static void __fun(_Range&&) = delete; | |
| 45 | ||
| 46 | public: | |
| 47 | template<class _Tp> | |
| 48 | requires __different_from<_Tp, ref_view> && | |
| 49 | convertible_to<_Tp, _Range&> && requires { __fun(declval<_Tp>()); } | |
| 50 | _LIBCPP_HIDE_FROM_ABI | |
| 51 | constexpr ref_view(_Tp&& __t) | |
| 52 | : __range_(_VSTD::addressof(static_cast<_Range&>(_VSTD::forward<_Tp>(__t)))) | |
| 53 | {} | |
| 54 | ||
| 55 | _LIBCPP_HIDE_FROM_ABI constexpr _Range& base() const { return *__range_; } | |
| 56 | ||
| 57 | _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Range> begin() const { return ranges::begin(*__range_); } | |
| 58 | _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Range> end() const { return ranges::end(*__range_); } | |
| 59 | ||
| 60 | _LIBCPP_HIDE_FROM_ABI | |
| 61 | constexpr bool empty() const | |
| 62 | requires requires { ranges::empty(*__range_); } | |
| 63 | { return ranges::empty(*__range_); } | |
| 64 | ||
| 65 | _LIBCPP_HIDE_FROM_ABI | |
| 66 | constexpr auto size() const | |
| 67 | requires sized_range<_Range> | |
| 68 | { return ranges::size(*__range_); } | |
| 69 | ||
| 70 | _LIBCPP_HIDE_FROM_ABI | |
| 71 | constexpr auto data() const | |
| 72 | requires contiguous_range<_Range> | |
| 73 | { return ranges::data(*__range_); } | |
| 74 | }; | |
| 75 | ||
| 76 | template<class _Range> | |
| 77 | ref_view(_Range&) -> ref_view<_Range>; | |
| 78 | ||
| 79 | } // namespace ranges | |
| 80 | ||
| 81 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 82 | ||
| 83 | _LIBCPP_END_NAMESPACE_STD | |
| 84 | ||
| 85 | _LIBCPP_POP_MACROS | |
| 86 | ||
| 87 | #endif // _LIBCPP___RANGES_REF_VIEW_H |
lib/libcxx/include/__ranges/size.h created+132| ... | ... | @@ -0,0 +1,132 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_SIZE_H | |
| 10 | #define _LIBCPP___RANGES_SIZE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__ranges/access.h> | |
| 16 | #include <__utility/__decay_copy.h> | |
| 17 | #include <__utility/forward.h> | |
| 18 | #include <concepts> | |
| 19 | #include <type_traits> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 31 | ||
| 32 | // clang-format off | |
| 33 | namespace ranges { | |
| 34 | template<class> | |
| 35 | inline constexpr bool disable_sized_range = false; | |
| 36 | ||
| 37 | // [range.prim.size] | |
| 38 | namespace __size { | |
| 39 | void size(auto&) = delete; | |
| 40 | void size(const auto&) = delete; | |
| 41 | ||
| 42 | template <class _Tp> | |
| 43 | concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>; | |
| 44 | ||
| 45 | template <class _Tp> | |
| 46 | concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) { | |
| 47 | { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).size()) } -> __integer_like; | |
| 48 | }; | |
| 49 | ||
| 50 | template <class _Tp> | |
| 51 | concept __unqualified_size = | |
| 52 | __size_enabled<_Tp> && | |
| 53 | !__member_size<_Tp> && | |
| 54 | __class_or_enum<remove_cvref_t<_Tp>> && | |
| 55 | requires(_Tp&& __t) { | |
| 56 | { _VSTD::__decay_copy(size(_VSTD::forward<_Tp>(__t))) } -> __integer_like; | |
| 57 | }; | |
| 58 | ||
| 59 | template <class _Tp> | |
| 60 | concept __difference = | |
| 61 | !__member_size<_Tp> && | |
| 62 | !__unqualified_size<_Tp> && | |
| 63 | __class_or_enum<remove_cvref_t<_Tp>> && | |
| 64 | requires(_Tp&& __t) { | |
| 65 | { ranges::begin(__t) } -> forward_iterator; | |
| 66 | { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(declval<_Tp>()))>; | |
| 67 | }; | |
| 68 | ||
| 69 | struct __fn { | |
| 70 | template <class _Tp, size_t _Sz> | |
| 71 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept { | |
| 72 | return _Sz; | |
| 73 | } | |
| 74 | ||
| 75 | template <class _Tp, size_t _Sz> | |
| 76 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept { | |
| 77 | return _Sz; | |
| 78 | } | |
| 79 | ||
| 80 | template <__member_size _Tp> | |
| 81 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const | |
| 82 | noexcept(noexcept(_VSTD::forward<_Tp>(__t).size())) { | |
| 83 | return _VSTD::forward<_Tp>(__t).size(); | |
| 84 | } | |
| 85 | ||
| 86 | template <__unqualified_size _Tp> | |
| 87 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const | |
| 88 | noexcept(noexcept(size(_VSTD::forward<_Tp>(__t)))) { | |
| 89 | return size(_VSTD::forward<_Tp>(__t)); | |
| 90 | } | |
| 91 | ||
| 92 | template<__difference _Tp> | |
| 93 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const | |
| 94 | noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) { | |
| 95 | return _VSTD::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)); | |
| 96 | } | |
| 97 | }; | |
| 98 | } // end namespace __size | |
| 99 | ||
| 100 | inline namespace __cpo { | |
| 101 | inline constexpr auto size = __size::__fn{}; | |
| 102 | } // namespace __cpo | |
| 103 | ||
| 104 | namespace __ssize { | |
| 105 | struct __fn { | |
| 106 | template<class _Tp> | |
| 107 | requires requires (_Tp&& __t) { ranges::size(__t); } | |
| 108 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr integral auto operator()(_Tp&& __t) const | |
| 109 | noexcept(noexcept(ranges::size(__t))) { | |
| 110 | using _Signed = make_signed_t<decltype(ranges::size(__t))>; | |
| 111 | if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed)) | |
| 112 | return static_cast<ptrdiff_t>(ranges::size(__t)); | |
| 113 | else | |
| 114 | return static_cast<_Signed>(ranges::size(__t)); | |
| 115 | } | |
| 116 | }; | |
| 117 | } | |
| 118 | ||
| 119 | inline namespace __cpo { | |
| 120 | inline constexpr const auto ssize = __ssize::__fn{}; | |
| 121 | } // namespace __cpo | |
| 122 | } // namespace ranges | |
| 123 | ||
| 124 | // clang-format off | |
| 125 | ||
| 126 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 127 | ||
| 128 | _LIBCPP_END_NAMESPACE_STD | |
| 129 | ||
| 130 | _LIBCPP_POP_MACROS | |
| 131 | ||
| 132 | #endif // _LIBCPP___RANGES_SIZE_H |
lib/libcxx/include/__ranges/subrange.h created+267| ... | ... | @@ -0,0 +1,267 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_SUBRANGE_H | |
| 10 | #define _LIBCPP___RANGES_SUBRANGE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/incrementable_traits.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__iterator/advance.h> | |
| 17 | #include <__ranges/access.h> | |
| 18 | #include <__ranges/concepts.h> | |
| 19 | #include <__ranges/dangling.h> | |
| 20 | #include <__ranges/enable_borrowed_range.h> | |
| 21 | #include <__ranges/size.h> | |
| 22 | #include <__ranges/view_interface.h> | |
| 23 | #include <concepts> | |
| 24 | #include <type_traits> | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 27 | #pragma GCC system_header | |
| 28 | #endif | |
| 29 | ||
| 30 | _LIBCPP_PUSH_MACROS | |
| 31 | #include <__undef_macros> | |
| 32 | ||
| 33 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 34 | ||
| 35 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 36 | ||
| 37 | // clang-format off | |
| 38 | namespace ranges { | |
| 39 | template<class _From, class _To> | |
| 40 | concept __convertible_to_non_slicing = | |
| 41 | convertible_to<_From, _To> && | |
| 42 | // If they're both pointers, they must have the same element type. | |
| 43 | !(is_pointer_v<decay_t<_From>> && | |
| 44 | is_pointer_v<decay_t<_To>> && | |
| 45 | __different_from<remove_pointer_t<decay_t<_From>>, remove_pointer_t<decay_t<_To>>>); | |
| 46 | ||
| 47 | template<class _Tp> | |
| 48 | concept __pair_like = | |
| 49 | !is_reference_v<_Tp> && requires(_Tp __t) { | |
| 50 | typename tuple_size<_Tp>::type; // Ensures `tuple_size<T>` is complete. | |
| 51 | requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>; | |
| 52 | typename tuple_element_t<0, remove_const_t<_Tp>>; | |
| 53 | typename tuple_element_t<1, remove_const_t<_Tp>>; | |
| 54 | { _VSTD::get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>; | |
| 55 | { _VSTD::get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>; | |
| 56 | }; | |
| 57 | ||
| 58 | template<class _Pair, class _Iter, class _Sent> | |
| 59 | concept __pair_like_convertible_from = | |
| 60 | !range<_Pair> && __pair_like<_Pair> && | |
| 61 | constructible_from<_Pair, _Iter, _Sent> && | |
| 62 | __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && | |
| 63 | convertible_to<_Sent, tuple_element_t<1, _Pair>>; | |
| 64 | ||
| 65 | enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized }; | |
| 66 | ||
| 67 | template<class _Iter, class _Sent, bool> | |
| 68 | struct __subrange_base { | |
| 69 | static constexpr bool __store_size = false; | |
| 70 | _Iter __begin_ = _Iter(); | |
| 71 | _Sent __end_ = _Sent(); | |
| 72 | ||
| 73 | _LIBCPP_HIDE_FROM_ABI | |
| 74 | constexpr __subrange_base() = default; | |
| 75 | ||
| 76 | _LIBCPP_HIDE_FROM_ABI | |
| 77 | constexpr __subrange_base(_Iter __iter, _Sent __sent, make_unsigned_t<iter_difference_t<_Iter>> = 0) | |
| 78 | : __begin_(_VSTD::move(__iter)), __end_(__sent) { } | |
| 79 | }; | |
| 80 | ||
| 81 | template<class _Iter, class _Sent> | |
| 82 | struct __subrange_base<_Iter, _Sent, true> { | |
| 83 | static constexpr bool __store_size = true; | |
| 84 | _Iter __begin_ = _Iter(); | |
| 85 | _Sent __end_ = _Sent(); | |
| 86 | make_unsigned_t<iter_difference_t<_Iter>> __size_ = 0; | |
| 87 | ||
| 88 | _LIBCPP_HIDE_FROM_ABI | |
| 89 | constexpr __subrange_base() = default; | |
| 90 | ||
| 91 | _LIBCPP_HIDE_FROM_ABI | |
| 92 | constexpr __subrange_base(_Iter __iter, _Sent __sent, decltype(__size_) __size) | |
| 93 | : __begin_(_VSTD::move(__iter)), __end_(__sent), __size_(__size) { } | |
| 94 | }; | |
| 95 | ||
| 96 | template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter, | |
| 97 | subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> | |
| 98 | ? subrange_kind::sized | |
| 99 | : subrange_kind::unsized> | |
| 100 | requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) | |
| 101 | struct _LIBCPP_TEMPLATE_VIS subrange | |
| 102 | : public view_interface<subrange<_Iter, _Sent, _Kind>>, | |
| 103 | private __subrange_base<_Iter, _Sent, _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>> { | |
| 104 | ||
| 105 | using _Base = __subrange_base<_Iter, _Sent, _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>>; | |
| 106 | ||
| 107 | _LIBCPP_HIDE_FROM_ABI | |
| 108 | subrange() requires default_initializable<_Iter> = default; | |
| 109 | ||
| 110 | _LIBCPP_HIDE_FROM_ABI | |
| 111 | constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent) | |
| 112 | requires (!_Base::__store_size) | |
| 113 | : _Base(_VSTD::move(__iter), __sent) {} | |
| 114 | ||
| 115 | _LIBCPP_HIDE_FROM_ABI | |
| 116 | constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent, | |
| 117 | make_unsigned_t<iter_difference_t<_Iter>> __n) | |
| 118 | requires (_Kind == subrange_kind::sized) | |
| 119 | : _Base(_VSTD::move(__iter), __sent, __n) { } | |
| 120 | ||
| 121 | template<__different_from<subrange> _Range> | |
| 122 | requires borrowed_range<_Range> && | |
| 123 | __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && | |
| 124 | convertible_to<sentinel_t<_Range>, _Sent> | |
| 125 | _LIBCPP_HIDE_FROM_ABI | |
| 126 | constexpr subrange(_Range&& __range) | |
| 127 | requires (!_Base::__store_size) | |
| 128 | : subrange(ranges::begin(__range), ranges::end(__range)) { } | |
| 129 | ||
| 130 | template<__different_from<subrange> _Range> | |
| 131 | requires borrowed_range<_Range> && | |
| 132 | __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && | |
| 133 | convertible_to<sentinel_t<_Range>, _Sent> | |
| 134 | _LIBCPP_HIDE_FROM_ABI | |
| 135 | constexpr subrange(_Range&& __range) | |
| 136 | requires _Base::__store_size && sized_range<_Range> | |
| 137 | : subrange(__range, ranges::size(__range)) { } | |
| 138 | ||
| 139 | ||
| 140 | template<borrowed_range _Range> | |
| 141 | requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && | |
| 142 | convertible_to<sentinel_t<_Range>, _Sent> | |
| 143 | _LIBCPP_HIDE_FROM_ABI | |
| 144 | constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n) | |
| 145 | requires (_Kind == subrange_kind::sized) | |
| 146 | : subrange(ranges::begin(__range), ranges::end(__range), __n) { } | |
| 147 | ||
| 148 | template<__different_from<subrange> _Pair> | |
| 149 | requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&> | |
| 150 | _LIBCPP_HIDE_FROM_ABI | |
| 151 | constexpr operator _Pair() const { return _Pair(this->__begin_, this->__end_); } | |
| 152 | ||
| 153 | _LIBCPP_HIDE_FROM_ABI | |
| 154 | constexpr _Iter begin() const requires copyable<_Iter> { | |
| 155 | return this->__begin_; | |
| 156 | } | |
| 157 | ||
| 158 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() requires (!copyable<_Iter>) { | |
| 159 | return _VSTD::move(this->__begin_); | |
| 160 | } | |
| 161 | ||
| 162 | _LIBCPP_HIDE_FROM_ABI | |
| 163 | constexpr _Sent end() const { return this->__end_; } | |
| 164 | ||
| 165 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return this->__begin_ == this->__end_; } | |
| 166 | ||
| 167 | _LIBCPP_HIDE_FROM_ABI | |
| 168 | constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const | |
| 169 | requires (_Kind == subrange_kind::sized) | |
| 170 | { | |
| 171 | if constexpr (_Base::__store_size) | |
| 172 | return this->__size_; | |
| 173 | else | |
| 174 | return __to_unsigned_like(this->__end_ - this->__begin_); | |
| 175 | } | |
| 176 | ||
| 177 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const& | |
| 178 | requires forward_iterator<_Iter> { | |
| 179 | auto __tmp = *this; | |
| 180 | __tmp.advance(__n); | |
| 181 | return __tmp; | |
| 182 | } | |
| 183 | ||
| 184 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && { | |
| 185 | advance(__n); | |
| 186 | return _VSTD::move(*this); | |
| 187 | } | |
| 188 | ||
| 189 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const | |
| 190 | requires bidirectional_iterator<_Iter> { | |
| 191 | auto __tmp = *this; | |
| 192 | __tmp.advance(-__n); | |
| 193 | return __tmp; | |
| 194 | } | |
| 195 | ||
| 196 | _LIBCPP_HIDE_FROM_ABI | |
| 197 | constexpr subrange& advance(iter_difference_t<_Iter> __n) { | |
| 198 | if constexpr (bidirectional_iterator<_Iter>) { | |
| 199 | if (__n < 0) { | |
| 200 | ranges::advance(this->__begin_, __n); | |
| 201 | if constexpr (_Base::__store_size) | |
| 202 | this->__size_ += _VSTD::__to_unsigned_like(-__n); | |
| 203 | return *this; | |
| 204 | } | |
| 205 | } | |
| 206 | ||
| 207 | auto __d = __n - ranges::advance(this->__begin_, __n, this->__end_); | |
| 208 | if constexpr (_Base::__store_size) | |
| 209 | this->__size_ -= _VSTD::__to_unsigned_like(__d); | |
| 210 | return *this; | |
| 211 | } | |
| 212 | }; | |
| 213 | ||
| 214 | template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> | |
| 215 | subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>; | |
| 216 | ||
| 217 | template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> | |
| 218 | subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>) | |
| 219 | -> subrange<_Iter, _Sent, subrange_kind::sized>; | |
| 220 | ||
| 221 | template<borrowed_range _Range> | |
| 222 | subrange(_Range&&) -> subrange<iterator_t<_Range>, sentinel_t<_Range>, | |
| 223 | (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>) | |
| 224 | ? subrange_kind::sized : subrange_kind::unsized>; | |
| 225 | ||
| 226 | template<borrowed_range _Range> | |
| 227 | subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>) | |
| 228 | -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>; | |
| 229 | ||
| 230 | template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> | |
| 231 | requires (_Index < 2) | |
| 232 | _LIBCPP_HIDE_FROM_ABI | |
| 233 | constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) { | |
| 234 | if constexpr (_Index == 0) | |
| 235 | return __subrange.begin(); | |
| 236 | else | |
| 237 | return __subrange.end(); | |
| 238 | } | |
| 239 | ||
| 240 | template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> | |
| 241 | requires (_Index < 2) | |
| 242 | _LIBCPP_HIDE_FROM_ABI | |
| 243 | constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) { | |
| 244 | if constexpr (_Index == 0) | |
| 245 | return __subrange.begin(); | |
| 246 | else | |
| 247 | return __subrange.end(); | |
| 248 | } | |
| 249 | ||
| 250 | template<class _Ip, class _Sp, subrange_kind _Kp> | |
| 251 | inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true; | |
| 252 | ||
| 253 | template<range _Rp> | |
| 254 | using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp> >, dangling>; | |
| 255 | } // namespace ranges | |
| 256 | ||
| 257 | using ranges::get; | |
| 258 | ||
| 259 | // clang-format off | |
| 260 | ||
| 261 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 262 | ||
| 263 | _LIBCPP_END_NAMESPACE_STD | |
| 264 | ||
| 265 | _LIBCPP_POP_MACROS | |
| 266 | ||
| 267 | #endif // _LIBCPP___RANGES_SUBRANGE_H |
lib/libcxx/include/__ranges/transform_view.h created+408| ... | ... | @@ -0,0 +1,408 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_TRANSFORM_VIEW_H | |
| 10 | #define _LIBCPP___RANGES_TRANSFORM_VIEW_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/iter_swap.h> | |
| 15 | #include <__iterator/iterator_traits.h> | |
| 16 | #include <__ranges/access.h> | |
| 17 | #include <__ranges/all.h> | |
| 18 | #include <__ranges/concepts.h> | |
| 19 | #include <__ranges/copyable_box.h> | |
| 20 | #include <__ranges/empty.h> | |
| 21 | #include <__ranges/size.h> | |
| 22 | #include <__ranges/view_interface.h> | |
| 23 | #include <concepts> | |
| 24 | #include <type_traits> | |
| 25 | ||
| 26 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 27 | #pragma GCC system_header | |
| 28 | #endif | |
| 29 | ||
| 30 | _LIBCPP_PUSH_MACROS | |
| 31 | #include <__undef_macros> | |
| 32 | ||
| 33 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 34 | ||
| 35 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 36 | ||
| 37 | namespace ranges { | |
| 38 | ||
| 39 | template<class _View, class _Fn> | |
| 40 | concept __transform_view_constraints = | |
| 41 | view<_View> && is_object_v<_Fn> && | |
| 42 | regular_invocable<_Fn&, range_reference_t<_View>> && | |
| 43 | __referenceable<invoke_result_t<_Fn&, range_reference_t<_View>>>; | |
| 44 | ||
| 45 | template<input_range _View, copy_constructible _Fn> | |
| 46 | requires __transform_view_constraints<_View, _Fn> | |
| 47 | class transform_view : public view_interface<transform_view<_View, _Fn>> { | |
| 48 | template<bool> class __iterator; | |
| 49 | template<bool> class __sentinel; | |
| 50 | ||
| 51 | [[no_unique_address]] __copyable_box<_Fn> __func_; | |
| 52 | [[no_unique_address]] _View __base_ = _View(); | |
| 53 | ||
| 54 | public: | |
| 55 | _LIBCPP_HIDE_FROM_ABI | |
| 56 | transform_view() | |
| 57 | requires default_initializable<_View> && default_initializable<_Fn> = default; | |
| 58 | ||
| 59 | _LIBCPP_HIDE_FROM_ABI | |
| 60 | constexpr transform_view(_View __base, _Fn __func) | |
| 61 | : __func_(_VSTD::in_place, _VSTD::move(__func)), __base_(_VSTD::move(__base)) {} | |
| 62 | ||
| 63 | _LIBCPP_HIDE_FROM_ABI | |
| 64 | constexpr _View base() const& requires copy_constructible<_View> { return __base_; } | |
| 65 | _LIBCPP_HIDE_FROM_ABI | |
| 66 | constexpr _View base() && { return _VSTD::move(__base_); } | |
| 67 | ||
| 68 | _LIBCPP_HIDE_FROM_ABI | |
| 69 | constexpr __iterator<false> begin() { | |
| 70 | return __iterator<false>{*this, ranges::begin(__base_)}; | |
| 71 | } | |
| 72 | _LIBCPP_HIDE_FROM_ABI | |
| 73 | constexpr __iterator<true> begin() const | |
| 74 | requires range<const _View> && | |
| 75 | regular_invocable<const _Fn&, range_reference_t<const _View>> | |
| 76 | { | |
| 77 | return __iterator<true>(*this, ranges::begin(__base_)); | |
| 78 | } | |
| 79 | ||
| 80 | _LIBCPP_HIDE_FROM_ABI | |
| 81 | constexpr __sentinel<false> end() { | |
| 82 | return __sentinel<false>(ranges::end(__base_)); | |
| 83 | } | |
| 84 | _LIBCPP_HIDE_FROM_ABI | |
| 85 | constexpr __iterator<false> end() | |
| 86 | requires common_range<_View> | |
| 87 | { | |
| 88 | return __iterator<false>(*this, ranges::end(__base_)); | |
| 89 | } | |
| 90 | _LIBCPP_HIDE_FROM_ABI | |
| 91 | constexpr __sentinel<true> end() const | |
| 92 | requires range<const _View> && | |
| 93 | regular_invocable<const _Fn&, range_reference_t<const _View>> | |
| 94 | { | |
| 95 | return __sentinel<true>(ranges::end(__base_)); | |
| 96 | } | |
| 97 | _LIBCPP_HIDE_FROM_ABI | |
| 98 | constexpr __iterator<true> end() const | |
| 99 | requires common_range<const _View> && | |
| 100 | regular_invocable<const _Fn&, range_reference_t<const _View>> | |
| 101 | { | |
| 102 | return __iterator<true>(*this, ranges::end(__base_)); | |
| 103 | } | |
| 104 | ||
| 105 | _LIBCPP_HIDE_FROM_ABI | |
| 106 | constexpr auto size() requires sized_range<_View> { return ranges::size(__base_); } | |
| 107 | _LIBCPP_HIDE_FROM_ABI | |
| 108 | constexpr auto size() const requires sized_range<const _View> { return ranges::size(__base_); } | |
| 109 | }; | |
| 110 | ||
| 111 | template<class _Range, class _Fn> | |
| 112 | transform_view(_Range&&, _Fn) -> transform_view<views::all_t<_Range>, _Fn>; | |
| 113 | ||
| 114 | template<class _View> | |
| 115 | struct __transform_view_iterator_concept { using type = input_iterator_tag; }; | |
| 116 | ||
| 117 | template<random_access_range _View> | |
| 118 | struct __transform_view_iterator_concept<_View> { using type = random_access_iterator_tag; }; | |
| 119 | ||
| 120 | template<bidirectional_range _View> | |
| 121 | struct __transform_view_iterator_concept<_View> { using type = bidirectional_iterator_tag; }; | |
| 122 | ||
| 123 | template<forward_range _View> | |
| 124 | struct __transform_view_iterator_concept<_View> { using type = forward_iterator_tag; }; | |
| 125 | ||
| 126 | template<class, class> | |
| 127 | struct __transform_view_iterator_category_base {}; | |
| 128 | ||
| 129 | template<forward_range _View, class _Fn> | |
| 130 | struct __transform_view_iterator_category_base<_View, _Fn> { | |
| 131 | using _Cat = typename iterator_traits<iterator_t<_View>>::iterator_category; | |
| 132 | ||
| 133 | using iterator_category = conditional_t< | |
| 134 | is_lvalue_reference_v<invoke_result_t<_Fn&, range_reference_t<_View>>>, | |
| 135 | conditional_t< | |
| 136 | derived_from<_Cat, contiguous_iterator_tag>, | |
| 137 | random_access_iterator_tag, | |
| 138 | _Cat | |
| 139 | >, | |
| 140 | input_iterator_tag | |
| 141 | >; | |
| 142 | }; | |
| 143 | ||
| 144 | template<input_range _View, copy_constructible _Fn> | |
| 145 | requires __transform_view_constraints<_View, _Fn> | |
| 146 | template<bool _Const> | |
| 147 | class transform_view<_View, _Fn>::__iterator | |
| 148 | : public __transform_view_iterator_category_base<_View, _Fn> { | |
| 149 | ||
| 150 | using _Parent = __maybe_const<_Const, transform_view>; | |
| 151 | using _Base = __maybe_const<_Const, _View>; | |
| 152 | ||
| 153 | _Parent *__parent_ = nullptr; | |
| 154 | ||
| 155 | template<bool> | |
| 156 | friend class transform_view<_View, _Fn>::__iterator; | |
| 157 | ||
| 158 | template<bool> | |
| 159 | friend class transform_view<_View, _Fn>::__sentinel; | |
| 160 | ||
| 161 | public: | |
| 162 | iterator_t<_Base> __current_ = iterator_t<_Base>(); | |
| 163 | ||
| 164 | using iterator_concept = typename __transform_view_iterator_concept<_View>::type; | |
| 165 | using value_type = remove_cvref_t<invoke_result_t<_Fn&, range_reference_t<_Base>>>; | |
| 166 | using difference_type = range_difference_t<_Base>; | |
| 167 | ||
| 168 | _LIBCPP_HIDE_FROM_ABI | |
| 169 | __iterator() requires default_initializable<iterator_t<_Base>> = default; | |
| 170 | ||
| 171 | _LIBCPP_HIDE_FROM_ABI | |
| 172 | constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current) | |
| 173 | : __parent_(_VSTD::addressof(__parent)), __current_(_VSTD::move(__current)) {} | |
| 174 | ||
| 175 | // Note: `__i` should always be `__iterator<false>`, but directly using | |
| 176 | // `__iterator<false>` is ill-formed when `_Const` is false | |
| 177 | // (see http://wg21.link/class.copy.ctor#5). | |
| 178 | _LIBCPP_HIDE_FROM_ABI | |
| 179 | constexpr __iterator(__iterator<!_Const> __i) | |
| 180 | requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> | |
| 181 | : __parent_(__i.__parent_), __current_(_VSTD::move(__i.__current_)) {} | |
| 182 | ||
| 183 | _LIBCPP_HIDE_FROM_ABI | |
| 184 | constexpr iterator_t<_Base> base() const& | |
| 185 | requires copyable<iterator_t<_Base>> | |
| 186 | { | |
| 187 | return __current_; | |
| 188 | } | |
| 189 | ||
| 190 | _LIBCPP_HIDE_FROM_ABI | |
| 191 | constexpr iterator_t<_Base> base() && { | |
| 192 | return _VSTD::move(__current_); | |
| 193 | } | |
| 194 | ||
| 195 | _LIBCPP_HIDE_FROM_ABI | |
| 196 | constexpr decltype(auto) operator*() const | |
| 197 | noexcept(noexcept(_VSTD::invoke(*__parent_->__func_, *__current_))) | |
| 198 | { | |
| 199 | return _VSTD::invoke(*__parent_->__func_, *__current_); | |
| 200 | } | |
| 201 | ||
| 202 | _LIBCPP_HIDE_FROM_ABI | |
| 203 | constexpr __iterator& operator++() { | |
| 204 | ++__current_; | |
| 205 | return *this; | |
| 206 | } | |
| 207 | ||
| 208 | _LIBCPP_HIDE_FROM_ABI | |
| 209 | constexpr void operator++(int) { ++__current_; } | |
| 210 | ||
| 211 | _LIBCPP_HIDE_FROM_ABI | |
| 212 | constexpr __iterator operator++(int) | |
| 213 | requires forward_range<_Base> | |
| 214 | { | |
| 215 | auto __tmp = *this; | |
| 216 | ++*this; | |
| 217 | return __tmp; | |
| 218 | } | |
| 219 | ||
| 220 | _LIBCPP_HIDE_FROM_ABI | |
| 221 | constexpr __iterator& operator--() | |
| 222 | requires bidirectional_range<_Base> | |
| 223 | { | |
| 224 | --__current_; | |
| 225 | return *this; | |
| 226 | } | |
| 227 | ||
| 228 | _LIBCPP_HIDE_FROM_ABI | |
| 229 | constexpr __iterator operator--(int) | |
| 230 | requires bidirectional_range<_Base> | |
| 231 | { | |
| 232 | auto __tmp = *this; | |
| 233 | --*this; | |
| 234 | return __tmp; | |
| 235 | } | |
| 236 | ||
| 237 | _LIBCPP_HIDE_FROM_ABI | |
| 238 | constexpr __iterator& operator+=(difference_type __n) | |
| 239 | requires random_access_range<_Base> | |
| 240 | { | |
| 241 | __current_ += __n; | |
| 242 | return *this; | |
| 243 | } | |
| 244 | ||
| 245 | _LIBCPP_HIDE_FROM_ABI | |
| 246 | constexpr __iterator& operator-=(difference_type __n) | |
| 247 | requires random_access_range<_Base> | |
| 248 | { | |
| 249 | __current_ -= __n; | |
| 250 | return *this; | |
| 251 | } | |
| 252 | ||
| 253 | _LIBCPP_HIDE_FROM_ABI | |
| 254 | constexpr decltype(auto) operator[](difference_type __n) const | |
| 255 | noexcept(noexcept(_VSTD::invoke(*__parent_->__func_, __current_[__n]))) | |
| 256 | requires random_access_range<_Base> | |
| 257 | { | |
| 258 | return _VSTD::invoke(*__parent_->__func_, __current_[__n]); | |
| 259 | } | |
| 260 | ||
| 261 | _LIBCPP_HIDE_FROM_ABI | |
| 262 | friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) | |
| 263 | requires equality_comparable<iterator_t<_Base>> | |
| 264 | { | |
| 265 | return __x.__current_ == __y.__current_; | |
| 266 | } | |
| 267 | ||
| 268 | _LIBCPP_HIDE_FROM_ABI | |
| 269 | friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) | |
| 270 | requires random_access_range<_Base> | |
| 271 | { | |
| 272 | return __x.__current_ < __y.__current_; | |
| 273 | } | |
| 274 | ||
| 275 | _LIBCPP_HIDE_FROM_ABI | |
| 276 | friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) | |
| 277 | requires random_access_range<_Base> | |
| 278 | { | |
| 279 | return __x.__current_ > __y.__current_; | |
| 280 | } | |
| 281 | ||
| 282 | _LIBCPP_HIDE_FROM_ABI | |
| 283 | friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) | |
| 284 | requires random_access_range<_Base> | |
| 285 | { | |
| 286 | return __x.__current_ <= __y.__current_; | |
| 287 | } | |
| 288 | ||
| 289 | _LIBCPP_HIDE_FROM_ABI | |
| 290 | friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) | |
| 291 | requires random_access_range<_Base> | |
| 292 | { | |
| 293 | return __x.__current_ >= __y.__current_; | |
| 294 | } | |
| 295 | ||
| 296 | // TODO: Fix this as soon as soon as three_way_comparable is implemented. | |
| 297 | // _LIBCPP_HIDE_FROM_ABI | |
| 298 | // friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) | |
| 299 | // requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> | |
| 300 | // { | |
| 301 | // return __x.__current_ <=> __y.__current_; | |
| 302 | // } | |
| 303 | ||
| 304 | _LIBCPP_HIDE_FROM_ABI | |
| 305 | friend constexpr __iterator operator+(__iterator __i, difference_type __n) | |
| 306 | requires random_access_range<_Base> | |
| 307 | { | |
| 308 | return __iterator{*__i.__parent_, __i.__current_ + __n}; | |
| 309 | } | |
| 310 | ||
| 311 | _LIBCPP_HIDE_FROM_ABI | |
| 312 | friend constexpr __iterator operator+(difference_type __n, __iterator __i) | |
| 313 | requires random_access_range<_Base> | |
| 314 | { | |
| 315 | return __iterator{*__i.__parent_, __i.__current_ + __n}; | |
| 316 | } | |
| 317 | ||
| 318 | _LIBCPP_HIDE_FROM_ABI | |
| 319 | friend constexpr __iterator operator-(__iterator __i, difference_type __n) | |
| 320 | requires random_access_range<_Base> | |
| 321 | { | |
| 322 | return __iterator{*__i.__parent_, __i.__current_ - __n}; | |
| 323 | } | |
| 324 | ||
| 325 | _LIBCPP_HIDE_FROM_ABI | |
| 326 | friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) | |
| 327 | requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> | |
| 328 | { | |
| 329 | return __x.__current_ - __y.__current_; | |
| 330 | } | |
| 331 | ||
| 332 | _LIBCPP_HIDE_FROM_ABI | |
| 333 | friend constexpr decltype(auto) iter_move(const __iterator& __i) | |
| 334 | noexcept(noexcept(*__i)) | |
| 335 | { | |
| 336 | if constexpr (is_lvalue_reference_v<decltype(*__i)>) | |
| 337 | return _VSTD::move(*__i); | |
| 338 | else | |
| 339 | return *__i; | |
| 340 | } | |
| 341 | }; | |
| 342 | ||
| 343 | template<input_range _View, copy_constructible _Fn> | |
| 344 | requires __transform_view_constraints<_View, _Fn> | |
| 345 | template<bool _Const> | |
| 346 | class transform_view<_View, _Fn>::__sentinel { | |
| 347 | using _Parent = __maybe_const<_Const, transform_view>; | |
| 348 | using _Base = __maybe_const<_Const, _View>; | |
| 349 | ||
| 350 | sentinel_t<_Base> __end_ = sentinel_t<_Base>(); | |
| 351 | ||
| 352 | template<bool> | |
| 353 | friend class transform_view<_View, _Fn>::__iterator; | |
| 354 | ||
| 355 | template<bool> | |
| 356 | friend class transform_view<_View, _Fn>::__sentinel; | |
| 357 | ||
| 358 | public: | |
| 359 | _LIBCPP_HIDE_FROM_ABI | |
| 360 | __sentinel() = default; | |
| 361 | ||
| 362 | _LIBCPP_HIDE_FROM_ABI | |
| 363 | constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {} | |
| 364 | ||
| 365 | // Note: `__i` should always be `__sentinel<false>`, but directly using | |
| 366 | // `__sentinel<false>` is ill-formed when `_Const` is false | |
| 367 | // (see http://wg21.link/class.copy.ctor#5). | |
| 368 | _LIBCPP_HIDE_FROM_ABI | |
| 369 | constexpr __sentinel(__sentinel<!_Const> __i) | |
| 370 | requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> | |
| 371 | : __end_(_VSTD::move(__i.__end_)) {} | |
| 372 | ||
| 373 | _LIBCPP_HIDE_FROM_ABI | |
| 374 | constexpr sentinel_t<_Base> base() const { return __end_; } | |
| 375 | ||
| 376 | template<bool _OtherConst> | |
| 377 | requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> | |
| 378 | _LIBCPP_HIDE_FROM_ABI | |
| 379 | friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { | |
| 380 | return __x.__current_ == __y.__end_; | |
| 381 | } | |
| 382 | ||
| 383 | template<bool _OtherConst> | |
| 384 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> | |
| 385 | _LIBCPP_HIDE_FROM_ABI | |
| 386 | friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> | |
| 387 | operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { | |
| 388 | return __x.__current_ - __y.__end_; | |
| 389 | } | |
| 390 | ||
| 391 | template<bool _OtherConst> | |
| 392 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> | |
| 393 | _LIBCPP_HIDE_FROM_ABI | |
| 394 | friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> | |
| 395 | operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { | |
| 396 | return __x.__end_ - __y.__current_; | |
| 397 | } | |
| 398 | }; | |
| 399 | ||
| 400 | } // namespace ranges | |
| 401 | ||
| 402 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 403 | ||
| 404 | _LIBCPP_END_NAMESPACE_STD | |
| 405 | ||
| 406 | _LIBCPP_POP_MACROS | |
| 407 | ||
| 408 | #endif // _LIBCPP___RANGES_TRANSFORM_VIEW_H |
lib/libcxx/include/__ranges/view_interface.h created+198| ... | ... | @@ -0,0 +1,198 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H | |
| 10 | #define _LIBCPP___RANGES_VIEW_INTERFACE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__iterator/concepts.h> | |
| 14 | #include <__iterator/iterator_traits.h> | |
| 15 | #include <__iterator/prev.h> | |
| 16 | #include <__memory/pointer_traits.h> | |
| 17 | #include <__ranges/access.h> | |
| 18 | #include <__ranges/concepts.h> | |
| 19 | #include <__ranges/empty.h> | |
| 20 | #include <__ranges/enable_view.h> | |
| 21 | #include <concepts> | |
| 22 | #include <type_traits> | |
| 23 | ||
| 24 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 25 | #pragma GCC system_header | |
| 26 | #endif | |
| 27 | ||
| 28 | _LIBCPP_PUSH_MACROS | |
| 29 | #include <__undef_macros> | |
| 30 | ||
| 31 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 32 | ||
| 33 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 34 | ||
| 35 | namespace ranges { | |
| 36 | ||
| 37 | template<class _Tp> | |
| 38 | concept __can_empty = requires(_Tp __t) { ranges::empty(__t); }; | |
| 39 | ||
| 40 | template<class _Tp> | |
| 41 | void __implicitly_convert_to(type_identity_t<_Tp>) noexcept; | |
| 42 | ||
| 43 | template<class _Derived> | |
| 44 | requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> | |
| 45 | class view_interface : public view_base { | |
| 46 | _LIBCPP_HIDE_FROM_ABI | |
| 47 | constexpr _Derived& __derived() noexcept { | |
| 48 | return static_cast<_Derived&>(*this); | |
| 49 | } | |
| 50 | ||
| 51 | _LIBCPP_HIDE_FROM_ABI | |
| 52 | constexpr _Derived const& __derived() const noexcept { | |
| 53 | return static_cast<_Derived const&>(*this); | |
| 54 | } | |
| 55 | ||
| 56 | public: | |
| 57 | template<class _D2 = _Derived> | |
| 58 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() | |
| 59 | noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived())))) | |
| 60 | requires forward_range<_D2> | |
| 61 | { | |
| 62 | return ranges::begin(__derived()) == ranges::end(__derived()); | |
| 63 | } | |
| 64 | ||
| 65 | template<class _D2 = _Derived> | |
| 66 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const | |
| 67 | noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived())))) | |
| 68 | requires forward_range<const _D2> | |
| 69 | { | |
| 70 | return ranges::begin(__derived()) == ranges::end(__derived()); | |
| 71 | } | |
| 72 | ||
| 73 | template<class _D2 = _Derived> | |
| 74 | _LIBCPP_HIDE_FROM_ABI | |
| 75 | constexpr explicit operator bool() | |
| 76 | noexcept(noexcept(ranges::empty(declval<_D2>()))) | |
| 77 | requires __can_empty<_D2> | |
| 78 | { | |
| 79 | return !ranges::empty(__derived()); | |
| 80 | } | |
| 81 | ||
| 82 | template<class _D2 = _Derived> | |
| 83 | _LIBCPP_HIDE_FROM_ABI | |
| 84 | constexpr explicit operator bool() const | |
| 85 | noexcept(noexcept(ranges::empty(declval<const _D2>()))) | |
| 86 | requires __can_empty<const _D2> | |
| 87 | { | |
| 88 | return !ranges::empty(__derived()); | |
| 89 | } | |
| 90 | ||
| 91 | template<class _D2 = _Derived> | |
| 92 | _LIBCPP_HIDE_FROM_ABI | |
| 93 | constexpr auto data() | |
| 94 | noexcept(noexcept(_VSTD::to_address(ranges::begin(__derived())))) | |
| 95 | requires contiguous_iterator<iterator_t<_D2>> | |
| 96 | { | |
| 97 | return _VSTD::to_address(ranges::begin(__derived())); | |
| 98 | } | |
| 99 | ||
| 100 | template<class _D2 = _Derived> | |
| 101 | _LIBCPP_HIDE_FROM_ABI | |
| 102 | constexpr auto data() const | |
| 103 | noexcept(noexcept(_VSTD::to_address(ranges::begin(__derived())))) | |
| 104 | requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>> | |
| 105 | { | |
| 106 | return _VSTD::to_address(ranges::begin(__derived())); | |
| 107 | } | |
| 108 | ||
| 109 | template<class _D2 = _Derived> | |
| 110 | _LIBCPP_HIDE_FROM_ABI | |
| 111 | constexpr auto size() | |
| 112 | noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived()))) | |
| 113 | requires forward_range<_D2> | |
| 114 | && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>> | |
| 115 | { | |
| 116 | return ranges::end(__derived()) - ranges::begin(__derived()); | |
| 117 | } | |
| 118 | ||
| 119 | template<class _D2 = _Derived> | |
| 120 | _LIBCPP_HIDE_FROM_ABI | |
| 121 | constexpr auto size() const | |
| 122 | noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived()))) | |
| 123 | requires forward_range<const _D2> | |
| 124 | && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>> | |
| 125 | { | |
| 126 | return ranges::end(__derived()) - ranges::begin(__derived()); | |
| 127 | } | |
| 128 | ||
| 129 | template<class _D2 = _Derived> | |
| 130 | _LIBCPP_HIDE_FROM_ABI | |
| 131 | constexpr decltype(auto) front() | |
| 132 | noexcept(noexcept(*ranges::begin(__derived()))) | |
| 133 | requires forward_range<_D2> | |
| 134 | { | |
| 135 | _LIBCPP_ASSERT(!empty(), | |
| 136 | "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); | |
| 137 | return *ranges::begin(__derived()); | |
| 138 | } | |
| 139 | ||
| 140 | template<class _D2 = _Derived> | |
| 141 | _LIBCPP_HIDE_FROM_ABI | |
| 142 | constexpr decltype(auto) front() const | |
| 143 | noexcept(noexcept(*ranges::begin(__derived()))) | |
| 144 | requires forward_range<const _D2> | |
| 145 | { | |
| 146 | _LIBCPP_ASSERT(!empty(), | |
| 147 | "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); | |
| 148 | return *ranges::begin(__derived()); | |
| 149 | } | |
| 150 | ||
| 151 | template<class _D2 = _Derived> | |
| 152 | _LIBCPP_HIDE_FROM_ABI | |
| 153 | constexpr decltype(auto) back() | |
| 154 | noexcept(noexcept(*ranges::prev(ranges::end(__derived())))) | |
| 155 | requires bidirectional_range<_D2> && common_range<_D2> | |
| 156 | { | |
| 157 | _LIBCPP_ASSERT(!empty(), | |
| 158 | "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); | |
| 159 | return *ranges::prev(ranges::end(__derived())); | |
| 160 | } | |
| 161 | ||
| 162 | template<class _D2 = _Derived> | |
| 163 | _LIBCPP_HIDE_FROM_ABI | |
| 164 | constexpr decltype(auto) back() const | |
| 165 | noexcept(noexcept(*ranges::prev(ranges::end(__derived())))) | |
| 166 | requires bidirectional_range<const _D2> && common_range<const _D2> | |
| 167 | { | |
| 168 | _LIBCPP_ASSERT(!empty(), | |
| 169 | "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); | |
| 170 | return *ranges::prev(ranges::end(__derived())); | |
| 171 | } | |
| 172 | ||
| 173 | template<random_access_range _RARange = _Derived> | |
| 174 | _LIBCPP_HIDE_FROM_ABI | |
| 175 | constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) | |
| 176 | noexcept(noexcept(ranges::begin(__derived())[__index])) | |
| 177 | { | |
| 178 | return ranges::begin(__derived())[__index]; | |
| 179 | } | |
| 180 | ||
| 181 | template<random_access_range _RARange = const _Derived> | |
| 182 | _LIBCPP_HIDE_FROM_ABI | |
| 183 | constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const | |
| 184 | noexcept(noexcept(ranges::begin(__derived())[__index])) | |
| 185 | { | |
| 186 | return ranges::begin(__derived())[__index]; | |
| 187 | } | |
| 188 | }; | |
| 189 | ||
| 190 | } | |
| 191 | ||
| 192 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 193 | ||
| 194 | _LIBCPP_END_NAMESPACE_STD | |
| 195 | ||
| 196 | _LIBCPP_POP_MACROS | |
| 197 | ||
| 198 | #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H |
lib/libcxx/include/__split_buffer+7-6| ... | ... | @@ -3,8 +3,9 @@ |
| 3 | 3 | #define _LIBCPP_SPLIT_BUFFER |
| 4 | 4 | |
| 5 | 5 | #include <__config> |
| 6 | #include <type_traits> | |
| 6 | #include <__utility/forward.h> | |
| 7 | 7 | #include <algorithm> |
| 8 | #include <type_traits> | |
| 8 | 9 | |
| 9 | 10 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 10 | 11 | #pragma GCC system_header |
| ... | ... | @@ -20,8 +21,8 @@ template <bool> |
| 20 | 21 | class __split_buffer_common |
| 21 | 22 | { |
| 22 | 23 | protected: |
| 23 | void __throw_length_error() const; | |
| 24 | void __throw_out_of_range() const; | |
| 24 | _LIBCPP_NORETURN void __throw_length_error() const; | |
| 25 | _LIBCPP_NORETURN void __throw_out_of_range() const; | |
| 25 | 26 | }; |
| 26 | 27 | |
| 27 | 28 | template <class _Tp, class _Allocator = allocator<_Tp> > |
| ... | ... | @@ -444,7 +445,7 @@ __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT |
| 444 | 445 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 445 | 446 | try |
| 446 | 447 | { |
| 447 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 448 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 448 | 449 | __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc()); |
| 449 | 450 | __t.__construct_at_end(move_iterator<pointer>(__begin_), |
| 450 | 451 | move_iterator<pointer>(__end_)); |
| ... | ... | @@ -458,7 +459,7 @@ __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT |
| 458 | 459 | catch (...) |
| 459 | 460 | { |
| 460 | 461 | } |
| 461 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 462 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 462 | 463 | } |
| 463 | 464 | } |
| 464 | 465 | |
| ... | ... | @@ -625,4 +626,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 625 | 626 | |
| 626 | 627 | _LIBCPP_POP_MACROS |
| 627 | 628 | |
| 628 | #endif // _LIBCPP_SPLIT_BUFFER | |
| 629 | #endif // _LIBCPP_SPLIT_BUFFER |
lib/libcxx/include/__sso_allocator deleted-77| ... | ... | @@ -1,77 +0,0 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___SSO_ALLOCATOR | |
| 11 | #define _LIBCPP___SSO_ALLOCATOR | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <memory> | |
| 15 | #include <new> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _Tp, size_t _Np> class _LIBCPP_HIDDEN __sso_allocator; | |
| 25 | ||
| 26 | template <size_t _Np> | |
| 27 | class _LIBCPP_HIDDEN __sso_allocator<void, _Np> | |
| 28 | { | |
| 29 | public: | |
| 30 | typedef const void* const_pointer; | |
| 31 | typedef void value_type; | |
| 32 | }; | |
| 33 | ||
| 34 | template <class _Tp, size_t _Np> | |
| 35 | class _LIBCPP_HIDDEN __sso_allocator | |
| 36 | { | |
| 37 | typename aligned_storage<sizeof(_Tp) * _Np>::type buf_; | |
| 38 | bool __allocated_; | |
| 39 | public: | |
| 40 | typedef size_t size_type; | |
| 41 | typedef _Tp* pointer; | |
| 42 | typedef _Tp value_type; | |
| 43 | ||
| 44 | _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} | |
| 45 | _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} | |
| 46 | template <class _Up> _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() | |
| 47 | : __allocated_(false) {} | |
| 48 | private: | |
| 49 | __sso_allocator& operator=(const __sso_allocator&); | |
| 50 | public: | |
| 51 | _LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, typename __sso_allocator<void, _Np>::const_pointer = nullptr) | |
| 52 | { | |
| 53 | if (!__allocated_ && __n <= _Np) | |
| 54 | { | |
| 55 | __allocated_ = true; | |
| 56 | return (pointer)&buf_; | |
| 57 | } | |
| 58 | return allocator<_Tp>().allocate(__n); | |
| 59 | } | |
| 60 | _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) | |
| 61 | { | |
| 62 | if (__p == (pointer)&buf_) | |
| 63 | __allocated_ = false; | |
| 64 | else | |
| 65 | allocator<_Tp>().deallocate(__p, __n); | |
| 66 | } | |
| 67 | _LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);} | |
| 68 | ||
| 69 | _LIBCPP_INLINE_VISIBILITY | |
| 70 | bool operator==(__sso_allocator& __a) const {return &buf_ == &__a.buf_;} | |
| 71 | _LIBCPP_INLINE_VISIBILITY | |
| 72 | bool operator!=(__sso_allocator& __a) const {return &buf_ != &__a.buf_;} | |
| 73 | }; | |
| 74 | ||
| 75 | _LIBCPP_END_NAMESPACE_STD | |
| 76 | ||
| 77 | #endif // _LIBCPP___SSO_ALLOCATOR |
lib/libcxx/include/__std_stream+3-3| ... | ... | @@ -11,10 +11,10 @@ |
| 11 | 11 | #define _LIBCPP___STD_STREAM |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <ostream> | |
| 15 | #include <istream> | |
| 16 | 14 | #include <__locale> |
| 17 | 15 | #include <cstdio> |
| 16 | #include <istream> | |
| 17 | #include <ostream> | |
| 18 | 18 | |
| 19 | 19 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 20 | 20 | #pragma GCC system_header |
| ... | ... | @@ -358,4 +358,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 358 | 358 | |
| 359 | 359 | _LIBCPP_POP_MACROS |
| 360 | 360 | |
| 361 | #endif // _LIBCPP___STD_STREAM | |
| 361 | #endif // _LIBCPP___STD_STREAM |
lib/libcxx/include/__string+19-53| ... | ... | @@ -10,55 +10,21 @@ |
| 10 | 10 | #ifndef _LIBCPP___STRING |
| 11 | 11 | #define _LIBCPP___STRING |
| 12 | 12 | |
| 13 | /* | |
| 14 | string synopsis | |
| 15 | ||
| 16 | namespace std | |
| 17 | { | |
| 18 | ||
| 19 | template <class charT> | |
| 20 | struct char_traits | |
| 21 | { | |
| 22 | typedef charT char_type; | |
| 23 | typedef ... int_type; | |
| 24 | typedef streamoff off_type; | |
| 25 | typedef streampos pos_type; | |
| 26 | typedef mbstate_t state_type; | |
| 27 | ||
| 28 | static constexpr void assign(char_type& c1, const char_type& c2) noexcept; | |
| 29 | static constexpr bool eq(char_type c1, char_type c2) noexcept; | |
| 30 | static constexpr bool lt(char_type c1, char_type c2) noexcept; | |
| 31 | ||
| 32 | static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); | |
| 33 | static constexpr size_t length(const char_type* s); | |
| 34 | static constexpr const char_type* | |
| 35 | find(const char_type* s, size_t n, const char_type& a); | |
| 36 | ||
| 37 | static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); // constexpr in C++20 | |
| 38 | static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); // constexpr in C++20 | |
| 39 | static constexpr char_type* assign(char_type* s, size_t n, char_type a); // constexpr in C++20 | |
| 40 | ||
| 41 | static constexpr int_type not_eof(int_type c) noexcept; | |
| 42 | static constexpr char_type to_char_type(int_type c) noexcept; | |
| 43 | static constexpr int_type to_int_type(char_type c) noexcept; | |
| 44 | static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; | |
| 45 | static constexpr int_type eof() noexcept; | |
| 46 | }; | |
| 47 | ||
| 48 | template <> struct char_traits<char>; | |
| 49 | template <> struct char_traits<wchar_t>; | |
| 50 | template <> struct char_traits<char8_t>; // c++20 | |
| 51 | ||
| 52 | } // std | |
| 53 | ||
| 54 | */ | |
| 55 | ||
| 56 | 13 | #include <__config> |
| 57 | #include <algorithm> // for search and min | |
| 58 | #include <cstdio> // for EOF | |
| 59 | #include <cstring> // for memcpy | |
| 60 | #include <cwchar> // for wmemcpy | |
| 61 | #include <memory> // for __murmur2_or_cityhash | |
| 14 | #include <__algorithm/copy.h> | |
| 15 | #include <__algorithm/copy_backward.h> | |
| 16 | #include <__algorithm/copy_n.h> | |
| 17 | #include <__algorithm/fill_n.h> | |
| 18 | #include <__algorithm/find_first_of.h> | |
| 19 | #include <__algorithm/find_end.h> | |
| 20 | #include <__algorithm/min.h> | |
| 21 | #include <__functional/hash.h> // for __murmur2_or_cityhash | |
| 22 | #include <__iterator/iterator_traits.h> | |
| 23 | #include <cstdio> // for EOF | |
| 24 | #include <cstdint> // for uint_least16_t | |
| 25 | #include <cstring> // for memcpy | |
| 26 | #include <cwchar> // for wmemcpy | |
| 27 | #include <type_traits> // for __libcpp_is_constant_evaluated | |
| 62 | 28 | |
| 63 | 29 | #include <__debug> |
| 64 | 30 | |
| ... | ... | @@ -581,7 +547,7 @@ char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __ |
| 581 | 547 | } |
| 582 | 548 | |
| 583 | 549 | |
| 584 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 550 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 585 | 551 | |
| 586 | 552 | template <> |
| 587 | 553 | struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> |
| ... | ... | @@ -688,7 +654,7 @@ char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __ |
| 688 | 654 | return nullptr; |
| 689 | 655 | } |
| 690 | 656 | |
| 691 | #endif // #_LIBCPP_NO_HAS_CHAR8_T | |
| 657 | #endif // #_LIBCPP_HAS_NO_CHAR8_T | |
| 692 | 658 | |
| 693 | 659 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS |
| 694 | 660 | |
| ... | ... | @@ -932,7 +898,7 @@ char_traits<char32_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCE |
| 932 | 898 | return __r; |
| 933 | 899 | } |
| 934 | 900 | |
| 935 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 901 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 936 | 902 | |
| 937 | 903 | // helper fns for basic_string and string_view |
| 938 | 904 | |
| ... | ... | @@ -953,7 +919,7 @@ __str_find(const _CharT *__p, _SizeT __sz, |
| 953 | 919 | template <class _CharT, class _Traits> |
| 954 | 920 | inline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT * |
| 955 | 921 | __search_substring(const _CharT *__first1, const _CharT *__last1, |
| 956 | const _CharT *__first2, const _CharT *__last2) { | |
| 922 | const _CharT *__first2, const _CharT *__last2) _NOEXCEPT { | |
| 957 | 923 | // Take advantage of knowing source and pattern lengths. |
| 958 | 924 | // Stop short when source is smaller than pattern. |
| 959 | 925 | const ptrdiff_t __len2 = __last2 - __first2; |
| ... | ... | @@ -1177,4 +1143,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 1177 | 1143 | |
| 1178 | 1144 | _LIBCPP_POP_MACROS |
| 1179 | 1145 | |
| 1180 | #endif // _LIBCPP___STRING | |
| 1146 | #endif // _LIBCPP___STRING |
lib/libcxx/include/__support/ibm/gettod_zos.h created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP_SUPPORT_IBM_GETTOD_ZOS_H | |
| 11 | #define _LIBCPP_SUPPORT_IBM_GETTOD_ZOS_H | |
| 12 | ||
| 13 | #include <time.h> | |
| 14 | ||
| 15 | static inline int gettimeofdayMonotonic(struct timespec64* Output) { | |
| 16 | ||
| 17 | // The POSIX gettimeofday() function is not available on z/OS. Therefore, | |
| 18 | // we will call stcke and other hardware instructions in implement equivalent. | |
| 19 | // Note that nanoseconds alone will overflow when reaching new epoch in 2042. | |
| 20 | ||
| 21 | struct _t { | |
| 22 | uint64_t Hi; | |
| 23 | uint64_t Lo; | |
| 24 | }; | |
| 25 | struct _t Value = {0, 0}; | |
| 26 | uint64_t CC = 0; | |
| 27 | asm(" stcke %0\n" | |
| 28 | " ipm %1\n" | |
| 29 | " srlg %1,%1,28\n" | |
| 30 | : "=m"(Value), "+r"(CC)::); | |
| 31 | ||
| 32 | if (CC != 0) { | |
| 33 | errno = EMVSTODNOTSET; | |
| 34 | return CC; | |
| 35 | } | |
| 36 | uint64_t us = (Value.Hi >> 4); | |
| 37 | uint64_t ns = ((Value.Hi & 0x0F) << 8) + (Value.Lo >> 56); | |
| 38 | ns = (ns * 1000) >> 12; | |
| 39 | us = us - 2208988800000000; | |
| 40 | ||
| 41 | register uint64_t DivPair0 asm("r0"); // dividend (upper half), remainder | |
| 42 | DivPair0 = 0; | |
| 43 | register uint64_t DivPair1 asm("r1"); // dividend (lower half), quotient | |
| 44 | DivPair1 = us; | |
| 45 | uint64_t Divisor = 1000000; | |
| 46 | asm(" dlgr %0,%2" : "+r"(DivPair0), "+r"(DivPair1) : "r"(Divisor) :); | |
| 47 | ||
| 48 | Output->tv_sec = DivPair1; | |
| 49 | Output->tv_nsec = DivPair0 * 1000 + ns; | |
| 50 | return 0; | |
| 51 | } | |
| 52 | ||
| 53 | #endif // _LIBCPP_SUPPORT_IBM_GETTOD_ZOS_H |
lib/libcxx/include/__support/ibm/locale_mgmt_zos.h created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H | |
| 11 | #define _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H | |
| 12 | ||
| 13 | #if defined(__MVS__) | |
| 14 | #include <locale.h> | |
| 15 | #include <string> | |
| 16 | ||
| 17 | #ifdef __cplusplus | |
| 18 | extern "C" { | |
| 19 | #endif | |
| 20 | ||
| 21 | #define _LC_MAX LC_MESSAGES /* highest real category */ | |
| 22 | #define _NCAT (_LC_MAX + 1) /* maximum + 1 */ | |
| 23 | ||
| 24 | #define _CATMASK(n) (1 << (n)) | |
| 25 | #define LC_COLLATE_MASK _CATMASK(LC_COLLATE) | |
| 26 | #define LC_CTYPE_MASK _CATMASK(LC_CTYPE) | |
| 27 | #define LC_MONETARY_MASK _CATMASK(LC_MONETARY) | |
| 28 | #define LC_NUMERIC_MASK _CATMASK(LC_NUMERIC) | |
| 29 | #define LC_TIME_MASK _CATMASK(LC_TIME) | |
| 30 | #define LC_MESSAGES_MASK _CATMASK(LC_MESSAGES) | |
| 31 | #define LC_ALL_MASK (_CATMASK(_NCAT) - 1) | |
| 32 | ||
| 33 | typedef struct locale_struct { | |
| 34 | int category_mask; | |
| 35 | std::string lc_collate; | |
| 36 | std::string lc_ctype; | |
| 37 | std::string lc_monetary; | |
| 38 | std::string lc_numeric; | |
| 39 | std::string lc_time; | |
| 40 | std::string lc_messages; | |
| 41 | } * locale_t; | |
| 42 | ||
| 43 | // z/OS does not have newlocale, freelocale and uselocale. | |
| 44 | // The functions below are workarounds in single thread mode. | |
| 45 | locale_t newlocale(int category_mask, const char* locale, locale_t base); | |
| 46 | void freelocale(locale_t locobj); | |
| 47 | locale_t uselocale(locale_t newloc); | |
| 48 | ||
| 49 | #ifdef __cplusplus | |
| 50 | } | |
| 51 | #endif | |
| 52 | #endif // defined(__MVS__) | |
| 53 | #endif // _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H |
lib/libcxx/include/__support/ibm/nanosleep.h+39-21| ... | ... | @@ -12,27 +12,45 @@ |
| 12 | 12 | |
| 13 | 13 | #include <unistd.h> |
| 14 | 14 | |
| 15 | inline int nanosleep(const struct timespec* req, struct timespec* rem) | |
| 16 | { | |
| 17 | // The nanosleep() function is not available on z/OS. Therefore, we will call | |
| 18 | // sleep() to sleep for whole seconds and usleep() to sleep for any remaining | |
| 19 | // fraction of a second. Any remaining nanoseconds will round up to the next | |
| 20 | // microsecond. | |
| 21 | ||
| 22 | useconds_t __micro_sec = (rem->tv_nsec + 999) / 1000; | |
| 23 | if (__micro_sec > 999999) | |
| 24 | { | |
| 25 | ++rem->tv_sec; | |
| 26 | __micro_sec -= 1000000; | |
| 27 | } | |
| 28 | while (rem->tv_sec) | |
| 29 | rem->tv_sec = sleep(rem->tv_sec); | |
| 30 | if (__micro_sec) { | |
| 31 | rem->tv_nsec = __micro_sec * 1000; | |
| 32 | return usleep(__micro_sec); | |
| 33 | } | |
| 34 | rem->tv_nsec = 0; | |
| 35 | return 0; | |
| 15 | inline int nanosleep(const struct timespec* __req, struct timespec* __rem) { | |
| 16 | // The nanosleep() function is not available on z/OS. Therefore, we will call | |
| 17 | // sleep() to sleep for whole seconds and usleep() to sleep for any remaining | |
| 18 | // fraction of a second. Any remaining nanoseconds will round up to the next | |
| 19 | // microsecond. | |
| 20 | if (__req->tv_sec < 0 || __req->tv_nsec < 0 || __req->tv_nsec > 999999999) { | |
| 21 | errno = EINVAL; | |
| 22 | return -1; | |
| 23 | } | |
| 24 | useconds_t __micro_sec = | |
| 25 | static_cast<useconds_t>((__req->tv_nsec + 999) / 1000); | |
| 26 | time_t __sec = __req->tv_sec; | |
| 27 | if (__micro_sec > 999999) { | |
| 28 | ++__sec; | |
| 29 | __micro_sec -= 1000000; | |
| 30 | } | |
| 31 | __sec = sleep(static_cast<unsigned int>(__sec)); | |
| 32 | if (__sec) { | |
| 33 | if (__rem) { | |
| 34 | // Updating the remaining time to sleep in case of unsuccessful call to sleep(). | |
| 35 | __rem->tv_sec = __sec; | |
| 36 | __rem->tv_nsec = __micro_sec * 1000; | |
| 37 | } | |
| 38 | errno = EINTR; | |
| 39 | return -1; | |
| 40 | } | |
| 41 | if (__micro_sec) { | |
| 42 | int __rt = usleep(__micro_sec); | |
| 43 | if (__rt != 0 && __rem) { | |
| 44 | // The usleep() does not provide the amount of remaining time upon its failure, | |
| 45 | // so the time slept will be ignored. | |
| 46 | __rem->tv_sec = 0; | |
| 47 | __rem->tv_nsec = __micro_sec * 1000; | |
| 48 | // The errno is already set. | |
| 49 | return -1; | |
| 50 | } | |
| 51 | return __rt; | |
| 52 | } | |
| 53 | return 0; | |
| 36 | 54 | } |
| 37 | 55 | |
| 38 | 56 | #endif // _LIBCPP_SUPPORT_IBM_NANOSLEEP_H |
lib/libcxx/include/__support/ibm/xlocale.h+67-9| ... | ... | @@ -11,6 +11,8 @@ |
| 11 | 11 | #define _LIBCPP_SUPPORT_IBM_XLOCALE_H |
| 12 | 12 | |
| 13 | 13 | #include <__support/ibm/locale_mgmt_aix.h> |
| 14 | #include <__support/ibm/locale_mgmt_zos.h> | |
| 15 | #include <stdarg.h> | |
| 14 | 16 | |
| 15 | 17 | #include "cstdlib" |
| 16 | 18 | |
| ... | ... | @@ -210,11 +212,13 @@ size_t wcsxfrm_l(wchar_t *__ws1, const wchar_t *__ws2, size_t __n, |
| 210 | 212 | |
| 211 | 213 | // strftime_l() is defined by POSIX. However, AIX 7.1 and z/OS do not have it |
| 212 | 214 | // implemented yet. z/OS retrieves it from the POSIX fallbacks. |
| 215 | #if !defined(_AIX72) | |
| 213 | 216 | static inline |
| 214 | 217 | size_t strftime_l(char *__s, size_t __size, const char *__fmt, |
| 215 | 218 | const struct tm *__tm, locale_t locale) { |
| 216 | 219 | return __xstrftime(locale, __s, __size, __fmt, __tm); |
| 217 | 220 | } |
| 221 | #endif | |
| 218 | 222 | |
| 219 | 223 | #elif defined(__MVS__) |
| 220 | 224 | #include <wctype.h> |
| ... | ... | @@ -222,47 +226,101 @@ size_t strftime_l(char *__s, size_t __size, const char *__fmt, |
| 222 | 226 | #include <__support/xlocale/__posix_l_fallback.h> |
| 223 | 227 | #endif // defined(__MVS__) |
| 224 | 228 | |
| 229 | namespace { | |
| 230 | ||
| 231 | struct __setAndRestore { | |
| 232 | explicit __setAndRestore(locale_t locale) { | |
| 233 | if (locale == (locale_t)0) { | |
| 234 | __cloc = newlocale(LC_ALL_MASK, "C", /* base */ (locale_t)0); | |
| 235 | __stored = uselocale(__cloc); | |
| 236 | } else { | |
| 237 | __stored = uselocale(locale); | |
| 238 | } | |
| 239 | } | |
| 240 | ||
| 241 | ~__setAndRestore() { | |
| 242 | uselocale(__stored); | |
| 243 | if (__cloc) | |
| 244 | freelocale(__cloc); | |
| 245 | } | |
| 246 | ||
| 247 | private: | |
| 248 | locale_t __stored = (locale_t)0; | |
| 249 | locale_t __cloc = (locale_t)0; | |
| 250 | }; | |
| 251 | ||
| 252 | } // namespace | |
| 253 | ||
| 225 | 254 | // The following are not POSIX routines. These are quick-and-dirty hacks |
| 226 | 255 | // to make things pretend to work |
| 227 | 256 | static inline |
| 228 | 257 | long long strtoll_l(const char *__nptr, char **__endptr, |
| 229 | 258 | int __base, locale_t locale) { |
| 259 | __setAndRestore __newloc(locale); | |
| 230 | 260 | return strtoll(__nptr, __endptr, __base); |
| 231 | 261 | } |
| 262 | ||
| 232 | 263 | static inline |
| 233 | 264 | long strtol_l(const char *__nptr, char **__endptr, |
| 234 | 265 | int __base, locale_t locale) { |
| 266 | __setAndRestore __newloc(locale); | |
| 235 | 267 | return strtol(__nptr, __endptr, __base); |
| 236 | 268 | } |
| 269 | ||
| 270 | static inline | |
| 271 | double strtod_l(const char *__nptr, char **__endptr, | |
| 272 | locale_t locale) { | |
| 273 | __setAndRestore __newloc(locale); | |
| 274 | return strtod(__nptr, __endptr); | |
| 275 | } | |
| 276 | ||
| 277 | static inline | |
| 278 | float strtof_l(const char *__nptr, char **__endptr, | |
| 279 | locale_t locale) { | |
| 280 | __setAndRestore __newloc(locale); | |
| 281 | return strtof(__nptr, __endptr); | |
| 282 | } | |
| 283 | ||
| 237 | 284 | static inline |
| 238 | 285 | long double strtold_l(const char *__nptr, char **__endptr, |
| 239 | 286 | locale_t locale) { |
| 287 | __setAndRestore __newloc(locale); | |
| 240 | 288 | return strtold(__nptr, __endptr); |
| 241 | 289 | } |
| 290 | ||
| 242 | 291 | static inline |
| 243 | 292 | unsigned long long strtoull_l(const char *__nptr, char **__endptr, |
| 244 | 293 | int __base, locale_t locale) { |
| 294 | __setAndRestore __newloc(locale); | |
| 245 | 295 | return strtoull(__nptr, __endptr, __base); |
| 246 | 296 | } |
| 297 | ||
| 247 | 298 | static inline |
| 248 | 299 | unsigned long strtoul_l(const char *__nptr, char **__endptr, |
| 249 | 300 | int __base, locale_t locale) { |
| 301 | __setAndRestore __newloc(locale); | |
| 250 | 302 | return strtoul(__nptr, __endptr, __base); |
| 251 | 303 | } |
| 252 | 304 | |
| 253 | 305 | static inline |
| 254 | int vasprintf(char **strp, const char *fmt, va_list ap) | |
| 255 | { | |
| 306 | int vasprintf(char **strp, const char *fmt, va_list ap) { | |
| 256 | 307 | const size_t buff_size = 256; |
| 257 | int str_size; | |
| 258 | if ((*strp = (char *)malloc(buff_size)) == NULL) | |
| 259 | { | |
| 308 | if ((*strp = (char *)malloc(buff_size)) == NULL) { | |
| 260 | 309 | return -1; |
| 261 | 310 | } |
| 262 | if ((str_size = vsnprintf(*strp, buff_size, fmt, ap)) >= buff_size) | |
| 263 | { | |
| 264 | if ((*strp = (char *)realloc(*strp, str_size + 1)) == NULL) | |
| 265 | { | |
| 311 | ||
| 312 | va_list ap_copy; | |
| 313 | // va_copy may not be provided by the C library in C++ 03 mode. | |
| 314 | #if defined(_LIBCPP_CXX03_LANG) && __has_builtin(__builtin_va_copy) | |
| 315 | __builtin_va_copy(ap_copy, ap); | |
| 316 | #else | |
| 317 | va_copy(ap_copy, ap); | |
| 318 | #endif | |
| 319 | int str_size = vsnprintf(*strp, buff_size, fmt, ap_copy); | |
| 320 | va_end(ap_copy); | |
| 321 | ||
| 322 | if ((size_t) str_size >= buff_size) { | |
| 323 | if ((*strp = (char *)realloc(*strp, str_size + 1)) == NULL) { | |
| 266 | 324 | return -1; |
| 267 | 325 | } |
| 268 | 326 | str_size = vsnprintf(*strp, str_size + 1, fmt, ap); |
lib/libcxx/include/__support/openbsd/xlocale.h+3-3| ... | ... | @@ -10,10 +10,10 @@ |
| 10 | 10 | #ifndef _LIBCPP_SUPPORT_OPENBSD_XLOCALE_H |
| 11 | 11 | #define _LIBCPP_SUPPORT_OPENBSD_XLOCALE_H |
| 12 | 12 | |
| 13 | #include <cstdlib> | |
| 13 | #include <__support/xlocale/__strtonum_fallback.h> | |
| 14 | 14 | #include <clocale> |
| 15 | #include <cwctype> | |
| 15 | #include <cstdlib> | |
| 16 | 16 | #include <ctype.h> |
| 17 | #include <__support/xlocale/__strtonum_fallback.h> | |
| 17 | #include <cwctype> | |
| 18 | 18 | |
| 19 | 19 | #endif |
lib/libcxx/include/__support/win32/limits_msvc_win32.h+1-1| ... | ... | @@ -17,8 +17,8 @@ |
| 17 | 17 | #error "This header should only be included when using Microsofts C1XX frontend" |
| 18 | 18 | #endif |
| 19 | 19 | |
| 20 | #include <limits.h> // CHAR_BIT | |
| 21 | 20 | #include <float.h> // limit constants |
| 21 | #include <limits.h> // CHAR_BIT | |
| 22 | 22 | #include <math.h> // HUGE_VAL |
| 23 | 23 | #include <ymath.h> // internal MSVC header providing the needed functionality |
| 24 | 24 |
lib/libcxx/include/__support/win32/locale_win32.h+21-2| ... | ... | @@ -11,9 +11,28 @@ |
| 11 | 11 | #define _LIBCPP_SUPPORT_WIN32_LOCALE_WIN32_H |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <stdio.h> | |
| 15 | #include <xlocinfo.h> // _locale_t | |
| 16 | 14 | #include <__nullptr> |
| 15 | #include <locale.h> // _locale_t | |
| 16 | #include <stdio.h> | |
| 17 | ||
| 18 | #define _X_ALL LC_ALL | |
| 19 | #define _X_COLLATE LC_COLLATE | |
| 20 | #define _X_CTYPE LC_CTYPE | |
| 21 | #define _X_MONETARY LC_MONETARY | |
| 22 | #define _X_NUMERIC LC_NUMERIC | |
| 23 | #define _X_TIME LC_TIME | |
| 24 | #define _X_MAX LC_MAX | |
| 25 | #define _X_MESSAGES 6 | |
| 26 | #define _NCAT (_X_MESSAGES + 1) | |
| 27 | ||
| 28 | #define _CATMASK(n) ((1 << (n)) >> 1) | |
| 29 | #define _M_COLLATE _CATMASK(_X_COLLATE) | |
| 30 | #define _M_CTYPE _CATMASK(_X_CTYPE) | |
| 31 | #define _M_MONETARY _CATMASK(_X_MONETARY) | |
| 32 | #define _M_NUMERIC _CATMASK(_X_NUMERIC) | |
| 33 | #define _M_TIME _CATMASK(_X_TIME) | |
| 34 | #define _M_MESSAGES _CATMASK(_X_MESSAGES) | |
| 35 | #define _M_ALL (_CATMASK(_NCAT) - 1) | |
| 17 | 36 | |
| 18 | 37 | #define LC_COLLATE_MASK _M_COLLATE |
| 19 | 38 | #define LC_CTYPE_MASK _M_CTYPE |
lib/libcxx/include/__threading_support+14-9| ... | ... | @@ -10,11 +10,12 @@ |
| 10 | 10 | #ifndef _LIBCPP_THREADING_SUPPORT |
| 11 | 11 | #define _LIBCPP_THREADING_SUPPORT |
| 12 | 12 | |
| 13 | #include <__config> | |
| 14 | 13 | #include <__availability> |
| 14 | #include <__config> | |
| 15 | 15 | #include <chrono> |
| 16 | #include <iosfwd> | |
| 17 | 16 | #include <errno.h> |
| 17 | #include <iosfwd> | |
| 18 | #include <limits> | |
| 18 | 19 | |
| 19 | 20 | #ifdef __MVS__ |
| 20 | 21 | # include <__support/ibm/nanosleep.h> |
| ... | ... | @@ -28,14 +29,15 @@ |
| 28 | 29 | # include <__external_threading> |
| 29 | 30 | #elif !defined(_LIBCPP_HAS_NO_THREADS) |
| 30 | 31 | |
| 32 | #if defined(__APPLE__) || defined(__MVS__) | |
| 33 | # define _LIBCPP_NO_NATIVE_SEMAPHORES | |
| 34 | #endif | |
| 35 | ||
| 31 | 36 | #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) |
| 32 | 37 | # include <pthread.h> |
| 33 | 38 | # include <sched.h> |
| 34 | # if defined(__APPLE__) || defined(__MVS__) | |
| 35 | # define _LIBCPP_NO_NATIVE_SEMAPHORES | |
| 36 | # endif | |
| 37 | 39 | # ifndef _LIBCPP_NO_NATIVE_SEMAPHORES |
| 38 | # include <semaphore.h> | |
| 40 | # include <semaphore.h> | |
| 39 | 41 | # endif |
| 40 | 42 | #elif defined(_LIBCPP_HAS_THREAD_API_C11) |
| 41 | 43 | # include <threads.h> |
| ... | ... | @@ -149,6 +151,9 @@ typedef void* __libcpp_condvar_t; |
| 149 | 151 | |
| 150 | 152 | // Semaphore |
| 151 | 153 | typedef void* __libcpp_semaphore_t; |
| 154 | #if defined(_LIBCPP_HAS_THREAD_API_WIN32) | |
| 155 | # define _LIBCPP_SEMAPHORE_MAX (::std::numeric_limits<long>::max()) | |
| 156 | #endif | |
| 152 | 157 | |
| 153 | 158 | // Execute Once |
| 154 | 159 | typedef void* __libcpp_exec_once_flag; |
| ... | ... | @@ -390,7 +395,7 @@ bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) |
| 390 | 395 | return pthread_mutex_trylock(__m) == 0; |
| 391 | 396 | } |
| 392 | 397 | |
| 393 | int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) | |
| 398 | int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) | |
| 394 | 399 | { |
| 395 | 400 | return pthread_mutex_unlock(__m); |
| 396 | 401 | } |
| ... | ... | @@ -500,7 +505,7 @@ bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) |
| 500 | 505 | |
| 501 | 506 | // Thread |
| 502 | 507 | bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { |
| 503 | return *__t == __libcpp_thread_t(); | |
| 508 | return __libcpp_thread_get_id(__t) == 0; | |
| 504 | 509 | } |
| 505 | 510 | |
| 506 | 511 | int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), |
| ... | ... | @@ -578,7 +583,7 @@ bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) |
| 578 | 583 | return mtx_trylock(__m) == thrd_success; |
| 579 | 584 | } |
| 580 | 585 | |
| 581 | int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) | |
| 586 | int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) | |
| 582 | 587 | { |
| 583 | 588 | return mtx_unlock(__m) == thrd_success ? 0 : EINVAL; |
| 584 | 589 | } |
lib/libcxx/include/__tree+7-5| ... | ... | @@ -11,10 +11,12 @@ |
| 11 | 11 | #define _LIBCPP___TREE |
| 12 | 12 | |
| 13 | 13 | #include <__config> |
| 14 | #include <__utility/forward.h> | |
| 15 | #include <algorithm> | |
| 14 | 16 | #include <iterator> |
| 17 | #include <limits> | |
| 15 | 18 | #include <memory> |
| 16 | 19 | #include <stdexcept> |
| 17 | #include <algorithm> | |
| 18 | 20 | |
| 19 | 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 20 | 22 | #pragma GCC system_header |
| ... | ... | @@ -714,7 +716,7 @@ public: |
| 714 | 716 | }; |
| 715 | 717 | |
| 716 | 718 | template <class _VoidPtr> |
| 717 | class __tree_node_base | |
| 719 | class _LIBCPP_STANDALONE_DEBUG __tree_node_base | |
| 718 | 720 | : public __tree_node_base_types<_VoidPtr>::__end_node_type |
| 719 | 721 | { |
| 720 | 722 | typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes; |
| ... | ... | @@ -742,7 +744,7 @@ private: |
| 742 | 744 | }; |
| 743 | 745 | |
| 744 | 746 | template <class _Tp, class _VoidPtr> |
| 745 | class __tree_node | |
| 747 | class _LIBCPP_STANDALONE_DEBUG __tree_node | |
| 746 | 748 | : public __tree_node_base<_VoidPtr> |
| 747 | 749 | { |
| 748 | 750 | public: |
| ... | ... | @@ -2410,7 +2412,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(_Tree& __source) |
| 2410 | 2412 | } |
| 2411 | 2413 | } |
| 2412 | 2414 | |
| 2413 | #endif // _LIBCPP_STD_VER > 14 | |
| 2415 | #endif // _LIBCPP_STD_VER > 14 | |
| 2414 | 2416 | |
| 2415 | 2417 | template <class _Tp, class _Compare, class _Allocator> |
| 2416 | 2418 | typename __tree<_Tp, _Compare, _Allocator>::iterator |
| ... | ... | @@ -2743,4 +2745,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 2743 | 2745 | |
| 2744 | 2746 | _LIBCPP_POP_MACROS |
| 2745 | 2747 | |
| 2746 | #endif // _LIBCPP___TREE | |
| 2748 | #endif // _LIBCPP___TREE |
lib/libcxx/include/__tuple+2-2| ... | ... | @@ -134,7 +134,7 @@ template<> struct __parity<7> { template<size_t _Np> struct __pmake : __repeat<t |
| 134 | 134 | |
| 135 | 135 | } // namespace detail |
| 136 | 136 | |
| 137 | #endif // !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE) | |
| 137 | #endif // !__has_builtin(__make_integer_seq) || defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE) | |
| 138 | 138 | |
| 139 | 139 | #if __has_builtin(__make_integer_seq) |
| 140 | 140 | template <size_t _Ep, size_t _Sp> |
| ... | ... | @@ -548,4 +548,4 @@ struct __sfinae_assign_base<false, true> { |
| 548 | 548 | |
| 549 | 549 | _LIBCPP_END_NAMESPACE_STD |
| 550 | 550 | |
| 551 | #endif // _LIBCPP___TUPLE | |
| 551 | #endif // _LIBCPP___TUPLE |
lib/libcxx/include/__utility/__decay_copy.h created+39| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___TYPE_TRAITS_DECAY_COPY_H | |
| 11 | #define _LIBCPP___TYPE_TRAITS_DECAY_COPY_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__utility/forward.h> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | template <class _Tp> | |
| 27 | inline _LIBCPP_INLINE_VISIBILITY typename decay<_Tp>::type __decay_copy(_Tp&& __t) | |
| 28 | #if _LIBCPP_STD_VER > 17 | |
| 29 | noexcept(is_nothrow_convertible_v<_Tp, remove_reference_t<_Tp> >) | |
| 30 | #endif | |
| 31 | { | |
| 32 | return _VSTD::forward<_Tp>(__t); | |
| 33 | } | |
| 34 | ||
| 35 | _LIBCPP_END_NAMESPACE_STD | |
| 36 | ||
| 37 | _LIBCPP_POP_MACROS | |
| 38 | ||
| 39 | #endif // _LIBCPP___TYPE_TRAITS_DECAY_COPY_H |
lib/libcxx/include/__utility/as_const.h created+38| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_AS_CONST_H | |
| 10 | #define _LIBCPP___UTILITY_AS_CONST_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__utility/forward.h> | |
| 14 | #include <__utility/move.h> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if _LIBCPP_STD_VER > 14 | |
| 27 | template <class _Tp> | |
| 28 | _LIBCPP_NODISCARD_EXT constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } | |
| 29 | ||
| 30 | template <class _Tp> | |
| 31 | void as_const(const _Tp&&) = delete; | |
| 32 | #endif | |
| 33 | ||
| 34 | _LIBCPP_END_NAMESPACE_STD | |
| 35 | ||
| 36 | _LIBCPP_POP_MACROS | |
| 37 | ||
| 38 | #endif // _LIBCPP___UTILITY_AS_CONST_H |
lib/libcxx/include/__utility/cmp.h created+107| ... | ... | @@ -0,0 +1,107 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_CMP_H | |
| 10 | #define _LIBCPP___UTILITY_CMP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__utility/forward.h> | |
| 14 | #include <__utility/move.h> | |
| 15 | #include <limits> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 28 | template<class _Tp, class... _Up> | |
| 29 | struct _IsSameAsAny : _Or<_IsSame<_Tp, _Up>...> {}; | |
| 30 | ||
| 31 | template<class _Tp> | |
| 32 | concept __is_safe_integral_cmp = is_integral_v<_Tp> && | |
| 33 | !_IsSameAsAny<_Tp, bool, char, | |
| 34 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 35 | char8_t, | |
| 36 | #endif | |
| 37 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 38 | char16_t, char32_t, | |
| 39 | #endif | |
| 40 | wchar_t>::value; | |
| 41 | ||
| 42 | template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up> | |
| 43 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 44 | bool cmp_equal(_Tp __t, _Up __u) noexcept | |
| 45 | { | |
| 46 | if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) | |
| 47 | return __t == __u; | |
| 48 | else if constexpr (is_signed_v<_Tp>) | |
| 49 | return __t < 0 ? false : make_unsigned_t<_Tp>(__t) == __u; | |
| 50 | else | |
| 51 | return __u < 0 ? false : __t == make_unsigned_t<_Up>(__u); | |
| 52 | } | |
| 53 | ||
| 54 | template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up> | |
| 55 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 56 | bool cmp_not_equal(_Tp __t, _Up __u) noexcept | |
| 57 | { | |
| 58 | return !_VSTD::cmp_equal(__t, __u); | |
| 59 | } | |
| 60 | ||
| 61 | template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up> | |
| 62 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 63 | bool cmp_less(_Tp __t, _Up __u) noexcept | |
| 64 | { | |
| 65 | if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) | |
| 66 | return __t < __u; | |
| 67 | else if constexpr (is_signed_v<_Tp>) | |
| 68 | return __t < 0 ? true : make_unsigned_t<_Tp>(__t) < __u; | |
| 69 | else | |
| 70 | return __u < 0 ? false : __t < make_unsigned_t<_Up>(__u); | |
| 71 | } | |
| 72 | ||
| 73 | template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up> | |
| 74 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 75 | bool cmp_greater(_Tp __t, _Up __u) noexcept | |
| 76 | { | |
| 77 | return _VSTD::cmp_less(__u, __t); | |
| 78 | } | |
| 79 | ||
| 80 | template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up> | |
| 81 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 82 | bool cmp_less_equal(_Tp __t, _Up __u) noexcept | |
| 83 | { | |
| 84 | return !_VSTD::cmp_greater(__t, __u); | |
| 85 | } | |
| 86 | ||
| 87 | template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up> | |
| 88 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 89 | bool cmp_greater_equal(_Tp __t, _Up __u) noexcept | |
| 90 | { | |
| 91 | return !_VSTD::cmp_less(__t, __u); | |
| 92 | } | |
| 93 | ||
| 94 | template<__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up> | |
| 95 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 96 | bool in_range(_Up __u) noexcept | |
| 97 | { | |
| 98 | return _VSTD::cmp_less_equal(__u, numeric_limits<_Tp>::max()) && | |
| 99 | _VSTD::cmp_greater_equal(__u, numeric_limits<_Tp>::min()); | |
| 100 | } | |
| 101 | #endif | |
| 102 | ||
| 103 | _LIBCPP_END_NAMESPACE_STD | |
| 104 | ||
| 105 | _LIBCPP_POP_MACROS | |
| 106 | ||
| 107 | #endif // _LIBCPP___UTILITY_CMP_H |
lib/libcxx/include/__utility/declval.h created+39| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_DECLVAL_H | |
| 10 | #define _LIBCPP___UTILITY_DECLVAL_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | // Suppress deprecation notice for volatile-qualified return type resulting | |
| 24 | // from volatile-qualified types _Tp. | |
| 25 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 26 | template <class _Tp> | |
| 27 | _Tp&& __declval(int); | |
| 28 | template <class _Tp> | |
| 29 | _Tp __declval(long); | |
| 30 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 31 | ||
| 32 | template <class _Tp> | |
| 33 | decltype(__declval<_Tp>(0)) declval() _NOEXCEPT; | |
| 34 | ||
| 35 | _LIBCPP_END_NAMESPACE_STD | |
| 36 | ||
| 37 | _LIBCPP_POP_MACROS | |
| 38 | ||
| 39 | #endif // _LIBCPP___UTILITY_DECLVAL_H |
lib/libcxx/include/__utility/exchange.h created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_EXCHANGE_H | |
| 10 | #define _LIBCPP___UTILITY_EXCHANGE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__utility/forward.h> | |
| 14 | #include <__utility/move.h> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #if _LIBCPP_STD_VER > 11 | |
| 26 | template<class _T1, class _T2 = _T1> | |
| 27 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 28 | _T1 exchange(_T1& __obj, _T2 && __new_value) | |
| 29 | { | |
| 30 | _T1 __old_value = _VSTD::move(__obj); | |
| 31 | __obj = _VSTD::forward<_T2>(__new_value); | |
| 32 | return __old_value; | |
| 33 | } | |
| 34 | #endif // _LIBCPP_STD_VER > 11 | |
| 35 | ||
| 36 | _LIBCPP_END_NAMESPACE_STD | |
| 37 | ||
| 38 | _LIBCPP_POP_MACROS | |
| 39 | ||
| 40 | #endif // _LIBCPP___UTILITY_EXCHANGE_H |
lib/libcxx/include/__utility/forward.h created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___UTILITY_FORWARD_H | |
| 11 | #define _LIBCPP___UTILITY_FORWARD_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _Tp> | |
| 26 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _Tp&& | |
| 27 | forward(typename remove_reference<_Tp>::type& __t) _NOEXCEPT { | |
| 28 | return static_cast<_Tp&&>(__t); | |
| 29 | } | |
| 30 | ||
| 31 | template <class _Tp> | |
| 32 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _Tp&& | |
| 33 | forward(typename remove_reference<_Tp>::type&& __t) _NOEXCEPT { | |
| 34 | static_assert(!is_lvalue_reference<_Tp>::value, "cannot forward an rvalue as an lvalue"); | |
| 35 | return static_cast<_Tp&&>(__t); | |
| 36 | } | |
| 37 | ||
| 38 | _LIBCPP_END_NAMESPACE_STD | |
| 39 | ||
| 40 | _LIBCPP_POP_MACROS | |
| 41 | ||
| 42 | #endif // _LIBCPP___UTILITY_FORWARD_H |
lib/libcxx/include/__utility/in_place.h created+63| ... | ... | @@ -0,0 +1,63 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_IN_PLACE_H | |
| 10 | #define _LIBCPP___UTILITY_IN_PLACE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <type_traits> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #if _LIBCPP_STD_VER > 14 | |
| 25 | ||
| 26 | struct _LIBCPP_TYPE_VIS in_place_t { | |
| 27 | explicit in_place_t() = default; | |
| 28 | }; | |
| 29 | _LIBCPP_INLINE_VAR constexpr in_place_t in_place{}; | |
| 30 | ||
| 31 | template <class _Tp> | |
| 32 | struct _LIBCPP_TEMPLATE_VIS in_place_type_t { | |
| 33 | explicit in_place_type_t() = default; | |
| 34 | }; | |
| 35 | template <class _Tp> | |
| 36 | _LIBCPP_INLINE_VAR constexpr in_place_type_t<_Tp> in_place_type{}; | |
| 37 | ||
| 38 | template <size_t _Idx> | |
| 39 | struct _LIBCPP_TEMPLATE_VIS in_place_index_t { | |
| 40 | explicit in_place_index_t() = default; | |
| 41 | }; | |
| 42 | template <size_t _Idx> | |
| 43 | _LIBCPP_INLINE_VAR constexpr in_place_index_t<_Idx> in_place_index{}; | |
| 44 | ||
| 45 | template <class _Tp> struct __is_inplace_type_imp : false_type {}; | |
| 46 | template <class _Tp> struct __is_inplace_type_imp<in_place_type_t<_Tp>> : true_type {}; | |
| 47 | ||
| 48 | template <class _Tp> | |
| 49 | using __is_inplace_type = __is_inplace_type_imp<__uncvref_t<_Tp>>; | |
| 50 | ||
| 51 | template <class _Tp> struct __is_inplace_index_imp : false_type {}; | |
| 52 | template <size_t _Idx> struct __is_inplace_index_imp<in_place_index_t<_Idx>> : true_type {}; | |
| 53 | ||
| 54 | template <class _Tp> | |
| 55 | using __is_inplace_index = __is_inplace_index_imp<__uncvref_t<_Tp>>; | |
| 56 | ||
| 57 | #endif // _LIBCPP_STD_VER > 14 | |
| 58 | ||
| 59 | _LIBCPP_END_NAMESPACE_STD | |
| 60 | ||
| 61 | _LIBCPP_POP_MACROS | |
| 62 | ||
| 63 | #endif // _LIBCPP___UTILITY_IN_PLACE_H |
lib/libcxx/include/__utility/integer_sequence.h created+83| ... | ... | @@ -0,0 +1,83 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_INTEGER_SEQUENCE_H | |
| 10 | #define _LIBCPP___UTILITY_INTEGER_SEQUENCE_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <type_traits> | |
| 14 | ||
| 15 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 16 | #pragma GCC system_header | |
| 17 | #endif | |
| 18 | ||
| 19 | _LIBCPP_PUSH_MACROS | |
| 20 | #include <__undef_macros> | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | #if _LIBCPP_STD_VER > 11 | |
| 25 | ||
| 26 | template<class _Tp, _Tp... _Ip> | |
| 27 | struct _LIBCPP_TEMPLATE_VIS integer_sequence | |
| 28 | { | |
| 29 | typedef _Tp value_type; | |
| 30 | static_assert( is_integral<_Tp>::value, | |
| 31 | "std::integer_sequence can only be instantiated with an integral type" ); | |
| 32 | static | |
| 33 | _LIBCPP_INLINE_VISIBILITY | |
| 34 | constexpr | |
| 35 | size_t | |
| 36 | size() noexcept { return sizeof...(_Ip); } | |
| 37 | }; | |
| 38 | ||
| 39 | template<size_t... _Ip> | |
| 40 | using index_sequence = integer_sequence<size_t, _Ip...>; | |
| 41 | ||
| 42 | #if __has_builtin(__make_integer_seq) && !defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE) | |
| 43 | ||
| 44 | template <class _Tp, _Tp _Ep> | |
| 45 | using __make_integer_sequence _LIBCPP_NODEBUG_TYPE = __make_integer_seq<integer_sequence, _Tp, _Ep>; | |
| 46 | ||
| 47 | #else | |
| 48 | ||
| 49 | template<typename _Tp, _Tp _Np> using __make_integer_sequence_unchecked _LIBCPP_NODEBUG_TYPE = | |
| 50 | typename __detail::__make<_Np>::type::template __convert<integer_sequence, _Tp>; | |
| 51 | ||
| 52 | template <class _Tp, _Tp _Ep> | |
| 53 | struct __make_integer_sequence_checked | |
| 54 | { | |
| 55 | static_assert(is_integral<_Tp>::value, | |
| 56 | "std::make_integer_sequence can only be instantiated with an integral type" ); | |
| 57 | static_assert(0 <= _Ep, "std::make_integer_sequence must have a non-negative sequence length"); | |
| 58 | // Workaround GCC bug by preventing bad installations when 0 <= _Ep | |
| 59 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68929 | |
| 60 | typedef _LIBCPP_NODEBUG_TYPE __make_integer_sequence_unchecked<_Tp, 0 <= _Ep ? _Ep : 0> type; | |
| 61 | }; | |
| 62 | ||
| 63 | template <class _Tp, _Tp _Ep> | |
| 64 | using __make_integer_sequence _LIBCPP_NODEBUG_TYPE = typename __make_integer_sequence_checked<_Tp, _Ep>::type; | |
| 65 | ||
| 66 | #endif | |
| 67 | ||
| 68 | template<class _Tp, _Tp _Np> | |
| 69 | using make_integer_sequence = __make_integer_sequence<_Tp, _Np>; | |
| 70 | ||
| 71 | template<size_t _Np> | |
| 72 | using make_index_sequence = make_integer_sequence<size_t, _Np>; | |
| 73 | ||
| 74 | template<class... _Tp> | |
| 75 | using index_sequence_for = make_index_sequence<sizeof...(_Tp)>; | |
| 76 | ||
| 77 | #endif // _LIBCPP_STD_VER > 11 | |
| 78 | ||
| 79 | _LIBCPP_END_NAMESPACE_STD | |
| 80 | ||
| 81 | _LIBCPP_POP_MACROS | |
| 82 | ||
| 83 | #endif // _LIBCPP___UTILITY_INTEGER_SEQUENCE_H |
lib/libcxx/include/__utility/move.h created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___UTILITY_MOVE_H | |
| 11 | #define _LIBCPP___UTILITY_MOVE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | template <class _Tp> | |
| 26 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename remove_reference<_Tp>::type&& | |
| 27 | move(_Tp&& __t) _NOEXCEPT { | |
| 28 | typedef _LIBCPP_NODEBUG_TYPE typename remove_reference<_Tp>::type _Up; | |
| 29 | return static_cast<_Up&&>(__t); | |
| 30 | } | |
| 31 | ||
| 32 | #ifndef _LIBCPP_CXX03_LANG | |
| 33 | template <class _Tp> | |
| 34 | using __move_if_noexcept_result_t = | |
| 35 | typename conditional<!is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value, const _Tp&, | |
| 36 | _Tp&&>::type; | |
| 37 | #else // _LIBCPP_CXX03_LANG | |
| 38 | template <class _Tp> | |
| 39 | using __move_if_noexcept_result_t = const _Tp&; | |
| 40 | #endif | |
| 41 | ||
| 42 | template <class _Tp> | |
| 43 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 __move_if_noexcept_result_t<_Tp> | |
| 44 | move_if_noexcept(_Tp& __x) _NOEXCEPT { | |
| 45 | return _VSTD::move(__x); | |
| 46 | } | |
| 47 | ||
| 48 | _LIBCPP_END_NAMESPACE_STD | |
| 49 | ||
| 50 | _LIBCPP_POP_MACROS | |
| 51 | ||
| 52 | #endif // _LIBCPP___UTILITY_MOVE_H |
lib/libcxx/include/__utility/pair.h created+585| ... | ... | @@ -0,0 +1,585 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_PAIR_H | |
| 10 | #define _LIBCPP___UTILITY_PAIR_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__functional/unwrap_ref.h> | |
| 14 | #include <__tuple> | |
| 15 | #include <__utility/forward.h> | |
| 16 | #include <__utility/move.h> | |
| 17 | #include <__utility/piecewise_construct.h> | |
| 18 | #include <cstddef> | |
| 19 | #include <type_traits> | |
| 20 | ||
| 21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 22 | #pragma GCC system_header | |
| 23 | #endif | |
| 24 | ||
| 25 | _LIBCPP_PUSH_MACROS | |
| 26 | #include <__undef_macros> | |
| 27 | ||
| 28 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 29 | ||
| 30 | ||
| 31 | #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) | |
| 32 | template <class, class> | |
| 33 | struct __non_trivially_copyable_base { | |
| 34 | _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY | |
| 35 | __non_trivially_copyable_base() _NOEXCEPT {} | |
| 36 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 37 | __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {} | |
| 38 | }; | |
| 39 | #endif | |
| 40 | ||
| 41 | template <class _T1, class _T2> | |
| 42 | struct _LIBCPP_TEMPLATE_VIS pair | |
| 43 | #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) | |
| 44 | : private __non_trivially_copyable_base<_T1, _T2> | |
| 45 | #endif | |
| 46 | { | |
| 47 | typedef _T1 first_type; | |
| 48 | typedef _T2 second_type; | |
| 49 | ||
| 50 | _T1 first; | |
| 51 | _T2 second; | |
| 52 | ||
| 53 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 54 | pair(pair const&) = default; | |
| 55 | pair(pair&&) = default; | |
| 56 | #else | |
| 57 | // Use the implicitly declared copy constructor in C++03 | |
| 58 | #endif | |
| 59 | ||
| 60 | #ifdef _LIBCPP_CXX03_LANG | |
| 61 | _LIBCPP_INLINE_VISIBILITY | |
| 62 | pair() : first(), second() {} | |
| 63 | ||
| 64 | _LIBCPP_INLINE_VISIBILITY | |
| 65 | pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {} | |
| 66 | ||
| 67 | template <class _U1, class _U2> | |
| 68 | _LIBCPP_INLINE_VISIBILITY | |
| 69 | pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {} | |
| 70 | ||
| 71 | _LIBCPP_INLINE_VISIBILITY | |
| 72 | pair& operator=(pair const& __p) { | |
| 73 | first = __p.first; | |
| 74 | second = __p.second; | |
| 75 | return *this; | |
| 76 | } | |
| 77 | #else | |
| 78 | template <bool _Val> | |
| 79 | using _EnableB _LIBCPP_NODEBUG_TYPE = typename enable_if<_Val, bool>::type; | |
| 80 | ||
| 81 | struct _CheckArgs { | |
| 82 | template <int&...> | |
| 83 | static constexpr bool __enable_explicit_default() { | |
| 84 | return is_default_constructible<_T1>::value | |
| 85 | && is_default_constructible<_T2>::value | |
| 86 | && !__enable_implicit_default<>(); | |
| 87 | } | |
| 88 | ||
| 89 | template <int&...> | |
| 90 | static constexpr bool __enable_implicit_default() { | |
| 91 | return __is_implicitly_default_constructible<_T1>::value | |
| 92 | && __is_implicitly_default_constructible<_T2>::value; | |
| 93 | } | |
| 94 | ||
| 95 | template <class _U1, class _U2> | |
| 96 | static constexpr bool __enable_explicit() { | |
| 97 | return is_constructible<first_type, _U1>::value | |
| 98 | && is_constructible<second_type, _U2>::value | |
| 99 | && (!is_convertible<_U1, first_type>::value | |
| 100 | || !is_convertible<_U2, second_type>::value); | |
| 101 | } | |
| 102 | ||
| 103 | template <class _U1, class _U2> | |
| 104 | static constexpr bool __enable_implicit() { | |
| 105 | return is_constructible<first_type, _U1>::value | |
| 106 | && is_constructible<second_type, _U2>::value | |
| 107 | && is_convertible<_U1, first_type>::value | |
| 108 | && is_convertible<_U2, second_type>::value; | |
| 109 | } | |
| 110 | }; | |
| 111 | ||
| 112 | template <bool _MaybeEnable> | |
| 113 | using _CheckArgsDep _LIBCPP_NODEBUG_TYPE = typename conditional< | |
| 114 | _MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type; | |
| 115 | ||
| 116 | struct _CheckTupleLikeConstructor { | |
| 117 | template <class _Tuple> | |
| 118 | static constexpr bool __enable_implicit() { | |
| 119 | return __tuple_convertible<_Tuple, pair>::value; | |
| 120 | } | |
| 121 | ||
| 122 | template <class _Tuple> | |
| 123 | static constexpr bool __enable_explicit() { | |
| 124 | return __tuple_constructible<_Tuple, pair>::value | |
| 125 | && !__tuple_convertible<_Tuple, pair>::value; | |
| 126 | } | |
| 127 | ||
| 128 | template <class _Tuple> | |
| 129 | static constexpr bool __enable_assign() { | |
| 130 | return __tuple_assignable<_Tuple, pair>::value; | |
| 131 | } | |
| 132 | }; | |
| 133 | ||
| 134 | template <class _Tuple> | |
| 135 | using _CheckTLC _LIBCPP_NODEBUG_TYPE = typename conditional< | |
| 136 | __tuple_like_with_size<_Tuple, 2>::value | |
| 137 | && !is_same<typename decay<_Tuple>::type, pair>::value, | |
| 138 | _CheckTupleLikeConstructor, | |
| 139 | __check_tuple_constructor_fail | |
| 140 | >::type; | |
| 141 | ||
| 142 | template<bool _Dummy = true, _EnableB< | |
| 143 | _CheckArgsDep<_Dummy>::__enable_explicit_default() | |
| 144 | > = false> | |
| 145 | explicit _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 146 | pair() _NOEXCEPT_(is_nothrow_default_constructible<first_type>::value && | |
| 147 | is_nothrow_default_constructible<second_type>::value) | |
| 148 | : first(), second() {} | |
| 149 | ||
| 150 | template<bool _Dummy = true, _EnableB< | |
| 151 | _CheckArgsDep<_Dummy>::__enable_implicit_default() | |
| 152 | > = false> | |
| 153 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 154 | pair() _NOEXCEPT_(is_nothrow_default_constructible<first_type>::value && | |
| 155 | is_nothrow_default_constructible<second_type>::value) | |
| 156 | : first(), second() {} | |
| 157 | ||
| 158 | template <bool _Dummy = true, _EnableB< | |
| 159 | _CheckArgsDep<_Dummy>::template __enable_explicit<_T1 const&, _T2 const&>() | |
| 160 | > = false> | |
| 161 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 162 | explicit pair(_T1 const& __t1, _T2 const& __t2) | |
| 163 | _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && | |
| 164 | is_nothrow_copy_constructible<second_type>::value) | |
| 165 | : first(__t1), second(__t2) {} | |
| 166 | ||
| 167 | template<bool _Dummy = true, _EnableB< | |
| 168 | _CheckArgsDep<_Dummy>::template __enable_implicit<_T1 const&, _T2 const&>() | |
| 169 | > = false> | |
| 170 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 171 | pair(_T1 const& __t1, _T2 const& __t2) | |
| 172 | _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && | |
| 173 | is_nothrow_copy_constructible<second_type>::value) | |
| 174 | : first(__t1), second(__t2) {} | |
| 175 | ||
| 176 | template<class _U1, class _U2, _EnableB< | |
| 177 | _CheckArgs::template __enable_explicit<_U1, _U2>() | |
| 178 | > = false> | |
| 179 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 180 | explicit pair(_U1&& __u1, _U2&& __u2) | |
| 181 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && | |
| 182 | is_nothrow_constructible<second_type, _U2>::value)) | |
| 183 | : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} | |
| 184 | ||
| 185 | template<class _U1, class _U2, _EnableB< | |
| 186 | _CheckArgs::template __enable_implicit<_U1, _U2>() | |
| 187 | > = false> | |
| 188 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 189 | pair(_U1&& __u1, _U2&& __u2) | |
| 190 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && | |
| 191 | is_nothrow_constructible<second_type, _U2>::value)) | |
| 192 | : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} | |
| 193 | ||
| 194 | template<class _U1, class _U2, _EnableB< | |
| 195 | _CheckArgs::template __enable_explicit<_U1 const&, _U2 const&>() | |
| 196 | > = false> | |
| 197 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 198 | explicit pair(pair<_U1, _U2> const& __p) | |
| 199 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && | |
| 200 | is_nothrow_constructible<second_type, _U2 const&>::value)) | |
| 201 | : first(__p.first), second(__p.second) {} | |
| 202 | ||
| 203 | template<class _U1, class _U2, _EnableB< | |
| 204 | _CheckArgs::template __enable_implicit<_U1 const&, _U2 const&>() | |
| 205 | > = false> | |
| 206 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 207 | pair(pair<_U1, _U2> const& __p) | |
| 208 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && | |
| 209 | is_nothrow_constructible<second_type, _U2 const&>::value)) | |
| 210 | : first(__p.first), second(__p.second) {} | |
| 211 | ||
| 212 | template<class _U1, class _U2, _EnableB< | |
| 213 | _CheckArgs::template __enable_explicit<_U1, _U2>() | |
| 214 | > = false> | |
| 215 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 216 | explicit pair(pair<_U1, _U2>&&__p) | |
| 217 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && | |
| 218 | is_nothrow_constructible<second_type, _U2&&>::value)) | |
| 219 | : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} | |
| 220 | ||
| 221 | template<class _U1, class _U2, _EnableB< | |
| 222 | _CheckArgs::template __enable_implicit<_U1, _U2>() | |
| 223 | > = false> | |
| 224 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 225 | pair(pair<_U1, _U2>&& __p) | |
| 226 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && | |
| 227 | is_nothrow_constructible<second_type, _U2&&>::value)) | |
| 228 | : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} | |
| 229 | ||
| 230 | template<class _Tuple, _EnableB< | |
| 231 | _CheckTLC<_Tuple>::template __enable_explicit<_Tuple>() | |
| 232 | > = false> | |
| 233 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 234 | explicit pair(_Tuple&& __p) | |
| 235 | : first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))), | |
| 236 | second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} | |
| 237 | ||
| 238 | template<class _Tuple, _EnableB< | |
| 239 | _CheckTLC<_Tuple>::template __enable_implicit<_Tuple>() | |
| 240 | > = false> | |
| 241 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 242 | pair(_Tuple&& __p) | |
| 243 | : first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))), | |
| 244 | second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} | |
| 245 | ||
| 246 | template <class... _Args1, class... _Args2> | |
| 247 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 248 | pair(piecewise_construct_t __pc, | |
| 249 | tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) | |
| 250 | _NOEXCEPT_((is_nothrow_constructible<first_type, _Args1...>::value && | |
| 251 | is_nothrow_constructible<second_type, _Args2...>::value)) | |
| 252 | : pair(__pc, __first_args, __second_args, | |
| 253 | typename __make_tuple_indices<sizeof...(_Args1)>::type(), | |
| 254 | typename __make_tuple_indices<sizeof...(_Args2) >::type()) {} | |
| 255 | ||
| 256 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 257 | pair& operator=(typename conditional< | |
| 258 | is_copy_assignable<first_type>::value && | |
| 259 | is_copy_assignable<second_type>::value, | |
| 260 | pair, __nat>::type const& __p) | |
| 261 | _NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value && | |
| 262 | is_nothrow_copy_assignable<second_type>::value) | |
| 263 | { | |
| 264 | first = __p.first; | |
| 265 | second = __p.second; | |
| 266 | return *this; | |
| 267 | } | |
| 268 | ||
| 269 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 270 | pair& operator=(typename conditional< | |
| 271 | is_move_assignable<first_type>::value && | |
| 272 | is_move_assignable<second_type>::value, | |
| 273 | pair, __nat>::type&& __p) | |
| 274 | _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value && | |
| 275 | is_nothrow_move_assignable<second_type>::value) | |
| 276 | { | |
| 277 | first = _VSTD::forward<first_type>(__p.first); | |
| 278 | second = _VSTD::forward<second_type>(__p.second); | |
| 279 | return *this; | |
| 280 | } | |
| 281 | ||
| 282 | template <class _Tuple, _EnableB< | |
| 283 | _CheckTLC<_Tuple>::template __enable_assign<_Tuple>() | |
| 284 | > = false> | |
| 285 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 286 | pair& operator=(_Tuple&& __p) { | |
| 287 | first = _VSTD::get<0>(_VSTD::forward<_Tuple>(__p)); | |
| 288 | second = _VSTD::get<1>(_VSTD::forward<_Tuple>(__p)); | |
| 289 | return *this; | |
| 290 | } | |
| 291 | #endif | |
| 292 | ||
| 293 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 294 | void | |
| 295 | swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable<first_type>::value && | |
| 296 | __is_nothrow_swappable<second_type>::value) | |
| 297 | { | |
| 298 | using _VSTD::swap; | |
| 299 | swap(first, __p.first); | |
| 300 | swap(second, __p.second); | |
| 301 | } | |
| 302 | private: | |
| 303 | ||
| 304 | #ifndef _LIBCPP_CXX03_LANG | |
| 305 | template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2> | |
| 306 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 307 | pair(piecewise_construct_t, | |
| 308 | tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, | |
| 309 | __tuple_indices<_I1...>, __tuple_indices<_I2...>); | |
| 310 | #endif | |
| 311 | }; | |
| 312 | ||
| 313 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 314 | template<class _T1, class _T2> | |
| 315 | pair(_T1, _T2) -> pair<_T1, _T2>; | |
| 316 | #endif // _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 317 | ||
| 318 | template <class _T1, class _T2> | |
| 319 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 320 | bool | |
| 321 | operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 322 | { | |
| 323 | return __x.first == __y.first && __x.second == __y.second; | |
| 324 | } | |
| 325 | ||
| 326 | template <class _T1, class _T2> | |
| 327 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 328 | bool | |
| 329 | operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 330 | { | |
| 331 | return !(__x == __y); | |
| 332 | } | |
| 333 | ||
| 334 | template <class _T1, class _T2> | |
| 335 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 336 | bool | |
| 337 | operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 338 | { | |
| 339 | return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second); | |
| 340 | } | |
| 341 | ||
| 342 | template <class _T1, class _T2> | |
| 343 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 344 | bool | |
| 345 | operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 346 | { | |
| 347 | return __y < __x; | |
| 348 | } | |
| 349 | ||
| 350 | template <class _T1, class _T2> | |
| 351 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 352 | bool | |
| 353 | operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 354 | { | |
| 355 | return !(__x < __y); | |
| 356 | } | |
| 357 | ||
| 358 | template <class _T1, class _T2> | |
| 359 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 360 | bool | |
| 361 | operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 362 | { | |
| 363 | return !(__y < __x); | |
| 364 | } | |
| 365 | ||
| 366 | template <class _T1, class _T2> | |
| 367 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 368 | typename enable_if | |
| 369 | < | |
| 370 | __is_swappable<_T1>::value && | |
| 371 | __is_swappable<_T2>::value, | |
| 372 | void | |
| 373 | >::type | |
| 374 | swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) | |
| 375 | _NOEXCEPT_((__is_nothrow_swappable<_T1>::value && | |
| 376 | __is_nothrow_swappable<_T2>::value)) | |
| 377 | { | |
| 378 | __x.swap(__y); | |
| 379 | } | |
| 380 | ||
| 381 | #ifndef _LIBCPP_CXX03_LANG | |
| 382 | ||
| 383 | template <class _T1, class _T2> | |
| 384 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 385 | pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> | |
| 386 | make_pair(_T1&& __t1, _T2&& __t2) | |
| 387 | { | |
| 388 | return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> | |
| 389 | (_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2)); | |
| 390 | } | |
| 391 | ||
| 392 | #else // _LIBCPP_CXX03_LANG | |
| 393 | ||
| 394 | template <class _T1, class _T2> | |
| 395 | inline _LIBCPP_INLINE_VISIBILITY | |
| 396 | pair<_T1,_T2> | |
| 397 | make_pair(_T1 __x, _T2 __y) | |
| 398 | { | |
| 399 | return pair<_T1, _T2>(__x, __y); | |
| 400 | } | |
| 401 | ||
| 402 | #endif // _LIBCPP_CXX03_LANG | |
| 403 | ||
| 404 | template <class _T1, class _T2> | |
| 405 | struct _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > | |
| 406 | : public integral_constant<size_t, 2> {}; | |
| 407 | ||
| 408 | template <size_t _Ip, class _T1, class _T2> | |
| 409 | struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, pair<_T1, _T2> > | |
| 410 | { | |
| 411 | static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::pair<T1, T2>>"); | |
| 412 | }; | |
| 413 | ||
| 414 | template <class _T1, class _T2> | |
| 415 | struct _LIBCPP_TEMPLATE_VIS tuple_element<0, pair<_T1, _T2> > | |
| 416 | { | |
| 417 | typedef _LIBCPP_NODEBUG_TYPE _T1 type; | |
| 418 | }; | |
| 419 | ||
| 420 | template <class _T1, class _T2> | |
| 421 | struct _LIBCPP_TEMPLATE_VIS tuple_element<1, pair<_T1, _T2> > | |
| 422 | { | |
| 423 | typedef _LIBCPP_NODEBUG_TYPE _T2 type; | |
| 424 | }; | |
| 425 | ||
| 426 | template <size_t _Ip> struct __get_pair; | |
| 427 | ||
| 428 | template <> | |
| 429 | struct __get_pair<0> | |
| 430 | { | |
| 431 | template <class _T1, class _T2> | |
| 432 | static | |
| 433 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 434 | _T1& | |
| 435 | get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;} | |
| 436 | ||
| 437 | template <class _T1, class _T2> | |
| 438 | static | |
| 439 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 440 | const _T1& | |
| 441 | get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;} | |
| 442 | ||
| 443 | #ifndef _LIBCPP_CXX03_LANG | |
| 444 | template <class _T1, class _T2> | |
| 445 | static | |
| 446 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 447 | _T1&& | |
| 448 | get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T1>(__p.first);} | |
| 449 | ||
| 450 | template <class _T1, class _T2> | |
| 451 | static | |
| 452 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 453 | const _T1&& | |
| 454 | get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<const _T1>(__p.first);} | |
| 455 | #endif // _LIBCPP_CXX03_LANG | |
| 456 | }; | |
| 457 | ||
| 458 | template <> | |
| 459 | struct __get_pair<1> | |
| 460 | { | |
| 461 | template <class _T1, class _T2> | |
| 462 | static | |
| 463 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 464 | _T2& | |
| 465 | get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;} | |
| 466 | ||
| 467 | template <class _T1, class _T2> | |
| 468 | static | |
| 469 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 470 | const _T2& | |
| 471 | get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;} | |
| 472 | ||
| 473 | #ifndef _LIBCPP_CXX03_LANG | |
| 474 | template <class _T1, class _T2> | |
| 475 | static | |
| 476 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 477 | _T2&& | |
| 478 | get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T2>(__p.second);} | |
| 479 | ||
| 480 | template <class _T1, class _T2> | |
| 481 | static | |
| 482 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 483 | const _T2&& | |
| 484 | get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<const _T2>(__p.second);} | |
| 485 | #endif // _LIBCPP_CXX03_LANG | |
| 486 | }; | |
| 487 | ||
| 488 | template <size_t _Ip, class _T1, class _T2> | |
| 489 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 490 | typename tuple_element<_Ip, pair<_T1, _T2> >::type& | |
| 491 | get(pair<_T1, _T2>& __p) _NOEXCEPT | |
| 492 | { | |
| 493 | return __get_pair<_Ip>::get(__p); | |
| 494 | } | |
| 495 | ||
| 496 | template <size_t _Ip, class _T1, class _T2> | |
| 497 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 498 | const typename tuple_element<_Ip, pair<_T1, _T2> >::type& | |
| 499 | get(const pair<_T1, _T2>& __p) _NOEXCEPT | |
| 500 | { | |
| 501 | return __get_pair<_Ip>::get(__p); | |
| 502 | } | |
| 503 | ||
| 504 | #ifndef _LIBCPP_CXX03_LANG | |
| 505 | template <size_t _Ip, class _T1, class _T2> | |
| 506 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 507 | typename tuple_element<_Ip, pair<_T1, _T2> >::type&& | |
| 508 | get(pair<_T1, _T2>&& __p) _NOEXCEPT | |
| 509 | { | |
| 510 | return __get_pair<_Ip>::get(_VSTD::move(__p)); | |
| 511 | } | |
| 512 | ||
| 513 | template <size_t _Ip, class _T1, class _T2> | |
| 514 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 515 | const typename tuple_element<_Ip, pair<_T1, _T2> >::type&& | |
| 516 | get(const pair<_T1, _T2>&& __p) _NOEXCEPT | |
| 517 | { | |
| 518 | return __get_pair<_Ip>::get(_VSTD::move(__p)); | |
| 519 | } | |
| 520 | #endif // _LIBCPP_CXX03_LANG | |
| 521 | ||
| 522 | #if _LIBCPP_STD_VER > 11 | |
| 523 | template <class _T1, class _T2> | |
| 524 | inline _LIBCPP_INLINE_VISIBILITY | |
| 525 | constexpr _T1 & get(pair<_T1, _T2>& __p) _NOEXCEPT | |
| 526 | { | |
| 527 | return __get_pair<0>::get(__p); | |
| 528 | } | |
| 529 | ||
| 530 | template <class _T1, class _T2> | |
| 531 | inline _LIBCPP_INLINE_VISIBILITY | |
| 532 | constexpr _T1 const & get(pair<_T1, _T2> const& __p) _NOEXCEPT | |
| 533 | { | |
| 534 | return __get_pair<0>::get(__p); | |
| 535 | } | |
| 536 | ||
| 537 | template <class _T1, class _T2> | |
| 538 | inline _LIBCPP_INLINE_VISIBILITY | |
| 539 | constexpr _T1 && get(pair<_T1, _T2>&& __p) _NOEXCEPT | |
| 540 | { | |
| 541 | return __get_pair<0>::get(_VSTD::move(__p)); | |
| 542 | } | |
| 543 | ||
| 544 | template <class _T1, class _T2> | |
| 545 | inline _LIBCPP_INLINE_VISIBILITY | |
| 546 | constexpr _T1 const && get(pair<_T1, _T2> const&& __p) _NOEXCEPT | |
| 547 | { | |
| 548 | return __get_pair<0>::get(_VSTD::move(__p)); | |
| 549 | } | |
| 550 | ||
| 551 | template <class _T1, class _T2> | |
| 552 | inline _LIBCPP_INLINE_VISIBILITY | |
| 553 | constexpr _T1 & get(pair<_T2, _T1>& __p) _NOEXCEPT | |
| 554 | { | |
| 555 | return __get_pair<1>::get(__p); | |
| 556 | } | |
| 557 | ||
| 558 | template <class _T1, class _T2> | |
| 559 | inline _LIBCPP_INLINE_VISIBILITY | |
| 560 | constexpr _T1 const & get(pair<_T2, _T1> const& __p) _NOEXCEPT | |
| 561 | { | |
| 562 | return __get_pair<1>::get(__p); | |
| 563 | } | |
| 564 | ||
| 565 | template <class _T1, class _T2> | |
| 566 | inline _LIBCPP_INLINE_VISIBILITY | |
| 567 | constexpr _T1 && get(pair<_T2, _T1>&& __p) _NOEXCEPT | |
| 568 | { | |
| 569 | return __get_pair<1>::get(_VSTD::move(__p)); | |
| 570 | } | |
| 571 | ||
| 572 | template <class _T1, class _T2> | |
| 573 | inline _LIBCPP_INLINE_VISIBILITY | |
| 574 | constexpr _T1 const && get(pair<_T2, _T1> const&& __p) _NOEXCEPT | |
| 575 | { | |
| 576 | return __get_pair<1>::get(_VSTD::move(__p)); | |
| 577 | } | |
| 578 | ||
| 579 | #endif | |
| 580 | ||
| 581 | _LIBCPP_END_NAMESPACE_STD | |
| 582 | ||
| 583 | _LIBCPP_POP_MACROS | |
| 584 | ||
| 585 | #endif // _LIBCPP___UTILITY_PAIR_H |
lib/libcxx/include/__utility/piecewise_construct.h created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_PIECEWISE_CONSTRUCT_H | |
| 10 | #define _LIBCPP___UTILITY_PIECEWISE_CONSTRUCT_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | ||
| 14 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 15 | #pragma GCC system_header | |
| 16 | #endif | |
| 17 | ||
| 18 | _LIBCPP_PUSH_MACROS | |
| 19 | #include <__undef_macros> | |
| 20 | ||
| 21 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 22 | ||
| 23 | struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { explicit piecewise_construct_t() = default; }; | |
| 24 | #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 25 | extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;// = piecewise_construct_t(); | |
| 26 | #else | |
| 27 | /* _LIBCPP_INLINE_VAR */ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); | |
| 28 | #endif | |
| 29 | ||
| 30 | _LIBCPP_END_NAMESPACE_STD | |
| 31 | ||
| 32 | _LIBCPP_POP_MACROS | |
| 33 | ||
| 34 | #endif // _LIBCPP___UTILITY_PIECEWISE_CONSTRUCT_H |
lib/libcxx/include/__utility/rel_ops.h created+67| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_REL_OPS_H | |
| 10 | #define _LIBCPP___UTILITY_REL_OPS_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__utility/forward.h> | |
| 14 | #include <__utility/move.h> | |
| 15 | #include <type_traits> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | namespace rel_ops | |
| 27 | { | |
| 28 | ||
| 29 | template<class _Tp> | |
| 30 | inline _LIBCPP_INLINE_VISIBILITY | |
| 31 | bool | |
| 32 | operator!=(const _Tp& __x, const _Tp& __y) | |
| 33 | { | |
| 34 | return !(__x == __y); | |
| 35 | } | |
| 36 | ||
| 37 | template<class _Tp> | |
| 38 | inline _LIBCPP_INLINE_VISIBILITY | |
| 39 | bool | |
| 40 | operator> (const _Tp& __x, const _Tp& __y) | |
| 41 | { | |
| 42 | return __y < __x; | |
| 43 | } | |
| 44 | ||
| 45 | template<class _Tp> | |
| 46 | inline _LIBCPP_INLINE_VISIBILITY | |
| 47 | bool | |
| 48 | operator<=(const _Tp& __x, const _Tp& __y) | |
| 49 | { | |
| 50 | return !(__y < __x); | |
| 51 | } | |
| 52 | ||
| 53 | template<class _Tp> | |
| 54 | inline _LIBCPP_INLINE_VISIBILITY | |
| 55 | bool | |
| 56 | operator>=(const _Tp& __x, const _Tp& __y) | |
| 57 | { | |
| 58 | return !(__x < __y); | |
| 59 | } | |
| 60 | ||
| 61 | } // rel_ops | |
| 62 | ||
| 63 | _LIBCPP_END_NAMESPACE_STD | |
| 64 | ||
| 65 | _LIBCPP_POP_MACROS | |
| 66 | ||
| 67 | #endif // _LIBCPP___UTILITY_REL_OPS_H |
lib/libcxx/include/__utility/swap.h created+55| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef _LIBCPP___UTILITY_SWAP_H | |
| 10 | #define _LIBCPP___UTILITY_SWAP_H | |
| 11 | ||
| 12 | #include <__config> | |
| 13 | #include <__utility/declval.h> | |
| 14 | #include <__utility/move.h> | |
| 15 | #include <type_traits> | |
| 16 | #include <cstddef> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_PUSH_MACROS | |
| 23 | #include <__undef_macros> | |
| 24 | ||
| 25 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 26 | ||
| 27 | #ifndef _LIBCPP_CXX03_LANG | |
| 28 | template <class _Tp> | |
| 29 | using __swap_result_t = typename enable_if<is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value>::type; | |
| 30 | #else | |
| 31 | template <class> | |
| 32 | using __swap_result_t = void; | |
| 33 | #endif | |
| 34 | ||
| 35 | template <class _Tp> | |
| 36 | inline _LIBCPP_INLINE_VISIBILITY __swap_result_t<_Tp> _LIBCPP_CONSTEXPR_AFTER_CXX17 swap(_Tp& __x, _Tp& __y) | |
| 37 | _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value&& is_nothrow_move_assignable<_Tp>::value) { | |
| 38 | _Tp __t(_VSTD::move(__x)); | |
| 39 | __x = _VSTD::move(__y); | |
| 40 | __y = _VSTD::move(__t); | |
| 41 | } | |
| 42 | ||
| 43 | template <class _Tp, size_t _Np> | |
| 44 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if<__is_swappable<_Tp>::value>::type | |
| 45 | swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) { | |
| 46 | for (size_t __i = 0; __i != _Np; ++__i) { | |
| 47 | swap(__a[__i], __b[__i]); | |
| 48 | } | |
| 49 | } | |
| 50 | ||
| 51 | _LIBCPP_END_NAMESPACE_STD | |
| 52 | ||
| 53 | _LIBCPP_POP_MACROS | |
| 54 | ||
| 55 | #endif // _LIBCPP___UTILITY_SWAP_H |
lib/libcxx/include/__utility/to_underlying.h created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------- __utility/to_underlying.h --------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___UTILITY_TO_UNDERLYING_H | |
| 11 | #define _LIBCPP___UTILITY_TO_UNDERLYING_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <type_traits> | |
| 15 | ||
| 16 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 17 | #pragma GCC system_header | |
| 18 | #endif | |
| 19 | ||
| 20 | _LIBCPP_PUSH_MACROS | |
| 21 | #include <__undef_macros> | |
| 22 | ||
| 23 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 24 | ||
| 25 | #ifndef _LIBCPP_CXX03_LANG | |
| 26 | template <class _Tp> | |
| 27 | _LIBCPP_INLINE_VISIBILITY constexpr typename underlying_type<_Tp>::type | |
| 28 | __to_underlying(_Tp __val) noexcept { | |
| 29 | return static_cast<typename underlying_type<_Tp>::type>(__val); | |
| 30 | } | |
| 31 | #endif // !_LIBCPP_CXX03_LANG | |
| 32 | ||
| 33 | #if _LIBCPP_STD_VER > 20 | |
| 34 | template <class _Tp> | |
| 35 | _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY constexpr underlying_type_t<_Tp> | |
| 36 | to_underlying(_Tp __val) noexcept { | |
| 37 | return _VSTD::__to_underlying(__val); | |
| 38 | } | |
| 39 | #endif | |
| 40 | ||
| 41 | _LIBCPP_END_NAMESPACE_STD | |
| 42 | ||
| 43 | _LIBCPP_POP_MACROS | |
| 44 | ||
| 45 | #endif // _LIBCPP___UTILITY_TO_UNDERLYING_H |
lib/libcxx/include/__variant/monostate.h created+65| ... | ... | @@ -0,0 +1,65 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP___VARIANT_MONOSTATE_H | |
| 11 | #define _LIBCPP___VARIANT_MONOSTATE_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <__functional/hash.h> | |
| 15 | #include <cstddef> | |
| 16 | ||
| 17 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 18 | #pragma GCC system_header | |
| 19 | #endif | |
| 20 | ||
| 21 | _LIBCPP_PUSH_MACROS | |
| 22 | #include <__undef_macros> | |
| 23 | ||
| 24 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 25 | ||
| 26 | #if _LIBCPP_STD_VER > 14 | |
| 27 | ||
| 28 | struct _LIBCPP_TEMPLATE_VIS monostate {}; | |
| 29 | ||
| 30 | inline _LIBCPP_INLINE_VISIBILITY | |
| 31 | constexpr bool operator<(monostate, monostate) noexcept { return false; } | |
| 32 | ||
| 33 | inline _LIBCPP_INLINE_VISIBILITY | |
| 34 | constexpr bool operator>(monostate, monostate) noexcept { return false; } | |
| 35 | ||
| 36 | inline _LIBCPP_INLINE_VISIBILITY | |
| 37 | constexpr bool operator<=(monostate, monostate) noexcept { return true; } | |
| 38 | ||
| 39 | inline _LIBCPP_INLINE_VISIBILITY | |
| 40 | constexpr bool operator>=(monostate, monostate) noexcept { return true; } | |
| 41 | ||
| 42 | inline _LIBCPP_INLINE_VISIBILITY | |
| 43 | constexpr bool operator==(monostate, monostate) noexcept { return true; } | |
| 44 | ||
| 45 | inline _LIBCPP_INLINE_VISIBILITY | |
| 46 | constexpr bool operator!=(monostate, monostate) noexcept { return false; } | |
| 47 | ||
| 48 | template <> | |
| 49 | struct _LIBCPP_TEMPLATE_VIS hash<monostate> { | |
| 50 | using argument_type = monostate; | |
| 51 | using result_type = size_t; | |
| 52 | ||
| 53 | inline _LIBCPP_INLINE_VISIBILITY | |
| 54 | result_type operator()(const argument_type&) const _NOEXCEPT { | |
| 55 | return 66740831; // return a fundamentally attractive random value. | |
| 56 | } | |
| 57 | }; | |
| 58 | ||
| 59 | #endif // _LIBCPP_STD_VER > 14 | |
| 60 | ||
| 61 | _LIBCPP_END_NAMESPACE_STD | |
| 62 | ||
| 63 | _LIBCPP_POP_MACROS | |
| 64 | ||
| 65 | #endif // _LIBCPP___VARIANT_MONOSTATE_H |
lib/libcxx/include/algorithm+118-5210| ... | ... | @@ -351,11 +351,11 @@ template <class ForwardIterator, class Compare> |
| 351 | 351 | is_sorted_until(ForwardIterator first, ForwardIterator last, Compare comp); |
| 352 | 352 | |
| 353 | 353 | template <class RandomAccessIterator> |
| 354 | void | |
| 354 | constexpr void // constexpr in C++20 | |
| 355 | 355 | sort(RandomAccessIterator first, RandomAccessIterator last); |
| 356 | 356 | |
| 357 | 357 | template <class RandomAccessIterator, class Compare> |
| 358 | void | |
| 358 | constexpr void // constexpr in C++20 | |
| 359 | 359 | sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); |
| 360 | 360 | |
| 361 | 361 | template <class RandomAccessIterator> |
| ... | ... | @@ -367,29 +367,29 @@ template <class RandomAccessIterator, class Compare> |
| 367 | 367 | stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); |
| 368 | 368 | |
| 369 | 369 | template <class RandomAccessIterator> |
| 370 | void | |
| 370 | constexpr void // constexpr in C++20 | |
| 371 | 371 | partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); |
| 372 | 372 | |
| 373 | 373 | template <class RandomAccessIterator, class Compare> |
| 374 | void | |
| 374 | constexpr void // constexpr in C++20 | |
| 375 | 375 | partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); |
| 376 | 376 | |
| 377 | 377 | template <class InputIterator, class RandomAccessIterator> |
| 378 | RandomAccessIterator | |
| 378 | constexpr RandomAccessIterator // constexpr in C++20 | |
| 379 | 379 | partial_sort_copy(InputIterator first, InputIterator last, |
| 380 | 380 | RandomAccessIterator result_first, RandomAccessIterator result_last); |
| 381 | 381 | |
| 382 | 382 | template <class InputIterator, class RandomAccessIterator, class Compare> |
| 383 | RandomAccessIterator | |
| 383 | constexpr RandomAccessIterator // constexpr in C++20 | |
| 384 | 384 | partial_sort_copy(InputIterator first, InputIterator last, |
| 385 | 385 | RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp); |
| 386 | 386 | |
| 387 | 387 | template <class RandomAccessIterator> |
| 388 | void | |
| 388 | constexpr void // constexpr in C++20 | |
| 389 | 389 | nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); |
| 390 | 390 | |
| 391 | 391 | template <class RandomAccessIterator, class Compare> |
| 392 | void | |
| 392 | constexpr void // constexpr in C++20 | |
| 393 | 393 | nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); |
| 394 | 394 | |
| 395 | 395 | template <class ForwardIterator, class T> |
| ... | ... | @@ -491,35 +491,35 @@ template <class InputIterator1, class InputIterator2, class OutputIterator, clas |
| 491 | 491 | InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); |
| 492 | 492 | |
| 493 | 493 | template <class RandomAccessIterator> |
| 494 | void | |
| 494 | constexpr void // constexpr in C++20 | |
| 495 | 495 | push_heap(RandomAccessIterator first, RandomAccessIterator last); |
| 496 | 496 | |
| 497 | 497 | template <class RandomAccessIterator, class Compare> |
| 498 | void | |
| 498 | constexpr void // constexpr in C++20 | |
| 499 | 499 | push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); |
| 500 | 500 | |
| 501 | 501 | template <class RandomAccessIterator> |
| 502 | void | |
| 502 | constexpr void // constexpr in C++20 | |
| 503 | 503 | pop_heap(RandomAccessIterator first, RandomAccessIterator last); |
| 504 | 504 | |
| 505 | 505 | template <class RandomAccessIterator, class Compare> |
| 506 | void | |
| 506 | constexpr void // constexpr in C++20 | |
| 507 | 507 | pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); |
| 508 | 508 | |
| 509 | 509 | template <class RandomAccessIterator> |
| 510 | void | |
| 510 | constexpr void // constexpr in C++20 | |
| 511 | 511 | make_heap(RandomAccessIterator first, RandomAccessIterator last); |
| 512 | 512 | |
| 513 | 513 | template <class RandomAccessIterator, class Compare> |
| 514 | void | |
| 514 | constexpr void // constexpr in C++20 | |
| 515 | 515 | make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); |
| 516 | 516 | |
| 517 | 517 | template <class RandomAccessIterator> |
| 518 | void | |
| 518 | constexpr void // constexpr in C++20 | |
| 519 | 519 | sort_heap(RandomAccessIterator first, RandomAccessIterator last); |
| 520 | 520 | |
| 521 | 521 | template <class RandomAccessIterator, class Compare> |
| 522 | void | |
| 522 | constexpr void // constexpr in C++20 | |
| 523 | 523 | sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); |
| 524 | 524 | |
| 525 | 525 | template <class RandomAccessIterator> |
| ... | ... | @@ -646,18 +646,113 @@ template <class BidirectionalIterator, class Compare> |
| 646 | 646 | */ |
| 647 | 647 | |
| 648 | 648 | #include <__config> |
| 649 | #include <initializer_list> | |
| 650 | #include <type_traits> | |
| 649 | #include <__debug> | |
| 650 | #include <__bits> // __libcpp_clz | |
| 651 | #include <cstddef> | |
| 651 | 652 | #include <cstring> |
| 653 | #include <functional> | |
| 654 | #include <initializer_list> | |
| 652 | 655 | #include <utility> // needed to provide swap_ranges. |
| 653 | 656 | #include <memory> |
| 654 | #include <functional> | |
| 655 | 657 | #include <iterator> |
| 656 | #include <cstddef> | |
| 657 | #include <bit> | |
| 658 | #include <memory> | |
| 659 | #include <type_traits> | |
| 660 | #include <utility> // swap_ranges | |
| 658 | 661 | #include <version> |
| 659 | 662 | |
| 660 | #include <__debug> | |
| 663 | #include <__algorithm/adjacent_find.h> | |
| 664 | #include <__algorithm/all_of.h> | |
| 665 | #include <__algorithm/any_of.h> | |
| 666 | #include <__algorithm/binary_search.h> | |
| 667 | #include <__algorithm/clamp.h> | |
| 668 | #include <__algorithm/comp.h> | |
| 669 | #include <__algorithm/comp_ref_type.h> | |
| 670 | #include <__algorithm/copy.h> | |
| 671 | #include <__algorithm/copy_backward.h> | |
| 672 | #include <__algorithm/copy_if.h> | |
| 673 | #include <__algorithm/copy_n.h> | |
| 674 | #include <__algorithm/count.h> | |
| 675 | #include <__algorithm/count_if.h> | |
| 676 | #include <__algorithm/equal.h> | |
| 677 | #include <__algorithm/equal_range.h> | |
| 678 | #include <__algorithm/fill_n.h> | |
| 679 | #include <__algorithm/fill.h> | |
| 680 | #include <__algorithm/find.h> | |
| 681 | #include <__algorithm/find_end.h> | |
| 682 | #include <__algorithm/find_first_of.h> | |
| 683 | #include <__algorithm/find_if.h> | |
| 684 | #include <__algorithm/find_if_not.h> | |
| 685 | #include <__algorithm/for_each.h> | |
| 686 | #include <__algorithm/for_each_n.h> | |
| 687 | #include <__algorithm/generate_n.h> | |
| 688 | #include <__algorithm/generate.h> | |
| 689 | #include <__algorithm/half_positive.h> | |
| 690 | #include <__algorithm/includes.h> | |
| 691 | #include <__algorithm/inplace_merge.h> | |
| 692 | #include <__algorithm/is_heap.h> | |
| 693 | #include <__algorithm/is_heap_until.h> | |
| 694 | #include <__algorithm/is_partitioned.h> | |
| 695 | #include <__algorithm/is_permutation.h> | |
| 696 | #include <__algorithm/is_sorted.h> | |
| 697 | #include <__algorithm/is_sorted_until.h> | |
| 698 | #include <__algorithm/iter_swap.h> | |
| 699 | #include <__algorithm/lexicographical_compare.h> | |
| 700 | #include <__algorithm/lower_bound.h> | |
| 701 | #include <__algorithm/make_heap.h> | |
| 702 | #include <__algorithm/max.h> | |
| 703 | #include <__algorithm/max_element.h> | |
| 704 | #include <__algorithm/merge.h> | |
| 705 | #include <__algorithm/min.h> | |
| 706 | #include <__algorithm/min_element.h> | |
| 707 | #include <__algorithm/minmax.h> | |
| 708 | #include <__algorithm/minmax_element.h> | |
| 709 | #include <__algorithm/mismatch.h> | |
| 710 | #include <__algorithm/move.h> | |
| 711 | #include <__algorithm/move_backward.h> | |
| 712 | #include <__algorithm/next_permutation.h> | |
| 713 | #include <__algorithm/none_of.h> | |
| 714 | #include <__algorithm/nth_element.h> | |
| 715 | #include <__algorithm/partial_sort.h> | |
| 716 | #include <__algorithm/partial_sort_copy.h> | |
| 717 | #include <__algorithm/partition.h> | |
| 718 | #include <__algorithm/partition_copy.h> | |
| 719 | #include <__algorithm/partition_point.h> | |
| 720 | #include <__algorithm/pop_heap.h> | |
| 721 | #include <__algorithm/prev_permutation.h> | |
| 722 | #include <__algorithm/push_heap.h> | |
| 723 | #include <__algorithm/remove.h> | |
| 724 | #include <__algorithm/remove_copy.h> | |
| 725 | #include <__algorithm/remove_copy_if.h> | |
| 726 | #include <__algorithm/remove_if.h> | |
| 727 | #include <__algorithm/replace.h> | |
| 728 | #include <__algorithm/replace_copy.h> | |
| 729 | #include <__algorithm/replace_copy_if.h> | |
| 730 | #include <__algorithm/replace_if.h> | |
| 731 | #include <__algorithm/reverse.h> | |
| 732 | #include <__algorithm/reverse_copy.h> | |
| 733 | #include <__algorithm/rotate.h> | |
| 734 | #include <__algorithm/rotate_copy.h> | |
| 735 | #include <__algorithm/sample.h> | |
| 736 | #include <__algorithm/search.h> | |
| 737 | #include <__algorithm/search_n.h> | |
| 738 | #include <__algorithm/set_difference.h> | |
| 739 | #include <__algorithm/set_intersection.h> | |
| 740 | #include <__algorithm/set_symmetric_difference.h> | |
| 741 | #include <__algorithm/set_union.h> | |
| 742 | #include <__algorithm/shift_left.h> | |
| 743 | #include <__algorithm/shift_right.h> | |
| 744 | #include <__algorithm/shuffle.h> | |
| 745 | #include <__algorithm/sift_down.h> | |
| 746 | #include <__algorithm/sort.h> | |
| 747 | #include <__algorithm/sort_heap.h> | |
| 748 | #include <__algorithm/stable_partition.h> | |
| 749 | #include <__algorithm/stable_sort.h> | |
| 750 | #include <__algorithm/swap_ranges.h> | |
| 751 | #include <__algorithm/transform.h> | |
| 752 | #include <__algorithm/unique_copy.h> | |
| 753 | #include <__algorithm/unique.h> | |
| 754 | #include <__algorithm/unwrap_iter.h> | |
| 755 | #include <__algorithm/upper_bound.h> | |
| 661 | 756 | |
| 662 | 757 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 663 | 758 | #pragma GCC system_header |
| ... | ... | @@ -666,5197 +761,10 @@ template <class BidirectionalIterator, class Compare> |
| 666 | 761 | _LIBCPP_PUSH_MACROS |
| 667 | 762 | #include <__undef_macros> |
| 668 | 763 | |
| 669 | ||
| 670 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 671 | ||
| 672 | // I'd like to replace these with _VSTD::equal_to<void>, but can't because: | |
| 673 | // * That only works with C++14 and later, and | |
| 674 | // * We haven't included <functional> here. | |
| 675 | template <class _T1, class _T2 = _T1> | |
| 676 | struct __equal_to | |
| 677 | { | |
| 678 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 679 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T2& __y) const {return __x == __y;} | |
| 680 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T1& __y) const {return __x == __y;} | |
| 681 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T2& __y) const {return __x == __y;} | |
| 682 | }; | |
| 683 | ||
| 684 | template <class _T1> | |
| 685 | struct __equal_to<_T1, _T1> | |
| 686 | { | |
| 687 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 688 | bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 689 | }; | |
| 690 | ||
| 691 | template <class _T1> | |
| 692 | struct __equal_to<const _T1, _T1> | |
| 693 | { | |
| 694 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 695 | bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 696 | }; | |
| 697 | ||
| 698 | template <class _T1> | |
| 699 | struct __equal_to<_T1, const _T1> | |
| 700 | { | |
| 701 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 702 | bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} | |
| 703 | }; | |
| 704 | ||
| 705 | template <class _T1, class _T2 = _T1> | |
| 706 | struct __less | |
| 707 | { | |
| 708 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 709 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 710 | ||
| 711 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 712 | bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;} | |
| 713 | ||
| 714 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 715 | bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;} | |
| 716 | ||
| 717 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 718 | bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;} | |
| 719 | }; | |
| 720 | ||
| 721 | template <class _T1> | |
| 722 | struct __less<_T1, _T1> | |
| 723 | { | |
| 724 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 725 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 726 | }; | |
| 727 | ||
| 728 | template <class _T1> | |
| 729 | struct __less<const _T1, _T1> | |
| 730 | { | |
| 731 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 732 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 733 | }; | |
| 734 | ||
| 735 | template <class _T1> | |
| 736 | struct __less<_T1, const _T1> | |
| 737 | { | |
| 738 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 739 | bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} | |
| 740 | }; | |
| 741 | ||
| 742 | template <class _Predicate> | |
| 743 | class __invert // invert the sense of a comparison | |
| 744 | { | |
| 745 | private: | |
| 746 | _Predicate __p_; | |
| 747 | public: | |
| 748 | _LIBCPP_INLINE_VISIBILITY __invert() {} | |
| 749 | ||
| 750 | _LIBCPP_INLINE_VISIBILITY | |
| 751 | explicit __invert(_Predicate __p) : __p_(__p) {} | |
| 752 | ||
| 753 | template <class _T1> | |
| 754 | _LIBCPP_INLINE_VISIBILITY | |
| 755 | bool operator()(const _T1& __x) {return !__p_(__x);} | |
| 756 | ||
| 757 | template <class _T1, class _T2> | |
| 758 | _LIBCPP_INLINE_VISIBILITY | |
| 759 | bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);} | |
| 760 | }; | |
| 761 | ||
| 762 | // Perform division by two quickly for positive integers (llvm.org/PR39129) | |
| 763 | ||
| 764 | template <typename _Integral> | |
| 765 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 766 | typename enable_if | |
| 767 | < | |
| 768 | is_integral<_Integral>::value, | |
| 769 | _Integral | |
| 770 | >::type | |
| 771 | __half_positive(_Integral __value) | |
| 772 | { | |
| 773 | return static_cast<_Integral>(static_cast<typename make_unsigned<_Integral>::type>(__value) / 2); | |
| 774 | } | |
| 775 | ||
| 776 | template <typename _Tp> | |
| 777 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 778 | typename enable_if | |
| 779 | < | |
| 780 | !is_integral<_Tp>::value, | |
| 781 | _Tp | |
| 782 | >::type | |
| 783 | __half_positive(_Tp __value) | |
| 784 | { | |
| 785 | return __value / 2; | |
| 786 | } | |
| 787 | ||
| 788 | #ifdef _LIBCPP_DEBUG | |
| 789 | ||
| 790 | template <class _Compare> | |
| 791 | struct __debug_less | |
| 792 | { | |
| 793 | _Compare &__comp_; | |
| 794 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 795 | __debug_less(_Compare& __c) : __comp_(__c) {} | |
| 796 | ||
| 797 | template <class _Tp, class _Up> | |
| 798 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 799 | bool operator()(const _Tp& __x, const _Up& __y) | |
| 800 | { | |
| 801 | bool __r = __comp_(__x, __y); | |
| 802 | if (__r) | |
| 803 | __do_compare_assert(0, __y, __x); | |
| 804 | return __r; | |
| 805 | } | |
| 806 | ||
| 807 | template <class _Tp, class _Up> | |
| 808 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 809 | bool operator()(_Tp& __x, _Up& __y) | |
| 810 | { | |
| 811 | bool __r = __comp_(__x, __y); | |
| 812 | if (__r) | |
| 813 | __do_compare_assert(0, __y, __x); | |
| 814 | return __r; | |
| 815 | } | |
| 816 | ||
| 817 | template <class _LHS, class _RHS> | |
| 818 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 819 | inline _LIBCPP_INLINE_VISIBILITY | |
| 820 | decltype((void)_VSTD::declval<_Compare&>()( | |
| 821 | _VSTD::declval<_LHS &>(), _VSTD::declval<_RHS &>())) | |
| 822 | __do_compare_assert(int, _LHS & __l, _RHS & __r) { | |
| 823 | _LIBCPP_ASSERT(!__comp_(__l, __r), | |
| 824 | "Comparator does not induce a strict weak ordering"); | |
| 825 | } | |
| 826 | ||
| 827 | template <class _LHS, class _RHS> | |
| 828 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 829 | inline _LIBCPP_INLINE_VISIBILITY | |
| 830 | void __do_compare_assert(long, _LHS &, _RHS &) {} | |
| 831 | }; | |
| 832 | ||
| 833 | #endif // _LIBCPP_DEBUG | |
| 834 | ||
| 835 | template <class _Comp> | |
| 836 | struct __comp_ref_type { | |
| 837 | // Pass the comparator by lvalue reference. Or in debug mode, using a | |
| 838 | // debugging wrapper that stores a reference. | |
| 839 | #ifndef _LIBCPP_DEBUG | |
| 840 | typedef typename add_lvalue_reference<_Comp>::type type; | |
| 841 | #else | |
| 842 | typedef __debug_less<_Comp> type; | |
| 843 | #endif | |
| 844 | }; | |
| 845 | ||
| 846 | // all_of | |
| 847 | ||
| 848 | template <class _InputIterator, class _Predicate> | |
| 849 | _LIBCPP_NODISCARD_EXT inline | |
| 850 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 851 | bool | |
| 852 | all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 853 | { | |
| 854 | for (; __first != __last; ++__first) | |
| 855 | if (!__pred(*__first)) | |
| 856 | return false; | |
| 857 | return true; | |
| 858 | } | |
| 859 | ||
| 860 | // any_of | |
| 861 | ||
| 862 | template <class _InputIterator, class _Predicate> | |
| 863 | _LIBCPP_NODISCARD_EXT inline | |
| 864 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 865 | bool | |
| 866 | any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 867 | { | |
| 868 | for (; __first != __last; ++__first) | |
| 869 | if (__pred(*__first)) | |
| 870 | return true; | |
| 871 | return false; | |
| 872 | } | |
| 873 | ||
| 874 | // none_of | |
| 875 | ||
| 876 | template <class _InputIterator, class _Predicate> | |
| 877 | _LIBCPP_NODISCARD_EXT inline | |
| 878 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 879 | bool | |
| 880 | none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 881 | { | |
| 882 | for (; __first != __last; ++__first) | |
| 883 | if (__pred(*__first)) | |
| 884 | return false; | |
| 885 | return true; | |
| 886 | } | |
| 887 | ||
| 888 | // for_each | |
| 889 | ||
| 890 | template <class _InputIterator, class _Function> | |
| 891 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 892 | _Function | |
| 893 | for_each(_InputIterator __first, _InputIterator __last, _Function __f) | |
| 894 | { | |
| 895 | for (; __first != __last; ++__first) | |
| 896 | __f(*__first); | |
| 897 | return __f; | |
| 898 | } | |
| 899 | ||
| 900 | #if _LIBCPP_STD_VER > 14 | |
| 901 | // for_each_n | |
| 902 | ||
| 903 | template <class _InputIterator, class _Size, class _Function> | |
| 904 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 905 | _InputIterator | |
| 906 | for_each_n(_InputIterator __first, _Size __orig_n, _Function __f) | |
| 907 | { | |
| 908 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 909 | _IntegralSize __n = __orig_n; | |
| 910 | while (__n > 0) | |
| 911 | { | |
| 912 | __f(*__first); | |
| 913 | ++__first; | |
| 914 | --__n; | |
| 915 | } | |
| 916 | return __first; | |
| 917 | } | |
| 918 | #endif | |
| 919 | ||
| 920 | // find | |
| 921 | ||
| 922 | template <class _InputIterator, class _Tp> | |
| 923 | _LIBCPP_NODISCARD_EXT inline | |
| 924 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 925 | _InputIterator | |
| 926 | find(_InputIterator __first, _InputIterator __last, const _Tp& __value_) | |
| 927 | { | |
| 928 | for (; __first != __last; ++__first) | |
| 929 | if (*__first == __value_) | |
| 930 | break; | |
| 931 | return __first; | |
| 932 | } | |
| 933 | ||
| 934 | // find_if | |
| 935 | ||
| 936 | template <class _InputIterator, class _Predicate> | |
| 937 | _LIBCPP_NODISCARD_EXT inline | |
| 938 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 939 | _InputIterator | |
| 940 | find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 941 | { | |
| 942 | for (; __first != __last; ++__first) | |
| 943 | if (__pred(*__first)) | |
| 944 | break; | |
| 945 | return __first; | |
| 946 | } | |
| 947 | ||
| 948 | // find_if_not | |
| 949 | ||
| 950 | template<class _InputIterator, class _Predicate> | |
| 951 | _LIBCPP_NODISCARD_EXT inline | |
| 952 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 953 | _InputIterator | |
| 954 | find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 955 | { | |
| 956 | for (; __first != __last; ++__first) | |
| 957 | if (!__pred(*__first)) | |
| 958 | break; | |
| 959 | return __first; | |
| 960 | } | |
| 961 | ||
| 962 | // find_end | |
| 963 | ||
| 964 | template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2> | |
| 965 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 | |
| 966 | __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 967 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred, | |
| 968 | forward_iterator_tag, forward_iterator_tag) | |
| 969 | { | |
| 970 | // modeled after search algorithm | |
| 971 | _ForwardIterator1 __r = __last1; // __last1 is the "default" answer | |
| 972 | if (__first2 == __last2) | |
| 973 | return __r; | |
| 974 | while (true) | |
| 975 | { | |
| 976 | while (true) | |
| 977 | { | |
| 978 | if (__first1 == __last1) // if source exhausted return last correct answer | |
| 979 | return __r; // (or __last1 if never found) | |
| 980 | if (__pred(*__first1, *__first2)) | |
| 981 | break; | |
| 982 | ++__first1; | |
| 983 | } | |
| 984 | // *__first1 matches *__first2, now match elements after here | |
| 985 | _ForwardIterator1 __m1 = __first1; | |
| 986 | _ForwardIterator2 __m2 = __first2; | |
| 987 | while (true) | |
| 988 | { | |
| 989 | if (++__m2 == __last2) | |
| 990 | { // Pattern exhaused, record answer and search for another one | |
| 991 | __r = __first1; | |
| 992 | ++__first1; | |
| 993 | break; | |
| 994 | } | |
| 995 | if (++__m1 == __last1) // Source exhausted, return last answer | |
| 996 | return __r; | |
| 997 | if (!__pred(*__m1, *__m2)) // mismatch, restart with a new __first | |
| 998 | { | |
| 999 | ++__first1; | |
| 1000 | break; | |
| 1001 | } // else there is a match, check next elements | |
| 1002 | } | |
| 1003 | } | |
| 1004 | } | |
| 1005 | ||
| 1006 | template <class _BinaryPredicate, class _BidirectionalIterator1, class _BidirectionalIterator2> | |
| 1007 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator1 | |
| 1008 | __find_end(_BidirectionalIterator1 __first1, _BidirectionalIterator1 __last1, | |
| 1009 | _BidirectionalIterator2 __first2, _BidirectionalIterator2 __last2, _BinaryPredicate __pred, | |
| 1010 | bidirectional_iterator_tag, bidirectional_iterator_tag) | |
| 1011 | { | |
| 1012 | // modeled after search algorithm (in reverse) | |
| 1013 | if (__first2 == __last2) | |
| 1014 | return __last1; // Everything matches an empty sequence | |
| 1015 | _BidirectionalIterator1 __l1 = __last1; | |
| 1016 | _BidirectionalIterator2 __l2 = __last2; | |
| 1017 | --__l2; | |
| 1018 | while (true) | |
| 1019 | { | |
| 1020 | // Find last element in sequence 1 that matchs *(__last2-1), with a mininum of loop checks | |
| 1021 | while (true) | |
| 1022 | { | |
| 1023 | if (__first1 == __l1) // return __last1 if no element matches *__first2 | |
| 1024 | return __last1; | |
| 1025 | if (__pred(*--__l1, *__l2)) | |
| 1026 | break; | |
| 1027 | } | |
| 1028 | // *__l1 matches *__l2, now match elements before here | |
| 1029 | _BidirectionalIterator1 __m1 = __l1; | |
| 1030 | _BidirectionalIterator2 __m2 = __l2; | |
| 1031 | while (true) | |
| 1032 | { | |
| 1033 | if (__m2 == __first2) // If pattern exhausted, __m1 is the answer (works for 1 element pattern) | |
| 1034 | return __m1; | |
| 1035 | if (__m1 == __first1) // Otherwise if source exhaused, pattern not found | |
| 1036 | return __last1; | |
| 1037 | if (!__pred(*--__m1, *--__m2)) // if there is a mismatch, restart with a new __l1 | |
| 1038 | { | |
| 1039 | break; | |
| 1040 | } // else there is a match, check next elements | |
| 1041 | } | |
| 1042 | } | |
| 1043 | } | |
| 1044 | ||
| 1045 | template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 1046 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator1 | |
| 1047 | __find_end(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, | |
| 1048 | _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __pred, | |
| 1049 | random_access_iterator_tag, random_access_iterator_tag) | |
| 1050 | { | |
| 1051 | // Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern | |
| 1052 | typename iterator_traits<_RandomAccessIterator2>::difference_type __len2 = __last2 - __first2; | |
| 1053 | if (__len2 == 0) | |
| 1054 | return __last1; | |
| 1055 | typename iterator_traits<_RandomAccessIterator1>::difference_type __len1 = __last1 - __first1; | |
| 1056 | if (__len1 < __len2) | |
| 1057 | return __last1; | |
| 1058 | const _RandomAccessIterator1 __s = __first1 + (__len2 - 1); // End of pattern match can't go before here | |
| 1059 | _RandomAccessIterator1 __l1 = __last1; | |
| 1060 | _RandomAccessIterator2 __l2 = __last2; | |
| 1061 | --__l2; | |
| 1062 | while (true) | |
| 1063 | { | |
| 1064 | while (true) | |
| 1065 | { | |
| 1066 | if (__s == __l1) | |
| 1067 | return __last1; | |
| 1068 | if (__pred(*--__l1, *__l2)) | |
| 1069 | break; | |
| 1070 | } | |
| 1071 | _RandomAccessIterator1 __m1 = __l1; | |
| 1072 | _RandomAccessIterator2 __m2 = __l2; | |
| 1073 | while (true) | |
| 1074 | { | |
| 1075 | if (__m2 == __first2) | |
| 1076 | return __m1; | |
| 1077 | // no need to check range on __m1 because __s guarantees we have enough source | |
| 1078 | if (!__pred(*--__m1, *--__m2)) | |
| 1079 | { | |
| 1080 | break; | |
| 1081 | } | |
| 1082 | } | |
| 1083 | } | |
| 1084 | } | |
| 1085 | ||
| 1086 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 1087 | _LIBCPP_NODISCARD_EXT inline | |
| 1088 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1089 | _ForwardIterator1 | |
| 1090 | find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1091 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) | |
| 1092 | { | |
| 1093 | return _VSTD::__find_end<typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 1094 | (__first1, __last1, __first2, __last2, __pred, | |
| 1095 | typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 1096 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 1097 | } | |
| 1098 | ||
| 1099 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 1100 | _LIBCPP_NODISCARD_EXT inline | |
| 1101 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1102 | _ForwardIterator1 | |
| 1103 | find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1104 | _ForwardIterator2 __first2, _ForwardIterator2 __last2) | |
| 1105 | { | |
| 1106 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 1107 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 1108 | return _VSTD::find_end(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 1109 | } | |
| 1110 | ||
| 1111 | // find_first_of | |
| 1112 | ||
| 1113 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 1114 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator1 | |
| 1115 | __find_first_of_ce(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1116 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) | |
| 1117 | { | |
| 1118 | for (; __first1 != __last1; ++__first1) | |
| 1119 | for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) | |
| 1120 | if (__pred(*__first1, *__j)) | |
| 1121 | return __first1; | |
| 1122 | return __last1; | |
| 1123 | } | |
| 1124 | ||
| 1125 | ||
| 1126 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 1127 | _LIBCPP_NODISCARD_EXT inline | |
| 1128 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1129 | _ForwardIterator1 | |
| 1130 | find_first_of(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1131 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) | |
| 1132 | { | |
| 1133 | return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __pred); | |
| 1134 | } | |
| 1135 | ||
| 1136 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 1137 | _LIBCPP_NODISCARD_EXT inline | |
| 1138 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1139 | _ForwardIterator1 | |
| 1140 | find_first_of(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1141 | _ForwardIterator2 __first2, _ForwardIterator2 __last2) | |
| 1142 | { | |
| 1143 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 1144 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 1145 | return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 1146 | } | |
| 1147 | ||
| 1148 | // adjacent_find | |
| 1149 | ||
| 1150 | template <class _ForwardIterator, class _BinaryPredicate> | |
| 1151 | _LIBCPP_NODISCARD_EXT inline | |
| 1152 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1153 | _ForwardIterator | |
| 1154 | adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) | |
| 1155 | { | |
| 1156 | if (__first != __last) | |
| 1157 | { | |
| 1158 | _ForwardIterator __i = __first; | |
| 1159 | while (++__i != __last) | |
| 1160 | { | |
| 1161 | if (__pred(*__first, *__i)) | |
| 1162 | return __first; | |
| 1163 | __first = __i; | |
| 1164 | } | |
| 1165 | } | |
| 1166 | return __last; | |
| 1167 | } | |
| 1168 | ||
| 1169 | template <class _ForwardIterator> | |
| 1170 | _LIBCPP_NODISCARD_EXT inline | |
| 1171 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1172 | _ForwardIterator | |
| 1173 | adjacent_find(_ForwardIterator __first, _ForwardIterator __last) | |
| 1174 | { | |
| 1175 | typedef typename iterator_traits<_ForwardIterator>::value_type __v; | |
| 1176 | return _VSTD::adjacent_find(__first, __last, __equal_to<__v>()); | |
| 1177 | } | |
| 1178 | ||
| 1179 | // count | |
| 1180 | ||
| 1181 | template <class _InputIterator, class _Tp> | |
| 1182 | _LIBCPP_NODISCARD_EXT inline | |
| 1183 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1184 | typename iterator_traits<_InputIterator>::difference_type | |
| 1185 | count(_InputIterator __first, _InputIterator __last, const _Tp& __value_) | |
| 1186 | { | |
| 1187 | typename iterator_traits<_InputIterator>::difference_type __r(0); | |
| 1188 | for (; __first != __last; ++__first) | |
| 1189 | if (*__first == __value_) | |
| 1190 | ++__r; | |
| 1191 | return __r; | |
| 1192 | } | |
| 1193 | ||
| 1194 | // count_if | |
| 1195 | ||
| 1196 | template <class _InputIterator, class _Predicate> | |
| 1197 | _LIBCPP_NODISCARD_EXT inline | |
| 1198 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1199 | typename iterator_traits<_InputIterator>::difference_type | |
| 1200 | count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 1201 | { | |
| 1202 | typename iterator_traits<_InputIterator>::difference_type __r(0); | |
| 1203 | for (; __first != __last; ++__first) | |
| 1204 | if (__pred(*__first)) | |
| 1205 | ++__r; | |
| 1206 | return __r; | |
| 1207 | } | |
| 1208 | ||
| 1209 | // mismatch | |
| 1210 | ||
| 1211 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 1212 | _LIBCPP_NODISCARD_EXT inline | |
| 1213 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1214 | pair<_InputIterator1, _InputIterator2> | |
| 1215 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 1216 | _InputIterator2 __first2, _BinaryPredicate __pred) | |
| 1217 | { | |
| 1218 | for (; __first1 != __last1; ++__first1, (void) ++__first2) | |
| 1219 | if (!__pred(*__first1, *__first2)) | |
| 1220 | break; | |
| 1221 | return pair<_InputIterator1, _InputIterator2>(__first1, __first2); | |
| 1222 | } | |
| 1223 | ||
| 1224 | template <class _InputIterator1, class _InputIterator2> | |
| 1225 | _LIBCPP_NODISCARD_EXT inline | |
| 1226 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1227 | pair<_InputIterator1, _InputIterator2> | |
| 1228 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) | |
| 1229 | { | |
| 1230 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 1231 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 1232 | return _VSTD::mismatch(__first1, __last1, __first2, __equal_to<__v1, __v2>()); | |
| 1233 | } | |
| 1234 | ||
| 1235 | #if _LIBCPP_STD_VER > 11 | |
| 1236 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 1237 | _LIBCPP_NODISCARD_EXT inline | |
| 1238 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1239 | pair<_InputIterator1, _InputIterator2> | |
| 1240 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 1241 | _InputIterator2 __first2, _InputIterator2 __last2, | |
| 1242 | _BinaryPredicate __pred) | |
| 1243 | { | |
| 1244 | for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void) ++__first2) | |
| 1245 | if (!__pred(*__first1, *__first2)) | |
| 1246 | break; | |
| 1247 | return pair<_InputIterator1, _InputIterator2>(__first1, __first2); | |
| 1248 | } | |
| 1249 | ||
| 1250 | template <class _InputIterator1, class _InputIterator2> | |
| 1251 | _LIBCPP_NODISCARD_EXT inline | |
| 1252 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1253 | pair<_InputIterator1, _InputIterator2> | |
| 1254 | mismatch(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 1255 | _InputIterator2 __first2, _InputIterator2 __last2) | |
| 1256 | { | |
| 1257 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 1258 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 1259 | return _VSTD::mismatch(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 1260 | } | |
| 1261 | #endif | |
| 1262 | ||
| 1263 | // equal | |
| 1264 | ||
| 1265 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 1266 | _LIBCPP_NODISCARD_EXT inline | |
| 1267 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1268 | bool | |
| 1269 | equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) | |
| 1270 | { | |
| 1271 | for (; __first1 != __last1; ++__first1, (void) ++__first2) | |
| 1272 | if (!__pred(*__first1, *__first2)) | |
| 1273 | return false; | |
| 1274 | return true; | |
| 1275 | } | |
| 1276 | ||
| 1277 | template <class _InputIterator1, class _InputIterator2> | |
| 1278 | _LIBCPP_NODISCARD_EXT inline | |
| 1279 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1280 | bool | |
| 1281 | equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) | |
| 1282 | { | |
| 1283 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 1284 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 1285 | return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>()); | |
| 1286 | } | |
| 1287 | ||
| 1288 | #if _LIBCPP_STD_VER > 11 | |
| 1289 | template <class _BinaryPredicate, class _InputIterator1, class _InputIterator2> | |
| 1290 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1291 | bool | |
| 1292 | __equal(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 1293 | _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred, | |
| 1294 | input_iterator_tag, input_iterator_tag ) | |
| 1295 | { | |
| 1296 | for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void) ++__first2) | |
| 1297 | if (!__pred(*__first1, *__first2)) | |
| 1298 | return false; | |
| 1299 | return __first1 == __last1 && __first2 == __last2; | |
| 1300 | } | |
| 1301 | ||
| 1302 | template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 1303 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1304 | bool | |
| 1305 | __equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, | |
| 1306 | _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __pred, | |
| 1307 | random_access_iterator_tag, random_access_iterator_tag ) | |
| 1308 | { | |
| 1309 | if ( _VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) | |
| 1310 | return false; | |
| 1311 | return _VSTD::equal<_RandomAccessIterator1, _RandomAccessIterator2, | |
| 1312 | typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 1313 | (__first1, __last1, __first2, __pred ); | |
| 1314 | } | |
| 1315 | ||
| 1316 | template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> | |
| 1317 | _LIBCPP_NODISCARD_EXT inline | |
| 1318 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1319 | bool | |
| 1320 | equal(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 1321 | _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred ) | |
| 1322 | { | |
| 1323 | return _VSTD::__equal<typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 1324 | (__first1, __last1, __first2, __last2, __pred, | |
| 1325 | typename iterator_traits<_InputIterator1>::iterator_category(), | |
| 1326 | typename iterator_traits<_InputIterator2>::iterator_category()); | |
| 1327 | } | |
| 1328 | ||
| 1329 | template <class _InputIterator1, class _InputIterator2> | |
| 1330 | _LIBCPP_NODISCARD_EXT inline | |
| 1331 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1332 | bool | |
| 1333 | equal(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 1334 | _InputIterator2 __first2, _InputIterator2 __last2) | |
| 1335 | { | |
| 1336 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 1337 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 1338 | return _VSTD::__equal(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(), | |
| 1339 | typename iterator_traits<_InputIterator1>::iterator_category(), | |
| 1340 | typename iterator_traits<_InputIterator2>::iterator_category()); | |
| 1341 | } | |
| 1342 | #endif | |
| 1343 | ||
| 1344 | // is_permutation | |
| 1345 | ||
| 1346 | template<class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 1347 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 1348 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1349 | _ForwardIterator2 __first2, _BinaryPredicate __pred) | |
| 1350 | { | |
| 1351 | // shorten sequences as much as possible by lopping of any equal prefix | |
| 1352 | for (; __first1 != __last1; ++__first1, (void) ++__first2) | |
| 1353 | if (!__pred(*__first1, *__first2)) | |
| 1354 | break; | |
| 1355 | if (__first1 == __last1) | |
| 1356 | return true; | |
| 1357 | ||
| 1358 | // __first1 != __last1 && *__first1 != *__first2 | |
| 1359 | typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; | |
| 1360 | _D1 __l1 = _VSTD::distance(__first1, __last1); | |
| 1361 | if (__l1 == _D1(1)) | |
| 1362 | return false; | |
| 1363 | _ForwardIterator2 __last2 = _VSTD::next(__first2, __l1); | |
| 1364 | // For each element in [f1, l1) see if there are the same number of | |
| 1365 | // equal elements in [f2, l2) | |
| 1366 | for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) | |
| 1367 | { | |
| 1368 | // Have we already counted the number of *__i in [f1, l1)? | |
| 1369 | _ForwardIterator1 __match = __first1; | |
| 1370 | for (; __match != __i; ++__match) | |
| 1371 | if (__pred(*__match, *__i)) | |
| 1372 | break; | |
| 1373 | if (__match == __i) { | |
| 1374 | // Count number of *__i in [f2, l2) | |
| 1375 | _D1 __c2 = 0; | |
| 1376 | for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) | |
| 1377 | if (__pred(*__i, *__j)) | |
| 1378 | ++__c2; | |
| 1379 | if (__c2 == 0) | |
| 1380 | return false; | |
| 1381 | // Count number of *__i in [__i, l1) (we can start with 1) | |
| 1382 | _D1 __c1 = 1; | |
| 1383 | for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) | |
| 1384 | if (__pred(*__i, *__j)) | |
| 1385 | ++__c1; | |
| 1386 | if (__c1 != __c2) | |
| 1387 | return false; | |
| 1388 | } | |
| 1389 | } | |
| 1390 | return true; | |
| 1391 | } | |
| 1392 | ||
| 1393 | template<class _ForwardIterator1, class _ForwardIterator2> | |
| 1394 | _LIBCPP_NODISCARD_EXT inline | |
| 1395 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1396 | bool | |
| 1397 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1398 | _ForwardIterator2 __first2) | |
| 1399 | { | |
| 1400 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 1401 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 1402 | return _VSTD::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>()); | |
| 1403 | } | |
| 1404 | ||
| 1405 | #if _LIBCPP_STD_VER > 11 | |
| 1406 | template<class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2> | |
| 1407 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 1408 | __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1409 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, | |
| 1410 | _BinaryPredicate __pred, | |
| 1411 | forward_iterator_tag, forward_iterator_tag ) | |
| 1412 | { | |
| 1413 | // shorten sequences as much as possible by lopping of any equal prefix | |
| 1414 | for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void) ++__first2) | |
| 1415 | if (!__pred(*__first1, *__first2)) | |
| 1416 | break; | |
| 1417 | if (__first1 == __last1) | |
| 1418 | return __first2 == __last2; | |
| 1419 | else if (__first2 == __last2) | |
| 1420 | return false; | |
| 1421 | ||
| 1422 | typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; | |
| 1423 | _D1 __l1 = _VSTD::distance(__first1, __last1); | |
| 1424 | ||
| 1425 | typedef typename iterator_traits<_ForwardIterator2>::difference_type _D2; | |
| 1426 | _D2 __l2 = _VSTD::distance(__first2, __last2); | |
| 1427 | if (__l1 != __l2) | |
| 1428 | return false; | |
| 1429 | ||
| 1430 | // For each element in [f1, l1) see if there are the same number of | |
| 1431 | // equal elements in [f2, l2) | |
| 1432 | for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) | |
| 1433 | { | |
| 1434 | // Have we already counted the number of *__i in [f1, l1)? | |
| 1435 | _ForwardIterator1 __match = __first1; | |
| 1436 | for (; __match != __i; ++__match) | |
| 1437 | if (__pred(*__match, *__i)) | |
| 1438 | break; | |
| 1439 | if (__match == __i) { | |
| 1440 | // Count number of *__i in [f2, l2) | |
| 1441 | _D1 __c2 = 0; | |
| 1442 | for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) | |
| 1443 | if (__pred(*__i, *__j)) | |
| 1444 | ++__c2; | |
| 1445 | if (__c2 == 0) | |
| 1446 | return false; | |
| 1447 | // Count number of *__i in [__i, l1) (we can start with 1) | |
| 1448 | _D1 __c1 = 1; | |
| 1449 | for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) | |
| 1450 | if (__pred(*__i, *__j)) | |
| 1451 | ++__c1; | |
| 1452 | if (__c1 != __c2) | |
| 1453 | return false; | |
| 1454 | } | |
| 1455 | } | |
| 1456 | return true; | |
| 1457 | } | |
| 1458 | ||
| 1459 | template<class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 1460 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 1461 | __is_permutation(_RandomAccessIterator1 __first1, _RandomAccessIterator2 __last1, | |
| 1462 | _RandomAccessIterator1 __first2, _RandomAccessIterator2 __last2, | |
| 1463 | _BinaryPredicate __pred, | |
| 1464 | random_access_iterator_tag, random_access_iterator_tag ) | |
| 1465 | { | |
| 1466 | if ( _VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) | |
| 1467 | return false; | |
| 1468 | return _VSTD::is_permutation<_RandomAccessIterator1, _RandomAccessIterator2, | |
| 1469 | typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 1470 | (__first1, __last1, __first2, __pred ); | |
| 1471 | } | |
| 1472 | ||
| 1473 | template<class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 1474 | _LIBCPP_NODISCARD_EXT inline | |
| 1475 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1476 | bool | |
| 1477 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1478 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, | |
| 1479 | _BinaryPredicate __pred ) | |
| 1480 | { | |
| 1481 | return _VSTD::__is_permutation<typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 1482 | (__first1, __last1, __first2, __last2, __pred, | |
| 1483 | typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 1484 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 1485 | } | |
| 1486 | ||
| 1487 | template<class _ForwardIterator1, class _ForwardIterator2> | |
| 1488 | _LIBCPP_NODISCARD_EXT inline | |
| 1489 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1490 | bool | |
| 1491 | is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1492 | _ForwardIterator2 __first2, _ForwardIterator2 __last2) | |
| 1493 | { | |
| 1494 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 1495 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 1496 | return _VSTD::__is_permutation(__first1, __last1, __first2, __last2, | |
| 1497 | __equal_to<__v1, __v2>(), | |
| 1498 | typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 1499 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 1500 | } | |
| 1501 | #endif | |
| 1502 | ||
| 1503 | // search | |
| 1504 | // __search is in <functional> | |
| 1505 | ||
| 1506 | template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> | |
| 1507 | _LIBCPP_NODISCARD_EXT inline | |
| 1508 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1509 | _ForwardIterator1 | |
| 1510 | search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1511 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) | |
| 1512 | { | |
| 1513 | return _VSTD::__search<typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 1514 | (__first1, __last1, __first2, __last2, __pred, | |
| 1515 | typename iterator_traits<_ForwardIterator1>::iterator_category(), | |
| 1516 | typename iterator_traits<_ForwardIterator2>::iterator_category()) | |
| 1517 | .first; | |
| 1518 | } | |
| 1519 | ||
| 1520 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 1521 | _LIBCPP_NODISCARD_EXT inline | |
| 1522 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1523 | _ForwardIterator1 | |
| 1524 | search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 1525 | _ForwardIterator2 __first2, _ForwardIterator2 __last2) | |
| 1526 | { | |
| 1527 | typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; | |
| 1528 | typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; | |
| 1529 | return _VSTD::search(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>()); | |
| 1530 | } | |
| 1531 | ||
| 1532 | ||
| 1533 | #if _LIBCPP_STD_VER > 14 | |
| 1534 | template <class _ForwardIterator, class _Searcher> | |
| 1535 | _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1536 | _ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher &__s) | |
| 1537 | { return __s(__f, __l).first; } | |
| 1538 | #endif | |
| 1539 | ||
| 1540 | // search_n | |
| 1541 | ||
| 1542 | template <class _BinaryPredicate, class _ForwardIterator, class _Size, class _Tp> | |
| 1543 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 1544 | __search_n(_ForwardIterator __first, _ForwardIterator __last, | |
| 1545 | _Size __count, const _Tp& __value_, _BinaryPredicate __pred, forward_iterator_tag) | |
| 1546 | { | |
| 1547 | if (__count <= 0) | |
| 1548 | return __first; | |
| 1549 | while (true) | |
| 1550 | { | |
| 1551 | // Find first element in sequence that matchs __value_, with a mininum of loop checks | |
| 1552 | while (true) | |
| 1553 | { | |
| 1554 | if (__first == __last) // return __last if no element matches __value_ | |
| 1555 | return __last; | |
| 1556 | if (__pred(*__first, __value_)) | |
| 1557 | break; | |
| 1558 | ++__first; | |
| 1559 | } | |
| 1560 | // *__first matches __value_, now match elements after here | |
| 1561 | _ForwardIterator __m = __first; | |
| 1562 | _Size __c(0); | |
| 1563 | while (true) | |
| 1564 | { | |
| 1565 | if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern) | |
| 1566 | return __first; | |
| 1567 | if (++__m == __last) // Otherwise if source exhaused, pattern not found | |
| 1568 | return __last; | |
| 1569 | if (!__pred(*__m, __value_)) // if there is a mismatch, restart with a new __first | |
| 1570 | { | |
| 1571 | __first = __m; | |
| 1572 | ++__first; | |
| 1573 | break; | |
| 1574 | } // else there is a match, check next elements | |
| 1575 | } | |
| 1576 | } | |
| 1577 | } | |
| 1578 | ||
| 1579 | template <class _BinaryPredicate, class _RandomAccessIterator, class _Size, class _Tp> | |
| 1580 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator | |
| 1581 | __search_n(_RandomAccessIterator __first, _RandomAccessIterator __last, | |
| 1582 | _Size __count, const _Tp& __value_, _BinaryPredicate __pred, random_access_iterator_tag) | |
| 1583 | { | |
| 1584 | if (__count <= 0) | |
| 1585 | return __first; | |
| 1586 | _Size __len = static_cast<_Size>(__last - __first); | |
| 1587 | if (__len < __count) | |
| 1588 | return __last; | |
| 1589 | const _RandomAccessIterator __s = __last - (__count - 1); // Start of pattern match can't go beyond here | |
| 1590 | while (true) | |
| 1591 | { | |
| 1592 | // Find first element in sequence that matchs __value_, with a mininum of loop checks | |
| 1593 | while (true) | |
| 1594 | { | |
| 1595 | if (__first >= __s) // return __last if no element matches __value_ | |
| 1596 | return __last; | |
| 1597 | if (__pred(*__first, __value_)) | |
| 1598 | break; | |
| 1599 | ++__first; | |
| 1600 | } | |
| 1601 | // *__first matches __value_, now match elements after here | |
| 1602 | _RandomAccessIterator __m = __first; | |
| 1603 | _Size __c(0); | |
| 1604 | while (true) | |
| 1605 | { | |
| 1606 | if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern) | |
| 1607 | return __first; | |
| 1608 | ++__m; // no need to check range on __m because __s guarantees we have enough source | |
| 1609 | if (!__pred(*__m, __value_)) // if there is a mismatch, restart with a new __first | |
| 1610 | { | |
| 1611 | __first = __m; | |
| 1612 | ++__first; | |
| 1613 | break; | |
| 1614 | } // else there is a match, check next elements | |
| 1615 | } | |
| 1616 | } | |
| 1617 | } | |
| 1618 | ||
| 1619 | template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> | |
| 1620 | _LIBCPP_NODISCARD_EXT inline | |
| 1621 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1622 | _ForwardIterator | |
| 1623 | search_n(_ForwardIterator __first, _ForwardIterator __last, | |
| 1624 | _Size __count, const _Tp& __value_, _BinaryPredicate __pred) | |
| 1625 | { | |
| 1626 | return _VSTD::__search_n<typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 1627 | (__first, __last, _VSTD::__convert_to_integral(__count), __value_, __pred, | |
| 1628 | typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 1629 | } | |
| 1630 | ||
| 1631 | template <class _ForwardIterator, class _Size, class _Tp> | |
| 1632 | _LIBCPP_NODISCARD_EXT inline | |
| 1633 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1634 | _ForwardIterator | |
| 1635 | search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value_) | |
| 1636 | { | |
| 1637 | typedef typename iterator_traits<_ForwardIterator>::value_type __v; | |
| 1638 | return _VSTD::search_n(__first, __last, _VSTD::__convert_to_integral(__count), | |
| 1639 | __value_, __equal_to<__v, _Tp>()); | |
| 1640 | } | |
| 1641 | ||
| 1642 | // copy | |
| 1643 | template <class _Iter> | |
| 1644 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1645 | _Iter | |
| 1646 | __unwrap_iter(_Iter __i) | |
| 1647 | { | |
| 1648 | return __i; | |
| 1649 | } | |
| 1650 | ||
| 1651 | template <class _Tp> | |
| 1652 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1653 | typename enable_if | |
| 1654 | < | |
| 1655 | is_trivially_copy_assignable<_Tp>::value, | |
| 1656 | _Tp* | |
| 1657 | >::type | |
| 1658 | __unwrap_iter(move_iterator<_Tp*> __i) | |
| 1659 | { | |
| 1660 | return __i.base(); | |
| 1661 | } | |
| 1662 | ||
| 1663 | #if _LIBCPP_DEBUG_LEVEL < 2 | |
| 1664 | ||
| 1665 | template <class _Tp> | |
| 1666 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1667 | typename enable_if | |
| 1668 | < | |
| 1669 | is_trivially_copy_assignable<_Tp>::value, | |
| 1670 | _Tp* | |
| 1671 | >::type | |
| 1672 | __unwrap_iter(__wrap_iter<_Tp*> __i) | |
| 1673 | { | |
| 1674 | return __i.base(); | |
| 1675 | } | |
| 1676 | ||
| 1677 | template <class _Tp> | |
| 1678 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1679 | typename enable_if | |
| 1680 | < | |
| 1681 | is_trivially_copy_assignable<_Tp>::value, | |
| 1682 | const _Tp* | |
| 1683 | >::type | |
| 1684 | __unwrap_iter(__wrap_iter<const _Tp*> __i) | |
| 1685 | { | |
| 1686 | return __i.base(); | |
| 1687 | } | |
| 1688 | ||
| 1689 | #else | |
| 1690 | ||
| 1691 | template <class _Tp> | |
| 1692 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1693 | typename enable_if | |
| 1694 | < | |
| 1695 | is_trivially_copy_assignable<_Tp>::value, | |
| 1696 | __wrap_iter<_Tp*> | |
| 1697 | >::type | |
| 1698 | __unwrap_iter(__wrap_iter<_Tp*> __i) | |
| 1699 | { | |
| 1700 | return __i; | |
| 1701 | } | |
| 1702 | ||
| 1703 | #endif // _LIBCPP_DEBUG_LEVEL < 2 | |
| 1704 | ||
| 1705 | template <class _InputIterator, class _OutputIterator> | |
| 1706 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1707 | _OutputIterator | |
| 1708 | __copy_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1709 | { | |
| 1710 | for (; __first != __last; ++__first, (void) ++__result) | |
| 1711 | *__result = *__first; | |
| 1712 | return __result; | |
| 1713 | } | |
| 1714 | ||
| 1715 | template <class _InputIterator, class _OutputIterator> | |
| 1716 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1717 | _OutputIterator | |
| 1718 | __copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1719 | { | |
| 1720 | return _VSTD::__copy_constexpr(__first, __last, __result); | |
| 1721 | } | |
| 1722 | ||
| 1723 | template <class _Tp, class _Up> | |
| 1724 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1725 | typename enable_if | |
| 1726 | < | |
| 1727 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 1728 | is_trivially_copy_assignable<_Up>::value, | |
| 1729 | _Up* | |
| 1730 | >::type | |
| 1731 | __copy(_Tp* __first, _Tp* __last, _Up* __result) | |
| 1732 | { | |
| 1733 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 1734 | if (__n > 0) | |
| 1735 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 1736 | return __result + __n; | |
| 1737 | } | |
| 1738 | ||
| 1739 | template <class _InputIterator, class _OutputIterator> | |
| 1740 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1741 | _OutputIterator | |
| 1742 | copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1743 | { | |
| 1744 | if (__libcpp_is_constant_evaluated()) { | |
| 1745 | return _VSTD::__copy_constexpr( | |
| 1746 | _VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result)); | |
| 1747 | } else { | |
| 1748 | return _VSTD::__copy( | |
| 1749 | _VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result)); | |
| 1750 | } | |
| 1751 | } | |
| 1752 | ||
| 1753 | // copy_backward | |
| 1754 | ||
| 1755 | template <class _BidirectionalIterator, class _OutputIterator> | |
| 1756 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1757 | _OutputIterator | |
| 1758 | __copy_backward_constexpr(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) | |
| 1759 | { | |
| 1760 | while (__first != __last) | |
| 1761 | *--__result = *--__last; | |
| 1762 | return __result; | |
| 1763 | } | |
| 1764 | ||
| 1765 | template <class _BidirectionalIterator, class _OutputIterator> | |
| 1766 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1767 | _OutputIterator | |
| 1768 | __copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) | |
| 1769 | { | |
| 1770 | return _VSTD::__copy_backward_constexpr(__first, __last, __result); | |
| 1771 | } | |
| 1772 | ||
| 1773 | template <class _Tp, class _Up> | |
| 1774 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1775 | typename enable_if | |
| 1776 | < | |
| 1777 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 1778 | is_trivially_copy_assignable<_Up>::value, | |
| 1779 | _Up* | |
| 1780 | >::type | |
| 1781 | __copy_backward(_Tp* __first, _Tp* __last, _Up* __result) | |
| 1782 | { | |
| 1783 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 1784 | if (__n > 0) | |
| 1785 | { | |
| 1786 | __result -= __n; | |
| 1787 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 1788 | } | |
| 1789 | return __result; | |
| 1790 | } | |
| 1791 | ||
| 1792 | template <class _BidirectionalIterator1, class _BidirectionalIterator2> | |
| 1793 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1794 | _BidirectionalIterator2 | |
| 1795 | copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, | |
| 1796 | _BidirectionalIterator2 __result) | |
| 1797 | { | |
| 1798 | if (__libcpp_is_constant_evaluated()) { | |
| 1799 | return _VSTD::__copy_backward_constexpr(_VSTD::__unwrap_iter(__first), | |
| 1800 | _VSTD::__unwrap_iter(__last), | |
| 1801 | _VSTD::__unwrap_iter(__result)); | |
| 1802 | } else { | |
| 1803 | return _VSTD::__copy_backward(_VSTD::__unwrap_iter(__first), | |
| 1804 | _VSTD::__unwrap_iter(__last), | |
| 1805 | _VSTD::__unwrap_iter(__result)); | |
| 1806 | } | |
| 1807 | } | |
| 1808 | ||
| 1809 | // copy_if | |
| 1810 | ||
| 1811 | template<class _InputIterator, class _OutputIterator, class _Predicate> | |
| 1812 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1813 | _OutputIterator | |
| 1814 | copy_if(_InputIterator __first, _InputIterator __last, | |
| 1815 | _OutputIterator __result, _Predicate __pred) | |
| 1816 | { | |
| 1817 | for (; __first != __last; ++__first) | |
| 1818 | { | |
| 1819 | if (__pred(*__first)) | |
| 1820 | { | |
| 1821 | *__result = *__first; | |
| 1822 | ++__result; | |
| 1823 | } | |
| 1824 | } | |
| 1825 | return __result; | |
| 1826 | } | |
| 1827 | ||
| 1828 | // copy_n | |
| 1829 | ||
| 1830 | template<class _InputIterator, class _Size, class _OutputIterator> | |
| 1831 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1832 | typename enable_if | |
| 1833 | < | |
| 1834 | __is_cpp17_input_iterator<_InputIterator>::value && | |
| 1835 | !__is_cpp17_random_access_iterator<_InputIterator>::value, | |
| 1836 | _OutputIterator | |
| 1837 | >::type | |
| 1838 | copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) | |
| 1839 | { | |
| 1840 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 1841 | _IntegralSize __n = __orig_n; | |
| 1842 | if (__n > 0) | |
| 1843 | { | |
| 1844 | *__result = *__first; | |
| 1845 | ++__result; | |
| 1846 | for (--__n; __n > 0; --__n) | |
| 1847 | { | |
| 1848 | ++__first; | |
| 1849 | *__result = *__first; | |
| 1850 | ++__result; | |
| 1851 | } | |
| 1852 | } | |
| 1853 | return __result; | |
| 1854 | } | |
| 1855 | ||
| 1856 | template<class _InputIterator, class _Size, class _OutputIterator> | |
| 1857 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1858 | typename enable_if | |
| 1859 | < | |
| 1860 | __is_cpp17_random_access_iterator<_InputIterator>::value, | |
| 1861 | _OutputIterator | |
| 1862 | >::type | |
| 1863 | copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) | |
| 1864 | { | |
| 1865 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 1866 | _IntegralSize __n = __orig_n; | |
| 1867 | return _VSTD::copy(__first, __first + __n, __result); | |
| 1868 | } | |
| 1869 | ||
| 1870 | // move | |
| 1871 | ||
| 1872 | // __move_constexpr exists so that __move doesn't call itself when delegating to the constexpr | |
| 1873 | // version of __move. | |
| 1874 | template <class _InputIterator, class _OutputIterator> | |
| 1875 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1876 | _OutputIterator | |
| 1877 | __move_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1878 | { | |
| 1879 | for (; __first != __last; ++__first, (void) ++__result) | |
| 1880 | *__result = _VSTD::move(*__first); | |
| 1881 | return __result; | |
| 1882 | } | |
| 1883 | ||
| 1884 | template <class _InputIterator, class _OutputIterator> | |
| 1885 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1886 | _OutputIterator | |
| 1887 | __move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1888 | { | |
| 1889 | return _VSTD::__move_constexpr(__first, __last, __result); | |
| 1890 | } | |
| 1891 | ||
| 1892 | template <class _Tp, class _Up> | |
| 1893 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1894 | typename enable_if | |
| 1895 | < | |
| 1896 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 1897 | is_trivially_copy_assignable<_Up>::value, | |
| 1898 | _Up* | |
| 1899 | >::type | |
| 1900 | __move(_Tp* __first, _Tp* __last, _Up* __result) | |
| 1901 | { | |
| 1902 | if (__libcpp_is_constant_evaluated()) | |
| 1903 | return _VSTD::__move_constexpr(__first, __last, __result); | |
| 1904 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 1905 | if (__n > 0) | |
| 1906 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 1907 | return __result + __n; | |
| 1908 | } | |
| 1909 | ||
| 1910 | template <class _InputIterator, class _OutputIterator> | |
| 1911 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1912 | _OutputIterator | |
| 1913 | move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1914 | { | |
| 1915 | return _VSTD::__move(_VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result)); | |
| 1916 | } | |
| 1917 | ||
| 1918 | // move_backward | |
| 1919 | ||
| 1920 | // __move_backward_constexpr exists so that __move_backward doesn't call itself when delegating to | |
| 1921 | // the constexpr version of __move_backward. | |
| 1922 | template <class _InputIterator, class _OutputIterator> | |
| 1923 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1924 | _OutputIterator | |
| 1925 | __move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1926 | { | |
| 1927 | while (__first != __last) | |
| 1928 | *--__result = _VSTD::move(*--__last); | |
| 1929 | return __result; | |
| 1930 | } | |
| 1931 | ||
| 1932 | template <class _InputIterator, class _OutputIterator> | |
| 1933 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1934 | _OutputIterator | |
| 1935 | __move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 1936 | { | |
| 1937 | return _VSTD::__move_backward_constexpr(__first, __last, __result); | |
| 1938 | } | |
| 1939 | ||
| 1940 | template <class _Tp, class _Up> | |
| 1941 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1942 | typename enable_if | |
| 1943 | < | |
| 1944 | is_same<typename remove_const<_Tp>::type, _Up>::value && | |
| 1945 | is_trivially_copy_assignable<_Up>::value, | |
| 1946 | _Up* | |
| 1947 | >::type | |
| 1948 | __move_backward(_Tp* __first, _Tp* __last, _Up* __result) | |
| 1949 | { | |
| 1950 | if (__libcpp_is_constant_evaluated()) | |
| 1951 | return _VSTD::__move_backward_constexpr(__first, __last, __result); | |
| 1952 | const size_t __n = static_cast<size_t>(__last - __first); | |
| 1953 | if (__n > 0) | |
| 1954 | { | |
| 1955 | __result -= __n; | |
| 1956 | _VSTD::memmove(__result, __first, __n * sizeof(_Up)); | |
| 1957 | } | |
| 1958 | return __result; | |
| 1959 | } | |
| 1960 | ||
| 1961 | template <class _BidirectionalIterator1, class _BidirectionalIterator2> | |
| 1962 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1963 | _BidirectionalIterator2 | |
| 1964 | move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, | |
| 1965 | _BidirectionalIterator2 __result) | |
| 1966 | { | |
| 1967 | return _VSTD::__move_backward(_VSTD::__unwrap_iter(__first), _VSTD::__unwrap_iter(__last), _VSTD::__unwrap_iter(__result)); | |
| 1968 | } | |
| 1969 | ||
| 1970 | // iter_swap | |
| 1971 | ||
| 1972 | // moved to <type_traits> for better swap / noexcept support | |
| 1973 | ||
| 1974 | // transform | |
| 1975 | ||
| 1976 | template <class _InputIterator, class _OutputIterator, class _UnaryOperation> | |
| 1977 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1978 | _OutputIterator | |
| 1979 | transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op) | |
| 1980 | { | |
| 1981 | for (; __first != __last; ++__first, (void) ++__result) | |
| 1982 | *__result = __op(*__first); | |
| 1983 | return __result; | |
| 1984 | } | |
| 1985 | ||
| 1986 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _BinaryOperation> | |
| 1987 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1988 | _OutputIterator | |
| 1989 | transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, | |
| 1990 | _OutputIterator __result, _BinaryOperation __binary_op) | |
| 1991 | { | |
| 1992 | for (; __first1 != __last1; ++__first1, (void) ++__first2, ++__result) | |
| 1993 | *__result = __binary_op(*__first1, *__first2); | |
| 1994 | return __result; | |
| 1995 | } | |
| 1996 | ||
| 1997 | // replace | |
| 1998 | ||
| 1999 | template <class _ForwardIterator, class _Tp> | |
| 2000 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2001 | void | |
| 2002 | replace(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __old_value, const _Tp& __new_value) | |
| 2003 | { | |
| 2004 | for (; __first != __last; ++__first) | |
| 2005 | if (*__first == __old_value) | |
| 2006 | *__first = __new_value; | |
| 2007 | } | |
| 2008 | ||
| 2009 | // replace_if | |
| 2010 | ||
| 2011 | template <class _ForwardIterator, class _Predicate, class _Tp> | |
| 2012 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2013 | void | |
| 2014 | replace_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, const _Tp& __new_value) | |
| 2015 | { | |
| 2016 | for (; __first != __last; ++__first) | |
| 2017 | if (__pred(*__first)) | |
| 2018 | *__first = __new_value; | |
| 2019 | } | |
| 2020 | ||
| 2021 | // replace_copy | |
| 2022 | ||
| 2023 | template <class _InputIterator, class _OutputIterator, class _Tp> | |
| 2024 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2025 | _OutputIterator | |
| 2026 | replace_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, | |
| 2027 | const _Tp& __old_value, const _Tp& __new_value) | |
| 2028 | { | |
| 2029 | for (; __first != __last; ++__first, (void) ++__result) | |
| 2030 | if (*__first == __old_value) | |
| 2031 | *__result = __new_value; | |
| 2032 | else | |
| 2033 | *__result = *__first; | |
| 2034 | return __result; | |
| 2035 | } | |
| 2036 | ||
| 2037 | // replace_copy_if | |
| 2038 | ||
| 2039 | template <class _InputIterator, class _OutputIterator, class _Predicate, class _Tp> | |
| 2040 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2041 | _OutputIterator | |
| 2042 | replace_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, | |
| 2043 | _Predicate __pred, const _Tp& __new_value) | |
| 2044 | { | |
| 2045 | for (; __first != __last; ++__first, (void) ++__result) | |
| 2046 | if (__pred(*__first)) | |
| 2047 | *__result = __new_value; | |
| 2048 | else | |
| 2049 | *__result = *__first; | |
| 2050 | return __result; | |
| 2051 | } | |
| 2052 | ||
| 2053 | // fill_n | |
| 2054 | ||
| 2055 | template <class _OutputIterator, class _Size, class _Tp> | |
| 2056 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2057 | _OutputIterator | |
| 2058 | __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_) | |
| 2059 | { | |
| 2060 | for (; __n > 0; ++__first, (void) --__n) | |
| 2061 | *__first = __value_; | |
| 2062 | return __first; | |
| 2063 | } | |
| 2064 | ||
| 2065 | template <class _OutputIterator, class _Size, class _Tp> | |
| 2066 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2067 | _OutputIterator | |
| 2068 | fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_) | |
| 2069 | { | |
| 2070 | return _VSTD::__fill_n(__first, _VSTD::__convert_to_integral(__n), __value_); | |
| 2071 | } | |
| 2072 | ||
| 2073 | // fill | |
| 2074 | ||
| 2075 | template <class _ForwardIterator, class _Tp> | |
| 2076 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2077 | void | |
| 2078 | __fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, forward_iterator_tag) | |
| 2079 | { | |
| 2080 | for (; __first != __last; ++__first) | |
| 2081 | *__first = __value_; | |
| 2082 | } | |
| 2083 | ||
| 2084 | template <class _RandomAccessIterator, class _Tp> | |
| 2085 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2086 | void | |
| 2087 | __fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value_, random_access_iterator_tag) | |
| 2088 | { | |
| 2089 | _VSTD::fill_n(__first, __last - __first, __value_); | |
| 2090 | } | |
| 2091 | ||
| 2092 | template <class _ForwardIterator, class _Tp> | |
| 2093 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2094 | void | |
| 2095 | fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 2096 | { | |
| 2097 | _VSTD::__fill(__first, __last, __value_, typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 2098 | } | |
| 2099 | ||
| 2100 | // generate | |
| 2101 | ||
| 2102 | template <class _ForwardIterator, class _Generator> | |
| 2103 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2104 | void | |
| 2105 | generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) | |
| 2106 | { | |
| 2107 | for (; __first != __last; ++__first) | |
| 2108 | *__first = __gen(); | |
| 2109 | } | |
| 2110 | ||
| 2111 | // generate_n | |
| 2112 | ||
| 2113 | template <class _OutputIterator, class _Size, class _Generator> | |
| 2114 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2115 | _OutputIterator | |
| 2116 | generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) | |
| 2117 | { | |
| 2118 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 2119 | _IntegralSize __n = __orig_n; | |
| 2120 | for (; __n > 0; ++__first, (void) --__n) | |
| 2121 | *__first = __gen(); | |
| 2122 | return __first; | |
| 2123 | } | |
| 2124 | ||
| 2125 | // remove | |
| 2126 | ||
| 2127 | template <class _ForwardIterator, class _Tp> | |
| 2128 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 2129 | remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 2130 | { | |
| 2131 | __first = _VSTD::find(__first, __last, __value_); | |
| 2132 | if (__first != __last) | |
| 2133 | { | |
| 2134 | _ForwardIterator __i = __first; | |
| 2135 | while (++__i != __last) | |
| 2136 | { | |
| 2137 | if (!(*__i == __value_)) | |
| 2138 | { | |
| 2139 | *__first = _VSTD::move(*__i); | |
| 2140 | ++__first; | |
| 2141 | } | |
| 2142 | } | |
| 2143 | } | |
| 2144 | return __first; | |
| 2145 | } | |
| 2146 | ||
| 2147 | // remove_if | |
| 2148 | ||
| 2149 | template <class _ForwardIterator, class _Predicate> | |
| 2150 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 2151 | remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 2152 | { | |
| 2153 | __first = _VSTD::find_if<_ForwardIterator, typename add_lvalue_reference<_Predicate>::type> | |
| 2154 | (__first, __last, __pred); | |
| 2155 | if (__first != __last) | |
| 2156 | { | |
| 2157 | _ForwardIterator __i = __first; | |
| 2158 | while (++__i != __last) | |
| 2159 | { | |
| 2160 | if (!__pred(*__i)) | |
| 2161 | { | |
| 2162 | *__first = _VSTD::move(*__i); | |
| 2163 | ++__first; | |
| 2164 | } | |
| 2165 | } | |
| 2166 | } | |
| 2167 | return __first; | |
| 2168 | } | |
| 2169 | ||
| 2170 | // remove_copy | |
| 2171 | ||
| 2172 | template <class _InputIterator, class _OutputIterator, class _Tp> | |
| 2173 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2174 | _OutputIterator | |
| 2175 | remove_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, const _Tp& __value_) | |
| 2176 | { | |
| 2177 | for (; __first != __last; ++__first) | |
| 2178 | { | |
| 2179 | if (!(*__first == __value_)) | |
| 2180 | { | |
| 2181 | *__result = *__first; | |
| 2182 | ++__result; | |
| 2183 | } | |
| 2184 | } | |
| 2185 | return __result; | |
| 2186 | } | |
| 2187 | ||
| 2188 | // remove_copy_if | |
| 2189 | ||
| 2190 | template <class _InputIterator, class _OutputIterator, class _Predicate> | |
| 2191 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2192 | _OutputIterator | |
| 2193 | remove_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred) | |
| 2194 | { | |
| 2195 | for (; __first != __last; ++__first) | |
| 2196 | { | |
| 2197 | if (!__pred(*__first)) | |
| 2198 | { | |
| 2199 | *__result = *__first; | |
| 2200 | ++__result; | |
| 2201 | } | |
| 2202 | } | |
| 2203 | return __result; | |
| 2204 | } | |
| 2205 | ||
| 2206 | // unique | |
| 2207 | ||
| 2208 | template <class _ForwardIterator, class _BinaryPredicate> | |
| 2209 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 2210 | unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) | |
| 2211 | { | |
| 2212 | __first = _VSTD::adjacent_find<_ForwardIterator, typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 2213 | (__first, __last, __pred); | |
| 2214 | if (__first != __last) | |
| 2215 | { | |
| 2216 | // ... a a ? ... | |
| 2217 | // f i | |
| 2218 | _ForwardIterator __i = __first; | |
| 2219 | for (++__i; ++__i != __last;) | |
| 2220 | if (!__pred(*__first, *__i)) | |
| 2221 | *++__first = _VSTD::move(*__i); | |
| 2222 | ++__first; | |
| 2223 | } | |
| 2224 | return __first; | |
| 2225 | } | |
| 2226 | ||
| 2227 | template <class _ForwardIterator> | |
| 2228 | _LIBCPP_NODISCARD_EXT inline | |
| 2229 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2230 | _ForwardIterator | |
| 2231 | unique(_ForwardIterator __first, _ForwardIterator __last) | |
| 2232 | { | |
| 2233 | typedef typename iterator_traits<_ForwardIterator>::value_type __v; | |
| 2234 | return _VSTD::unique(__first, __last, __equal_to<__v>()); | |
| 2235 | } | |
| 2236 | ||
| 2237 | // unique_copy | |
| 2238 | ||
| 2239 | template <class _BinaryPredicate, class _InputIterator, class _OutputIterator> | |
| 2240 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 2241 | __unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred, | |
| 2242 | input_iterator_tag, output_iterator_tag) | |
| 2243 | { | |
| 2244 | if (__first != __last) | |
| 2245 | { | |
| 2246 | typename iterator_traits<_InputIterator>::value_type __t(*__first); | |
| 2247 | *__result = __t; | |
| 2248 | ++__result; | |
| 2249 | while (++__first != __last) | |
| 2250 | { | |
| 2251 | if (!__pred(__t, *__first)) | |
| 2252 | { | |
| 2253 | __t = *__first; | |
| 2254 | *__result = __t; | |
| 2255 | ++__result; | |
| 2256 | } | |
| 2257 | } | |
| 2258 | } | |
| 2259 | return __result; | |
| 2260 | } | |
| 2261 | ||
| 2262 | template <class _BinaryPredicate, class _ForwardIterator, class _OutputIterator> | |
| 2263 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 2264 | __unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred, | |
| 2265 | forward_iterator_tag, output_iterator_tag) | |
| 2266 | { | |
| 2267 | if (__first != __last) | |
| 2268 | { | |
| 2269 | _ForwardIterator __i = __first; | |
| 2270 | *__result = *__i; | |
| 2271 | ++__result; | |
| 2272 | while (++__first != __last) | |
| 2273 | { | |
| 2274 | if (!__pred(*__i, *__first)) | |
| 2275 | { | |
| 2276 | *__result = *__first; | |
| 2277 | ++__result; | |
| 2278 | __i = __first; | |
| 2279 | } | |
| 2280 | } | |
| 2281 | } | |
| 2282 | return __result; | |
| 2283 | } | |
| 2284 | ||
| 2285 | template <class _BinaryPredicate, class _InputIterator, class _ForwardIterator> | |
| 2286 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 2287 | __unique_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result, _BinaryPredicate __pred, | |
| 2288 | input_iterator_tag, forward_iterator_tag) | |
| 2289 | { | |
| 2290 | if (__first != __last) | |
| 2291 | { | |
| 2292 | *__result = *__first; | |
| 2293 | while (++__first != __last) | |
| 2294 | if (!__pred(*__result, *__first)) | |
| 2295 | *++__result = *__first; | |
| 2296 | ++__result; | |
| 2297 | } | |
| 2298 | return __result; | |
| 2299 | } | |
| 2300 | ||
| 2301 | template <class _InputIterator, class _OutputIterator, class _BinaryPredicate> | |
| 2302 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2303 | _OutputIterator | |
| 2304 | unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) | |
| 2305 | { | |
| 2306 | return _VSTD::__unique_copy<typename add_lvalue_reference<_BinaryPredicate>::type> | |
| 2307 | (__first, __last, __result, __pred, | |
| 2308 | typename iterator_traits<_InputIterator>::iterator_category(), | |
| 2309 | typename iterator_traits<_OutputIterator>::iterator_category()); | |
| 2310 | } | |
| 2311 | ||
| 2312 | template <class _InputIterator, class _OutputIterator> | |
| 2313 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2314 | _OutputIterator | |
| 2315 | unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
| 2316 | { | |
| 2317 | typedef typename iterator_traits<_InputIterator>::value_type __v; | |
| 2318 | return _VSTD::unique_copy(__first, __last, __result, __equal_to<__v>()); | |
| 2319 | } | |
| 2320 | ||
| 2321 | // reverse | |
| 2322 | ||
| 2323 | template <class _BidirectionalIterator> | |
| 2324 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2325 | void | |
| 2326 | __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag) | |
| 2327 | { | |
| 2328 | while (__first != __last) | |
| 2329 | { | |
| 2330 | if (__first == --__last) | |
| 2331 | break; | |
| 2332 | _VSTD::iter_swap(__first, __last); | |
| 2333 | ++__first; | |
| 2334 | } | |
| 2335 | } | |
| 2336 | ||
| 2337 | template <class _RandomAccessIterator> | |
| 2338 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2339 | void | |
| 2340 | __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) | |
| 2341 | { | |
| 2342 | if (__first != __last) | |
| 2343 | for (; __first < --__last; ++__first) | |
| 2344 | _VSTD::iter_swap(__first, __last); | |
| 2345 | } | |
| 2346 | ||
| 2347 | template <class _BidirectionalIterator> | |
| 2348 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2349 | void | |
| 2350 | reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 2351 | { | |
| 2352 | _VSTD::__reverse(__first, __last, typename iterator_traits<_BidirectionalIterator>::iterator_category()); | |
| 2353 | } | |
| 2354 | ||
| 2355 | // reverse_copy | |
| 2356 | ||
| 2357 | template <class _BidirectionalIterator, class _OutputIterator> | |
| 2358 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2359 | _OutputIterator | |
| 2360 | reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) | |
| 2361 | { | |
| 2362 | for (; __first != __last; ++__result) | |
| 2363 | *__result = *--__last; | |
| 2364 | return __result; | |
| 2365 | } | |
| 2366 | ||
| 2367 | // rotate | |
| 2368 | ||
| 2369 | template <class _ForwardIterator> | |
| 2370 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator | |
| 2371 | __rotate_left(_ForwardIterator __first, _ForwardIterator __last) | |
| 2372 | { | |
| 2373 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 2374 | value_type __tmp = _VSTD::move(*__first); | |
| 2375 | _ForwardIterator __lm1 = _VSTD::move(_VSTD::next(__first), __last, __first); | |
| 2376 | *__lm1 = _VSTD::move(__tmp); | |
| 2377 | return __lm1; | |
| 2378 | } | |
| 2379 | ||
| 2380 | template <class _BidirectionalIterator> | |
| 2381 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator | |
| 2382 | __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 2383 | { | |
| 2384 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 2385 | _BidirectionalIterator __lm1 = _VSTD::prev(__last); | |
| 2386 | value_type __tmp = _VSTD::move(*__lm1); | |
| 2387 | _BidirectionalIterator __fp1 = _VSTD::move_backward(__first, __lm1, __last); | |
| 2388 | *__first = _VSTD::move(__tmp); | |
| 2389 | return __fp1; | |
| 2390 | } | |
| 2391 | ||
| 2392 | template <class _ForwardIterator> | |
| 2393 | _LIBCPP_CONSTEXPR_AFTER_CXX14 _ForwardIterator | |
| 2394 | __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) | |
| 2395 | { | |
| 2396 | _ForwardIterator __i = __middle; | |
| 2397 | while (true) | |
| 2398 | { | |
| 2399 | swap(*__first, *__i); | |
| 2400 | ++__first; | |
| 2401 | if (++__i == __last) | |
| 2402 | break; | |
| 2403 | if (__first == __middle) | |
| 2404 | __middle = __i; | |
| 2405 | } | |
| 2406 | _ForwardIterator __r = __first; | |
| 2407 | if (__first != __middle) | |
| 2408 | { | |
| 2409 | __i = __middle; | |
| 2410 | while (true) | |
| 2411 | { | |
| 2412 | swap(*__first, *__i); | |
| 2413 | ++__first; | |
| 2414 | if (++__i == __last) | |
| 2415 | { | |
| 2416 | if (__first == __middle) | |
| 2417 | break; | |
| 2418 | __i = __middle; | |
| 2419 | } | |
| 2420 | else if (__first == __middle) | |
| 2421 | __middle = __i; | |
| 2422 | } | |
| 2423 | } | |
| 2424 | return __r; | |
| 2425 | } | |
| 2426 | ||
| 2427 | template<typename _Integral> | |
| 2428 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2429 | _LIBCPP_CONSTEXPR_AFTER_CXX14 _Integral | |
| 2430 | __algo_gcd(_Integral __x, _Integral __y) | |
| 2431 | { | |
| 2432 | do | |
| 2433 | { | |
| 2434 | _Integral __t = __x % __y; | |
| 2435 | __x = __y; | |
| 2436 | __y = __t; | |
| 2437 | } while (__y); | |
| 2438 | return __x; | |
| 2439 | } | |
| 2440 | ||
| 2441 | template<typename _RandomAccessIterator> | |
| 2442 | _LIBCPP_CONSTEXPR_AFTER_CXX14 _RandomAccessIterator | |
| 2443 | __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) | |
| 2444 | { | |
| 2445 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 2446 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 2447 | ||
| 2448 | const difference_type __m1 = __middle - __first; | |
| 2449 | const difference_type __m2 = __last - __middle; | |
| 2450 | if (__m1 == __m2) | |
| 2451 | { | |
| 2452 | _VSTD::swap_ranges(__first, __middle, __middle); | |
| 2453 | return __middle; | |
| 2454 | } | |
| 2455 | const difference_type __g = _VSTD::__algo_gcd(__m1, __m2); | |
| 2456 | for (_RandomAccessIterator __p = __first + __g; __p != __first;) | |
| 2457 | { | |
| 2458 | value_type __t(_VSTD::move(*--__p)); | |
| 2459 | _RandomAccessIterator __p1 = __p; | |
| 2460 | _RandomAccessIterator __p2 = __p1 + __m1; | |
| 2461 | do | |
| 2462 | { | |
| 2463 | *__p1 = _VSTD::move(*__p2); | |
| 2464 | __p1 = __p2; | |
| 2465 | const difference_type __d = __last - __p2; | |
| 2466 | if (__m1 < __d) | |
| 2467 | __p2 += __m1; | |
| 2468 | else | |
| 2469 | __p2 = __first + (__m1 - __d); | |
| 2470 | } while (__p2 != __p); | |
| 2471 | *__p1 = _VSTD::move(__t); | |
| 2472 | } | |
| 2473 | return __first + __m2; | |
| 2474 | } | |
| 2475 | ||
| 2476 | template <class _ForwardIterator> | |
| 2477 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2478 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator | |
| 2479 | __rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, | |
| 2480 | _VSTD::forward_iterator_tag) | |
| 2481 | { | |
| 2482 | typedef typename _VSTD::iterator_traits<_ForwardIterator>::value_type value_type; | |
| 2483 | if (_VSTD::is_trivially_move_assignable<value_type>::value) | |
| 2484 | { | |
| 2485 | if (_VSTD::next(__first) == __middle) | |
| 2486 | return _VSTD::__rotate_left(__first, __last); | |
| 2487 | } | |
| 2488 | return _VSTD::__rotate_forward(__first, __middle, __last); | |
| 2489 | } | |
| 2490 | ||
| 2491 | template <class _BidirectionalIterator> | |
| 2492 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2493 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator | |
| 2494 | __rotate(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 2495 | _VSTD::bidirectional_iterator_tag) | |
| 2496 | { | |
| 2497 | typedef typename _VSTD::iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 2498 | if (_VSTD::is_trivially_move_assignable<value_type>::value) | |
| 2499 | { | |
| 2500 | if (_VSTD::next(__first) == __middle) | |
| 2501 | return _VSTD::__rotate_left(__first, __last); | |
| 2502 | if (_VSTD::next(__middle) == __last) | |
| 2503 | return _VSTD::__rotate_right(__first, __last); | |
| 2504 | } | |
| 2505 | return _VSTD::__rotate_forward(__first, __middle, __last); | |
| 2506 | } | |
| 2507 | ||
| 2508 | template <class _RandomAccessIterator> | |
| 2509 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2510 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator | |
| 2511 | __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, | |
| 2512 | _VSTD::random_access_iterator_tag) | |
| 2513 | { | |
| 2514 | typedef typename _VSTD::iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 2515 | if (_VSTD::is_trivially_move_assignable<value_type>::value) | |
| 2516 | { | |
| 2517 | if (_VSTD::next(__first) == __middle) | |
| 2518 | return _VSTD::__rotate_left(__first, __last); | |
| 2519 | if (_VSTD::next(__middle) == __last) | |
| 2520 | return _VSTD::__rotate_right(__first, __last); | |
| 2521 | return _VSTD::__rotate_gcd(__first, __middle, __last); | |
| 2522 | } | |
| 2523 | return _VSTD::__rotate_forward(__first, __middle, __last); | |
| 2524 | } | |
| 2525 | ||
| 2526 | template <class _ForwardIterator> | |
| 2527 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2528 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 2529 | rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) | |
| 2530 | { | |
| 2531 | if (__first == __middle) | |
| 2532 | return __last; | |
| 2533 | if (__middle == __last) | |
| 2534 | return __first; | |
| 2535 | return _VSTD::__rotate(__first, __middle, __last, | |
| 2536 | typename _VSTD::iterator_traits<_ForwardIterator>::iterator_category()); | |
| 2537 | } | |
| 2538 | ||
| 2539 | // rotate_copy | |
| 2540 | ||
| 2541 | template <class _ForwardIterator, class _OutputIterator> | |
| 2542 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2543 | _OutputIterator | |
| 2544 | rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, _OutputIterator __result) | |
| 2545 | { | |
| 2546 | return _VSTD::copy(__first, __middle, _VSTD::copy(__middle, __last, __result)); | |
| 2547 | } | |
| 2548 | ||
| 2549 | // min_element | |
| 2550 | ||
| 2551 | template <class _ForwardIterator, class _Compare> | |
| 2552 | _LIBCPP_NODISCARD_EXT inline | |
| 2553 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2554 | _ForwardIterator | |
| 2555 | min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 2556 | { | |
| 2557 | static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 2558 | "std::min_element requires a ForwardIterator"); | |
| 2559 | if (__first != __last) | |
| 2560 | { | |
| 2561 | _ForwardIterator __i = __first; | |
| 2562 | while (++__i != __last) | |
| 2563 | if (__comp(*__i, *__first)) | |
| 2564 | __first = __i; | |
| 2565 | } | |
| 2566 | return __first; | |
| 2567 | } | |
| 2568 | ||
| 2569 | template <class _ForwardIterator> | |
| 2570 | _LIBCPP_NODISCARD_EXT inline | |
| 2571 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2572 | _ForwardIterator | |
| 2573 | min_element(_ForwardIterator __first, _ForwardIterator __last) | |
| 2574 | { | |
| 2575 | return _VSTD::min_element(__first, __last, | |
| 2576 | __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 2577 | } | |
| 2578 | ||
| 2579 | // min | |
| 2580 | ||
| 2581 | template <class _Tp, class _Compare> | |
| 2582 | _LIBCPP_NODISCARD_EXT inline | |
| 2583 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2584 | const _Tp& | |
| 2585 | min(const _Tp& __a, const _Tp& __b, _Compare __comp) | |
| 2586 | { | |
| 2587 | return __comp(__b, __a) ? __b : __a; | |
| 2588 | } | |
| 2589 | ||
| 2590 | template <class _Tp> | |
| 2591 | _LIBCPP_NODISCARD_EXT inline | |
| 2592 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2593 | const _Tp& | |
| 2594 | min(const _Tp& __a, const _Tp& __b) | |
| 2595 | { | |
| 2596 | return _VSTD::min(__a, __b, __less<_Tp>()); | |
| 2597 | } | |
| 2598 | ||
| 2599 | #ifndef _LIBCPP_CXX03_LANG | |
| 2600 | ||
| 2601 | template<class _Tp, class _Compare> | |
| 2602 | _LIBCPP_NODISCARD_EXT inline | |
| 2603 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2604 | _Tp | |
| 2605 | min(initializer_list<_Tp> __t, _Compare __comp) | |
| 2606 | { | |
| 2607 | return *_VSTD::min_element(__t.begin(), __t.end(), __comp); | |
| 2608 | } | |
| 2609 | ||
| 2610 | template<class _Tp> | |
| 2611 | _LIBCPP_NODISCARD_EXT inline | |
| 2612 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2613 | _Tp | |
| 2614 | min(initializer_list<_Tp> __t) | |
| 2615 | { | |
| 2616 | return *_VSTD::min_element(__t.begin(), __t.end(), __less<_Tp>()); | |
| 2617 | } | |
| 2618 | ||
| 2619 | #endif // _LIBCPP_CXX03_LANG | |
| 2620 | ||
| 2621 | // max_element | |
| 2622 | ||
| 2623 | template <class _ForwardIterator, class _Compare> | |
| 2624 | _LIBCPP_NODISCARD_EXT inline | |
| 2625 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2626 | _ForwardIterator | |
| 2627 | max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 2628 | { | |
| 2629 | static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 2630 | "std::max_element requires a ForwardIterator"); | |
| 2631 | if (__first != __last) | |
| 2632 | { | |
| 2633 | _ForwardIterator __i = __first; | |
| 2634 | while (++__i != __last) | |
| 2635 | if (__comp(*__first, *__i)) | |
| 2636 | __first = __i; | |
| 2637 | } | |
| 2638 | return __first; | |
| 2639 | } | |
| 2640 | ||
| 2641 | ||
| 2642 | template <class _ForwardIterator> | |
| 2643 | _LIBCPP_NODISCARD_EXT inline | |
| 2644 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2645 | _ForwardIterator | |
| 2646 | max_element(_ForwardIterator __first, _ForwardIterator __last) | |
| 2647 | { | |
| 2648 | return _VSTD::max_element(__first, __last, | |
| 2649 | __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 2650 | } | |
| 2651 | ||
| 2652 | // max | |
| 2653 | ||
| 2654 | template <class _Tp, class _Compare> | |
| 2655 | _LIBCPP_NODISCARD_EXT inline | |
| 2656 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2657 | const _Tp& | |
| 2658 | max(const _Tp& __a, const _Tp& __b, _Compare __comp) | |
| 2659 | { | |
| 2660 | return __comp(__a, __b) ? __b : __a; | |
| 2661 | } | |
| 2662 | ||
| 2663 | template <class _Tp> | |
| 2664 | _LIBCPP_NODISCARD_EXT inline | |
| 2665 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2666 | const _Tp& | |
| 2667 | max(const _Tp& __a, const _Tp& __b) | |
| 2668 | { | |
| 2669 | return _VSTD::max(__a, __b, __less<_Tp>()); | |
| 2670 | } | |
| 2671 | ||
| 2672 | #ifndef _LIBCPP_CXX03_LANG | |
| 2673 | ||
| 2674 | template<class _Tp, class _Compare> | |
| 2675 | _LIBCPP_NODISCARD_EXT inline | |
| 2676 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2677 | _Tp | |
| 2678 | max(initializer_list<_Tp> __t, _Compare __comp) | |
| 2679 | { | |
| 2680 | return *_VSTD::max_element(__t.begin(), __t.end(), __comp); | |
| 2681 | } | |
| 2682 | ||
| 2683 | template<class _Tp> | |
| 2684 | _LIBCPP_NODISCARD_EXT inline | |
| 2685 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2686 | _Tp | |
| 2687 | max(initializer_list<_Tp> __t) | |
| 2688 | { | |
| 2689 | return *_VSTD::max_element(__t.begin(), __t.end(), __less<_Tp>()); | |
| 2690 | } | |
| 2691 | ||
| 2692 | #endif // _LIBCPP_CXX03_LANG | |
| 2693 | ||
| 2694 | #if _LIBCPP_STD_VER > 14 | |
| 2695 | // clamp | |
| 2696 | template<class _Tp, class _Compare> | |
| 2697 | _LIBCPP_NODISCARD_EXT inline | |
| 2698 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 2699 | const _Tp& | |
| 2700 | clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) | |
| 2701 | { | |
| 2702 | _LIBCPP_ASSERT(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); | |
| 2703 | return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; | |
| 2704 | ||
| 2705 | } | |
| 2706 | ||
| 2707 | template<class _Tp> | |
| 2708 | _LIBCPP_NODISCARD_EXT inline | |
| 2709 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 2710 | const _Tp& | |
| 2711 | clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) | |
| 2712 | { | |
| 2713 | return _VSTD::clamp(__v, __lo, __hi, __less<_Tp>()); | |
| 2714 | } | |
| 2715 | #endif | |
| 2716 | ||
| 2717 | // minmax_element | |
| 2718 | ||
| 2719 | template <class _ForwardIterator, class _Compare> | |
| 2720 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2721 | pair<_ForwardIterator, _ForwardIterator> | |
| 2722 | minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 2723 | { | |
| 2724 | static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 2725 | "std::minmax_element requires a ForwardIterator"); | |
| 2726 | pair<_ForwardIterator, _ForwardIterator> __result(__first, __first); | |
| 2727 | if (__first != __last) | |
| 2728 | { | |
| 2729 | if (++__first != __last) | |
| 2730 | { | |
| 2731 | if (__comp(*__first, *__result.first)) | |
| 2732 | __result.first = __first; | |
| 2733 | else | |
| 2734 | __result.second = __first; | |
| 2735 | while (++__first != __last) | |
| 2736 | { | |
| 2737 | _ForwardIterator __i = __first; | |
| 2738 | if (++__first == __last) | |
| 2739 | { | |
| 2740 | if (__comp(*__i, *__result.first)) | |
| 2741 | __result.first = __i; | |
| 2742 | else if (!__comp(*__i, *__result.second)) | |
| 2743 | __result.second = __i; | |
| 2744 | break; | |
| 2745 | } | |
| 2746 | else | |
| 2747 | { | |
| 2748 | if (__comp(*__first, *__i)) | |
| 2749 | { | |
| 2750 | if (__comp(*__first, *__result.first)) | |
| 2751 | __result.first = __first; | |
| 2752 | if (!__comp(*__i, *__result.second)) | |
| 2753 | __result.second = __i; | |
| 2754 | } | |
| 2755 | else | |
| 2756 | { | |
| 2757 | if (__comp(*__i, *__result.first)) | |
| 2758 | __result.first = __i; | |
| 2759 | if (!__comp(*__first, *__result.second)) | |
| 2760 | __result.second = __first; | |
| 2761 | } | |
| 2762 | } | |
| 2763 | } | |
| 2764 | } | |
| 2765 | } | |
| 2766 | return __result; | |
| 2767 | } | |
| 2768 | ||
| 2769 | template <class _ForwardIterator> | |
| 2770 | _LIBCPP_NODISCARD_EXT inline | |
| 2771 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2772 | pair<_ForwardIterator, _ForwardIterator> | |
| 2773 | minmax_element(_ForwardIterator __first, _ForwardIterator __last) | |
| 2774 | { | |
| 2775 | return _VSTD::minmax_element(__first, __last, | |
| 2776 | __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 2777 | } | |
| 2778 | ||
| 2779 | // minmax | |
| 2780 | ||
| 2781 | template<class _Tp, class _Compare> | |
| 2782 | _LIBCPP_NODISCARD_EXT inline | |
| 2783 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2784 | pair<const _Tp&, const _Tp&> | |
| 2785 | minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) | |
| 2786 | { | |
| 2787 | return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a) : | |
| 2788 | pair<const _Tp&, const _Tp&>(__a, __b); | |
| 2789 | } | |
| 2790 | ||
| 2791 | template<class _Tp> | |
| 2792 | _LIBCPP_NODISCARD_EXT inline | |
| 2793 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2794 | pair<const _Tp&, const _Tp&> | |
| 2795 | minmax(const _Tp& __a, const _Tp& __b) | |
| 2796 | { | |
| 2797 | return _VSTD::minmax(__a, __b, __less<_Tp>()); | |
| 2798 | } | |
| 2799 | ||
| 2800 | #ifndef _LIBCPP_CXX03_LANG | |
| 2801 | ||
| 2802 | template<class _Tp, class _Compare> | |
| 2803 | _LIBCPP_NODISCARD_EXT inline | |
| 2804 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2805 | pair<_Tp, _Tp> | |
| 2806 | minmax(initializer_list<_Tp> __t, _Compare __comp) | |
| 2807 | { | |
| 2808 | typedef typename initializer_list<_Tp>::const_iterator _Iter; | |
| 2809 | _Iter __first = __t.begin(); | |
| 2810 | _Iter __last = __t.end(); | |
| 2811 | pair<_Tp, _Tp> __result(*__first, *__first); | |
| 2812 | ||
| 2813 | ++__first; | |
| 2814 | if (__t.size() % 2 == 0) | |
| 2815 | { | |
| 2816 | if (__comp(*__first, __result.first)) | |
| 2817 | __result.first = *__first; | |
| 2818 | else | |
| 2819 | __result.second = *__first; | |
| 2820 | ++__first; | |
| 2821 | } | |
| 2822 | ||
| 2823 | while (__first != __last) | |
| 2824 | { | |
| 2825 | _Tp __prev = *__first++; | |
| 2826 | if (__comp(*__first, __prev)) { | |
| 2827 | if ( __comp(*__first, __result.first)) __result.first = *__first; | |
| 2828 | if (!__comp(__prev, __result.second)) __result.second = __prev; | |
| 2829 | } | |
| 2830 | else { | |
| 2831 | if ( __comp(__prev, __result.first)) __result.first = __prev; | |
| 2832 | if (!__comp(*__first, __result.second)) __result.second = *__first; | |
| 2833 | } | |
| 2834 | ||
| 2835 | __first++; | |
| 2836 | } | |
| 2837 | return __result; | |
| 2838 | } | |
| 2839 | ||
| 2840 | template<class _Tp> | |
| 2841 | _LIBCPP_NODISCARD_EXT inline | |
| 2842 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 2843 | pair<_Tp, _Tp> | |
| 2844 | minmax(initializer_list<_Tp> __t) | |
| 2845 | { | |
| 2846 | return _VSTD::minmax(__t, __less<_Tp>()); | |
| 2847 | } | |
| 2848 | ||
| 2849 | #endif // _LIBCPP_CXX03_LANG | |
| 2850 | ||
| 2851 | // random_shuffle | |
| 2852 | ||
| 2853 | // __independent_bits_engine | |
| 2854 | ||
| 2855 | template <unsigned long long _Xp, size_t _Rp> | |
| 2856 | struct __log2_imp | |
| 2857 | { | |
| 2858 | static const size_t value = _Xp & ((unsigned long long)(1) << _Rp) ? _Rp | |
| 2859 | : __log2_imp<_Xp, _Rp - 1>::value; | |
| 2860 | }; | |
| 2861 | ||
| 2862 | template <unsigned long long _Xp> | |
| 2863 | struct __log2_imp<_Xp, 0> | |
| 2864 | { | |
| 2865 | static const size_t value = 0; | |
| 2866 | }; | |
| 2867 | ||
| 2868 | template <size_t _Rp> | |
| 2869 | struct __log2_imp<0, _Rp> | |
| 2870 | { | |
| 2871 | static const size_t value = _Rp + 1; | |
| 2872 | }; | |
| 2873 | ||
| 2874 | template <class _UIntType, _UIntType _Xp> | |
| 2875 | struct __log2 | |
| 2876 | { | |
| 2877 | static const size_t value = __log2_imp<_Xp, | |
| 2878 | sizeof(_UIntType) * __CHAR_BIT__ - 1>::value; | |
| 2879 | }; | |
| 2880 | ||
| 2881 | template<class _Engine, class _UIntType> | |
| 2882 | class __independent_bits_engine | |
| 2883 | { | |
| 2884 | public: | |
| 2885 | // types | |
| 2886 | typedef _UIntType result_type; | |
| 2887 | ||
| 2888 | private: | |
| 2889 | typedef typename _Engine::result_type _Engine_result_type; | |
| 2890 | typedef typename conditional | |
| 2891 | < | |
| 2892 | sizeof(_Engine_result_type) <= sizeof(result_type), | |
| 2893 | result_type, | |
| 2894 | _Engine_result_type | |
| 2895 | >::type _Working_result_type; | |
| 2896 | ||
| 2897 | _Engine& __e_; | |
| 2898 | size_t __w_; | |
| 2899 | size_t __w0_; | |
| 2900 | size_t __n_; | |
| 2901 | size_t __n0_; | |
| 2902 | _Working_result_type __y0_; | |
| 2903 | _Working_result_type __y1_; | |
| 2904 | _Engine_result_type __mask0_; | |
| 2905 | _Engine_result_type __mask1_; | |
| 2906 | ||
| 2907 | #ifdef _LIBCPP_CXX03_LANG | |
| 2908 | static const _Working_result_type _Rp = _Engine::_Max - _Engine::_Min | |
| 2909 | + _Working_result_type(1); | |
| 2910 | #else | |
| 2911 | static _LIBCPP_CONSTEXPR const _Working_result_type _Rp = _Engine::max() - _Engine::min() | |
| 2912 | + _Working_result_type(1); | |
| 2913 | #endif | |
| 2914 | static _LIBCPP_CONSTEXPR const size_t __m = __log2<_Working_result_type, _Rp>::value; | |
| 2915 | static _LIBCPP_CONSTEXPR const size_t _WDt = numeric_limits<_Working_result_type>::digits; | |
| 2916 | static _LIBCPP_CONSTEXPR const size_t _EDt = numeric_limits<_Engine_result_type>::digits; | |
| 2917 | ||
| 2918 | public: | |
| 2919 | // constructors and seeding functions | |
| 2920 | __independent_bits_engine(_Engine& __e, size_t __w); | |
| 2921 | ||
| 2922 | // generating functions | |
| 2923 | result_type operator()() {return __eval(integral_constant<bool, _Rp != 0>());} | |
| 2924 | ||
| 2925 | private: | |
| 2926 | result_type __eval(false_type); | |
| 2927 | result_type __eval(true_type); | |
| 2928 | }; | |
| 2929 | ||
| 2930 | template<class _Engine, class _UIntType> | |
| 2931 | __independent_bits_engine<_Engine, _UIntType> | |
| 2932 | ::__independent_bits_engine(_Engine& __e, size_t __w) | |
| 2933 | : __e_(__e), | |
| 2934 | __w_(__w) | |
| 2935 | { | |
| 2936 | __n_ = __w_ / __m + (__w_ % __m != 0); | |
| 2937 | __w0_ = __w_ / __n_; | |
| 2938 | if (_Rp == 0) | |
| 2939 | __y0_ = _Rp; | |
| 2940 | else if (__w0_ < _WDt) | |
| 2941 | __y0_ = (_Rp >> __w0_) << __w0_; | |
| 2942 | else | |
| 2943 | __y0_ = 0; | |
| 2944 | if (_Rp - __y0_ > __y0_ / __n_) | |
| 2945 | { | |
| 2946 | ++__n_; | |
| 2947 | __w0_ = __w_ / __n_; | |
| 2948 | if (__w0_ < _WDt) | |
| 2949 | __y0_ = (_Rp >> __w0_) << __w0_; | |
| 2950 | else | |
| 2951 | __y0_ = 0; | |
| 2952 | } | |
| 2953 | __n0_ = __n_ - __w_ % __n_; | |
| 2954 | if (__w0_ < _WDt - 1) | |
| 2955 | __y1_ = (_Rp >> (__w0_ + 1)) << (__w0_ + 1); | |
| 2956 | else | |
| 2957 | __y1_ = 0; | |
| 2958 | __mask0_ = __w0_ > 0 ? _Engine_result_type(~0) >> (_EDt - __w0_) : | |
| 2959 | _Engine_result_type(0); | |
| 2960 | __mask1_ = __w0_ < _EDt - 1 ? | |
| 2961 | _Engine_result_type(~0) >> (_EDt - (__w0_ + 1)) : | |
| 2962 | _Engine_result_type(~0); | |
| 2963 | } | |
| 2964 | ||
| 2965 | template<class _Engine, class _UIntType> | |
| 2966 | inline | |
| 2967 | _UIntType | |
| 2968 | __independent_bits_engine<_Engine, _UIntType>::__eval(false_type) | |
| 2969 | { | |
| 2970 | return static_cast<result_type>(__e_() & __mask0_); | |
| 2971 | } | |
| 2972 | ||
| 2973 | template<class _Engine, class _UIntType> | |
| 2974 | _UIntType | |
| 2975 | __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) | |
| 2976 | { | |
| 2977 | const size_t _WRt = numeric_limits<result_type>::digits; | |
| 2978 | result_type _Sp = 0; | |
| 2979 | for (size_t __k = 0; __k < __n0_; ++__k) | |
| 2980 | { | |
| 2981 | _Engine_result_type __u; | |
| 2982 | do | |
| 2983 | { | |
| 2984 | __u = __e_() - _Engine::min(); | |
| 2985 | } while (__u >= __y0_); | |
| 2986 | if (__w0_ < _WRt) | |
| 2987 | _Sp <<= __w0_; | |
| 2988 | else | |
| 2989 | _Sp = 0; | |
| 2990 | _Sp += __u & __mask0_; | |
| 2991 | } | |
| 2992 | for (size_t __k = __n0_; __k < __n_; ++__k) | |
| 2993 | { | |
| 2994 | _Engine_result_type __u; | |
| 2995 | do | |
| 2996 | { | |
| 2997 | __u = __e_() - _Engine::min(); | |
| 2998 | } while (__u >= __y1_); | |
| 2999 | if (__w0_ < _WRt - 1) | |
| 3000 | _Sp <<= __w0_ + 1; | |
| 3001 | else | |
| 3002 | _Sp = 0; | |
| 3003 | _Sp += __u & __mask1_; | |
| 3004 | } | |
| 3005 | return _Sp; | |
| 3006 | } | |
| 3007 | ||
| 3008 | // uniform_int_distribution | |
| 3009 | ||
| 3010 | template<class _IntType = int> | |
| 3011 | class uniform_int_distribution | |
| 3012 | { | |
| 3013 | public: | |
| 3014 | // types | |
| 3015 | typedef _IntType result_type; | |
| 3016 | ||
| 3017 | class param_type | |
| 3018 | { | |
| 3019 | result_type __a_; | |
| 3020 | result_type __b_; | |
| 3021 | public: | |
| 3022 | typedef uniform_int_distribution distribution_type; | |
| 3023 | ||
| 3024 | explicit param_type(result_type __a = 0, | |
| 3025 | result_type __b = numeric_limits<result_type>::max()) | |
| 3026 | : __a_(__a), __b_(__b) {} | |
| 3027 | ||
| 3028 | result_type a() const {return __a_;} | |
| 3029 | result_type b() const {return __b_;} | |
| 3030 | ||
| 3031 | friend bool operator==(const param_type& __x, const param_type& __y) | |
| 3032 | {return __x.__a_ == __y.__a_ && __x.__b_ == __y.__b_;} | |
| 3033 | friend bool operator!=(const param_type& __x, const param_type& __y) | |
| 3034 | {return !(__x == __y);} | |
| 3035 | }; | |
| 3036 | ||
| 3037 | private: | |
| 3038 | param_type __p_; | |
| 3039 | ||
| 3040 | public: | |
| 3041 | // constructors and reset functions | |
| 3042 | #ifndef _LIBCPP_CXX03_LANG | |
| 3043 | uniform_int_distribution() : uniform_int_distribution(0) {} | |
| 3044 | explicit uniform_int_distribution( | |
| 3045 | result_type __a, result_type __b = numeric_limits<result_type>::max()) | |
| 3046 | : __p_(param_type(__a, __b)) {} | |
| 3047 | #else | |
| 3048 | explicit uniform_int_distribution( | |
| 3049 | result_type __a = 0, | |
| 3050 | result_type __b = numeric_limits<result_type>::max()) | |
| 3051 | : __p_(param_type(__a, __b)) {} | |
| 3052 | #endif | |
| 3053 | explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} | |
| 3054 | void reset() {} | |
| 3055 | ||
| 3056 | // generating functions | |
| 3057 | template<class _URNG> result_type operator()(_URNG& __g) | |
| 3058 | {return (*this)(__g, __p_);} | |
| 3059 | template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); | |
| 3060 | ||
| 3061 | // property functions | |
| 3062 | result_type a() const {return __p_.a();} | |
| 3063 | result_type b() const {return __p_.b();} | |
| 3064 | ||
| 3065 | param_type param() const {return __p_;} | |
| 3066 | void param(const param_type& __p) {__p_ = __p;} | |
| 3067 | ||
| 3068 | result_type min() const {return a();} | |
| 3069 | result_type max() const {return b();} | |
| 3070 | ||
| 3071 | friend bool operator==(const uniform_int_distribution& __x, | |
| 3072 | const uniform_int_distribution& __y) | |
| 3073 | {return __x.__p_ == __y.__p_;} | |
| 3074 | friend bool operator!=(const uniform_int_distribution& __x, | |
| 3075 | const uniform_int_distribution& __y) | |
| 3076 | {return !(__x == __y);} | |
| 3077 | }; | |
| 3078 | ||
| 3079 | template<class _IntType> | |
| 3080 | template<class _URNG> | |
| 3081 | typename uniform_int_distribution<_IntType>::result_type | |
| 3082 | uniform_int_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p) | |
| 3083 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 3084 | { | |
| 3085 | typedef typename conditional<sizeof(result_type) <= sizeof(uint32_t), | |
| 3086 | uint32_t, uint64_t>::type _UIntType; | |
| 3087 | const _UIntType _Rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1); | |
| 3088 | if (_Rp == 1) | |
| 3089 | return __p.a(); | |
| 3090 | const size_t _Dt = numeric_limits<_UIntType>::digits; | |
| 3091 | typedef __independent_bits_engine<_URNG, _UIntType> _Eng; | |
| 3092 | if (_Rp == 0) | |
| 3093 | return static_cast<result_type>(_Eng(__g, _Dt)()); | |
| 3094 | size_t __w = _Dt - __libcpp_clz(_Rp) - 1; | |
| 3095 | if ((_Rp & (numeric_limits<_UIntType>::max() >> (_Dt - __w))) != 0) | |
| 3096 | ++__w; | |
| 3097 | _Eng __e(__g, __w); | |
| 3098 | _UIntType __u; | |
| 3099 | do | |
| 3100 | { | |
| 3101 | __u = __e(); | |
| 3102 | } while (__u >= _Rp); | |
| 3103 | return static_cast<result_type>(__u + __p.a()); | |
| 3104 | } | |
| 3105 | ||
| 3106 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ | |
| 3107 | || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 3108 | class _LIBCPP_TYPE_VIS __rs_default; | |
| 3109 | ||
| 3110 | _LIBCPP_FUNC_VIS __rs_default __rs_get(); | |
| 3111 | ||
| 3112 | class _LIBCPP_TYPE_VIS __rs_default | |
| 3113 | { | |
| 3114 | static unsigned __c_; | |
| 3115 | ||
| 3116 | __rs_default(); | |
| 3117 | public: | |
| 3118 | typedef uint_fast32_t result_type; | |
| 3119 | ||
| 3120 | static const result_type _Min = 0; | |
| 3121 | static const result_type _Max = 0xFFFFFFFF; | |
| 3122 | ||
| 3123 | __rs_default(const __rs_default&); | |
| 3124 | ~__rs_default(); | |
| 3125 | ||
| 3126 | result_type operator()(); | |
| 3127 | ||
| 3128 | static _LIBCPP_CONSTEXPR result_type min() {return _Min;} | |
| 3129 | static _LIBCPP_CONSTEXPR result_type max() {return _Max;} | |
| 3130 | ||
| 3131 | friend _LIBCPP_FUNC_VIS __rs_default __rs_get(); | |
| 3132 | }; | |
| 3133 | ||
| 3134 | _LIBCPP_FUNC_VIS __rs_default __rs_get(); | |
| 3135 | ||
| 3136 | template <class _RandomAccessIterator> | |
| 3137 | _LIBCPP_DEPRECATED_IN_CXX14 void | |
| 3138 | random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 3139 | { | |
| 3140 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 3141 | typedef uniform_int_distribution<ptrdiff_t> _Dp; | |
| 3142 | typedef typename _Dp::param_type _Pp; | |
| 3143 | difference_type __d = __last - __first; | |
| 3144 | if (__d > 1) | |
| 3145 | { | |
| 3146 | _Dp __uid; | |
| 3147 | __rs_default __g = __rs_get(); | |
| 3148 | for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) | |
| 3149 | { | |
| 3150 | difference_type __i = __uid(__g, _Pp(0, __d)); | |
| 3151 | if (__i != difference_type(0)) | |
| 3152 | swap(*__first, *(__first + __i)); | |
| 3153 | } | |
| 3154 | } | |
| 3155 | } | |
| 3156 | ||
| 3157 | template <class _RandomAccessIterator, class _RandomNumberGenerator> | |
| 3158 | _LIBCPP_DEPRECATED_IN_CXX14 void | |
| 3159 | random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, | |
| 3160 | #ifndef _LIBCPP_CXX03_LANG | |
| 3161 | _RandomNumberGenerator&& __rand) | |
| 3162 | #else | |
| 3163 | _RandomNumberGenerator& __rand) | |
| 3164 | #endif | |
| 3165 | { | |
| 3166 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 3167 | difference_type __d = __last - __first; | |
| 3168 | if (__d > 1) | |
| 3169 | { | |
| 3170 | for (--__last; __first < __last; ++__first, (void) --__d) | |
| 3171 | { | |
| 3172 | difference_type __i = __rand(__d); | |
| 3173 | if (__i != difference_type(0)) | |
| 3174 | swap(*__first, *(__first + __i)); | |
| 3175 | } | |
| 3176 | } | |
| 3177 | } | |
| 3178 | #endif | |
| 3179 | ||
| 3180 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 3181 | class _UniformRandomNumberGenerator> | |
| 3182 | _LIBCPP_INLINE_VISIBILITY | |
| 3183 | _SampleIterator __sample(_PopulationIterator __first, | |
| 3184 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 3185 | _Distance __n, | |
| 3186 | _UniformRandomNumberGenerator & __g, | |
| 3187 | input_iterator_tag) { | |
| 3188 | ||
| 3189 | _Distance __k = 0; | |
| 3190 | for (; __first != __last && __k < __n; ++__first, (void) ++__k) | |
| 3191 | __output_iter[__k] = *__first; | |
| 3192 | _Distance __sz = __k; | |
| 3193 | for (; __first != __last; ++__first, (void) ++__k) { | |
| 3194 | _Distance __r = _VSTD::uniform_int_distribution<_Distance>(0, __k)(__g); | |
| 3195 | if (__r < __sz) | |
| 3196 | __output_iter[__r] = *__first; | |
| 3197 | } | |
| 3198 | return __output_iter + _VSTD::min(__n, __k); | |
| 3199 | } | |
| 3200 | ||
| 3201 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 3202 | class _UniformRandomNumberGenerator> | |
| 3203 | _LIBCPP_INLINE_VISIBILITY | |
| 3204 | _SampleIterator __sample(_PopulationIterator __first, | |
| 3205 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 3206 | _Distance __n, | |
| 3207 | _UniformRandomNumberGenerator& __g, | |
| 3208 | forward_iterator_tag) { | |
| 3209 | _Distance __unsampled_sz = _VSTD::distance(__first, __last); | |
| 3210 | for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) { | |
| 3211 | _Distance __r = | |
| 3212 | _VSTD::uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g); | |
| 3213 | if (__r < __n) { | |
| 3214 | *__output_iter++ = *__first; | |
| 3215 | --__n; | |
| 3216 | } | |
| 3217 | } | |
| 3218 | return __output_iter; | |
| 3219 | } | |
| 3220 | ||
| 3221 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 3222 | class _UniformRandomNumberGenerator> | |
| 3223 | _LIBCPP_INLINE_VISIBILITY | |
| 3224 | _SampleIterator __sample(_PopulationIterator __first, | |
| 3225 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 3226 | _Distance __n, _UniformRandomNumberGenerator& __g) { | |
| 3227 | typedef typename iterator_traits<_PopulationIterator>::iterator_category | |
| 3228 | _PopCategory; | |
| 3229 | typedef typename iterator_traits<_PopulationIterator>::difference_type | |
| 3230 | _Difference; | |
| 3231 | static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || | |
| 3232 | __is_cpp17_random_access_iterator<_SampleIterator>::value, | |
| 3233 | "SampleIterator must meet the requirements of RandomAccessIterator"); | |
| 3234 | typedef typename common_type<_Distance, _Difference>::type _CommonType; | |
| 3235 | _LIBCPP_ASSERT(__n >= 0, "N must be a positive number."); | |
| 3236 | return _VSTD::__sample( | |
| 3237 | __first, __last, __output_iter, _CommonType(__n), | |
| 3238 | __g, _PopCategory()); | |
| 3239 | } | |
| 3240 | ||
| 3241 | #if _LIBCPP_STD_VER > 14 | |
| 3242 | template <class _PopulationIterator, class _SampleIterator, class _Distance, | |
| 3243 | class _UniformRandomNumberGenerator> | |
| 3244 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3245 | _SampleIterator sample(_PopulationIterator __first, | |
| 3246 | _PopulationIterator __last, _SampleIterator __output_iter, | |
| 3247 | _Distance __n, _UniformRandomNumberGenerator&& __g) { | |
| 3248 | return _VSTD::__sample(__first, __last, __output_iter, __n, __g); | |
| 3249 | } | |
| 3250 | #endif // _LIBCPP_STD_VER > 14 | |
| 3251 | ||
| 3252 | template<class _RandomAccessIterator, class _UniformRandomNumberGenerator> | |
| 3253 | void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, | |
| 3254 | _UniformRandomNumberGenerator&& __g) | |
| 3255 | { | |
| 3256 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 3257 | typedef uniform_int_distribution<ptrdiff_t> _Dp; | |
| 3258 | typedef typename _Dp::param_type _Pp; | |
| 3259 | difference_type __d = __last - __first; | |
| 3260 | if (__d > 1) | |
| 3261 | { | |
| 3262 | _Dp __uid; | |
| 3263 | for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) | |
| 3264 | { | |
| 3265 | difference_type __i = __uid(__g, _Pp(0, __d)); | |
| 3266 | if (__i != difference_type(0)) | |
| 3267 | swap(*__first, *(__first + __i)); | |
| 3268 | } | |
| 3269 | } | |
| 3270 | } | |
| 3271 | ||
| 3272 | #if _LIBCPP_STD_VER > 17 | |
| 3273 | ||
| 3274 | // shift_left, shift_right | |
| 3275 | ||
| 3276 | template <class _ForwardIterator> | |
| 3277 | inline _LIBCPP_INLINE_VISIBILITY constexpr | |
| 3278 | _ForwardIterator | |
| 3279 | shift_left(_ForwardIterator __first, _ForwardIterator __last, | |
| 3280 | typename iterator_traits<_ForwardIterator>::difference_type __n) | |
| 3281 | { | |
| 3282 | if (__n == 0) { | |
| 3283 | return __last; | |
| 3284 | } | |
| 3285 | ||
| 3286 | _ForwardIterator __m = __first; | |
| 3287 | if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { | |
| 3288 | if (__n >= __last - __first) { | |
| 3289 | return __first; | |
| 3290 | } | |
| 3291 | __m += __n; | |
| 3292 | } else { | |
| 3293 | for (; __n > 0; --__n) { | |
| 3294 | if (__m == __last) { | |
| 3295 | return __first; | |
| 3296 | } | |
| 3297 | ++__m; | |
| 3298 | } | |
| 3299 | } | |
| 3300 | return _VSTD::move(__m, __last, __first); | |
| 3301 | } | |
| 3302 | ||
| 3303 | template <class _ForwardIterator> | |
| 3304 | inline _LIBCPP_INLINE_VISIBILITY constexpr | |
| 3305 | _ForwardIterator | |
| 3306 | shift_right(_ForwardIterator __first, _ForwardIterator __last, | |
| 3307 | typename iterator_traits<_ForwardIterator>::difference_type __n) | |
| 3308 | { | |
| 3309 | if (__n == 0) { | |
| 3310 | return __first; | |
| 3311 | } | |
| 3312 | ||
| 3313 | if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { | |
| 3314 | decltype(__n) __d = __last - __first; | |
| 3315 | if (__n >= __d) { | |
| 3316 | return __last; | |
| 3317 | } | |
| 3318 | _ForwardIterator __m = __first + (__d - __n); | |
| 3319 | return _VSTD::move_backward(__first, __m, __last); | |
| 3320 | } else if constexpr (__is_cpp17_bidirectional_iterator<_ForwardIterator>::value) { | |
| 3321 | _ForwardIterator __m = __last; | |
| 3322 | for (; __n > 0; --__n) { | |
| 3323 | if (__m == __first) { | |
| 3324 | return __last; | |
| 3325 | } | |
| 3326 | --__m; | |
| 3327 | } | |
| 3328 | return _VSTD::move_backward(__first, __m, __last); | |
| 3329 | } else { | |
| 3330 | _ForwardIterator __ret = __first; | |
| 3331 | for (; __n > 0; --__n) { | |
| 3332 | if (__ret == __last) { | |
| 3333 | return __last; | |
| 3334 | } | |
| 3335 | ++__ret; | |
| 3336 | } | |
| 3337 | ||
| 3338 | // We have an __n-element scratch space from __first to __ret. | |
| 3339 | // Slide an __n-element window [__trail, __lead) from left to right. | |
| 3340 | // We're essentially doing swap_ranges(__first, __ret, __trail, __lead) | |
| 3341 | // over and over; but once __lead reaches __last we needn't bother | |
| 3342 | // to save the values of elements [__trail, __last). | |
| 3343 | ||
| 3344 | auto __trail = __first; | |
| 3345 | auto __lead = __ret; | |
| 3346 | while (__trail != __ret) { | |
| 3347 | if (__lead == __last) { | |
| 3348 | _VSTD::move(__first, __trail, __ret); | |
| 3349 | return __ret; | |
| 3350 | } | |
| 3351 | ++__trail; | |
| 3352 | ++__lead; | |
| 3353 | } | |
| 3354 | ||
| 3355 | _ForwardIterator __mid = __first; | |
| 3356 | while (true) { | |
| 3357 | if (__lead == __last) { | |
| 3358 | __trail = _VSTD::move(__mid, __ret, __trail); | |
| 3359 | _VSTD::move(__first, __mid, __trail); | |
| 3360 | return __ret; | |
| 3361 | } | |
| 3362 | swap(*__mid, *__trail); | |
| 3363 | ++__mid; | |
| 3364 | ++__trail; | |
| 3365 | ++__lead; | |
| 3366 | if (__mid == __ret) { | |
| 3367 | __mid = __first; | |
| 3368 | } | |
| 3369 | } | |
| 3370 | } | |
| 3371 | } | |
| 3372 | ||
| 3373 | #endif // _LIBCPP_STD_VER > 17 | |
| 3374 | ||
| 3375 | // is_partitioned | |
| 3376 | ||
| 3377 | template <class _InputIterator, class _Predicate> | |
| 3378 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 3379 | is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) | |
| 3380 | { | |
| 3381 | for (; __first != __last; ++__first) | |
| 3382 | if (!__pred(*__first)) | |
| 3383 | break; | |
| 3384 | if ( __first == __last ) | |
| 3385 | return true; | |
| 3386 | ++__first; | |
| 3387 | for (; __first != __last; ++__first) | |
| 3388 | if (__pred(*__first)) | |
| 3389 | return false; | |
| 3390 | return true; | |
| 3391 | } | |
| 3392 | ||
| 3393 | // partition | |
| 3394 | ||
| 3395 | template <class _Predicate, class _ForwardIterator> | |
| 3396 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 3397 | __partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) | |
| 3398 | { | |
| 3399 | while (true) | |
| 3400 | { | |
| 3401 | if (__first == __last) | |
| 3402 | return __first; | |
| 3403 | if (!__pred(*__first)) | |
| 3404 | break; | |
| 3405 | ++__first; | |
| 3406 | } | |
| 3407 | for (_ForwardIterator __p = __first; ++__p != __last;) | |
| 3408 | { | |
| 3409 | if (__pred(*__p)) | |
| 3410 | { | |
| 3411 | swap(*__first, *__p); | |
| 3412 | ++__first; | |
| 3413 | } | |
| 3414 | } | |
| 3415 | return __first; | |
| 3416 | } | |
| 3417 | ||
| 3418 | template <class _Predicate, class _BidirectionalIterator> | |
| 3419 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator | |
| 3420 | __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, | |
| 3421 | bidirectional_iterator_tag) | |
| 3422 | { | |
| 3423 | while (true) | |
| 3424 | { | |
| 3425 | while (true) | |
| 3426 | { | |
| 3427 | if (__first == __last) | |
| 3428 | return __first; | |
| 3429 | if (!__pred(*__first)) | |
| 3430 | break; | |
| 3431 | ++__first; | |
| 3432 | } | |
| 3433 | do | |
| 3434 | { | |
| 3435 | if (__first == --__last) | |
| 3436 | return __first; | |
| 3437 | } while (!__pred(*__last)); | |
| 3438 | swap(*__first, *__last); | |
| 3439 | ++__first; | |
| 3440 | } | |
| 3441 | } | |
| 3442 | ||
| 3443 | template <class _ForwardIterator, class _Predicate> | |
| 3444 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3445 | _ForwardIterator | |
| 3446 | partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 3447 | { | |
| 3448 | return _VSTD::__partition<typename add_lvalue_reference<_Predicate>::type> | |
| 3449 | (__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 3450 | } | |
| 3451 | ||
| 3452 | // partition_copy | |
| 3453 | ||
| 3454 | template <class _InputIterator, class _OutputIterator1, | |
| 3455 | class _OutputIterator2, class _Predicate> | |
| 3456 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_OutputIterator1, _OutputIterator2> | |
| 3457 | partition_copy(_InputIterator __first, _InputIterator __last, | |
| 3458 | _OutputIterator1 __out_true, _OutputIterator2 __out_false, | |
| 3459 | _Predicate __pred) | |
| 3460 | { | |
| 3461 | for (; __first != __last; ++__first) | |
| 3462 | { | |
| 3463 | if (__pred(*__first)) | |
| 3464 | { | |
| 3465 | *__out_true = *__first; | |
| 3466 | ++__out_true; | |
| 3467 | } | |
| 3468 | else | |
| 3469 | { | |
| 3470 | *__out_false = *__first; | |
| 3471 | ++__out_false; | |
| 3472 | } | |
| 3473 | } | |
| 3474 | return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); | |
| 3475 | } | |
| 3476 | ||
| 3477 | // partition_point | |
| 3478 | ||
| 3479 | template<class _ForwardIterator, class _Predicate> | |
| 3480 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 3481 | partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 3482 | { | |
| 3483 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 3484 | difference_type __len = _VSTD::distance(__first, __last); | |
| 3485 | while (__len != 0) | |
| 3486 | { | |
| 3487 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 3488 | _ForwardIterator __m = __first; | |
| 3489 | _VSTD::advance(__m, __l2); | |
| 3490 | if (__pred(*__m)) | |
| 3491 | { | |
| 3492 | __first = ++__m; | |
| 3493 | __len -= __l2 + 1; | |
| 3494 | } | |
| 3495 | else | |
| 3496 | __len = __l2; | |
| 3497 | } | |
| 3498 | return __first; | |
| 3499 | } | |
| 3500 | ||
| 3501 | // stable_partition | |
| 3502 | ||
| 3503 | template <class _Predicate, class _ForwardIterator, class _Distance, class _Pair> | |
| 3504 | _ForwardIterator | |
| 3505 | __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, | |
| 3506 | _Distance __len, _Pair __p, forward_iterator_tag __fit) | |
| 3507 | { | |
| 3508 | // *__first is known to be false | |
| 3509 | // __len >= 1 | |
| 3510 | if (__len == 1) | |
| 3511 | return __first; | |
| 3512 | if (__len == 2) | |
| 3513 | { | |
| 3514 | _ForwardIterator __m = __first; | |
| 3515 | if (__pred(*++__m)) | |
| 3516 | { | |
| 3517 | swap(*__first, *__m); | |
| 3518 | return __m; | |
| 3519 | } | |
| 3520 | return __first; | |
| 3521 | } | |
| 3522 | if (__len <= __p.second) | |
| 3523 | { // The buffer is big enough to use | |
| 3524 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 3525 | __destruct_n __d(0); | |
| 3526 | unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); | |
| 3527 | // Move the falses into the temporary buffer, and the trues to the front of the line | |
| 3528 | // Update __first to always point to the end of the trues | |
| 3529 | value_type* __t = __p.first; | |
| 3530 | ::new ((void*)__t) value_type(_VSTD::move(*__first)); | |
| 3531 | __d.template __incr<value_type>(); | |
| 3532 | ++__t; | |
| 3533 | _ForwardIterator __i = __first; | |
| 3534 | while (++__i != __last) | |
| 3535 | { | |
| 3536 | if (__pred(*__i)) | |
| 3537 | { | |
| 3538 | *__first = _VSTD::move(*__i); | |
| 3539 | ++__first; | |
| 3540 | } | |
| 3541 | else | |
| 3542 | { | |
| 3543 | ::new ((void*)__t) value_type(_VSTD::move(*__i)); | |
| 3544 | __d.template __incr<value_type>(); | |
| 3545 | ++__t; | |
| 3546 | } | |
| 3547 | } | |
| 3548 | // All trues now at start of range, all falses in buffer | |
| 3549 | // Move falses back into range, but don't mess up __first which points to first false | |
| 3550 | __i = __first; | |
| 3551 | for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) | |
| 3552 | *__i = _VSTD::move(*__t2); | |
| 3553 | // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer | |
| 3554 | return __first; | |
| 3555 | } | |
| 3556 | // Else not enough buffer, do in place | |
| 3557 | // __len >= 3 | |
| 3558 | _ForwardIterator __m = __first; | |
| 3559 | _Distance __len2 = __len / 2; // __len2 >= 2 | |
| 3560 | _VSTD::advance(__m, __len2); | |
| 3561 | // recurse on [__first, __m), *__first know to be false | |
| 3562 | // F????????????????? | |
| 3563 | // f m l | |
| 3564 | typedef typename add_lvalue_reference<_Predicate>::type _PredRef; | |
| 3565 | _ForwardIterator __first_false = _VSTD::__stable_partition<_PredRef>(__first, __m, __pred, __len2, __p, __fit); | |
| 3566 | // TTTFFFFF?????????? | |
| 3567 | // f ff m l | |
| 3568 | // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true | |
| 3569 | _ForwardIterator __m1 = __m; | |
| 3570 | _ForwardIterator __second_false = __last; | |
| 3571 | _Distance __len_half = __len - __len2; | |
| 3572 | while (__pred(*__m1)) | |
| 3573 | { | |
| 3574 | if (++__m1 == __last) | |
| 3575 | goto __second_half_done; | |
| 3576 | --__len_half; | |
| 3577 | } | |
| 3578 | // TTTFFFFFTTTF?????? | |
| 3579 | // f ff m m1 l | |
| 3580 | __second_false = _VSTD::__stable_partition<_PredRef>(__m1, __last, __pred, __len_half, __p, __fit); | |
| 3581 | __second_half_done: | |
| 3582 | // TTTFFFFFTTTTTFFFFF | |
| 3583 | // f ff m sf l | |
| 3584 | return _VSTD::rotate(__first_false, __m, __second_false); | |
| 3585 | // TTTTTTTTFFFFFFFFFF | |
| 3586 | // | | |
| 3587 | } | |
| 3588 | ||
| 3589 | struct __return_temporary_buffer | |
| 3590 | { | |
| 3591 | template <class _Tp> | |
| 3592 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) const {_VSTD::return_temporary_buffer(__p);} | |
| 3593 | }; | |
| 3594 | ||
| 3595 | template <class _Predicate, class _ForwardIterator> | |
| 3596 | _ForwardIterator | |
| 3597 | __stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, | |
| 3598 | forward_iterator_tag) | |
| 3599 | { | |
| 3600 | const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment | |
| 3601 | // Either prove all true and return __first or point to first false | |
| 3602 | while (true) | |
| 3603 | { | |
| 3604 | if (__first == __last) | |
| 3605 | return __first; | |
| 3606 | if (!__pred(*__first)) | |
| 3607 | break; | |
| 3608 | ++__first; | |
| 3609 | } | |
| 3610 | // We now have a reduced range [__first, __last) | |
| 3611 | // *__first is known to be false | |
| 3612 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 3613 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 3614 | difference_type __len = _VSTD::distance(__first, __last); | |
| 3615 | pair<value_type*, ptrdiff_t> __p(0, 0); | |
| 3616 | unique_ptr<value_type, __return_temporary_buffer> __h; | |
| 3617 | if (__len >= __alloc_limit) | |
| 3618 | { | |
| 3619 | __p = _VSTD::get_temporary_buffer<value_type>(__len); | |
| 3620 | __h.reset(__p.first); | |
| 3621 | } | |
| 3622 | return _VSTD::__stable_partition<typename add_lvalue_reference<_Predicate>::type> | |
| 3623 | (__first, __last, __pred, __len, __p, forward_iterator_tag()); | |
| 3624 | } | |
| 3625 | ||
| 3626 | template <class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair> | |
| 3627 | _BidirectionalIterator | |
| 3628 | __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, | |
| 3629 | _Distance __len, _Pair __p, bidirectional_iterator_tag __bit) | |
| 3630 | { | |
| 3631 | // *__first is known to be false | |
| 3632 | // *__last is known to be true | |
| 3633 | // __len >= 2 | |
| 3634 | if (__len == 2) | |
| 3635 | { | |
| 3636 | swap(*__first, *__last); | |
| 3637 | return __last; | |
| 3638 | } | |
| 3639 | if (__len == 3) | |
| 3640 | { | |
| 3641 | _BidirectionalIterator __m = __first; | |
| 3642 | if (__pred(*++__m)) | |
| 3643 | { | |
| 3644 | swap(*__first, *__m); | |
| 3645 | swap(*__m, *__last); | |
| 3646 | return __last; | |
| 3647 | } | |
| 3648 | swap(*__m, *__last); | |
| 3649 | swap(*__first, *__m); | |
| 3650 | return __m; | |
| 3651 | } | |
| 3652 | if (__len <= __p.second) | |
| 3653 | { // The buffer is big enough to use | |
| 3654 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 3655 | __destruct_n __d(0); | |
| 3656 | unique_ptr<value_type, __destruct_n&> __h(__p.first, __d); | |
| 3657 | // Move the falses into the temporary buffer, and the trues to the front of the line | |
| 3658 | // Update __first to always point to the end of the trues | |
| 3659 | value_type* __t = __p.first; | |
| 3660 | ::new ((void*)__t) value_type(_VSTD::move(*__first)); | |
| 3661 | __d.template __incr<value_type>(); | |
| 3662 | ++__t; | |
| 3663 | _BidirectionalIterator __i = __first; | |
| 3664 | while (++__i != __last) | |
| 3665 | { | |
| 3666 | if (__pred(*__i)) | |
| 3667 | { | |
| 3668 | *__first = _VSTD::move(*__i); | |
| 3669 | ++__first; | |
| 3670 | } | |
| 3671 | else | |
| 3672 | { | |
| 3673 | ::new ((void*)__t) value_type(_VSTD::move(*__i)); | |
| 3674 | __d.template __incr<value_type>(); | |
| 3675 | ++__t; | |
| 3676 | } | |
| 3677 | } | |
| 3678 | // move *__last, known to be true | |
| 3679 | *__first = _VSTD::move(*__i); | |
| 3680 | __i = ++__first; | |
| 3681 | // All trues now at start of range, all falses in buffer | |
| 3682 | // Move falses back into range, but don't mess up __first which points to first false | |
| 3683 | for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void) ++__i) | |
| 3684 | *__i = _VSTD::move(*__t2); | |
| 3685 | // __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer | |
| 3686 | return __first; | |
| 3687 | } | |
| 3688 | // Else not enough buffer, do in place | |
| 3689 | // __len >= 4 | |
| 3690 | _BidirectionalIterator __m = __first; | |
| 3691 | _Distance __len2 = __len / 2; // __len2 >= 2 | |
| 3692 | _VSTD::advance(__m, __len2); | |
| 3693 | // recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false | |
| 3694 | // F????????????????T | |
| 3695 | // f m l | |
| 3696 | _BidirectionalIterator __m1 = __m; | |
| 3697 | _BidirectionalIterator __first_false = __first; | |
| 3698 | _Distance __len_half = __len2; | |
| 3699 | while (!__pred(*--__m1)) | |
| 3700 | { | |
| 3701 | if (__m1 == __first) | |
| 3702 | goto __first_half_done; | |
| 3703 | --__len_half; | |
| 3704 | } | |
| 3705 | // F???TFFF?????????T | |
| 3706 | // f m1 m l | |
| 3707 | typedef typename add_lvalue_reference<_Predicate>::type _PredRef; | |
| 3708 | __first_false = _VSTD::__stable_partition<_PredRef>(__first, __m1, __pred, __len_half, __p, __bit); | |
| 3709 | __first_half_done: | |
| 3710 | // TTTFFFFF?????????T | |
| 3711 | // f ff m l | |
| 3712 | // recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true | |
| 3713 | __m1 = __m; | |
| 3714 | _BidirectionalIterator __second_false = __last; | |
| 3715 | ++__second_false; | |
| 3716 | __len_half = __len - __len2; | |
| 3717 | while (__pred(*__m1)) | |
| 3718 | { | |
| 3719 | if (++__m1 == __last) | |
| 3720 | goto __second_half_done; | |
| 3721 | --__len_half; | |
| 3722 | } | |
| 3723 | // TTTFFFFFTTTF?????T | |
| 3724 | // f ff m m1 l | |
| 3725 | __second_false = _VSTD::__stable_partition<_PredRef>(__m1, __last, __pred, __len_half, __p, __bit); | |
| 3726 | __second_half_done: | |
| 3727 | // TTTFFFFFTTTTTFFFFF | |
| 3728 | // f ff m sf l | |
| 3729 | return _VSTD::rotate(__first_false, __m, __second_false); | |
| 3730 | // TTTTTTTTFFFFFFFFFF | |
| 3731 | // | | |
| 3732 | } | |
| 3733 | ||
| 3734 | template <class _Predicate, class _BidirectionalIterator> | |
| 3735 | _BidirectionalIterator | |
| 3736 | __stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, | |
| 3737 | bidirectional_iterator_tag) | |
| 3738 | { | |
| 3739 | typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; | |
| 3740 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 3741 | const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment | |
| 3742 | // Either prove all true and return __first or point to first false | |
| 3743 | while (true) | |
| 3744 | { | |
| 3745 | if (__first == __last) | |
| 3746 | return __first; | |
| 3747 | if (!__pred(*__first)) | |
| 3748 | break; | |
| 3749 | ++__first; | |
| 3750 | } | |
| 3751 | // __first points to first false, everything prior to __first is already set. | |
| 3752 | // Either prove [__first, __last) is all false and return __first, or point __last to last true | |
| 3753 | do | |
| 3754 | { | |
| 3755 | if (__first == --__last) | |
| 3756 | return __first; | |
| 3757 | } while (!__pred(*__last)); | |
| 3758 | // We now have a reduced range [__first, __last] | |
| 3759 | // *__first is known to be false | |
| 3760 | // *__last is known to be true | |
| 3761 | // __len >= 2 | |
| 3762 | difference_type __len = _VSTD::distance(__first, __last) + 1; | |
| 3763 | pair<value_type*, ptrdiff_t> __p(0, 0); | |
| 3764 | unique_ptr<value_type, __return_temporary_buffer> __h; | |
| 3765 | if (__len >= __alloc_limit) | |
| 3766 | { | |
| 3767 | __p = _VSTD::get_temporary_buffer<value_type>(__len); | |
| 3768 | __h.reset(__p.first); | |
| 3769 | } | |
| 3770 | return _VSTD::__stable_partition<typename add_lvalue_reference<_Predicate>::type> | |
| 3771 | (__first, __last, __pred, __len, __p, bidirectional_iterator_tag()); | |
| 3772 | } | |
| 3773 | ||
| 3774 | template <class _ForwardIterator, class _Predicate> | |
| 3775 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3776 | _ForwardIterator | |
| 3777 | stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) | |
| 3778 | { | |
| 3779 | return _VSTD::__stable_partition<typename add_lvalue_reference<_Predicate>::type> | |
| 3780 | (__first, __last, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); | |
| 3781 | } | |
| 3782 | ||
| 3783 | // is_sorted_until | |
| 3784 | ||
| 3785 | template <class _ForwardIterator, class _Compare> | |
| 3786 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 3787 | is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 3788 | { | |
| 3789 | if (__first != __last) | |
| 3790 | { | |
| 3791 | _ForwardIterator __i = __first; | |
| 3792 | while (++__i != __last) | |
| 3793 | { | |
| 3794 | if (__comp(*__i, *__first)) | |
| 3795 | return __i; | |
| 3796 | __first = __i; | |
| 3797 | } | |
| 3798 | } | |
| 3799 | return __last; | |
| 3800 | } | |
| 3801 | ||
| 3802 | template<class _ForwardIterator> | |
| 3803 | _LIBCPP_NODISCARD_EXT inline | |
| 3804 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3805 | _ForwardIterator | |
| 3806 | is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) | |
| 3807 | { | |
| 3808 | return _VSTD::is_sorted_until(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 3809 | } | |
| 3810 | ||
| 3811 | // is_sorted | |
| 3812 | ||
| 3813 | template <class _ForwardIterator, class _Compare> | |
| 3814 | _LIBCPP_NODISCARD_EXT inline | |
| 3815 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3816 | bool | |
| 3817 | is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) | |
| 3818 | { | |
| 3819 | return _VSTD::is_sorted_until(__first, __last, __comp) == __last; | |
| 3820 | } | |
| 3821 | ||
| 3822 | template<class _ForwardIterator> | |
| 3823 | _LIBCPP_NODISCARD_EXT inline | |
| 3824 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3825 | bool | |
| 3826 | is_sorted(_ForwardIterator __first, _ForwardIterator __last) | |
| 3827 | { | |
| 3828 | return _VSTD::is_sorted(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 3829 | } | |
| 3830 | ||
| 3831 | // sort | |
| 3832 | ||
| 3833 | // stable, 2-3 compares, 0-2 swaps | |
| 3834 | ||
| 3835 | template <class _Compare, class _ForwardIterator> | |
| 3836 | unsigned | |
| 3837 | __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z, _Compare __c) | |
| 3838 | { | |
| 3839 | unsigned __r = 0; | |
| 3840 | if (!__c(*__y, *__x)) // if x <= y | |
| 3841 | { | |
| 3842 | if (!__c(*__z, *__y)) // if y <= z | |
| 3843 | return __r; // x <= y && y <= z | |
| 3844 | // x <= y && y > z | |
| 3845 | swap(*__y, *__z); // x <= z && y < z | |
| 3846 | __r = 1; | |
| 3847 | if (__c(*__y, *__x)) // if x > y | |
| 3848 | { | |
| 3849 | swap(*__x, *__y); // x < y && y <= z | |
| 3850 | __r = 2; | |
| 3851 | } | |
| 3852 | return __r; // x <= y && y < z | |
| 3853 | } | |
| 3854 | if (__c(*__z, *__y)) // x > y, if y > z | |
| 3855 | { | |
| 3856 | swap(*__x, *__z); // x < y && y < z | |
| 3857 | __r = 1; | |
| 3858 | return __r; | |
| 3859 | } | |
| 3860 | swap(*__x, *__y); // x > y && y <= z | |
| 3861 | __r = 1; // x < y && x <= z | |
| 3862 | if (__c(*__z, *__y)) // if y > z | |
| 3863 | { | |
| 3864 | swap(*__y, *__z); // x <= y && y < z | |
| 3865 | __r = 2; | |
| 3866 | } | |
| 3867 | return __r; | |
| 3868 | } // x <= y && y <= z | |
| 3869 | ||
| 3870 | // stable, 3-6 compares, 0-5 swaps | |
| 3871 | ||
| 3872 | template <class _Compare, class _ForwardIterator> | |
| 3873 | unsigned | |
| 3874 | __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, | |
| 3875 | _ForwardIterator __x4, _Compare __c) | |
| 3876 | { | |
| 3877 | unsigned __r = _VSTD::__sort3<_Compare>(__x1, __x2, __x3, __c); | |
| 3878 | if (__c(*__x4, *__x3)) | |
| 3879 | { | |
| 3880 | swap(*__x3, *__x4); | |
| 3881 | ++__r; | |
| 3882 | if (__c(*__x3, *__x2)) | |
| 3883 | { | |
| 3884 | swap(*__x2, *__x3); | |
| 3885 | ++__r; | |
| 3886 | if (__c(*__x2, *__x1)) | |
| 3887 | { | |
| 3888 | swap(*__x1, *__x2); | |
| 3889 | ++__r; | |
| 3890 | } | |
| 3891 | } | |
| 3892 | } | |
| 3893 | return __r; | |
| 3894 | } | |
| 3895 | ||
| 3896 | // stable, 4-10 compares, 0-9 swaps | |
| 3897 | ||
| 3898 | template <class _Compare, class _ForwardIterator> | |
| 3899 | _LIBCPP_HIDDEN | |
| 3900 | unsigned | |
| 3901 | __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, | |
| 3902 | _ForwardIterator __x4, _ForwardIterator __x5, _Compare __c) | |
| 3903 | { | |
| 3904 | unsigned __r = _VSTD::__sort4<_Compare>(__x1, __x2, __x3, __x4, __c); | |
| 3905 | if (__c(*__x5, *__x4)) | |
| 3906 | { | |
| 3907 | swap(*__x4, *__x5); | |
| 3908 | ++__r; | |
| 3909 | if (__c(*__x4, *__x3)) | |
| 3910 | { | |
| 3911 | swap(*__x3, *__x4); | |
| 3912 | ++__r; | |
| 3913 | if (__c(*__x3, *__x2)) | |
| 3914 | { | |
| 3915 | swap(*__x2, *__x3); | |
| 3916 | ++__r; | |
| 3917 | if (__c(*__x2, *__x1)) | |
| 3918 | { | |
| 3919 | swap(*__x1, *__x2); | |
| 3920 | ++__r; | |
| 3921 | } | |
| 3922 | } | |
| 3923 | } | |
| 3924 | } | |
| 3925 | return __r; | |
| 3926 | } | |
| 3927 | ||
| 3928 | // Assumes size > 0 | |
| 3929 | template <class _Compare, class _BidirectionalIterator> | |
| 3930 | void | |
| 3931 | __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 3932 | { | |
| 3933 | _BidirectionalIterator __lm1 = __last; | |
| 3934 | for (--__lm1; __first != __lm1; ++__first) | |
| 3935 | { | |
| 3936 | _BidirectionalIterator __i = _VSTD::min_element<_BidirectionalIterator, | |
| 3937 | typename add_lvalue_reference<_Compare>::type> | |
| 3938 | (__first, __last, __comp); | |
| 3939 | if (__i != __first) | |
| 3940 | swap(*__first, *__i); | |
| 3941 | } | |
| 3942 | } | |
| 3943 | ||
| 3944 | template <class _Compare, class _BidirectionalIterator> | |
| 3945 | void | |
| 3946 | __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 3947 | { | |
| 3948 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 3949 | if (__first != __last) | |
| 3950 | { | |
| 3951 | _BidirectionalIterator __i = __first; | |
| 3952 | for (++__i; __i != __last; ++__i) | |
| 3953 | { | |
| 3954 | _BidirectionalIterator __j = __i; | |
| 3955 | value_type __t(_VSTD::move(*__j)); | |
| 3956 | for (_BidirectionalIterator __k = __i; __k != __first && __comp(__t, *--__k); --__j) | |
| 3957 | *__j = _VSTD::move(*__k); | |
| 3958 | *__j = _VSTD::move(__t); | |
| 3959 | } | |
| 3960 | } | |
| 3961 | } | |
| 3962 | ||
| 3963 | template <class _Compare, class _RandomAccessIterator> | |
| 3964 | void | |
| 3965 | __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 3966 | { | |
| 3967 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 3968 | _RandomAccessIterator __j = __first+2; | |
| 3969 | _VSTD::__sort3<_Compare>(__first, __first+1, __j, __comp); | |
| 3970 | for (_RandomAccessIterator __i = __j+1; __i != __last; ++__i) | |
| 3971 | { | |
| 3972 | if (__comp(*__i, *__j)) | |
| 3973 | { | |
| 3974 | value_type __t(_VSTD::move(*__i)); | |
| 3975 | _RandomAccessIterator __k = __j; | |
| 3976 | __j = __i; | |
| 3977 | do | |
| 3978 | { | |
| 3979 | *__j = _VSTD::move(*__k); | |
| 3980 | __j = __k; | |
| 3981 | } while (__j != __first && __comp(__t, *--__k)); | |
| 3982 | *__j = _VSTD::move(__t); | |
| 3983 | } | |
| 3984 | __j = __i; | |
| 3985 | } | |
| 3986 | } | |
| 3987 | ||
| 3988 | template <class _Compare, class _RandomAccessIterator> | |
| 3989 | bool | |
| 3990 | __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 3991 | { | |
| 3992 | switch (__last - __first) | |
| 3993 | { | |
| 3994 | case 0: | |
| 3995 | case 1: | |
| 3996 | return true; | |
| 3997 | case 2: | |
| 3998 | if (__comp(*--__last, *__first)) | |
| 3999 | swap(*__first, *__last); | |
| 4000 | return true; | |
| 4001 | case 3: | |
| 4002 | _VSTD::__sort3<_Compare>(__first, __first+1, --__last, __comp); | |
| 4003 | return true; | |
| 4004 | case 4: | |
| 4005 | _VSTD::__sort4<_Compare>(__first, __first+1, __first+2, --__last, __comp); | |
| 4006 | return true; | |
| 4007 | case 5: | |
| 4008 | _VSTD::__sort5<_Compare>(__first, __first+1, __first+2, __first+3, --__last, __comp); | |
| 4009 | return true; | |
| 4010 | } | |
| 4011 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 4012 | _RandomAccessIterator __j = __first+2; | |
| 4013 | _VSTD::__sort3<_Compare>(__first, __first+1, __j, __comp); | |
| 4014 | const unsigned __limit = 8; | |
| 4015 | unsigned __count = 0; | |
| 4016 | for (_RandomAccessIterator __i = __j+1; __i != __last; ++__i) | |
| 4017 | { | |
| 4018 | if (__comp(*__i, *__j)) | |
| 4019 | { | |
| 4020 | value_type __t(_VSTD::move(*__i)); | |
| 4021 | _RandomAccessIterator __k = __j; | |
| 4022 | __j = __i; | |
| 4023 | do | |
| 4024 | { | |
| 4025 | *__j = _VSTD::move(*__k); | |
| 4026 | __j = __k; | |
| 4027 | } while (__j != __first && __comp(__t, *--__k)); | |
| 4028 | *__j = _VSTD::move(__t); | |
| 4029 | if (++__count == __limit) | |
| 4030 | return ++__i == __last; | |
| 4031 | } | |
| 4032 | __j = __i; | |
| 4033 | } | |
| 4034 | return true; | |
| 4035 | } | |
| 4036 | ||
| 4037 | template <class _Compare, class _BidirectionalIterator> | |
| 4038 | void | |
| 4039 | __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, | |
| 4040 | typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) | |
| 4041 | { | |
| 4042 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 4043 | if (__first1 != __last1) | |
| 4044 | { | |
| 4045 | __destruct_n __d(0); | |
| 4046 | unique_ptr<value_type, __destruct_n&> __h(__first2, __d); | |
| 4047 | value_type* __last2 = __first2; | |
| 4048 | ::new ((void*)__last2) value_type(_VSTD::move(*__first1)); | |
| 4049 | __d.template __incr<value_type>(); | |
| 4050 | for (++__last2; ++__first1 != __last1; ++__last2) | |
| 4051 | { | |
| 4052 | value_type* __j2 = __last2; | |
| 4053 | value_type* __i2 = __j2; | |
| 4054 | if (__comp(*__first1, *--__i2)) | |
| 4055 | { | |
| 4056 | ::new ((void*)__j2) value_type(_VSTD::move(*__i2)); | |
| 4057 | __d.template __incr<value_type>(); | |
| 4058 | for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) | |
| 4059 | *__j2 = _VSTD::move(*__i2); | |
| 4060 | *__j2 = _VSTD::move(*__first1); | |
| 4061 | } | |
| 4062 | else | |
| 4063 | { | |
| 4064 | ::new ((void*)__j2) value_type(_VSTD::move(*__first1)); | |
| 4065 | __d.template __incr<value_type>(); | |
| 4066 | } | |
| 4067 | } | |
| 4068 | __h.release(); | |
| 4069 | } | |
| 4070 | } | |
| 4071 | ||
| 4072 | template <class _Compare, class _RandomAccessIterator> | |
| 4073 | void | |
| 4074 | __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 4075 | { | |
| 4076 | // _Compare is known to be a reference type | |
| 4077 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 4078 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 4079 | const difference_type __limit = is_trivially_copy_constructible<value_type>::value && | |
| 4080 | is_trivially_copy_assignable<value_type>::value ? 30 : 6; | |
| 4081 | while (true) | |
| 4082 | { | |
| 4083 | __restart: | |
| 4084 | difference_type __len = __last - __first; | |
| 4085 | switch (__len) | |
| 4086 | { | |
| 4087 | case 0: | |
| 4088 | case 1: | |
| 4089 | return; | |
| 4090 | case 2: | |
| 4091 | if (__comp(*--__last, *__first)) | |
| 4092 | swap(*__first, *__last); | |
| 4093 | return; | |
| 4094 | case 3: | |
| 4095 | _VSTD::__sort3<_Compare>(__first, __first+1, --__last, __comp); | |
| 4096 | return; | |
| 4097 | case 4: | |
| 4098 | _VSTD::__sort4<_Compare>(__first, __first+1, __first+2, --__last, __comp); | |
| 4099 | return; | |
| 4100 | case 5: | |
| 4101 | _VSTD::__sort5<_Compare>(__first, __first+1, __first+2, __first+3, --__last, __comp); | |
| 4102 | return; | |
| 4103 | } | |
| 4104 | if (__len <= __limit) | |
| 4105 | { | |
| 4106 | _VSTD::__insertion_sort_3<_Compare>(__first, __last, __comp); | |
| 4107 | return; | |
| 4108 | } | |
| 4109 | // __len > 5 | |
| 4110 | _RandomAccessIterator __m = __first; | |
| 4111 | _RandomAccessIterator __lm1 = __last; | |
| 4112 | --__lm1; | |
| 4113 | unsigned __n_swaps; | |
| 4114 | { | |
| 4115 | difference_type __delta; | |
| 4116 | if (__len >= 1000) | |
| 4117 | { | |
| 4118 | __delta = __len/2; | |
| 4119 | __m += __delta; | |
| 4120 | __delta /= 2; | |
| 4121 | __n_swaps = _VSTD::__sort5<_Compare>(__first, __first + __delta, __m, __m+__delta, __lm1, __comp); | |
| 4122 | } | |
| 4123 | else | |
| 4124 | { | |
| 4125 | __delta = __len/2; | |
| 4126 | __m += __delta; | |
| 4127 | __n_swaps = _VSTD::__sort3<_Compare>(__first, __m, __lm1, __comp); | |
| 4128 | } | |
| 4129 | } | |
| 4130 | // *__m is median | |
| 4131 | // partition [__first, __m) < *__m and *__m <= [__m, __last) | |
| 4132 | // (this inhibits tossing elements equivalent to __m around unnecessarily) | |
| 4133 | _RandomAccessIterator __i = __first; | |
| 4134 | _RandomAccessIterator __j = __lm1; | |
| 4135 | // j points beyond range to be tested, *__m is known to be <= *__lm1 | |
| 4136 | // The search going up is known to be guarded but the search coming down isn't. | |
| 4137 | // Prime the downward search with a guard. | |
| 4138 | if (!__comp(*__i, *__m)) // if *__first == *__m | |
| 4139 | { | |
| 4140 | // *__first == *__m, *__first doesn't go in first part | |
| 4141 | // manually guard downward moving __j against __i | |
| 4142 | while (true) | |
| 4143 | { | |
| 4144 | if (__i == --__j) | |
| 4145 | { | |
| 4146 | // *__first == *__m, *__m <= all other elements | |
| 4147 | // Parition instead into [__first, __i) == *__first and *__first < [__i, __last) | |
| 4148 | ++__i; // __first + 1 | |
| 4149 | __j = __last; | |
| 4150 | if (!__comp(*__first, *--__j)) // we need a guard if *__first == *(__last-1) | |
| 4151 | { | |
| 4152 | while (true) | |
| 4153 | { | |
| 4154 | if (__i == __j) | |
| 4155 | return; // [__first, __last) all equivalent elements | |
| 4156 | if (__comp(*__first, *__i)) | |
| 4157 | { | |
| 4158 | swap(*__i, *__j); | |
| 4159 | ++__n_swaps; | |
| 4160 | ++__i; | |
| 4161 | break; | |
| 4162 | } | |
| 4163 | ++__i; | |
| 4164 | } | |
| 4165 | } | |
| 4166 | // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 | |
| 4167 | if (__i == __j) | |
| 4168 | return; | |
| 4169 | while (true) | |
| 4170 | { | |
| 4171 | while (!__comp(*__first, *__i)) | |
| 4172 | ++__i; | |
| 4173 | while (__comp(*__first, *--__j)) | |
| 4174 | ; | |
| 4175 | if (__i >= __j) | |
| 4176 | break; | |
| 4177 | swap(*__i, *__j); | |
| 4178 | ++__n_swaps; | |
| 4179 | ++__i; | |
| 4180 | } | |
| 4181 | // [__first, __i) == *__first and *__first < [__i, __last) | |
| 4182 | // The first part is sorted, sort the second part | |
| 4183 | // _VSTD::__sort<_Compare>(__i, __last, __comp); | |
| 4184 | __first = __i; | |
| 4185 | goto __restart; | |
| 4186 | } | |
| 4187 | if (__comp(*__j, *__m)) | |
| 4188 | { | |
| 4189 | swap(*__i, *__j); | |
| 4190 | ++__n_swaps; | |
| 4191 | break; // found guard for downward moving __j, now use unguarded partition | |
| 4192 | } | |
| 4193 | } | |
| 4194 | } | |
| 4195 | // It is known that *__i < *__m | |
| 4196 | ++__i; | |
| 4197 | // j points beyond range to be tested, *__m is known to be <= *__lm1 | |
| 4198 | // if not yet partitioned... | |
| 4199 | if (__i < __j) | |
| 4200 | { | |
| 4201 | // known that *(__i - 1) < *__m | |
| 4202 | // known that __i <= __m | |
| 4203 | while (true) | |
| 4204 | { | |
| 4205 | // __m still guards upward moving __i | |
| 4206 | while (__comp(*__i, *__m)) | |
| 4207 | ++__i; | |
| 4208 | // It is now known that a guard exists for downward moving __j | |
| 4209 | while (!__comp(*--__j, *__m)) | |
| 4210 | ; | |
| 4211 | if (__i > __j) | |
| 4212 | break; | |
| 4213 | swap(*__i, *__j); | |
| 4214 | ++__n_swaps; | |
| 4215 | // It is known that __m != __j | |
| 4216 | // If __m just moved, follow it | |
| 4217 | if (__m == __i) | |
| 4218 | __m = __j; | |
| 4219 | ++__i; | |
| 4220 | } | |
| 4221 | } | |
| 4222 | // [__first, __i) < *__m and *__m <= [__i, __last) | |
| 4223 | if (__i != __m && __comp(*__m, *__i)) | |
| 4224 | { | |
| 4225 | swap(*__i, *__m); | |
| 4226 | ++__n_swaps; | |
| 4227 | } | |
| 4228 | // [__first, __i) < *__i and *__i <= [__i+1, __last) | |
| 4229 | // If we were given a perfect partition, see if insertion sort is quick... | |
| 4230 | if (__n_swaps == 0) | |
| 4231 | { | |
| 4232 | bool __fs = _VSTD::__insertion_sort_incomplete<_Compare>(__first, __i, __comp); | |
| 4233 | if (_VSTD::__insertion_sort_incomplete<_Compare>(__i+1, __last, __comp)) | |
| 4234 | { | |
| 4235 | if (__fs) | |
| 4236 | return; | |
| 4237 | __last = __i; | |
| 4238 | continue; | |
| 4239 | } | |
| 4240 | else | |
| 4241 | { | |
| 4242 | if (__fs) | |
| 4243 | { | |
| 4244 | __first = ++__i; | |
| 4245 | continue; | |
| 4246 | } | |
| 4247 | } | |
| 4248 | } | |
| 4249 | // sort smaller range with recursive call and larger with tail recursion elimination | |
| 4250 | if (__i - __first < __last - __i) | |
| 4251 | { | |
| 4252 | _VSTD::__sort<_Compare>(__first, __i, __comp); | |
| 4253 | // _VSTD::__sort<_Compare>(__i+1, __last, __comp); | |
| 4254 | __first = ++__i; | |
| 4255 | } | |
| 4256 | else | |
| 4257 | { | |
| 4258 | _VSTD::__sort<_Compare>(__i+1, __last, __comp); | |
| 4259 | // _VSTD::__sort<_Compare>(__first, __i, __comp); | |
| 4260 | __last = __i; | |
| 4261 | } | |
| 4262 | } | |
| 4263 | } | |
| 4264 | ||
| 4265 | // This forwarder keeps the top call and the recursive calls using the same instantiation, forcing a reference _Compare | |
| 4266 | template <class _RandomAccessIterator, class _Compare> | |
| 4267 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4268 | void | |
| 4269 | sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 4270 | { | |
| 4271 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 4272 | _VSTD::__sort<_Comp_ref>(__first, __last, _Comp_ref(__comp)); | |
| 4273 | } | |
| 4274 | ||
| 4275 | template <class _RandomAccessIterator> | |
| 4276 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4277 | void | |
| 4278 | sort(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 4279 | { | |
| 4280 | _VSTD::sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 4281 | } | |
| 4282 | ||
| 4283 | template <class _Tp> | |
| 4284 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4285 | void | |
| 4286 | sort(_Tp** __first, _Tp** __last) | |
| 4287 | { | |
| 4288 | _VSTD::sort((uintptr_t*)__first, (uintptr_t*)__last, __less<uintptr_t>()); | |
| 4289 | } | |
| 4290 | ||
| 4291 | template <class _Tp> | |
| 4292 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4293 | void | |
| 4294 | sort(__wrap_iter<_Tp*> __first, __wrap_iter<_Tp*> __last) | |
| 4295 | { | |
| 4296 | _VSTD::sort(__first.base(), __last.base()); | |
| 4297 | } | |
| 4298 | ||
| 4299 | template <class _Tp, class _Compare> | |
| 4300 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4301 | void | |
| 4302 | sort(__wrap_iter<_Tp*> __first, __wrap_iter<_Tp*> __last, _Compare __comp) | |
| 4303 | { | |
| 4304 | typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; | |
| 4305 | _VSTD::sort<_Tp*, _Comp_ref>(__first.base(), __last.base(), __comp); | |
| 4306 | } | |
| 4307 | ||
| 4308 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<char>&, char*>(char*, char*, __less<char>&)) | |
| 4309 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&)) | |
| 4310 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&)) | |
| 4311 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&)) | |
| 4312 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<short>&, short*>(short*, short*, __less<short>&)) | |
| 4313 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&)) | |
| 4314 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<int>&, int*>(int*, int*, __less<int>&)) | |
| 4315 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&)) | |
| 4316 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<long>&, long*>(long*, long*, __less<long>&)) | |
| 4317 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&)) | |
| 4318 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&)) | |
| 4319 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&)) | |
| 4320 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<float>&, float*>(float*, float*, __less<float>&)) | |
| 4321 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<double>&, double*>(double*, double*, __less<double>&)) | |
| 4322 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&)) | |
| 4323 | ||
| 4324 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&)) | |
| 4325 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&)) | |
| 4326 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&)) | |
| 4327 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&)) | |
| 4328 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&)) | |
| 4329 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&)) | |
| 4330 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&)) | |
| 4331 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&)) | |
| 4332 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&)) | |
| 4333 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&)) | |
| 4334 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&)) | |
| 4335 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&)) | |
| 4336 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&)) | |
| 4337 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&)) | |
| 4338 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&)) | |
| 4339 | ||
| 4340 | _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&)) | |
| 4341 | ||
| 4342 | // lower_bound | |
| 4343 | ||
| 4344 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 4345 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 4346 | __lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4347 | { | |
| 4348 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 4349 | difference_type __len = _VSTD::distance(__first, __last); | |
| 4350 | while (__len != 0) | |
| 4351 | { | |
| 4352 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 4353 | _ForwardIterator __m = __first; | |
| 4354 | _VSTD::advance(__m, __l2); | |
| 4355 | if (__comp(*__m, __value_)) | |
| 4356 | { | |
| 4357 | __first = ++__m; | |
| 4358 | __len -= __l2 + 1; | |
| 4359 | } | |
| 4360 | else | |
| 4361 | __len = __l2; | |
| 4362 | } | |
| 4363 | return __first; | |
| 4364 | } | |
| 4365 | ||
| 4366 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 4367 | _LIBCPP_NODISCARD_EXT inline | |
| 4368 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4369 | _ForwardIterator | |
| 4370 | lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4371 | { | |
| 4372 | typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; | |
| 4373 | return _VSTD::__lower_bound<_Comp_ref>(__first, __last, __value_, __comp); | |
| 4374 | } | |
| 4375 | ||
| 4376 | template <class _ForwardIterator, class _Tp> | |
| 4377 | _LIBCPP_NODISCARD_EXT inline | |
| 4378 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4379 | _ForwardIterator | |
| 4380 | lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 4381 | { | |
| 4382 | return _VSTD::lower_bound(__first, __last, __value_, | |
| 4383 | __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); | |
| 4384 | } | |
| 4385 | ||
| 4386 | // upper_bound | |
| 4387 | ||
| 4388 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 4389 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator | |
| 4390 | __upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4391 | { | |
| 4392 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 4393 | difference_type __len = _VSTD::distance(__first, __last); | |
| 4394 | while (__len != 0) | |
| 4395 | { | |
| 4396 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 4397 | _ForwardIterator __m = __first; | |
| 4398 | _VSTD::advance(__m, __l2); | |
| 4399 | if (__comp(__value_, *__m)) | |
| 4400 | __len = __l2; | |
| 4401 | else | |
| 4402 | { | |
| 4403 | __first = ++__m; | |
| 4404 | __len -= __l2 + 1; | |
| 4405 | } | |
| 4406 | } | |
| 4407 | return __first; | |
| 4408 | } | |
| 4409 | ||
| 4410 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 4411 | _LIBCPP_NODISCARD_EXT inline | |
| 4412 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4413 | _ForwardIterator | |
| 4414 | upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4415 | { | |
| 4416 | typedef typename add_lvalue_reference<_Compare>::type _Comp_ref; | |
| 4417 | return _VSTD::__upper_bound<_Comp_ref>(__first, __last, __value_, __comp); | |
| 4418 | } | |
| 4419 | ||
| 4420 | template <class _ForwardIterator, class _Tp> | |
| 4421 | _LIBCPP_NODISCARD_EXT inline | |
| 4422 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4423 | _ForwardIterator | |
| 4424 | upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 4425 | { | |
| 4426 | return _VSTD::upper_bound(__first, __last, __value_, | |
| 4427 | __less<_Tp, typename iterator_traits<_ForwardIterator>::value_type>()); | |
| 4428 | } | |
| 4429 | ||
| 4430 | // equal_range | |
| 4431 | ||
| 4432 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 4433 | _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator> | |
| 4434 | __equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4435 | { | |
| 4436 | typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; | |
| 4437 | difference_type __len = _VSTD::distance(__first, __last); | |
| 4438 | while (__len != 0) | |
| 4439 | { | |
| 4440 | difference_type __l2 = _VSTD::__half_positive(__len); | |
| 4441 | _ForwardIterator __m = __first; | |
| 4442 | _VSTD::advance(__m, __l2); | |
| 4443 | if (__comp(*__m, __value_)) | |
| 4444 | { | |
| 4445 | __first = ++__m; | |
| 4446 | __len -= __l2 + 1; | |
| 4447 | } | |
| 4448 | else if (__comp(__value_, *__m)) | |
| 4449 | { | |
| 4450 | __last = __m; | |
| 4451 | __len = __l2; | |
| 4452 | } | |
| 4453 | else | |
| 4454 | { | |
| 4455 | _ForwardIterator __mp1 = __m; | |
| 4456 | return pair<_ForwardIterator, _ForwardIterator> | |
| 4457 | ( | |
| 4458 | _VSTD::__lower_bound<_Compare>(__first, __m, __value_, __comp), | |
| 4459 | _VSTD::__upper_bound<_Compare>(++__mp1, __last, __value_, __comp) | |
| 4460 | ); | |
| 4461 | } | |
| 4462 | } | |
| 4463 | return pair<_ForwardIterator, _ForwardIterator>(__first, __first); | |
| 4464 | } | |
| 4465 | ||
| 4466 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 4467 | _LIBCPP_NODISCARD_EXT inline | |
| 4468 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4469 | pair<_ForwardIterator, _ForwardIterator> | |
| 4470 | equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4471 | { | |
| 4472 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 4473 | return _VSTD::__equal_range<_Comp_ref>(__first, __last, __value_, __comp); | |
| 4474 | } | |
| 4475 | ||
| 4476 | template <class _ForwardIterator, class _Tp> | |
| 4477 | _LIBCPP_NODISCARD_EXT inline | |
| 4478 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4479 | pair<_ForwardIterator, _ForwardIterator> | |
| 4480 | equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 4481 | { | |
| 4482 | return _VSTD::equal_range(__first, __last, __value_, | |
| 4483 | __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); | |
| 4484 | } | |
| 4485 | ||
| 4486 | // binary_search | |
| 4487 | ||
| 4488 | template <class _Compare, class _ForwardIterator, class _Tp> | |
| 4489 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4490 | bool | |
| 4491 | __binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4492 | { | |
| 4493 | __first = _VSTD::__lower_bound<_Compare>(__first, __last, __value_, __comp); | |
| 4494 | return __first != __last && !__comp(__value_, *__first); | |
| 4495 | } | |
| 4496 | ||
| 4497 | template <class _ForwardIterator, class _Tp, class _Compare> | |
| 4498 | _LIBCPP_NODISCARD_EXT inline | |
| 4499 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4500 | bool | |
| 4501 | binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp) | |
| 4502 | { | |
| 4503 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 4504 | return _VSTD::__binary_search<_Comp_ref>(__first, __last, __value_, __comp); | |
| 4505 | } | |
| 4506 | ||
| 4507 | template <class _ForwardIterator, class _Tp> | |
| 4508 | _LIBCPP_NODISCARD_EXT inline | |
| 4509 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4510 | bool | |
| 4511 | binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_) | |
| 4512 | { | |
| 4513 | return _VSTD::binary_search(__first, __last, __value_, | |
| 4514 | __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); | |
| 4515 | } | |
| 4516 | ||
| 4517 | // merge | |
| 4518 | ||
| 4519 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 4520 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4521 | _OutputIterator | |
| 4522 | __merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 4523 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 4524 | { | |
| 4525 | for (; __first1 != __last1; ++__result) | |
| 4526 | { | |
| 4527 | if (__first2 == __last2) | |
| 4528 | return _VSTD::copy(__first1, __last1, __result); | |
| 4529 | if (__comp(*__first2, *__first1)) | |
| 4530 | { | |
| 4531 | *__result = *__first2; | |
| 4532 | ++__first2; | |
| 4533 | } | |
| 4534 | else | |
| 4535 | { | |
| 4536 | *__result = *__first1; | |
| 4537 | ++__first1; | |
| 4538 | } | |
| 4539 | } | |
| 4540 | return _VSTD::copy(__first2, __last2, __result); | |
| 4541 | } | |
| 4542 | ||
| 4543 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 4544 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4545 | _OutputIterator | |
| 4546 | merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 4547 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 4548 | { | |
| 4549 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 4550 | return _VSTD::__merge<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 4551 | } | |
| 4552 | ||
| 4553 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 4554 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4555 | _OutputIterator | |
| 4556 | merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 4557 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 4558 | { | |
| 4559 | typedef typename iterator_traits<_InputIterator1>::value_type __v1; | |
| 4560 | typedef typename iterator_traits<_InputIterator2>::value_type __v2; | |
| 4561 | return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<__v1, __v2>()); | |
| 4562 | } | |
| 4563 | ||
| 4564 | // inplace_merge | |
| 4565 | ||
| 4566 | template <class _Compare, class _InputIterator1, class _InputIterator2, | |
| 4567 | class _OutputIterator> | |
| 4568 | void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 4569 | _InputIterator2 __first2, _InputIterator2 __last2, | |
| 4570 | _OutputIterator __result, _Compare __comp) | |
| 4571 | { | |
| 4572 | for (; __first1 != __last1; ++__result) | |
| 4573 | { | |
| 4574 | if (__first2 == __last2) | |
| 4575 | { | |
| 4576 | _VSTD::move(__first1, __last1, __result); | |
| 4577 | return; | |
| 4578 | } | |
| 4579 | ||
| 4580 | if (__comp(*__first2, *__first1)) | |
| 4581 | { | |
| 4582 | *__result = _VSTD::move(*__first2); | |
| 4583 | ++__first2; | |
| 4584 | } | |
| 4585 | else | |
| 4586 | { | |
| 4587 | *__result = _VSTD::move(*__first1); | |
| 4588 | ++__first1; | |
| 4589 | } | |
| 4590 | } | |
| 4591 | // __first2 through __last2 are already in the right spot. | |
| 4592 | } | |
| 4593 | ||
| 4594 | template <class _Compare, class _BidirectionalIterator> | |
| 4595 | void | |
| 4596 | __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 4597 | _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, | |
| 4598 | typename iterator_traits<_BidirectionalIterator>::difference_type __len2, | |
| 4599 | typename iterator_traits<_BidirectionalIterator>::value_type* __buff) | |
| 4600 | { | |
| 4601 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 4602 | __destruct_n __d(0); | |
| 4603 | unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); | |
| 4604 | if (__len1 <= __len2) | |
| 4605 | { | |
| 4606 | value_type* __p = __buff; | |
| 4607 | for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) | |
| 4608 | ::new ((void*)__p) value_type(_VSTD::move(*__i)); | |
| 4609 | _VSTD::__half_inplace_merge<_Compare>(__buff, __p, __middle, __last, __first, __comp); | |
| 4610 | } | |
| 4611 | else | |
| 4612 | { | |
| 4613 | value_type* __p = __buff; | |
| 4614 | for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p) | |
| 4615 | ::new ((void*)__p) value_type(_VSTD::move(*__i)); | |
| 4616 | typedef reverse_iterator<_BidirectionalIterator> _RBi; | |
| 4617 | typedef reverse_iterator<value_type*> _Rv; | |
| 4618 | typedef __invert<_Compare> _Inverted; | |
| 4619 | _VSTD::__half_inplace_merge<_Inverted>(_Rv(__p), _Rv(__buff), | |
| 4620 | _RBi(__middle), _RBi(__first), | |
| 4621 | _RBi(__last), _Inverted(__comp)); | |
| 4622 | } | |
| 4623 | } | |
| 4624 | ||
| 4625 | template <class _Compare, class _BidirectionalIterator> | |
| 4626 | void | |
| 4627 | __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 4628 | _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, | |
| 4629 | typename iterator_traits<_BidirectionalIterator>::difference_type __len2, | |
| 4630 | typename iterator_traits<_BidirectionalIterator>::value_type* __buff, ptrdiff_t __buff_size) | |
| 4631 | { | |
| 4632 | typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; | |
| 4633 | while (true) | |
| 4634 | { | |
| 4635 | // if __middle == __last, we're done | |
| 4636 | if (__len2 == 0) | |
| 4637 | return; | |
| 4638 | if (__len1 <= __buff_size || __len2 <= __buff_size) | |
| 4639 | return _VSTD::__buffered_inplace_merge<_Compare> | |
| 4640 | (__first, __middle, __last, __comp, __len1, __len2, __buff); | |
| 4641 | // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 | |
| 4642 | for (; true; ++__first, (void) --__len1) | |
| 4643 | { | |
| 4644 | if (__len1 == 0) | |
| 4645 | return; | |
| 4646 | if (__comp(*__middle, *__first)) | |
| 4647 | break; | |
| 4648 | } | |
| 4649 | // __first < __middle < __last | |
| 4650 | // *__first > *__middle | |
| 4651 | // partition [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) such that | |
| 4652 | // all elements in: | |
| 4653 | // [__first, __m1) <= [__middle, __m2) | |
| 4654 | // [__middle, __m2) < [__m1, __middle) | |
| 4655 | // [__m1, __middle) <= [__m2, __last) | |
| 4656 | // and __m1 or __m2 is in the middle of its range | |
| 4657 | _BidirectionalIterator __m1; // "median" of [__first, __middle) | |
| 4658 | _BidirectionalIterator __m2; // "median" of [__middle, __last) | |
| 4659 | difference_type __len11; // distance(__first, __m1) | |
| 4660 | difference_type __len21; // distance(__middle, __m2) | |
| 4661 | // binary search smaller range | |
| 4662 | if (__len1 < __len2) | |
| 4663 | { // __len >= 1, __len2 >= 2 | |
| 4664 | __len21 = __len2 / 2; | |
| 4665 | __m2 = __middle; | |
| 4666 | _VSTD::advance(__m2, __len21); | |
| 4667 | __m1 = _VSTD::__upper_bound<_Compare>(__first, __middle, *__m2, __comp); | |
| 4668 | __len11 = _VSTD::distance(__first, __m1); | |
| 4669 | } | |
| 4670 | else | |
| 4671 | { | |
| 4672 | if (__len1 == 1) | |
| 4673 | { // __len1 >= __len2 && __len2 > 0, therefore __len2 == 1 | |
| 4674 | // It is known *__first > *__middle | |
| 4675 | swap(*__first, *__middle); | |
| 4676 | return; | |
| 4677 | } | |
| 4678 | // __len1 >= 2, __len2 >= 1 | |
| 4679 | __len11 = __len1 / 2; | |
| 4680 | __m1 = __first; | |
| 4681 | _VSTD::advance(__m1, __len11); | |
| 4682 | __m2 = _VSTD::__lower_bound<_Compare>(__middle, __last, *__m1, __comp); | |
| 4683 | __len21 = _VSTD::distance(__middle, __m2); | |
| 4684 | } | |
| 4685 | difference_type __len12 = __len1 - __len11; // distance(__m1, __middle) | |
| 4686 | difference_type __len22 = __len2 - __len21; // distance(__m2, __last) | |
| 4687 | // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) | |
| 4688 | // swap middle two partitions | |
| 4689 | __middle = _VSTD::rotate(__m1, __middle, __m2); | |
| 4690 | // __len12 and __len21 now have swapped meanings | |
| 4691 | // merge smaller range with recursive call and larger with tail recursion elimination | |
| 4692 | if (__len11 + __len21 < __len12 + __len22) | |
| 4693 | { | |
| 4694 | _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); | |
| 4695 | // _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); | |
| 4696 | __first = __middle; | |
| 4697 | __middle = __m2; | |
| 4698 | __len1 = __len12; | |
| 4699 | __len2 = __len22; | |
| 4700 | } | |
| 4701 | else | |
| 4702 | { | |
| 4703 | _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); | |
| 4704 | // _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); | |
| 4705 | __last = __middle; | |
| 4706 | __middle = __m1; | |
| 4707 | __len1 = __len11; | |
| 4708 | __len2 = __len21; | |
| 4709 | } | |
| 4710 | } | |
| 4711 | } | |
| 4712 | ||
| 4713 | template <class _BidirectionalIterator, class _Compare> | |
| 4714 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4715 | void | |
| 4716 | inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, | |
| 4717 | _Compare __comp) | |
| 4718 | { | |
| 4719 | typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; | |
| 4720 | typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; | |
| 4721 | difference_type __len1 = _VSTD::distance(__first, __middle); | |
| 4722 | difference_type __len2 = _VSTD::distance(__middle, __last); | |
| 4723 | difference_type __buf_size = _VSTD::min(__len1, __len2); | |
| 4724 | pair<value_type*, ptrdiff_t> __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size); | |
| 4725 | unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first); | |
| 4726 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 4727 | return _VSTD::__inplace_merge<_Comp_ref>(__first, __middle, __last, __comp, __len1, __len2, | |
| 4728 | __buf.first, __buf.second); | |
| 4729 | } | |
| 4730 | ||
| 4731 | template <class _BidirectionalIterator> | |
| 4732 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4733 | void | |
| 4734 | inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) | |
| 4735 | { | |
| 4736 | _VSTD::inplace_merge(__first, __middle, __last, | |
| 4737 | __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); | |
| 4738 | } | |
| 4739 | ||
| 4740 | // stable_sort | |
| 4741 | ||
| 4742 | template <class _Compare, class _InputIterator1, class _InputIterator2> | |
| 4743 | void | |
| 4744 | __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 4745 | _InputIterator2 __first2, _InputIterator2 __last2, | |
| 4746 | typename iterator_traits<_InputIterator1>::value_type* __result, _Compare __comp) | |
| 4747 | { | |
| 4748 | typedef typename iterator_traits<_InputIterator1>::value_type value_type; | |
| 4749 | __destruct_n __d(0); | |
| 4750 | unique_ptr<value_type, __destruct_n&> __h(__result, __d); | |
| 4751 | for (; true; ++__result) | |
| 4752 | { | |
| 4753 | if (__first1 == __last1) | |
| 4754 | { | |
| 4755 | for (; __first2 != __last2; ++__first2, ++__result, (void)__d.template __incr<value_type>()) | |
| 4756 | ::new ((void*)__result) value_type(_VSTD::move(*__first2)); | |
| 4757 | __h.release(); | |
| 4758 | return; | |
| 4759 | } | |
| 4760 | if (__first2 == __last2) | |
| 4761 | { | |
| 4762 | for (; __first1 != __last1; ++__first1, ++__result, (void)__d.template __incr<value_type>()) | |
| 4763 | ::new ((void*)__result) value_type(_VSTD::move(*__first1)); | |
| 4764 | __h.release(); | |
| 4765 | return; | |
| 4766 | } | |
| 4767 | if (__comp(*__first2, *__first1)) | |
| 4768 | { | |
| 4769 | ::new ((void*)__result) value_type(_VSTD::move(*__first2)); | |
| 4770 | __d.template __incr<value_type>(); | |
| 4771 | ++__first2; | |
| 4772 | } | |
| 4773 | else | |
| 4774 | { | |
| 4775 | ::new ((void*)__result) value_type(_VSTD::move(*__first1)); | |
| 4776 | __d.template __incr<value_type>(); | |
| 4777 | ++__first1; | |
| 4778 | } | |
| 4779 | } | |
| 4780 | } | |
| 4781 | ||
| 4782 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 4783 | void | |
| 4784 | __merge_move_assign(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 4785 | _InputIterator2 __first2, _InputIterator2 __last2, | |
| 4786 | _OutputIterator __result, _Compare __comp) | |
| 4787 | { | |
| 4788 | for (; __first1 != __last1; ++__result) | |
| 4789 | { | |
| 4790 | if (__first2 == __last2) | |
| 4791 | { | |
| 4792 | for (; __first1 != __last1; ++__first1, (void) ++__result) | |
| 4793 | *__result = _VSTD::move(*__first1); | |
| 4794 | return; | |
| 4795 | } | |
| 4796 | if (__comp(*__first2, *__first1)) | |
| 4797 | { | |
| 4798 | *__result = _VSTD::move(*__first2); | |
| 4799 | ++__first2; | |
| 4800 | } | |
| 4801 | else | |
| 4802 | { | |
| 4803 | *__result = _VSTD::move(*__first1); | |
| 4804 | ++__first1; | |
| 4805 | } | |
| 4806 | } | |
| 4807 | for (; __first2 != __last2; ++__first2, (void) ++__result) | |
| 4808 | *__result = _VSTD::move(*__first2); | |
| 4809 | } | |
| 4810 | ||
| 4811 | template <class _Compare, class _RandomAccessIterator> | |
| 4812 | void | |
| 4813 | __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 4814 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 4815 | typename iterator_traits<_RandomAccessIterator>::value_type* __buff, ptrdiff_t __buff_size); | |
| 4816 | ||
| 4817 | template <class _Compare, class _RandomAccessIterator> | |
| 4818 | void | |
| 4819 | __stable_sort_move(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Compare __comp, | |
| 4820 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 4821 | typename iterator_traits<_RandomAccessIterator>::value_type* __first2) | |
| 4822 | { | |
| 4823 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 4824 | switch (__len) | |
| 4825 | { | |
| 4826 | case 0: | |
| 4827 | return; | |
| 4828 | case 1: | |
| 4829 | ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); | |
| 4830 | return; | |
| 4831 | case 2: | |
| 4832 | __destruct_n __d(0); | |
| 4833 | unique_ptr<value_type, __destruct_n&> __h2(__first2, __d); | |
| 4834 | if (__comp(*--__last1, *__first1)) | |
| 4835 | { | |
| 4836 | ::new ((void*)__first2) value_type(_VSTD::move(*__last1)); | |
| 4837 | __d.template __incr<value_type>(); | |
| 4838 | ++__first2; | |
| 4839 | ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); | |
| 4840 | } | |
| 4841 | else | |
| 4842 | { | |
| 4843 | ::new ((void*)__first2) value_type(_VSTD::move(*__first1)); | |
| 4844 | __d.template __incr<value_type>(); | |
| 4845 | ++__first2; | |
| 4846 | ::new ((void*)__first2) value_type(_VSTD::move(*__last1)); | |
| 4847 | } | |
| 4848 | __h2.release(); | |
| 4849 | return; | |
| 4850 | } | |
| 4851 | if (__len <= 8) | |
| 4852 | { | |
| 4853 | _VSTD::__insertion_sort_move<_Compare>(__first1, __last1, __first2, __comp); | |
| 4854 | return; | |
| 4855 | } | |
| 4856 | typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; | |
| 4857 | _RandomAccessIterator __m = __first1 + __l2; | |
| 4858 | _VSTD::__stable_sort<_Compare>(__first1, __m, __comp, __l2, __first2, __l2); | |
| 4859 | _VSTD::__stable_sort<_Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2); | |
| 4860 | _VSTD::__merge_move_construct<_Compare>(__first1, __m, __m, __last1, __first2, __comp); | |
| 4861 | } | |
| 4862 | ||
| 4863 | template <class _Tp> | |
| 4864 | struct __stable_sort_switch | |
| 4865 | { | |
| 4866 | static const unsigned value = 128*is_trivially_copy_assignable<_Tp>::value; | |
| 4867 | }; | |
| 4868 | ||
| 4869 | template <class _Compare, class _RandomAccessIterator> | |
| 4870 | void | |
| 4871 | __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 4872 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 4873 | typename iterator_traits<_RandomAccessIterator>::value_type* __buff, ptrdiff_t __buff_size) | |
| 4874 | { | |
| 4875 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 4876 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 4877 | switch (__len) | |
| 4878 | { | |
| 4879 | case 0: | |
| 4880 | case 1: | |
| 4881 | return; | |
| 4882 | case 2: | |
| 4883 | if (__comp(*--__last, *__first)) | |
| 4884 | swap(*__first, *__last); | |
| 4885 | return; | |
| 4886 | } | |
| 4887 | if (__len <= static_cast<difference_type>(__stable_sort_switch<value_type>::value)) | |
| 4888 | { | |
| 4889 | _VSTD::__insertion_sort<_Compare>(__first, __last, __comp); | |
| 4890 | return; | |
| 4891 | } | |
| 4892 | typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2; | |
| 4893 | _RandomAccessIterator __m = __first + __l2; | |
| 4894 | if (__len <= __buff_size) | |
| 4895 | { | |
| 4896 | __destruct_n __d(0); | |
| 4897 | unique_ptr<value_type, __destruct_n&> __h2(__buff, __d); | |
| 4898 | _VSTD::__stable_sort_move<_Compare>(__first, __m, __comp, __l2, __buff); | |
| 4899 | __d.__set(__l2, (value_type*)nullptr); | |
| 4900 | _VSTD::__stable_sort_move<_Compare>(__m, __last, __comp, __len - __l2, __buff + __l2); | |
| 4901 | __d.__set(__len, (value_type*)nullptr); | |
| 4902 | _VSTD::__merge_move_assign<_Compare>(__buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp); | |
| 4903 | // _VSTD::__merge<_Compare>(move_iterator<value_type*>(__buff), | |
| 4904 | // move_iterator<value_type*>(__buff + __l2), | |
| 4905 | // move_iterator<_RandomAccessIterator>(__buff + __l2), | |
| 4906 | // move_iterator<_RandomAccessIterator>(__buff + __len), | |
| 4907 | // __first, __comp); | |
| 4908 | return; | |
| 4909 | } | |
| 4910 | _VSTD::__stable_sort<_Compare>(__first, __m, __comp, __l2, __buff, __buff_size); | |
| 4911 | _VSTD::__stable_sort<_Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); | |
| 4912 | _VSTD::__inplace_merge<_Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); | |
| 4913 | } | |
| 4914 | ||
| 4915 | template <class _RandomAccessIterator, class _Compare> | |
| 4916 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4917 | void | |
| 4918 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 4919 | { | |
| 4920 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 4921 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 4922 | difference_type __len = __last - __first; | |
| 4923 | pair<value_type*, ptrdiff_t> __buf(0, 0); | |
| 4924 | unique_ptr<value_type, __return_temporary_buffer> __h; | |
| 4925 | if (__len > static_cast<difference_type>(__stable_sort_switch<value_type>::value)) | |
| 4926 | { | |
| 4927 | __buf = _VSTD::get_temporary_buffer<value_type>(__len); | |
| 4928 | __h.reset(__buf.first); | |
| 4929 | } | |
| 4930 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 4931 | _VSTD::__stable_sort<_Comp_ref>(__first, __last, __comp, __len, __buf.first, __buf.second); | |
| 4932 | } | |
| 4933 | ||
| 4934 | template <class _RandomAccessIterator> | |
| 4935 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4936 | void | |
| 4937 | stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 4938 | { | |
| 4939 | _VSTD::stable_sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 4940 | } | |
| 4941 | ||
| 4942 | // is_heap_until | |
| 4943 | ||
| 4944 | template <class _RandomAccessIterator, class _Compare> | |
| 4945 | _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator | |
| 4946 | is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 4947 | { | |
| 4948 | typedef typename _VSTD::iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 4949 | difference_type __len = __last - __first; | |
| 4950 | difference_type __p = 0; | |
| 4951 | difference_type __c = 1; | |
| 4952 | _RandomAccessIterator __pp = __first; | |
| 4953 | while (__c < __len) | |
| 4954 | { | |
| 4955 | _RandomAccessIterator __cp = __first + __c; | |
| 4956 | if (__comp(*__pp, *__cp)) | |
| 4957 | return __cp; | |
| 4958 | ++__c; | |
| 4959 | ++__cp; | |
| 4960 | if (__c == __len) | |
| 4961 | return __last; | |
| 4962 | if (__comp(*__pp, *__cp)) | |
| 4963 | return __cp; | |
| 4964 | ++__p; | |
| 4965 | ++__pp; | |
| 4966 | __c = 2 * __p + 1; | |
| 4967 | } | |
| 4968 | return __last; | |
| 4969 | } | |
| 4970 | ||
| 4971 | template<class _RandomAccessIterator> | |
| 4972 | _LIBCPP_NODISCARD_EXT inline | |
| 4973 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4974 | _RandomAccessIterator | |
| 4975 | is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 4976 | { | |
| 4977 | return _VSTD::is_heap_until(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 4978 | } | |
| 4979 | ||
| 4980 | // is_heap | |
| 4981 | ||
| 4982 | template <class _RandomAccessIterator, class _Compare> | |
| 4983 | _LIBCPP_NODISCARD_EXT inline | |
| 4984 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4985 | bool | |
| 4986 | is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 4987 | { | |
| 4988 | return _VSTD::is_heap_until(__first, __last, __comp) == __last; | |
| 4989 | } | |
| 4990 | ||
| 4991 | template<class _RandomAccessIterator> | |
| 4992 | _LIBCPP_NODISCARD_EXT inline | |
| 4993 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4994 | bool | |
| 4995 | is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 4996 | { | |
| 4997 | return _VSTD::is_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 4998 | } | |
| 4999 | ||
| 5000 | // push_heap | |
| 5001 | ||
| 5002 | template <class _Compare, class _RandomAccessIterator> | |
| 5003 | void | |
| 5004 | __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 5005 | typename iterator_traits<_RandomAccessIterator>::difference_type __len) | |
| 5006 | { | |
| 5007 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 5008 | if (__len > 1) | |
| 5009 | { | |
| 5010 | __len = (__len - 2) / 2; | |
| 5011 | _RandomAccessIterator __ptr = __first + __len; | |
| 5012 | if (__comp(*__ptr, *--__last)) | |
| 5013 | { | |
| 5014 | value_type __t(_VSTD::move(*__last)); | |
| 5015 | do | |
| 5016 | { | |
| 5017 | *__last = _VSTD::move(*__ptr); | |
| 5018 | __last = __ptr; | |
| 5019 | if (__len == 0) | |
| 5020 | break; | |
| 5021 | __len = (__len - 1) / 2; | |
| 5022 | __ptr = __first + __len; | |
| 5023 | } while (__comp(*__ptr, __t)); | |
| 5024 | *__last = _VSTD::move(__t); | |
| 5025 | } | |
| 5026 | } | |
| 5027 | } | |
| 5028 | ||
| 5029 | template <class _RandomAccessIterator, class _Compare> | |
| 5030 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5031 | void | |
| 5032 | push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 5033 | { | |
| 5034 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5035 | _VSTD::__sift_up<_Comp_ref>(__first, __last, __comp, __last - __first); | |
| 5036 | } | |
| 5037 | ||
| 5038 | template <class _RandomAccessIterator> | |
| 5039 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5040 | void | |
| 5041 | push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 5042 | { | |
| 5043 | _VSTD::push_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 5044 | } | |
| 5045 | ||
| 5046 | // pop_heap | |
| 5047 | ||
| 5048 | template <class _Compare, class _RandomAccessIterator> | |
| 5049 | void | |
| 5050 | __sift_down(_RandomAccessIterator __first, _RandomAccessIterator /*__last*/, | |
| 5051 | _Compare __comp, | |
| 5052 | typename iterator_traits<_RandomAccessIterator>::difference_type __len, | |
| 5053 | _RandomAccessIterator __start) | |
| 5054 | { | |
| 5055 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 5056 | typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; | |
| 5057 | // left-child of __start is at 2 * __start + 1 | |
| 5058 | // right-child of __start is at 2 * __start + 2 | |
| 5059 | difference_type __child = __start - __first; | |
| 5060 | ||
| 5061 | if (__len < 2 || (__len - 2) / 2 < __child) | |
| 5062 | return; | |
| 5063 | ||
| 5064 | __child = 2 * __child + 1; | |
| 5065 | _RandomAccessIterator __child_i = __first + __child; | |
| 5066 | ||
| 5067 | if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + 1))) { | |
| 5068 | // right-child exists and is greater than left-child | |
| 5069 | ++__child_i; | |
| 5070 | ++__child; | |
| 5071 | } | |
| 5072 | ||
| 5073 | // check if we are in heap-order | |
| 5074 | if (__comp(*__child_i, *__start)) | |
| 5075 | // we are, __start is larger than it's largest child | |
| 5076 | return; | |
| 5077 | ||
| 5078 | value_type __top(_VSTD::move(*__start)); | |
| 5079 | do | |
| 5080 | { | |
| 5081 | // we are not in heap-order, swap the parent with it's largest child | |
| 5082 | *__start = _VSTD::move(*__child_i); | |
| 5083 | __start = __child_i; | |
| 5084 | ||
| 5085 | if ((__len - 2) / 2 < __child) | |
| 5086 | break; | |
| 5087 | ||
| 5088 | // recompute the child based off of the updated parent | |
| 5089 | __child = 2 * __child + 1; | |
| 5090 | __child_i = __first + __child; | |
| 5091 | ||
| 5092 | if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + 1))) { | |
| 5093 | // right-child exists and is greater than left-child | |
| 5094 | ++__child_i; | |
| 5095 | ++__child; | |
| 5096 | } | |
| 5097 | ||
| 5098 | // check if we are in heap-order | |
| 5099 | } while (!__comp(*__child_i, __top)); | |
| 5100 | *__start = _VSTD::move(__top); | |
| 5101 | } | |
| 5102 | ||
| 5103 | template <class _Compare, class _RandomAccessIterator> | |
| 5104 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5105 | void | |
| 5106 | __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, | |
| 5107 | typename iterator_traits<_RandomAccessIterator>::difference_type __len) | |
| 5108 | { | |
| 5109 | if (__len > 1) | |
| 5110 | { | |
| 5111 | swap(*__first, *--__last); | |
| 5112 | _VSTD::__sift_down<_Compare>(__first, __last, __comp, __len - 1, __first); | |
| 5113 | } | |
| 5114 | } | |
| 5115 | ||
| 5116 | template <class _RandomAccessIterator, class _Compare> | |
| 5117 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5118 | void | |
| 5119 | pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 5120 | { | |
| 5121 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5122 | _VSTD::__pop_heap<_Comp_ref>(__first, __last, __comp, __last - __first); | |
| 5123 | } | |
| 5124 | ||
| 5125 | template <class _RandomAccessIterator> | |
| 5126 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5127 | void | |
| 5128 | pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 5129 | { | |
| 5130 | _VSTD::pop_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 5131 | } | |
| 5132 | ||
| 5133 | // make_heap | |
| 5134 | ||
| 5135 | template <class _Compare, class _RandomAccessIterator> | |
| 5136 | void | |
| 5137 | __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 5138 | { | |
| 5139 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 5140 | difference_type __n = __last - __first; | |
| 5141 | if (__n > 1) | |
| 5142 | { | |
| 5143 | // start from the first parent, there is no need to consider children | |
| 5144 | for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) | |
| 5145 | { | |
| 5146 | _VSTD::__sift_down<_Compare>(__first, __last, __comp, __n, __first + __start); | |
| 5147 | } | |
| 5148 | } | |
| 5149 | } | |
| 5150 | ||
| 5151 | template <class _RandomAccessIterator, class _Compare> | |
| 5152 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5153 | void | |
| 5154 | make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 5155 | { | |
| 5156 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5157 | _VSTD::__make_heap<_Comp_ref>(__first, __last, __comp); | |
| 5158 | } | |
| 5159 | ||
| 5160 | template <class _RandomAccessIterator> | |
| 5161 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5162 | void | |
| 5163 | make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 5164 | { | |
| 5165 | _VSTD::make_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 5166 | } | |
| 5167 | ||
| 5168 | // sort_heap | |
| 5169 | ||
| 5170 | template <class _Compare, class _RandomAccessIterator> | |
| 5171 | void | |
| 5172 | __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 5173 | { | |
| 5174 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 5175 | for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n) | |
| 5176 | _VSTD::__pop_heap<_Compare>(__first, __last, __comp, __n); | |
| 5177 | } | |
| 5178 | ||
| 5179 | template <class _RandomAccessIterator, class _Compare> | |
| 5180 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5181 | void | |
| 5182 | sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) | |
| 5183 | { | |
| 5184 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5185 | _VSTD::__sort_heap<_Comp_ref>(__first, __last, __comp); | |
| 5186 | } | |
| 5187 | ||
| 5188 | template <class _RandomAccessIterator> | |
| 5189 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5190 | void | |
| 5191 | sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) | |
| 5192 | { | |
| 5193 | _VSTD::sort_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 5194 | } | |
| 5195 | ||
| 5196 | // partial_sort | |
| 5197 | ||
| 5198 | template <class _Compare, class _RandomAccessIterator> | |
| 5199 | void | |
| 5200 | __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, | |
| 5201 | _Compare __comp) | |
| 5202 | { | |
| 5203 | _VSTD::__make_heap<_Compare>(__first, __middle, __comp); | |
| 5204 | typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; | |
| 5205 | for (_RandomAccessIterator __i = __middle; __i != __last; ++__i) | |
| 5206 | { | |
| 5207 | if (__comp(*__i, *__first)) | |
| 5208 | { | |
| 5209 | swap(*__i, *__first); | |
| 5210 | _VSTD::__sift_down<_Compare>(__first, __middle, __comp, __len, __first); | |
| 5211 | } | |
| 5212 | } | |
| 5213 | _VSTD::__sort_heap<_Compare>(__first, __middle, __comp); | |
| 5214 | } | |
| 5215 | ||
| 5216 | template <class _RandomAccessIterator, class _Compare> | |
| 5217 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5218 | void | |
| 5219 | partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, | |
| 5220 | _Compare __comp) | |
| 5221 | { | |
| 5222 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5223 | _VSTD::__partial_sort<_Comp_ref>(__first, __middle, __last, __comp); | |
| 5224 | } | |
| 5225 | ||
| 5226 | template <class _RandomAccessIterator> | |
| 5227 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5228 | void | |
| 5229 | partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) | |
| 5230 | { | |
| 5231 | _VSTD::partial_sort(__first, __middle, __last, | |
| 5232 | __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 5233 | } | |
| 5234 | ||
| 5235 | // partial_sort_copy | |
| 5236 | ||
| 5237 | template <class _Compare, class _InputIterator, class _RandomAccessIterator> | |
| 5238 | _RandomAccessIterator | |
| 5239 | __partial_sort_copy(_InputIterator __first, _InputIterator __last, | |
| 5240 | _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) | |
| 5241 | { | |
| 5242 | _RandomAccessIterator __r = __result_first; | |
| 5243 | if (__r != __result_last) | |
| 5244 | { | |
| 5245 | for (; __first != __last && __r != __result_last; ++__first, (void) ++__r) | |
| 5246 | *__r = *__first; | |
| 5247 | _VSTD::__make_heap<_Compare>(__result_first, __r, __comp); | |
| 5248 | typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first; | |
| 5249 | for (; __first != __last; ++__first) | |
| 5250 | if (__comp(*__first, *__result_first)) | |
| 5251 | { | |
| 5252 | *__result_first = *__first; | |
| 5253 | _VSTD::__sift_down<_Compare>(__result_first, __r, __comp, __len, __result_first); | |
| 5254 | } | |
| 5255 | _VSTD::__sort_heap<_Compare>(__result_first, __r, __comp); | |
| 5256 | } | |
| 5257 | return __r; | |
| 5258 | } | |
| 5259 | ||
| 5260 | template <class _InputIterator, class _RandomAccessIterator, class _Compare> | |
| 5261 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5262 | _RandomAccessIterator | |
| 5263 | partial_sort_copy(_InputIterator __first, _InputIterator __last, | |
| 5264 | _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) | |
| 5265 | { | |
| 5266 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5267 | return _VSTD::__partial_sort_copy<_Comp_ref>(__first, __last, __result_first, __result_last, __comp); | |
| 5268 | } | |
| 5269 | ||
| 5270 | template <class _InputIterator, class _RandomAccessIterator> | |
| 5271 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5272 | _RandomAccessIterator | |
| 5273 | partial_sort_copy(_InputIterator __first, _InputIterator __last, | |
| 5274 | _RandomAccessIterator __result_first, _RandomAccessIterator __result_last) | |
| 5275 | { | |
| 5276 | return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, | |
| 5277 | __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 5278 | } | |
| 5279 | ||
| 5280 | // nth_element | |
| 5281 | ||
| 5282 | template <class _Compare, class _RandomAccessIterator> | |
| 5283 | void | |
| 5284 | __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) | |
| 5285 | { | |
| 5286 | // _Compare is known to be a reference type | |
| 5287 | typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; | |
| 5288 | const difference_type __limit = 7; | |
| 5289 | while (true) | |
| 5290 | { | |
| 5291 | __restart: | |
| 5292 | if (__nth == __last) | |
| 5293 | return; | |
| 5294 | difference_type __len = __last - __first; | |
| 5295 | switch (__len) | |
| 5296 | { | |
| 5297 | case 0: | |
| 5298 | case 1: | |
| 5299 | return; | |
| 5300 | case 2: | |
| 5301 | if (__comp(*--__last, *__first)) | |
| 5302 | swap(*__first, *__last); | |
| 5303 | return; | |
| 5304 | case 3: | |
| 5305 | { | |
| 5306 | _RandomAccessIterator __m = __first; | |
| 5307 | _VSTD::__sort3<_Compare>(__first, ++__m, --__last, __comp); | |
| 5308 | return; | |
| 5309 | } | |
| 5310 | } | |
| 5311 | if (__len <= __limit) | |
| 5312 | { | |
| 5313 | _VSTD::__selection_sort<_Compare>(__first, __last, __comp); | |
| 5314 | return; | |
| 5315 | } | |
| 5316 | // __len > __limit >= 3 | |
| 5317 | _RandomAccessIterator __m = __first + __len/2; | |
| 5318 | _RandomAccessIterator __lm1 = __last; | |
| 5319 | unsigned __n_swaps = _VSTD::__sort3<_Compare>(__first, __m, --__lm1, __comp); | |
| 5320 | // *__m is median | |
| 5321 | // partition [__first, __m) < *__m and *__m <= [__m, __last) | |
| 5322 | // (this inhibits tossing elements equivalent to __m around unnecessarily) | |
| 5323 | _RandomAccessIterator __i = __first; | |
| 5324 | _RandomAccessIterator __j = __lm1; | |
| 5325 | // j points beyond range to be tested, *__lm1 is known to be <= *__m | |
| 5326 | // The search going up is known to be guarded but the search coming down isn't. | |
| 5327 | // Prime the downward search with a guard. | |
| 5328 | if (!__comp(*__i, *__m)) // if *__first == *__m | |
| 5329 | { | |
| 5330 | // *__first == *__m, *__first doesn't go in first part | |
| 5331 | // manually guard downward moving __j against __i | |
| 5332 | while (true) | |
| 5333 | { | |
| 5334 | if (__i == --__j) | |
| 5335 | { | |
| 5336 | // *__first == *__m, *__m <= all other elements | |
| 5337 | // Partition instead into [__first, __i) == *__first and *__first < [__i, __last) | |
| 5338 | ++__i; // __first + 1 | |
| 5339 | __j = __last; | |
| 5340 | if (!__comp(*__first, *--__j)) // we need a guard if *__first == *(__last-1) | |
| 5341 | { | |
| 5342 | while (true) | |
| 5343 | { | |
| 5344 | if (__i == __j) | |
| 5345 | return; // [__first, __last) all equivalent elements | |
| 5346 | if (__comp(*__first, *__i)) | |
| 5347 | { | |
| 5348 | swap(*__i, *__j); | |
| 5349 | ++__n_swaps; | |
| 5350 | ++__i; | |
| 5351 | break; | |
| 5352 | } | |
| 5353 | ++__i; | |
| 5354 | } | |
| 5355 | } | |
| 5356 | // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1 | |
| 5357 | if (__i == __j) | |
| 5358 | return; | |
| 5359 | while (true) | |
| 5360 | { | |
| 5361 | while (!__comp(*__first, *__i)) | |
| 5362 | ++__i; | |
| 5363 | while (__comp(*__first, *--__j)) | |
| 5364 | ; | |
| 5365 | if (__i >= __j) | |
| 5366 | break; | |
| 5367 | swap(*__i, *__j); | |
| 5368 | ++__n_swaps; | |
| 5369 | ++__i; | |
| 5370 | } | |
| 5371 | // [__first, __i) == *__first and *__first < [__i, __last) | |
| 5372 | // The first part is sorted, | |
| 5373 | if (__nth < __i) | |
| 5374 | return; | |
| 5375 | // __nth_element the second part | |
| 5376 | // _VSTD::__nth_element<_Compare>(__i, __nth, __last, __comp); | |
| 5377 | __first = __i; | |
| 5378 | goto __restart; | |
| 5379 | } | |
| 5380 | if (__comp(*__j, *__m)) | |
| 5381 | { | |
| 5382 | swap(*__i, *__j); | |
| 5383 | ++__n_swaps; | |
| 5384 | break; // found guard for downward moving __j, now use unguarded partition | |
| 5385 | } | |
| 5386 | } | |
| 5387 | } | |
| 5388 | ++__i; | |
| 5389 | // j points beyond range to be tested, *__lm1 is known to be <= *__m | |
| 5390 | // if not yet partitioned... | |
| 5391 | if (__i < __j) | |
| 5392 | { | |
| 5393 | // known that *(__i - 1) < *__m | |
| 5394 | while (true) | |
| 5395 | { | |
| 5396 | // __m still guards upward moving __i | |
| 5397 | while (__comp(*__i, *__m)) | |
| 5398 | ++__i; | |
| 5399 | // It is now known that a guard exists for downward moving __j | |
| 5400 | while (!__comp(*--__j, *__m)) | |
| 5401 | ; | |
| 5402 | if (__i >= __j) | |
| 5403 | break; | |
| 5404 | swap(*__i, *__j); | |
| 5405 | ++__n_swaps; | |
| 5406 | // It is known that __m != __j | |
| 5407 | // If __m just moved, follow it | |
| 5408 | if (__m == __i) | |
| 5409 | __m = __j; | |
| 5410 | ++__i; | |
| 5411 | } | |
| 5412 | } | |
| 5413 | // [__first, __i) < *__m and *__m <= [__i, __last) | |
| 5414 | if (__i != __m && __comp(*__m, *__i)) | |
| 5415 | { | |
| 5416 | swap(*__i, *__m); | |
| 5417 | ++__n_swaps; | |
| 5418 | } | |
| 5419 | // [__first, __i) < *__i and *__i <= [__i+1, __last) | |
| 5420 | if (__nth == __i) | |
| 5421 | return; | |
| 5422 | if (__n_swaps == 0) | |
| 5423 | { | |
| 5424 | // We were given a perfectly partitioned sequence. Coincidence? | |
| 5425 | if (__nth < __i) | |
| 5426 | { | |
| 5427 | // Check for [__first, __i) already sorted | |
| 5428 | __j = __m = __first; | |
| 5429 | while (++__j != __i) | |
| 5430 | { | |
| 5431 | if (__comp(*__j, *__m)) | |
| 5432 | // not yet sorted, so sort | |
| 5433 | goto not_sorted; | |
| 5434 | __m = __j; | |
| 5435 | } | |
| 5436 | // [__first, __i) sorted | |
| 5437 | return; | |
| 5438 | } | |
| 5439 | else | |
| 5440 | { | |
| 5441 | // Check for [__i, __last) already sorted | |
| 5442 | __j = __m = __i; | |
| 5443 | while (++__j != __last) | |
| 5444 | { | |
| 5445 | if (__comp(*__j, *__m)) | |
| 5446 | // not yet sorted, so sort | |
| 5447 | goto not_sorted; | |
| 5448 | __m = __j; | |
| 5449 | } | |
| 5450 | // [__i, __last) sorted | |
| 5451 | return; | |
| 5452 | } | |
| 5453 | } | |
| 5454 | not_sorted: | |
| 5455 | // __nth_element on range containing __nth | |
| 5456 | if (__nth < __i) | |
| 5457 | { | |
| 5458 | // _VSTD::__nth_element<_Compare>(__first, __nth, __i, __comp); | |
| 5459 | __last = __i; | |
| 5460 | } | |
| 5461 | else | |
| 5462 | { | |
| 5463 | // _VSTD::__nth_element<_Compare>(__i+1, __nth, __last, __comp); | |
| 5464 | __first = ++__i; | |
| 5465 | } | |
| 5466 | } | |
| 5467 | } | |
| 5468 | ||
| 5469 | template <class _RandomAccessIterator, class _Compare> | |
| 5470 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5471 | void | |
| 5472 | nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) | |
| 5473 | { | |
| 5474 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5475 | _VSTD::__nth_element<_Comp_ref>(__first, __nth, __last, __comp); | |
| 5476 | } | |
| 5477 | ||
| 5478 | template <class _RandomAccessIterator> | |
| 5479 | inline _LIBCPP_INLINE_VISIBILITY | |
| 5480 | void | |
| 5481 | nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) | |
| 5482 | { | |
| 5483 | _VSTD::nth_element(__first, __nth, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); | |
| 5484 | } | |
| 5485 | ||
| 5486 | // includes | |
| 5487 | ||
| 5488 | template <class _Compare, class _InputIterator1, class _InputIterator2> | |
| 5489 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 5490 | __includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, | |
| 5491 | _Compare __comp) | |
| 5492 | { | |
| 5493 | for (; __first2 != __last2; ++__first1) | |
| 5494 | { | |
| 5495 | if (__first1 == __last1 || __comp(*__first2, *__first1)) | |
| 5496 | return false; | |
| 5497 | if (!__comp(*__first1, *__first2)) | |
| 5498 | ++__first2; | |
| 5499 | } | |
| 5500 | return true; | |
| 5501 | } | |
| 5502 | ||
| 5503 | template <class _InputIterator1, class _InputIterator2, class _Compare> | |
| 5504 | _LIBCPP_NODISCARD_EXT inline | |
| 5505 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5506 | bool | |
| 5507 | includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, | |
| 5508 | _Compare __comp) | |
| 5509 | { | |
| 5510 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5511 | return _VSTD::__includes<_Comp_ref>(__first1, __last1, __first2, __last2, __comp); | |
| 5512 | } | |
| 5513 | ||
| 5514 | template <class _InputIterator1, class _InputIterator2> | |
| 5515 | _LIBCPP_NODISCARD_EXT inline | |
| 5516 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5517 | bool | |
| 5518 | includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) | |
| 5519 | { | |
| 5520 | return _VSTD::includes(__first1, __last1, __first2, __last2, | |
| 5521 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 5522 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 5523 | } | |
| 5524 | ||
| 5525 | // set_union | |
| 5526 | ||
| 5527 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5528 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 5529 | __set_union(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5530 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5531 | { | |
| 5532 | for (; __first1 != __last1; ++__result) | |
| 5533 | { | |
| 5534 | if (__first2 == __last2) | |
| 5535 | return _VSTD::copy(__first1, __last1, __result); | |
| 5536 | if (__comp(*__first2, *__first1)) | |
| 5537 | { | |
| 5538 | *__result = *__first2; | |
| 5539 | ++__first2; | |
| 5540 | } | |
| 5541 | else | |
| 5542 | { | |
| 5543 | if (!__comp(*__first1, *__first2)) | |
| 5544 | ++__first2; | |
| 5545 | *__result = *__first1; | |
| 5546 | ++__first1; | |
| 5547 | } | |
| 5548 | } | |
| 5549 | return _VSTD::copy(__first2, __last2, __result); | |
| 5550 | } | |
| 5551 | ||
| 5552 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 5553 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5554 | _OutputIterator | |
| 5555 | set_union(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5556 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5557 | { | |
| 5558 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5559 | return _VSTD::__set_union<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 5560 | } | |
| 5561 | ||
| 5562 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5563 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5564 | _OutputIterator | |
| 5565 | set_union(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5566 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 5567 | { | |
| 5568 | return _VSTD::set_union(__first1, __last1, __first2, __last2, __result, | |
| 5569 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 5570 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 5571 | } | |
| 5572 | ||
| 5573 | // set_intersection | |
| 5574 | ||
| 5575 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5576 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 5577 | __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5578 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5579 | { | |
| 5580 | while (__first1 != __last1 && __first2 != __last2) | |
| 5581 | { | |
| 5582 | if (__comp(*__first1, *__first2)) | |
| 5583 | ++__first1; | |
| 5584 | else | |
| 5585 | { | |
| 5586 | if (!__comp(*__first2, *__first1)) | |
| 5587 | { | |
| 5588 | *__result = *__first1; | |
| 5589 | ++__result; | |
| 5590 | ++__first1; | |
| 5591 | } | |
| 5592 | ++__first2; | |
| 5593 | } | |
| 5594 | } | |
| 5595 | return __result; | |
| 5596 | } | |
| 5597 | ||
| 5598 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 5599 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5600 | _OutputIterator | |
| 5601 | set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5602 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5603 | { | |
| 5604 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5605 | return _VSTD::__set_intersection<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 5606 | } | |
| 5607 | ||
| 5608 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5609 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5610 | _OutputIterator | |
| 5611 | set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5612 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 5613 | { | |
| 5614 | return _VSTD::set_intersection(__first1, __last1, __first2, __last2, __result, | |
| 5615 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 5616 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 5617 | } | |
| 5618 | ||
| 5619 | // set_difference | |
| 5620 | ||
| 5621 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5622 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 5623 | __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5624 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5625 | { | |
| 5626 | while (__first1 != __last1) | |
| 5627 | { | |
| 5628 | if (__first2 == __last2) | |
| 5629 | return _VSTD::copy(__first1, __last1, __result); | |
| 5630 | if (__comp(*__first1, *__first2)) | |
| 5631 | { | |
| 5632 | *__result = *__first1; | |
| 5633 | ++__result; | |
| 5634 | ++__first1; | |
| 5635 | } | |
| 5636 | else | |
| 5637 | { | |
| 5638 | if (!__comp(*__first2, *__first1)) | |
| 5639 | ++__first1; | |
| 5640 | ++__first2; | |
| 5641 | } | |
| 5642 | } | |
| 5643 | return __result; | |
| 5644 | } | |
| 5645 | ||
| 5646 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 5647 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5648 | _OutputIterator | |
| 5649 | set_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5650 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5651 | { | |
| 5652 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5653 | return _VSTD::__set_difference<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 5654 | } | |
| 5655 | ||
| 5656 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5657 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5658 | _OutputIterator | |
| 5659 | set_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5660 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 5661 | { | |
| 5662 | return _VSTD::set_difference(__first1, __last1, __first2, __last2, __result, | |
| 5663 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 5664 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 5665 | } | |
| 5666 | ||
| 5667 | // set_symmetric_difference | |
| 5668 | ||
| 5669 | template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5670 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator | |
| 5671 | __set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5672 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5673 | { | |
| 5674 | while (__first1 != __last1) | |
| 5675 | { | |
| 5676 | if (__first2 == __last2) | |
| 5677 | return _VSTD::copy(__first1, __last1, __result); | |
| 5678 | if (__comp(*__first1, *__first2)) | |
| 5679 | { | |
| 5680 | *__result = *__first1; | |
| 5681 | ++__result; | |
| 5682 | ++__first1; | |
| 5683 | } | |
| 5684 | else | |
| 5685 | { | |
| 5686 | if (__comp(*__first2, *__first1)) | |
| 5687 | { | |
| 5688 | *__result = *__first2; | |
| 5689 | ++__result; | |
| 5690 | } | |
| 5691 | else | |
| 5692 | ++__first1; | |
| 5693 | ++__first2; | |
| 5694 | } | |
| 5695 | } | |
| 5696 | return _VSTD::copy(__first2, __last2, __result); | |
| 5697 | } | |
| 5698 | ||
| 5699 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> | |
| 5700 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5701 | _OutputIterator | |
| 5702 | set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5703 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) | |
| 5704 | { | |
| 5705 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5706 | return _VSTD::__set_symmetric_difference<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp); | |
| 5707 | } | |
| 5708 | ||
| 5709 | template <class _InputIterator1, class _InputIterator2, class _OutputIterator> | |
| 5710 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5711 | _OutputIterator | |
| 5712 | set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5713 | _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) | |
| 5714 | { | |
| 5715 | return _VSTD::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, | |
| 5716 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 5717 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 5718 | } | |
| 5719 | ||
| 5720 | // lexicographical_compare | |
| 5721 | ||
| 5722 | template <class _Compare, class _InputIterator1, class _InputIterator2> | |
| 5723 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 5724 | __lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5725 | _InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) | |
| 5726 | { | |
| 5727 | for (; __first2 != __last2; ++__first1, (void) ++__first2) | |
| 5728 | { | |
| 5729 | if (__first1 == __last1 || __comp(*__first1, *__first2)) | |
| 5730 | return true; | |
| 5731 | if (__comp(*__first2, *__first1)) | |
| 5732 | return false; | |
| 5733 | } | |
| 5734 | return false; | |
| 5735 | } | |
| 5736 | ||
| 5737 | template <class _InputIterator1, class _InputIterator2, class _Compare> | |
| 5738 | _LIBCPP_NODISCARD_EXT inline | |
| 5739 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5740 | bool | |
| 5741 | lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5742 | _InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp) | |
| 5743 | { | |
| 5744 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5745 | return _VSTD::__lexicographical_compare<_Comp_ref>(__first1, __last1, __first2, __last2, __comp); | |
| 5746 | } | |
| 5747 | ||
| 5748 | template <class _InputIterator1, class _InputIterator2> | |
| 5749 | _LIBCPP_NODISCARD_EXT inline | |
| 5750 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5751 | bool | |
| 5752 | lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, | |
| 5753 | _InputIterator2 __first2, _InputIterator2 __last2) | |
| 5754 | { | |
| 5755 | return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, | |
| 5756 | __less<typename iterator_traits<_InputIterator1>::value_type, | |
| 5757 | typename iterator_traits<_InputIterator2>::value_type>()); | |
| 5758 | } | |
| 5759 | ||
| 5760 | // next_permutation | |
| 5761 | ||
| 5762 | template <class _Compare, class _BidirectionalIterator> | |
| 5763 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 5764 | __next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 5765 | { | |
| 5766 | _BidirectionalIterator __i = __last; | |
| 5767 | if (__first == __last || __first == --__i) | |
| 5768 | return false; | |
| 5769 | while (true) | |
| 5770 | { | |
| 5771 | _BidirectionalIterator __ip1 = __i; | |
| 5772 | if (__comp(*--__i, *__ip1)) | |
| 5773 | { | |
| 5774 | _BidirectionalIterator __j = __last; | |
| 5775 | while (!__comp(*__i, *--__j)) | |
| 5776 | ; | |
| 5777 | swap(*__i, *__j); | |
| 5778 | _VSTD::reverse(__ip1, __last); | |
| 5779 | return true; | |
| 5780 | } | |
| 5781 | if (__i == __first) | |
| 5782 | { | |
| 5783 | _VSTD::reverse(__first, __last); | |
| 5784 | return false; | |
| 5785 | } | |
| 5786 | } | |
| 5787 | } | |
| 5788 | ||
| 5789 | template <class _BidirectionalIterator, class _Compare> | |
| 5790 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5791 | bool | |
| 5792 | next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 5793 | { | |
| 5794 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5795 | return _VSTD::__next_permutation<_Comp_ref>(__first, __last, __comp); | |
| 5796 | } | |
| 5797 | ||
| 5798 | template <class _BidirectionalIterator> | |
| 5799 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5800 | bool | |
| 5801 | next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 5802 | { | |
| 5803 | return _VSTD::next_permutation(__first, __last, | |
| 5804 | __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); | |
| 5805 | } | |
| 5806 | ||
| 5807 | // prev_permutation | |
| 5808 | ||
| 5809 | template <class _Compare, class _BidirectionalIterator> | |
| 5810 | _LIBCPP_CONSTEXPR_AFTER_CXX17 bool | |
| 5811 | __prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 5812 | { | |
| 5813 | _BidirectionalIterator __i = __last; | |
| 5814 | if (__first == __last || __first == --__i) | |
| 5815 | return false; | |
| 5816 | while (true) | |
| 5817 | { | |
| 5818 | _BidirectionalIterator __ip1 = __i; | |
| 5819 | if (__comp(*__ip1, *--__i)) | |
| 5820 | { | |
| 5821 | _BidirectionalIterator __j = __last; | |
| 5822 | while (!__comp(*--__j, *__i)) | |
| 5823 | ; | |
| 5824 | swap(*__i, *__j); | |
| 5825 | _VSTD::reverse(__ip1, __last); | |
| 5826 | return true; | |
| 5827 | } | |
| 5828 | if (__i == __first) | |
| 5829 | { | |
| 5830 | _VSTD::reverse(__first, __last); | |
| 5831 | return false; | |
| 5832 | } | |
| 5833 | } | |
| 5834 | } | |
| 5835 | ||
| 5836 | template <class _BidirectionalIterator, class _Compare> | |
| 5837 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5838 | bool | |
| 5839 | prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) | |
| 5840 | { | |
| 5841 | typedef typename __comp_ref_type<_Compare>::type _Comp_ref; | |
| 5842 | return _VSTD::__prev_permutation<_Comp_ref>(__first, __last, __comp); | |
| 5843 | } | |
| 5844 | ||
| 5845 | template <class _BidirectionalIterator> | |
| 5846 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 5847 | bool | |
| 5848 | prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) | |
| 5849 | { | |
| 5850 | return _VSTD::prev_permutation(__first, __last, | |
| 5851 | __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); | |
| 5852 | } | |
| 5853 | ||
| 5854 | _LIBCPP_END_NAMESPACE_STD | |
| 5855 | ||
| 5856 | 764 | _LIBCPP_POP_MACROS |
| 5857 | 765 | |
| 5858 | 766 | #if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 |
| 5859 | 767 | # include <__pstl_algorithm> |
| 5860 | 768 | #endif |
| 5861 | 769 | |
| 5862 | #endif // _LIBCPP_ALGORITHM | |
| 770 | #endif // _LIBCPP_ALGORITHM |
lib/libcxx/include/any+4-3| ... | ... | @@ -80,12 +80,13 @@ namespace std { |
| 80 | 80 | |
| 81 | 81 | */ |
| 82 | 82 | |
| 83 | #include <experimental/__config> | |
| 84 | 83 | #include <__availability> |
| 84 | #include <__config> | |
| 85 | #include <__utility/forward.h> | |
| 86 | #include <cstdlib> | |
| 85 | 87 | #include <memory> |
| 86 | #include <typeinfo> | |
| 87 | 88 | #include <type_traits> |
| 88 | #include <cstdlib> | |
| 89 | #include <typeinfo> | |
| 89 | 90 | #include <version> |
| 90 | 91 | |
| 91 | 92 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
lib/libcxx/include/array+6-9| ... | ... | @@ -109,25 +109,22 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce |
| 109 | 109 | */ |
| 110 | 110 | |
| 111 | 111 | #include <__config> |
| 112 | #include <__debug> | |
| 112 | 113 | #include <__tuple> |
| 113 | #include <type_traits> | |
| 114 | #include <utility> | |
| 115 | #include <iterator> | |
| 116 | 114 | #include <algorithm> |
| 117 | #include <stdexcept> | |
| 118 | 115 | #include <cstdlib> // for _LIBCPP_UNREACHABLE |
| 116 | #include <iterator> | |
| 117 | #include <stdexcept> | |
| 118 | #include <type_traits> | |
| 119 | #include <utility> | |
| 119 | 120 | #include <version> |
| 120 | #include <__debug> | |
| 121 | 121 | |
| 122 | 122 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 123 | 123 | #pragma GCC system_header |
| 124 | 124 | #endif |
| 125 | 125 | |
| 126 | ||
| 127 | ||
| 128 | 126 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 129 | 127 | |
| 130 | ||
| 131 | 128 | template <class _Tp, size_t _Size> |
| 132 | 129 | struct _LIBCPP_TEMPLATE_VIS array |
| 133 | 130 | { |
| ... | ... | @@ -520,4 +517,4 @@ to_array(_Tp(&&__arr)[_Size]) noexcept(is_nothrow_move_constructible_v<_Tp>) { |
| 520 | 517 | |
| 521 | 518 | _LIBCPP_END_NAMESPACE_STD |
| 522 | 519 | |
| 523 | #endif // _LIBCPP_ARRAY | |
| 520 | #endif // _LIBCPP_ARRAY |
lib/libcxx/include/atomic+54-23| ... | ... | @@ -67,7 +67,8 @@ struct atomic |
| 67 | 67 | bool is_lock_free() const volatile noexcept; |
| 68 | 68 | bool is_lock_free() const noexcept; |
| 69 | 69 | |
| 70 | atomic() noexcept = default; | |
| 70 | atomic() noexcept = default; // until C++20 | |
| 71 | constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>); // since C++20 | |
| 71 | 72 | constexpr atomic(T desr) noexcept; |
| 72 | 73 | atomic(const atomic&) = delete; |
| 73 | 74 | atomic& operator=(const atomic&) = delete; |
| ... | ... | @@ -201,7 +202,8 @@ struct atomic<T*> |
| 201 | 202 | bool is_lock_free() const volatile noexcept; |
| 202 | 203 | bool is_lock_free() const noexcept; |
| 203 | 204 | |
| 204 | atomic() noexcept = default; | |
| 205 | atomic() noexcept = default; // until C++20 | |
| 206 | constexpr atomic() noexcept; // since C++20 | |
| 205 | 207 | constexpr atomic(T* desr) noexcept; |
| 206 | 208 | atomic(const atomic&) = delete; |
| 207 | 209 | atomic& operator=(const atomic&) = delete; |
| ... | ... | @@ -509,7 +511,8 @@ typedef atomic<uintmax_t> atomic_uintmax_t; |
| 509 | 511 | |
| 510 | 512 | typedef struct atomic_flag |
| 511 | 513 | { |
| 512 | atomic_flag() noexcept = default; | |
| 514 | atomic_flag() noexcept = default; // until C++20 | |
| 515 | constexpr atomic_flag() noexcept; // since C++20 | |
| 513 | 516 | atomic_flag(const atomic_flag&) = delete; |
| 514 | 517 | atomic_flag& operator=(const atomic_flag&) = delete; |
| 515 | 518 | atomic_flag& operator=(const atomic_flag&) volatile = delete; |
| ... | ... | @@ -574,8 +577,8 @@ template <class T> |
| 574 | 577 | |
| 575 | 578 | */ |
| 576 | 579 | |
| 577 | #include <__config> | |
| 578 | 580 | #include <__availability> |
| 581 | #include <__config> | |
| 579 | 582 | #include <__threading_support> |
| 580 | 583 | #include <cstddef> |
| 581 | 584 | #include <cstdint> |
| ... | ... | @@ -669,7 +672,7 @@ static_assert((is_same<underlying_type<memory_order>::type, __memory_order_under |
| 669 | 672 | "unexpected underlying type for std::memory_order"); |
| 670 | 673 | |
| 671 | 674 | #if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) || \ |
| 672 | 	defined(_LIBCPP_ATOMIC_ONLY_USE_BUILTINS) | |
| 675 | defined(_LIBCPP_ATOMIC_ONLY_USE_BUILTINS) | |
| 673 | 676 | |
| 674 | 677 | // [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because |
| 675 | 678 | // the default operator= in an object is not volatile, a byte-by-byte copy |
| ... | ... | @@ -1017,26 +1020,33 @@ _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> * __a, _Tp __value, memory |
| 1017 | 1020 | return __c11_atomic_exchange(&__a->__a_value, __value, static_cast<__memory_order_underlying_t>(__order)); |
| 1018 | 1021 | } |
| 1019 | 1022 | |
| 1023 | _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { | |
| 1024 | // Avoid switch statement to make this a constexpr. | |
| 1025 | return __order == memory_order_release ? memory_order_relaxed: | |
| 1026 | (__order == memory_order_acq_rel ? memory_order_acquire: | |
| 1027 | __order); | |
| 1028 | } | |
| 1029 | ||
| 1020 | 1030 | template<class _Tp> |
| 1021 | 1031 | _LIBCPP_INLINE_VISIBILITY |
| 1022 | 1032 | bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { |
| 1023 | return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__failure)); | |
| 1033 | return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); | |
| 1024 | 1034 | } |
| 1025 | 1035 | template<class _Tp> |
| 1026 | 1036 | _LIBCPP_INLINE_VISIBILITY |
| 1027 | 1037 | bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { |
| 1028 | return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__failure)); | |
| 1038 | return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); | |
| 1029 | 1039 | } |
| 1030 | 1040 | |
| 1031 | 1041 | template<class _Tp> |
| 1032 | 1042 | _LIBCPP_INLINE_VISIBILITY |
| 1033 | 1043 | bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { |
| 1034 | return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__failure)); | |
| 1044 | return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); | |
| 1035 | 1045 | } |
| 1036 | 1046 | template<class _Tp> |
| 1037 | 1047 | _LIBCPP_INLINE_VISIBILITY |
| 1038 | 1048 | bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { |
| 1039 | return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__failure)); | |
| 1049 | return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); | |
| 1040 | 1050 | } |
| 1041 | 1051 | |
| 1042 | 1052 | template<class _Tp> |
| ... | ... | @@ -1127,7 +1137,7 @@ _Tp kill_dependency(_Tp __y) _NOEXCEPT |
| 1127 | 1137 | #if defined(__CLANG_ATOMIC_BOOL_LOCK_FREE) |
| 1128 | 1138 | # define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE |
| 1129 | 1139 | # define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE |
| 1130 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1140 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1131 | 1141 | # define ATOMIC_CHAR8_T_LOCK_FREE __CLANG_ATOMIC_CHAR8_T_LOCK_FREE |
| 1132 | 1142 | #endif |
| 1133 | 1143 | # define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE |
| ... | ... | @@ -1141,7 +1151,7 @@ _Tp kill_dependency(_Tp __y) _NOEXCEPT |
| 1141 | 1151 | #elif defined(__GCC_ATOMIC_BOOL_LOCK_FREE) |
| 1142 | 1152 | # define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE |
| 1143 | 1153 | # define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE |
| 1144 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1154 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1145 | 1155 | # define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE |
| 1146 | 1156 | #endif |
| 1147 | 1157 | # define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE |
| ... | ... | @@ -1458,7 +1468,7 @@ template<> struct __cxx_is_always_lock_free<bool> { enum { __value = 2 == ATOMIC |
| 1458 | 1468 | template<> struct __cxx_is_always_lock_free<char> { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; |
| 1459 | 1469 | template<> struct __cxx_is_always_lock_free<signed char> { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; |
| 1460 | 1470 | template<> struct __cxx_is_always_lock_free<unsigned char> { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; |
| 1461 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1471 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1462 | 1472 | template<> struct __cxx_is_always_lock_free<char8_t> { enum { __value = 2 == ATOMIC_CHAR8_T_LOCK_FREE }; }; |
| 1463 | 1473 | #endif |
| 1464 | 1474 | template<> struct __cxx_is_always_lock_free<char16_t> { enum { __value = 2 == ATOMIC_CHAR16_T_LOCK_FREE }; }; |
| ... | ... | @@ -1673,24 +1683,23 @@ struct __atomic_base // false |
| 1673 | 1683 | _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() _NOEXCEPT |
| 1674 | 1684 | {__cxx_atomic_notify_all(&__a_);} |
| 1675 | 1685 | |
| 1686 | #if _LIBCPP_STD_VER > 17 | |
| 1687 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 1688 | __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} | |
| 1689 | #else | |
| 1676 | 1690 | _LIBCPP_INLINE_VISIBILITY |
| 1677 | 1691 | __atomic_base() _NOEXCEPT _LIBCPP_DEFAULT |
| 1692 | #endif | |
| 1678 | 1693 | |
| 1679 | 1694 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR |
| 1680 | 1695 | __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} |
| 1681 | 1696 | |
| 1682 | 1697 | #ifndef _LIBCPP_CXX03_LANG |
| 1683 | 1698 | __atomic_base(const __atomic_base&) = delete; |
| 1684 | __atomic_base& operator=(const __atomic_base&) = delete; | |
| 1685 | __atomic_base& operator=(const __atomic_base&) volatile = delete; | |
| 1686 | 1699 | #else |
| 1687 | 1700 | private: |
| 1688 | 1701 | _LIBCPP_INLINE_VISIBILITY |
| 1689 | 1702 | __atomic_base(const __atomic_base&); |
| 1690 | _LIBCPP_INLINE_VISIBILITY | |
| 1691 | __atomic_base& operator=(const __atomic_base&); | |
| 1692 | _LIBCPP_INLINE_VISIBILITY | |
| 1693 | __atomic_base& operator=(const __atomic_base&) volatile; | |
| 1694 | 1703 | #endif |
| 1695 | 1704 | }; |
| 1696 | 1705 | |
| ... | ... | @@ -1706,8 +1715,10 @@ struct __atomic_base<_Tp, true> |
| 1706 | 1715 | : public __atomic_base<_Tp, false> |
| 1707 | 1716 | { |
| 1708 | 1717 | typedef __atomic_base<_Tp, false> __base; |
| 1709 | _LIBCPP_INLINE_VISIBILITY | |
| 1718 | ||
| 1719 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1710 | 1720 | __atomic_base() _NOEXCEPT _LIBCPP_DEFAULT |
| 1721 | ||
| 1711 | 1722 | _LIBCPP_INLINE_VISIBILITY |
| 1712 | 1723 | _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} |
| 1713 | 1724 | |
| ... | ... | @@ -1789,8 +1800,15 @@ struct atomic |
| 1789 | 1800 | typedef __atomic_base<_Tp> __base; |
| 1790 | 1801 | typedef _Tp value_type; |
| 1791 | 1802 | typedef value_type difference_type; |
| 1803 | ||
| 1804 | #if _LIBCPP_STD_VER > 17 | |
| 1805 | _LIBCPP_INLINE_VISIBILITY | |
| 1806 | atomic() = default; | |
| 1807 | #else | |
| 1792 | 1808 | _LIBCPP_INLINE_VISIBILITY |
| 1793 | 1809 | atomic() _NOEXCEPT _LIBCPP_DEFAULT |
| 1810 | #endif | |
| 1811 | ||
| 1794 | 1812 | _LIBCPP_INLINE_VISIBILITY |
| 1795 | 1813 | _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} |
| 1796 | 1814 | |
| ... | ... | @@ -1800,6 +1818,9 @@ struct atomic |
| 1800 | 1818 | _LIBCPP_INLINE_VISIBILITY |
| 1801 | 1819 | _Tp operator=(_Tp __d) _NOEXCEPT |
| 1802 | 1820 | {__base::store(__d); return __d;} |
| 1821 | ||
| 1822 | atomic& operator=(const atomic&) = delete; | |
| 1823 | atomic& operator=(const atomic&) volatile = delete; | |
| 1803 | 1824 | }; |
| 1804 | 1825 | |
| 1805 | 1826 | // atomic<T*> |
| ... | ... | @@ -1811,8 +1832,10 @@ struct atomic<_Tp*> |
| 1811 | 1832 | typedef __atomic_base<_Tp*> __base; |
| 1812 | 1833 | typedef _Tp* value_type; |
| 1813 | 1834 | typedef ptrdiff_t difference_type; |
| 1835 | ||
| 1814 | 1836 | _LIBCPP_INLINE_VISIBILITY |
| 1815 | 1837 | atomic() _NOEXCEPT _LIBCPP_DEFAULT |
| 1838 | ||
| 1816 | 1839 | _LIBCPP_INLINE_VISIBILITY |
| 1817 | 1840 | _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} |
| 1818 | 1841 | |
| ... | ... | @@ -1862,6 +1885,9 @@ struct atomic<_Tp*> |
| 1862 | 1885 | _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} |
| 1863 | 1886 | _LIBCPP_INLINE_VISIBILITY |
| 1864 | 1887 | _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT {return fetch_sub(__op) - __op;} |
| 1888 | ||
| 1889 | atomic& operator=(const atomic&) = delete; | |
| 1890 | atomic& operator=(const atomic&) volatile = delete; | |
| 1865 | 1891 | }; |
| 1866 | 1892 | |
| 1867 | 1893 | // atomic_is_lock_free |
| ... | ... | @@ -1885,7 +1911,7 @@ atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT |
| 1885 | 1911 | // atomic_init |
| 1886 | 1912 | |
| 1887 | 1913 | template <class _Tp> |
| 1888 | _LIBCPP_INLINE_VISIBILITY | |
| 1914 | _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY | |
| 1889 | 1915 | void |
| 1890 | 1916 | atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT |
| 1891 | 1917 | { |
| ... | ... | @@ -1893,7 +1919,7 @@ atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NO |
| 1893 | 1919 | } |
| 1894 | 1920 | |
| 1895 | 1921 | template <class _Tp> |
| 1896 | _LIBCPP_INLINE_VISIBILITY | |
| 1922 | _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY | |
| 1897 | 1923 | void |
| 1898 | 1924 | atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT |
| 1899 | 1925 | { |
| ... | ... | @@ -2534,8 +2560,13 @@ typedef struct atomic_flag |
| 2534 | 2560 | void notify_all() _NOEXCEPT |
| 2535 | 2561 | {__cxx_atomic_notify_all(&__a_);} |
| 2536 | 2562 | |
| 2563 | #if _LIBCPP_STD_VER > 17 | |
| 2564 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 2565 | atomic_flag() _NOEXCEPT : __a_(false) {} | |
| 2566 | #else | |
| 2537 | 2567 | _LIBCPP_INLINE_VISIBILITY |
| 2538 | 2568 | atomic_flag() _NOEXCEPT _LIBCPP_DEFAULT |
| 2569 | #endif | |
| 2539 | 2570 | |
| 2540 | 2571 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR |
| 2541 | 2572 | atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION |
| ... | ... | @@ -2728,7 +2759,7 @@ typedef atomic<long> atomic_long; |
| 2728 | 2759 | typedef atomic<unsigned long> atomic_ulong; |
| 2729 | 2760 | typedef atomic<long long> atomic_llong; |
| 2730 | 2761 | typedef atomic<unsigned long long> atomic_ullong; |
| 2731 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 2762 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 2732 | 2763 | typedef atomic<char8_t> atomic_char8_t; |
| 2733 | 2764 | #endif |
| 2734 | 2765 | typedef atomic<char16_t> atomic_char16_t; |
| ... | ... | @@ -2801,4 +2832,4 @@ typedef atomic<__libcpp_unsigned_lock_free> atomic_unsigned_lock_free; |
| 2801 | 2832 | |
| 2802 | 2833 | _LIBCPP_END_NAMESPACE_STD |
| 2803 | 2834 | |
| 2804 | #endif // _LIBCPP_ATOMIC | |
| 2835 | #endif // _LIBCPP_ATOMIC |
lib/libcxx/include/barrier+4-5| ... | ... | @@ -45,8 +45,8 @@ namespace std |
| 45 | 45 | |
| 46 | 46 | */ |
| 47 | 47 | |
| 48 | #include <__config> | |
| 49 | 48 | #include <__availability> |
| 49 | #include <__config> | |
| 50 | 50 | #include <atomic> |
| 51 | 51 | #ifndef _LIBCPP_HAS_NO_TREE_BARRIER |
| 52 | 52 | # include <memory> |
| ... | ... | @@ -107,7 +107,6 @@ void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier); |
| 107 | 107 | |
| 108 | 108 | template<class _CompletionF> |
| 109 | 109 | class __barrier_base { |
| 110 | ||
| 111 | 110 | ptrdiff_t __expected; |
| 112 | 111 | unique_ptr<__barrier_algorithm_base, |
| 113 | 112 | void (*)(__barrier_algorithm_base*)> __base; |
| ... | ... | @@ -146,7 +145,7 @@ public: |
| 146 | 145 | _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY |
| 147 | 146 | void wait(arrival_token&& __old_phase) const |
| 148 | 147 | { |
| 149 | auto const __test_fn = [=]() -> bool { | |
| 148 | auto const __test_fn = [this, __old_phase]() -> bool { | |
| 150 | 149 | return __phase.load(memory_order_acquire) != __old_phase; |
| 151 | 150 | }; |
| 152 | 151 | __libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy()); |
| ... | ... | @@ -309,11 +308,11 @@ public: |
| 309 | 308 | { |
| 310 | 309 | __b.wait(_VSTD::move(__phase)); |
| 311 | 310 | } |
| 312 | 	_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY | |
| 311 | _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY | |
| 313 | 312 | void arrive_and_wait() |
| 314 | 313 | { |
| 315 | 314 | wait(arrive()); |
| 316 | 	} | |
| 315 | } | |
| 317 | 316 | _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY |
| 318 | 317 | void arrive_and_drop() |
| 319 | 318 | { |
lib/libcxx/include/bit+26-56| ... | ... | @@ -55,11 +55,11 @@ namespace std { |
| 55 | 55 | */ |
| 56 | 56 | |
| 57 | 57 | #include <__config> |
| 58 | #include <__bits> | |
| 58 | #include <__bits> // __libcpp_clz | |
| 59 | #include <__debug> | |
| 59 | 60 | #include <limits> |
| 60 | 61 | #include <type_traits> |
| 61 | 62 | #include <version> |
| 62 | #include <__debug> | |
| 63 | 63 | |
| 64 | 64 | #if defined(__IBMCPP__) |
| 65 | 65 | #include "__support/ibm/support.h" |
| ... | ... | @@ -77,49 +77,33 @@ _LIBCPP_PUSH_MACROS |
| 77 | 77 | |
| 78 | 78 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 79 | 79 | |
| 80 | ||
| 81 | template <class _Tp> | |
| 82 | using __bitop_unsigned_integer _LIBCPP_NODEBUG_TYPE = integral_constant<bool, | |
| 83 | is_integral<_Tp>::value && | |
| 84 | is_unsigned<_Tp>::value && | |
| 85 | _IsNotSame<typename remove_cv<_Tp>::type, bool>::value && | |
| 86 | _IsNotSame<typename remove_cv<_Tp>::type, signed char>::value && | |
| 87 | _IsNotSame<typename remove_cv<_Tp>::type, wchar_t>::value && | |
| 88 | _IsNotSame<typename remove_cv<_Tp>::type, char16_t>::value && | |
| 89 | _IsNotSame<typename remove_cv<_Tp>::type, char32_t>::value | |
| 90 | >; | |
| 91 | ||
| 92 | ||
| 93 | 80 | template<class _Tp> |
| 94 | 81 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 95 | 82 | _Tp __rotl(_Tp __t, unsigned int __cnt) _NOEXCEPT |
| 96 | 83 | { |
| 97 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__rotl requires unsigned"); | |
| 84 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotl requires an unsigned integer type"); | |
| 98 | 85 | const unsigned int __dig = numeric_limits<_Tp>::digits; |
| 99 | 86 | if ((__cnt % __dig) == 0) |
| 100 | 87 | return __t; |
| 101 | 88 | return (__t << (__cnt % __dig)) | (__t >> (__dig - (__cnt % __dig))); |
| 102 | 89 | } |
| 103 | 90 | |
| 104 | ||
| 105 | 91 | template<class _Tp> |
| 106 | 92 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 107 | 93 | _Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT |
| 108 | 94 | { |
| 109 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__rotr requires unsigned"); | |
| 95 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type"); | |
| 110 | 96 | const unsigned int __dig = numeric_limits<_Tp>::digits; |
| 111 | 97 | if ((__cnt % __dig) == 0) |
| 112 | 98 | return __t; |
| 113 | 99 | return (__t >> (__cnt % __dig)) | (__t << (__dig - (__cnt % __dig))); |
| 114 | 100 | } |
| 115 | 101 | |
| 116 | ||
| 117 | ||
| 118 | 102 | template<class _Tp> |
| 119 | 103 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 120 | 104 | int __countr_zero(_Tp __t) _NOEXCEPT |
| 121 | 105 | { |
| 122 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__countr_zero requires unsigned"); | |
| 106 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countr_zero requires an unsigned integer type"); | |
| 123 | 107 | if (__t == 0) |
| 124 | 108 | return numeric_limits<_Tp>::digits; |
| 125 | 109 | |
| ... | ... | @@ -132,14 +116,13 @@ int __countr_zero(_Tp __t) _NOEXCEPT |
| 132 | 116 | else |
| 133 | 117 | { |
| 134 | 118 | int __ret = 0; |
| 135 | int __iter = 0; | |
| 136 | 119 | const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits; |
| 137 | while ((__iter = __libcpp_ctz(static_cast<unsigned long long>(__t))) == __ulldigits) | |
| 120 | while (static_cast<unsigned long long>(__t) == 0uLL) | |
| 138 | 121 | { |
| 139 | __ret += __iter; | |
| 122 | __ret += __ulldigits; | |
| 140 | 123 | __t >>= __ulldigits; |
| 141 | 124 | } |
| 142 | return __ret + __iter; | |
| 125 | return __ret + __libcpp_ctz(static_cast<unsigned long long>(__t)); | |
| 143 | 126 | } |
| 144 | 127 | } |
| 145 | 128 | |
| ... | ... | @@ -147,7 +130,7 @@ template<class _Tp> |
| 147 | 130 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 148 | 131 | int __countl_zero(_Tp __t) _NOEXCEPT |
| 149 | 132 | { |
| 150 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__countl_zero requires unsigned"); | |
| 133 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type"); | |
| 151 | 134 | if (__t == 0) |
| 152 | 135 | return numeric_limits<_Tp>::digits; |
| 153 | 136 | |
| ... | ... | @@ -179,30 +162,27 @@ template<class _Tp> |
| 179 | 162 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 180 | 163 | int __countl_one(_Tp __t) _NOEXCEPT |
| 181 | 164 | { |
| 182 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__countl_one requires unsigned"); | |
| 165 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_one requires an unsigned integer type"); | |
| 183 | 166 | return __t != numeric_limits<_Tp>::max() |
| 184 | 167 | ? __countl_zero(static_cast<_Tp>(~__t)) |
| 185 | 168 | : numeric_limits<_Tp>::digits; |
| 186 | 169 | } |
| 187 | 170 | |
| 188 | ||
| 189 | 171 | template<class _Tp> |
| 190 | 172 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 191 | 173 | int __countr_one(_Tp __t) _NOEXCEPT |
| 192 | 174 | { |
| 193 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__countr_one requires unsigned"); | |
| 175 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countr_one requires an unsigned integer type"); | |
| 194 | 176 | return __t != numeric_limits<_Tp>::max() |
| 195 | 177 | ? __countr_zero(static_cast<_Tp>(~__t)) |
| 196 | 178 | : numeric_limits<_Tp>::digits; |
| 197 | 179 | } |
| 198 | 180 | |
| 199 | ||
| 200 | 181 | template<class _Tp> |
| 201 | 182 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 202 | int | |
| 203 | __popcount(_Tp __t) _NOEXCEPT | |
| 183 | int __popcount(_Tp __t) _NOEXCEPT | |
| 204 | 184 | { |
| 205 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__libcpp_popcount requires unsigned"); | |
| 185 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__popcount requires an unsigned integer type"); | |
| 206 | 186 | if (sizeof(_Tp) <= sizeof(unsigned int)) |
| 207 | 187 | return __libcpp_popcount(static_cast<unsigned int>(__t)); |
| 208 | 188 | else if (sizeof(_Tp) <= sizeof(unsigned long)) |
| ... | ... | @@ -221,13 +201,12 @@ __popcount(_Tp __t) _NOEXCEPT |
| 221 | 201 | } |
| 222 | 202 | } |
| 223 | 203 | |
| 224 | ||
| 225 | 204 | // integral log base 2 |
| 226 | 205 | template<class _Tp> |
| 227 | 206 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 228 | 207 | unsigned __bit_log2(_Tp __t) _NOEXCEPT |
| 229 | 208 | { |
| 230 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__bit_log2 requires unsigned"); | |
| 209 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__bit_log2 requires an unsigned integer type"); | |
| 231 | 210 | return numeric_limits<_Tp>::digits - 1 - __countl_zero(__t); |
| 232 | 211 | } |
| 233 | 212 | |
| ... | ... | @@ -235,80 +214,71 @@ template <class _Tp> |
| 235 | 214 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR |
| 236 | 215 | bool __has_single_bit(_Tp __t) _NOEXCEPT |
| 237 | 216 | { |
| 238 | static_assert(__bitop_unsigned_integer<_Tp>::value, "__has_single_bit requires unsigned"); | |
| 217 | static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__has_single_bit requires an unsigned integer type"); | |
| 239 | 218 | return __t != 0 && (((__t & (__t - 1)) == 0)); |
| 240 | 219 | } |
| 241 | 220 | |
| 242 | ||
| 243 | 221 | #if _LIBCPP_STD_VER > 17 |
| 244 | 222 | |
| 245 | 223 | template<class _Tp> |
| 246 | 224 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 247 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> | |
| 225 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, _Tp> | |
| 248 | 226 | rotl(_Tp __t, unsigned int __cnt) noexcept |
| 249 | 227 | { |
| 250 | 228 | return __rotl(__t, __cnt); |
| 251 | 229 | } |
| 252 | 230 | |
| 253 | ||
| 254 | // rotr | |
| 255 | 231 | template<class _Tp> |
| 256 | 232 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 257 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> | |
| 233 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, _Tp> | |
| 258 | 234 | rotr(_Tp __t, unsigned int __cnt) noexcept |
| 259 | 235 | { |
| 260 | 236 | return __rotr(__t, __cnt); |
| 261 | 237 | } |
| 262 | 238 | |
| 263 | ||
| 264 | 239 | template<class _Tp> |
| 265 | 240 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 266 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> | |
| 241 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, int> | |
| 267 | 242 | countl_zero(_Tp __t) noexcept |
| 268 | 243 | { |
| 269 | 244 | return __countl_zero(__t); |
| 270 | 245 | } |
| 271 | 246 | |
| 272 | ||
| 273 | 247 | template<class _Tp> |
| 274 | 248 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 275 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> | |
| 249 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, int> | |
| 276 | 250 | countl_one(_Tp __t) noexcept |
| 277 | 251 | { |
| 278 | 252 | return __countl_one(__t); |
| 279 | 253 | } |
| 280 | 254 | |
| 281 | ||
| 282 | 255 | template<class _Tp> |
| 283 | 256 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 284 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> | |
| 257 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, int> | |
| 285 | 258 | countr_zero(_Tp __t) noexcept |
| 286 | 259 | { |
| 287 | 260 | return __countr_zero(__t); |
| 288 | 261 | } |
| 289 | 262 | |
| 290 | ||
| 291 | 263 | template<class _Tp> |
| 292 | 264 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 293 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> | |
| 265 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, int> | |
| 294 | 266 | countr_one(_Tp __t) noexcept |
| 295 | 267 | { |
| 296 | 268 | return __countr_one(__t); |
| 297 | 269 | } |
| 298 | 270 | |
| 299 | ||
| 300 | 271 | template<class _Tp> |
| 301 | 272 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 302 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> | |
| 273 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, int> | |
| 303 | 274 | popcount(_Tp __t) noexcept |
| 304 | 275 | { |
| 305 | 276 | return __popcount(__t); |
| 306 | 277 | } |
| 307 | 278 | |
| 308 | ||
| 309 | 279 | template <class _Tp> |
| 310 | 280 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 311 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, bool> | |
| 281 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, bool> | |
| 312 | 282 | has_single_bit(_Tp __t) noexcept |
| 313 | 283 | { |
| 314 | 284 | return __has_single_bit(__t); |
| ... | ... | @@ -316,7 +286,7 @@ has_single_bit(_Tp __t) noexcept |
| 316 | 286 | |
| 317 | 287 | template <class _Tp> |
| 318 | 288 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 319 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> | |
| 289 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, _Tp> | |
| 320 | 290 | bit_floor(_Tp __t) noexcept |
| 321 | 291 | { |
| 322 | 292 | return __t == 0 ? 0 : _Tp{1} << __bit_log2(__t); |
| ... | ... | @@ -324,7 +294,7 @@ bit_floor(_Tp __t) noexcept |
| 324 | 294 | |
| 325 | 295 | template <class _Tp> |
| 326 | 296 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 327 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> | |
| 297 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, _Tp> | |
| 328 | 298 | bit_ceil(_Tp __t) noexcept |
| 329 | 299 | { |
| 330 | 300 | if (__t < 2) return 1; |
| ... | ... | @@ -343,7 +313,7 @@ bit_ceil(_Tp __t) noexcept |
| 343 | 313 | |
| 344 | 314 | template <class _Tp> |
| 345 | 315 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 346 | enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> | |
| 316 | _EnableIf<__libcpp_is_unsigned_integer<_Tp>::value, _Tp> | |
| 347 | 317 | bit_width(_Tp __t) noexcept |
| 348 | 318 | { |
| 349 | 319 | return __t == 0 ? 0 : __bit_log2(__t) + 1; |
lib/libcxx/include/bitset+9-15| ... | ... | @@ -114,12 +114,12 @@ template <size_t N> struct hash<std::bitset<N>>; |
| 114 | 114 | |
| 115 | 115 | #include <__config> |
| 116 | 116 | #include <__bit_reference> |
| 117 | #include <cstddef> | |
| 117 | #include <__functional_base> | |
| 118 | 118 | #include <climits> |
| 119 | #include <string> | |
| 120 | #include <stdexcept> | |
| 119 | #include <cstddef> | |
| 121 | 120 | #include <iosfwd> |
| 122 | #include <__functional_base> | |
| 121 | #include <stdexcept> | |
| 122 | #include <string> | |
| 123 | 123 | |
| 124 | 124 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 125 | 125 | #pragma GCC system_header |
| ... | ... | @@ -202,7 +202,7 @@ private: |
| 202 | 202 | void __init(unsigned long long __v, false_type) _NOEXCEPT; |
| 203 | 203 | _LIBCPP_INLINE_VISIBILITY |
| 204 | 204 | void __init(unsigned long long __v, true_type) _NOEXCEPT; |
| 205 | #endif // _LIBCPP_CXX03_LANG | |
| 205 | #endif // _LIBCPP_CXX03_LANG | |
| 206 | 206 | unsigned long to_ulong(false_type) const; |
| 207 | 207 | _LIBCPP_INLINE_VISIBILITY |
| 208 | 208 | unsigned long to_ulong(true_type) const; |
| ... | ... | @@ -258,7 +258,7 @@ __bitset<_N_words, _Size>::__init(unsigned long long __v, true_type) _NOEXCEPT |
| 258 | 258 | _VSTD::fill(__first_ + 1, __first_ + sizeof(__first_)/sizeof(__first_[0]), __storage_type(0)); |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | #endif // _LIBCPP_CXX03_LANG | |
| 261 | #endif // _LIBCPP_CXX03_LANG | |
| 262 | 262 | |
| 263 | 263 | template <size_t _N_words, size_t _Size> |
| 264 | 264 | inline |
| ... | ... | @@ -775,10 +775,7 @@ bitset<_Size>::bitset(const _CharT* __str, |
| 775 | 775 | for (; __i < _Mp; ++__i) |
| 776 | 776 | { |
| 777 | 777 | _CharT __c = __str[_Mp - 1 - __i]; |
| 778 | if (__c == __zero) | |
| 779 | (*this)[__i] = false; | |
| 780 | else | |
| 781 | (*this)[__i] = true; | |
| 778 | (*this)[__i] = (__c == __one); | |
| 782 | 779 | } |
| 783 | 780 | _VSTD::fill(base::__make_iter(__i), base::__make_iter(_Size), false); |
| 784 | 781 | } |
| ... | ... | @@ -803,10 +800,7 @@ bitset<_Size>::bitset(const basic_string<_CharT,_Traits,_Allocator>& __str, |
| 803 | 800 | for (; __i < _Mp; ++__i) |
| 804 | 801 | { |
| 805 | 802 | _CharT __c = __str[__pos + _Mp - 1 - __i]; |
| 806 | if (_Traits::eq(__c, __zero)) | |
| 807 | (*this)[__i] = false; | |
| 808 | else | |
| 809 | (*this)[__i] = true; | |
| 803 | (*this)[__i] = _Traits::eq(__c, __one); | |
| 810 | 804 | } |
| 811 | 805 | _VSTD::fill(base::__make_iter(__i), base::__make_iter(_Size), false); |
| 812 | 806 | } |
| ... | ... | @@ -1106,4 +1100,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 1106 | 1100 | |
| 1107 | 1101 | _LIBCPP_POP_MACROS |
| 1108 | 1102 | |
| 1109 | #endif // _LIBCPP_BITSET | |
| 1103 | #endif // _LIBCPP_BITSET |
lib/libcxx/include/ccomplex+1-1| ... | ... | @@ -25,4 +25,4 @@ |
| 25 | 25 | |
| 26 | 26 | // hh 080623 Created |
| 27 | 27 | |
| 28 | #endif // _LIBCPP_CCOMPLEX | |
| 28 | #endif // _LIBCPP_CCOMPLEX |
lib/libcxx/include/cctype+15-15| ... | ... | @@ -100,21 +100,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD |
| 100 | 100 | #endif |
| 101 | 101 | |
| 102 | 102 | |
| 103 | using ::isalnum; | |
| 104 | using ::isalpha; | |
| 105 | using ::isblank; | |
| 106 | using ::iscntrl; | |
| 107 | using ::isdigit; | |
| 108 | using ::isgraph; | |
| 109 | using ::islower; | |
| 110 | using ::isprint; | |
| 111 | using ::ispunct; | |
| 112 | using ::isspace; | |
| 113 | using ::isupper; | |
| 114 | using ::isxdigit; | |
| 115 | using ::tolower; | |
| 116 | using ::toupper; | |
| 103 | using ::isalnum _LIBCPP_USING_IF_EXISTS; | |
| 104 | using ::isalpha _LIBCPP_USING_IF_EXISTS; | |
| 105 | using ::isblank _LIBCPP_USING_IF_EXISTS; | |
| 106 | using ::iscntrl _LIBCPP_USING_IF_EXISTS; | |
| 107 | using ::isdigit _LIBCPP_USING_IF_EXISTS; | |
| 108 | using ::isgraph _LIBCPP_USING_IF_EXISTS; | |
| 109 | using ::islower _LIBCPP_USING_IF_EXISTS; | |
| 110 | using ::isprint _LIBCPP_USING_IF_EXISTS; | |
| 111 | using ::ispunct _LIBCPP_USING_IF_EXISTS; | |
| 112 | using ::isspace _LIBCPP_USING_IF_EXISTS; | |
| 113 | using ::isupper _LIBCPP_USING_IF_EXISTS; | |
| 114 | using ::isxdigit _LIBCPP_USING_IF_EXISTS; | |
| 115 | using ::tolower _LIBCPP_USING_IF_EXISTS; | |
| 116 | using ::toupper _LIBCPP_USING_IF_EXISTS; | |
| 117 | 117 | |
| 118 | 118 | _LIBCPP_END_NAMESPACE_STD |
| 119 | 119 | |
| 120 | #endif // _LIBCPP_CCTYPE | |
| 120 | #endif // _LIBCPP_CCTYPE |
lib/libcxx/include/cerrno+1-1| ... | ... | @@ -29,4 +29,4 @@ Macros: |
| 29 | 29 | #pragma GCC system_header |
| 30 | 30 | #endif |
| 31 | 31 | |
| 32 | #endif // _LIBCPP_CERRNO | |
| 32 | #endif // _LIBCPP_CERRNO |
lib/libcxx/include/cfenv+15-15| ... | ... | @@ -61,21 +61,21 @@ int feupdateenv(const fenv_t* envp); |
| 61 | 61 | |
| 62 | 62 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 63 | 63 | |
| 64 | using ::fenv_t; | |
| 65 | using ::fexcept_t; | |
| 66 | ||
| 67 | using ::feclearexcept; | |
| 68 | using ::fegetexceptflag; | |
| 69 | using ::feraiseexcept; | |
| 70 | using ::fesetexceptflag; | |
| 71 | using ::fetestexcept; | |
| 72 | using ::fegetround; | |
| 73 | using ::fesetround; | |
| 74 | using ::fegetenv; | |
| 75 | using ::feholdexcept; | |
| 76 | using ::fesetenv; | |
| 77 | using ::feupdateenv; | |
| 64 | using ::fenv_t _LIBCPP_USING_IF_EXISTS; | |
| 65 | using ::fexcept_t _LIBCPP_USING_IF_EXISTS; | |
| 66 | ||
| 67 | using ::feclearexcept _LIBCPP_USING_IF_EXISTS; | |
| 68 | using ::fegetexceptflag _LIBCPP_USING_IF_EXISTS; | |
| 69 | using ::feraiseexcept _LIBCPP_USING_IF_EXISTS; | |
| 70 | using ::fesetexceptflag _LIBCPP_USING_IF_EXISTS; | |
| 71 | using ::fetestexcept _LIBCPP_USING_IF_EXISTS; | |
| 72 | using ::fegetround _LIBCPP_USING_IF_EXISTS; | |
| 73 | using ::fesetround _LIBCPP_USING_IF_EXISTS; | |
| 74 | using ::fegetenv _LIBCPP_USING_IF_EXISTS; | |
| 75 | using ::feholdexcept _LIBCPP_USING_IF_EXISTS; | |
| 76 | using ::fesetenv _LIBCPP_USING_IF_EXISTS; | |
| 77 | using ::feupdateenv _LIBCPP_USING_IF_EXISTS; | |
| 78 | 78 | |
| 79 | 79 | _LIBCPP_END_NAMESPACE_STD |
| 80 | 80 | |
| 81 | #endif // _LIBCPP_CFENV | |
| 81 | #endif // _LIBCPP_CFENV |
lib/libcxx/include/cfloat+1-1| ... | ... | @@ -76,4 +76,4 @@ Macros: |
| 76 | 76 | #pragma GCC system_header |
| 77 | 77 | #endif |
| 78 | 78 | |
| 79 | #endif // _LIBCPP_CFLOAT | |
| 79 | #endif // _LIBCPP_CFLOAT |
lib/libcxx/include/charconv+97-40| ... | ... | @@ -73,11 +73,13 @@ namespace std { |
| 73 | 73 | |
| 74 | 74 | */ |
| 75 | 75 | |
| 76 | #include <__config> | |
| 77 | 76 | #include <__availability> |
| 77 | #include <__config> | |
| 78 | 78 | #include <__errc> |
| 79 | #include <__utility/to_underlying.h> | |
| 79 | 80 | #include <cmath> // for log2f |
| 80 | 81 | #include <cstdint> |
| 82 | #include <cstdlib> // for _LIBCPP_UNREACHABLE | |
| 81 | 83 | #include <cstring> |
| 82 | 84 | #include <limits> |
| 83 | 85 | #include <type_traits> |
| ... | ... | @@ -108,6 +110,47 @@ enum class _LIBCPP_ENUM_VIS chars_format |
| 108 | 110 | general = fixed | scientific |
| 109 | 111 | }; |
| 110 | 112 | |
| 113 | inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format | |
| 114 | operator~(chars_format __x) { | |
| 115 | return chars_format(~_VSTD::__to_underlying(__x)); | |
| 116 | } | |
| 117 | ||
| 118 | inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format | |
| 119 | operator&(chars_format __x, chars_format __y) { | |
| 120 | return chars_format(_VSTD::__to_underlying(__x) & | |
| 121 | _VSTD::__to_underlying(__y)); | |
| 122 | } | |
| 123 | ||
| 124 | inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format | |
| 125 | operator|(chars_format __x, chars_format __y) { | |
| 126 | return chars_format(_VSTD::__to_underlying(__x) | | |
| 127 | _VSTD::__to_underlying(__y)); | |
| 128 | } | |
| 129 | ||
| 130 | inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format | |
| 131 | operator^(chars_format __x, chars_format __y) { | |
| 132 | return chars_format(_VSTD::__to_underlying(__x) ^ | |
| 133 | _VSTD::__to_underlying(__y)); | |
| 134 | } | |
| 135 | ||
| 136 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 chars_format& | |
| 137 | operator&=(chars_format& __x, chars_format __y) { | |
| 138 | __x = __x & __y; | |
| 139 | return __x; | |
| 140 | } | |
| 141 | ||
| 142 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 chars_format& | |
| 143 | operator|=(chars_format& __x, chars_format __y) { | |
| 144 | __x = __x | __y; | |
| 145 | return __x; | |
| 146 | } | |
| 147 | ||
| 148 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 chars_format& | |
| 149 | operator^=(chars_format& __x, chars_format __y) { | |
| 150 | __x = __x ^ __y; | |
| 151 | return __x; | |
| 152 | } | |
| 153 | ||
| 111 | 154 | struct _LIBCPP_TYPE_VIS to_chars_result |
| 112 | 155 | { |
| 113 | 156 | char* ptr; |
| ... | ... | @@ -288,19 +331,12 @@ __complement(_Tp __x) |
| 288 | 331 | return _Tp(~__x + 1); |
| 289 | 332 | } |
| 290 | 333 | |
| 291 | template <typename _Tp> | |
| 292 | inline _LIBCPP_INLINE_VISIBILITY typename make_unsigned<_Tp>::type | |
| 293 | __to_unsigned(_Tp __x) | |
| 294 | { | |
| 295 | return static_cast<typename make_unsigned<_Tp>::type>(__x); | |
| 296 | } | |
| 297 | ||
| 298 | 334 | template <typename _Tp> |
| 299 | 335 | _LIBCPP_AVAILABILITY_TO_CHARS |
| 300 | 336 | inline _LIBCPP_INLINE_VISIBILITY to_chars_result |
| 301 | 337 | __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) |
| 302 | 338 | { |
| 303 | auto __x = __to_unsigned(__value); | |
| 339 | auto __x = __to_unsigned_like(__value); | |
| 304 | 340 | if (__value < 0 && __first != __last) |
| 305 | 341 | { |
| 306 | 342 | *__first++ = '-'; |
| ... | ... | @@ -348,7 +384,7 @@ inline _LIBCPP_INLINE_VISIBILITY to_chars_result |
| 348 | 384 | __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, |
| 349 | 385 | true_type) |
| 350 | 386 | { |
| 351 | auto __x = __to_unsigned(__value); | |
| 387 | auto __x = __to_unsigned_like(__value); | |
| 352 | 388 | if (__value < 0 && __first != __last) |
| 353 | 389 | { |
| 354 | 390 | *__first++ = '-'; |
| ... | ... | @@ -358,33 +394,54 @@ __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, |
| 358 | 394 | return __to_chars_integral(__first, __last, __x, __base, false_type()); |
| 359 | 395 | } |
| 360 | 396 | |
| 397 | template <typename _Tp> | |
| 398 | _LIBCPP_AVAILABILITY_TO_CHARS _LIBCPP_INLINE_VISIBILITY int __to_chars_integral_width(_Tp __value, unsigned __base) { | |
| 399 | _LIBCPP_ASSERT(__value >= 0, "The function requires a non-negative value."); | |
| 400 | ||
| 401 | unsigned __base_2 = __base * __base; | |
| 402 | unsigned __base_3 = __base_2 * __base; | |
| 403 | unsigned __base_4 = __base_2 * __base_2; | |
| 404 | ||
| 405 | int __r = 0; | |
| 406 | while (true) { | |
| 407 | if (__value < __base) | |
| 408 | return __r + 1; | |
| 409 | if (__value < __base_2) | |
| 410 | return __r + 2; | |
| 411 | if (__value < __base_3) | |
| 412 | return __r + 3; | |
| 413 | if (__value < __base_4) | |
| 414 | return __r + 4; | |
| 415 | ||
| 416 | __value /= __base_4; | |
| 417 | __r += 4; | |
| 418 | } | |
| 419 | ||
| 420 | _LIBCPP_UNREACHABLE(); | |
| 421 | } | |
| 422 | ||
| 361 | 423 | template <typename _Tp> |
| 362 | 424 | _LIBCPP_AVAILABILITY_TO_CHARS |
| 363 | 425 | inline _LIBCPP_INLINE_VISIBILITY to_chars_result |
| 364 | 426 | __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, |
| 365 | 427 | false_type) |
| 366 | 428 | { |
| 367 | if (__base == 10) | |
| 368 | return __to_chars_itoa(__first, __last, __value, false_type()); | |
| 369 | ||
| 370 | auto __p = __last; | |
| 371 | while (__p != __first) | |
| 372 | { | |
| 373 | auto __c = __value % __base; | |
| 374 | __value /= __base; | |
| 375 | *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c]; | |
| 376 | if (__value == 0) | |
| 377 | break; | |
| 378 | } | |
| 379 | ||
| 380 | auto __len = __last - __p; | |
| 381 | if (__value != 0 || !__len) | |
| 382 | return {__last, errc::value_too_large}; | |
| 383 | else | |
| 384 | { | |
| 385 | _VSTD::memmove(__first, __p, __len); | |
| 386 | return {__first + __len, {}}; | |
| 387 | } | |
| 429 | if (__base == 10) | |
| 430 | return __to_chars_itoa(__first, __last, __value, false_type()); | |
| 431 | ||
| 432 | ptrdiff_t __cap = __last - __first; | |
| 433 | int __n = __to_chars_integral_width(__value, __base); | |
| 434 | if (__n > __cap) | |
| 435 | return {__last, errc::value_too_large}; | |
| 436 | ||
| 437 | __last = __first + __n; | |
| 438 | char* __p = __last; | |
| 439 | do { | |
| 440 | unsigned __c = __value % __base; | |
| 441 | __value /= __base; | |
| 442 | *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c]; | |
| 443 | } while (__value != 0); | |
| 444 | return {__last, errc(0)}; | |
| 388 | 445 | } |
| 389 | 446 | |
| 390 | 447 | template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> |
| ... | ... | @@ -410,7 +467,7 @@ inline _LIBCPP_INLINE_VISIBILITY from_chars_result |
| 410 | 467 | __sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) |
| 411 | 468 | { |
| 412 | 469 | using __tl = numeric_limits<_Tp>; |
| 413 | decltype(__to_unsigned(__value)) __x; | |
| 470 | decltype(__to_unsigned_like(__value)) __x; | |
| 414 | 471 | |
| 415 | 472 | bool __neg = (__first != __last && *__first == '-'); |
| 416 | 473 | auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...); |
| ... | ... | @@ -426,7 +483,7 @@ __sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) |
| 426 | 483 | |
| 427 | 484 | if (__neg) |
| 428 | 485 | { |
| 429 | if (__x <= __complement(__to_unsigned(__tl::min()))) | |
| 486 | if (__x <= __complement(__to_unsigned_like(__tl::min()))) | |
| 430 | 487 | { |
| 431 | 488 | __x = __complement(__x); |
| 432 | 489 | _VSTD::memcpy(&__value, &__x, sizeof(__x)); |
| ... | ... | @@ -541,7 +598,7 @@ template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0 |
| 541 | 598 | inline _LIBCPP_INLINE_VISIBILITY from_chars_result |
| 542 | 599 | __from_chars_atoi(const char* __first, const char* __last, _Tp& __value) |
| 543 | 600 | { |
| 544 | using __t = decltype(__to_unsigned(__value)); | |
| 601 | using __t = decltype(__to_unsigned_like(__value)); | |
| 545 | 602 | return __sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); |
| 546 | 603 | } |
| 547 | 604 | |
| ... | ... | @@ -555,13 +612,13 @@ __from_chars_integral(const char* __first, const char* __last, _Tp& __value, |
| 555 | 612 | |
| 556 | 613 | return __subject_seq_combinator( |
| 557 | 614 | __first, __last, __value, |
| 558 | [](const char* __p, const char* __last, _Tp& __value, | |
| 615 | [](const char* __p, const char* __lastx, _Tp& __value, | |
| 559 | 616 | int __base) -> from_chars_result { |
| 560 | 617 | using __tl = numeric_limits<_Tp>; |
| 561 | 618 | auto __digits = __tl::digits / log2f(float(__base)); |
| 562 | 619 | _Tp __a = __in_pattern(*__p++, __base).__val, __b = 0; |
| 563 | 620 | |
| 564 | for (int __i = 1; __p != __last; ++__i, ++__p) | |
| 621 | for (int __i = 1; __p != __lastx; ++__i, ++__p) | |
| 565 | 622 | { |
| 566 | 623 | if (auto __c = __in_pattern(*__p, __base)) |
| 567 | 624 | { |
| ... | ... | @@ -579,7 +636,7 @@ __from_chars_integral(const char* __first, const char* __last, _Tp& __value, |
| 579 | 636 | break; |
| 580 | 637 | } |
| 581 | 638 | |
| 582 | if (__p == __last || !__in_pattern(*__p, __base)) | |
| 639 | if (__p == __lastx || !__in_pattern(*__p, __base)) | |
| 583 | 640 | { |
| 584 | 641 | if (__tl::max() - __a >= __b) |
| 585 | 642 | { |
| ... | ... | @@ -597,7 +654,7 @@ inline _LIBCPP_INLINE_VISIBILITY from_chars_result |
| 597 | 654 | __from_chars_integral(const char* __first, const char* __last, _Tp& __value, |
| 598 | 655 | int __base) |
| 599 | 656 | { |
| 600 | using __t = decltype(__to_unsigned(__value)); | |
| 657 | using __t = decltype(__to_unsigned_like(__value)); | |
| 601 | 658 | return __sign_combinator(__first, __last, __value, |
| 602 | 659 | __from_chars_integral<__t>, __base); |
| 603 | 660 | } |
| ... | ... | @@ -617,10 +674,10 @@ from_chars(const char* __first, const char* __last, _Tp& __value, int __base) |
| 617 | 674 | return __from_chars_integral(__first, __last, __value, __base); |
| 618 | 675 | } |
| 619 | 676 | |
| 620 | #endif // _LIBCPP_CXX03_LANG | |
| 677 | #endif // _LIBCPP_CXX03_LANG | |
| 621 | 678 | |
| 622 | 679 | _LIBCPP_END_NAMESPACE_STD |
| 623 | 680 | |
| 624 | 681 | _LIBCPP_POP_MACROS |
| 625 | 682 | |
| 626 | #endif // _LIBCPP_CHARCONV | |
| 683 | #endif // _LIBCPP_CHARCONV |
lib/libcxx/include/chrono+17-16| ... | ... | @@ -823,12 +823,13 @@ constexpr chrono::year operator ""y(unsigned lo |
| 823 | 823 | } // std |
| 824 | 824 | */ |
| 825 | 825 | |
| 826 | #include <__config> | |
| 827 | 826 | #include <__availability> |
| 827 | #include <__config> | |
| 828 | #include <compare> | |
| 828 | 829 | #include <ctime> |
| 829 | #include <type_traits> | |
| 830 | #include <ratio> | |
| 831 | 830 | #include <limits> |
| 831 | #include <ratio> | |
| 832 | #include <type_traits> | |
| 832 | 833 | #include <version> |
| 833 | 834 | |
| 834 | 835 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -1091,7 +1092,7 @@ public: |
| 1091 | 1092 | (__no_overflow<_Period2, period>::type::den == 1 && |
| 1092 | 1093 | !treat_as_floating_point<_Rep2>::value)) |
| 1093 | 1094 | >::type* = nullptr) |
| 1094 | : __rep_(_VSTD::chrono::duration_cast<duration>(__d).count()) {} | |
| 1095 | : __rep_(chrono::duration_cast<duration>(__d).count()) {} | |
| 1095 | 1096 | |
| 1096 | 1097 | // observer |
| 1097 | 1098 | |
| ... | ... | @@ -1410,7 +1411,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 1410 | 1411 | time_point<_Clock, _ToDuration> |
| 1411 | 1412 | time_point_cast(const time_point<_Clock, _Duration>& __t) |
| 1412 | 1413 | { |
| 1413 | return time_point<_Clock, _ToDuration>(_VSTD::chrono::duration_cast<_ToDuration>(__t.time_since_epoch())); | |
| 1414 | return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch())); | |
| 1414 | 1415 | } |
| 1415 | 1416 | |
| 1416 | 1417 | #if _LIBCPP_STD_VER > 14 |
| ... | ... | @@ -1926,13 +1927,13 @@ inline constexpr weekday& weekday::operator-=(const days& __dd) noexcept |
| 1926 | 1927 | |
| 1927 | 1928 | class weekday_indexed { |
| 1928 | 1929 | private: |
| 1929 | _VSTD::chrono::weekday __wd; | |
| 1930 | chrono::weekday __wd; | |
| 1930 | 1931 | unsigned char __idx; |
| 1931 | 1932 | public: |
| 1932 | 1933 | weekday_indexed() = default; |
| 1933 | inline constexpr weekday_indexed(const _VSTD::chrono::weekday& __wdval, unsigned __idxval) noexcept | |
| 1934 | inline constexpr weekday_indexed(const chrono::weekday& __wdval, unsigned __idxval) noexcept | |
| 1934 | 1935 | : __wd{__wdval}, __idx(__idxval) {} |
| 1935 | inline constexpr _VSTD::chrono::weekday weekday() const noexcept { return __wd; } | |
| 1936 | inline constexpr chrono::weekday weekday() const noexcept { return __wd; } | |
| 1936 | 1937 | inline constexpr unsigned index() const noexcept { return __idx; } |
| 1937 | 1938 | inline constexpr bool ok() const noexcept { return __wd.ok() && __idx >= 1 && __idx <= 5; } |
| 1938 | 1939 | }; |
| ... | ... | @@ -1948,11 +1949,11 @@ bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noex |
| 1948 | 1949 | |
| 1949 | 1950 | class weekday_last { |
| 1950 | 1951 | private: |
| 1951 | _VSTD::chrono::weekday __wd; | |
| 1952 | chrono::weekday __wd; | |
| 1952 | 1953 | public: |
| 1953 | explicit constexpr weekday_last(const _VSTD::chrono::weekday& __val) noexcept | |
| 1954 | explicit constexpr weekday_last(const chrono::weekday& __val) noexcept | |
| 1954 | 1955 | : __wd{__val} {} |
| 1955 | constexpr _VSTD::chrono::weekday weekday() const noexcept { return __wd; } | |
| 1956 | constexpr chrono::weekday weekday() const noexcept { return __wd; } | |
| 1956 | 1957 | constexpr bool ok() const noexcept { return __wd.ok(); } |
| 1957 | 1958 | }; |
| 1958 | 1959 | |
| ... | ... | @@ -2308,8 +2309,8 @@ inline constexpr |
| 2308 | 2309 | year_month_day |
| 2309 | 2310 | year_month_day::__from_days(days __d) noexcept |
| 2310 | 2311 | { |
| 2311 | static_assert(std::numeric_limits<unsigned>::digits >= 18, ""); | |
| 2312 | static_assert(std::numeric_limits<int>::digits >= 20 , ""); | |
| 2312 | static_assert(numeric_limits<unsigned>::digits >= 18, ""); | |
| 2313 | static_assert(numeric_limits<int>::digits >= 20 , ""); | |
| 2313 | 2314 | const int __z = __d.count() + 719468; |
| 2314 | 2315 | const int __era = (__z >= 0 ? __z : __z - 146096) / 146097; |
| 2315 | 2316 | const unsigned __doe = static_cast<unsigned>(__z - __era * 146097); // [0, 146096] |
| ... | ... | @@ -2325,8 +2326,8 @@ year_month_day::__from_days(days __d) noexcept |
| 2325 | 2326 | // https://howardhinnant.github.io/date_algorithms.html#days_from_civil |
| 2326 | 2327 | inline constexpr days year_month_day::__to_days() const noexcept |
| 2327 | 2328 | { |
| 2328 | static_assert(std::numeric_limits<unsigned>::digits >= 18, ""); | |
| 2329 | static_assert(std::numeric_limits<int>::digits >= 20 , ""); | |
| 2329 | static_assert(numeric_limits<unsigned>::digits >= 18, ""); | |
| 2330 | static_assert(numeric_limits<int>::digits >= 20 , ""); | |
| 2330 | 2331 | |
| 2331 | 2332 | const int __yr = static_cast<int>(__y) - (__m <= February); |
| 2332 | 2333 | const unsigned __mth = static_cast<unsigned>(__m); |
| ... | ... | @@ -2964,4 +2965,4 @@ _LIBCPP_END_NAMESPACE_FILESYSTEM |
| 2964 | 2965 | |
| 2965 | 2966 | _LIBCPP_POP_MACROS |
| 2966 | 2967 | |
| 2967 | #endif // _LIBCPP_CHRONO | |
| 2968 | #endif // _LIBCPP_CHRONO |
lib/libcxx/include/cinttypes+8-8| ... | ... | @@ -244,14 +244,14 @@ uintmax_t wcstoumax(const wchar_t* restrict nptr, wchar_t** restrict endptr, int |
| 244 | 244 | |
| 245 | 245 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 246 | 246 | |
| 247 | using::imaxdiv_t; | |
| 248 | using::imaxabs; | |
| 249 | using::imaxdiv; | |
| 250 | using::strtoimax; | |
| 251 | using::strtoumax; | |
| 252 | using::wcstoimax; | |
| 253 | using::wcstoumax; | |
| 247 | using ::imaxdiv_t _LIBCPP_USING_IF_EXISTS; | |
| 248 | using ::imaxabs _LIBCPP_USING_IF_EXISTS; | |
| 249 | using ::imaxdiv _LIBCPP_USING_IF_EXISTS; | |
| 250 | using ::strtoimax _LIBCPP_USING_IF_EXISTS; | |
| 251 | using ::strtoumax _LIBCPP_USING_IF_EXISTS; | |
| 252 | using ::wcstoimax _LIBCPP_USING_IF_EXISTS; | |
| 253 | using ::wcstoumax _LIBCPP_USING_IF_EXISTS; | |
| 254 | 254 | |
| 255 | 255 | _LIBCPP_END_NAMESPACE_STD |
| 256 | 256 | |
| 257 | #endif // _LIBCPP_CINTTYPES | |
| 257 | #endif // _LIBCPP_CINTTYPES |
lib/libcxx/include/ciso646+1-1| ... | ... | @@ -21,4 +21,4 @@ |
| 21 | 21 | #pragma GCC system_header |
| 22 | 22 | #endif |
| 23 | 23 | |
| 24 | #endif // _LIBCPP_CISO646 | |
| 24 | #endif // _LIBCPP_CISO646 |
lib/libcxx/include/climits+1-1| ... | ... | @@ -44,4 +44,4 @@ Macros: |
| 44 | 44 | #pragma GCC system_header |
| 45 | 45 | #endif |
| 46 | 46 | |
| 47 | #endif // _LIBCPP_CLIMITS | |
| 47 | #endif // _LIBCPP_CLIMITS |
lib/libcxx/include/clocale+4-4| ... | ... | @@ -43,12 +43,12 @@ lconv* localeconv(); |
| 43 | 43 | |
| 44 | 44 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 45 | 45 | |
| 46 | using ::lconv; | |
| 46 | using ::lconv _LIBCPP_USING_IF_EXISTS; | |
| 47 | 47 | #ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS |
| 48 | using ::setlocale; | |
| 48 | using ::setlocale _LIBCPP_USING_IF_EXISTS; | |
| 49 | 49 | #endif |
| 50 | using ::localeconv; | |
| 50 | using ::localeconv _LIBCPP_USING_IF_EXISTS; | |
| 51 | 51 | |
| 52 | 52 | _LIBCPP_END_NAMESPACE_STD |
| 53 | 53 | |
| 54 | #endif // _LIBCPP_CLOCALE | |
| 54 | #endif // _LIBCPP_CLOCALE |
lib/libcxx/include/cmath+213-215| ... | ... | @@ -318,217 +318,215 @@ _LIBCPP_PUSH_MACROS |
| 318 | 318 | |
| 319 | 319 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 320 | 320 | |
| 321 | using ::signbit; | |
| 322 | using ::fpclassify; | |
| 323 | using ::isfinite; | |
| 324 | using ::isinf; | |
| 325 | using ::isnan; | |
| 326 | using ::isnormal; | |
| 327 | using ::isgreater; | |
| 328 | using ::isgreaterequal; | |
| 329 | using ::isless; | |
| 330 | using ::islessequal; | |
| 331 | using ::islessgreater; | |
| 332 | using ::isunordered; | |
| 333 | using ::isunordered; | |
| 334 | ||
| 335 | using ::float_t; | |
| 336 | using ::double_t; | |
| 337 | ||
| 338 | #ifndef _AIX | |
| 339 | using ::abs; | |
| 340 | #endif | |
| 341 | ||
| 342 | using ::acos; | |
| 343 | using ::acosf; | |
| 344 | using ::asin; | |
| 345 | using ::asinf; | |
| 346 | using ::atan; | |
| 347 | using ::atanf; | |
| 348 | using ::atan2; | |
| 349 | using ::atan2f; | |
| 350 | using ::ceil; | |
| 351 | using ::ceilf; | |
| 352 | using ::cos; | |
| 353 | using ::cosf; | |
| 354 | using ::cosh; | |
| 355 | using ::coshf; | |
| 356 | ||
| 357 | using ::exp; | |
| 358 | using ::expf; | |
| 359 | ||
| 360 | using ::fabs; | |
| 361 | using ::fabsf; | |
| 362 | using ::floor; | |
| 363 | using ::floorf; | |
| 364 | ||
| 365 | using ::fmod; | |
| 366 | using ::fmodf; | |
| 367 | ||
| 368 | using ::frexp; | |
| 369 | using ::frexpf; | |
| 370 | using ::ldexp; | |
| 371 | using ::ldexpf; | |
| 372 | ||
| 373 | using ::log; | |
| 374 | using ::logf; | |
| 375 | ||
| 376 | using ::log10; | |
| 377 | using ::log10f; | |
| 378 | using ::modf; | |
| 379 | using ::modff; | |
| 380 | ||
| 381 | using ::pow; | |
| 382 | using ::powf; | |
| 383 | ||
| 384 | using ::sin; | |
| 385 | using ::sinf; | |
| 386 | using ::sinh; | |
| 387 | using ::sinhf; | |
| 388 | ||
| 389 | using ::sqrt; | |
| 390 | using ::sqrtf; | |
| 391 | using ::tan; | |
| 392 | using ::tanf; | |
| 393 | ||
| 394 | using ::tanh; | |
| 395 | using ::tanhf; | |
| 396 | ||
| 397 | using ::acosh; | |
| 398 | using ::acoshf; | |
| 399 | using ::asinh; | |
| 400 | using ::asinhf; | |
| 401 | using ::atanh; | |
| 402 | using ::atanhf; | |
| 403 | using ::cbrt; | |
| 404 | using ::cbrtf; | |
| 405 | ||
| 406 | using ::copysign; | |
| 407 | using ::copysignf; | |
| 408 | ||
| 409 | using ::erf; | |
| 410 | using ::erff; | |
| 411 | using ::erfc; | |
| 412 | using ::erfcf; | |
| 413 | using ::exp2; | |
| 414 | using ::exp2f; | |
| 415 | using ::expm1; | |
| 416 | using ::expm1f; | |
| 417 | using ::fdim; | |
| 418 | using ::fdimf; | |
| 419 | using ::fmaf; | |
| 420 | using ::fma; | |
| 421 | using ::fmax; | |
| 422 | using ::fmaxf; | |
| 423 | using ::fmin; | |
| 424 | using ::fminf; | |
| 425 | using ::hypot; | |
| 426 | using ::hypotf; | |
| 427 | using ::ilogb; | |
| 428 | using ::ilogbf; | |
| 429 | using ::lgamma; | |
| 430 | using ::lgammaf; | |
| 431 | using ::llrint; | |
| 432 | using ::llrintf; | |
| 433 | using ::llround; | |
| 434 | using ::llroundf; | |
| 435 | using ::log1p; | |
| 436 | using ::log1pf; | |
| 437 | using ::log2; | |
| 438 | using ::log2f; | |
| 439 | using ::logb; | |
| 440 | using ::logbf; | |
| 441 | using ::lrint; | |
| 442 | using ::lrintf; | |
| 443 | using ::lround; | |
| 444 | using ::lroundf; | |
| 445 | ||
| 446 | using ::nan; | |
| 447 | using ::nanf; | |
| 448 | ||
| 449 | using ::nearbyint; | |
| 450 | using ::nearbyintf; | |
| 451 | using ::nextafter; | |
| 452 | using ::nextafterf; | |
| 453 | using ::nexttoward; | |
| 454 | using ::nexttowardf; | |
| 455 | using ::remainder; | |
| 456 | using ::remainderf; | |
| 457 | using ::remquo; | |
| 458 | using ::remquof; | |
| 459 | using ::rint; | |
| 460 | using ::rintf; | |
| 461 | using ::round; | |
| 462 | using ::roundf; | |
| 463 | using ::scalbln; | |
| 464 | using ::scalblnf; | |
| 465 | using ::scalbn; | |
| 466 | using ::scalbnf; | |
| 467 | using ::tgamma; | |
| 468 | using ::tgammaf; | |
| 469 | using ::trunc; | |
| 470 | using ::truncf; | |
| 471 | ||
| 472 | using ::acosl; | |
| 473 | using ::asinl; | |
| 474 | using ::atanl; | |
| 475 | using ::atan2l; | |
| 476 | using ::ceill; | |
| 477 | using ::cosl; | |
| 478 | using ::coshl; | |
| 479 | using ::expl; | |
| 480 | using ::fabsl; | |
| 481 | using ::floorl; | |
| 482 | using ::fmodl; | |
| 483 | using ::frexpl; | |
| 484 | using ::ldexpl; | |
| 485 | using ::logl; | |
| 486 | using ::log10l; | |
| 487 | using ::modfl; | |
| 488 | using ::powl; | |
| 489 | using ::sinl; | |
| 490 | using ::sinhl; | |
| 491 | using ::sqrtl; | |
| 492 | using ::tanl; | |
| 493 | ||
| 494 | using ::tanhl; | |
| 495 | using ::acoshl; | |
| 496 | using ::asinhl; | |
| 497 | using ::atanhl; | |
| 498 | using ::cbrtl; | |
| 499 | ||
| 500 | using ::copysignl; | |
| 501 | ||
| 502 | using ::erfl; | |
| 503 | using ::erfcl; | |
| 504 | using ::exp2l; | |
| 505 | using ::expm1l; | |
| 506 | using ::fdiml; | |
| 507 | using ::fmal; | |
| 508 | using ::fmaxl; | |
| 509 | using ::fminl; | |
| 510 | using ::hypotl; | |
| 511 | using ::ilogbl; | |
| 512 | using ::lgammal; | |
| 513 | using ::llrintl; | |
| 514 | using ::llroundl; | |
| 515 | using ::log1pl; | |
| 516 | using ::log2l; | |
| 517 | using ::logbl; | |
| 518 | using ::lrintl; | |
| 519 | using ::lroundl; | |
| 520 | using ::nanl; | |
| 521 | using ::nearbyintl; | |
| 522 | using ::nextafterl; | |
| 523 | using ::nexttowardl; | |
| 524 | using ::remainderl; | |
| 525 | using ::remquol; | |
| 526 | using ::rintl; | |
| 527 | using ::roundl; | |
| 528 | using ::scalblnl; | |
| 529 | using ::scalbnl; | |
| 530 | using ::tgammal; | |
| 531 | using ::truncl; | |
| 321 | using ::signbit _LIBCPP_USING_IF_EXISTS; | |
| 322 | using ::fpclassify _LIBCPP_USING_IF_EXISTS; | |
| 323 | using ::isfinite _LIBCPP_USING_IF_EXISTS; | |
| 324 | using ::isinf _LIBCPP_USING_IF_EXISTS; | |
| 325 | using ::isnan _LIBCPP_USING_IF_EXISTS; | |
| 326 | using ::isnormal _LIBCPP_USING_IF_EXISTS; | |
| 327 | using ::isgreater _LIBCPP_USING_IF_EXISTS; | |
| 328 | using ::isgreaterequal _LIBCPP_USING_IF_EXISTS; | |
| 329 | using ::isless _LIBCPP_USING_IF_EXISTS; | |
| 330 | using ::islessequal _LIBCPP_USING_IF_EXISTS; | |
| 331 | using ::islessgreater _LIBCPP_USING_IF_EXISTS; | |
| 332 | using ::isunordered _LIBCPP_USING_IF_EXISTS; | |
| 333 | using ::isunordered _LIBCPP_USING_IF_EXISTS; | |
| 334 | ||
| 335 | using ::float_t _LIBCPP_USING_IF_EXISTS; | |
| 336 | using ::double_t _LIBCPP_USING_IF_EXISTS; | |
| 337 | ||
| 338 | using ::abs _LIBCPP_USING_IF_EXISTS; | |
| 339 | ||
| 340 | using ::acos _LIBCPP_USING_IF_EXISTS; | |
| 341 | using ::acosf _LIBCPP_USING_IF_EXISTS; | |
| 342 | using ::asin _LIBCPP_USING_IF_EXISTS; | |
| 343 | using ::asinf _LIBCPP_USING_IF_EXISTS; | |
| 344 | using ::atan _LIBCPP_USING_IF_EXISTS; | |
| 345 | using ::atanf _LIBCPP_USING_IF_EXISTS; | |
| 346 | using ::atan2 _LIBCPP_USING_IF_EXISTS; | |
| 347 | using ::atan2f _LIBCPP_USING_IF_EXISTS; | |
| 348 | using ::ceil _LIBCPP_USING_IF_EXISTS; | |
| 349 | using ::ceilf _LIBCPP_USING_IF_EXISTS; | |
| 350 | using ::cos _LIBCPP_USING_IF_EXISTS; | |
| 351 | using ::cosf _LIBCPP_USING_IF_EXISTS; | |
| 352 | using ::cosh _LIBCPP_USING_IF_EXISTS; | |
| 353 | using ::coshf _LIBCPP_USING_IF_EXISTS; | |
| 354 | ||
| 355 | using ::exp _LIBCPP_USING_IF_EXISTS; | |
| 356 | using ::expf _LIBCPP_USING_IF_EXISTS; | |
| 357 | ||
| 358 | using ::fabs _LIBCPP_USING_IF_EXISTS; | |
| 359 | using ::fabsf _LIBCPP_USING_IF_EXISTS; | |
| 360 | using ::floor _LIBCPP_USING_IF_EXISTS; | |
| 361 | using ::floorf _LIBCPP_USING_IF_EXISTS; | |
| 362 | ||
| 363 | using ::fmod _LIBCPP_USING_IF_EXISTS; | |
| 364 | using ::fmodf _LIBCPP_USING_IF_EXISTS; | |
| 365 | ||
| 366 | using ::frexp _LIBCPP_USING_IF_EXISTS; | |
| 367 | using ::frexpf _LIBCPP_USING_IF_EXISTS; | |
| 368 | using ::ldexp _LIBCPP_USING_IF_EXISTS; | |
| 369 | using ::ldexpf _LIBCPP_USING_IF_EXISTS; | |
| 370 | ||
| 371 | using ::log _LIBCPP_USING_IF_EXISTS; | |
| 372 | using ::logf _LIBCPP_USING_IF_EXISTS; | |
| 373 | ||
| 374 | using ::log10 _LIBCPP_USING_IF_EXISTS; | |
| 375 | using ::log10f _LIBCPP_USING_IF_EXISTS; | |
| 376 | using ::modf _LIBCPP_USING_IF_EXISTS; | |
| 377 | using ::modff _LIBCPP_USING_IF_EXISTS; | |
| 378 | ||
| 379 | using ::pow _LIBCPP_USING_IF_EXISTS; | |
| 380 | using ::powf _LIBCPP_USING_IF_EXISTS; | |
| 381 | ||
| 382 | using ::sin _LIBCPP_USING_IF_EXISTS; | |
| 383 | using ::sinf _LIBCPP_USING_IF_EXISTS; | |
| 384 | using ::sinh _LIBCPP_USING_IF_EXISTS; | |
| 385 | using ::sinhf _LIBCPP_USING_IF_EXISTS; | |
| 386 | ||
| 387 | using ::sqrt _LIBCPP_USING_IF_EXISTS; | |
| 388 | using ::sqrtf _LIBCPP_USING_IF_EXISTS; | |
| 389 | using ::tan _LIBCPP_USING_IF_EXISTS; | |
| 390 | using ::tanf _LIBCPP_USING_IF_EXISTS; | |
| 391 | ||
| 392 | using ::tanh _LIBCPP_USING_IF_EXISTS; | |
| 393 | using ::tanhf _LIBCPP_USING_IF_EXISTS; | |
| 394 | ||
| 395 | using ::acosh _LIBCPP_USING_IF_EXISTS; | |
| 396 | using ::acoshf _LIBCPP_USING_IF_EXISTS; | |
| 397 | using ::asinh _LIBCPP_USING_IF_EXISTS; | |
| 398 | using ::asinhf _LIBCPP_USING_IF_EXISTS; | |
| 399 | using ::atanh _LIBCPP_USING_IF_EXISTS; | |
| 400 | using ::atanhf _LIBCPP_USING_IF_EXISTS; | |
| 401 | using ::cbrt _LIBCPP_USING_IF_EXISTS; | |
| 402 | using ::cbrtf _LIBCPP_USING_IF_EXISTS; | |
| 403 | ||
| 404 | using ::copysign _LIBCPP_USING_IF_EXISTS; | |
| 405 | using ::copysignf _LIBCPP_USING_IF_EXISTS; | |
| 406 | ||
| 407 | using ::erf _LIBCPP_USING_IF_EXISTS; | |
| 408 | using ::erff _LIBCPP_USING_IF_EXISTS; | |
| 409 | using ::erfc _LIBCPP_USING_IF_EXISTS; | |
| 410 | using ::erfcf _LIBCPP_USING_IF_EXISTS; | |
| 411 | using ::exp2 _LIBCPP_USING_IF_EXISTS; | |
| 412 | using ::exp2f _LIBCPP_USING_IF_EXISTS; | |
| 413 | using ::expm1 _LIBCPP_USING_IF_EXISTS; | |
| 414 | using ::expm1f _LIBCPP_USING_IF_EXISTS; | |
| 415 | using ::fdim _LIBCPP_USING_IF_EXISTS; | |
| 416 | using ::fdimf _LIBCPP_USING_IF_EXISTS; | |
| 417 | using ::fmaf _LIBCPP_USING_IF_EXISTS; | |
| 418 | using ::fma _LIBCPP_USING_IF_EXISTS; | |
| 419 | using ::fmax _LIBCPP_USING_IF_EXISTS; | |
| 420 | using ::fmaxf _LIBCPP_USING_IF_EXISTS; | |
| 421 | using ::fmin _LIBCPP_USING_IF_EXISTS; | |
| 422 | using ::fminf _LIBCPP_USING_IF_EXISTS; | |
| 423 | using ::hypot _LIBCPP_USING_IF_EXISTS; | |
| 424 | using ::hypotf _LIBCPP_USING_IF_EXISTS; | |
| 425 | using ::ilogb _LIBCPP_USING_IF_EXISTS; | |
| 426 | using ::ilogbf _LIBCPP_USING_IF_EXISTS; | |
| 427 | using ::lgamma _LIBCPP_USING_IF_EXISTS; | |
| 428 | using ::lgammaf _LIBCPP_USING_IF_EXISTS; | |
| 429 | using ::llrint _LIBCPP_USING_IF_EXISTS; | |
| 430 | using ::llrintf _LIBCPP_USING_IF_EXISTS; | |
| 431 | using ::llround _LIBCPP_USING_IF_EXISTS; | |
| 432 | using ::llroundf _LIBCPP_USING_IF_EXISTS; | |
| 433 | using ::log1p _LIBCPP_USING_IF_EXISTS; | |
| 434 | using ::log1pf _LIBCPP_USING_IF_EXISTS; | |
| 435 | using ::log2 _LIBCPP_USING_IF_EXISTS; | |
| 436 | using ::log2f _LIBCPP_USING_IF_EXISTS; | |
| 437 | using ::logb _LIBCPP_USING_IF_EXISTS; | |
| 438 | using ::logbf _LIBCPP_USING_IF_EXISTS; | |
| 439 | using ::lrint _LIBCPP_USING_IF_EXISTS; | |
| 440 | using ::lrintf _LIBCPP_USING_IF_EXISTS; | |
| 441 | using ::lround _LIBCPP_USING_IF_EXISTS; | |
| 442 | using ::lroundf _LIBCPP_USING_IF_EXISTS; | |
| 443 | ||
| 444 | using ::nan _LIBCPP_USING_IF_EXISTS; | |
| 445 | using ::nanf _LIBCPP_USING_IF_EXISTS; | |
| 446 | ||
| 447 | using ::nearbyint _LIBCPP_USING_IF_EXISTS; | |
| 448 | using ::nearbyintf _LIBCPP_USING_IF_EXISTS; | |
| 449 | using ::nextafter _LIBCPP_USING_IF_EXISTS; | |
| 450 | using ::nextafterf _LIBCPP_USING_IF_EXISTS; | |
| 451 | using ::nexttoward _LIBCPP_USING_IF_EXISTS; | |
| 452 | using ::nexttowardf _LIBCPP_USING_IF_EXISTS; | |
| 453 | using ::remainder _LIBCPP_USING_IF_EXISTS; | |
| 454 | using ::remainderf _LIBCPP_USING_IF_EXISTS; | |
| 455 | using ::remquo _LIBCPP_USING_IF_EXISTS; | |
| 456 | using ::remquof _LIBCPP_USING_IF_EXISTS; | |
| 457 | using ::rint _LIBCPP_USING_IF_EXISTS; | |
| 458 | using ::rintf _LIBCPP_USING_IF_EXISTS; | |
| 459 | using ::round _LIBCPP_USING_IF_EXISTS; | |
| 460 | using ::roundf _LIBCPP_USING_IF_EXISTS; | |
| 461 | using ::scalbln _LIBCPP_USING_IF_EXISTS; | |
| 462 | using ::scalblnf _LIBCPP_USING_IF_EXISTS; | |
| 463 | using ::scalbn _LIBCPP_USING_IF_EXISTS; | |
| 464 | using ::scalbnf _LIBCPP_USING_IF_EXISTS; | |
| 465 | using ::tgamma _LIBCPP_USING_IF_EXISTS; | |
| 466 | using ::tgammaf _LIBCPP_USING_IF_EXISTS; | |
| 467 | using ::trunc _LIBCPP_USING_IF_EXISTS; | |
| 468 | using ::truncf _LIBCPP_USING_IF_EXISTS; | |
| 469 | ||
| 470 | using ::acosl _LIBCPP_USING_IF_EXISTS; | |
| 471 | using ::asinl _LIBCPP_USING_IF_EXISTS; | |
| 472 | using ::atanl _LIBCPP_USING_IF_EXISTS; | |
| 473 | using ::atan2l _LIBCPP_USING_IF_EXISTS; | |
| 474 | using ::ceill _LIBCPP_USING_IF_EXISTS; | |
| 475 | using ::cosl _LIBCPP_USING_IF_EXISTS; | |
| 476 | using ::coshl _LIBCPP_USING_IF_EXISTS; | |
| 477 | using ::expl _LIBCPP_USING_IF_EXISTS; | |
| 478 | using ::fabsl _LIBCPP_USING_IF_EXISTS; | |
| 479 | using ::floorl _LIBCPP_USING_IF_EXISTS; | |
| 480 | using ::fmodl _LIBCPP_USING_IF_EXISTS; | |
| 481 | using ::frexpl _LIBCPP_USING_IF_EXISTS; | |
| 482 | using ::ldexpl _LIBCPP_USING_IF_EXISTS; | |
| 483 | using ::logl _LIBCPP_USING_IF_EXISTS; | |
| 484 | using ::log10l _LIBCPP_USING_IF_EXISTS; | |
| 485 | using ::modfl _LIBCPP_USING_IF_EXISTS; | |
| 486 | using ::powl _LIBCPP_USING_IF_EXISTS; | |
| 487 | using ::sinl _LIBCPP_USING_IF_EXISTS; | |
| 488 | using ::sinhl _LIBCPP_USING_IF_EXISTS; | |
| 489 | using ::sqrtl _LIBCPP_USING_IF_EXISTS; | |
| 490 | using ::tanl _LIBCPP_USING_IF_EXISTS; | |
| 491 | ||
| 492 | using ::tanhl _LIBCPP_USING_IF_EXISTS; | |
| 493 | using ::acoshl _LIBCPP_USING_IF_EXISTS; | |
| 494 | using ::asinhl _LIBCPP_USING_IF_EXISTS; | |
| 495 | using ::atanhl _LIBCPP_USING_IF_EXISTS; | |
| 496 | using ::cbrtl _LIBCPP_USING_IF_EXISTS; | |
| 497 | ||
| 498 | using ::copysignl _LIBCPP_USING_IF_EXISTS; | |
| 499 | ||
| 500 | using ::erfl _LIBCPP_USING_IF_EXISTS; | |
| 501 | using ::erfcl _LIBCPP_USING_IF_EXISTS; | |
| 502 | using ::exp2l _LIBCPP_USING_IF_EXISTS; | |
| 503 | using ::expm1l _LIBCPP_USING_IF_EXISTS; | |
| 504 | using ::fdiml _LIBCPP_USING_IF_EXISTS; | |
| 505 | using ::fmal _LIBCPP_USING_IF_EXISTS; | |
| 506 | using ::fmaxl _LIBCPP_USING_IF_EXISTS; | |
| 507 | using ::fminl _LIBCPP_USING_IF_EXISTS; | |
| 508 | using ::hypotl _LIBCPP_USING_IF_EXISTS; | |
| 509 | using ::ilogbl _LIBCPP_USING_IF_EXISTS; | |
| 510 | using ::lgammal _LIBCPP_USING_IF_EXISTS; | |
| 511 | using ::llrintl _LIBCPP_USING_IF_EXISTS; | |
| 512 | using ::llroundl _LIBCPP_USING_IF_EXISTS; | |
| 513 | using ::log1pl _LIBCPP_USING_IF_EXISTS; | |
| 514 | using ::log2l _LIBCPP_USING_IF_EXISTS; | |
| 515 | using ::logbl _LIBCPP_USING_IF_EXISTS; | |
| 516 | using ::lrintl _LIBCPP_USING_IF_EXISTS; | |
| 517 | using ::lroundl _LIBCPP_USING_IF_EXISTS; | |
| 518 | using ::nanl _LIBCPP_USING_IF_EXISTS; | |
| 519 | using ::nearbyintl _LIBCPP_USING_IF_EXISTS; | |
| 520 | using ::nextafterl _LIBCPP_USING_IF_EXISTS; | |
| 521 | using ::nexttowardl _LIBCPP_USING_IF_EXISTS; | |
| 522 | using ::remainderl _LIBCPP_USING_IF_EXISTS; | |
| 523 | using ::remquol _LIBCPP_USING_IF_EXISTS; | |
| 524 | using ::rintl _LIBCPP_USING_IF_EXISTS; | |
| 525 | using ::roundl _LIBCPP_USING_IF_EXISTS; | |
| 526 | using ::scalblnl _LIBCPP_USING_IF_EXISTS; | |
| 527 | using ::scalbnl _LIBCPP_USING_IF_EXISTS; | |
| 528 | using ::tgammal _LIBCPP_USING_IF_EXISTS; | |
| 529 | using ::truncl _LIBCPP_USING_IF_EXISTS; | |
| 532 | 530 | |
| 533 | 531 | #if _LIBCPP_STD_VER > 14 |
| 534 | 532 | inline _LIBCPP_INLINE_VISIBILITY float hypot( float x, float y, float z ) { return sqrt(x*x + y*y + z*z); } |
| ... | ... | @@ -623,10 +621,10 @@ _Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept { |
| 623 | 621 | |
| 624 | 622 | if (__t == 1) return __b; |
| 625 | 623 | const _Fp __x = __a + __t * (__b - __a); |
| 626 | if (__t > 1 == __b > __a) | |
| 627 | 	return __b < __x ? __x : __b; | |
| 624 | if ((__t > 1) == (__b > __a)) | |
| 625 | return __b < __x ? __x : __b; | |
| 628 | 626 | else |
| 629 | 	return __x < __b ? __x : __b; | |
| 627 | return __x < __b ? __x : __b; | |
| 630 | 628 | } |
| 631 | 629 | |
| 632 | 630 | constexpr float |
| ... | ... | @@ -674,4 +672,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 674 | 672 | |
| 675 | 673 | _LIBCPP_POP_MACROS |
| 676 | 674 | |
| 677 | #endif // _LIBCPP_CMATH | |
| 675 | #endif // _LIBCPP_CMATH |
lib/libcxx/include/codecvt+1-1| ... | ... | @@ -570,4 +570,4 @@ public: |
| 570 | 570 | |
| 571 | 571 | _LIBCPP_END_NAMESPACE_STD |
| 572 | 572 | |
| 573 | #endif // _LIBCPP_CODECVT | |
| 573 | #endif // _LIBCPP_CODECVT |
lib/libcxx/include/compare+146-424| ... | ... | @@ -15,15 +15,13 @@ |
| 15 | 15 | |
| 16 | 16 | namespace std { |
| 17 | 17 | // [cmp.categories], comparison category types |
| 18 | class weak_equality; | |
| 19 | class strong_equality; | |
| 20 | 18 | class partial_ordering; |
| 21 | 19 | class weak_ordering; |
| 22 | 20 | class strong_ordering; |
| 23 | 21 | |
| 24 | 22 | // named comparison functions |
| 25 | constexpr bool is_eq (weak_equality cmp) noexcept { return cmp == 0; } | |
| 26 | constexpr bool is_neq (weak_equality cmp) noexcept { return cmp != 0; } | |
| 23 | constexpr bool is_eq (partial_ordering cmp) noexcept { return cmp == 0; } | |
| 24 | constexpr bool is_neq (partial_ordering cmp) noexcept { return cmp != 0; } | |
| 27 | 25 | constexpr bool is_lt (partial_ordering cmp) noexcept { return cmp < 0; } |
| 28 | 26 | constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; } |
| 29 | 27 | constexpr bool is_gt (partial_ordering cmp) noexcept { return cmp > 0; } |
| ... | ... | @@ -41,8 +39,6 @@ namespace std { |
| 41 | 39 | template<class T> constexpr strong_ordering strong_order(const T& a, const T& b); |
| 42 | 40 | template<class T> constexpr weak_ordering weak_order(const T& a, const T& b); |
| 43 | 41 | template<class T> constexpr partial_ordering partial_order(const T& a, const T& b); |
| 44 | template<class T> constexpr strong_equality strong_equal(const T& a, const T& b); | |
| 45 | template<class T> constexpr weak_equality weak_equal(const T& a, const T& b); | |
| 46 | 42 | |
| 47 | 43 | // [cmp.partialord], Class partial_ordering |
| 48 | 44 | class partial_ordering { |
| ... | ... | @@ -126,7 +122,6 @@ namespace std { |
| 126 | 122 | |
| 127 | 123 | #include <__config> |
| 128 | 124 | #include <type_traits> |
| 129 | #include <array> | |
| 130 | 125 | |
| 131 | 126 | #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER |
| 132 | 127 | #pragma GCC system_header |
| ... | ... | @@ -134,8 +129,7 @@ namespace std { |
| 134 | 129 | |
| 135 | 130 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 136 | 131 | |
| 137 | #if _LIBCPP_STD_VER > 17 | |
| 138 | ||
| 132 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) | |
| 139 | 133 | // exposition only |
| 140 | 134 | enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char { |
| 141 | 135 | __zero = 0, |
| ... | ... | @@ -154,138 +148,21 @@ enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { |
| 154 | 148 | __unordered = -127 |
| 155 | 149 | }; |
| 156 | 150 | |
| 151 | class partial_ordering; | |
| 152 | class weak_ordering; | |
| 153 | class strong_ordering; | |
| 154 | ||
| 155 | template<class _Tp, class... _Args> | |
| 156 | inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); | |
| 157 | ||
| 157 | 158 | struct _CmpUnspecifiedParam { |
| 158 | 159 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEVAL |
| 159 | 160 | _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} |
| 160 | 161 | |
| 161 | template<typename _Tp, typename = _VSTD::enable_if_t<!_VSTD::is_same_v<_Tp, int>>> | |
| 162 | template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>> | |
| 162 | 163 | _CmpUnspecifiedParam(_Tp) = delete; |
| 163 | 164 | }; |
| 164 | 165 | |
| 165 | class weak_equality { | |
| 166 | _LIBCPP_INLINE_VISIBILITY | |
| 167 | constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {} | |
| 168 | ||
| 169 | public: | |
| 170 | static const weak_equality equivalent; | |
| 171 | static const weak_equality nonequivalent; | |
| 172 | ||
| 173 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept; | |
| 174 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept; | |
| 175 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept; | |
| 176 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept; | |
| 177 | ||
| 178 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 179 | _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept; | |
| 180 | _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept; | |
| 181 | #endif | |
| 182 | ||
| 183 | private: | |
| 184 | _EqResult __value_; | |
| 185 | }; | |
| 186 | ||
| 187 | _LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv); | |
| 188 | _LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv); | |
| 189 | ||
| 190 | _LIBCPP_INLINE_VISIBILITY | |
| 191 | inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept { | |
| 192 | return __v.__value_ == _EqResult::__zero; | |
| 193 | } | |
| 194 | ||
| 195 | _LIBCPP_INLINE_VISIBILITY | |
| 196 | inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept { | |
| 197 | return __v.__value_ == _EqResult::__zero; | |
| 198 | } | |
| 199 | ||
| 200 | _LIBCPP_INLINE_VISIBILITY | |
| 201 | inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept { | |
| 202 | return __v.__value_ != _EqResult::__zero; | |
| 203 | } | |
| 204 | ||
| 205 | _LIBCPP_INLINE_VISIBILITY | |
| 206 | inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept { | |
| 207 | return __v.__value_ != _EqResult::__zero; | |
| 208 | } | |
| 209 | ||
| 210 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 211 | _LIBCPP_INLINE_VISIBILITY | |
| 212 | inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept { | |
| 213 | return __v; | |
| 214 | } | |
| 215 | ||
| 216 | _LIBCPP_INLINE_VISIBILITY | |
| 217 | inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept { | |
| 218 | return __v; | |
| 219 | } | |
| 220 | #endif | |
| 221 | ||
| 222 | class strong_equality { | |
| 223 | _LIBCPP_INLINE_VISIBILITY | |
| 224 | explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {} | |
| 225 | ||
| 226 | public: | |
| 227 | static const strong_equality equal; | |
| 228 | static const strong_equality nonequal; | |
| 229 | static const strong_equality equivalent; | |
| 230 | static const strong_equality nonequivalent; | |
| 231 | ||
| 232 | // conversion | |
| 233 | _LIBCPP_INLINE_VISIBILITY constexpr operator weak_equality() const noexcept { | |
| 234 | return __value_ == _EqResult::__zero ? weak_equality::equivalent | |
| 235 | : weak_equality::nonequivalent; | |
| 236 | } | |
| 237 | ||
| 238 | // comparisons | |
| 239 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept; | |
| 240 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept; | |
| 241 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept; | |
| 242 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept; | |
| 243 | ||
| 244 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 245 | _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept; | |
| 246 | _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept; | |
| 247 | #endif | |
| 248 | private: | |
| 249 | _EqResult __value_; | |
| 250 | }; | |
| 251 | ||
| 252 | _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equal(_EqResult::__equal); | |
| 253 | _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal); | |
| 254 | _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv); | |
| 255 | _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv); | |
| 256 | ||
| 257 | _LIBCPP_INLINE_VISIBILITY | |
| 258 | constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept { | |
| 259 | return __v.__value_ == _EqResult::__zero; | |
| 260 | } | |
| 261 | ||
| 262 | _LIBCPP_INLINE_VISIBILITY | |
| 263 | constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept { | |
| 264 | return __v.__value_ == _EqResult::__zero; | |
| 265 | } | |
| 266 | ||
| 267 | _LIBCPP_INLINE_VISIBILITY | |
| 268 | constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept { | |
| 269 | return __v.__value_ != _EqResult::__zero; | |
| 270 | } | |
| 271 | ||
| 272 | _LIBCPP_INLINE_VISIBILITY | |
| 273 | constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept { | |
| 274 | return __v.__value_ != _EqResult::__zero; | |
| 275 | } | |
| 276 | ||
| 277 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 278 | _LIBCPP_INLINE_VISIBILITY | |
| 279 | constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept { | |
| 280 | return __v; | |
| 281 | } | |
| 282 | ||
| 283 | _LIBCPP_INLINE_VISIBILITY | |
| 284 | constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept { | |
| 285 | return __v; | |
| 286 | } | |
| 287 | #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 288 | ||
| 289 | 166 | class partial_ordering { |
| 290 | 167 | using _ValueT = signed char; |
| 291 | 168 | |
| ... | ... | @@ -311,32 +188,52 @@ public: |
| 311 | 188 | static const partial_ordering greater; |
| 312 | 189 | static const partial_ordering unordered; |
| 313 | 190 | |
| 314 | // conversion | |
| 315 | constexpr operator weak_equality() const noexcept { | |
| 316 | return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent; | |
| 317 | } | |
| 318 | ||
| 319 | 191 | // comparisons |
| 320 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 321 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 322 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 323 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 324 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 325 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 326 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept; | |
| 327 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; | |
| 328 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept; | |
| 329 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; | |
| 330 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept; | |
| 331 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; | |
| 332 | ||
| 333 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 334 | 192 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; |
| 335 | 193 | |
| 336 | _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 337 | _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept; | |
| 338 | #endif | |
| 194 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 195 | return __v.__is_ordered() && __v.__value_ == 0; | |
| 196 | } | |
| 197 | ||
| 198 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 199 | return __v.__is_ordered() && __v.__value_ < 0; | |
| 200 | } | |
| 201 | ||
| 202 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 203 | return __v.__is_ordered() && __v.__value_ <= 0; | |
| 204 | } | |
| 205 | ||
| 206 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 207 | return __v.__is_ordered() && __v.__value_ > 0; | |
| 208 | } | |
| 209 | ||
| 210 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 211 | return __v.__is_ordered() && __v.__value_ >= 0; | |
| 212 | } | |
| 339 | 213 | |
| 214 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 215 | return __v.__is_ordered() && 0 < __v.__value_; | |
| 216 | } | |
| 217 | ||
| 218 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 219 | return __v.__is_ordered() && 0 <= __v.__value_; | |
| 220 | } | |
| 221 | ||
| 222 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 223 | return __v.__is_ordered() && 0 > __v.__value_; | |
| 224 | } | |
| 225 | ||
| 226 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 227 | return __v.__is_ordered() && 0 >= __v.__value_; | |
| 228 | } | |
| 229 | ||
| 230 | _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 231 | return __v; | |
| 232 | } | |
| 233 | ||
| 234 | _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 235 | return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); | |
| 236 | } | |
| 340 | 237 | private: |
| 341 | 238 | _ValueT __value_; |
| 342 | 239 | }; |
| ... | ... | @@ -346,68 +243,6 @@ _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqRe |
| 346 | 243 | _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); |
| 347 | 244 | _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); |
| 348 | 245 | |
| 349 | _LIBCPP_INLINE_VISIBILITY | |
| 350 | constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 351 | return __v.__is_ordered() && __v.__value_ == 0; | |
| 352 | } | |
| 353 | _LIBCPP_INLINE_VISIBILITY | |
| 354 | constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 355 | return __v.__is_ordered() && __v.__value_ < 0; | |
| 356 | } | |
| 357 | _LIBCPP_INLINE_VISIBILITY | |
| 358 | constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 359 | return __v.__is_ordered() && __v.__value_ <= 0; | |
| 360 | } | |
| 361 | _LIBCPP_INLINE_VISIBILITY | |
| 362 | constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 363 | return __v.__is_ordered() && __v.__value_ > 0; | |
| 364 | } | |
| 365 | _LIBCPP_INLINE_VISIBILITY | |
| 366 | constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 367 | return __v.__is_ordered() && __v.__value_ >= 0; | |
| 368 | } | |
| 369 | ||
| 370 | _LIBCPP_INLINE_VISIBILITY | |
| 371 | constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 372 | return __v.__is_ordered() && 0 == __v.__value_; | |
| 373 | } | |
| 374 | _LIBCPP_INLINE_VISIBILITY | |
| 375 | constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 376 | return __v.__is_ordered() && 0 < __v.__value_; | |
| 377 | } | |
| 378 | _LIBCPP_INLINE_VISIBILITY | |
| 379 | constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 380 | return __v.__is_ordered() && 0 <= __v.__value_; | |
| 381 | } | |
| 382 | _LIBCPP_INLINE_VISIBILITY | |
| 383 | constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 384 | return __v.__is_ordered() && 0 > __v.__value_; | |
| 385 | } | |
| 386 | _LIBCPP_INLINE_VISIBILITY | |
| 387 | constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 388 | return __v.__is_ordered() && 0 >= __v.__value_; | |
| 389 | } | |
| 390 | ||
| 391 | _LIBCPP_INLINE_VISIBILITY | |
| 392 | constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 393 | return !__v.__is_ordered() || __v.__value_ != 0; | |
| 394 | } | |
| 395 | _LIBCPP_INLINE_VISIBILITY | |
| 396 | constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 397 | return !__v.__is_ordered() || __v.__value_ != 0; | |
| 398 | } | |
| 399 | ||
| 400 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 401 | _LIBCPP_INLINE_VISIBILITY | |
| 402 | constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 403 | return __v; | |
| 404 | } | |
| 405 | _LIBCPP_INLINE_VISIBILITY | |
| 406 | constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { | |
| 407 | return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); | |
| 408 | } | |
| 409 | #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 410 | ||
| 411 | 246 | class weak_ordering { |
| 412 | 247 | using _ValueT = signed char; |
| 413 | 248 | |
| ... | ... | @@ -421,13 +256,6 @@ public: |
| 421 | 256 | static const weak_ordering equivalent; |
| 422 | 257 | static const weak_ordering greater; |
| 423 | 258 | |
| 424 | // conversions | |
| 425 | _LIBCPP_INLINE_VISIBILITY | |
| 426 | constexpr operator weak_equality() const noexcept { | |
| 427 | return __value_ == 0 ? weak_equality::equivalent | |
| 428 | : weak_equality::nonequivalent; | |
| 429 | } | |
| 430 | ||
| 431 | 259 | _LIBCPP_INLINE_VISIBILITY |
| 432 | 260 | constexpr operator partial_ordering() const noexcept { |
| 433 | 261 | return __value_ == 0 ? partial_ordering::equivalent |
| ... | ... | @@ -435,25 +263,51 @@ public: |
| 435 | 263 | } |
| 436 | 264 | |
| 437 | 265 | // comparisons |
| 438 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 439 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 440 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 441 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 442 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 443 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 444 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept; | |
| 445 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; | |
| 446 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept; | |
| 447 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; | |
| 448 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept; | |
| 449 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; | |
| 450 | ||
| 451 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 452 | 266 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; |
| 453 | 267 | |
| 454 | _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 455 | _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept; | |
| 456 | #endif | |
| 268 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 269 | return __v.__value_ == 0; | |
| 270 | } | |
| 271 | ||
| 272 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 273 | return __v.__value_ < 0; | |
| 274 | } | |
| 275 | ||
| 276 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 277 | return __v.__value_ <= 0; | |
| 278 | } | |
| 279 | ||
| 280 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 281 | return __v.__value_ > 0; | |
| 282 | } | |
| 283 | ||
| 284 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 285 | return __v.__value_ >= 0; | |
| 286 | } | |
| 287 | ||
| 288 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 289 | return 0 < __v.__value_; | |
| 290 | } | |
| 291 | ||
| 292 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 293 | return 0 <= __v.__value_; | |
| 294 | } | |
| 295 | ||
| 296 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 297 | return 0 > __v.__value_; | |
| 298 | } | |
| 299 | ||
| 300 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 301 | return 0 >= __v.__value_; | |
| 302 | } | |
| 303 | ||
| 304 | _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 305 | return __v; | |
| 306 | } | |
| 307 | ||
| 308 | _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 309 | return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); | |
| 310 | } | |
| 457 | 311 | |
| 458 | 312 | private: |
| 459 | 313 | _ValueT __value_; |
| ... | ... | @@ -462,67 +316,6 @@ private: |
| 462 | 316 | _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less); |
| 463 | 317 | _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv); |
| 464 | 318 | _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); |
| 465 | ||
| 466 | _LIBCPP_INLINE_VISIBILITY | |
| 467 | constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 468 | return __v.__value_ == 0; | |
| 469 | } | |
| 470 | _LIBCPP_INLINE_VISIBILITY | |
| 471 | constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 472 | return __v.__value_ != 0; | |
| 473 | } | |
| 474 | _LIBCPP_INLINE_VISIBILITY | |
| 475 | constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 476 | return __v.__value_ < 0; | |
| 477 | } | |
| 478 | _LIBCPP_INLINE_VISIBILITY | |
| 479 | constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 480 | return __v.__value_ <= 0; | |
| 481 | } | |
| 482 | _LIBCPP_INLINE_VISIBILITY | |
| 483 | constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 484 | return __v.__value_ > 0; | |
| 485 | } | |
| 486 | _LIBCPP_INLINE_VISIBILITY | |
| 487 | constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 488 | return __v.__value_ >= 0; | |
| 489 | } | |
| 490 | _LIBCPP_INLINE_VISIBILITY | |
| 491 | constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 492 | return 0 == __v.__value_; | |
| 493 | } | |
| 494 | _LIBCPP_INLINE_VISIBILITY | |
| 495 | constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 496 | return 0 != __v.__value_; | |
| 497 | } | |
| 498 | _LIBCPP_INLINE_VISIBILITY | |
| 499 | constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 500 | return 0 < __v.__value_; | |
| 501 | } | |
| 502 | _LIBCPP_INLINE_VISIBILITY | |
| 503 | constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 504 | return 0 <= __v.__value_; | |
| 505 | } | |
| 506 | _LIBCPP_INLINE_VISIBILITY | |
| 507 | constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 508 | return 0 > __v.__value_; | |
| 509 | } | |
| 510 | _LIBCPP_INLINE_VISIBILITY | |
| 511 | constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 512 | return 0 >= __v.__value_; | |
| 513 | } | |
| 514 | ||
| 515 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 516 | _LIBCPP_INLINE_VISIBILITY | |
| 517 | constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 518 | return __v; | |
| 519 | } | |
| 520 | _LIBCPP_INLINE_VISIBILITY | |
| 521 | constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { | |
| 522 | return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); | |
| 523 | } | |
| 524 | #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 525 | ||
| 526 | 319 | class strong_ordering { |
| 527 | 320 | using _ValueT = signed char; |
| 528 | 321 | |
| ... | ... | @@ -538,18 +331,6 @@ public: |
| 538 | 331 | static const strong_ordering greater; |
| 539 | 332 | |
| 540 | 333 | // conversions |
| 541 | _LIBCPP_INLINE_VISIBILITY | |
| 542 | constexpr operator weak_equality() const noexcept { | |
| 543 | return __value_ == 0 ? weak_equality::equivalent | |
| 544 | : weak_equality::nonequivalent; | |
| 545 | } | |
| 546 | ||
| 547 | _LIBCPP_INLINE_VISIBILITY | |
| 548 | constexpr operator strong_equality() const noexcept { | |
| 549 | return __value_ == 0 ? strong_equality::equal | |
| 550 | : strong_equality::nonequal; | |
| 551 | } | |
| 552 | ||
| 553 | 334 | _LIBCPP_INLINE_VISIBILITY |
| 554 | 335 | constexpr operator partial_ordering() const noexcept { |
| 555 | 336 | return __value_ == 0 ? partial_ordering::equivalent |
| ... | ... | @@ -563,25 +344,51 @@ public: |
| 563 | 344 | } |
| 564 | 345 | |
| 565 | 346 | // comparisons |
| 566 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 567 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 568 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 569 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 570 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 571 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 572 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept; | |
| 573 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; | |
| 574 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept; | |
| 575 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; | |
| 576 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept; | |
| 577 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; | |
| 578 | ||
| 579 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 580 | 347 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; |
| 581 | 348 | |
| 582 | _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept; | |
| 583 | _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept; | |
| 584 | #endif | |
| 349 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 350 | return __v.__value_ == 0; | |
| 351 | } | |
| 352 | ||
| 353 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 354 | return __v.__value_ < 0; | |
| 355 | } | |
| 356 | ||
| 357 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 358 | return __v.__value_ <= 0; | |
| 359 | } | |
| 360 | ||
| 361 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 362 | return __v.__value_ > 0; | |
| 363 | } | |
| 364 | ||
| 365 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 366 | return __v.__value_ >= 0; | |
| 367 | } | |
| 368 | ||
| 369 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 370 | return 0 < __v.__value_; | |
| 371 | } | |
| 372 | ||
| 373 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 374 | return 0 <= __v.__value_; | |
| 375 | } | |
| 376 | ||
| 377 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 378 | return 0 > __v.__value_; | |
| 379 | } | |
| 380 | ||
| 381 | _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 382 | return 0 >= __v.__value_; | |
| 383 | } | |
| 384 | ||
| 385 | _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 386 | return __v; | |
| 387 | } | |
| 388 | ||
| 389 | _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 390 | return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); | |
| 391 | } | |
| 585 | 392 | |
| 586 | 393 | private: |
| 587 | 394 | _ValueT __value_; |
| ... | ... | @@ -592,73 +399,7 @@ _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::_ |
| 592 | 399 | _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv); |
| 593 | 400 | _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); |
| 594 | 401 | |
| 595 | _LIBCPP_INLINE_VISIBILITY | |
| 596 | constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 597 | return __v.__value_ == 0; | |
| 598 | } | |
| 599 | _LIBCPP_INLINE_VISIBILITY | |
| 600 | constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 601 | return __v.__value_ != 0; | |
| 602 | } | |
| 603 | _LIBCPP_INLINE_VISIBILITY | |
| 604 | constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 605 | return __v.__value_ < 0; | |
| 606 | } | |
| 607 | _LIBCPP_INLINE_VISIBILITY | |
| 608 | constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 609 | return __v.__value_ <= 0; | |
| 610 | } | |
| 611 | _LIBCPP_INLINE_VISIBILITY | |
| 612 | constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 613 | return __v.__value_ > 0; | |
| 614 | } | |
| 615 | _LIBCPP_INLINE_VISIBILITY | |
| 616 | constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 617 | return __v.__value_ >= 0; | |
| 618 | } | |
| 619 | _LIBCPP_INLINE_VISIBILITY | |
| 620 | constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 621 | return 0 == __v.__value_; | |
| 622 | } | |
| 623 | _LIBCPP_INLINE_VISIBILITY | |
| 624 | constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 625 | return 0 != __v.__value_; | |
| 626 | } | |
| 627 | _LIBCPP_INLINE_VISIBILITY | |
| 628 | constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 629 | return 0 < __v.__value_; | |
| 630 | } | |
| 631 | _LIBCPP_INLINE_VISIBILITY | |
| 632 | constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 633 | return 0 <= __v.__value_; | |
| 634 | } | |
| 635 | _LIBCPP_INLINE_VISIBILITY | |
| 636 | constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 637 | return 0 > __v.__value_; | |
| 638 | } | |
| 639 | _LIBCPP_INLINE_VISIBILITY | |
| 640 | constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 641 | return 0 >= __v.__value_; | |
| 642 | } | |
| 643 | ||
| 644 | #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 645 | _LIBCPP_INLINE_VISIBILITY | |
| 646 | constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { | |
| 647 | return __v; | |
| 648 | } | |
| 649 | _LIBCPP_INLINE_VISIBILITY | |
| 650 | constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { | |
| 651 | return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); | |
| 652 | } | |
| 653 | #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR | |
| 654 | ||
| 655 | 402 | // named comparison functions |
| 656 | _LIBCPP_INLINE_VISIBILITY | |
| 657 | constexpr bool is_eq(weak_equality __cmp) noexcept { return __cmp == 0; } | |
| 658 | ||
| 659 | _LIBCPP_INLINE_VISIBILITY | |
| 660 | constexpr bool is_neq(weak_equality __cmp) noexcept { return __cmp != 0; } | |
| 661 | ||
| 662 | 403 | _LIBCPP_INLINE_VISIBILITY |
| 663 | 404 | constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; } |
| 664 | 405 | |
| ... | ... | @@ -675,8 +416,6 @@ namespace __comp_detail { |
| 675 | 416 | |
| 676 | 417 | enum _ClassifyCompCategory : unsigned{ |
| 677 | 418 | _None, |
| 678 | _WeakEq, | |
| 679 | _StrongEq, | |
| 680 | 419 | _PartialOrd, |
| 681 | 420 | _WeakOrd, |
| 682 | 421 | _StrongOrd, |
| ... | ... | @@ -686,10 +425,6 @@ enum _ClassifyCompCategory : unsigned{ |
| 686 | 425 | template <class _Tp> |
| 687 | 426 | _LIBCPP_INLINE_VISIBILITY |
| 688 | 427 | constexpr _ClassifyCompCategory __type_to_enum() noexcept { |
| 689 | if (is_same_v<_Tp, weak_equality>) | |
| 690 | return _WeakEq; | |
| 691 | if (is_same_v<_Tp, strong_equality>) | |
| 692 | return _StrongEq; | |
| 693 | 428 | if (is_same_v<_Tp, partial_ordering>) |
| 694 | 429 | return _PartialOrd; |
| 695 | 430 | if (is_same_v<_Tp, weak_ordering>) |
| ... | ... | @@ -701,18 +436,12 @@ constexpr _ClassifyCompCategory __type_to_enum() noexcept { |
| 701 | 436 | |
| 702 | 437 | template <size_t _Size> |
| 703 | 438 | constexpr _ClassifyCompCategory |
| 704 | __compute_comp_type(array<_ClassifyCompCategory, _Size> __types) { | |
| 705 | array<int, _CCC_Size> __seen = {}; | |
| 439 | __compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { | |
| 440 | int __seen[_CCC_Size] = {}; | |
| 706 | 441 | for (auto __type : __types) |
| 707 | 442 | ++__seen[__type]; |
| 708 | 443 | if (__seen[_None]) |
| 709 | 444 | return _None; |
| 710 | if (__seen[_WeakEq]) | |
| 711 | return _WeakEq; | |
| 712 | if (__seen[_StrongEq] && (__seen[_PartialOrd] || __seen[_WeakOrd])) | |
| 713 | return _WeakEq; | |
| 714 | if (__seen[_StrongEq]) | |
| 715 | return _StrongEq; | |
| 716 | 445 | if (__seen[_PartialOrd]) |
| 717 | 446 | return _PartialOrd; |
| 718 | 447 | if (__seen[_WeakOrd]) |
| ... | ... | @@ -720,18 +449,13 @@ __compute_comp_type(array<_ClassifyCompCategory, _Size> __types) { |
| 720 | 449 | return _StrongOrd; |
| 721 | 450 | } |
| 722 | 451 | |
| 723 | template <class ..._Ts> | |
| 452 | template <class ..._Ts, bool _False = false> | |
| 724 | 453 | constexpr auto __get_comp_type() { |
| 725 | 454 | using _CCC = _ClassifyCompCategory; |
| 726 | constexpr array<_CCC, sizeof...(_Ts)> __type_kinds{{__comp_detail::__type_to_enum<_Ts>()...}}; | |
| 727 | constexpr _CCC _Cat = sizeof...(_Ts) == 0 ? _StrongOrd | |
| 728 | : __compute_comp_type(__type_kinds); | |
| 455 | constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; | |
| 456 | constexpr _CCC _Cat = __compute_comp_type(__type_kinds); | |
| 729 | 457 | if constexpr (_Cat == _None) |
| 730 | 458 | return void(); |
| 731 | else if constexpr (_Cat == _WeakEq) | |
| 732 | return weak_equality::equivalent; | |
| 733 | else if constexpr (_Cat == _StrongEq) | |
| 734 | return strong_equality::equivalent; | |
| 735 | 459 | else if constexpr (_Cat == _PartialOrd) |
| 736 | 460 | return partial_ordering::equivalent; |
| 737 | 461 | else if constexpr (_Cat == _WeakOrd) |
| ... | ... | @@ -739,7 +463,7 @@ constexpr auto __get_comp_type() { |
| 739 | 463 | else if constexpr (_Cat == _StrongOrd) |
| 740 | 464 | return strong_ordering::equivalent; |
| 741 | 465 | else |
| 742 | static_assert(_Cat != _Cat, "unhandled case"); | |
| 466 | static_assert(_False, "unhandled case"); | |
| 743 | 467 | } |
| 744 | 468 | } // namespace __comp_detail |
| 745 | 469 | |
| ... | ... | @@ -757,10 +481,8 @@ using common_comparison_category_t = typename common_comparison_category<_Ts...> |
| 757 | 481 | template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs); |
| 758 | 482 | template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs); |
| 759 | 483 | template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs); |
| 760 | template<class _Tp> constexpr strong_equality strong_equal(const _Tp& __lhs, const _Tp& __rhs); | |
| 761 | template<class _Tp> constexpr weak_equality weak_equal(const _Tp& __lhs, const _Tp& __rhs); | |
| 762 | 484 | |
| 763 | #endif // _LIBCPP_STD_VER > 17 | |
| 485 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) | |
| 764 | 486 | |
| 765 | 487 | _LIBCPP_END_NAMESPACE_STD |
| 766 | 488 |
lib/libcxx/include/complex+3-3| ... | ... | @@ -232,10 +232,10 @@ template<class T> complex<T> tanh (const complex<T>&); |
| 232 | 232 | */ |
| 233 | 233 | |
| 234 | 234 | #include <__config> |
| 235 | #include <type_traits> | |
| 236 | #include <stdexcept> | |
| 237 | 235 | #include <cmath> |
| 238 | 236 | #include <iosfwd> |
| 237 | #include <stdexcept> | |
| 238 | #include <type_traits> | |
| 239 | 239 | #include <version> |
| 240 | 240 | |
| 241 | 241 | #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) |
| ... | ... | @@ -1490,4 +1490,4 @@ inline namespace literals |
| 1490 | 1490 | |
| 1491 | 1491 | _LIBCPP_END_NAMESPACE_STD |
| 1492 | 1492 | |
| 1493 | #endif // _LIBCPP_COMPLEX | |
| 1493 | #endif // _LIBCPP_COMPLEX |
lib/libcxx/include/complex.h+2-2| ... | ... | @@ -31,6 +31,6 @@ |
| 31 | 31 | |
| 32 | 32 | #include_next <complex.h> |
| 33 | 33 | |
| 34 | #endif // __cplusplus | |
| 34 | #endif // __cplusplus | |
| 35 | 35 | |
| 36 | #endif // _LIBCPP_COMPLEX_H | |
| 36 | #endif // _LIBCPP_COMPLEX_H |
lib/libcxx/include/concepts+294-10| ... | ... | @@ -67,9 +67,9 @@ namespace std { |
| 67 | 67 | template<class T, class... Args> |
| 68 | 68 | concept constructible_from = see below; |
| 69 | 69 | |
| 70 | // [concept.defaultconstructible], concept default_constructible | |
| 70 | // [concept.default.init], concept default_initializable | |
| 71 | 71 | template<class T> |
| 72 | concept default_constructible = see below; | |
| 72 | concept default_initializable = see below; | |
| 73 | 73 | |
| 74 | 74 | // [concept.moveconstructible], concept move_constructible |
| 75 | 75 | template<class T> |
| ... | ... | @@ -79,11 +79,6 @@ namespace std { |
| 79 | 79 | template<class T> |
| 80 | 80 | concept copy_constructible = see below; |
| 81 | 81 | |
| 82 | // [concepts.compare], comparison concepts | |
| 83 | // [concept.boolean], concept boolean | |
| 84 | template<class B> | |
| 85 | concept boolean = see below; | |
| 86 | ||
| 87 | 82 | // [concept.equalitycomparable], concept equality_comparable |
| 88 | 83 | template<class T> |
| 89 | 84 | concept equality_comparable = see below; |
| ... | ... | @@ -135,7 +130,10 @@ namespace std { |
| 135 | 130 | */ |
| 136 | 131 | |
| 137 | 132 | #include <__config> |
| 133 | #include <__functional/invoke.h> | |
| 134 | #include <__functional_base> | |
| 138 | 135 | #include <type_traits> |
| 136 | #include <utility> | |
| 139 | 137 | #include <version> |
| 140 | 138 | |
| 141 | 139 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -147,7 +145,7 @@ _LIBCPP_PUSH_MACROS |
| 147 | 145 | |
| 148 | 146 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 149 | 147 | |
| 150 | #if _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L | |
| 148 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 151 | 149 | |
| 152 | 150 | // [concept.same] |
| 153 | 151 | |
| ... | ... | @@ -157,12 +155,298 @@ concept __same_as_impl = _VSTD::_IsSame<_Tp, _Up>::value; |
| 157 | 155 | template<class _Tp, class _Up> |
| 158 | 156 | concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; |
| 159 | 157 | |
| 158 | // [concept.derived] | |
| 159 | template<class _Dp, class _Bp> | |
| 160 | concept derived_from = | |
| 161 | is_base_of_v<_Bp, _Dp> && | |
| 162 | is_convertible_v<const volatile _Dp*, const volatile _Bp*>; | |
| 163 | ||
| 164 | // [concept.convertible] | |
| 165 | template<class _From, class _To> | |
| 166 | concept convertible_to = | |
| 167 | is_convertible_v<_From, _To> && | |
| 168 | requires(add_rvalue_reference_t<_From> (&__f)()) { | |
| 169 | static_cast<_To>(__f()); | |
| 170 | }; | |
| 171 | ||
| 172 | // [concept.commonref] | |
| 173 | template<class _Tp, class _Up> | |
| 174 | concept common_reference_with = | |
| 175 | same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> && | |
| 176 | convertible_to<_Tp, common_reference_t<_Tp, _Up>> && | |
| 177 | convertible_to<_Up, common_reference_t<_Tp, _Up>>; | |
| 178 | ||
| 179 | // [concept.common] | |
| 180 | template<class _Tp, class _Up> | |
| 181 | concept common_with = | |
| 182 | same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> && | |
| 183 | requires { | |
| 184 | static_cast<common_type_t<_Tp, _Up>>(declval<_Tp>()); | |
| 185 | static_cast<common_type_t<_Tp, _Up>>(declval<_Up>()); | |
| 186 | } && | |
| 187 | common_reference_with< | |
| 188 | add_lvalue_reference_t<const _Tp>, | |
| 189 | add_lvalue_reference_t<const _Up>> && | |
| 190 | common_reference_with< | |
| 191 | add_lvalue_reference_t<common_type_t<_Tp, _Up>>, | |
| 192 | common_reference_t< | |
| 193 | add_lvalue_reference_t<const _Tp>, | |
| 194 | add_lvalue_reference_t<const _Up>>>; | |
| 195 | ||
| 196 | // [concepts.arithmetic], arithmetic concepts | |
| 197 | template<class _Tp> | |
| 198 | concept integral = is_integral_v<_Tp>; | |
| 199 | ||
| 200 | template<class _Tp> | |
| 201 | concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; | |
| 202 | ||
| 203 | template<class _Tp> | |
| 204 | concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; | |
| 205 | ||
| 206 | template<class _Tp> | |
| 207 | concept floating_point = is_floating_point_v<_Tp>; | |
| 208 | ||
| 209 | // [concept.assignable] | |
| 210 | template<class _Lhs, class _Rhs> | |
| 211 | concept assignable_from = | |
| 212 | is_lvalue_reference_v<_Lhs> && | |
| 213 | common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> && | |
| 214 | requires (_Lhs __lhs, _Rhs&& __rhs) { | |
| 215 | { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>; | |
| 216 | }; | |
| 217 | ||
| 160 | 218 | // [concept.destructible] |
| 161 | 219 | |
| 162 | 220 | template<class _Tp> |
| 163 | concept destructible = _VSTD::is_nothrow_destructible_v<_Tp>; | |
| 221 | concept destructible = is_nothrow_destructible_v<_Tp>; | |
| 222 | ||
| 223 | // [concept.constructible] | |
| 224 | template<class _Tp, class... _Args> | |
| 225 | concept constructible_from = | |
| 226 | destructible<_Tp> && is_constructible_v<_Tp, _Args...>; | |
| 227 | ||
| 228 | // [concept.default.init] | |
| 229 | ||
| 230 | template<class _Tp> | |
| 231 | concept __default_initializable = requires { ::new _Tp; }; | |
| 232 | ||
| 233 | template<class _Tp> | |
| 234 | concept default_initializable = constructible_from<_Tp> && | |
| 235 | requires { _Tp{}; } && __default_initializable<_Tp>; | |
| 236 | ||
| 237 | // [concept.moveconstructible] | |
| 238 | template<class _Tp> | |
| 239 | concept move_constructible = | |
| 240 | constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; | |
| 241 | ||
| 242 | // [concept.copyconstructible] | |
| 243 | template<class _Tp> | |
| 244 | concept copy_constructible = | |
| 245 | move_constructible<_Tp> && | |
| 246 | constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> && | |
| 247 | constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp> && | |
| 248 | constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>; | |
| 249 | ||
| 250 | // Whether a type is a class type or enumeration type according to the Core wording. | |
| 251 | template<class _Tp> | |
| 252 | concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; | |
| 253 | ||
| 254 | // [concept.swappable] | |
| 255 | namespace ranges::__swap { | |
| 256 | // Deleted to inhibit ADL | |
| 257 | template<class _Tp> | |
| 258 | void swap(_Tp&, _Tp&) = delete; | |
| 259 | ||
| 260 | ||
| 261 | // [1] | |
| 262 | template<class _Tp, class _Up> | |
| 263 | concept __unqualified_swappable_with = | |
| 264 | (__class_or_enum<remove_cvref_t<_Tp>> || __class_or_enum<remove_cvref_t<_Up>>) && | |
| 265 | requires(_Tp&& __t, _Up&& __u) { | |
| 266 | swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); | |
| 267 | }; | |
| 268 | ||
| 269 | struct __fn; | |
| 270 | ||
| 271 | template<class _Tp, class _Up, size_t _Size> | |
| 272 | concept __swappable_arrays = | |
| 273 | !__unqualified_swappable_with<_Tp(&)[_Size], _Up(&)[_Size]> && | |
| 274 | extent_v<_Tp> == extent_v<_Up> && | |
| 275 | requires(_Tp(& __t)[_Size], _Up(& __u)[_Size], const __fn& __swap) { | |
| 276 | __swap(__t[0], __u[0]); | |
| 277 | }; | |
| 278 | ||
| 279 | template<class _Tp> | |
| 280 | concept __exchangeable = | |
| 281 | !__unqualified_swappable_with<_Tp&, _Tp&> && | |
| 282 | move_constructible<_Tp> && | |
| 283 | assignable_from<_Tp&, _Tp>; | |
| 284 | ||
| 285 | struct __fn { | |
| 286 | // 2.1 `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and... | |
| 287 | // *The name `swap` is used here unqualified. | |
| 288 | template<class _Tp, class _Up> | |
| 289 | requires __unqualified_swappable_with<_Tp, _Up> | |
| 290 | constexpr void operator()(_Tp&& __t, _Up&& __u) const | |
| 291 | noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) | |
| 292 | { | |
| 293 | swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); | |
| 294 | } | |
| 295 | ||
| 296 | // 2.2 Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and... | |
| 297 | template<class _Tp, class _Up, size_t _Size> | |
| 298 | requires __swappable_arrays<_Tp, _Up, _Size> | |
| 299 | constexpr void operator()(_Tp(& __t)[_Size], _Up(& __u)[_Size]) const | |
| 300 | noexcept(noexcept((*this)(*__t, *__u))) | |
| 301 | { | |
| 302 | // TODO(cjdb): replace with `ranges::swap_ranges`. | |
| 303 | for (size_t __i = 0; __i < _Size; ++__i) { | |
| 304 | (*this)(__t[__i], __u[__i]); | |
| 305 | } | |
| 306 | } | |
| 307 | ||
| 308 | // 2.3 Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models... | |
| 309 | template<__exchangeable _Tp> | |
| 310 | constexpr void operator()(_Tp& __x, _Tp& __y) const | |
| 311 | noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>) | |
| 312 | { | |
| 313 | __y = _VSTD::exchange(__x, _VSTD::move(__y)); | |
| 314 | } | |
| 315 | }; | |
| 316 | } // namespace ranges::__swap | |
| 317 | ||
| 318 | namespace ranges::inline __cpo { | |
| 319 | inline constexpr auto swap = __swap::__fn{}; | |
| 320 | } // namespace ranges::__cpo | |
| 321 | ||
| 322 | template<class _Tp> | |
| 323 | concept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; | |
| 324 | ||
| 325 | template<class _Tp, class _Up> | |
| 326 | concept swappable_with = | |
| 327 | common_reference_with<_Tp, _Up> && | |
| 328 | requires(_Tp&& __t, _Up&& __u) { | |
| 329 | ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t)); | |
| 330 | ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u)); | |
| 331 | ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); | |
| 332 | ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); | |
| 333 | }; | |
| 334 | ||
| 335 | // [concept.booleantestable] | |
| 336 | template<class _Tp> | |
| 337 | concept __boolean_testable_impl = convertible_to<_Tp, bool>; | |
| 338 | ||
| 339 | template<class _Tp> | |
| 340 | concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { | |
| 341 | { !std::forward<_Tp>(__t) } -> __boolean_testable_impl; | |
| 342 | }; | |
| 343 | ||
| 344 | // [concept.equalitycomparable] | |
| 345 | template<class _Tp, class _Up> | |
| 346 | concept __weakly_equality_comparable_with = | |
| 347 | requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { | |
| 348 | { __t == __u } -> __boolean_testable; | |
| 349 | { __t != __u } -> __boolean_testable; | |
| 350 | { __u == __t } -> __boolean_testable; | |
| 351 | { __u != __t } -> __boolean_testable; | |
| 352 | }; | |
| 353 | ||
| 354 | template<class _Tp> | |
| 355 | concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; | |
| 356 | ||
| 357 | template<class _Tp, class _Up> | |
| 358 | concept equality_comparable_with = | |
| 359 | equality_comparable<_Tp> && equality_comparable<_Up> && | |
| 360 | common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && | |
| 361 | equality_comparable< | |
| 362 | common_reference_t< | |
| 363 | __make_const_lvalue_ref<_Tp>, | |
| 364 | __make_const_lvalue_ref<_Up>>> && | |
| 365 | __weakly_equality_comparable_with<_Tp, _Up>; | |
| 366 | ||
| 367 | // [concept.totallyordered] | |
| 368 | ||
| 369 | template<class _Tp, class _Up> | |
| 370 | concept __partially_ordered_with = | |
| 371 | requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { | |
| 372 | { __t < __u } -> __boolean_testable; | |
| 373 | { __t > __u } -> __boolean_testable; | |
| 374 | { __t <= __u } -> __boolean_testable; | |
| 375 | { __t >= __u } -> __boolean_testable; | |
| 376 | { __u < __t } -> __boolean_testable; | |
| 377 | { __u > __t } -> __boolean_testable; | |
| 378 | { __u <= __t } -> __boolean_testable; | |
| 379 | { __u >= __t } -> __boolean_testable; | |
| 380 | }; | |
| 381 | ||
| 382 | template<class _Tp> | |
| 383 | concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; | |
| 384 | ||
| 385 | template<class _Tp, class _Up> | |
| 386 | concept totally_ordered_with = | |
| 387 | totally_ordered<_Tp> && totally_ordered<_Up> && | |
| 388 | equality_comparable_with<_Tp, _Up> && | |
| 389 | totally_ordered< | |
| 390 | common_reference_t< | |
| 391 | __make_const_lvalue_ref<_Tp>, | |
| 392 | __make_const_lvalue_ref<_Up>>> && | |
| 393 | __partially_ordered_with<_Tp, _Up>; | |
| 394 | ||
| 395 | // [concepts.object] | |
| 396 | template<class _Tp> | |
| 397 | concept movable = | |
| 398 | is_object_v<_Tp> && | |
| 399 | move_constructible<_Tp> && | |
| 400 | assignable_from<_Tp&, _Tp> && | |
| 401 | swappable<_Tp>; | |
| 402 | ||
| 403 | template<class _Tp> | |
| 404 | concept copyable = | |
| 405 | copy_constructible<_Tp> && | |
| 406 | movable<_Tp> && | |
| 407 | assignable_from<_Tp&, _Tp&> && | |
| 408 | assignable_from<_Tp&, const _Tp&> && | |
| 409 | assignable_from<_Tp&, const _Tp>; | |
| 410 | ||
| 411 | template<class _Tp> | |
| 412 | concept semiregular = copyable<_Tp> && default_initializable<_Tp>; | |
| 413 | ||
| 414 | template<class _Tp> | |
| 415 | concept regular = semiregular<_Tp> && equality_comparable<_Tp>; | |
| 416 | ||
| 417 | // [concept.invocable] | |
| 418 | template<class _Fn, class... _Args> | |
| 419 | concept invocable = requires(_Fn&& __fn, _Args&&... __args) { | |
| 420 | _VSTD::invoke(_VSTD::forward<_Fn>(__fn), _VSTD::forward<_Args>(__args)...); // not required to be equality preserving | |
| 421 | }; | |
| 422 | ||
| 423 | // [concept.regular.invocable] | |
| 424 | template<class _Fn, class... _Args> | |
| 425 | concept regular_invocable = invocable<_Fn, _Args...>; | |
| 426 | ||
| 427 | // [concept.predicate] | |
| 428 | template<class _Fn, class... _Args> | |
| 429 | concept predicate = | |
| 430 | regular_invocable<_Fn, _Args...> && __boolean_testable<invoke_result_t<_Fn, _Args...>>; | |
| 431 | ||
| 432 | // [concept.relation] | |
| 433 | template<class _Rp, class _Tp, class _Up> | |
| 434 | concept relation = | |
| 435 | predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && | |
| 436 | predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; | |
| 437 | ||
| 438 | // [concept.equiv] | |
| 439 | template<class _Rp, class _Tp, class _Up> | |
| 440 | concept equivalence_relation = relation<_Rp, _Tp, _Up>; | |
| 441 | ||
| 442 | // [concept.strictweakorder] | |
| 443 | template<class _Rp, class _Tp, class _Up> | |
| 444 | concept strict_weak_order = relation<_Rp, _Tp, _Up>; | |
| 445 | ||
| 446 | template<class _Tp, class _Up> | |
| 447 | concept __different_from = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>; | |
| 164 | 448 | |
| 165 | #endif //_LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L | |
| 449 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 166 | 450 | |
| 167 | 451 | _LIBCPP_END_NAMESPACE_STD |
| 168 | 452 |
lib/libcxx/include/condition_variable+1-1| ... | ... | @@ -265,4 +265,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 265 | 265 | |
| 266 | 266 | #endif // !_LIBCPP_HAS_NO_THREADS |
| 267 | 267 | |
| 268 | #endif // _LIBCPP_CONDITION_VARIABLE | |
| 268 | #endif // _LIBCPP_CONDITION_VARIABLE |
lib/libcxx/include/csetjmp+3-3| ... | ... | @@ -39,9 +39,9 @@ void longjmp(jmp_buf env, int val); |
| 39 | 39 | |
| 40 | 40 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 41 | 41 | |
| 42 | using ::jmp_buf; | |
| 43 | using ::longjmp; | |
| 42 | using ::jmp_buf _LIBCPP_USING_IF_EXISTS; | |
| 43 | using ::longjmp _LIBCPP_USING_IF_EXISTS; | |
| 44 | 44 | |
| 45 | 45 | _LIBCPP_END_NAMESPACE_STD |
| 46 | 46 | |
| 47 | #endif // _LIBCPP_CSETJMP | |
| 47 | #endif // _LIBCPP_CSETJMP |
lib/libcxx/include/csignal+4-4| ... | ... | @@ -48,10 +48,10 @@ int raise(int sig); |
| 48 | 48 | |
| 49 | 49 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 50 | 50 | |
| 51 | using ::sig_atomic_t; | |
| 52 | using ::signal; | |
| 53 | using ::raise; | |
| 51 | using ::sig_atomic_t _LIBCPP_USING_IF_EXISTS; | |
| 52 | using ::signal _LIBCPP_USING_IF_EXISTS; | |
| 53 | using ::raise _LIBCPP_USING_IF_EXISTS; | |
| 54 | 54 | |
| 55 | 55 | _LIBCPP_END_NAMESPACE_STD |
| 56 | 56 | |
| 57 | #endif // _LIBCPP_CSIGNAL | |
| 57 | #endif // _LIBCPP_CSIGNAL |
lib/libcxx/include/cstdarg+2-2| ... | ... | @@ -40,8 +40,8 @@ Types: |
| 40 | 40 | |
| 41 | 41 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 42 | 42 | |
| 43 | using ::va_list; | |
| 43 | using ::va_list _LIBCPP_USING_IF_EXISTS; | |
| 44 | 44 | |
| 45 | 45 | _LIBCPP_END_NAMESPACE_STD |
| 46 | 46 | |
| 47 | #endif // _LIBCPP_CSTDARG | |
| 47 | #endif // _LIBCPP_CSTDARG |
lib/libcxx/include/cstdbool+1-1| ... | ... | @@ -28,4 +28,4 @@ Macros: |
| 28 | 28 | #undef __bool_true_false_are_defined |
| 29 | 29 | #define __bool_true_false_are_defined 1 |
| 30 | 30 | |
| 31 | #endif // _LIBCPP_CSTDBOOL | |
| 31 | #endif // _LIBCPP_CSTDBOOL |
lib/libcxx/include/cstddef+7-7| ... | ... | @@ -46,11 +46,11 @@ Types: |
| 46 | 46 | |
| 47 | 47 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 48 | 48 | |
| 49 | using ::ptrdiff_t; | |
| 50 | using ::size_t; | |
| 49 | using ::ptrdiff_t _LIBCPP_USING_IF_EXISTS; | |
| 50 | using ::size_t _LIBCPP_USING_IF_EXISTS; | |
| 51 | 51 | |
| 52 | 52 | #if !defined(_LIBCPP_CXX03_LANG) |
| 53 | using ::max_align_t; | |
| 53 | using ::max_align_t _LIBCPP_USING_IF_EXISTS; | |
| 54 | 54 | #endif |
| 55 | 55 | |
| 56 | 56 | template <class _Tp> struct __libcpp_is_integral { enum { value = 0 }; }; |
| ... | ... | @@ -59,13 +59,13 @@ template <> struct __libcpp_is_integral<char> { enum { va |
| 59 | 59 | template <> struct __libcpp_is_integral<signed char> { enum { value = 1 }; }; |
| 60 | 60 | template <> struct __libcpp_is_integral<unsigned char> { enum { value = 1 }; }; |
| 61 | 61 | template <> struct __libcpp_is_integral<wchar_t> { enum { value = 1 }; }; |
| 62 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 62 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 63 | 63 | template <> struct __libcpp_is_integral<char8_t> { enum { value = 1 }; }; |
| 64 | 64 | #endif |
| 65 | 65 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS |
| 66 | 66 | template <> struct __libcpp_is_integral<char16_t> { enum { value = 1 }; }; |
| 67 | 67 | template <> struct __libcpp_is_integral<char32_t> { enum { value = 1 }; }; |
| 68 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 68 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 69 | 69 | template <> struct __libcpp_is_integral<short> { enum { value = 1 }; }; |
| 70 | 70 | template <> struct __libcpp_is_integral<unsigned short> { enum { value = 1 }; }; |
| 71 | 71 | template <> struct __libcpp_is_integral<int> { enum { value = 1 }; }; |
| ... | ... | @@ -152,10 +152,10 @@ template <class _Integer> |
| 152 | 152 | { return static_cast<byte>(static_cast<unsigned char>(static_cast<unsigned int>(__lhs) >> __shift)); } |
| 153 | 153 | |
| 154 | 154 | template <class _Integer, class = _EnableByteOverload<_Integer> > |
| 155 | constexpr _Integer | |
| 155 | _LIBCPP_NODISCARD_EXT constexpr _Integer | |
| 156 | 156 | to_integer(byte __b) noexcept { return static_cast<_Integer>(__b); } |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | 159 | #endif |
| 160 | 160 | |
| 161 | #endif // _LIBCPP_CSTDDEF | |
| 161 | #endif // _LIBCPP_CSTDDEF |
lib/libcxx/include/cstdint+36-36| ... | ... | @@ -149,42 +149,42 @@ Types: |
| 149 | 149 | |
| 150 | 150 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 151 | 151 | |
| 152 | using::int8_t; | |
| 153 | using::int16_t; | |
| 154 | using::int32_t; | |
| 155 | using::int64_t; | |
| 156 | ||
| 157 | using::uint8_t; | |
| 158 | using::uint16_t; | |
| 159 | using::uint32_t; | |
| 160 | using::uint64_t; | |
| 161 | ||
| 162 | using::int_least8_t; | |
| 163 | using::int_least16_t; | |
| 164 | using::int_least32_t; | |
| 165 | using::int_least64_t; | |
| 166 | ||
| 167 | using::uint_least8_t; | |
| 168 | using::uint_least16_t; | |
| 169 | using::uint_least32_t; | |
| 170 | using::uint_least64_t; | |
| 171 | ||
| 172 | using::int_fast8_t; | |
| 173 | using::int_fast16_t; | |
| 174 | using::int_fast32_t; | |
| 175 | using::int_fast64_t; | |
| 176 | ||
| 177 | using::uint_fast8_t; | |
| 178 | using::uint_fast16_t; | |
| 179 | using::uint_fast32_t; | |
| 180 | using::uint_fast64_t; | |
| 181 | ||
| 182 | using::intptr_t; | |
| 183 | using::uintptr_t; | |
| 184 | ||
| 185 | using::intmax_t; | |
| 186 | using::uintmax_t; | |
| 152 | using ::int8_t _LIBCPP_USING_IF_EXISTS; | |
| 153 | using ::int16_t _LIBCPP_USING_IF_EXISTS; | |
| 154 | using ::int32_t _LIBCPP_USING_IF_EXISTS; | |
| 155 | using ::int64_t _LIBCPP_USING_IF_EXISTS; | |
| 156 | ||
| 157 | using ::uint8_t _LIBCPP_USING_IF_EXISTS; | |
| 158 | using ::uint16_t _LIBCPP_USING_IF_EXISTS; | |
| 159 | using ::uint32_t _LIBCPP_USING_IF_EXISTS; | |
| 160 | using ::uint64_t _LIBCPP_USING_IF_EXISTS; | |
| 161 | ||
| 162 | using ::int_least8_t _LIBCPP_USING_IF_EXISTS; | |
| 163 | using ::int_least16_t _LIBCPP_USING_IF_EXISTS; | |
| 164 | using ::int_least32_t _LIBCPP_USING_IF_EXISTS; | |
| 165 | using ::int_least64_t _LIBCPP_USING_IF_EXISTS; | |
| 166 | ||
| 167 | using ::uint_least8_t _LIBCPP_USING_IF_EXISTS; | |
| 168 | using ::uint_least16_t _LIBCPP_USING_IF_EXISTS; | |
| 169 | using ::uint_least32_t _LIBCPP_USING_IF_EXISTS; | |
| 170 | using ::uint_least64_t _LIBCPP_USING_IF_EXISTS; | |
| 171 | ||
| 172 | using ::int_fast8_t _LIBCPP_USING_IF_EXISTS; | |
| 173 | using ::int_fast16_t _LIBCPP_USING_IF_EXISTS; | |
| 174 | using ::int_fast32_t _LIBCPP_USING_IF_EXISTS; | |
| 175 | using ::int_fast64_t _LIBCPP_USING_IF_EXISTS; | |
| 176 | ||
| 177 | using ::uint_fast8_t _LIBCPP_USING_IF_EXISTS; | |
| 178 | using ::uint_fast16_t _LIBCPP_USING_IF_EXISTS; | |
| 179 | using ::uint_fast32_t _LIBCPP_USING_IF_EXISTS; | |
| 180 | using ::uint_fast64_t _LIBCPP_USING_IF_EXISTS; | |
| 181 | ||
| 182 | using ::intptr_t _LIBCPP_USING_IF_EXISTS; | |
| 183 | using ::uintptr_t _LIBCPP_USING_IF_EXISTS; | |
| 184 | ||
| 185 | using ::intmax_t _LIBCPP_USING_IF_EXISTS; | |
| 186 | using ::uintmax_t _LIBCPP_USING_IF_EXISTS; | |
| 187 | 187 | |
| 188 | 188 | _LIBCPP_END_NAMESPACE_STD |
| 189 | 189 | |
| 190 | #endif // _LIBCPP_CSTDINT | |
| 190 | #endif // _LIBCPP_CSTDINT |
lib/libcxx/include/cstdio+51-51| ... | ... | @@ -104,72 +104,72 @@ void perror(const char* s); |
| 104 | 104 | |
| 105 | 105 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 106 | 106 | |
| 107 | using ::FILE; | |
| 108 | using ::fpos_t; | |
| 109 | using ::size_t; | |
| 110 | ||
| 111 | using ::fclose; | |
| 112 | using ::fflush; | |
| 113 | using ::setbuf; | |
| 114 | using ::setvbuf; | |
| 115 | using ::fprintf; | |
| 116 | using ::fscanf; | |
| 117 | using ::snprintf; | |
| 118 | using ::sprintf; | |
| 119 | using ::sscanf; | |
| 120 | using ::vfprintf; | |
| 121 | using ::vfscanf; | |
| 122 | using ::vsscanf; | |
| 123 | using ::vsnprintf; | |
| 124 | using ::vsprintf; | |
| 125 | using ::fgetc; | |
| 126 | using ::fgets; | |
| 127 | using ::fputc; | |
| 128 | using ::fputs; | |
| 129 | using ::getc; | |
| 130 | using ::putc; | |
| 131 | using ::ungetc; | |
| 132 | using ::fread; | |
| 133 | using ::fwrite; | |
| 107 | using ::FILE _LIBCPP_USING_IF_EXISTS; | |
| 108 | using ::fpos_t _LIBCPP_USING_IF_EXISTS; | |
| 109 | using ::size_t _LIBCPP_USING_IF_EXISTS; | |
| 110 | ||
| 111 | using ::fclose _LIBCPP_USING_IF_EXISTS; | |
| 112 | using ::fflush _LIBCPP_USING_IF_EXISTS; | |
| 113 | using ::setbuf _LIBCPP_USING_IF_EXISTS; | |
| 114 | using ::setvbuf _LIBCPP_USING_IF_EXISTS; | |
| 115 | using ::fprintf _LIBCPP_USING_IF_EXISTS; | |
| 116 | using ::fscanf _LIBCPP_USING_IF_EXISTS; | |
| 117 | using ::snprintf _LIBCPP_USING_IF_EXISTS; | |
| 118 | using ::sprintf _LIBCPP_USING_IF_EXISTS; | |
| 119 | using ::sscanf _LIBCPP_USING_IF_EXISTS; | |
| 120 | using ::vfprintf _LIBCPP_USING_IF_EXISTS; | |
| 121 | using ::vfscanf _LIBCPP_USING_IF_EXISTS; | |
| 122 | using ::vsscanf _LIBCPP_USING_IF_EXISTS; | |
| 123 | using ::vsnprintf _LIBCPP_USING_IF_EXISTS; | |
| 124 | using ::vsprintf _LIBCPP_USING_IF_EXISTS; | |
| 125 | using ::fgetc _LIBCPP_USING_IF_EXISTS; | |
| 126 | using ::fgets _LIBCPP_USING_IF_EXISTS; | |
| 127 | using ::fputc _LIBCPP_USING_IF_EXISTS; | |
| 128 | using ::fputs _LIBCPP_USING_IF_EXISTS; | |
| 129 | using ::getc _LIBCPP_USING_IF_EXISTS; | |
| 130 | using ::putc _LIBCPP_USING_IF_EXISTS; | |
| 131 | using ::ungetc _LIBCPP_USING_IF_EXISTS; | |
| 132 | using ::fread _LIBCPP_USING_IF_EXISTS; | |
| 133 | using ::fwrite _LIBCPP_USING_IF_EXISTS; | |
| 134 | 134 | #ifndef _LIBCPP_HAS_NO_FGETPOS_FSETPOS |
| 135 | using ::fgetpos; | |
| 135 | using ::fgetpos _LIBCPP_USING_IF_EXISTS; | |
| 136 | 136 | #endif |
| 137 | using ::fseek; | |
| 137 | using ::fseek _LIBCPP_USING_IF_EXISTS; | |
| 138 | 138 | #ifndef _LIBCPP_HAS_NO_FGETPOS_FSETPOS |
| 139 | using ::fsetpos; | |
| 139 | using ::fsetpos _LIBCPP_USING_IF_EXISTS; | |
| 140 | 140 | #endif |
| 141 | using ::ftell; | |
| 142 | using ::rewind; | |
| 143 | using ::clearerr; | |
| 144 | using ::feof; | |
| 145 | using ::ferror; | |
| 146 | using ::perror; | |
| 141 | using ::ftell _LIBCPP_USING_IF_EXISTS; | |
| 142 | using ::rewind _LIBCPP_USING_IF_EXISTS; | |
| 143 | using ::clearerr _LIBCPP_USING_IF_EXISTS; | |
| 144 | using ::feof _LIBCPP_USING_IF_EXISTS; | |
| 145 | using ::ferror _LIBCPP_USING_IF_EXISTS; | |
| 146 | using ::perror _LIBCPP_USING_IF_EXISTS; | |
| 147 | 147 | |
| 148 | 148 | #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE |
| 149 | using ::fopen; | |
| 150 | using ::freopen; | |
| 151 | using ::remove; | |
| 152 | using ::rename; | |
| 153 | using ::tmpfile; | |
| 154 | using ::tmpnam; | |
| 149 | using ::fopen _LIBCPP_USING_IF_EXISTS; | |
| 150 | using ::freopen _LIBCPP_USING_IF_EXISTS; | |
| 151 | using ::remove _LIBCPP_USING_IF_EXISTS; | |
| 152 | using ::rename _LIBCPP_USING_IF_EXISTS; | |
| 153 | using ::tmpfile _LIBCPP_USING_IF_EXISTS; | |
| 154 | using ::tmpnam _LIBCPP_USING_IF_EXISTS; | |
| 155 | 155 | #endif |
| 156 | 156 | |
| 157 | 157 | #ifndef _LIBCPP_HAS_NO_STDIN |
| 158 | using ::getchar; | |
| 158 | using ::getchar _LIBCPP_USING_IF_EXISTS; | |
| 159 | 159 | #if _LIBCPP_STD_VER <= 11 && !defined(_LIBCPP_C_HAS_NO_GETS) |
| 160 | using ::gets; | |
| 160 | using ::gets _LIBCPP_USING_IF_EXISTS; | |
| 161 | 161 | #endif |
| 162 | using ::scanf; | |
| 163 | using ::vscanf; | |
| 162 | using ::scanf _LIBCPP_USING_IF_EXISTS; | |
| 163 | using ::vscanf _LIBCPP_USING_IF_EXISTS; | |
| 164 | 164 | #endif |
| 165 | 165 | |
| 166 | 166 | #ifndef _LIBCPP_HAS_NO_STDOUT |
| 167 | using ::printf; | |
| 168 | using ::putchar; | |
| 169 | using ::puts; | |
| 170 | using ::vprintf; | |
| 167 | using ::printf _LIBCPP_USING_IF_EXISTS; | |
| 168 | using ::putchar _LIBCPP_USING_IF_EXISTS; | |
| 169 | using ::puts _LIBCPP_USING_IF_EXISTS; | |
| 170 | using ::vprintf _LIBCPP_USING_IF_EXISTS; | |
| 171 | 171 | #endif |
| 172 | 172 | |
| 173 | 173 | _LIBCPP_END_NAMESPACE_STD |
| 174 | 174 | |
| 175 | #endif // _LIBCPP_CSTDIO | |
| 175 | #endif // _LIBCPP_CSTDIO |
lib/libcxx/include/cstdlib+44-44| ... | ... | @@ -96,68 +96,68 @@ void *aligned_alloc(size_t alignment, size_t size); // C11 |
| 96 | 96 | |
| 97 | 97 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 98 | 98 | |
| 99 | using ::size_t; | |
| 100 | using ::div_t; | |
| 101 | using ::ldiv_t; | |
| 99 | using ::size_t _LIBCPP_USING_IF_EXISTS; | |
| 100 | using ::div_t _LIBCPP_USING_IF_EXISTS; | |
| 101 | using ::ldiv_t _LIBCPP_USING_IF_EXISTS; | |
| 102 | 102 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 103 | using ::lldiv_t; | |
| 103 | using ::lldiv_t _LIBCPP_USING_IF_EXISTS; | |
| 104 | 104 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 105 | using ::atof; | |
| 106 | using ::atoi; | |
| 107 | using ::atol; | |
| 105 | using ::atof _LIBCPP_USING_IF_EXISTS; | |
| 106 | using ::atoi _LIBCPP_USING_IF_EXISTS; | |
| 107 | using ::atol _LIBCPP_USING_IF_EXISTS; | |
| 108 | 108 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 109 | using ::atoll; | |
| 109 | using ::atoll _LIBCPP_USING_IF_EXISTS; | |
| 110 | 110 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 111 | using ::strtod; | |
| 112 | using ::strtof; | |
| 113 | using ::strtold; | |
| 114 | using ::strtol; | |
| 111 | using ::strtod _LIBCPP_USING_IF_EXISTS; | |
| 112 | using ::strtof _LIBCPP_USING_IF_EXISTS; | |
| 113 | using ::strtold _LIBCPP_USING_IF_EXISTS; | |
| 114 | using ::strtol _LIBCPP_USING_IF_EXISTS; | |
| 115 | 115 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 116 | using ::strtoll; | |
| 116 | using ::strtoll _LIBCPP_USING_IF_EXISTS; | |
| 117 | 117 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 118 | using ::strtoul; | |
| 118 | using ::strtoul _LIBCPP_USING_IF_EXISTS; | |
| 119 | 119 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 120 | using ::strtoull; | |
| 120 | using ::strtoull _LIBCPP_USING_IF_EXISTS; | |
| 121 | 121 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 122 | using ::rand; | |
| 123 | using ::srand; | |
| 124 | using ::calloc; | |
| 125 | using ::free; | |
| 126 | using ::malloc; | |
| 127 | using ::realloc; | |
| 128 | using ::abort; | |
| 129 | using ::atexit; | |
| 130 | using ::exit; | |
| 131 | using ::_Exit; | |
| 122 | using ::rand _LIBCPP_USING_IF_EXISTS; | |
| 123 | using ::srand _LIBCPP_USING_IF_EXISTS; | |
| 124 | using ::calloc _LIBCPP_USING_IF_EXISTS; | |
| 125 | using ::free _LIBCPP_USING_IF_EXISTS; | |
| 126 | using ::malloc _LIBCPP_USING_IF_EXISTS; | |
| 127 | using ::realloc _LIBCPP_USING_IF_EXISTS; | |
| 128 | using ::abort _LIBCPP_USING_IF_EXISTS; | |
| 129 | using ::atexit _LIBCPP_USING_IF_EXISTS; | |
| 130 | using ::exit _LIBCPP_USING_IF_EXISTS; | |
| 131 | using ::_Exit _LIBCPP_USING_IF_EXISTS; | |
| 132 | 132 | #ifndef _LIBCPP_WINDOWS_STORE_APP |
| 133 | using ::getenv; | |
| 134 | using ::system; | |
| 133 | using ::getenv _LIBCPP_USING_IF_EXISTS; | |
| 134 | using ::system _LIBCPP_USING_IF_EXISTS; | |
| 135 | 135 | #endif |
| 136 | using ::bsearch; | |
| 137 | using ::qsort; | |
| 138 | using ::abs; | |
| 139 | using ::labs; | |
| 136 | using ::bsearch _LIBCPP_USING_IF_EXISTS; | |
| 137 | using ::qsort _LIBCPP_USING_IF_EXISTS; | |
| 138 | using ::abs _LIBCPP_USING_IF_EXISTS; | |
| 139 | using ::labs _LIBCPP_USING_IF_EXISTS; | |
| 140 | 140 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 141 | using ::llabs; | |
| 141 | using ::llabs _LIBCPP_USING_IF_EXISTS; | |
| 142 | 142 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 143 | using ::div; | |
| 144 | using ::ldiv; | |
| 143 | using ::div _LIBCPP_USING_IF_EXISTS; | |
| 144 | using ::ldiv _LIBCPP_USING_IF_EXISTS; | |
| 145 | 145 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 146 | using ::lldiv; | |
| 146 | using ::lldiv _LIBCPP_USING_IF_EXISTS; | |
| 147 | 147 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 148 | using ::mblen; | |
| 149 | using ::mbtowc; | |
| 150 | using ::wctomb; | |
| 151 | using ::mbstowcs; | |
| 152 | using ::wcstombs; | |
| 148 | using ::mblen _LIBCPP_USING_IF_EXISTS; | |
| 149 | using ::mbtowc _LIBCPP_USING_IF_EXISTS; | |
| 150 | using ::wctomb _LIBCPP_USING_IF_EXISTS; | |
| 151 | using ::mbstowcs _LIBCPP_USING_IF_EXISTS; | |
| 152 | using ::wcstombs _LIBCPP_USING_IF_EXISTS; | |
| 153 | 153 | #if !defined(_LIBCPP_CXX03_LANG) && defined(_LIBCPP_HAS_QUICK_EXIT) |
| 154 | using ::at_quick_exit; | |
| 155 | using ::quick_exit; | |
| 154 | using ::at_quick_exit _LIBCPP_USING_IF_EXISTS; | |
| 155 | using ::quick_exit _LIBCPP_USING_IF_EXISTS; | |
| 156 | 156 | #endif |
| 157 | 157 | #if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_ALIGNED_ALLOC) |
| 158 | using ::aligned_alloc; | |
| 158 | using ::aligned_alloc _LIBCPP_USING_IF_EXISTS; | |
| 159 | 159 | #endif |
| 160 | 160 | |
| 161 | 161 | _LIBCPP_END_NAMESPACE_STD |
| 162 | 162 | |
| 163 | #endif // _LIBCPP_CSTDLIB | |
| 163 | #endif // _LIBCPP_CSTDLIB |
lib/libcxx/include/cstring+24-24| ... | ... | @@ -65,32 +65,32 @@ size_t strlen(const char* s); |
| 65 | 65 | |
| 66 | 66 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 67 | 67 | |
| 68 | using ::size_t; | |
| 69 | using ::memcpy; | |
| 70 | using ::memmove; | |
| 71 | using ::strcpy; | |
| 72 | using ::strncpy; | |
| 73 | using ::strcat; | |
| 74 | using ::strncat; | |
| 75 | using ::memcmp; | |
| 76 | using ::strcmp; | |
| 77 | using ::strncmp; | |
| 78 | using ::strcoll; | |
| 79 | using ::strxfrm; | |
| 80 | using ::memchr; | |
| 81 | using ::strchr; | |
| 82 | using ::strcspn; | |
| 83 | using ::strpbrk; | |
| 84 | using ::strrchr; | |
| 85 | using ::strspn; | |
| 86 | using ::strstr; | |
| 68 | using ::size_t _LIBCPP_USING_IF_EXISTS; | |
| 69 | using ::memcpy _LIBCPP_USING_IF_EXISTS; | |
| 70 | using ::memmove _LIBCPP_USING_IF_EXISTS; | |
| 71 | using ::strcpy _LIBCPP_USING_IF_EXISTS; | |
| 72 | using ::strncpy _LIBCPP_USING_IF_EXISTS; | |
| 73 | using ::strcat _LIBCPP_USING_IF_EXISTS; | |
| 74 | using ::strncat _LIBCPP_USING_IF_EXISTS; | |
| 75 | using ::memcmp _LIBCPP_USING_IF_EXISTS; | |
| 76 | using ::strcmp _LIBCPP_USING_IF_EXISTS; | |
| 77 | using ::strncmp _LIBCPP_USING_IF_EXISTS; | |
| 78 | using ::strcoll _LIBCPP_USING_IF_EXISTS; | |
| 79 | using ::strxfrm _LIBCPP_USING_IF_EXISTS; | |
| 80 | using ::memchr _LIBCPP_USING_IF_EXISTS; | |
| 81 | using ::strchr _LIBCPP_USING_IF_EXISTS; | |
| 82 | using ::strcspn _LIBCPP_USING_IF_EXISTS; | |
| 83 | using ::strpbrk _LIBCPP_USING_IF_EXISTS; | |
| 84 | using ::strrchr _LIBCPP_USING_IF_EXISTS; | |
| 85 | using ::strspn _LIBCPP_USING_IF_EXISTS; | |
| 86 | using ::strstr _LIBCPP_USING_IF_EXISTS; | |
| 87 | 87 | #ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS |
| 88 | using ::strtok; | |
| 88 | using ::strtok _LIBCPP_USING_IF_EXISTS; | |
| 89 | 89 | #endif |
| 90 | using ::memset; | |
| 91 | using ::strerror; | |
| 92 | using ::strlen; | |
| 90 | using ::memset _LIBCPP_USING_IF_EXISTS; | |
| 91 | using ::strerror _LIBCPP_USING_IF_EXISTS; | |
| 92 | using ::strlen _LIBCPP_USING_IF_EXISTS; | |
| 93 | 93 | |
| 94 | 94 | _LIBCPP_END_NAMESPACE_STD |
| 95 | 95 | |
| 96 | #endif // _LIBCPP_CSTRING | |
| 96 | #endif // _LIBCPP_CSTRING |
lib/libcxx/include/ctgmath+1-1| ... | ... | @@ -25,4 +25,4 @@ |
| 25 | 25 | #pragma GCC system_header |
| 26 | 26 | #endif |
| 27 | 27 | |
| 28 | #endif // _LIBCPP_CTGMATH | |
| 28 | #endif // _LIBCPP_CTGMATH |
lib/libcxx/include/ctime+16-16| ... | ... | @@ -68,28 +68,28 @@ int timespec_get( struct timespec *ts, int base); // C++17 |
| 68 | 68 | |
| 69 | 69 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 70 | 70 | |
| 71 | using ::clock_t; | |
| 72 | using ::size_t; | |
| 73 | using ::time_t; | |
| 74 | using ::tm; | |
| 71 | using ::clock_t _LIBCPP_USING_IF_EXISTS; | |
| 72 | using ::size_t _LIBCPP_USING_IF_EXISTS; | |
| 73 | using ::time_t _LIBCPP_USING_IF_EXISTS; | |
| 74 | using ::tm _LIBCPP_USING_IF_EXISTS; | |
| 75 | 75 | #if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_TIMESPEC_GET) |
| 76 | using ::timespec; | |
| 76 | using ::timespec _LIBCPP_USING_IF_EXISTS; | |
| 77 | 77 | #endif |
| 78 | using ::clock; | |
| 79 | using ::difftime; | |
| 80 | using ::mktime; | |
| 81 | using ::time; | |
| 78 | using ::clock _LIBCPP_USING_IF_EXISTS; | |
| 79 | using ::difftime _LIBCPP_USING_IF_EXISTS; | |
| 80 | using ::mktime _LIBCPP_USING_IF_EXISTS; | |
| 81 | using ::time _LIBCPP_USING_IF_EXISTS; | |
| 82 | 82 | #ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS |
| 83 | using ::asctime; | |
| 84 | using ::ctime; | |
| 85 | using ::gmtime; | |
| 86 | using ::localtime; | |
| 83 | using ::asctime _LIBCPP_USING_IF_EXISTS; | |
| 84 | using ::ctime _LIBCPP_USING_IF_EXISTS; | |
| 85 | using ::gmtime _LIBCPP_USING_IF_EXISTS; | |
| 86 | using ::localtime _LIBCPP_USING_IF_EXISTS; | |
| 87 | 87 | #endif |
| 88 | using ::strftime; | |
| 88 | using ::strftime _LIBCPP_USING_IF_EXISTS; | |
| 89 | 89 | #if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_TIMESPEC_GET) && !defined(_LIBCPP_HAS_TIMESPEC_GET_NOT_ACTUALLY_PROVIDED) |
| 90 | using ::timespec_get; | |
| 90 | using ::timespec_get _LIBCPP_USING_IF_EXISTS; | |
| 91 | 91 | #endif |
| 92 | 92 | |
| 93 | 93 | _LIBCPP_END_NAMESPACE_STD |
| 94 | 94 | |
| 95 | #endif // _LIBCPP_CTIME | |
| 95 | #endif // _LIBCPP_CTIME |
lib/libcxx/include/ctype.h+1-1| ... | ... | @@ -56,4 +56,4 @@ int toupper(int c); |
| 56 | 56 | |
| 57 | 57 | #endif |
| 58 | 58 | |
| 59 | #endif // _LIBCPP_CTYPE_H | |
| 59 | #endif // _LIBCPP_CTYPE_H |
lib/libcxx/include/cwchar+65-65| ... | ... | @@ -112,81 +112,81 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len, |
| 112 | 112 | |
| 113 | 113 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 114 | 114 | |
| 115 | using ::mbstate_t; | |
| 116 | using ::size_t; | |
| 117 | using ::tm; | |
| 118 | using ::wint_t; | |
| 119 | using ::FILE; | |
| 120 | using ::fwprintf; | |
| 121 | using ::fwscanf; | |
| 122 | using ::swprintf; | |
| 123 | using ::vfwprintf; | |
| 124 | using ::vswprintf; | |
| 125 | using ::swscanf; | |
| 126 | using ::vfwscanf; | |
| 127 | using ::vswscanf; | |
| 128 | using ::fgetwc; | |
| 129 | using ::fgetws; | |
| 130 | using ::fputwc; | |
| 131 | using ::fputws; | |
| 132 | using ::fwide; | |
| 133 | using ::getwc; | |
| 134 | using ::putwc; | |
| 135 | using ::ungetwc; | |
| 136 | using ::wcstod; | |
| 137 | using ::wcstof; | |
| 138 | using ::wcstold; | |
| 139 | using ::wcstol; | |
| 115 | using ::mbstate_t _LIBCPP_USING_IF_EXISTS; | |
| 116 | using ::size_t _LIBCPP_USING_IF_EXISTS; | |
| 117 | using ::tm _LIBCPP_USING_IF_EXISTS; | |
| 118 | using ::wint_t _LIBCPP_USING_IF_EXISTS; | |
| 119 | using ::FILE _LIBCPP_USING_IF_EXISTS; | |
| 120 | using ::fwprintf _LIBCPP_USING_IF_EXISTS; | |
| 121 | using ::fwscanf _LIBCPP_USING_IF_EXISTS; | |
| 122 | using ::swprintf _LIBCPP_USING_IF_EXISTS; | |
| 123 | using ::vfwprintf _LIBCPP_USING_IF_EXISTS; | |
| 124 | using ::vswprintf _LIBCPP_USING_IF_EXISTS; | |
| 125 | using ::swscanf _LIBCPP_USING_IF_EXISTS; | |
| 126 | using ::vfwscanf _LIBCPP_USING_IF_EXISTS; | |
| 127 | using ::vswscanf _LIBCPP_USING_IF_EXISTS; | |
| 128 | using ::fgetwc _LIBCPP_USING_IF_EXISTS; | |
| 129 | using ::fgetws _LIBCPP_USING_IF_EXISTS; | |
| 130 | using ::fputwc _LIBCPP_USING_IF_EXISTS; | |
| 131 | using ::fputws _LIBCPP_USING_IF_EXISTS; | |
| 132 | using ::fwide _LIBCPP_USING_IF_EXISTS; | |
| 133 | using ::getwc _LIBCPP_USING_IF_EXISTS; | |
| 134 | using ::putwc _LIBCPP_USING_IF_EXISTS; | |
| 135 | using ::ungetwc _LIBCPP_USING_IF_EXISTS; | |
| 136 | using ::wcstod _LIBCPP_USING_IF_EXISTS; | |
| 137 | using ::wcstof _LIBCPP_USING_IF_EXISTS; | |
| 138 | using ::wcstold _LIBCPP_USING_IF_EXISTS; | |
| 139 | using ::wcstol _LIBCPP_USING_IF_EXISTS; | |
| 140 | 140 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 141 | using ::wcstoll; | |
| 141 | using ::wcstoll _LIBCPP_USING_IF_EXISTS; | |
| 142 | 142 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 143 | using ::wcstoul; | |
| 143 | using ::wcstoul _LIBCPP_USING_IF_EXISTS; | |
| 144 | 144 | #ifndef _LIBCPP_HAS_NO_LONG_LONG |
| 145 | using ::wcstoull; | |
| 145 | using ::wcstoull _LIBCPP_USING_IF_EXISTS; | |
| 146 | 146 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 147 | using ::wcscpy; | |
| 148 | using ::wcsncpy; | |
| 149 | using ::wcscat; | |
| 150 | using ::wcsncat; | |
| 151 | using ::wcscmp; | |
| 152 | using ::wcscoll; | |
| 153 | using ::wcsncmp; | |
| 154 | using ::wcsxfrm; | |
| 155 | using ::wcschr; | |
| 156 | using ::wcspbrk; | |
| 157 | using ::wcsrchr; | |
| 158 | using ::wcsstr; | |
| 159 | using ::wmemchr; | |
| 160 | using ::wcscspn; | |
| 161 | using ::wcslen; | |
| 162 | using ::wcsspn; | |
| 163 | using ::wcstok; | |
| 164 | using ::wmemcmp; | |
| 165 | using ::wmemcpy; | |
| 166 | using ::wmemmove; | |
| 167 | using ::wmemset; | |
| 168 | using ::wcsftime; | |
| 169 | using ::btowc; | |
| 170 | using ::wctob; | |
| 171 | using ::mbsinit; | |
| 172 | using ::mbrlen; | |
| 173 | using ::mbrtowc; | |
| 174 | using ::wcrtomb; | |
| 175 | using ::mbsrtowcs; | |
| 176 | using ::wcsrtombs; | |
| 147 | using ::wcscpy _LIBCPP_USING_IF_EXISTS; | |
| 148 | using ::wcsncpy _LIBCPP_USING_IF_EXISTS; | |
| 149 | using ::wcscat _LIBCPP_USING_IF_EXISTS; | |
| 150 | using ::wcsncat _LIBCPP_USING_IF_EXISTS; | |
| 151 | using ::wcscmp _LIBCPP_USING_IF_EXISTS; | |
| 152 | using ::wcscoll _LIBCPP_USING_IF_EXISTS; | |
| 153 | using ::wcsncmp _LIBCPP_USING_IF_EXISTS; | |
| 154 | using ::wcsxfrm _LIBCPP_USING_IF_EXISTS; | |
| 155 | using ::wcschr _LIBCPP_USING_IF_EXISTS; | |
| 156 | using ::wcspbrk _LIBCPP_USING_IF_EXISTS; | |
| 157 | using ::wcsrchr _LIBCPP_USING_IF_EXISTS; | |
| 158 | using ::wcsstr _LIBCPP_USING_IF_EXISTS; | |
| 159 | using ::wmemchr _LIBCPP_USING_IF_EXISTS; | |
| 160 | using ::wcscspn _LIBCPP_USING_IF_EXISTS; | |
| 161 | using ::wcslen _LIBCPP_USING_IF_EXISTS; | |
| 162 | using ::wcsspn _LIBCPP_USING_IF_EXISTS; | |
| 163 | using ::wcstok _LIBCPP_USING_IF_EXISTS; | |
| 164 | using ::wmemcmp _LIBCPP_USING_IF_EXISTS; | |
| 165 | using ::wmemcpy _LIBCPP_USING_IF_EXISTS; | |
| 166 | using ::wmemmove _LIBCPP_USING_IF_EXISTS; | |
| 167 | using ::wmemset _LIBCPP_USING_IF_EXISTS; | |
| 168 | using ::wcsftime _LIBCPP_USING_IF_EXISTS; | |
| 169 | using ::btowc _LIBCPP_USING_IF_EXISTS; | |
| 170 | using ::wctob _LIBCPP_USING_IF_EXISTS; | |
| 171 | using ::mbsinit _LIBCPP_USING_IF_EXISTS; | |
| 172 | using ::mbrlen _LIBCPP_USING_IF_EXISTS; | |
| 173 | using ::mbrtowc _LIBCPP_USING_IF_EXISTS; | |
| 174 | using ::wcrtomb _LIBCPP_USING_IF_EXISTS; | |
| 175 | using ::mbsrtowcs _LIBCPP_USING_IF_EXISTS; | |
| 176 | using ::wcsrtombs _LIBCPP_USING_IF_EXISTS; | |
| 177 | 177 | |
| 178 | 178 | #ifndef _LIBCPP_HAS_NO_STDIN |
| 179 | using ::getwchar; | |
| 180 | using ::vwscanf; | |
| 181 | using ::wscanf; | |
| 179 | using ::getwchar _LIBCPP_USING_IF_EXISTS; | |
| 180 | using ::vwscanf _LIBCPP_USING_IF_EXISTS; | |
| 181 | using ::wscanf _LIBCPP_USING_IF_EXISTS; | |
| 182 | 182 | #endif |
| 183 | 183 | |
| 184 | 184 | #ifndef _LIBCPP_HAS_NO_STDOUT |
| 185 | using ::putwchar; | |
| 186 | using ::vwprintf; | |
| 187 | using ::wprintf; | |
| 185 | using ::putwchar _LIBCPP_USING_IF_EXISTS; | |
| 186 | using ::vwprintf _LIBCPP_USING_IF_EXISTS; | |
| 187 | using ::wprintf _LIBCPP_USING_IF_EXISTS; | |
| 188 | 188 | #endif |
| 189 | 189 | |
| 190 | 190 | _LIBCPP_END_NAMESPACE_STD |
| 191 | 191 | |
| 192 | #endif // _LIBCPP_CWCHAR | |
| 192 | #endif // _LIBCPP_CWCHAR |
lib/libcxx/include/cwctype+22-22| ... | ... | @@ -59,28 +59,28 @@ wctrans_t wctrans(const char* property); |
| 59 | 59 | |
| 60 | 60 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 61 | 61 | |
| 62 | using ::wint_t; | |
| 63 | using ::wctrans_t; | |
| 64 | using ::wctype_t; | |
| 65 | using ::iswalnum; | |
| 66 | using ::iswalpha; | |
| 67 | using ::iswblank; | |
| 68 | using ::iswcntrl; | |
| 69 | using ::iswdigit; | |
| 70 | using ::iswgraph; | |
| 71 | using ::iswlower; | |
| 72 | using ::iswprint; | |
| 73 | using ::iswpunct; | |
| 74 | using ::iswspace; | |
| 75 | using ::iswupper; | |
| 76 | using ::iswxdigit; | |
| 77 | using ::iswctype; | |
| 78 | using ::wctype; | |
| 79 | using ::towlower; | |
| 80 | using ::towupper; | |
| 81 | using ::towctrans; | |
| 82 | using ::wctrans; | |
| 62 | using ::wint_t _LIBCPP_USING_IF_EXISTS; | |
| 63 | using ::wctrans_t _LIBCPP_USING_IF_EXISTS; | |
| 64 | using ::wctype_t _LIBCPP_USING_IF_EXISTS; | |
| 65 | using ::iswalnum _LIBCPP_USING_IF_EXISTS; | |
| 66 | using ::iswalpha _LIBCPP_USING_IF_EXISTS; | |
| 67 | using ::iswblank _LIBCPP_USING_IF_EXISTS; | |
| 68 | using ::iswcntrl _LIBCPP_USING_IF_EXISTS; | |
| 69 | using ::iswdigit _LIBCPP_USING_IF_EXISTS; | |
| 70 | using ::iswgraph _LIBCPP_USING_IF_EXISTS; | |
| 71 | using ::iswlower _LIBCPP_USING_IF_EXISTS; | |
| 72 | using ::iswprint _LIBCPP_USING_IF_EXISTS; | |
| 73 | using ::iswpunct _LIBCPP_USING_IF_EXISTS; | |
| 74 | using ::iswspace _LIBCPP_USING_IF_EXISTS; | |
| 75 | using ::iswupper _LIBCPP_USING_IF_EXISTS; | |
| 76 | using ::iswxdigit _LIBCPP_USING_IF_EXISTS; | |
| 77 | using ::iswctype _LIBCPP_USING_IF_EXISTS; | |
| 78 | using ::wctype _LIBCPP_USING_IF_EXISTS; | |
| 79 | using ::towlower _LIBCPP_USING_IF_EXISTS; | |
| 80 | using ::towupper _LIBCPP_USING_IF_EXISTS; | |
| 81 | using ::towctrans _LIBCPP_USING_IF_EXISTS; | |
| 82 | using ::wctrans _LIBCPP_USING_IF_EXISTS; | |
| 83 | 83 | |
| 84 | 84 | _LIBCPP_END_NAMESPACE_STD |
| 85 | 85 | |
| 86 | #endif // _LIBCPP_CWCTYPE | |
| 86 | #endif // _LIBCPP_CWCTYPE |
lib/libcxx/include/deque+27-23| ... | ... | @@ -161,12 +161,16 @@ template <class T, class Allocator, class Predicate> |
| 161 | 161 | */ |
| 162 | 162 | |
| 163 | 163 | #include <__config> |
| 164 | #include <__debug> | |
| 164 | 165 | #include <__split_buffer> |
| 165 | #include <type_traits> | |
| 166 | #include <__utility/forward.h> | |
| 167 | #include <algorithm> | |
| 168 | #include <compare> | |
| 166 | 169 | #include <initializer_list> |
| 167 | 170 | #include <iterator> |
| 168 | #include <algorithm> | |
| 171 | #include <limits> | |
| 169 | 172 | #include <stdexcept> |
| 173 | #include <type_traits> | |
| 170 | 174 | #include <version> |
| 171 | 175 | |
| 172 | 176 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -1055,7 +1059,7 @@ public: |
| 1055 | 1059 | __deque_base(__deque_base&& __c) |
| 1056 | 1060 | _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); |
| 1057 | 1061 | __deque_base(__deque_base&& __c, const allocator_type& __a); |
| 1058 | #endif // _LIBCPP_CXX03_LANG | |
| 1062 | #endif // _LIBCPP_CXX03_LANG | |
| 1059 | 1063 | |
| 1060 | 1064 | void swap(__deque_base& __c) |
| 1061 | 1065 | #if _LIBCPP_STD_VER >= 14 |
| ... | ... | @@ -1222,7 +1226,7 @@ __deque_base<_Tp, _Allocator>::__deque_base(__deque_base&& __c, const allocator_ |
| 1222 | 1226 | } |
| 1223 | 1227 | } |
| 1224 | 1228 | |
| 1225 | #endif // _LIBCPP_CXX03_LANG | |
| 1229 | #endif // _LIBCPP_CXX03_LANG | |
| 1226 | 1230 | |
| 1227 | 1231 | template <class _Tp, class _Allocator> |
| 1228 | 1232 | void |
| ... | ... | @@ -1315,7 +1319,7 @@ public: |
| 1315 | 1319 | deque(_InputIter __f, _InputIter __l, const allocator_type& __a, |
| 1316 | 1320 | typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0); |
| 1317 | 1321 | deque(const deque& __c); |
| 1318 | deque(const deque& __c, const allocator_type& __a); | |
| 1322 | deque(const deque& __c, const __identity_t<allocator_type>& __a); | |
| 1319 | 1323 | |
| 1320 | 1324 | deque& operator=(const deque& __c); |
| 1321 | 1325 | |
| ... | ... | @@ -1329,7 +1333,7 @@ public: |
| 1329 | 1333 | _LIBCPP_INLINE_VISIBILITY |
| 1330 | 1334 | deque(deque&& __c) _NOEXCEPT_(is_nothrow_move_constructible<__base>::value); |
| 1331 | 1335 | _LIBCPP_INLINE_VISIBILITY |
| 1332 | deque(deque&& __c, const allocator_type& __a); | |
| 1336 | deque(deque&& __c, const __identity_t<allocator_type>& __a); | |
| 1333 | 1337 | _LIBCPP_INLINE_VISIBILITY |
| 1334 | 1338 | deque& operator=(deque&& __c) |
| 1335 | 1339 | _NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value && |
| ... | ... | @@ -1337,7 +1341,7 @@ public: |
| 1337 | 1341 | |
| 1338 | 1342 | _LIBCPP_INLINE_VISIBILITY |
| 1339 | 1343 | void assign(initializer_list<value_type> __il) {assign(__il.begin(), __il.end());} |
| 1340 | #endif // _LIBCPP_CXX03_LANG | |
| 1344 | #endif // _LIBCPP_CXX03_LANG | |
| 1341 | 1345 | |
| 1342 | 1346 | template <class _InputIter> |
| 1343 | 1347 | void assign(_InputIter __f, _InputIter __l, |
| ... | ... | @@ -1440,7 +1444,7 @@ public: |
| 1440 | 1444 | _LIBCPP_INLINE_VISIBILITY |
| 1441 | 1445 | iterator insert(const_iterator __p, initializer_list<value_type> __il) |
| 1442 | 1446 | {return insert(__p, __il.begin(), __il.end());} |
| 1443 | #endif // _LIBCPP_CXX03_LANG | |
| 1447 | #endif // _LIBCPP_CXX03_LANG | |
| 1444 | 1448 | iterator insert(const_iterator __p, const value_type& __v); |
| 1445 | 1449 | iterator insert(const_iterator __p, size_type __n, const value_type& __v); |
| 1446 | 1450 | template <class _InputIter> |
| ... | ... | @@ -1586,18 +1590,18 @@ public: |
| 1586 | 1590 | |
| 1587 | 1591 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 1588 | 1592 | template<class _InputIterator, |
| 1589 | class _Alloc = allocator<typename iterator_traits<_InputIterator>::value_type>, | |
| 1590 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 1593 | class _Alloc = allocator<__iter_value_type<_InputIterator>>, | |
| 1594 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 1591 | 1595 | > |
| 1592 | 1596 | deque(_InputIterator, _InputIterator) |
| 1593 | -> deque<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 1597 | -> deque<__iter_value_type<_InputIterator>, _Alloc>; | |
| 1594 | 1598 | |
| 1595 | 1599 | template<class _InputIterator, |
| 1596 | 1600 | class _Alloc, |
| 1597 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 1601 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 1598 | 1602 | > |
| 1599 | 1603 | deque(_InputIterator, _InputIterator, _Alloc) |
| 1600 | -> deque<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 1604 | -> deque<__iter_value_type<_InputIterator>, _Alloc>; | |
| 1601 | 1605 | #endif |
| 1602 | 1606 | |
| 1603 | 1607 | |
| ... | ... | @@ -1658,7 +1662,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c) |
| 1658 | 1662 | } |
| 1659 | 1663 | |
| 1660 | 1664 | template <class _Tp, class _Allocator> |
| 1661 | deque<_Tp, _Allocator>::deque(const deque& __c, const allocator_type& __a) | |
| 1665 | deque<_Tp, _Allocator>::deque(const deque& __c, const __identity_t<allocator_type>& __a) | |
| 1662 | 1666 | : __base(__a) |
| 1663 | 1667 | { |
| 1664 | 1668 | __append(__c.begin(), __c.end()); |
| ... | ... | @@ -1701,7 +1705,7 @@ deque<_Tp, _Allocator>::deque(deque&& __c) |
| 1701 | 1705 | |
| 1702 | 1706 | template <class _Tp, class _Allocator> |
| 1703 | 1707 | inline |
| 1704 | deque<_Tp, _Allocator>::deque(deque&& __c, const allocator_type& __a) | |
| 1708 | deque<_Tp, _Allocator>::deque(deque&& __c, const __identity_t<allocator_type>& __a) | |
| 1705 | 1709 | : __base(_VSTD::move(__c), __a) |
| 1706 | 1710 | { |
| 1707 | 1711 | if (__a != __c.__alloc()) |
| ... | ... | @@ -1746,7 +1750,7 @@ deque<_Tp, _Allocator>::__move_assign(deque& __c, true_type) |
| 1746 | 1750 | __base::__move_assign(__c); |
| 1747 | 1751 | } |
| 1748 | 1752 | |
| 1749 | #endif // _LIBCPP_CXX03_LANG | |
| 1753 | #endif // _LIBCPP_CXX03_LANG | |
| 1750 | 1754 | |
| 1751 | 1755 | template <class _Tp, class _Allocator> |
| 1752 | 1756 | template <class _InputIter> |
| ... | ... | @@ -2128,7 +2132,7 @@ deque<_Tp, _Allocator>::emplace(const_iterator __p, _Args&&... __args) |
| 2128 | 2132 | return __base::begin() + __pos; |
| 2129 | 2133 | } |
| 2130 | 2134 | |
| 2131 | #endif // _LIBCPP_CXX03_LANG | |
| 2135 | #endif // _LIBCPP_CXX03_LANG | |
| 2132 | 2136 | |
| 2133 | 2137 | |
| 2134 | 2138 | template <class _Tp, class _Allocator> |
| ... | ... | @@ -2532,7 +2536,7 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) |
| 2532 | 2536 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2533 | 2537 | try |
| 2534 | 2538 | { |
| 2535 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2539 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2536 | 2540 | for (; __nb > 0; --__nb) |
| 2537 | 2541 | __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); |
| 2538 | 2542 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2544,7 +2548,7 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) |
| 2544 | 2548 | __alloc_traits::deallocate(__a, *__i, __base::__block_size); |
| 2545 | 2549 | throw; |
| 2546 | 2550 | } |
| 2547 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2551 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2548 | 2552 | for (; __back_capacity > 0; --__back_capacity) |
| 2549 | 2553 | { |
| 2550 | 2554 | __buf.push_back(__base::__map_.back()); |
| ... | ... | @@ -2674,7 +2678,7 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) |
| 2674 | 2678 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2675 | 2679 | try |
| 2676 | 2680 | { |
| 2677 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2681 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2678 | 2682 | for (; __nb > 0; --__nb) |
| 2679 | 2683 | __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); |
| 2680 | 2684 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2686,7 +2690,7 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) |
| 2686 | 2690 | __alloc_traits::deallocate(__a, *__i, __base::__block_size); |
| 2687 | 2691 | throw; |
| 2688 | 2692 | } |
| 2689 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2693 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2690 | 2694 | for (; __front_capacity > 0; --__front_capacity) |
| 2691 | 2695 | { |
| 2692 | 2696 | __buf.push_back(__base::__map_.front()); |
| ... | ... | @@ -2720,7 +2724,7 @@ template <class _Tp, class _Allocator> |
| 2720 | 2724 | void |
| 2721 | 2725 | deque<_Tp, _Allocator>::pop_back() |
| 2722 | 2726 | { |
| 2723 | _LIBCPP_ASSERT(!empty(), "deque::pop_back called for empty deque"); | |
| 2727 | _LIBCPP_ASSERT(!empty(), "deque::pop_back called on an empty deque"); | |
| 2724 | 2728 | allocator_type& __a = __base::__alloc(); |
| 2725 | 2729 | size_type __p = __base::size() + __base::__start_ - 1; |
| 2726 | 2730 | __alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() + |
| ... | ... | @@ -3044,4 +3048,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 3044 | 3048 | |
| 3045 | 3049 | _LIBCPP_POP_MACROS |
| 3046 | 3050 | |
| 3047 | #endif // _LIBCPP_DEQUE | |
| 3051 | #endif // _LIBCPP_DEQUE |
lib/libcxx/include/errno.h+3-3| ... | ... | @@ -72,9 +72,9 @@ static const int __elast2 = 105; |
| 72 | 72 | #define ELAST ENOTRECOVERABLE |
| 73 | 73 | #endif |
| 74 | 74 | |
| 75 | #endif // defined(EOWNERDEAD) | |
| 75 | #endif // defined(EOWNERDEAD) | |
| 76 | 76 | |
| 77 | #endif // !defined(EOWNERDEAD) || !defined(ENOTRECOVERABLE) | |
| 77 | #endif // !defined(EOWNERDEAD) || !defined(ENOTRECOVERABLE) | |
| 78 | 78 | |
| 79 | 79 | // supply errno values likely to be missing, particularly on Windows |
| 80 | 80 | |
| ... | ... | @@ -394,4 +394,4 @@ static const int __elast2 = 105; |
| 394 | 394 | |
| 395 | 395 | #endif // __cplusplus |
| 396 | 396 | |
| 397 | #endif // _LIBCPP_ERRNO_H | |
| 397 | #endif // _LIBCPP_ERRNO_H |
lib/libcxx/include/exception+9-9| ... | ... | @@ -76,9 +76,9 @@ template <class E> void rethrow_if_nested(const E& e); |
| 76 | 76 | |
| 77 | 77 | */ |
| 78 | 78 | |
| 79 | #include <__config> | |
| 80 | 79 | #include <__availability> |
| 81 | #include <__memory/base.h> | |
| 80 | #include <__config> | |
| 81 | #include <__memory/addressof.h> | |
| 82 | 82 | #include <cstddef> |
| 83 | 83 | #include <cstdlib> |
| 84 | 84 | #include <type_traits> |
| ... | ... | @@ -151,7 +151,7 @@ public: |
| 151 | 151 | exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; |
| 152 | 152 | ~exception_ptr() _NOEXCEPT; |
| 153 | 153 | |
| 154 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT | |
| 154 | _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT | |
| 155 | 155 | {return __ptr_ != nullptr;} |
| 156 | 156 | |
| 157 | 157 | friend _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -205,7 +205,7 @@ public: |
| 205 | 205 | exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; |
| 206 | 206 | exception_ptr& operator=(nullptr_t) _NOEXCEPT; |
| 207 | 207 | ~exception_ptr() _NOEXCEPT; |
| 208 | _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT; | |
| 208 | explicit operator bool() const _NOEXCEPT; | |
| 209 | 209 | }; |
| 210 | 210 | |
| 211 | 211 | _LIBCPP_FUNC_VIS |
| ... | ... | @@ -266,7 +266,7 @@ struct __throw_with_nested<_Tp, _Up, true> { |
| 266 | 266 | _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void |
| 267 | 267 | __do_throw(_Tp&& __t) |
| 268 | 268 | { |
| 269 | throw __nested<_Up>(_VSTD::forward<_Tp>(__t)); | |
| 269 | throw __nested<_Up>(static_cast<_Tp&&>(__t)); | |
| 270 | 270 | } |
| 271 | 271 | }; |
| 272 | 272 | |
| ... | ... | @@ -277,9 +277,9 @@ struct __throw_with_nested<_Tp, _Up, false> { |
| 277 | 277 | __do_throw(_Tp&& __t) |
| 278 | 278 | #else |
| 279 | 279 | __do_throw (_Tp& __t) |
| 280 | #endif // _LIBCPP_CXX03_LANG | |
| 280 | #endif // _LIBCPP_CXX03_LANG | |
| 281 | 281 | { |
| 282 | throw _VSTD::forward<_Tp>(__t); | |
| 282 | throw static_cast<_Tp&&>(__t); | |
| 283 | 283 | } |
| 284 | 284 | }; |
| 285 | 285 | #endif |
| ... | ... | @@ -296,7 +296,7 @@ throw_with_nested(_Tp&& __t) |
| 296 | 296 | is_class<_Up>::value && |
| 297 | 297 | !is_base_of<nested_exception, _Up>::value && |
| 298 | 298 | !__libcpp_is_final<_Up>::value>:: |
| 299 | __do_throw(_VSTD::forward<_Tp>(__t)); | |
| 299 | __do_throw(static_cast<_Tp&&>(__t)); | |
| 300 | 300 | #else |
| 301 | 301 | ((void)__t); |
| 302 | 302 | // FIXME: Make this abort |
| ... | ... | @@ -330,4 +330,4 @@ rethrow_if_nested(const _Ep&, |
| 330 | 330 | |
| 331 | 331 | } // std |
| 332 | 332 | |
| 333 | #endif // _LIBCPP_EXCEPTION | |
| 333 | #endif // _LIBCPP_EXCEPTION |
lib/libcxx/include/experimental/__config-4| ... | ... | @@ -32,10 +32,6 @@ |
| 32 | 32 | #define _LIBCPP_END_NAMESPACE_LFTS_PMR _LIBCPP_END_NAMESPACE_LFTS } |
| 33 | 33 | #define _VSTD_LFTS_PMR _VSTD_LFTS::pmr |
| 34 | 34 | |
| 35 | #define _LIBCPP_BEGIN_NAMESPACE_CHRONO_LFTS _LIBCPP_BEGIN_NAMESPACE_STD \ | |
| 36 | namespace chrono { namespace experimental { inline namespace fundamentals_v1 { | |
| 37 | #define _LIBCPP_END_NAMESPACE_CHRONO_LFTS _LIBCPP_END_NAMESPACE_STD } } } | |
| 38 | ||
| 39 | 35 | #if defined(_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_FILESYSTEM) |
| 40 | 36 | # define _LIBCPP_DEPRECATED_EXPERIMENTAL_FILESYSTEM /* nothing */ |
| 41 | 37 | #else |
lib/libcxx/include/experimental/__memory+26-1| ... | ... | @@ -10,6 +10,8 @@ |
| 10 | 10 | #ifndef _LIBCPP_EXPERIMENTAL___MEMORY |
| 11 | 11 | #define _LIBCPP_EXPERIMENTAL___MEMORY |
| 12 | 12 | |
| 13 | #include <__memory/allocator_arg_t.h> | |
| 14 | #include <__memory/uses_allocator.h> | |
| 13 | 15 | #include <experimental/__config> |
| 14 | 16 | #include <experimental/utility> // for erased_type |
| 15 | 17 | #include <__functional_base> |
| ... | ... | @@ -73,12 +75,35 @@ struct __lfts_uses_alloc_ctor |
| 73 | 75 | > |
| 74 | 76 | {}; |
| 75 | 77 | |
| 78 | template <class _Tp, class _Allocator, class... _Args> | |
| 79 | inline _LIBCPP_INLINE_VISIBILITY | |
| 80 | void __user_alloc_construct_impl (integral_constant<int, 0>, _Tp *__storage, const _Allocator &, _Args &&... __args ) | |
| 81 | { | |
| 82 | new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); | |
| 83 | } | |
| 84 | ||
| 85 | // FIXME: This should have a version which takes a non-const alloc. | |
| 86 | template <class _Tp, class _Allocator, class... _Args> | |
| 87 | inline _LIBCPP_INLINE_VISIBILITY | |
| 88 | void __user_alloc_construct_impl (integral_constant<int, 1>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) | |
| 89 | { | |
| 90 | new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); | |
| 91 | } | |
| 92 | ||
| 93 | // FIXME: This should have a version which takes a non-const alloc. | |
| 94 | template <class _Tp, class _Allocator, class... _Args> | |
| 95 | inline _LIBCPP_INLINE_VISIBILITY | |
| 96 | void __user_alloc_construct_impl (integral_constant<int, 2>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) | |
| 97 | { | |
| 98 | new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); | |
| 99 | } | |
| 100 | ||
| 76 | 101 | template <class _Tp, class _Alloc, class ..._Args> |
| 77 | 102 | inline _LIBCPP_INLINE_VISIBILITY |
| 78 | 103 | void __lfts_user_alloc_construct( |
| 79 | 104 | _Tp * __store, const _Alloc & __a, _Args &&... __args) |
| 80 | 105 | { |
| 81 | _VSTD::__user_alloc_construct_impl( | |
| 106 | ::std::experimental::fundamentals_v1::__user_alloc_construct_impl( | |
| 82 | 107 | typename __lfts_uses_alloc_ctor<_Tp, _Alloc, _Args...>::type() |
| 83 | 108 | , __store, __a, _VSTD::forward<_Args>(__args)... |
| 84 | 109 | ); |
lib/libcxx/include/experimental/functional+23-22| ... | ... | @@ -86,6 +86,7 @@ inline namespace fundamentals_v1 { |
| 86 | 86 | |
| 87 | 87 | */ |
| 88 | 88 | |
| 89 | #include <__memory/uses_allocator.h> | |
| 89 | 90 | #include <experimental/__config> |
| 90 | 91 | #include <functional> |
| 91 | 92 | #include <algorithm> |
| ... | ... | @@ -109,7 +110,7 @@ _LIBCPP_BEGIN_NAMESPACE_LFTS |
| 109 | 110 | #if _LIBCPP_STD_VER > 11 |
| 110 | 111 | // default searcher |
| 111 | 112 | template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> |
| 112 | class _LIBCPP_TYPE_VIS default_searcher { | |
| 113 | class _LIBCPP_TEMPLATE_VIS default_searcher { | |
| 113 | 114 | public: |
| 114 | 115 | _LIBCPP_INLINE_VISIBILITY |
| 115 | 116 | default_searcher(_ForwardIterator __f, _ForwardIterator __l, |
| ... | ... | @@ -122,8 +123,8 @@ public: |
| 122 | 123 | operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const |
| 123 | 124 | { |
| 124 | 125 | return _VSTD::__search(__f, __l, __first_, __last_, __pred_, |
| 125 | typename _VSTD::iterator_traits<_ForwardIterator>::iterator_category(), | |
| 126 | typename _VSTD::iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 126 | typename iterator_traits<_ForwardIterator>::iterator_category(), | |
| 127 | typename iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 127 | 128 | } |
| 128 | 129 | |
| 129 | 130 | private: |
| ... | ... | @@ -154,7 +155,7 @@ public: // TODO private: |
| 154 | 155 | |
| 155 | 156 | public: |
| 156 | 157 | _LIBCPP_INLINE_VISIBILITY |
| 157 | _BMSkipTable(std::size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred) | |
| 158 | _BMSkipTable(size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred) | |
| 158 | 159 | : __default_value_(__default), __table(__sz, __hf, __pred) {} |
| 159 | 160 | |
| 160 | 161 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -179,13 +180,13 @@ private: |
| 179 | 180 | typedef _Value value_type; |
| 180 | 181 | typedef _Key key_type; |
| 181 | 182 | |
| 182 | typedef typename std::make_unsigned<key_type>::type unsigned_key_type; | |
| 183 | typedef std::array<value_type, _VSTD::numeric_limits<unsigned_key_type>::max()> skip_map; | |
| 183 | typedef typename make_unsigned<key_type>::type unsigned_key_type; | |
| 184 | typedef std::array<value_type, numeric_limits<unsigned_key_type>::max()> skip_map; | |
| 184 | 185 | skip_map __table; |
| 185 | 186 | |
| 186 | 187 | public: |
| 187 | 188 | _LIBCPP_INLINE_VISIBILITY |
| 188 | _BMSkipTable(std::size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/) | |
| 189 | _BMSkipTable(size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/) | |
| 189 | 190 | { |
| 190 | 191 | std::fill_n(__table.begin(), __table.size(), __default); |
| 191 | 192 | } |
| ... | ... | @@ -207,12 +208,12 @@ public: |
| 207 | 208 | template <class _RandomAccessIterator1, |
| 208 | 209 | class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, |
| 209 | 210 | class _BinaryPredicate = equal_to<>> |
| 210 | class _LIBCPP_TYPE_VIS boyer_moore_searcher { | |
| 211 | class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher { | |
| 211 | 212 | private: |
| 212 | 213 | typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type; |
| 213 | 214 | typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type; |
| 214 | 215 | typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate, |
| 215 | _VSTD::is_integral<value_type>::value && // what about enums? | |
| 216 | is_integral<value_type>::value && // what about enums? | |
| 216 | 217 | sizeof(value_type) == 1 && |
| 217 | 218 | is_same<_Hash, hash<value_type>>::value && |
| 218 | 219 | is_same<_BinaryPredicate, equal_to<>>::value |
| ... | ... | @@ -247,7 +248,7 @@ public: |
| 247 | 248 | if (__first_ == __last_) return make_pair(__f, __f); // empty pattern |
| 248 | 249 | |
| 249 | 250 | // If the pattern is larger than the corpus, we can't find it! |
| 250 | if ( __pattern_length_ > _VSTD::distance (__f, __l)) | |
| 251 | if ( __pattern_length_ > _VSTD::distance(__f, __l)) | |
| 251 | 252 | return make_pair(__l, __l); |
| 252 | 253 | |
| 253 | 254 | // Do the search |
| ... | ... | @@ -299,11 +300,11 @@ public: // TODO private: |
| 299 | 300 | template<typename _Iterator, typename _Container> |
| 300 | 301 | void __compute_bm_prefix ( _Iterator __f, _Iterator __l, _BinaryPredicate __pred, _Container &__prefix ) |
| 301 | 302 | { |
| 302 | const std::size_t __count = _VSTD::distance(__f, __l); | |
| 303 | const size_t __count = _VSTD::distance(__f, __l); | |
| 303 | 304 | |
| 304 | 305 | __prefix[0] = 0; |
| 305 | std::size_t __k = 0; | |
| 306 | for ( std::size_t __i = 1; __i < __count; ++__i ) | |
| 306 | size_t __k = 0; | |
| 307 | for ( size_t __i = 1; __i < __count; ++__i ) | |
| 307 | 308 | { |
| 308 | 309 | while ( __k > 0 && !__pred ( __f[__k], __f[__i] )) |
| 309 | 310 | __k = __prefix [ __k - 1 ]; |
| ... | ... | @@ -317,22 +318,22 @@ public: // TODO private: |
| 317 | 318 | void __build_suffix_table(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, |
| 318 | 319 | _BinaryPredicate __pred) |
| 319 | 320 | { |
| 320 | const std::size_t __count = _VSTD::distance(__f, __l); | |
| 321 | const size_t __count = _VSTD::distance(__f, __l); | |
| 321 | 322 | vector<difference_type> & __suffix = *__suffix_.get(); |
| 322 | 323 | if (__count > 0) |
| 323 | 324 | { |
| 324 | _VSTD::vector<value_type> __scratch(__count); | |
| 325 | vector<value_type> __scratch(__count); | |
| 325 | 326 | |
| 326 | 327 | __compute_bm_prefix(__f, __l, __pred, __scratch); |
| 327 | for ( std::size_t __i = 0; __i <= __count; __i++ ) | |
| 328 | for ( size_t __i = 0; __i <= __count; __i++ ) | |
| 328 | 329 | __suffix[__i] = __count - __scratch[__count-1]; |
| 329 | 330 | |
| 330 | typedef _VSTD::reverse_iterator<_RandomAccessIterator1> _RevIter; | |
| 331 | typedef reverse_iterator<_RandomAccessIterator1> _RevIter; | |
| 331 | 332 | __compute_bm_prefix(_RevIter(__l), _RevIter(__f), __pred, __scratch); |
| 332 | 333 | |
| 333 | for ( std::size_t __i = 0; __i < __count; __i++ ) | |
| 334 | for ( size_t __i = 0; __i < __count; __i++ ) | |
| 334 | 335 | { |
| 335 | const std::size_t __j = __count - __scratch[__i]; | |
| 336 | const size_t __j = __count - __scratch[__i]; | |
| 336 | 337 | const difference_type __k = __i - __scratch[__i] + 1; |
| 337 | 338 | |
| 338 | 339 | if (__suffix[__j] > __k) |
| ... | ... | @@ -358,12 +359,12 @@ make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l, |
| 358 | 359 | template <class _RandomAccessIterator1, |
| 359 | 360 | class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, |
| 360 | 361 | class _BinaryPredicate = equal_to<>> |
| 361 | class _LIBCPP_TYPE_VIS boyer_moore_horspool_searcher { | |
| 362 | class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher { | |
| 362 | 363 | private: |
| 363 | 364 | typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type; |
| 364 | 365 | typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type; |
| 365 | 366 | typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate, |
| 366 | _VSTD::is_integral<value_type>::value && // what about enums? | |
| 367 | is_integral<value_type>::value && // what about enums? | |
| 367 | 368 | sizeof(value_type) == 1 && |
| 368 | 369 | is_same<_Hash, hash<value_type>>::value && |
| 369 | 370 | is_same<_BinaryPredicate, equal_to<>>::value |
| ... | ... | @@ -399,7 +400,7 @@ public: |
| 399 | 400 | if (__first_ == __last_) return make_pair(__f, __f); // empty pattern |
| 400 | 401 | |
| 401 | 402 | // If the pattern is larger than the corpus, we can't find it! |
| 402 | if ( __pattern_length_ > _VSTD::distance (__f, __l)) | |
| 403 | if ( __pattern_length_ > _VSTD::distance(__f, __l)) | |
| 403 | 404 | return make_pair(__l, __l); |
| 404 | 405 | |
| 405 | 406 | // Do the search |
lib/libcxx/include/experimental/iterator+3| ... | ... | @@ -56,6 +56,9 @@ namespace std { |
| 56 | 56 | |
| 57 | 57 | #if _LIBCPP_STD_VER > 11 |
| 58 | 58 | |
| 59 | #include <__memory/addressof.h> | |
| 60 | #include <__utility/move.h> | |
| 61 | #include <__utility/forward.h> | |
| 59 | 62 | #include <iterator> |
| 60 | 63 | |
| 61 | 64 | _LIBCPP_BEGIN_NAMESPACE_LFTS |
lib/libcxx/include/experimental/propagate_const+1-1| ... | ... | @@ -135,7 +135,7 @@ template <class _Tp> |
| 135 | 135 | class propagate_const |
| 136 | 136 | { |
| 137 | 137 | public: |
| 138 | typedef remove_reference_t<decltype(*_VSTD::declval<_Tp&>())> element_type; | |
| 138 | typedef remove_reference_t<decltype(*declval<_Tp&>())> element_type; | |
| 139 | 139 | |
| 140 | 140 | static_assert(!is_array<_Tp>::value, |
| 141 | 141 | "Instantiation of propagate_const with an array type is ill-formed."); |
lib/libcxx/include/experimental/simd+2-2| ... | ... | @@ -725,12 +725,12 @@ constexpr size_t __ceil_pow_of_2(size_t __val) { |
| 725 | 725 | |
| 726 | 726 | template <class _Tp, size_t __bytes> |
| 727 | 727 | struct __vec_ext_traits { |
| 728 | #if !defined(_LIBCPP_COMPILER_CLANG) | |
| 728 | #if !defined(_LIBCPP_COMPILER_CLANG_BASED) | |
| 729 | 729 | typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes)))); |
| 730 | 730 | #endif |
| 731 | 731 | }; |
| 732 | 732 | |
| 733 | #if defined(_LIBCPP_COMPILER_CLANG) | |
| 733 | #if defined(_LIBCPP_COMPILER_CLANG_BASED) | |
| 734 | 734 | #define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ |
| 735 | 735 | template <> \ |
| 736 | 736 | struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ |
lib/libcxx/include/experimental/type_traits+1-1| ... | ... | @@ -105,7 +105,7 @@ using raw_invocation_type_t = typename raw_invocation_type<_Tp>::type; |
| 105 | 105 | // 3.3.4, Detection idiom |
| 106 | 106 | template <class...> using void_t = void; |
| 107 | 107 | |
| 108 | struct nonesuch : private _VSTD::__nat { // make nonesuch "not an aggregate" | |
| 108 | struct nonesuch : private __nat { // make nonesuch "not an aggregate" | |
| 109 | 109 | ~nonesuch() = delete; |
| 110 | 110 | nonesuch (nonesuch const&) = delete; |
| 111 | 111 | void operator=(nonesuch const&) = delete; |
lib/libcxx/include/ext/__hash+2-1| ... | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | |
| 13 | 13 | #pragma GCC system_header |
| 14 | 14 | |
| 15 | #include <__string> | |
| 15 | 16 | #include <string> |
| 16 | 17 | #include <cstring> |
| 17 | 18 | |
| ... | ... | @@ -130,4 +131,4 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<unsigned long> |
| 130 | 131 | }; |
| 131 | 132 | } |
| 132 | 133 | |
| 133 | #endif // _LIBCPP_EXT_HASH | |
| 134 | #endif // _LIBCPP_EXT_HASH |
lib/libcxx/include/ext/hash_map+3-3| ... | ... | @@ -208,7 +208,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc> |
| 208 | 208 | #include <type_traits> |
| 209 | 209 | #include <ext/__hash> |
| 210 | 210 | |
| 211 | #if __DEPRECATED | |
| 211 | #if defined(__DEPRECATED) && __DEPRECATED | |
| 212 | 212 | #if defined(_LIBCPP_WARNING) |
| 213 | 213 | _LIBCPP_WARNING("Use of the header <ext/hash_map> is deprecated. Migrate to <unordered_map>") |
| 214 | 214 | #else |
| ... | ... | @@ -350,7 +350,7 @@ public: |
| 350 | 350 | { |
| 351 | 351 | const_cast<bool&>(__x.__value_constructed) = false; |
| 352 | 352 | } |
| 353 | #endif // _LIBCPP_CXX03_LANG | |
| 353 | #endif // _LIBCPP_CXX03_LANG | |
| 354 | 354 | |
| 355 | 355 | _LIBCPP_INLINE_VISIBILITY |
| 356 | 356 | void operator()(pointer __p) |
| ... | ... | @@ -981,4 +981,4 @@ operator!=(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, |
| 981 | 981 | |
| 982 | 982 | } // __gnu_cxx |
| 983 | 983 | |
| 984 | #endif // _LIBCPP_HASH_MAP | |
| 984 | #endif // _LIBCPP_HASH_MAP |
lib/libcxx/include/ext/hash_set+2-2| ... | ... | @@ -197,7 +197,7 @@ template <class Value, class Hash, class Pred, class Alloc> |
| 197 | 197 | #include <functional> |
| 198 | 198 | #include <ext/__hash> |
| 199 | 199 | |
| 200 | #if __DEPRECATED | |
| 200 | #if defined(__DEPRECATED) && __DEPRECATED | |
| 201 | 201 | #if defined(_LIBCPP_WARNING) |
| 202 | 202 | _LIBCPP_WARNING("Use of the header <ext/hash_set> is deprecated. Migrate to <unordered_set>") |
| 203 | 203 | #else |
| ... | ... | @@ -656,4 +656,4 @@ operator!=(const hash_multiset<_Value, _Hash, _Pred, _Alloc>& __x, |
| 656 | 656 | |
| 657 | 657 | } // __gnu_cxx |
| 658 | 658 | |
| 659 | #endif // _LIBCPP_HASH_SET | |
| 659 | #endif // _LIBCPP_HASH_SET |
lib/libcxx/include/filesystem+111-31| ... | ... | @@ -229,19 +229,22 @@ |
| 229 | 229 | |
| 230 | 230 | */ |
| 231 | 231 | |
| 232 | #include <__config> | |
| 233 | 232 | #include <__availability> |
| 233 | #include <__config> | |
| 234 | #include <__debug> | |
| 235 | #include <__utility/forward.h> | |
| 236 | #include <chrono> | |
| 237 | #include <compare> | |
| 234 | 238 | #include <cstddef> |
| 235 | 239 | #include <cstdlib> |
| 236 | #include <chrono> | |
| 237 | #include <iterator> | |
| 238 | 240 | #include <iosfwd> |
| 241 | #include <iterator> | |
| 239 | 242 | #include <memory> |
| 240 | 243 | #include <stack> |
| 241 | 244 | #include <string> |
| 245 | #include <string_view> | |
| 242 | 246 | #include <system_error> |
| 243 | 247 | #include <utility> |
| 244 | #include <string_view> | |
| 245 | 248 | #include <version> |
| 246 | 249 | |
| 247 | 250 | #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) |
| ... | ... | @@ -249,8 +252,6 @@ |
| 249 | 252 | # include <iomanip> // for quoted |
| 250 | 253 | #endif |
| 251 | 254 | |
| 252 | #include <__debug> | |
| 253 | ||
| 254 | 255 | #if defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) |
| 255 | 256 | # error "The Filesystem library is not supported by this configuration of libc++" |
| 256 | 257 | #endif |
| ... | ... | @@ -276,6 +277,8 @@ struct _LIBCPP_TYPE_VIS space_info { |
| 276 | 277 | uintmax_t available; |
| 277 | 278 | }; |
| 278 | 279 | |
| 280 | // On Windows, the library never identifies files as block, character, fifo | |
| 281 | // or socket. | |
| 279 | 282 | enum class _LIBCPP_ENUM_VIS file_type : signed char { |
| 280 | 283 | none = 0, |
| 281 | 284 | not_found = -1, |
| ... | ... | @@ -289,6 +292,10 @@ enum class _LIBCPP_ENUM_VIS file_type : signed char { |
| 289 | 292 | unknown = 8 |
| 290 | 293 | }; |
| 291 | 294 | |
| 295 | // On Windows, these permission bits map to one single readonly flag per | |
| 296 | // file, and the executable bit is always returned as set. When setting | |
| 297 | // permissions, as long as the write bit is set for either owner, group or | |
| 298 | // others, the readonly flag is cleared. | |
| 292 | 299 | enum class _LIBCPP_ENUM_VIS perms : unsigned { |
| 293 | 300 | none = 0, |
| 294 | 301 | |
| ... | ... | @@ -551,7 +558,7 @@ struct __can_convert_char<wchar_t> { |
| 551 | 558 | static const bool value = true; |
| 552 | 559 | using __char_type = wchar_t; |
| 553 | 560 | }; |
| 554 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 561 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 555 | 562 | template <> |
| 556 | 563 | struct __can_convert_char<char8_t> { |
| 557 | 564 | static const bool value = true; |
| ... | ... | @@ -579,7 +586,7 @@ __is_separator(_ECharT __e) { |
| 579 | 586 | #endif |
| 580 | 587 | } |
| 581 | 588 | |
| 582 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 589 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 583 | 590 | typedef u8string __u8_string; |
| 584 | 591 | #else |
| 585 | 592 | typedef string __u8_string; |
| ... | ... | @@ -785,7 +792,7 @@ struct _PathCVT<__path_value> { |
| 785 | 792 | template <class _Iter> |
| 786 | 793 | static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type |
| 787 | 794 | __append_range(__path_string& __dest, _Iter __b, _Iter __e) { |
| 788 | __dest.__append_forward_unsafe(__b, __e); | |
| 795 | __dest.append(__b, __e); | |
| 789 | 796 | } |
| 790 | 797 | |
| 791 | 798 | template <class _Iter> |
| ... | ... | @@ -886,7 +893,7 @@ struct _PathExport<char16_t> { |
| 886 | 893 | } |
| 887 | 894 | }; |
| 888 | 895 | |
| 889 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 896 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 890 | 897 | template <> |
| 891 | 898 | struct _PathExport<char8_t> { |
| 892 | 899 | typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower; |
| ... | ... | @@ -896,7 +903,7 @@ struct _PathExport<char8_t> { |
| 896 | 903 | _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size()); |
| 897 | 904 | } |
| 898 | 905 | }; |
| 899 | #endif /* !_LIBCPP_NO_HAS_CHAR8_T */ | |
| 906 | #endif /* !_LIBCPP_HAS_NO_CHAR8_T */ | |
| 900 | 907 | #endif /* _LIBCPP_WIN32API */ |
| 901 | 908 | |
| 902 | 909 | class _LIBCPP_TYPE_VIS path { |
| ... | ... | @@ -921,7 +928,7 @@ public: |
| 921 | 928 | typedef basic_string<value_type> string_type; |
| 922 | 929 | typedef basic_string_view<value_type> __string_view; |
| 923 | 930 | |
| 924 | enum class _LIBCPP_ENUM_VIS format : unsigned char { | |
| 931 | enum _LIBCPP_ENUM_VIS format : unsigned char { | |
| 925 | 932 | auto_format, |
| 926 | 933 | native_format, |
| 927 | 934 | generic_format |
| ... | ... | @@ -973,8 +980,8 @@ public: |
| 973 | 980 | return *this; |
| 974 | 981 | } |
| 975 | 982 | |
| 976 | template <class = void> | |
| 977 | _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept { | |
| 983 | _LIBCPP_INLINE_VISIBILITY | |
| 984 | path& operator=(string_type&& __s) noexcept { | |
| 978 | 985 | __pn_ = _VSTD::move(__s); |
| 979 | 986 | return *this; |
| 980 | 987 | } |
| ... | ... | @@ -1006,14 +1013,44 @@ public: |
| 1006 | 1013 | return *this; |
| 1007 | 1014 | } |
| 1008 | 1015 | |
| 1009 | private: | |
| 1010 | template <class _ECharT> | |
| 1011 | static bool __source_is_absolute(_ECharT __first_or_null) { | |
| 1012 | return __is_separator(__first_or_null); | |
| 1013 | } | |
| 1014 | ||
| 1015 | 1016 | public: |
| 1016 | 1017 | // appends |
| 1018 | #if defined(_LIBCPP_WIN32API) | |
| 1019 | path& operator/=(const path& __p) { | |
| 1020 | auto __p_root_name = __p.__root_name(); | |
| 1021 | auto __p_root_name_size = __p_root_name.size(); | |
| 1022 | if (__p.is_absolute() || | |
| 1023 | (!__p_root_name.empty() && __p_root_name != root_name())) { | |
| 1024 | __pn_ = __p.__pn_; | |
| 1025 | return *this; | |
| 1026 | } | |
| 1027 | if (__p.has_root_directory()) { | |
| 1028 | path __root_name_str = root_name(); | |
| 1029 | __pn_ = __root_name_str.native(); | |
| 1030 | __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); | |
| 1031 | return *this; | |
| 1032 | } | |
| 1033 | if (has_filename() || (!has_root_directory() && is_absolute())) | |
| 1034 | __pn_ += preferred_separator; | |
| 1035 | __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size); | |
| 1036 | return *this; | |
| 1037 | } | |
| 1038 | template <class _Source> | |
| 1039 | _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> | |
| 1040 | operator/=(const _Source& __src) { | |
| 1041 | return operator/=(path(__src)); | |
| 1042 | } | |
| 1043 | ||
| 1044 | template <class _Source> | |
| 1045 | _EnableIfPathable<_Source> append(const _Source& __src) { | |
| 1046 | return operator/=(path(__src)); | |
| 1047 | } | |
| 1048 | ||
| 1049 | template <class _InputIt> | |
| 1050 | path& append(_InputIt __first, _InputIt __last) { | |
| 1051 | return operator/=(path(__first, __last)); | |
| 1052 | } | |
| 1053 | #else | |
| 1017 | 1054 | path& operator/=(const path& __p) { |
| 1018 | 1055 | if (__p.is_absolute()) { |
| 1019 | 1056 | __pn_ = __p.__pn_; |
| ... | ... | @@ -1038,7 +1075,8 @@ public: |
| 1038 | 1075 | _EnableIfPathable<_Source> append(const _Source& __src) { |
| 1039 | 1076 | using _Traits = __is_pathable<_Source>; |
| 1040 | 1077 | using _CVT = _PathCVT<_SourceChar<_Source> >; |
| 1041 | if (__source_is_absolute(_Traits::__first_or_null(__src))) | |
| 1078 | bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src)); | |
| 1079 | if (__source_is_absolute) | |
| 1042 | 1080 | __pn_.clear(); |
| 1043 | 1081 | else if (has_filename()) |
| 1044 | 1082 | __pn_ += preferred_separator; |
| ... | ... | @@ -1051,13 +1089,14 @@ public: |
| 1051 | 1089 | typedef typename iterator_traits<_InputIt>::value_type _ItVal; |
| 1052 | 1090 | static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); |
| 1053 | 1091 | using _CVT = _PathCVT<_ItVal>; |
| 1054 | if (__first != __last && __source_is_absolute(*__first)) | |
| 1092 | if (__first != __last && __is_separator(*__first)) | |
| 1055 | 1093 | __pn_.clear(); |
| 1056 | 1094 | else if (has_filename()) |
| 1057 | 1095 | __pn_ += preferred_separator; |
| 1058 | 1096 | _CVT::__append_range(__pn_, __first, __last); |
| 1059 | 1097 | return *this; |
| 1060 | 1098 | } |
| 1099 | #endif | |
| 1061 | 1100 | |
| 1062 | 1101 | // concatenation |
| 1063 | 1102 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1161,7 +1200,12 @@ public: |
| 1161 | 1200 | #if defined(_LIBCPP_WIN32API) |
| 1162 | 1201 | _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; } |
| 1163 | 1202 | |
| 1164 | _VSTD::wstring generic_wstring() const { return __pn_; } | |
| 1203 | _VSTD::wstring generic_wstring() const { | |
| 1204 | _VSTD::wstring __s; | |
| 1205 | __s.resize(__pn_.size()); | |
| 1206 | _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/'); | |
| 1207 | return __s; | |
| 1208 | } | |
| 1165 | 1209 | |
| 1166 | 1210 | #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) |
| 1167 | 1211 | template <class _ECharT, class _Traits = char_traits<_ECharT>, |
| ... | ... | @@ -1198,18 +1242,29 @@ public: |
| 1198 | 1242 | class _Allocator = allocator<_ECharT> > |
| 1199 | 1243 | basic_string<_ECharT, _Traits, _Allocator> |
| 1200 | 1244 | generic_string(const _Allocator& __a = _Allocator()) const { |
| 1201 | return string<_ECharT, _Traits, _Allocator>(__a); | |
| 1245 | using _Str = basic_string<_ECharT, _Traits, _Allocator>; | |
| 1246 | _Str __s = string<_ECharT, _Traits, _Allocator>(__a); | |
| 1247 | // Note: This (and generic_u8string below) is slightly suboptimal as | |
| 1248 | // it iterates twice over the string; once to convert it to the right | |
| 1249 | // character type, and once to replace path delimiters. | |
| 1250 | _VSTD::replace(__s.begin(), __s.end(), | |
| 1251 | static_cast<_ECharT>('\\'), static_cast<_ECharT>('/')); | |
| 1252 | return __s; | |
| 1202 | 1253 | } |
| 1203 | 1254 | |
| 1204 | 1255 | _VSTD::string generic_string() const { return generic_string<char>(); } |
| 1205 | 1256 | _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); } |
| 1206 | 1257 | _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); } |
| 1207 | __u8_string generic_u8string() const { return u8string(); } | |
| 1258 | __u8_string generic_u8string() const { | |
| 1259 | __u8_string __s = u8string(); | |
| 1260 | _VSTD::replace(__s.begin(), __s.end(), '\\', '/'); | |
| 1261 | return __s; | |
| 1262 | } | |
| 1208 | 1263 | #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ |
| 1209 | 1264 | #else /* _LIBCPP_WIN32API */ |
| 1210 | 1265 | |
| 1211 | 1266 | _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; } |
| 1212 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1267 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1213 | 1268 | _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } |
| 1214 | 1269 | #else |
| 1215 | 1270 | _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; } |
| ... | ... | @@ -1241,7 +1296,7 @@ public: |
| 1241 | 1296 | |
| 1242 | 1297 | // generic format observers |
| 1243 | 1298 | _VSTD::string generic_string() const { return __pn_; } |
| 1244 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1299 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1245 | 1300 | _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); } |
| 1246 | 1301 | #else |
| 1247 | 1302 | _VSTD::string generic_u8string() const { return __pn_; } |
| ... | ... | @@ -1295,7 +1350,11 @@ public: |
| 1295 | 1350 | return string_type(__root_directory()); |
| 1296 | 1351 | } |
| 1297 | 1352 | _LIBCPP_INLINE_VISIBILITY path root_path() const { |
| 1353 | #if defined(_LIBCPP_WIN32API) | |
| 1354 | return string_type(__root_path_raw()); | |
| 1355 | #else | |
| 1298 | 1356 | return root_name().append(string_type(__root_directory())); |
| 1357 | #endif | |
| 1299 | 1358 | } |
| 1300 | 1359 | _LIBCPP_INLINE_VISIBILITY path relative_path() const { |
| 1301 | 1360 | return string_type(__relative_path()); |
| ... | ... | @@ -1341,7 +1400,28 @@ public: |
| 1341 | 1400 | } |
| 1342 | 1401 | |
| 1343 | 1402 | _LIBCPP_INLINE_VISIBILITY bool is_absolute() const { |
| 1403 | #if defined(_LIBCPP_WIN32API) | |
| 1404 | __string_view __root_name_str = __root_name(); | |
| 1405 | __string_view __root_dir = __root_directory(); | |
| 1406 | if (__root_name_str.size() == 2 && __root_name_str[1] == ':') { | |
| 1407 | // A drive letter with no root directory is relative, e.g. x:example. | |
| 1408 | return !__root_dir.empty(); | |
| 1409 | } | |
| 1410 | // If no root name, it's relative, e.g. \example is relative to the current drive | |
| 1411 | if (__root_name_str.empty()) | |
| 1412 | return false; | |
| 1413 | if (__root_name_str.size() < 3) | |
| 1414 | return false; | |
| 1415 | // A server root name, like \\server, is always absolute | |
| 1416 | if (__root_name_str[0] != '/' && __root_name_str[0] != '\\') | |
| 1417 | return false; | |
| 1418 | if (__root_name_str[1] != '/' && __root_name_str[1] != '\\') | |
| 1419 | return false; | |
| 1420 | // Seems to be a server root name | |
| 1421 | return true; | |
| 1422 | #else | |
| 1344 | 1423 | return has_root_directory(); |
| 1424 | #endif | |
| 1345 | 1425 | } |
| 1346 | 1426 | _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); } |
| 1347 | 1427 | |
| ... | ... | @@ -1440,7 +1520,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T |
| 1440 | 1520 | typename enable_if<__is_pathable<_InputIt>::value, path>::type |
| 1441 | 1521 | u8path(_InputIt __f, _InputIt __l) { |
| 1442 | 1522 | static_assert( |
| 1443 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1523 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1444 | 1524 | is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value || |
| 1445 | 1525 | #endif |
| 1446 | 1526 | is_same<typename __is_pathable<_InputIt>::__char_type, char>::value, |
| ... | ... | @@ -1464,7 +1544,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T |
| 1464 | 1544 | typename enable_if<__is_pathable<_InputIt>::value, path>::type |
| 1465 | 1545 | u8path(_InputIt __f, _NullSentinel) { |
| 1466 | 1546 | static_assert( |
| 1467 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1547 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1468 | 1548 | is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value || |
| 1469 | 1549 | #endif |
| 1470 | 1550 | is_same<typename __is_pathable<_InputIt>::__char_type, char>::value, |
| ... | ... | @@ -1487,7 +1567,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T |
| 1487 | 1567 | typename enable_if<__is_pathable<_Source>::value, path>::type |
| 1488 | 1568 | u8path(const _Source& __s) { |
| 1489 | 1569 | static_assert( |
| 1490 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1570 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 1491 | 1571 | is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value || |
| 1492 | 1572 | #endif |
| 1493 | 1573 | is_same<typename __is_pathable<_Source>::__char_type, char>::value, |
| ... | ... | @@ -1495,7 +1575,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T |
| 1495 | 1575 | "'char' or 'char8_t'"); |
| 1496 | 1576 | #if defined(_LIBCPP_WIN32API) |
| 1497 | 1577 | using _Traits = __is_pathable<_Source>; |
| 1498 | return u8path(__unwrap_iter(_Traits::__range_begin(__s)), __unwrap_iter(_Traits::__range_end(__s))); | |
| 1578 | return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s))); | |
| 1499 | 1579 | #else |
| 1500 | 1580 | return path(__s); |
| 1501 | 1581 | #endif |
lib/libcxx/include/float.h+1-1| ... | ... | @@ -90,4 +90,4 @@ Macros: |
| 90 | 90 | |
| 91 | 91 | #endif // __cplusplus |
| 92 | 92 | |
| 93 | #endif // _LIBCPP_FLOAT_H | |
| 93 | #endif // _LIBCPP_FLOAT_H |
lib/libcxx/include/format created+86| ... | ... | @@ -0,0 +1,86 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===--------------------------- format -----------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP_FORMAT | |
| 11 | #define _LIBCPP_FORMAT | |
| 12 | ||
| 13 | /* | |
| 14 | ||
| 15 | namespace std { | |
| 16 | // [format.error], class format_error | |
| 17 | class format_error : public runtime_error { | |
| 18 | public: | |
| 19 | explicit format_error(const string& what_arg); | |
| 20 | explicit format_error(const char* what_arg); | |
| 21 | }; | |
| 22 | ||
| 23 | // [format.parse.ctx], class template basic_format_parse_context | |
| 24 | template<class charT> | |
| 25 | class basic_format_parse_context { | |
| 26 | public: | |
| 27 | using char_type = charT; | |
| 28 | using const_iterator = typename basic_string_view<charT>::const_iterator; | |
| 29 | using iterator = const_iterator; | |
| 30 | ||
| 31 | private: | |
| 32 | iterator begin_; // exposition only | |
| 33 | iterator end_; // exposition only | |
| 34 | enum indexing { unknown, manual, automatic }; // exposition only | |
| 35 | indexing indexing_; // exposition only | |
| 36 | size_t next_arg_id_; // exposition only | |
| 37 | size_t num_args_; // exposition only | |
| 38 | ||
| 39 | public: | |
| 40 | constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt, | |
| 41 | size_t num_args = 0) noexcept; | |
| 42 | basic_format_parse_context(const basic_format_parse_context&) = delete; | |
| 43 | basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; | |
| 44 | ||
| 45 | constexpr const_iterator begin() const noexcept; | |
| 46 | constexpr const_iterator end() const noexcept; | |
| 47 | constexpr void advance_to(const_iterator it); | |
| 48 | ||
| 49 | constexpr size_t next_arg_id(); | |
| 50 | constexpr void check_arg_id(size_t id); | |
| 51 | }; | |
| 52 | using format_parse_context = basic_format_parse_context<char>; | |
| 53 | using wformat_parse_context = basic_format_parse_context<wchar_t>; | |
| 54 | } | |
| 55 | ||
| 56 | */ | |
| 57 | ||
| 58 | // Make sure all feature tests macros are always available. | |
| 59 | #include <version> | |
| 60 | // Only enable the contents of the header when libc++ was build with LIBCXX_ENABLE_INCOMPLETE_FEATURES enabled | |
| 61 | #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) | |
| 62 | ||
| 63 | #include <__config> | |
| 64 | #include <__format/format_error.h> | |
| 65 | #include <__format/format_parse_context.h> | |
| 66 | ||
| 67 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 68 | # pragma GCC system_header | |
| 69 | #endif | |
| 70 | ||
| 71 | _LIBCPP_PUSH_MACROS | |
| 72 | #include <__undef_macros> | |
| 73 | ||
| 74 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 75 | ||
| 76 | #if _LIBCPP_STD_VER > 17 | |
| 77 | ||
| 78 | #endif //_LIBCPP_STD_VER > 17 | |
| 79 | ||
| 80 | _LIBCPP_END_NAMESPACE_STD | |
| 81 | ||
| 82 | _LIBCPP_POP_MACROS | |
| 83 | ||
| 84 | #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) | |
| 85 | ||
| 86 | #endif // _LIBCPP_FORMAT |
lib/libcxx/include/forward_list+31-30| ... | ... | @@ -180,11 +180,12 @@ template <class T, class Allocator, class Predicate> |
| 180 | 180 | */ |
| 181 | 181 | |
| 182 | 182 | #include <__config> |
| 183 | #include <__utility/forward.h> | |
| 184 | #include <algorithm> | |
| 183 | 185 | #include <initializer_list> |
| 184 | #include <memory> | |
| 185 | #include <limits> | |
| 186 | 186 | #include <iterator> |
| 187 | #include <algorithm> | |
| 187 | #include <limits> | |
| 188 | #include <memory> | |
| 188 | 189 | #include <version> |
| 189 | 190 | |
| 190 | 191 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -272,7 +273,7 @@ struct _LIBCPP_HIDDEN __begin_node_of |
| 272 | 273 | }; |
| 273 | 274 | |
| 274 | 275 | template <class _Tp, class _VoidPtr> |
| 275 | struct __forward_list_node | |
| 276 | struct _LIBCPP_STANDALONE_DEBUG __forward_list_node | |
| 276 | 277 | : public __begin_node_of<_Tp, _VoidPtr>::type |
| 277 | 278 | { |
| 278 | 279 | typedef _Tp value_type; |
| ... | ... | @@ -506,7 +507,7 @@ public: |
| 506 | 507 | _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value); |
| 507 | 508 | _LIBCPP_INLINE_VISIBILITY |
| 508 | 509 | __forward_list_base(__forward_list_base&& __x, const allocator_type& __a); |
| 509 | #endif // _LIBCPP_CXX03_LANG | |
| 510 | #endif // _LIBCPP_CXX03_LANG | |
| 510 | 511 | |
| 511 | 512 | private: |
| 512 | 513 | __forward_list_base(const __forward_list_base&); |
| ... | ... | @@ -534,7 +535,7 @@ public: |
| 534 | 535 | #if _LIBCPP_STD_VER >= 14 |
| 535 | 536 | _NOEXCEPT; |
| 536 | 537 | #else |
| 537 | _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || | |
| 538 | _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || | |
| 538 | 539 | __is_nothrow_swappable<__node_allocator>::value); |
| 539 | 540 | #endif |
| 540 | 541 | protected: |
| ... | ... | @@ -584,7 +585,7 @@ __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x, |
| 584 | 585 | } |
| 585 | 586 | } |
| 586 | 587 | |
| 587 | #endif // _LIBCPP_CXX03_LANG | |
| 588 | #endif // _LIBCPP_CXX03_LANG | |
| 588 | 589 | |
| 589 | 590 | template <class _Tp, class _Alloc> |
| 590 | 591 | __forward_list_base<_Tp, _Alloc>::~__forward_list_base() |
| ... | ... | @@ -599,7 +600,7 @@ __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x) |
| 599 | 600 | #if _LIBCPP_STD_VER >= 14 |
| 600 | 601 | _NOEXCEPT |
| 601 | 602 | #else |
| 602 | _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || | |
| 603 | _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || | |
| 603 | 604 | __is_nothrow_swappable<__node_allocator>::value) |
| 604 | 605 | #endif |
| 605 | 606 | { |
| ... | ... | @@ -681,7 +682,7 @@ public: |
| 681 | 682 | __is_cpp17_input_iterator<_InputIterator>::value |
| 682 | 683 | >::type* = nullptr); |
| 683 | 684 | forward_list(const forward_list& __x); |
| 684 | forward_list(const forward_list& __x, const allocator_type& __a); | |
| 685 | forward_list(const forward_list& __x, const __identity_t<allocator_type>& __a); | |
| 685 | 686 | |
| 686 | 687 | forward_list& operator=(const forward_list& __x); |
| 687 | 688 | |
| ... | ... | @@ -690,7 +691,7 @@ public: |
| 690 | 691 | forward_list(forward_list&& __x) |
| 691 | 692 | _NOEXCEPT_(is_nothrow_move_constructible<base>::value) |
| 692 | 693 | : base(_VSTD::move(__x)) {} |
| 693 | forward_list(forward_list&& __x, const allocator_type& __a); | |
| 694 | forward_list(forward_list&& __x, const __identity_t<allocator_type>& __a); | |
| 694 | 695 | |
| 695 | 696 | forward_list(initializer_list<value_type> __il); |
| 696 | 697 | forward_list(initializer_list<value_type> __il, const allocator_type& __a); |
| ... | ... | @@ -706,7 +707,7 @@ public: |
| 706 | 707 | |
| 707 | 708 | _LIBCPP_INLINE_VISIBILITY |
| 708 | 709 | void assign(initializer_list<value_type> __il); |
| 709 | #endif // _LIBCPP_CXX03_LANG | |
| 710 | #endif // _LIBCPP_CXX03_LANG | |
| 710 | 711 | |
| 711 | 712 | // ~forward_list() = default; |
| 712 | 713 | |
| ... | ... | @@ -775,7 +776,7 @@ public: |
| 775 | 776 | template <class... _Args> void emplace_front(_Args&&... __args); |
| 776 | 777 | #endif |
| 777 | 778 | void push_front(value_type&& __v); |
| 778 | #endif // _LIBCPP_CXX03_LANG | |
| 779 | #endif // _LIBCPP_CXX03_LANG | |
| 779 | 780 | void push_front(const value_type& __v); |
| 780 | 781 | |
| 781 | 782 | void pop_front(); |
| ... | ... | @@ -787,7 +788,7 @@ public: |
| 787 | 788 | iterator insert_after(const_iterator __p, value_type&& __v); |
| 788 | 789 | iterator insert_after(const_iterator __p, initializer_list<value_type> __il) |
| 789 | 790 | {return insert_after(__p, __il.begin(), __il.end());} |
| 790 | #endif // _LIBCPP_CXX03_LANG | |
| 791 | #endif // _LIBCPP_CXX03_LANG | |
| 791 | 792 | iterator insert_after(const_iterator __p, const value_type& __v); |
| 792 | 793 | iterator insert_after(const_iterator __p, size_type __n, const value_type& __v); |
| 793 | 794 | template <class _InputIterator> |
| ... | ... | @@ -840,7 +841,7 @@ public: |
| 840 | 841 | _LIBCPP_INLINE_VISIBILITY |
| 841 | 842 | void merge(forward_list&& __x, _Compare __comp) |
| 842 | 843 | {merge(__x, _VSTD::move(__comp));} |
| 843 | #endif // _LIBCPP_CXX03_LANG | |
| 844 | #endif // _LIBCPP_CXX03_LANG | |
| 844 | 845 | _LIBCPP_INLINE_VISIBILITY |
| 845 | 846 | void merge(forward_list& __x) {merge(__x, __less<value_type>());} |
| 846 | 847 | template <class _Compare> void merge(forward_list& __x, _Compare __comp); |
| ... | ... | @@ -855,7 +856,7 @@ private: |
| 855 | 856 | void __move_assign(forward_list& __x, true_type) |
| 856 | 857 | _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); |
| 857 | 858 | void __move_assign(forward_list& __x, false_type); |
| 858 | #endif // _LIBCPP_CXX03_LANG | |
| 859 | #endif // _LIBCPP_CXX03_LANG | |
| 859 | 860 | |
| 860 | 861 | template <class _Compare> |
| 861 | 862 | static |
| ... | ... | @@ -871,18 +872,18 @@ private: |
| 871 | 872 | |
| 872 | 873 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 873 | 874 | template<class _InputIterator, |
| 874 | class _Alloc = allocator<typename iterator_traits<_InputIterator>::value_type>, | |
| 875 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 875 | class _Alloc = allocator<__iter_value_type<_InputIterator>>, | |
| 876 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 876 | 877 | > |
| 877 | 878 | forward_list(_InputIterator, _InputIterator) |
| 878 | -> forward_list<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 879 | -> forward_list<__iter_value_type<_InputIterator>, _Alloc>; | |
| 879 | 880 | |
| 880 | 881 | template<class _InputIterator, |
| 881 | 882 | class _Alloc, |
| 882 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 883 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 883 | 884 | > |
| 884 | 885 | forward_list(_InputIterator, _InputIterator, _Alloc) |
| 885 | -> forward_list<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 886 | -> forward_list<__iter_value_type<_InputIterator>, _Alloc>; | |
| 886 | 887 | #endif |
| 887 | 888 | |
| 888 | 889 | template <class _Tp, class _Alloc> |
| ... | ... | @@ -979,7 +980,7 @@ forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x) |
| 979 | 980 | |
| 980 | 981 | template <class _Tp, class _Alloc> |
| 981 | 982 | forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x, |
| 982 | const allocator_type& __a) | |
| 983 | const __identity_t<allocator_type>& __a) | |
| 983 | 984 | : base(__a) |
| 984 | 985 | { |
| 985 | 986 | insert_after(cbefore_begin(), __x.begin(), __x.end()); |
| ... | ... | @@ -1000,7 +1001,7 @@ forward_list<_Tp, _Alloc>::operator=(const forward_list& __x) |
| 1000 | 1001 | #ifndef _LIBCPP_CXX03_LANG |
| 1001 | 1002 | template <class _Tp, class _Alloc> |
| 1002 | 1003 | forward_list<_Tp, _Alloc>::forward_list(forward_list&& __x, |
| 1003 | const allocator_type& __a) | |
| 1004 | const __identity_t<allocator_type>& __a) | |
| 1004 | 1005 | : base(_VSTD::move(__x), __a) |
| 1005 | 1006 | { |
| 1006 | 1007 | if (base::__alloc() != __x.__alloc()) |
| ... | ... | @@ -1070,7 +1071,7 @@ forward_list<_Tp, _Alloc>::operator=(initializer_list<value_type> __il) |
| 1070 | 1071 | return *this; |
| 1071 | 1072 | } |
| 1072 | 1073 | |
| 1073 | #endif // _LIBCPP_CXX03_LANG | |
| 1074 | #endif // _LIBCPP_CXX03_LANG | |
| 1074 | 1075 | |
| 1075 | 1076 | template <class _Tp, class _Alloc> |
| 1076 | 1077 | template <class _InputIterator> |
| ... | ... | @@ -1150,7 +1151,7 @@ forward_list<_Tp, _Alloc>::push_front(value_type&& __v) |
| 1150 | 1151 | base::__before_begin()->__next_ = __h.release(); |
| 1151 | 1152 | } |
| 1152 | 1153 | |
| 1153 | #endif // _LIBCPP_CXX03_LANG | |
| 1154 | #endif // _LIBCPP_CXX03_LANG | |
| 1154 | 1155 | |
| 1155 | 1156 | template <class _Tp, class _Alloc> |
| 1156 | 1157 | void |
| ... | ... | @@ -1207,7 +1208,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, value_type&& __v) |
| 1207 | 1208 | return iterator(__r->__next_); |
| 1208 | 1209 | } |
| 1209 | 1210 | |
| 1210 | #endif // _LIBCPP_CXX03_LANG | |
| 1211 | #endif // _LIBCPP_CXX03_LANG | |
| 1211 | 1212 | |
| 1212 | 1213 | template <class _Tp, class _Alloc> |
| 1213 | 1214 | typename forward_list<_Tp, _Alloc>::iterator |
| ... | ... | @@ -1240,7 +1241,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n, |
| 1240 | 1241 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1241 | 1242 | try |
| 1242 | 1243 | { |
| 1243 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1244 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1244 | 1245 | for (--__n; __n != 0; --__n, __last = __last->__next_) |
| 1245 | 1246 | { |
| 1246 | 1247 | __h.reset(__node_traits::allocate(__a, 1)); |
| ... | ... | @@ -1260,7 +1261,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n, |
| 1260 | 1261 | } |
| 1261 | 1262 | throw; |
| 1262 | 1263 | } |
| 1263 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1264 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1264 | 1265 | __last->__next_ = __r->__next_; |
| 1265 | 1266 | __r->__next_ = __first; |
| 1266 | 1267 | __r = static_cast<__begin_node_pointer>(__last); |
| ... | ... | @@ -1290,7 +1291,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, |
| 1290 | 1291 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1291 | 1292 | try |
| 1292 | 1293 | { |
| 1293 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1294 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1294 | 1295 | for (++__f; __f != __l; ++__f, ((void)(__last = __last->__next_))) |
| 1295 | 1296 | { |
| 1296 | 1297 | __h.reset(__node_traits::allocate(__a, 1)); |
| ... | ... | @@ -1310,7 +1311,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, |
| 1310 | 1311 | } |
| 1311 | 1312 | throw; |
| 1312 | 1313 | } |
| 1313 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1314 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1314 | 1315 | __last->__next_ = __r->__next_; |
| 1315 | 1316 | __r->__next_ = __first; |
| 1316 | 1317 | __r = static_cast<__begin_node_pointer>(__last); |
| ... | ... | @@ -1784,4 +1785,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 1784 | 1785 | |
| 1785 | 1786 | _LIBCPP_POP_MACROS |
| 1786 | 1787 | |
| 1787 | #endif // _LIBCPP_FORWARD_LIST | |
| 1788 | #endif // _LIBCPP_FORWARD_LIST |
lib/libcxx/include/fstream+15-36| ... | ... | @@ -179,13 +179,14 @@ typedef basic_fstream<wchar_t> wfstream; |
| 179 | 179 | |
| 180 | 180 | */ |
| 181 | 181 | |
| 182 | #include <__config> | |
| 183 | 182 | #include <__availability> |
| 184 | #include <ostream> | |
| 185 | #include <istream> | |
| 183 | #include <__config> | |
| 184 | #include <__debug> | |
| 186 | 185 | #include <__locale> |
| 187 | 186 | #include <cstdio> |
| 188 | 187 | #include <cstdlib> |
| 188 | #include <istream> | |
| 189 | #include <ostream> | |
| 189 | 190 | |
| 190 | 191 | #if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) |
| 191 | 192 | # include <filesystem> |
| ... | ... | @@ -198,6 +199,9 @@ typedef basic_fstream<wchar_t> wfstream; |
| 198 | 199 | _LIBCPP_PUSH_MACROS |
| 199 | 200 | #include <__undef_macros> |
| 200 | 201 | |
| 202 | #if defined(_LIBCPP_MSVCRT) || defined(_NEWLIB_VERSION) | |
| 203 | # define _LIBCPP_HAS_NO_OFF_T_FUNCTIONS | |
| 204 | #endif | |
| 201 | 205 | |
| 202 | 206 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 203 | 207 | |
| ... | ... | @@ -215,16 +219,12 @@ public: |
| 215 | 219 | |
| 216 | 220 | // 27.9.1.2 Constructors/destructor: |
| 217 | 221 | basic_filebuf(); |
| 218 | #ifndef _LIBCPP_CXX03_LANG | |
| 219 | 222 | basic_filebuf(basic_filebuf&& __rhs); |
| 220 | #endif | |
| 221 | 223 | virtual ~basic_filebuf(); |
| 222 | 224 | |
| 223 | 225 | // 27.9.1.3 Assign/swap: |
| 224 | #ifndef _LIBCPP_CXX03_LANG | |
| 225 | 226 | _LIBCPP_INLINE_VISIBILITY |
| 226 | 227 | basic_filebuf& operator=(basic_filebuf&& __rhs); |
| 227 | #endif | |
| 228 | 228 | void swap(basic_filebuf& __rhs); |
| 229 | 229 | |
| 230 | 230 | // 27.9.1.4 Members: |
| ... | ... | @@ -244,7 +244,7 @@ public: |
| 244 | 244 | return open(__p.c_str(), __mode); |
| 245 | 245 | } |
| 246 | 246 | #endif |
| 247 | inline _LIBCPP_INLINE_VISIBILITY | |
| 247 | _LIBCPP_INLINE_VISIBILITY | |
| 248 | 248 | basic_filebuf* __open(int __fd, ios_base::openmode __mode); |
| 249 | 249 | #endif |
| 250 | 250 | basic_filebuf* close(); |
| ... | ... | @@ -314,8 +314,6 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf() |
| 314 | 314 | setbuf(nullptr, 4096); |
| 315 | 315 | } |
| 316 | 316 | |
| 317 | #ifndef _LIBCPP_CXX03_LANG | |
| 318 | ||
| 319 | 317 | template <class _CharT, class _Traits> |
| 320 | 318 | basic_filebuf<_CharT, _Traits>::basic_filebuf(basic_filebuf&& __rhs) |
| 321 | 319 | : basic_streambuf<_CharT, _Traits>(__rhs) |
| ... | ... | @@ -390,22 +388,20 @@ basic_filebuf<_CharT, _Traits>::operator=(basic_filebuf&& __rhs) |
| 390 | 388 | return *this; |
| 391 | 389 | } |
| 392 | 390 | |
| 393 | #endif // _LIBCPP_CXX03_LANG | |
| 394 | ||
| 395 | 391 | template <class _CharT, class _Traits> |
| 396 | 392 | basic_filebuf<_CharT, _Traits>::~basic_filebuf() |
| 397 | 393 | { |
| 398 | 394 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 399 | 395 | try |
| 400 | 396 | { |
| 401 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 397 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 402 | 398 | close(); |
| 403 | 399 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 404 | 400 | } |
| 405 | 401 | catch (...) |
| 406 | 402 | { |
| 407 | 403 | } |
| 408 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 404 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 409 | 405 | if (__owns_eb_) |
| 410 | 406 | delete [] __extbuf_; |
| 411 | 407 | if (__owns_ib_) |
| ... | ... | @@ -574,7 +570,7 @@ basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) |
| 574 | 570 | } |
| 575 | 571 | |
| 576 | 572 | template <class _CharT, class _Traits> |
| 577 | inline _LIBCPP_INLINE_VISIBILITY | |
| 573 | inline | |
| 578 | 574 | basic_filebuf<_CharT, _Traits>* |
| 579 | 575 | basic_filebuf<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) { |
| 580 | 576 | basic_filebuf<_CharT, _Traits>* __rt = nullptr; |
| ... | ... | @@ -1160,13 +1156,10 @@ public: |
| 1160 | 1156 | : basic_ifstream(__p.c_str(), __mode) {} |
| 1161 | 1157 | #endif // _LIBCPP_STD_VER >= 17 |
| 1162 | 1158 | #endif |
| 1163 | #ifndef _LIBCPP_CXX03_LANG | |
| 1164 | 1159 | _LIBCPP_INLINE_VISIBILITY |
| 1165 | 1160 | basic_ifstream(basic_ifstream&& __rhs); |
| 1166 | ||
| 1167 | 1161 | _LIBCPP_INLINE_VISIBILITY |
| 1168 | 1162 | basic_ifstream& operator=(basic_ifstream&& __rhs); |
| 1169 | #endif | |
| 1170 | 1163 | _LIBCPP_INLINE_VISIBILITY |
| 1171 | 1164 | void swap(basic_ifstream& __rhs); |
| 1172 | 1165 | |
| ... | ... | @@ -1236,8 +1229,6 @@ basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_base::ope |
| 1236 | 1229 | } |
| 1237 | 1230 | #endif |
| 1238 | 1231 | |
| 1239 | #ifndef _LIBCPP_CXX03_LANG | |
| 1240 | ||
| 1241 | 1232 | template <class _CharT, class _Traits> |
| 1242 | 1233 | inline |
| 1243 | 1234 | basic_ifstream<_CharT, _Traits>::basic_ifstream(basic_ifstream&& __rhs) |
| ... | ... | @@ -1257,8 +1248,6 @@ basic_ifstream<_CharT, _Traits>::operator=(basic_ifstream&& __rhs) |
| 1257 | 1248 | return *this; |
| 1258 | 1249 | } |
| 1259 | 1250 | |
| 1260 | #endif // _LIBCPP_CXX03_LANG | |
| 1261 | ||
| 1262 | 1251 | template <class _CharT, class _Traits> |
| 1263 | 1252 | inline |
| 1264 | 1253 | void |
| ... | ... | @@ -1326,6 +1315,7 @@ basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo |
| 1326 | 1315 | } |
| 1327 | 1316 | |
| 1328 | 1317 | template <class _CharT, class _Traits> |
| 1318 | inline | |
| 1329 | 1319 | void basic_ifstream<_CharT, _Traits>::__open(int __fd, |
| 1330 | 1320 | ios_base::openmode __mode) { |
| 1331 | 1321 | if (__sb_.__open(__fd, __mode | ios_base::in)) |
| ... | ... | @@ -1374,13 +1364,10 @@ public: |
| 1374 | 1364 | : basic_ofstream(__p.c_str(), __mode) {} |
| 1375 | 1365 | #endif // _LIBCPP_STD_VER >= 17 |
| 1376 | 1366 | |
| 1377 | #ifndef _LIBCPP_CXX03_LANG | |
| 1378 | 1367 | _LIBCPP_INLINE_VISIBILITY |
| 1379 | 1368 | basic_ofstream(basic_ofstream&& __rhs); |
| 1380 | ||
| 1381 | 1369 | _LIBCPP_INLINE_VISIBILITY |
| 1382 | 1370 | basic_ofstream& operator=(basic_ofstream&& __rhs); |
| 1383 | #endif | |
| 1384 | 1371 | _LIBCPP_INLINE_VISIBILITY |
| 1385 | 1372 | void swap(basic_ofstream& __rhs); |
| 1386 | 1373 | |
| ... | ... | @@ -1449,8 +1436,6 @@ basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_base::ope |
| 1449 | 1436 | } |
| 1450 | 1437 | #endif |
| 1451 | 1438 | |
| 1452 | #ifndef _LIBCPP_CXX03_LANG | |
| 1453 | ||
| 1454 | 1439 | template <class _CharT, class _Traits> |
| 1455 | 1440 | inline |
| 1456 | 1441 | basic_ofstream<_CharT, _Traits>::basic_ofstream(basic_ofstream&& __rhs) |
| ... | ... | @@ -1470,8 +1455,6 @@ basic_ofstream<_CharT, _Traits>::operator=(basic_ofstream&& __rhs) |
| 1470 | 1455 | return *this; |
| 1471 | 1456 | } |
| 1472 | 1457 | |
| 1473 | #endif // _LIBCPP_CXX03_LANG | |
| 1474 | ||
| 1475 | 1458 | template <class _CharT, class _Traits> |
| 1476 | 1459 | inline |
| 1477 | 1460 | void |
| ... | ... | @@ -1539,6 +1522,7 @@ basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo |
| 1539 | 1522 | } |
| 1540 | 1523 | |
| 1541 | 1524 | template <class _CharT, class _Traits> |
| 1525 | inline | |
| 1542 | 1526 | void basic_ofstream<_CharT, _Traits>::__open(int __fd, |
| 1543 | 1527 | ios_base::openmode __mode) { |
| 1544 | 1528 | if (__sb_.__open(__fd, __mode | ios_base::out)) |
| ... | ... | @@ -1589,13 +1573,12 @@ public: |
| 1589 | 1573 | #endif // _LIBCPP_STD_VER >= 17 |
| 1590 | 1574 | |
| 1591 | 1575 | #endif |
| 1592 | #ifndef _LIBCPP_CXX03_LANG | |
| 1593 | 1576 | _LIBCPP_INLINE_VISIBILITY |
| 1594 | 1577 | basic_fstream(basic_fstream&& __rhs); |
| 1595 | 1578 | |
| 1596 | 1579 | _LIBCPP_INLINE_VISIBILITY |
| 1597 | 1580 | basic_fstream& operator=(basic_fstream&& __rhs); |
| 1598 | #endif | |
| 1581 | ||
| 1599 | 1582 | _LIBCPP_INLINE_VISIBILITY |
| 1600 | 1583 | void swap(basic_fstream& __rhs); |
| 1601 | 1584 | |
| ... | ... | @@ -1662,8 +1645,6 @@ basic_fstream<_CharT, _Traits>::basic_fstream(const string& __s, ios_base::openm |
| 1662 | 1645 | } |
| 1663 | 1646 | #endif |
| 1664 | 1647 | |
| 1665 | #ifndef _LIBCPP_CXX03_LANG | |
| 1666 | ||
| 1667 | 1648 | template <class _CharT, class _Traits> |
| 1668 | 1649 | inline |
| 1669 | 1650 | basic_fstream<_CharT, _Traits>::basic_fstream(basic_fstream&& __rhs) |
| ... | ... | @@ -1683,8 +1664,6 @@ basic_fstream<_CharT, _Traits>::operator=(basic_fstream&& __rhs) |
| 1683 | 1664 | return *this; |
| 1684 | 1665 | } |
| 1685 | 1666 | |
| 1686 | #endif // _LIBCPP_CXX03_LANG | |
| 1687 | ||
| 1688 | 1667 | template <class _CharT, class _Traits> |
| 1689 | 1668 | inline |
| 1690 | 1669 | void |
| ... | ... | @@ -1771,4 +1750,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 1771 | 1750 | |
| 1772 | 1751 | _LIBCPP_POP_MACROS |
| 1773 | 1752 | |
| 1774 | #endif // _LIBCPP_FSTREAM | |
| 1753 | #endif // _LIBCPP_FSTREAM |
lib/libcxx/include/functional+64-2722| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // -*- C++ -*- |
| 2 | //===------------------------ functional ----------------------------------===// | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | 3 | // |
| 4 | 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 5 | 5 | // See https://llvm.org/LICENSE.txt for license information. |
| ... | ... | @@ -42,8 +42,8 @@ public: |
| 42 | 42 | typedef see below result_type; // Not always defined |
| 43 | 43 | |
| 44 | 44 | // construct/copy/destroy |
| 45 | reference_wrapper(T&) noexcept; | |
| 46 | reference_wrapper(T&&) = delete; // do not bind to temps | |
| 45 | template<class U> | |
| 46 | reference_wrapper(U&&); | |
| 47 | 47 | reference_wrapper(const reference_wrapper<T>& x) noexcept; |
| 48 | 48 | |
| 49 | 49 | // assignment |
| ... | ... | @@ -59,6 +59,9 @@ public: |
| 59 | 59 | operator() (ArgTypes&&...) const; |
| 60 | 60 | }; |
| 61 | 61 | |
| 62 | template <class T> | |
| 63 | reference_wrapper(T&) -> reference_wrapper<T>; | |
| 64 | ||
| 62 | 65 | template <class T> reference_wrapper<T> ref(T& t) noexcept; |
| 63 | 66 | template <class T> void ref(const T&& t) = delete; |
| 64 | 67 | template <class T> reference_wrapper<T> ref(reference_wrapper<T>t) noexcept; |
| ... | ... | @@ -73,121 +76,104 @@ template <class T> using unwrap_reference_t = typename unwrap_reference<T>::type |
| 73 | 76 | template <class T> using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type; // since C++20 |
| 74 | 77 | |
| 75 | 78 | template <class T> // <class T=void> in C++14 |
| 76 | struct plus : binary_function<T, T, T> | |
| 77 | { | |
| 79 | struct plus { | |
| 78 | 80 | T operator()(const T& x, const T& y) const; |
| 79 | 81 | }; |
| 80 | 82 | |
| 81 | 83 | template <class T> // <class T=void> in C++14 |
| 82 | struct minus : binary_function<T, T, T> | |
| 83 | { | |
| 84 | struct minus { | |
| 84 | 85 | T operator()(const T& x, const T& y) const; |
| 85 | 86 | }; |
| 86 | 87 | |
| 87 | 88 | template <class T> // <class T=void> in C++14 |
| 88 | struct multiplies : binary_function<T, T, T> | |
| 89 | { | |
| 89 | struct multiplies { | |
| 90 | 90 | T operator()(const T& x, const T& y) const; |
| 91 | 91 | }; |
| 92 | 92 | |
| 93 | 93 | template <class T> // <class T=void> in C++14 |
| 94 | struct divides : binary_function<T, T, T> | |
| 95 | { | |
| 94 | struct divides { | |
| 96 | 95 | T operator()(const T& x, const T& y) const; |
| 97 | 96 | }; |
| 98 | 97 | |
| 99 | 98 | template <class T> // <class T=void> in C++14 |
| 100 | struct modulus : binary_function<T, T, T> | |
| 101 | { | |
| 99 | struct modulus { | |
| 102 | 100 | T operator()(const T& x, const T& y) const; |
| 103 | 101 | }; |
| 104 | 102 | |
| 105 | 103 | template <class T> // <class T=void> in C++14 |
| 106 | struct negate : unary_function<T, T> | |
| 107 | { | |
| 104 | struct negate { | |
| 108 | 105 | T operator()(const T& x) const; |
| 109 | 106 | }; |
| 110 | 107 | |
| 111 | 108 | template <class T> // <class T=void> in C++14 |
| 112 | struct equal_to : binary_function<T, T, bool> | |
| 113 | { | |
| 109 | struct equal_to { | |
| 114 | 110 | bool operator()(const T& x, const T& y) const; |
| 115 | 111 | }; |
| 116 | 112 | |
| 117 | 113 | template <class T> // <class T=void> in C++14 |
| 118 | struct not_equal_to : binary_function<T, T, bool> | |
| 119 | { | |
| 114 | struct not_equal_to { | |
| 120 | 115 | bool operator()(const T& x, const T& y) const; |
| 121 | 116 | }; |
| 122 | 117 | |
| 123 | 118 | template <class T> // <class T=void> in C++14 |
| 124 | struct greater : binary_function<T, T, bool> | |
| 125 | { | |
| 119 | struct greater { | |
| 126 | 120 | bool operator()(const T& x, const T& y) const; |
| 127 | 121 | }; |
| 128 | 122 | |
| 129 | 123 | template <class T> // <class T=void> in C++14 |
| 130 | struct less : binary_function<T, T, bool> | |
| 131 | { | |
| 124 | struct less { | |
| 132 | 125 | bool operator()(const T& x, const T& y) const; |
| 133 | 126 | }; |
| 134 | 127 | |
| 135 | 128 | template <class T> // <class T=void> in C++14 |
| 136 | struct greater_equal : binary_function<T, T, bool> | |
| 137 | { | |
| 129 | struct greater_equal { | |
| 138 | 130 | bool operator()(const T& x, const T& y) const; |
| 139 | 131 | }; |
| 140 | 132 | |
| 141 | 133 | template <class T> // <class T=void> in C++14 |
| 142 | struct less_equal : binary_function<T, T, bool> | |
| 143 | { | |
| 134 | struct less_equal { | |
| 144 | 135 | bool operator()(const T& x, const T& y) const; |
| 145 | 136 | }; |
| 146 | 137 | |
| 147 | 138 | template <class T> // <class T=void> in C++14 |
| 148 | struct logical_and : binary_function<T, T, bool> | |
| 149 | { | |
| 139 | struct logical_and { | |
| 150 | 140 | bool operator()(const T& x, const T& y) const; |
| 151 | 141 | }; |
| 152 | 142 | |
| 153 | 143 | template <class T> // <class T=void> in C++14 |
| 154 | struct logical_or : binary_function<T, T, bool> | |
| 155 | { | |
| 144 | struct logical_or { | |
| 156 | 145 | bool operator()(const T& x, const T& y) const; |
| 157 | 146 | }; |
| 158 | 147 | |
| 159 | 148 | template <class T> // <class T=void> in C++14 |
| 160 | struct logical_not : unary_function<T, bool> | |
| 161 | { | |
| 149 | struct logical_not { | |
| 162 | 150 | bool operator()(const T& x) const; |
| 163 | 151 | }; |
| 164 | 152 | |
| 165 | 153 | template <class T> // <class T=void> in C++14 |
| 166 | struct bit_and : unary_function<T, bool> | |
| 167 | { | |
| 168 | bool operator()(const T& x, const T& y) const; | |
| 154 | struct bit_and { | |
| 155 | T operator()(const T& x, const T& y) const; | |
| 169 | 156 | }; |
| 170 | 157 | |
| 171 | 158 | template <class T> // <class T=void> in C++14 |
| 172 | struct bit_or : unary_function<T, bool> | |
| 173 | { | |
| 174 | bool operator()(const T& x, const T& y) const; | |
| 159 | struct bit_or { | |
| 160 | T operator()(const T& x, const T& y) const; | |
| 175 | 161 | }; |
| 176 | 162 | |
| 177 | 163 | template <class T> // <class T=void> in C++14 |
| 178 | struct bit_xor : unary_function<T, bool> | |
| 179 | { | |
| 180 | bool operator()(const T& x, const T& y) const; | |
| 164 | struct bit_xor { | |
| 165 | T operator()(const T& x, const T& y) const; | |
| 181 | 166 | }; |
| 182 | 167 | |
| 183 | 168 | template <class T=void> // C++14 |
| 184 | struct bit_xor : unary_function<T, bool> | |
| 185 | { | |
| 186 | bool operator()(const T& x) const; | |
| 169 | struct bit_not { | |
| 170 | T operator()(const T& x) const; | |
| 187 | 171 | }; |
| 188 | 172 | |
| 173 | struct identity; // C++20 | |
| 174 | ||
| 189 | 175 | template <class Predicate> |
| 190 | class unary_negate // deprecated in C++17 | |
| 176 | class unary_negate // deprecated in C++17, removed in C++20 | |
| 191 | 177 | : public unary_function<typename Predicate::argument_type, bool> |
| 192 | 178 | { |
| 193 | 179 | public: |
| ... | ... | @@ -195,11 +181,11 @@ public: |
| 195 | 181 | bool operator()(const typename Predicate::argument_type& x) const; |
| 196 | 182 | }; |
| 197 | 183 | |
| 198 | template <class Predicate> // deprecated in C++17 | |
| 184 | template <class Predicate> // deprecated in C++17, removed in C++20 | |
| 199 | 185 | unary_negate<Predicate> not1(const Predicate& pred); |
| 200 | 186 | |
| 201 | 187 | template <class Predicate> |
| 202 | class binary_negate // deprecated in C++17 | |
| 188 | class binary_negate // deprecated in C++17, removed in C++20 | |
| 203 | 189 | : public binary_function<typename Predicate::first_argument_type, |
| 204 | 190 | typename Predicate::second_argument_type, |
| 205 | 191 | bool> |
| ... | ... | @@ -210,7 +196,7 @@ public: |
| 210 | 196 | const typename Predicate::second_argument_type& y) const; |
| 211 | 197 | }; |
| 212 | 198 | |
| 213 | template <class Predicate> // deprecated in C++17 | |
| 199 | template <class Predicate> // deprecated in C++17, removed in C++20 | |
| 214 | 200 | binary_negate<Predicate> not2(const Predicate& pred); |
| 215 | 201 | |
| 216 | 202 | template <class F> |
| ... | ... | @@ -501,2687 +487,43 @@ POLICY: For non-variadic implementations, the number of arguments is limited |
| 501 | 487 | |
| 502 | 488 | */ |
| 503 | 489 | |
| 490 | #include <__algorithm/search.h> | |
| 504 | 491 | #include <__config> |
| 505 | #include <type_traits> | |
| 506 | #include <typeinfo> | |
| 492 | #include <__debug> | |
| 493 | #include <__functional/binary_function.h> // TODO: deprecate | |
| 494 | #include <__functional/binary_negate.h> | |
| 495 | #include <__functional/bind_front.h> | |
| 496 | #include <__functional/bind.h> | |
| 497 | #include <__functional/binder1st.h> | |
| 498 | #include <__functional/binder2nd.h> | |
| 499 | #include <__functional/default_searcher.h> | |
| 500 | #include <__functional/function.h> | |
| 501 | #include <__functional/hash.h> | |
| 502 | #include <__functional/identity.h> | |
| 503 | #include <__functional/invoke.h> | |
| 504 | #include <__functional/mem_fn.h> // TODO: deprecate | |
| 505 | #include <__functional/mem_fun_ref.h> | |
| 506 | #include <__functional/not_fn.h> | |
| 507 | #include <__functional/operations.h> | |
| 508 | #include <__functional/pointer_to_binary_function.h> | |
| 509 | #include <__functional/pointer_to_unary_function.h> | |
| 510 | #include <__functional/ranges_operations.h> | |
| 511 | #include <__functional/reference_wrapper.h> | |
| 512 | #include <__functional/unary_function.h> // TODO: deprecate | |
| 513 | #include <__functional/unary_negate.h> | |
| 514 | #include <__functional/unwrap_ref.h> | |
| 515 | #include <__utility/forward.h> | |
| 516 | #include <concepts> | |
| 507 | 517 | #include <exception> |
| 508 | 518 | #include <memory> |
| 509 | 519 | #include <tuple> |
| 520 | #include <type_traits> | |
| 521 | #include <typeinfo> | |
| 510 | 522 | #include <utility> |
| 511 | 523 | #include <version> |
| 512 | 524 | |
| 513 | #include <__functional_base> | |
| 514 | ||
| 515 | 525 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 516 | 526 | #pragma GCC system_header |
| 517 | 527 | #endif |
| 518 | 528 | |
| 519 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 520 | ||
| 521 | #if _LIBCPP_STD_VER > 11 | |
| 522 | template <class _Tp = void> | |
| 523 | #else | |
| 524 | template <class _Tp> | |
| 525 | #endif | |
| 526 | struct _LIBCPP_TEMPLATE_VIS plus : binary_function<_Tp, _Tp, _Tp> | |
| 527 | { | |
| 528 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 529 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 530 | {return __x + __y;} | |
| 531 | }; | |
| 532 | ||
| 533 | #if _LIBCPP_STD_VER > 11 | |
| 534 | template <> | |
| 535 | struct _LIBCPP_TEMPLATE_VIS plus<void> | |
| 536 | { | |
| 537 | template <class _T1, class _T2> | |
| 538 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 539 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 540 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u))) | |
| 541 | -> decltype (_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u)) | |
| 542 | { return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); } | |
| 543 | typedef void is_transparent; | |
| 544 | }; | |
| 545 | #endif | |
| 546 | ||
| 547 | ||
| 548 | #if _LIBCPP_STD_VER > 11 | |
| 549 | template <class _Tp = void> | |
| 550 | #else | |
| 551 | template <class _Tp> | |
| 552 | #endif | |
| 553 | struct _LIBCPP_TEMPLATE_VIS minus : binary_function<_Tp, _Tp, _Tp> | |
| 554 | { | |
| 555 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 556 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 557 | {return __x - __y;} | |
| 558 | }; | |
| 559 | ||
| 560 | #if _LIBCPP_STD_VER > 11 | |
| 561 | template <> | |
| 562 | struct _LIBCPP_TEMPLATE_VIS minus<void> | |
| 563 | { | |
| 564 | template <class _T1, class _T2> | |
| 565 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 566 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 567 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u))) | |
| 568 | -> decltype (_VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u)) | |
| 569 | { return _VSTD::forward<_T1>(__t) - _VSTD::forward<_T2>(__u); } | |
| 570 | typedef void is_transparent; | |
| 571 | }; | |
| 572 | #endif | |
| 573 | ||
| 574 | ||
| 575 | #if _LIBCPP_STD_VER > 11 | |
| 576 | template <class _Tp = void> | |
| 577 | #else | |
| 578 | template <class _Tp> | |
| 579 | #endif | |
| 580 | struct _LIBCPP_TEMPLATE_VIS multiplies : binary_function<_Tp, _Tp, _Tp> | |
| 581 | { | |
| 582 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 583 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 584 | {return __x * __y;} | |
| 585 | }; | |
| 586 | ||
| 587 | #if _LIBCPP_STD_VER > 11 | |
| 588 | template <> | |
| 589 | struct _LIBCPP_TEMPLATE_VIS multiplies<void> | |
| 590 | { | |
| 591 | template <class _T1, class _T2> | |
| 592 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 593 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 594 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u))) | |
| 595 | -> decltype (_VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u)) | |
| 596 | { return _VSTD::forward<_T1>(__t) * _VSTD::forward<_T2>(__u); } | |
| 597 | typedef void is_transparent; | |
| 598 | }; | |
| 599 | #endif | |
| 600 | ||
| 601 | ||
| 602 | #if _LIBCPP_STD_VER > 11 | |
| 603 | template <class _Tp = void> | |
| 604 | #else | |
| 605 | template <class _Tp> | |
| 606 | #endif | |
| 607 | struct _LIBCPP_TEMPLATE_VIS divides : binary_function<_Tp, _Tp, _Tp> | |
| 608 | { | |
| 609 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 610 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 611 | {return __x / __y;} | |
| 612 | }; | |
| 613 | ||
| 614 | #if _LIBCPP_STD_VER > 11 | |
| 615 | template <> | |
| 616 | struct _LIBCPP_TEMPLATE_VIS divides<void> | |
| 617 | { | |
| 618 | template <class _T1, class _T2> | |
| 619 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 620 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 621 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u))) | |
| 622 | -> decltype (_VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u)) | |
| 623 | { return _VSTD::forward<_T1>(__t) / _VSTD::forward<_T2>(__u); } | |
| 624 | typedef void is_transparent; | |
| 625 | }; | |
| 626 | #endif | |
| 627 | ||
| 628 | ||
| 629 | #if _LIBCPP_STD_VER > 11 | |
| 630 | template <class _Tp = void> | |
| 631 | #else | |
| 632 | template <class _Tp> | |
| 633 | #endif | |
| 634 | struct _LIBCPP_TEMPLATE_VIS modulus : binary_function<_Tp, _Tp, _Tp> | |
| 635 | { | |
| 636 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 637 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 638 | {return __x % __y;} | |
| 639 | }; | |
| 640 | ||
| 641 | #if _LIBCPP_STD_VER > 11 | |
| 642 | template <> | |
| 643 | struct _LIBCPP_TEMPLATE_VIS modulus<void> | |
| 644 | { | |
| 645 | template <class _T1, class _T2> | |
| 646 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 647 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 648 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u))) | |
| 649 | -> decltype (_VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u)) | |
| 650 | { return _VSTD::forward<_T1>(__t) % _VSTD::forward<_T2>(__u); } | |
| 651 | typedef void is_transparent; | |
| 652 | }; | |
| 653 | #endif | |
| 654 | ||
| 655 | ||
| 656 | #if _LIBCPP_STD_VER > 11 | |
| 657 | template <class _Tp = void> | |
| 658 | #else | |
| 659 | template <class _Tp> | |
| 660 | #endif | |
| 661 | struct _LIBCPP_TEMPLATE_VIS negate : unary_function<_Tp, _Tp> | |
| 662 | { | |
| 663 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 664 | _Tp operator()(const _Tp& __x) const | |
| 665 | {return -__x;} | |
| 666 | }; | |
| 667 | ||
| 668 | #if _LIBCPP_STD_VER > 11 | |
| 669 | template <> | |
| 670 | struct _LIBCPP_TEMPLATE_VIS negate<void> | |
| 671 | { | |
| 672 | template <class _Tp> | |
| 673 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 674 | auto operator()(_Tp&& __x) const | |
| 675 | _NOEXCEPT_(noexcept(- _VSTD::forward<_Tp>(__x))) | |
| 676 | -> decltype (- _VSTD::forward<_Tp>(__x)) | |
| 677 | { return - _VSTD::forward<_Tp>(__x); } | |
| 678 | typedef void is_transparent; | |
| 679 | }; | |
| 680 | #endif | |
| 681 | ||
| 682 | ||
| 683 | #if _LIBCPP_STD_VER > 11 | |
| 684 | template <class _Tp = void> | |
| 685 | #else | |
| 686 | template <class _Tp> | |
| 687 | #endif | |
| 688 | struct _LIBCPP_TEMPLATE_VIS equal_to : binary_function<_Tp, _Tp, bool> | |
| 689 | { | |
| 690 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 691 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 692 | {return __x == __y;} | |
| 693 | }; | |
| 694 | ||
| 695 | #if _LIBCPP_STD_VER > 11 | |
| 696 | template <> | |
| 697 | struct _LIBCPP_TEMPLATE_VIS equal_to<void> | |
| 698 | { | |
| 699 | template <class _T1, class _T2> | |
| 700 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 701 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 702 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u))) | |
| 703 | -> decltype (_VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u)) | |
| 704 | { return _VSTD::forward<_T1>(__t) == _VSTD::forward<_T2>(__u); } | |
| 705 | typedef void is_transparent; | |
| 706 | }; | |
| 707 | #endif | |
| 708 | ||
| 709 | ||
| 710 | #if _LIBCPP_STD_VER > 11 | |
| 711 | template <class _Tp = void> | |
| 712 | #else | |
| 713 | template <class _Tp> | |
| 714 | #endif | |
| 715 | struct _LIBCPP_TEMPLATE_VIS not_equal_to : binary_function<_Tp, _Tp, bool> | |
| 716 | { | |
| 717 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 718 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 719 | {return __x != __y;} | |
| 720 | }; | |
| 721 | ||
| 722 | #if _LIBCPP_STD_VER > 11 | |
| 723 | template <> | |
| 724 | struct _LIBCPP_TEMPLATE_VIS not_equal_to<void> | |
| 725 | { | |
| 726 | template <class _T1, class _T2> | |
| 727 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 728 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 729 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u))) | |
| 730 | -> decltype (_VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u)) | |
| 731 | { return _VSTD::forward<_T1>(__t) != _VSTD::forward<_T2>(__u); } | |
| 732 | typedef void is_transparent; | |
| 733 | }; | |
| 734 | #endif | |
| 735 | ||
| 736 | ||
| 737 | #if _LIBCPP_STD_VER > 11 | |
| 738 | template <class _Tp = void> | |
| 739 | #else | |
| 740 | template <class _Tp> | |
| 741 | #endif | |
| 742 | struct _LIBCPP_TEMPLATE_VIS greater : binary_function<_Tp, _Tp, bool> | |
| 743 | { | |
| 744 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 745 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 746 | {return __x > __y;} | |
| 747 | }; | |
| 748 | ||
| 749 | #if _LIBCPP_STD_VER > 11 | |
| 750 | template <> | |
| 751 | struct _LIBCPP_TEMPLATE_VIS greater<void> | |
| 752 | { | |
| 753 | template <class _T1, class _T2> | |
| 754 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 755 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 756 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u))) | |
| 757 | -> decltype (_VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u)) | |
| 758 | { return _VSTD::forward<_T1>(__t) > _VSTD::forward<_T2>(__u); } | |
| 759 | typedef void is_transparent; | |
| 760 | }; | |
| 761 | #endif | |
| 762 | ||
| 763 | ||
| 764 | // less in <__functional_base> | |
| 765 | ||
| 766 | #if _LIBCPP_STD_VER > 11 | |
| 767 | template <class _Tp = void> | |
| 768 | #else | |
| 769 | template <class _Tp> | |
| 770 | #endif | |
| 771 | struct _LIBCPP_TEMPLATE_VIS greater_equal : binary_function<_Tp, _Tp, bool> | |
| 772 | { | |
| 773 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 774 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 775 | {return __x >= __y;} | |
| 776 | }; | |
| 777 | ||
| 778 | #if _LIBCPP_STD_VER > 11 | |
| 779 | template <> | |
| 780 | struct _LIBCPP_TEMPLATE_VIS greater_equal<void> | |
| 781 | { | |
| 782 | template <class _T1, class _T2> | |
| 783 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 784 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 785 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u))) | |
| 786 | -> decltype (_VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u)) | |
| 787 | { return _VSTD::forward<_T1>(__t) >= _VSTD::forward<_T2>(__u); } | |
| 788 | typedef void is_transparent; | |
| 789 | }; | |
| 790 | #endif | |
| 791 | ||
| 792 | ||
| 793 | #if _LIBCPP_STD_VER > 11 | |
| 794 | template <class _Tp = void> | |
| 795 | #else | |
| 796 | template <class _Tp> | |
| 797 | #endif | |
| 798 | struct _LIBCPP_TEMPLATE_VIS less_equal : binary_function<_Tp, _Tp, bool> | |
| 799 | { | |
| 800 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 801 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 802 | {return __x <= __y;} | |
| 803 | }; | |
| 804 | ||
| 805 | #if _LIBCPP_STD_VER > 11 | |
| 806 | template <> | |
| 807 | struct _LIBCPP_TEMPLATE_VIS less_equal<void> | |
| 808 | { | |
| 809 | template <class _T1, class _T2> | |
| 810 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 811 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 812 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u))) | |
| 813 | -> decltype (_VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u)) | |
| 814 | { return _VSTD::forward<_T1>(__t) <= _VSTD::forward<_T2>(__u); } | |
| 815 | typedef void is_transparent; | |
| 816 | }; | |
| 817 | #endif | |
| 818 | ||
| 819 | ||
| 820 | #if _LIBCPP_STD_VER > 11 | |
| 821 | template <class _Tp = void> | |
| 822 | #else | |
| 823 | template <class _Tp> | |
| 824 | #endif | |
| 825 | struct _LIBCPP_TEMPLATE_VIS logical_and : binary_function<_Tp, _Tp, bool> | |
| 826 | { | |
| 827 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 828 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 829 | {return __x && __y;} | |
| 830 | }; | |
| 831 | ||
| 832 | #if _LIBCPP_STD_VER > 11 | |
| 833 | template <> | |
| 834 | struct _LIBCPP_TEMPLATE_VIS logical_and<void> | |
| 835 | { | |
| 836 | template <class _T1, class _T2> | |
| 837 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 838 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 839 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u))) | |
| 840 | -> decltype (_VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u)) | |
| 841 | { return _VSTD::forward<_T1>(__t) && _VSTD::forward<_T2>(__u); } | |
| 842 | typedef void is_transparent; | |
| 843 | }; | |
| 844 | #endif | |
| 845 | ||
| 846 | ||
| 847 | #if _LIBCPP_STD_VER > 11 | |
| 848 | template <class _Tp = void> | |
| 849 | #else | |
| 850 | template <class _Tp> | |
| 851 | #endif | |
| 852 | struct _LIBCPP_TEMPLATE_VIS logical_or : binary_function<_Tp, _Tp, bool> | |
| 853 | { | |
| 854 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 855 | bool operator()(const _Tp& __x, const _Tp& __y) const | |
| 856 | {return __x || __y;} | |
| 857 | }; | |
| 858 | ||
| 859 | #if _LIBCPP_STD_VER > 11 | |
| 860 | template <> | |
| 861 | struct _LIBCPP_TEMPLATE_VIS logical_or<void> | |
| 862 | { | |
| 863 | template <class _T1, class _T2> | |
| 864 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 865 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 866 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u))) | |
| 867 | -> decltype (_VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u)) | |
| 868 | { return _VSTD::forward<_T1>(__t) || _VSTD::forward<_T2>(__u); } | |
| 869 | typedef void is_transparent; | |
| 870 | }; | |
| 871 | #endif | |
| 872 | ||
| 873 | ||
| 874 | #if _LIBCPP_STD_VER > 11 | |
| 875 | template <class _Tp = void> | |
| 876 | #else | |
| 877 | template <class _Tp> | |
| 878 | #endif | |
| 879 | struct _LIBCPP_TEMPLATE_VIS logical_not : unary_function<_Tp, bool> | |
| 880 | { | |
| 881 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 882 | bool operator()(const _Tp& __x) const | |
| 883 | {return !__x;} | |
| 884 | }; | |
| 885 | ||
| 886 | #if _LIBCPP_STD_VER > 11 | |
| 887 | template <> | |
| 888 | struct _LIBCPP_TEMPLATE_VIS logical_not<void> | |
| 889 | { | |
| 890 | template <class _Tp> | |
| 891 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 892 | auto operator()(_Tp&& __x) const | |
| 893 | _NOEXCEPT_(noexcept(!_VSTD::forward<_Tp>(__x))) | |
| 894 | -> decltype (!_VSTD::forward<_Tp>(__x)) | |
| 895 | { return !_VSTD::forward<_Tp>(__x); } | |
| 896 | typedef void is_transparent; | |
| 897 | }; | |
| 898 | #endif | |
| 899 | ||
| 900 | ||
| 901 | #if _LIBCPP_STD_VER > 11 | |
| 902 | template <class _Tp = void> | |
| 903 | #else | |
| 904 | template <class _Tp> | |
| 905 | #endif | |
| 906 | struct _LIBCPP_TEMPLATE_VIS bit_and : binary_function<_Tp, _Tp, _Tp> | |
| 907 | { | |
| 908 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 909 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 910 | {return __x & __y;} | |
| 911 | }; | |
| 912 | ||
| 913 | #if _LIBCPP_STD_VER > 11 | |
| 914 | template <> | |
| 915 | struct _LIBCPP_TEMPLATE_VIS bit_and<void> | |
| 916 | { | |
| 917 | template <class _T1, class _T2> | |
| 918 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 919 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 920 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u))) | |
| 921 | -> decltype (_VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u)) | |
| 922 | { return _VSTD::forward<_T1>(__t) & _VSTD::forward<_T2>(__u); } | |
| 923 | typedef void is_transparent; | |
| 924 | }; | |
| 925 | #endif | |
| 926 | ||
| 927 | ||
| 928 | #if _LIBCPP_STD_VER > 11 | |
| 929 | template <class _Tp = void> | |
| 930 | #else | |
| 931 | template <class _Tp> | |
| 932 | #endif | |
| 933 | struct _LIBCPP_TEMPLATE_VIS bit_or : binary_function<_Tp, _Tp, _Tp> | |
| 934 | { | |
| 935 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 936 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 937 | {return __x | __y;} | |
| 938 | }; | |
| 939 | ||
| 940 | #if _LIBCPP_STD_VER > 11 | |
| 941 | template <> | |
| 942 | struct _LIBCPP_TEMPLATE_VIS bit_or<void> | |
| 943 | { | |
| 944 | template <class _T1, class _T2> | |
| 945 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 946 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 947 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u))) | |
| 948 | -> decltype (_VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u)) | |
| 949 | { return _VSTD::forward<_T1>(__t) | _VSTD::forward<_T2>(__u); } | |
| 950 | typedef void is_transparent; | |
| 951 | }; | |
| 952 | #endif | |
| 953 | ||
| 954 | ||
| 955 | #if _LIBCPP_STD_VER > 11 | |
| 956 | template <class _Tp = void> | |
| 957 | #else | |
| 958 | template <class _Tp> | |
| 959 | #endif | |
| 960 | struct _LIBCPP_TEMPLATE_VIS bit_xor : binary_function<_Tp, _Tp, _Tp> | |
| 961 | { | |
| 962 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 963 | _Tp operator()(const _Tp& __x, const _Tp& __y) const | |
| 964 | {return __x ^ __y;} | |
| 965 | }; | |
| 966 | ||
| 967 | #if _LIBCPP_STD_VER > 11 | |
| 968 | template <> | |
| 969 | struct _LIBCPP_TEMPLATE_VIS bit_xor<void> | |
| 970 | { | |
| 971 | template <class _T1, class _T2> | |
| 972 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 973 | auto operator()(_T1&& __t, _T2&& __u) const | |
| 974 | _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u))) | |
| 975 | -> decltype (_VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u)) | |
| 976 | { return _VSTD::forward<_T1>(__t) ^ _VSTD::forward<_T2>(__u); } | |
| 977 | typedef void is_transparent; | |
| 978 | }; | |
| 979 | #endif | |
| 980 | ||
| 981 | ||
| 982 | #if _LIBCPP_STD_VER > 11 | |
| 983 | template <class _Tp = void> | |
| 984 | struct _LIBCPP_TEMPLATE_VIS bit_not : unary_function<_Tp, _Tp> | |
| 985 | { | |
| 986 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 987 | _Tp operator()(const _Tp& __x) const | |
| 988 | {return ~__x;} | |
| 989 | }; | |
| 990 | ||
| 991 | template <> | |
| 992 | struct _LIBCPP_TEMPLATE_VIS bit_not<void> | |
| 993 | { | |
| 994 | template <class _Tp> | |
| 995 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 996 | auto operator()(_Tp&& __x) const | |
| 997 | _NOEXCEPT_(noexcept(~_VSTD::forward<_Tp>(__x))) | |
| 998 | -> decltype (~_VSTD::forward<_Tp>(__x)) | |
| 999 | { return ~_VSTD::forward<_Tp>(__x); } | |
| 1000 | typedef void is_transparent; | |
| 1001 | }; | |
| 1002 | #endif | |
| 1003 | ||
| 1004 | template <class _Predicate> | |
| 1005 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 unary_negate | |
| 1006 | : public unary_function<typename _Predicate::argument_type, bool> | |
| 1007 | { | |
| 1008 | _Predicate __pred_; | |
| 1009 | public: | |
| 1010 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 1011 | explicit unary_negate(const _Predicate& __pred) | |
| 1012 | : __pred_(__pred) {} | |
| 1013 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 1014 | bool operator()(const typename _Predicate::argument_type& __x) const | |
| 1015 | {return !__pred_(__x);} | |
| 1016 | }; | |
| 1017 | ||
| 1018 | template <class _Predicate> | |
| 1019 | _LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 1020 | unary_negate<_Predicate> | |
| 1021 | not1(const _Predicate& __pred) {return unary_negate<_Predicate>(__pred);} | |
| 1022 | ||
| 1023 | template <class _Predicate> | |
| 1024 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 binary_negate | |
| 1025 | : public binary_function<typename _Predicate::first_argument_type, | |
| 1026 | typename _Predicate::second_argument_type, | |
| 1027 | bool> | |
| 1028 | { | |
| 1029 | _Predicate __pred_; | |
| 1030 | public: | |
| 1031 | _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 1032 | binary_negate(const _Predicate& __pred) : __pred_(__pred) {} | |
| 1033 | ||
| 1034 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 1035 | bool operator()(const typename _Predicate::first_argument_type& __x, | |
| 1036 | const typename _Predicate::second_argument_type& __y) const | |
| 1037 | {return !__pred_(__x, __y);} | |
| 1038 | }; | |
| 1039 | ||
| 1040 | template <class _Predicate> | |
| 1041 | _LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 1042 | binary_negate<_Predicate> | |
| 1043 | not2(const _Predicate& __pred) {return binary_negate<_Predicate>(__pred);} | |
| 1044 | ||
| 1045 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) | |
| 1046 | template <class __Operation> | |
| 1047 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder1st | |
| 1048 | : public unary_function<typename __Operation::second_argument_type, | |
| 1049 | typename __Operation::result_type> | |
| 1050 | { | |
| 1051 | protected: | |
| 1052 | __Operation op; | |
| 1053 | typename __Operation::first_argument_type value; | |
| 1054 | public: | |
| 1055 | _LIBCPP_INLINE_VISIBILITY binder1st(const __Operation& __x, | |
| 1056 | const typename __Operation::first_argument_type __y) | |
| 1057 | : op(__x), value(__y) {} | |
| 1058 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 1059 | (typename __Operation::second_argument_type& __x) const | |
| 1060 | {return op(value, __x);} | |
| 1061 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 1062 | (const typename __Operation::second_argument_type& __x) const | |
| 1063 | {return op(value, __x);} | |
| 1064 | }; | |
| 1065 | ||
| 1066 | template <class __Operation, class _Tp> | |
| 1067 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1068 | binder1st<__Operation> | |
| 1069 | bind1st(const __Operation& __op, const _Tp& __x) | |
| 1070 | {return binder1st<__Operation>(__op, __x);} | |
| 1071 | ||
| 1072 | template <class __Operation> | |
| 1073 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder2nd | |
| 1074 | : public unary_function<typename __Operation::first_argument_type, | |
| 1075 | typename __Operation::result_type> | |
| 1076 | { | |
| 1077 | protected: | |
| 1078 | __Operation op; | |
| 1079 | typename __Operation::second_argument_type value; | |
| 1080 | public: | |
| 1081 | _LIBCPP_INLINE_VISIBILITY | |
| 1082 | binder2nd(const __Operation& __x, const typename __Operation::second_argument_type __y) | |
| 1083 | : op(__x), value(__y) {} | |
| 1084 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 1085 | ( typename __Operation::first_argument_type& __x) const | |
| 1086 | {return op(__x, value);} | |
| 1087 | _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() | |
| 1088 | (const typename __Operation::first_argument_type& __x) const | |
| 1089 | {return op(__x, value);} | |
| 1090 | }; | |
| 1091 | ||
| 1092 | template <class __Operation, class _Tp> | |
| 1093 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1094 | binder2nd<__Operation> | |
| 1095 | bind2nd(const __Operation& __op, const _Tp& __x) | |
| 1096 | {return binder2nd<__Operation>(__op, __x);} | |
| 1097 | ||
| 1098 | template <class _Arg, class _Result> | |
| 1099 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function | |
| 1100 | : public unary_function<_Arg, _Result> | |
| 1101 | { | |
| 1102 | _Result (*__f_)(_Arg); | |
| 1103 | public: | |
| 1104 | _LIBCPP_INLINE_VISIBILITY explicit pointer_to_unary_function(_Result (*__f)(_Arg)) | |
| 1105 | : __f_(__f) {} | |
| 1106 | _LIBCPP_INLINE_VISIBILITY _Result operator()(_Arg __x) const | |
| 1107 | {return __f_(__x);} | |
| 1108 | }; | |
| 1109 | ||
| 1110 | template <class _Arg, class _Result> | |
| 1111 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1112 | pointer_to_unary_function<_Arg,_Result> | |
| 1113 | ptr_fun(_Result (*__f)(_Arg)) | |
| 1114 | {return pointer_to_unary_function<_Arg,_Result>(__f);} | |
| 1115 | ||
| 1116 | template <class _Arg1, class _Arg2, class _Result> | |
| 1117 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function | |
| 1118 | : public binary_function<_Arg1, _Arg2, _Result> | |
| 1119 | { | |
| 1120 | _Result (*__f_)(_Arg1, _Arg2); | |
| 1121 | public: | |
| 1122 | _LIBCPP_INLINE_VISIBILITY explicit pointer_to_binary_function(_Result (*__f)(_Arg1, _Arg2)) | |
| 1123 | : __f_(__f) {} | |
| 1124 | _LIBCPP_INLINE_VISIBILITY _Result operator()(_Arg1 __x, _Arg2 __y) const | |
| 1125 | {return __f_(__x, __y);} | |
| 1126 | }; | |
| 1127 | ||
| 1128 | template <class _Arg1, class _Arg2, class _Result> | |
| 1129 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1130 | pointer_to_binary_function<_Arg1,_Arg2,_Result> | |
| 1131 | ptr_fun(_Result (*__f)(_Arg1,_Arg2)) | |
| 1132 | {return pointer_to_binary_function<_Arg1,_Arg2,_Result>(__f);} | |
| 1133 | ||
| 1134 | template<class _Sp, class _Tp> | |
| 1135 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_t | |
| 1136 | : public unary_function<_Tp*, _Sp> | |
| 1137 | { | |
| 1138 | _Sp (_Tp::*__p_)(); | |
| 1139 | public: | |
| 1140 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun_t(_Sp (_Tp::*__p)()) | |
| 1141 | : __p_(__p) {} | |
| 1142 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp* __p) const | |
| 1143 | {return (__p->*__p_)();} | |
| 1144 | }; | |
| 1145 | ||
| 1146 | template<class _Sp, class _Tp, class _Ap> | |
| 1147 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_t | |
| 1148 | : public binary_function<_Tp*, _Ap, _Sp> | |
| 1149 | { | |
| 1150 | _Sp (_Tp::*__p_)(_Ap); | |
| 1151 | public: | |
| 1152 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun1_t(_Sp (_Tp::*__p)(_Ap)) | |
| 1153 | : __p_(__p) {} | |
| 1154 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp* __p, _Ap __x) const | |
| 1155 | {return (__p->*__p_)(__x);} | |
| 1156 | }; | |
| 1157 | ||
| 1158 | template<class _Sp, class _Tp> | |
| 1159 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1160 | mem_fun_t<_Sp,_Tp> | |
| 1161 | mem_fun(_Sp (_Tp::*__f)()) | |
| 1162 | {return mem_fun_t<_Sp,_Tp>(__f);} | |
| 1163 | ||
| 1164 | template<class _Sp, class _Tp, class _Ap> | |
| 1165 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1166 | mem_fun1_t<_Sp,_Tp,_Ap> | |
| 1167 | mem_fun(_Sp (_Tp::*__f)(_Ap)) | |
| 1168 | {return mem_fun1_t<_Sp,_Tp,_Ap>(__f);} | |
| 1169 | ||
| 1170 | template<class _Sp, class _Tp> | |
| 1171 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_ref_t | |
| 1172 | : public unary_function<_Tp, _Sp> | |
| 1173 | { | |
| 1174 | _Sp (_Tp::*__p_)(); | |
| 1175 | public: | |
| 1176 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun_ref_t(_Sp (_Tp::*__p)()) | |
| 1177 | : __p_(__p) {} | |
| 1178 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp& __p) const | |
| 1179 | {return (__p.*__p_)();} | |
| 1180 | }; | |
| 1181 | ||
| 1182 | template<class _Sp, class _Tp, class _Ap> | |
| 1183 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_ref_t | |
| 1184 | : public binary_function<_Tp, _Ap, _Sp> | |
| 1185 | { | |
| 1186 | _Sp (_Tp::*__p_)(_Ap); | |
| 1187 | public: | |
| 1188 | _LIBCPP_INLINE_VISIBILITY explicit mem_fun1_ref_t(_Sp (_Tp::*__p)(_Ap)) | |
| 1189 | : __p_(__p) {} | |
| 1190 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(_Tp& __p, _Ap __x) const | |
| 1191 | {return (__p.*__p_)(__x);} | |
| 1192 | }; | |
| 1193 | ||
| 1194 | template<class _Sp, class _Tp> | |
| 1195 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1196 | mem_fun_ref_t<_Sp,_Tp> | |
| 1197 | mem_fun_ref(_Sp (_Tp::*__f)()) | |
| 1198 | {return mem_fun_ref_t<_Sp,_Tp>(__f);} | |
| 1199 | ||
| 1200 | template<class _Sp, class _Tp, class _Ap> | |
| 1201 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1202 | mem_fun1_ref_t<_Sp,_Tp,_Ap> | |
| 1203 | mem_fun_ref(_Sp (_Tp::*__f)(_Ap)) | |
| 1204 | {return mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} | |
| 1205 | ||
| 1206 | template <class _Sp, class _Tp> | |
| 1207 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_t | |
| 1208 | : public unary_function<const _Tp*, _Sp> | |
| 1209 | { | |
| 1210 | _Sp (_Tp::*__p_)() const; | |
| 1211 | public: | |
| 1212 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun_t(_Sp (_Tp::*__p)() const) | |
| 1213 | : __p_(__p) {} | |
| 1214 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp* __p) const | |
| 1215 | {return (__p->*__p_)();} | |
| 1216 | }; | |
| 1217 | ||
| 1218 | template <class _Sp, class _Tp, class _Ap> | |
| 1219 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t | |
| 1220 | : public binary_function<const _Tp*, _Ap, _Sp> | |
| 1221 | { | |
| 1222 | _Sp (_Tp::*__p_)(_Ap) const; | |
| 1223 | public: | |
| 1224 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun1_t(_Sp (_Tp::*__p)(_Ap) const) | |
| 1225 | : __p_(__p) {} | |
| 1226 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp* __p, _Ap __x) const | |
| 1227 | {return (__p->*__p_)(__x);} | |
| 1228 | }; | |
| 1229 | ||
| 1230 | template <class _Sp, class _Tp> | |
| 1231 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1232 | const_mem_fun_t<_Sp,_Tp> | |
| 1233 | mem_fun(_Sp (_Tp::*__f)() const) | |
| 1234 | {return const_mem_fun_t<_Sp,_Tp>(__f);} | |
| 1235 | ||
| 1236 | template <class _Sp, class _Tp, class _Ap> | |
| 1237 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1238 | const_mem_fun1_t<_Sp,_Tp,_Ap> | |
| 1239 | mem_fun(_Sp (_Tp::*__f)(_Ap) const) | |
| 1240 | {return const_mem_fun1_t<_Sp,_Tp,_Ap>(__f);} | |
| 1241 | ||
| 1242 | template <class _Sp, class _Tp> | |
| 1243 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_ref_t | |
| 1244 | : public unary_function<_Tp, _Sp> | |
| 1245 | { | |
| 1246 | _Sp (_Tp::*__p_)() const; | |
| 1247 | public: | |
| 1248 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun_ref_t(_Sp (_Tp::*__p)() const) | |
| 1249 | : __p_(__p) {} | |
| 1250 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp& __p) const | |
| 1251 | {return (__p.*__p_)();} | |
| 1252 | }; | |
| 1253 | ||
| 1254 | template <class _Sp, class _Tp, class _Ap> | |
| 1255 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_ref_t | |
| 1256 | : public binary_function<_Tp, _Ap, _Sp> | |
| 1257 | { | |
| 1258 | _Sp (_Tp::*__p_)(_Ap) const; | |
| 1259 | public: | |
| 1260 | _LIBCPP_INLINE_VISIBILITY explicit const_mem_fun1_ref_t(_Sp (_Tp::*__p)(_Ap) const) | |
| 1261 | : __p_(__p) {} | |
| 1262 | _LIBCPP_INLINE_VISIBILITY _Sp operator()(const _Tp& __p, _Ap __x) const | |
| 1263 | {return (__p.*__p_)(__x);} | |
| 1264 | }; | |
| 1265 | ||
| 1266 | template <class _Sp, class _Tp> | |
| 1267 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1268 | const_mem_fun_ref_t<_Sp,_Tp> | |
| 1269 | mem_fun_ref(_Sp (_Tp::*__f)() const) | |
| 1270 | {return const_mem_fun_ref_t<_Sp,_Tp>(__f);} | |
| 1271 | ||
| 1272 | template <class _Sp, class _Tp, class _Ap> | |
| 1273 | _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY | |
| 1274 | const_mem_fun1_ref_t<_Sp,_Tp,_Ap> | |
| 1275 | mem_fun_ref(_Sp (_Tp::*__f)(_Ap) const) | |
| 1276 | {return const_mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} | |
| 1277 | #endif | |
| 1278 | ||
| 1279 | //////////////////////////////////////////////////////////////////////////////// | |
| 1280 | // MEMFUN | |
| 1281 | //============================================================================== | |
| 1282 | ||
| 1283 | template <class _Tp> | |
| 1284 | class __mem_fn | |
| 1285 | : public __weak_result_type<_Tp> | |
| 1286 | { | |
| 1287 | public: | |
| 1288 | // types | |
| 1289 | typedef _Tp type; | |
| 1290 | private: | |
| 1291 | type __f_; | |
| 1292 | ||
| 1293 | public: | |
| 1294 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1295 | __mem_fn(type __f) _NOEXCEPT : __f_(__f) {} | |
| 1296 | ||
| 1297 | #ifndef _LIBCPP_CXX03_LANG | |
| 1298 | // invoke | |
| 1299 | template <class... _ArgTypes> | |
| 1300 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1301 | typename __invoke_return<type, _ArgTypes...>::type | |
| 1302 | operator() (_ArgTypes&&... __args) const { | |
| 1303 | return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__args)...); | |
| 1304 | } | |
| 1305 | #else | |
| 1306 | ||
| 1307 | template <class _A0> | |
| 1308 | _LIBCPP_INLINE_VISIBILITY | |
| 1309 | typename __invoke_return0<type, _A0>::type | |
| 1310 | operator() (_A0& __a0) const { | |
| 1311 | return _VSTD::__invoke(__f_, __a0); | |
| 1312 | } | |
| 1313 | ||
| 1314 | template <class _A0> | |
| 1315 | _LIBCPP_INLINE_VISIBILITY | |
| 1316 | typename __invoke_return0<type, _A0 const>::type | |
| 1317 | operator() (_A0 const& __a0) const { | |
| 1318 | return _VSTD::__invoke(__f_, __a0); | |
| 1319 | } | |
| 1320 | ||
| 1321 | template <class _A0, class _A1> | |
| 1322 | _LIBCPP_INLINE_VISIBILITY | |
| 1323 | typename __invoke_return1<type, _A0, _A1>::type | |
| 1324 | operator() (_A0& __a0, _A1& __a1) const { | |
| 1325 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 1326 | } | |
| 1327 | ||
| 1328 | template <class _A0, class _A1> | |
| 1329 | _LIBCPP_INLINE_VISIBILITY | |
| 1330 | typename __invoke_return1<type, _A0 const, _A1>::type | |
| 1331 | operator() (_A0 const& __a0, _A1& __a1) const { | |
| 1332 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 1333 | } | |
| 1334 | ||
| 1335 | template <class _A0, class _A1> | |
| 1336 | _LIBCPP_INLINE_VISIBILITY | |
| 1337 | typename __invoke_return1<type, _A0, _A1 const>::type | |
| 1338 | operator() (_A0& __a0, _A1 const& __a1) const { | |
| 1339 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 1340 | } | |
| 1341 | ||
| 1342 | template <class _A0, class _A1> | |
| 1343 | _LIBCPP_INLINE_VISIBILITY | |
| 1344 | typename __invoke_return1<type, _A0 const, _A1 const>::type | |
| 1345 | operator() (_A0 const& __a0, _A1 const& __a1) const { | |
| 1346 | return _VSTD::__invoke(__f_, __a0, __a1); | |
| 1347 | } | |
| 1348 | ||
| 1349 | template <class _A0, class _A1, class _A2> | |
| 1350 | _LIBCPP_INLINE_VISIBILITY | |
| 1351 | typename __invoke_return2<type, _A0, _A1, _A2>::type | |
| 1352 | operator() (_A0& __a0, _A1& __a1, _A2& __a2) const { | |
| 1353 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1354 | } | |
| 1355 | ||
| 1356 | template <class _A0, class _A1, class _A2> | |
| 1357 | _LIBCPP_INLINE_VISIBILITY | |
| 1358 | typename __invoke_return2<type, _A0 const, _A1, _A2>::type | |
| 1359 | operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const { | |
| 1360 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1361 | } | |
| 1362 | ||
| 1363 | template <class _A0, class _A1, class _A2> | |
| 1364 | _LIBCPP_INLINE_VISIBILITY | |
| 1365 | typename __invoke_return2<type, _A0, _A1 const, _A2>::type | |
| 1366 | operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 1367 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1368 | } | |
| 1369 | ||
| 1370 | template <class _A0, class _A1, class _A2> | |
| 1371 | _LIBCPP_INLINE_VISIBILITY | |
| 1372 | typename __invoke_return2<type, _A0, _A1, _A2 const>::type | |
| 1373 | operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 1374 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1375 | } | |
| 1376 | ||
| 1377 | template <class _A0, class _A1, class _A2> | |
| 1378 | _LIBCPP_INLINE_VISIBILITY | |
| 1379 | typename __invoke_return2<type, _A0 const, _A1 const, _A2>::type | |
| 1380 | operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const { | |
| 1381 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1382 | } | |
| 1383 | ||
| 1384 | template <class _A0, class _A1, class _A2> | |
| 1385 | _LIBCPP_INLINE_VISIBILITY | |
| 1386 | typename __invoke_return2<type, _A0 const, _A1, _A2 const>::type | |
| 1387 | operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const { | |
| 1388 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1389 | } | |
| 1390 | ||
| 1391 | template <class _A0, class _A1, class _A2> | |
| 1392 | _LIBCPP_INLINE_VISIBILITY | |
| 1393 | typename __invoke_return2<type, _A0, _A1 const, _A2 const>::type | |
| 1394 | operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 1395 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1396 | } | |
| 1397 | ||
| 1398 | template <class _A0, class _A1, class _A2> | |
| 1399 | _LIBCPP_INLINE_VISIBILITY | |
| 1400 | typename __invoke_return2<type, _A0 const, _A1 const, _A2 const>::type | |
| 1401 | operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const { | |
| 1402 | return _VSTD::__invoke(__f_, __a0, __a1, __a2); | |
| 1403 | } | |
| 1404 | #endif | |
| 1405 | }; | |
| 1406 | ||
| 1407 | template<class _Rp, class _Tp> | |
| 1408 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1409 | __mem_fn<_Rp _Tp::*> | |
| 1410 | mem_fn(_Rp _Tp::* __pm) _NOEXCEPT | |
| 1411 | { | |
| 1412 | return __mem_fn<_Rp _Tp::*>(__pm); | |
| 1413 | } | |
| 1414 | ||
| 1415 | //////////////////////////////////////////////////////////////////////////////// | |
| 1416 | // FUNCTION | |
| 1417 | //============================================================================== | |
| 1418 | ||
| 1419 | // bad_function_call | |
| 1420 | ||
| 1421 | class _LIBCPP_EXCEPTION_ABI bad_function_call | |
| 1422 | : public exception | |
| 1423 | { | |
| 1424 | #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION | |
| 1425 | public: | |
| 1426 | virtual ~bad_function_call() _NOEXCEPT; | |
| 1427 | ||
| 1428 | virtual const char* what() const _NOEXCEPT; | |
| 1429 | #endif | |
| 1430 | }; | |
| 1431 | ||
| 1432 | _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY | |
| 1433 | void __throw_bad_function_call() | |
| 1434 | { | |
| 1435 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 1436 | throw bad_function_call(); | |
| 1437 | #else | |
| 1438 | _VSTD::abort(); | |
| 1439 | #endif | |
| 1440 | } | |
| 1441 | ||
| 1442 | #if defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) && __has_attribute(deprecated) | |
| 1443 | # define _LIBCPP_DEPRECATED_CXX03_FUNCTION \ | |
| 1444 | __attribute__((deprecated("Using std::function in C++03 is not supported anymore. Please upgrade to C++11 or later, or use a different type"))) | |
| 1445 | #else | |
| 1446 | # define _LIBCPP_DEPRECATED_CXX03_FUNCTION /* nothing */ | |
| 1447 | #endif | |
| 1448 | ||
| 1449 | template<class _Fp> class _LIBCPP_DEPRECATED_CXX03_FUNCTION _LIBCPP_TEMPLATE_VIS function; // undefined | |
| 1450 | ||
| 1451 | namespace __function | |
| 1452 | { | |
| 1453 | ||
| 1454 | template<class _Rp> | |
| 1455 | struct __maybe_derive_from_unary_function | |
| 1456 | { | |
| 1457 | }; | |
| 1458 | ||
| 1459 | template<class _Rp, class _A1> | |
| 1460 | struct __maybe_derive_from_unary_function<_Rp(_A1)> | |
| 1461 | : public unary_function<_A1, _Rp> | |
| 1462 | { | |
| 1463 | }; | |
| 1464 | ||
| 1465 | template<class _Rp> | |
| 1466 | struct __maybe_derive_from_binary_function | |
| 1467 | { | |
| 1468 | }; | |
| 1469 | ||
| 1470 | template<class _Rp, class _A1, class _A2> | |
| 1471 | struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> | |
| 1472 | : public binary_function<_A1, _A2, _Rp> | |
| 1473 | { | |
| 1474 | }; | |
| 1475 | ||
| 1476 | template <class _Fp> | |
| 1477 | _LIBCPP_INLINE_VISIBILITY | |
| 1478 | bool __not_null(_Fp const&) { return true; } | |
| 1479 | ||
| 1480 | template <class _Fp> | |
| 1481 | _LIBCPP_INLINE_VISIBILITY | |
| 1482 | bool __not_null(_Fp* __ptr) { return __ptr; } | |
| 1483 | ||
| 1484 | template <class _Ret, class _Class> | |
| 1485 | _LIBCPP_INLINE_VISIBILITY | |
| 1486 | bool __not_null(_Ret _Class::*__ptr) { return __ptr; } | |
| 1487 | ||
| 1488 | template <class _Fp> | |
| 1489 | _LIBCPP_INLINE_VISIBILITY | |
| 1490 | bool __not_null(function<_Fp> const& __f) { return !!__f; } | |
| 1491 | ||
| 1492 | #ifdef _LIBCPP_HAS_EXTENSION_BLOCKS | |
| 1493 | template <class _Rp, class ..._Args> | |
| 1494 | _LIBCPP_INLINE_VISIBILITY | |
| 1495 | bool __not_null(_Rp (^__p)(_Args...)) { return __p; } | |
| 1496 | #endif | |
| 1497 | ||
| 1498 | } // namespace __function | |
| 1499 | ||
| 1500 | #ifndef _LIBCPP_CXX03_LANG | |
| 1501 | ||
| 1502 | namespace __function { | |
| 1503 | ||
| 1504 | // __alloc_func holds a functor and an allocator. | |
| 1505 | ||
| 1506 | template <class _Fp, class _Ap, class _FB> class __alloc_func; | |
| 1507 | template <class _Fp, class _FB> | |
| 1508 | class __default_alloc_func; | |
| 1509 | ||
| 1510 | template <class _Fp, class _Ap, class _Rp, class... _ArgTypes> | |
| 1511 | class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> | |
| 1512 | { | |
| 1513 | __compressed_pair<_Fp, _Ap> __f_; | |
| 1514 | ||
| 1515 | public: | |
| 1516 | typedef _LIBCPP_NODEBUG_TYPE _Fp _Target; | |
| 1517 | typedef _LIBCPP_NODEBUG_TYPE _Ap _Alloc; | |
| 1518 | ||
| 1519 | _LIBCPP_INLINE_VISIBILITY | |
| 1520 | const _Target& __target() const { return __f_.first(); } | |
| 1521 | ||
| 1522 | // WIN32 APIs may define __allocator, so use __get_allocator instead. | |
| 1523 | _LIBCPP_INLINE_VISIBILITY | |
| 1524 | const _Alloc& __get_allocator() const { return __f_.second(); } | |
| 1525 | ||
| 1526 | _LIBCPP_INLINE_VISIBILITY | |
| 1527 | explicit __alloc_func(_Target&& __f) | |
| 1528 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), | |
| 1529 | _VSTD::forward_as_tuple()) | |
| 1530 | { | |
| 1531 | } | |
| 1532 | ||
| 1533 | _LIBCPP_INLINE_VISIBILITY | |
| 1534 | explicit __alloc_func(const _Target& __f, const _Alloc& __a) | |
| 1535 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), | |
| 1536 | _VSTD::forward_as_tuple(__a)) | |
| 1537 | { | |
| 1538 | } | |
| 1539 | ||
| 1540 | _LIBCPP_INLINE_VISIBILITY | |
| 1541 | explicit __alloc_func(const _Target& __f, _Alloc&& __a) | |
| 1542 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), | |
| 1543 | _VSTD::forward_as_tuple(_VSTD::move(__a))) | |
| 1544 | { | |
| 1545 | } | |
| 1546 | ||
| 1547 | _LIBCPP_INLINE_VISIBILITY | |
| 1548 | explicit __alloc_func(_Target&& __f, _Alloc&& __a) | |
| 1549 | : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), | |
| 1550 | _VSTD::forward_as_tuple(_VSTD::move(__a))) | |
| 1551 | { | |
| 1552 | } | |
| 1553 | ||
| 1554 | _LIBCPP_INLINE_VISIBILITY | |
| 1555 | _Rp operator()(_ArgTypes&&... __arg) | |
| 1556 | { | |
| 1557 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 1558 | return _Invoker::__call(__f_.first(), | |
| 1559 | _VSTD::forward<_ArgTypes>(__arg)...); | |
| 1560 | } | |
| 1561 | ||
| 1562 | _LIBCPP_INLINE_VISIBILITY | |
| 1563 | __alloc_func* __clone() const | |
| 1564 | { | |
| 1565 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1566 | typedef | |
| 1567 | typename __rebind_alloc_helper<__alloc_traits, __alloc_func>::type | |
| 1568 | _AA; | |
| 1569 | _AA __a(__f_.second()); | |
| 1570 | typedef __allocator_destructor<_AA> _Dp; | |
| 1571 | unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1572 | ::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a)); | |
| 1573 | return __hold.release(); | |
| 1574 | } | |
| 1575 | ||
| 1576 | _LIBCPP_INLINE_VISIBILITY | |
| 1577 | void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); } | |
| 1578 | ||
| 1579 | static void __destroy_and_delete(__alloc_func* __f) { | |
| 1580 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1581 | typedef typename __rebind_alloc_helper<__alloc_traits, __alloc_func>::type | |
| 1582 | _FunAlloc; | |
| 1583 | _FunAlloc __a(__f->__get_allocator()); | |
| 1584 | __f->destroy(); | |
| 1585 | __a.deallocate(__f, 1); | |
| 1586 | } | |
| 1587 | }; | |
| 1588 | ||
| 1589 | template <class _Fp, class _Rp, class... _ArgTypes> | |
| 1590 | class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> { | |
| 1591 | _Fp __f_; | |
| 1592 | ||
| 1593 | public: | |
| 1594 | typedef _LIBCPP_NODEBUG_TYPE _Fp _Target; | |
| 1595 | ||
| 1596 | _LIBCPP_INLINE_VISIBILITY | |
| 1597 | const _Target& __target() const { return __f_; } | |
| 1598 | ||
| 1599 | _LIBCPP_INLINE_VISIBILITY | |
| 1600 | explicit __default_alloc_func(_Target&& __f) : __f_(_VSTD::move(__f)) {} | |
| 1601 | ||
| 1602 | _LIBCPP_INLINE_VISIBILITY | |
| 1603 | explicit __default_alloc_func(const _Target& __f) : __f_(__f) {} | |
| 1604 | ||
| 1605 | _LIBCPP_INLINE_VISIBILITY | |
| 1606 | _Rp operator()(_ArgTypes&&... __arg) { | |
| 1607 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 1608 | return _Invoker::__call(__f_, _VSTD::forward<_ArgTypes>(__arg)...); | |
| 1609 | } | |
| 1610 | ||
| 1611 | _LIBCPP_INLINE_VISIBILITY | |
| 1612 | __default_alloc_func* __clone() const { | |
| 1613 | __builtin_new_allocator::__holder_t __hold = | |
| 1614 | __builtin_new_allocator::__allocate_type<__default_alloc_func>(1); | |
| 1615 | __default_alloc_func* __res = | |
| 1616 | ::new ((void*)__hold.get()) __default_alloc_func(__f_); | |
| 1617 | (void)__hold.release(); | |
| 1618 | return __res; | |
| 1619 | } | |
| 1620 | ||
| 1621 | _LIBCPP_INLINE_VISIBILITY | |
| 1622 | void destroy() _NOEXCEPT { __f_.~_Target(); } | |
| 1623 | ||
| 1624 | static void __destroy_and_delete(__default_alloc_func* __f) { | |
| 1625 | __f->destroy(); | |
| 1626 | __builtin_new_allocator::__deallocate_type<__default_alloc_func>(__f, 1); | |
| 1627 | } | |
| 1628 | }; | |
| 1629 | ||
| 1630 | // __base provides an abstract interface for copyable functors. | |
| 1631 | ||
| 1632 | template<class _Fp> class _LIBCPP_TEMPLATE_VIS __base; | |
| 1633 | ||
| 1634 | template<class _Rp, class ..._ArgTypes> | |
| 1635 | class __base<_Rp(_ArgTypes...)> | |
| 1636 | { | |
| 1637 | __base(const __base&); | |
| 1638 | __base& operator=(const __base&); | |
| 1639 | public: | |
| 1640 | _LIBCPP_INLINE_VISIBILITY __base() {} | |
| 1641 | _LIBCPP_INLINE_VISIBILITY virtual ~__base() {} | |
| 1642 | virtual __base* __clone() const = 0; | |
| 1643 | virtual void __clone(__base*) const = 0; | |
| 1644 | virtual void destroy() _NOEXCEPT = 0; | |
| 1645 | virtual void destroy_deallocate() _NOEXCEPT = 0; | |
| 1646 | virtual _Rp operator()(_ArgTypes&& ...) = 0; | |
| 1647 | #ifndef _LIBCPP_NO_RTTI | |
| 1648 | virtual const void* target(const type_info&) const _NOEXCEPT = 0; | |
| 1649 | virtual const std::type_info& target_type() const _NOEXCEPT = 0; | |
| 1650 | #endif // _LIBCPP_NO_RTTI | |
| 1651 | }; | |
| 1652 | ||
| 1653 | // __func implements __base for a given functor type. | |
| 1654 | ||
| 1655 | template<class _FD, class _Alloc, class _FB> class __func; | |
| 1656 | ||
| 1657 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1658 | class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> | |
| 1659 | : public __base<_Rp(_ArgTypes...)> | |
| 1660 | { | |
| 1661 | __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; | |
| 1662 | public: | |
| 1663 | _LIBCPP_INLINE_VISIBILITY | |
| 1664 | explicit __func(_Fp&& __f) | |
| 1665 | : __f_(_VSTD::move(__f)) {} | |
| 1666 | ||
| 1667 | _LIBCPP_INLINE_VISIBILITY | |
| 1668 | explicit __func(const _Fp& __f, const _Alloc& __a) | |
| 1669 | : __f_(__f, __a) {} | |
| 1670 | ||
| 1671 | _LIBCPP_INLINE_VISIBILITY | |
| 1672 | explicit __func(const _Fp& __f, _Alloc&& __a) | |
| 1673 | : __f_(__f, _VSTD::move(__a)) {} | |
| 1674 | ||
| 1675 | _LIBCPP_INLINE_VISIBILITY | |
| 1676 | explicit __func(_Fp&& __f, _Alloc&& __a) | |
| 1677 | : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} | |
| 1678 | ||
| 1679 | virtual __base<_Rp(_ArgTypes...)>* __clone() const; | |
| 1680 | virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; | |
| 1681 | virtual void destroy() _NOEXCEPT; | |
| 1682 | virtual void destroy_deallocate() _NOEXCEPT; | |
| 1683 | virtual _Rp operator()(_ArgTypes&&... __arg); | |
| 1684 | #ifndef _LIBCPP_NO_RTTI | |
| 1685 | virtual const void* target(const type_info&) const _NOEXCEPT; | |
| 1686 | virtual const std::type_info& target_type() const _NOEXCEPT; | |
| 1687 | #endif // _LIBCPP_NO_RTTI | |
| 1688 | }; | |
| 1689 | ||
| 1690 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1691 | __base<_Rp(_ArgTypes...)>* | |
| 1692 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const | |
| 1693 | { | |
| 1694 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1695 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1696 | _Ap __a(__f_.__get_allocator()); | |
| 1697 | typedef __allocator_destructor<_Ap> _Dp; | |
| 1698 | unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); | |
| 1699 | ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a)); | |
| 1700 | return __hold.release(); | |
| 1701 | } | |
| 1702 | ||
| 1703 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1704 | void | |
| 1705 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const | |
| 1706 | { | |
| 1707 | ::new ((void*)__p) __func(__f_.__target(), __f_.__get_allocator()); | |
| 1708 | } | |
| 1709 | ||
| 1710 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1711 | void | |
| 1712 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT | |
| 1713 | { | |
| 1714 | __f_.destroy(); | |
| 1715 | } | |
| 1716 | ||
| 1717 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1718 | void | |
| 1719 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT | |
| 1720 | { | |
| 1721 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1722 | typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; | |
| 1723 | _Ap __a(__f_.__get_allocator()); | |
| 1724 | __f_.destroy(); | |
| 1725 | __a.deallocate(this, 1); | |
| 1726 | } | |
| 1727 | ||
| 1728 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1729 | _Rp | |
| 1730 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) | |
| 1731 | { | |
| 1732 | return __f_(_VSTD::forward<_ArgTypes>(__arg)...); | |
| 1733 | } | |
| 1734 | ||
| 1735 | #ifndef _LIBCPP_NO_RTTI | |
| 1736 | ||
| 1737 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1738 | const void* | |
| 1739 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT | |
| 1740 | { | |
| 1741 | if (__ti == typeid(_Fp)) | |
| 1742 | return &__f_.__target(); | |
| 1743 | return nullptr; | |
| 1744 | } | |
| 1745 | ||
| 1746 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 1747 | const std::type_info& | |
| 1748 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT | |
| 1749 | { | |
| 1750 | return typeid(_Fp); | |
| 1751 | } | |
| 1752 | ||
| 1753 | #endif // _LIBCPP_NO_RTTI | |
| 1754 | ||
| 1755 | // __value_func creates a value-type from a __func. | |
| 1756 | ||
| 1757 | template <class _Fp> class __value_func; | |
| 1758 | ||
| 1759 | template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> | |
| 1760 | { | |
| 1761 | typename aligned_storage<3 * sizeof(void*)>::type __buf_; | |
| 1762 | ||
| 1763 | typedef __base<_Rp(_ArgTypes...)> __func; | |
| 1764 | __func* __f_; | |
| 1765 | ||
| 1766 | _LIBCPP_NO_CFI static __func* __as_base(void* p) | |
| 1767 | { | |
| 1768 | return reinterpret_cast<__func*>(p); | |
| 1769 | } | |
| 1770 | ||
| 1771 | public: | |
| 1772 | _LIBCPP_INLINE_VISIBILITY | |
| 1773 | __value_func() _NOEXCEPT : __f_(nullptr) {} | |
| 1774 | ||
| 1775 | template <class _Fp, class _Alloc> | |
| 1776 | _LIBCPP_INLINE_VISIBILITY __value_func(_Fp&& __f, const _Alloc& __a) | |
| 1777 | : __f_(nullptr) | |
| 1778 | { | |
| 1779 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 1780 | typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; | |
| 1781 | typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type | |
| 1782 | _FunAlloc; | |
| 1783 | ||
| 1784 | if (__function::__not_null(__f)) | |
| 1785 | { | |
| 1786 | _FunAlloc __af(__a); | |
| 1787 | if (sizeof(_Fun) <= sizeof(__buf_) && | |
| 1788 | is_nothrow_copy_constructible<_Fp>::value && | |
| 1789 | is_nothrow_copy_constructible<_FunAlloc>::value) | |
| 1790 | { | |
| 1791 | __f_ = | |
| 1792 | ::new ((void*)&__buf_) _Fun(_VSTD::move(__f), _Alloc(__af)); | |
| 1793 | } | |
| 1794 | else | |
| 1795 | { | |
| 1796 | typedef __allocator_destructor<_FunAlloc> _Dp; | |
| 1797 | unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); | |
| 1798 | ::new ((void*)__hold.get()) _Fun(_VSTD::move(__f), _Alloc(__a)); | |
| 1799 | __f_ = __hold.release(); | |
| 1800 | } | |
| 1801 | } | |
| 1802 | } | |
| 1803 | ||
| 1804 | template <class _Fp, | |
| 1805 | class = typename enable_if<!is_same<typename decay<_Fp>::type, __value_func>::value>::type> | |
| 1806 | _LIBCPP_INLINE_VISIBILITY explicit __value_func(_Fp&& __f) | |
| 1807 | : __value_func(_VSTD::forward<_Fp>(__f), allocator<_Fp>()) {} | |
| 1808 | ||
| 1809 | _LIBCPP_INLINE_VISIBILITY | |
| 1810 | __value_func(const __value_func& __f) | |
| 1811 | { | |
| 1812 | if (__f.__f_ == nullptr) | |
| 1813 | __f_ = nullptr; | |
| 1814 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 1815 | { | |
| 1816 | __f_ = __as_base(&__buf_); | |
| 1817 | __f.__f_->__clone(__f_); | |
| 1818 | } | |
| 1819 | else | |
| 1820 | __f_ = __f.__f_->__clone(); | |
| 1821 | } | |
| 1822 | ||
| 1823 | _LIBCPP_INLINE_VISIBILITY | |
| 1824 | __value_func(__value_func&& __f) _NOEXCEPT | |
| 1825 | { | |
| 1826 | if (__f.__f_ == nullptr) | |
| 1827 | __f_ = nullptr; | |
| 1828 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 1829 | { | |
| 1830 | __f_ = __as_base(&__buf_); | |
| 1831 | __f.__f_->__clone(__f_); | |
| 1832 | } | |
| 1833 | else | |
| 1834 | { | |
| 1835 | __f_ = __f.__f_; | |
| 1836 | __f.__f_ = nullptr; | |
| 1837 | } | |
| 1838 | } | |
| 1839 | ||
| 1840 | _LIBCPP_INLINE_VISIBILITY | |
| 1841 | ~__value_func() | |
| 1842 | { | |
| 1843 | if ((void*)__f_ == &__buf_) | |
| 1844 | __f_->destroy(); | |
| 1845 | else if (__f_) | |
| 1846 | __f_->destroy_deallocate(); | |
| 1847 | } | |
| 1848 | ||
| 1849 | _LIBCPP_INLINE_VISIBILITY | |
| 1850 | __value_func& operator=(__value_func&& __f) | |
| 1851 | { | |
| 1852 | *this = nullptr; | |
| 1853 | if (__f.__f_ == nullptr) | |
| 1854 | __f_ = nullptr; | |
| 1855 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 1856 | { | |
| 1857 | __f_ = __as_base(&__buf_); | |
| 1858 | __f.__f_->__clone(__f_); | |
| 1859 | } | |
| 1860 | else | |
| 1861 | { | |
| 1862 | __f_ = __f.__f_; | |
| 1863 | __f.__f_ = nullptr; | |
| 1864 | } | |
| 1865 | return *this; | |
| 1866 | } | |
| 1867 | ||
| 1868 | _LIBCPP_INLINE_VISIBILITY | |
| 1869 | __value_func& operator=(nullptr_t) | |
| 1870 | { | |
| 1871 | __func* __f = __f_; | |
| 1872 | __f_ = nullptr; | |
| 1873 | if ((void*)__f == &__buf_) | |
| 1874 | __f->destroy(); | |
| 1875 | else if (__f) | |
| 1876 | __f->destroy_deallocate(); | |
| 1877 | return *this; | |
| 1878 | } | |
| 1879 | ||
| 1880 | _LIBCPP_INLINE_VISIBILITY | |
| 1881 | _Rp operator()(_ArgTypes&&... __args) const | |
| 1882 | { | |
| 1883 | if (__f_ == nullptr) | |
| 1884 | __throw_bad_function_call(); | |
| 1885 | return (*__f_)(_VSTD::forward<_ArgTypes>(__args)...); | |
| 1886 | } | |
| 1887 | ||
| 1888 | _LIBCPP_INLINE_VISIBILITY | |
| 1889 | void swap(__value_func& __f) _NOEXCEPT | |
| 1890 | { | |
| 1891 | if (&__f == this) | |
| 1892 | return; | |
| 1893 | if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_) | |
| 1894 | { | |
| 1895 | typename aligned_storage<sizeof(__buf_)>::type __tempbuf; | |
| 1896 | __func* __t = __as_base(&__tempbuf); | |
| 1897 | __f_->__clone(__t); | |
| 1898 | __f_->destroy(); | |
| 1899 | __f_ = nullptr; | |
| 1900 | __f.__f_->__clone(__as_base(&__buf_)); | |
| 1901 | __f.__f_->destroy(); | |
| 1902 | __f.__f_ = nullptr; | |
| 1903 | __f_ = __as_base(&__buf_); | |
| 1904 | __t->__clone(__as_base(&__f.__buf_)); | |
| 1905 | __t->destroy(); | |
| 1906 | __f.__f_ = __as_base(&__f.__buf_); | |
| 1907 | } | |
| 1908 | else if ((void*)__f_ == &__buf_) | |
| 1909 | { | |
| 1910 | __f_->__clone(__as_base(&__f.__buf_)); | |
| 1911 | __f_->destroy(); | |
| 1912 | __f_ = __f.__f_; | |
| 1913 | __f.__f_ = __as_base(&__f.__buf_); | |
| 1914 | } | |
| 1915 | else if ((void*)__f.__f_ == &__f.__buf_) | |
| 1916 | { | |
| 1917 | __f.__f_->__clone(__as_base(&__buf_)); | |
| 1918 | __f.__f_->destroy(); | |
| 1919 | __f.__f_ = __f_; | |
| 1920 | __f_ = __as_base(&__buf_); | |
| 1921 | } | |
| 1922 | else | |
| 1923 | _VSTD::swap(__f_, __f.__f_); | |
| 1924 | } | |
| 1925 | ||
| 1926 | _LIBCPP_INLINE_VISIBILITY | |
| 1927 | _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT { return __f_ != nullptr; } | |
| 1928 | ||
| 1929 | #ifndef _LIBCPP_NO_RTTI | |
| 1930 | _LIBCPP_INLINE_VISIBILITY | |
| 1931 | const std::type_info& target_type() const _NOEXCEPT | |
| 1932 | { | |
| 1933 | if (__f_ == nullptr) | |
| 1934 | return typeid(void); | |
| 1935 | return __f_->target_type(); | |
| 1936 | } | |
| 1937 | ||
| 1938 | template <typename _Tp> | |
| 1939 | _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT | |
| 1940 | { | |
| 1941 | if (__f_ == nullptr) | |
| 1942 | return nullptr; | |
| 1943 | return (const _Tp*)__f_->target(typeid(_Tp)); | |
| 1944 | } | |
| 1945 | #endif // _LIBCPP_NO_RTTI | |
| 1946 | }; | |
| 1947 | ||
| 1948 | // Storage for a functor object, to be used with __policy to manage copy and | |
| 1949 | // destruction. | |
| 1950 | union __policy_storage | |
| 1951 | { | |
| 1952 | mutable char __small[sizeof(void*) * 2]; | |
| 1953 | void* __large; | |
| 1954 | }; | |
| 1955 | ||
| 1956 | // True if _Fun can safely be held in __policy_storage.__small. | |
| 1957 | template <typename _Fun> | |
| 1958 | struct __use_small_storage | |
| 1959 | : public _VSTD::integral_constant< | |
| 1960 | bool, sizeof(_Fun) <= sizeof(__policy_storage) && | |
| 1961 | _LIBCPP_ALIGNOF(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage) && | |
| 1962 | _VSTD::is_trivially_copy_constructible<_Fun>::value && | |
| 1963 | _VSTD::is_trivially_destructible<_Fun>::value> {}; | |
| 1964 | ||
| 1965 | // Policy contains information about how to copy, destroy, and move the | |
| 1966 | // underlying functor. You can think of it as a vtable of sorts. | |
| 1967 | struct __policy | |
| 1968 | { | |
| 1969 | // Used to copy or destroy __large values. null for trivial objects. | |
| 1970 | void* (*const __clone)(const void*); | |
| 1971 | void (*const __destroy)(void*); | |
| 1972 | ||
| 1973 | // True if this is the null policy (no value). | |
| 1974 | const bool __is_null; | |
| 1975 | ||
| 1976 | // The target type. May be null if RTTI is disabled. | |
| 1977 | const std::type_info* const __type_info; | |
| 1978 | ||
| 1979 | // Returns a pointer to a static policy object suitable for the functor | |
| 1980 | // type. | |
| 1981 | template <typename _Fun> | |
| 1982 | _LIBCPP_INLINE_VISIBILITY static const __policy* __create() | |
| 1983 | { | |
| 1984 | return __choose_policy<_Fun>(__use_small_storage<_Fun>()); | |
| 1985 | } | |
| 1986 | ||
| 1987 | _LIBCPP_INLINE_VISIBILITY | |
| 1988 | static const __policy* __create_empty() | |
| 1989 | { | |
| 1990 | static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, | |
| 1991 | true, | |
| 1992 | #ifndef _LIBCPP_NO_RTTI | |
| 1993 | &typeid(void) | |
| 1994 | #else | |
| 1995 | nullptr | |
| 1996 | #endif | |
| 1997 | }; | |
| 1998 | return &__policy_; | |
| 1999 | } | |
| 2000 | ||
| 2001 | private: | |
| 2002 | template <typename _Fun> static void* __large_clone(const void* __s) | |
| 2003 | { | |
| 2004 | const _Fun* __f = static_cast<const _Fun*>(__s); | |
| 2005 | return __f->__clone(); | |
| 2006 | } | |
| 2007 | ||
| 2008 | template <typename _Fun> | |
| 2009 | static void __large_destroy(void* __s) { | |
| 2010 | _Fun::__destroy_and_delete(static_cast<_Fun*>(__s)); | |
| 2011 | } | |
| 2012 | ||
| 2013 | template <typename _Fun> | |
| 2014 | _LIBCPP_INLINE_VISIBILITY static const __policy* | |
| 2015 | __choose_policy(/* is_small = */ false_type) { | |
| 2016 | static const _LIBCPP_CONSTEXPR __policy __policy_ = { | |
| 2017 | &__large_clone<_Fun>, &__large_destroy<_Fun>, false, | |
| 2018 | #ifndef _LIBCPP_NO_RTTI | |
| 2019 | &typeid(typename _Fun::_Target) | |
| 2020 | #else | |
| 2021 | nullptr | |
| 2022 | #endif | |
| 2023 | }; | |
| 2024 | return &__policy_; | |
| 2025 | } | |
| 2026 | ||
| 2027 | template <typename _Fun> | |
| 2028 | _LIBCPP_INLINE_VISIBILITY static const __policy* | |
| 2029 | __choose_policy(/* is_small = */ true_type) | |
| 2030 | { | |
| 2031 | static const _LIBCPP_CONSTEXPR __policy __policy_ = { | |
| 2032 | nullptr, nullptr, false, | |
| 2033 | #ifndef _LIBCPP_NO_RTTI | |
| 2034 | &typeid(typename _Fun::_Target) | |
| 2035 | #else | |
| 2036 | nullptr | |
| 2037 | #endif | |
| 2038 | }; | |
| 2039 | return &__policy_; | |
| 2040 | } | |
| 2041 | }; | |
| 2042 | ||
| 2043 | // Used to choose between perfect forwarding or pass-by-value. Pass-by-value is | |
| 2044 | // faster for types that can be passed in registers. | |
| 2045 | template <typename _Tp> | |
| 2046 | using __fast_forward = | |
| 2047 | typename _VSTD::conditional<_VSTD::is_scalar<_Tp>::value, _Tp, _Tp&&>::type; | |
| 2048 | ||
| 2049 | // __policy_invoker calls an instance of __alloc_func held in __policy_storage. | |
| 2050 | ||
| 2051 | template <class _Fp> struct __policy_invoker; | |
| 2052 | ||
| 2053 | template <class _Rp, class... _ArgTypes> | |
| 2054 | struct __policy_invoker<_Rp(_ArgTypes...)> | |
| 2055 | { | |
| 2056 | typedef _Rp (*__Call)(const __policy_storage*, | |
| 2057 | __fast_forward<_ArgTypes>...); | |
| 2058 | ||
| 2059 | __Call __call_; | |
| 2060 | ||
| 2061 | // Creates an invoker that throws bad_function_call. | |
| 2062 | _LIBCPP_INLINE_VISIBILITY | |
| 2063 | __policy_invoker() : __call_(&__call_empty) {} | |
| 2064 | ||
| 2065 | // Creates an invoker that calls the given instance of __func. | |
| 2066 | template <typename _Fun> | |
| 2067 | _LIBCPP_INLINE_VISIBILITY static __policy_invoker __create() | |
| 2068 | { | |
| 2069 | return __policy_invoker(&__call_impl<_Fun>); | |
| 2070 | } | |
| 2071 | ||
| 2072 | private: | |
| 2073 | _LIBCPP_INLINE_VISIBILITY | |
| 2074 | explicit __policy_invoker(__Call __c) : __call_(__c) {} | |
| 2075 | ||
| 2076 | static _Rp __call_empty(const __policy_storage*, | |
| 2077 | __fast_forward<_ArgTypes>...) | |
| 2078 | { | |
| 2079 | __throw_bad_function_call(); | |
| 2080 | } | |
| 2081 | ||
| 2082 | template <typename _Fun> | |
| 2083 | static _Rp __call_impl(const __policy_storage* __buf, | |
| 2084 | __fast_forward<_ArgTypes>... __args) | |
| 2085 | { | |
| 2086 | _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value | |
| 2087 | ? &__buf->__small | |
| 2088 | : __buf->__large); | |
| 2089 | return (*__f)(_VSTD::forward<_ArgTypes>(__args)...); | |
| 2090 | } | |
| 2091 | }; | |
| 2092 | ||
| 2093 | // __policy_func uses a __policy and __policy_invoker to create a type-erased, | |
| 2094 | // copyable functor. | |
| 2095 | ||
| 2096 | template <class _Fp> class __policy_func; | |
| 2097 | ||
| 2098 | template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> | |
| 2099 | { | |
| 2100 | // Inline storage for small objects. | |
| 2101 | __policy_storage __buf_; | |
| 2102 | ||
| 2103 | // Calls the value stored in __buf_. This could technically be part of | |
| 2104 | // policy, but storing it here eliminates a level of indirection inside | |
| 2105 | // operator(). | |
| 2106 | typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker; | |
| 2107 | __invoker __invoker_; | |
| 2108 | ||
| 2109 | // The policy that describes how to move / copy / destroy __buf_. Never | |
| 2110 | // null, even if the function is empty. | |
| 2111 | const __policy* __policy_; | |
| 2112 | ||
| 2113 | public: | |
| 2114 | _LIBCPP_INLINE_VISIBILITY | |
| 2115 | __policy_func() : __policy_(__policy::__create_empty()) {} | |
| 2116 | ||
| 2117 | template <class _Fp, class _Alloc> | |
| 2118 | _LIBCPP_INLINE_VISIBILITY __policy_func(_Fp&& __f, const _Alloc& __a) | |
| 2119 | : __policy_(__policy::__create_empty()) | |
| 2120 | { | |
| 2121 | typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; | |
| 2122 | typedef allocator_traits<_Alloc> __alloc_traits; | |
| 2123 | typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type | |
| 2124 | _FunAlloc; | |
| 2125 | ||
| 2126 | if (__function::__not_null(__f)) | |
| 2127 | { | |
| 2128 | __invoker_ = __invoker::template __create<_Fun>(); | |
| 2129 | __policy_ = __policy::__create<_Fun>(); | |
| 2130 | ||
| 2131 | _FunAlloc __af(__a); | |
| 2132 | if (__use_small_storage<_Fun>()) | |
| 2133 | { | |
| 2134 | ::new ((void*)&__buf_.__small) | |
| 2135 | _Fun(_VSTD::move(__f), _Alloc(__af)); | |
| 2136 | } | |
| 2137 | else | |
| 2138 | { | |
| 2139 | typedef __allocator_destructor<_FunAlloc> _Dp; | |
| 2140 | unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); | |
| 2141 | ::new ((void*)__hold.get()) | |
| 2142 | _Fun(_VSTD::move(__f), _Alloc(__af)); | |
| 2143 | __buf_.__large = __hold.release(); | |
| 2144 | } | |
| 2145 | } | |
| 2146 | } | |
| 2147 | ||
| 2148 | template <class _Fp, class = typename enable_if<!is_same<typename decay<_Fp>::type, __policy_func>::value>::type> | |
| 2149 | _LIBCPP_INLINE_VISIBILITY explicit __policy_func(_Fp&& __f) | |
| 2150 | : __policy_(__policy::__create_empty()) { | |
| 2151 | typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun; | |
| 2152 | ||
| 2153 | if (__function::__not_null(__f)) { | |
| 2154 | __invoker_ = __invoker::template __create<_Fun>(); | |
| 2155 | __policy_ = __policy::__create<_Fun>(); | |
| 2156 | if (__use_small_storage<_Fun>()) { | |
| 2157 | ::new ((void*)&__buf_.__small) _Fun(_VSTD::move(__f)); | |
| 2158 | } else { | |
| 2159 | __builtin_new_allocator::__holder_t __hold = | |
| 2160 | __builtin_new_allocator::__allocate_type<_Fun>(1); | |
| 2161 | __buf_.__large = ::new ((void*)__hold.get()) _Fun(_VSTD::move(__f)); | |
| 2162 | (void)__hold.release(); | |
| 2163 | } | |
| 2164 | } | |
| 2165 | } | |
| 2166 | ||
| 2167 | _LIBCPP_INLINE_VISIBILITY | |
| 2168 | __policy_func(const __policy_func& __f) | |
| 2169 | : __buf_(__f.__buf_), __invoker_(__f.__invoker_), | |
| 2170 | __policy_(__f.__policy_) | |
| 2171 | { | |
| 2172 | if (__policy_->__clone) | |
| 2173 | __buf_.__large = __policy_->__clone(__f.__buf_.__large); | |
| 2174 | } | |
| 2175 | ||
| 2176 | _LIBCPP_INLINE_VISIBILITY | |
| 2177 | __policy_func(__policy_func&& __f) | |
| 2178 | : __buf_(__f.__buf_), __invoker_(__f.__invoker_), | |
| 2179 | __policy_(__f.__policy_) | |
| 2180 | { | |
| 2181 | if (__policy_->__destroy) | |
| 2182 | { | |
| 2183 | __f.__policy_ = __policy::__create_empty(); | |
| 2184 | __f.__invoker_ = __invoker(); | |
| 2185 | } | |
| 2186 | } | |
| 2187 | ||
| 2188 | _LIBCPP_INLINE_VISIBILITY | |
| 2189 | ~__policy_func() | |
| 2190 | { | |
| 2191 | if (__policy_->__destroy) | |
| 2192 | __policy_->__destroy(__buf_.__large); | |
| 2193 | } | |
| 2194 | ||
| 2195 | _LIBCPP_INLINE_VISIBILITY | |
| 2196 | __policy_func& operator=(__policy_func&& __f) | |
| 2197 | { | |
| 2198 | *this = nullptr; | |
| 2199 | __buf_ = __f.__buf_; | |
| 2200 | __invoker_ = __f.__invoker_; | |
| 2201 | __policy_ = __f.__policy_; | |
| 2202 | __f.__policy_ = __policy::__create_empty(); | |
| 2203 | __f.__invoker_ = __invoker(); | |
| 2204 | return *this; | |
| 2205 | } | |
| 2206 | ||
| 2207 | _LIBCPP_INLINE_VISIBILITY | |
| 2208 | __policy_func& operator=(nullptr_t) | |
| 2209 | { | |
| 2210 | const __policy* __p = __policy_; | |
| 2211 | __policy_ = __policy::__create_empty(); | |
| 2212 | __invoker_ = __invoker(); | |
| 2213 | if (__p->__destroy) | |
| 2214 | __p->__destroy(__buf_.__large); | |
| 2215 | return *this; | |
| 2216 | } | |
| 2217 | ||
| 2218 | _LIBCPP_INLINE_VISIBILITY | |
| 2219 | _Rp operator()(_ArgTypes&&... __args) const | |
| 2220 | { | |
| 2221 | return __invoker_.__call_(_VSTD::addressof(__buf_), | |
| 2222 | _VSTD::forward<_ArgTypes>(__args)...); | |
| 2223 | } | |
| 2224 | ||
| 2225 | _LIBCPP_INLINE_VISIBILITY | |
| 2226 | void swap(__policy_func& __f) | |
| 2227 | { | |
| 2228 | _VSTD::swap(__invoker_, __f.__invoker_); | |
| 2229 | _VSTD::swap(__policy_, __f.__policy_); | |
| 2230 | _VSTD::swap(__buf_, __f.__buf_); | |
| 2231 | } | |
| 2232 | ||
| 2233 | _LIBCPP_INLINE_VISIBILITY | |
| 2234 | explicit operator bool() const _NOEXCEPT | |
| 2235 | { | |
| 2236 | return !__policy_->__is_null; | |
| 2237 | } | |
| 2238 | ||
| 2239 | #ifndef _LIBCPP_NO_RTTI | |
| 2240 | _LIBCPP_INLINE_VISIBILITY | |
| 2241 | const std::type_info& target_type() const _NOEXCEPT | |
| 2242 | { | |
| 2243 | return *__policy_->__type_info; | |
| 2244 | } | |
| 2245 | ||
| 2246 | template <typename _Tp> | |
| 2247 | _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT | |
| 2248 | { | |
| 2249 | if (__policy_->__is_null || typeid(_Tp) != *__policy_->__type_info) | |
| 2250 | return nullptr; | |
| 2251 | if (__policy_->__clone) // Out of line storage. | |
| 2252 | return reinterpret_cast<const _Tp*>(__buf_.__large); | |
| 2253 | else | |
| 2254 | return reinterpret_cast<const _Tp*>(&__buf_.__small); | |
| 2255 | } | |
| 2256 | #endif // _LIBCPP_NO_RTTI | |
| 2257 | }; | |
| 2258 | ||
| 2259 | #if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) && !defined(_LIBCPP_HAS_OBJC_ARC) | |
| 2260 | ||
| 2261 | extern "C" void *_Block_copy(const void *); | |
| 2262 | extern "C" void _Block_release(const void *); | |
| 2263 | ||
| 2264 | template<class _Rp1, class ..._ArgTypes1, class _Alloc, class _Rp, class ..._ArgTypes> | |
| 2265 | class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> | |
| 2266 | : public __base<_Rp(_ArgTypes...)> | |
| 2267 | { | |
| 2268 | typedef _Rp1(^__block_type)(_ArgTypes1...); | |
| 2269 | __block_type __f_; | |
| 2270 | ||
| 2271 | public: | |
| 2272 | _LIBCPP_INLINE_VISIBILITY | |
| 2273 | explicit __func(__block_type const& __f) | |
| 2274 | : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) | |
| 2275 | { } | |
| 2276 | ||
| 2277 | // [TODO] add && to save on a retain | |
| 2278 | ||
| 2279 | _LIBCPP_INLINE_VISIBILITY | |
| 2280 | explicit __func(__block_type __f, const _Alloc& /* unused */) | |
| 2281 | : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) | |
| 2282 | { } | |
| 2283 | ||
| 2284 | virtual __base<_Rp(_ArgTypes...)>* __clone() const { | |
| 2285 | _LIBCPP_ASSERT(false, | |
| 2286 | "Block pointers are just pointers, so they should always fit into " | |
| 2287 | "std::function's small buffer optimization. This function should " | |
| 2288 | "never be invoked."); | |
| 2289 | return nullptr; | |
| 2290 | } | |
| 2291 | ||
| 2292 | virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const { | |
| 2293 | ::new ((void*)__p) __func(__f_); | |
| 2294 | } | |
| 2295 | ||
| 2296 | virtual void destroy() _NOEXCEPT { | |
| 2297 | if (__f_) | |
| 2298 | _Block_release(__f_); | |
| 2299 | __f_ = 0; | |
| 2300 | } | |
| 2301 | ||
| 2302 | virtual void destroy_deallocate() _NOEXCEPT { | |
| 2303 | _LIBCPP_ASSERT(false, | |
| 2304 | "Block pointers are just pointers, so they should always fit into " | |
| 2305 | "std::function's small buffer optimization. This function should " | |
| 2306 | "never be invoked."); | |
| 2307 | } | |
| 2308 | ||
| 2309 | virtual _Rp operator()(_ArgTypes&& ... __arg) { | |
| 2310 | return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...); | |
| 2311 | } | |
| 2312 | ||
| 2313 | #ifndef _LIBCPP_NO_RTTI | |
| 2314 | virtual const void* target(type_info const& __ti) const _NOEXCEPT { | |
| 2315 | if (__ti == typeid(__func::__block_type)) | |
| 2316 | return &__f_; | |
| 2317 | return (const void*)nullptr; | |
| 2318 | } | |
| 2319 | ||
| 2320 | virtual const std::type_info& target_type() const _NOEXCEPT { | |
| 2321 | return typeid(__func::__block_type); | |
| 2322 | } | |
| 2323 | #endif // _LIBCPP_NO_RTTI | |
| 2324 | }; | |
| 2325 | ||
| 2326 | #endif // _LIBCPP_HAS_EXTENSION_BLOCKS && !_LIBCPP_HAS_OBJC_ARC | |
| 2327 | ||
| 2328 | } // __function | |
| 2329 | ||
| 2330 | template<class _Rp, class ..._ArgTypes> | |
| 2331 | class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> | |
| 2332 | : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>, | |
| 2333 | public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> | |
| 2334 | { | |
| 2335 | #ifndef _LIBCPP_ABI_OPTIMIZED_FUNCTION | |
| 2336 | typedef __function::__value_func<_Rp(_ArgTypes...)> __func; | |
| 2337 | #else | |
| 2338 | typedef __function::__policy_func<_Rp(_ArgTypes...)> __func; | |
| 2339 | #endif | |
| 2340 | ||
| 2341 | __func __f_; | |
| 2342 | ||
| 2343 | template <class _Fp, bool = _And< | |
| 2344 | _IsNotSame<__uncvref_t<_Fp>, function>, | |
| 2345 | __invokable<_Fp, _ArgTypes...> | |
| 2346 | >::value> | |
| 2347 | struct __callable; | |
| 2348 | template <class _Fp> | |
| 2349 | struct __callable<_Fp, true> | |
| 2350 | { | |
| 2351 | static const bool value = is_void<_Rp>::value || | |
| 2352 | __is_core_convertible<typename __invoke_of<_Fp, _ArgTypes...>::type, | |
| 2353 | _Rp>::value; | |
| 2354 | }; | |
| 2355 | template <class _Fp> | |
| 2356 | struct __callable<_Fp, false> | |
| 2357 | { | |
| 2358 | static const bool value = false; | |
| 2359 | }; | |
| 2360 | ||
| 2361 | template <class _Fp> | |
| 2362 | using _EnableIfLValueCallable = typename enable_if<__callable<_Fp&>::value>::type; | |
| 2363 | public: | |
| 2364 | typedef _Rp result_type; | |
| 2365 | ||
| 2366 | // construct/copy/destroy: | |
| 2367 | _LIBCPP_INLINE_VISIBILITY | |
| 2368 | function() _NOEXCEPT { } | |
| 2369 | _LIBCPP_INLINE_VISIBILITY | |
| 2370 | function(nullptr_t) _NOEXCEPT {} | |
| 2371 | function(const function&); | |
| 2372 | function(function&&) _NOEXCEPT; | |
| 2373 | template<class _Fp, class = _EnableIfLValueCallable<_Fp>> | |
| 2374 | function(_Fp); | |
| 2375 | ||
| 2376 | #if _LIBCPP_STD_VER <= 14 | |
| 2377 | template<class _Alloc> | |
| 2378 | _LIBCPP_INLINE_VISIBILITY | |
| 2379 | function(allocator_arg_t, const _Alloc&) _NOEXCEPT {} | |
| 2380 | template<class _Alloc> | |
| 2381 | _LIBCPP_INLINE_VISIBILITY | |
| 2382 | function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT {} | |
| 2383 | template<class _Alloc> | |
| 2384 | function(allocator_arg_t, const _Alloc&, const function&); | |
| 2385 | template<class _Alloc> | |
| 2386 | function(allocator_arg_t, const _Alloc&, function&&); | |
| 2387 | template<class _Fp, class _Alloc, class = _EnableIfLValueCallable<_Fp>> | |
| 2388 | function(allocator_arg_t, const _Alloc& __a, _Fp __f); | |
| 2389 | #endif | |
| 2390 | ||
| 2391 | function& operator=(const function&); | |
| 2392 | function& operator=(function&&) _NOEXCEPT; | |
| 2393 | function& operator=(nullptr_t) _NOEXCEPT; | |
| 2394 | template<class _Fp, class = _EnableIfLValueCallable<typename decay<_Fp>::type>> | |
| 2395 | function& operator=(_Fp&&); | |
| 2396 | ||
| 2397 | ~function(); | |
| 2398 | ||
| 2399 | // function modifiers: | |
| 2400 | void swap(function&) _NOEXCEPT; | |
| 2401 | ||
| 2402 | #if _LIBCPP_STD_VER <= 14 | |
| 2403 | template<class _Fp, class _Alloc> | |
| 2404 | _LIBCPP_INLINE_VISIBILITY | |
| 2405 | void assign(_Fp&& __f, const _Alloc& __a) | |
| 2406 | {function(allocator_arg, __a, _VSTD::forward<_Fp>(__f)).swap(*this);} | |
| 2407 | #endif | |
| 2408 | ||
| 2409 | // function capacity: | |
| 2410 | _LIBCPP_INLINE_VISIBILITY | |
| 2411 | _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT { | |
| 2412 | return static_cast<bool>(__f_); | |
| 2413 | } | |
| 2414 | ||
| 2415 | // deleted overloads close possible hole in the type system | |
| 2416 | template<class _R2, class... _ArgTypes2> | |
| 2417 | bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete; | |
| 2418 | template<class _R2, class... _ArgTypes2> | |
| 2419 | bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete; | |
| 2420 | public: | |
| 2421 | // function invocation: | |
| 2422 | _Rp operator()(_ArgTypes...) const; | |
| 2423 | ||
| 2424 | #ifndef _LIBCPP_NO_RTTI | |
| 2425 | // function target access: | |
| 2426 | const std::type_info& target_type() const _NOEXCEPT; | |
| 2427 | template <typename _Tp> _Tp* target() _NOEXCEPT; | |
| 2428 | template <typename _Tp> const _Tp* target() const _NOEXCEPT; | |
| 2429 | #endif // _LIBCPP_NO_RTTI | |
| 2430 | }; | |
| 2431 | ||
| 2432 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 2433 | template<class _Rp, class ..._Ap> | |
| 2434 | function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>; | |
| 2435 | ||
| 2436 | template<class _Fp> | |
| 2437 | struct __strip_signature; | |
| 2438 | ||
| 2439 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2440 | struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; | |
| 2441 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2442 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); }; | |
| 2443 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2444 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); }; | |
| 2445 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2446 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); }; | |
| 2447 | ||
| 2448 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2449 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); }; | |
| 2450 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2451 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); }; | |
| 2452 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2453 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); }; | |
| 2454 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2455 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); }; | |
| 2456 | ||
| 2457 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2458 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); }; | |
| 2459 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2460 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); }; | |
| 2461 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2462 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); }; | |
| 2463 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2464 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); }; | |
| 2465 | ||
| 2466 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2467 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); }; | |
| 2468 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2469 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); }; | |
| 2470 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2471 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; | |
| 2472 | template<class _Rp, class _Gp, class ..._Ap> | |
| 2473 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); }; | |
| 2474 | ||
| 2475 | template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type> | |
| 2476 | function(_Fp) -> function<_Stripped>; | |
| 2477 | #endif // !_LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 2478 | ||
| 2479 | template<class _Rp, class ..._ArgTypes> | |
| 2480 | function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {} | |
| 2481 | ||
| 2482 | #if _LIBCPP_STD_VER <= 14 | |
| 2483 | template<class _Rp, class ..._ArgTypes> | |
| 2484 | template <class _Alloc> | |
| 2485 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, | |
| 2486 | const function& __f) : __f_(__f.__f_) {} | |
| 2487 | #endif | |
| 2488 | ||
| 2489 | template <class _Rp, class... _ArgTypes> | |
| 2490 | function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPT | |
| 2491 | : __f_(_VSTD::move(__f.__f_)) {} | |
| 2492 | ||
| 2493 | #if _LIBCPP_STD_VER <= 14 | |
| 2494 | template<class _Rp, class ..._ArgTypes> | |
| 2495 | template <class _Alloc> | |
| 2496 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, | |
| 2497 | function&& __f) | |
| 2498 | : __f_(_VSTD::move(__f.__f_)) {} | |
| 2499 | #endif | |
| 2500 | ||
| 2501 | template <class _Rp, class... _ArgTypes> | |
| 2502 | template <class _Fp, class> | |
| 2503 | function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(_VSTD::move(__f)) {} | |
| 2504 | ||
| 2505 | #if _LIBCPP_STD_VER <= 14 | |
| 2506 | template <class _Rp, class... _ArgTypes> | |
| 2507 | template <class _Fp, class _Alloc, class> | |
| 2508 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, | |
| 2509 | _Fp __f) | |
| 2510 | : __f_(_VSTD::move(__f), __a) {} | |
| 2511 | #endif | |
| 2512 | ||
| 2513 | template<class _Rp, class ..._ArgTypes> | |
| 2514 | function<_Rp(_ArgTypes...)>& | |
| 2515 | function<_Rp(_ArgTypes...)>::operator=(const function& __f) | |
| 2516 | { | |
| 2517 | function(__f).swap(*this); | |
| 2518 | return *this; | |
| 2519 | } | |
| 2520 | ||
| 2521 | template<class _Rp, class ..._ArgTypes> | |
| 2522 | function<_Rp(_ArgTypes...)>& | |
| 2523 | function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT | |
| 2524 | { | |
| 2525 | __f_ = _VSTD::move(__f.__f_); | |
| 2526 | return *this; | |
| 2527 | } | |
| 2528 | ||
| 2529 | template<class _Rp, class ..._ArgTypes> | |
| 2530 | function<_Rp(_ArgTypes...)>& | |
| 2531 | function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT | |
| 2532 | { | |
| 2533 | __f_ = nullptr; | |
| 2534 | return *this; | |
| 2535 | } | |
| 2536 | ||
| 2537 | template<class _Rp, class ..._ArgTypes> | |
| 2538 | template <class _Fp, class> | |
| 2539 | function<_Rp(_ArgTypes...)>& | |
| 2540 | function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) | |
| 2541 | { | |
| 2542 | function(_VSTD::forward<_Fp>(__f)).swap(*this); | |
| 2543 | return *this; | |
| 2544 | } | |
| 2545 | ||
| 2546 | template<class _Rp, class ..._ArgTypes> | |
| 2547 | function<_Rp(_ArgTypes...)>::~function() {} | |
| 2548 | ||
| 2549 | template<class _Rp, class ..._ArgTypes> | |
| 2550 | void | |
| 2551 | function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT | |
| 2552 | { | |
| 2553 | __f_.swap(__f.__f_); | |
| 2554 | } | |
| 2555 | ||
| 2556 | template<class _Rp, class ..._ArgTypes> | |
| 2557 | _Rp | |
| 2558 | function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const | |
| 2559 | { | |
| 2560 | return __f_(_VSTD::forward<_ArgTypes>(__arg)...); | |
| 2561 | } | |
| 2562 | ||
| 2563 | #ifndef _LIBCPP_NO_RTTI | |
| 2564 | ||
| 2565 | template<class _Rp, class ..._ArgTypes> | |
| 2566 | const std::type_info& | |
| 2567 | function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPT | |
| 2568 | { | |
| 2569 | return __f_.target_type(); | |
| 2570 | } | |
| 2571 | ||
| 2572 | template<class _Rp, class ..._ArgTypes> | |
| 2573 | template <typename _Tp> | |
| 2574 | _Tp* | |
| 2575 | function<_Rp(_ArgTypes...)>::target() _NOEXCEPT | |
| 2576 | { | |
| 2577 | return (_Tp*)(__f_.template target<_Tp>()); | |
| 2578 | } | |
| 2579 | ||
| 2580 | template<class _Rp, class ..._ArgTypes> | |
| 2581 | template <typename _Tp> | |
| 2582 | const _Tp* | |
| 2583 | function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT | |
| 2584 | { | |
| 2585 | return __f_.template target<_Tp>(); | |
| 2586 | } | |
| 2587 | ||
| 2588 | #endif // _LIBCPP_NO_RTTI | |
| 2589 | ||
| 2590 | template <class _Rp, class... _ArgTypes> | |
| 2591 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2592 | bool | |
| 2593 | operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return !__f;} | |
| 2594 | ||
| 2595 | template <class _Rp, class... _ArgTypes> | |
| 2596 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2597 | bool | |
| 2598 | operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return !__f;} | |
| 2599 | ||
| 2600 | template <class _Rp, class... _ArgTypes> | |
| 2601 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2602 | bool | |
| 2603 | operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return (bool)__f;} | |
| 2604 | ||
| 2605 | template <class _Rp, class... _ArgTypes> | |
| 2606 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2607 | bool | |
| 2608 | operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return (bool)__f;} | |
| 2609 | ||
| 2610 | template <class _Rp, class... _ArgTypes> | |
| 2611 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2612 | void | |
| 2613 | swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCEPT | |
| 2614 | {return __x.swap(__y);} | |
| 2615 | ||
| 2616 | #else // _LIBCPP_CXX03_LANG | |
| 2617 | ||
| 2618 | #include <__functional_03> | |
| 2619 | ||
| 2620 | #endif | |
| 2621 | ||
| 2622 | //////////////////////////////////////////////////////////////////////////////// | |
| 2623 | // BIND | |
| 2624 | //============================================================================== | |
| 2625 | ||
| 2626 | template<class _Tp> struct __is_bind_expression : public false_type {}; | |
| 2627 | template<class _Tp> struct _LIBCPP_TEMPLATE_VIS is_bind_expression | |
| 2628 | : public __is_bind_expression<typename remove_cv<_Tp>::type> {}; | |
| 2629 | ||
| 2630 | #if _LIBCPP_STD_VER > 14 | |
| 2631 | template <class _Tp> | |
| 2632 | _LIBCPP_INLINE_VAR constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; | |
| 2633 | #endif | |
| 2634 | ||
| 2635 | template<class _Tp> struct __is_placeholder : public integral_constant<int, 0> {}; | |
| 2636 | template<class _Tp> struct _LIBCPP_TEMPLATE_VIS is_placeholder | |
| 2637 | : public __is_placeholder<typename remove_cv<_Tp>::type> {}; | |
| 2638 | ||
| 2639 | #if _LIBCPP_STD_VER > 14 | |
| 2640 | template <class _Tp> | |
| 2641 | _LIBCPP_INLINE_VAR constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value; | |
| 2642 | #endif | |
| 2643 | ||
| 2644 | namespace placeholders | |
| 2645 | { | |
| 2646 | ||
| 2647 | template <int _Np> struct __ph {}; | |
| 2648 | ||
| 2649 | #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 2650 | _LIBCPP_FUNC_VIS extern const __ph<1> _1; | |
| 2651 | _LIBCPP_FUNC_VIS extern const __ph<2> _2; | |
| 2652 | _LIBCPP_FUNC_VIS extern const __ph<3> _3; | |
| 2653 | _LIBCPP_FUNC_VIS extern const __ph<4> _4; | |
| 2654 | _LIBCPP_FUNC_VIS extern const __ph<5> _5; | |
| 2655 | _LIBCPP_FUNC_VIS extern const __ph<6> _6; | |
| 2656 | _LIBCPP_FUNC_VIS extern const __ph<7> _7; | |
| 2657 | _LIBCPP_FUNC_VIS extern const __ph<8> _8; | |
| 2658 | _LIBCPP_FUNC_VIS extern const __ph<9> _9; | |
| 2659 | _LIBCPP_FUNC_VIS extern const __ph<10> _10; | |
| 2660 | #else | |
| 2661 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<1> _1{}; | |
| 2662 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<2> _2{}; | |
| 2663 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<3> _3{}; | |
| 2664 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<4> _4{}; | |
| 2665 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<5> _5{}; | |
| 2666 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<6> _6{}; | |
| 2667 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<7> _7{}; | |
| 2668 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<8> _8{}; | |
| 2669 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<9> _9{}; | |
| 2670 | /* _LIBCPP_INLINE_VAR */ constexpr __ph<10> _10{}; | |
| 2671 | #endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 2672 | ||
| 2673 | } // placeholders | |
| 2674 | ||
| 2675 | template<int _Np> | |
| 2676 | struct __is_placeholder<placeholders::__ph<_Np> > | |
| 2677 | : public integral_constant<int, _Np> {}; | |
| 2678 | ||
| 2679 | ||
| 2680 | #ifndef _LIBCPP_CXX03_LANG | |
| 2681 | ||
| 2682 | template <class _Tp, class _Uj> | |
| 2683 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2684 | _Tp& | |
| 2685 | __mu(reference_wrapper<_Tp> __t, _Uj&) | |
| 2686 | { | |
| 2687 | return __t.get(); | |
| 2688 | } | |
| 2689 | ||
| 2690 | template <class _Ti, class ..._Uj, size_t ..._Indx> | |
| 2691 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2692 | typename __invoke_of<_Ti&, _Uj...>::type | |
| 2693 | __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) | |
| 2694 | { | |
| 2695 | return __ti(_VSTD::forward<_Uj>(_VSTD::get<_Indx>(__uj))...); | |
| 2696 | } | |
| 2697 | ||
| 2698 | template <class _Ti, class ..._Uj> | |
| 2699 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2700 | typename _EnableIf | |
| 2701 | < | |
| 2702 | is_bind_expression<_Ti>::value, | |
| 2703 | __invoke_of<_Ti&, _Uj...> | |
| 2704 | >::type | |
| 2705 | __mu(_Ti& __ti, tuple<_Uj...>& __uj) | |
| 2706 | { | |
| 2707 | typedef typename __make_tuple_indices<sizeof...(_Uj)>::type __indices; | |
| 2708 | return _VSTD::__mu_expand(__ti, __uj, __indices()); | |
| 2709 | } | |
| 2710 | ||
| 2711 | template <bool IsPh, class _Ti, class _Uj> | |
| 2712 | struct __mu_return2 {}; | |
| 2713 | ||
| 2714 | template <class _Ti, class _Uj> | |
| 2715 | struct __mu_return2<true, _Ti, _Uj> | |
| 2716 | { | |
| 2717 | typedef typename tuple_element<is_placeholder<_Ti>::value - 1, _Uj>::type type; | |
| 2718 | }; | |
| 2719 | ||
| 2720 | template <class _Ti, class _Uj> | |
| 2721 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2722 | typename enable_if | |
| 2723 | < | |
| 2724 | 0 < is_placeholder<_Ti>::value, | |
| 2725 | typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type | |
| 2726 | >::type | |
| 2727 | __mu(_Ti&, _Uj& __uj) | |
| 2728 | { | |
| 2729 | const size_t _Indx = is_placeholder<_Ti>::value - 1; | |
| 2730 | return _VSTD::forward<typename tuple_element<_Indx, _Uj>::type>(_VSTD::get<_Indx>(__uj)); | |
| 2731 | } | |
| 2732 | ||
| 2733 | template <class _Ti, class _Uj> | |
| 2734 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2735 | typename enable_if | |
| 2736 | < | |
| 2737 | !is_bind_expression<_Ti>::value && | |
| 2738 | is_placeholder<_Ti>::value == 0 && | |
| 2739 | !__is_reference_wrapper<_Ti>::value, | |
| 2740 | _Ti& | |
| 2741 | >::type | |
| 2742 | __mu(_Ti& __ti, _Uj&) | |
| 2743 | { | |
| 2744 | return __ti; | |
| 2745 | } | |
| 2746 | ||
| 2747 | template <class _Ti, bool IsReferenceWrapper, bool IsBindEx, bool IsPh, | |
| 2748 | class _TupleUj> | |
| 2749 | struct __mu_return_impl; | |
| 2750 | ||
| 2751 | template <bool _Invokable, class _Ti, class ..._Uj> | |
| 2752 | struct __mu_return_invokable // false | |
| 2753 | { | |
| 2754 | typedef __nat type; | |
| 2755 | }; | |
| 2756 | ||
| 2757 | template <class _Ti, class ..._Uj> | |
| 2758 | struct __mu_return_invokable<true, _Ti, _Uj...> | |
| 2759 | { | |
| 2760 | typedef typename __invoke_of<_Ti&, _Uj...>::type type; | |
| 2761 | }; | |
| 2762 | ||
| 2763 | template <class _Ti, class ..._Uj> | |
| 2764 | struct __mu_return_impl<_Ti, false, true, false, tuple<_Uj...> > | |
| 2765 | : public __mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...> | |
| 2766 | { | |
| 2767 | }; | |
| 2768 | ||
| 2769 | template <class _Ti, class _TupleUj> | |
| 2770 | struct __mu_return_impl<_Ti, false, false, true, _TupleUj> | |
| 2771 | { | |
| 2772 | typedef typename tuple_element<is_placeholder<_Ti>::value - 1, | |
| 2773 | _TupleUj>::type&& type; | |
| 2774 | }; | |
| 2775 | ||
| 2776 | template <class _Ti, class _TupleUj> | |
| 2777 | struct __mu_return_impl<_Ti, true, false, false, _TupleUj> | |
| 2778 | { | |
| 2779 | typedef typename _Ti::type& type; | |
| 2780 | }; | |
| 2781 | ||
| 2782 | template <class _Ti, class _TupleUj> | |
| 2783 | struct __mu_return_impl<_Ti, false, false, false, _TupleUj> | |
| 2784 | { | |
| 2785 | typedef _Ti& type; | |
| 2786 | }; | |
| 2787 | ||
| 2788 | template <class _Ti, class _TupleUj> | |
| 2789 | struct __mu_return | |
| 2790 | : public __mu_return_impl<_Ti, | |
| 2791 | __is_reference_wrapper<_Ti>::value, | |
| 2792 | is_bind_expression<_Ti>::value, | |
| 2793 | 0 < is_placeholder<_Ti>::value && | |
| 2794 | is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value, | |
| 2795 | _TupleUj> | |
| 2796 | { | |
| 2797 | }; | |
| 2798 | ||
| 2799 | template <class _Fp, class _BoundArgs, class _TupleUj> | |
| 2800 | struct __is_valid_bind_return | |
| 2801 | { | |
| 2802 | static const bool value = false; | |
| 2803 | }; | |
| 2804 | ||
| 2805 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 2806 | struct __is_valid_bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj> | |
| 2807 | { | |
| 2808 | static const bool value = __invokable<_Fp, | |
| 2809 | typename __mu_return<_BoundArgs, _TupleUj>::type...>::value; | |
| 2810 | }; | |
| 2811 | ||
| 2812 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 2813 | struct __is_valid_bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj> | |
| 2814 | { | |
| 2815 | static const bool value = __invokable<_Fp, | |
| 2816 | typename __mu_return<const _BoundArgs, _TupleUj>::type...>::value; | |
| 2817 | }; | |
| 2818 | ||
| 2819 | template <class _Fp, class _BoundArgs, class _TupleUj, | |
| 2820 | bool = __is_valid_bind_return<_Fp, _BoundArgs, _TupleUj>::value> | |
| 2821 | struct __bind_return; | |
| 2822 | ||
| 2823 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 2824 | struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true> | |
| 2825 | { | |
| 2826 | typedef typename __invoke_of | |
| 2827 | < | |
| 2828 | _Fp&, | |
| 2829 | typename __mu_return | |
| 2830 | < | |
| 2831 | _BoundArgs, | |
| 2832 | _TupleUj | |
| 2833 | >::type... | |
| 2834 | >::type type; | |
| 2835 | }; | |
| 2836 | ||
| 2837 | template <class _Fp, class ..._BoundArgs, class _TupleUj> | |
| 2838 | struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> | |
| 2839 | { | |
| 2840 | typedef typename __invoke_of | |
| 2841 | < | |
| 2842 | _Fp&, | |
| 2843 | typename __mu_return | |
| 2844 | < | |
| 2845 | const _BoundArgs, | |
| 2846 | _TupleUj | |
| 2847 | >::type... | |
| 2848 | >::type type; | |
| 2849 | }; | |
| 2850 | ||
| 2851 | template <class _Fp, class _BoundArgs, size_t ..._Indx, class _Args> | |
| 2852 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2853 | typename __bind_return<_Fp, _BoundArgs, _Args>::type | |
| 2854 | __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, | |
| 2855 | _Args&& __args) | |
| 2856 | { | |
| 2857 | return _VSTD::__invoke(__f, _VSTD::__mu(_VSTD::get<_Indx>(__bound_args), __args)...); | |
| 2858 | } | |
| 2859 | ||
| 2860 | template<class _Fp, class ..._BoundArgs> | |
| 2861 | class __bind | |
| 2862 | : public __weak_result_type<typename decay<_Fp>::type> | |
| 2863 | { | |
| 2864 | protected: | |
| 2865 | typedef typename decay<_Fp>::type _Fd; | |
| 2866 | typedef tuple<typename decay<_BoundArgs>::type...> _Td; | |
| 2867 | private: | |
| 2868 | _Fd __f_; | |
| 2869 | _Td __bound_args_; | |
| 2870 | ||
| 2871 | typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices; | |
| 2872 | public: | |
| 2873 | template <class _Gp, class ..._BA, | |
| 2874 | class = typename enable_if | |
| 2875 | < | |
| 2876 | is_constructible<_Fd, _Gp>::value && | |
| 2877 | !is_same<typename remove_reference<_Gp>::type, | |
| 2878 | __bind>::value | |
| 2879 | >::type> | |
| 2880 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2881 | explicit __bind(_Gp&& __f, _BA&& ...__bound_args) | |
| 2882 | : __f_(_VSTD::forward<_Gp>(__f)), | |
| 2883 | __bound_args_(_VSTD::forward<_BA>(__bound_args)...) {} | |
| 2884 | ||
| 2885 | template <class ..._Args> | |
| 2886 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2887 | typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type | |
| 2888 | operator()(_Args&& ...__args) | |
| 2889 | { | |
| 2890 | return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), | |
| 2891 | tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); | |
| 2892 | } | |
| 2893 | ||
| 2894 | template <class ..._Args> | |
| 2895 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2896 | typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type | |
| 2897 | operator()(_Args&& ...__args) const | |
| 2898 | { | |
| 2899 | return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), | |
| 2900 | tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); | |
| 2901 | } | |
| 2902 | }; | |
| 2903 | ||
| 2904 | template<class _Fp, class ..._BoundArgs> | |
| 2905 | struct __is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; | |
| 2906 | ||
| 2907 | template<class _Rp, class _Fp, class ..._BoundArgs> | |
| 2908 | class __bind_r | |
| 2909 | : public __bind<_Fp, _BoundArgs...> | |
| 2910 | { | |
| 2911 | typedef __bind<_Fp, _BoundArgs...> base; | |
| 2912 | typedef typename base::_Fd _Fd; | |
| 2913 | typedef typename base::_Td _Td; | |
| 2914 | public: | |
| 2915 | typedef _Rp result_type; | |
| 2916 | ||
| 2917 | ||
| 2918 | template <class _Gp, class ..._BA, | |
| 2919 | class = typename enable_if | |
| 2920 | < | |
| 2921 | is_constructible<_Fd, _Gp>::value && | |
| 2922 | !is_same<typename remove_reference<_Gp>::type, | |
| 2923 | __bind_r>::value | |
| 2924 | >::type> | |
| 2925 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2926 | explicit __bind_r(_Gp&& __f, _BA&& ...__bound_args) | |
| 2927 | : base(_VSTD::forward<_Gp>(__f), | |
| 2928 | _VSTD::forward<_BA>(__bound_args)...) {} | |
| 2929 | ||
| 2930 | template <class ..._Args> | |
| 2931 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2932 | typename enable_if | |
| 2933 | < | |
| 2934 | is_convertible<typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type, | |
| 2935 | result_type>::value || is_void<_Rp>::value, | |
| 2936 | result_type | |
| 2937 | >::type | |
| 2938 | operator()(_Args&& ...__args) | |
| 2939 | { | |
| 2940 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 2941 | return _Invoker::__call(static_cast<base&>(*this), _VSTD::forward<_Args>(__args)...); | |
| 2942 | } | |
| 2943 | ||
| 2944 | template <class ..._Args> | |
| 2945 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2946 | typename enable_if | |
| 2947 | < | |
| 2948 | is_convertible<typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type, | |
| 2949 | result_type>::value || is_void<_Rp>::value, | |
| 2950 | result_type | |
| 2951 | >::type | |
| 2952 | operator()(_Args&& ...__args) const | |
| 2953 | { | |
| 2954 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; | |
| 2955 | return _Invoker::__call(static_cast<base const&>(*this), _VSTD::forward<_Args>(__args)...); | |
| 2956 | } | |
| 2957 | }; | |
| 2958 | ||
| 2959 | template<class _Rp, class _Fp, class ..._BoundArgs> | |
| 2960 | struct __is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; | |
| 2961 | ||
| 2962 | template<class _Fp, class ..._BoundArgs> | |
| 2963 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2964 | __bind<_Fp, _BoundArgs...> | |
| 2965 | bind(_Fp&& __f, _BoundArgs&&... __bound_args) | |
| 2966 | { | |
| 2967 | typedef __bind<_Fp, _BoundArgs...> type; | |
| 2968 | return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); | |
| 2969 | } | |
| 2970 | ||
| 2971 | template<class _Rp, class _Fp, class ..._BoundArgs> | |
| 2972 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2973 | __bind_r<_Rp, _Fp, _BoundArgs...> | |
| 2974 | bind(_Fp&& __f, _BoundArgs&&... __bound_args) | |
| 2975 | { | |
| 2976 | typedef __bind_r<_Rp, _Fp, _BoundArgs...> type; | |
| 2977 | return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); | |
| 2978 | } | |
| 2979 | ||
| 2980 | #endif // _LIBCPP_CXX03_LANG | |
| 2981 | ||
| 2982 | #if _LIBCPP_STD_VER > 14 | |
| 2983 | ||
| 2984 | template <class _Fn, class ..._Args> | |
| 2985 | _LIBCPP_CONSTEXPR_AFTER_CXX17 invoke_result_t<_Fn, _Args...> | |
| 2986 | invoke(_Fn&& __f, _Args&&... __args) | |
| 2987 | noexcept(is_nothrow_invocable_v<_Fn, _Args...>) | |
| 2988 | { | |
| 2989 | return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); | |
| 2990 | } | |
| 2991 | ||
| 2992 | template <class _DecayFunc> | |
| 2993 | class _LIBCPP_TEMPLATE_VIS __not_fn_imp { | |
| 2994 | _DecayFunc __fd; | |
| 2995 | ||
| 2996 | public: | |
| 2997 | __not_fn_imp() = delete; | |
| 2998 | ||
| 2999 | template <class ..._Args> | |
| 3000 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3001 | auto operator()(_Args&& ...__args) & | |
| 3002 | noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))) | |
| 3003 | -> decltype( !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)) | |
| 3004 | { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); } | |
| 3005 | ||
| 3006 | template <class ..._Args> | |
| 3007 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3008 | auto operator()(_Args&& ...__args) && | |
| 3009 | noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))) | |
| 3010 | -> decltype( !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)) | |
| 3011 | { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); } | |
| 3012 | ||
| 3013 | template <class ..._Args> | |
| 3014 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3015 | auto operator()(_Args&& ...__args) const& | |
| 3016 | noexcept(noexcept(!_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...))) | |
| 3017 | -> decltype( !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...)) | |
| 3018 | { return !_VSTD::invoke(__fd, _VSTD::forward<_Args>(__args)...); } | |
| 3019 | ||
| 3020 | ||
| 3021 | template <class ..._Args> | |
| 3022 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3023 | auto operator()(_Args&& ...__args) const&& | |
| 3024 | noexcept(noexcept(!_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...))) | |
| 3025 | -> decltype( !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...)) | |
| 3026 | { return !_VSTD::invoke(_VSTD::move(__fd), _VSTD::forward<_Args>(__args)...); } | |
| 3027 | ||
| 3028 | private: | |
| 3029 | template <class _RawFunc, | |
| 3030 | class = enable_if_t<!is_same<decay_t<_RawFunc>, __not_fn_imp>::value>> | |
| 3031 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3032 | explicit __not_fn_imp(_RawFunc&& __rf) | |
| 3033 | : __fd(_VSTD::forward<_RawFunc>(__rf)) {} | |
| 3034 | ||
| 3035 | template <class _RawFunc> | |
| 3036 | friend inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3037 | __not_fn_imp<decay_t<_RawFunc>> not_fn(_RawFunc&&); | |
| 3038 | }; | |
| 3039 | ||
| 3040 | template <class _RawFunc> | |
| 3041 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3042 | __not_fn_imp<decay_t<_RawFunc>> not_fn(_RawFunc&& __fn) { | |
| 3043 | return __not_fn_imp<decay_t<_RawFunc>>(_VSTD::forward<_RawFunc>(__fn)); | |
| 3044 | } | |
| 3045 | ||
| 3046 | #endif | |
| 3047 | ||
| 3048 | // struct hash<T*> in <memory> | |
| 3049 | ||
| 3050 | template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2> | |
| 3051 | pair<_ForwardIterator1, _ForwardIterator1> _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 3052 | __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, | |
| 3053 | _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred, | |
| 3054 | forward_iterator_tag, forward_iterator_tag) | |
| 3055 | { | |
| 3056 | if (__first2 == __last2) | |
| 3057 | return _VSTD::make_pair(__first1, __first1); // Everything matches an empty sequence | |
| 3058 | while (true) | |
| 3059 | { | |
| 3060 | // Find first element in sequence 1 that matchs *__first2, with a mininum of loop checks | |
| 3061 | while (true) | |
| 3062 | { | |
| 3063 | if (__first1 == __last1) // return __last1 if no element matches *__first2 | |
| 3064 | return _VSTD::make_pair(__last1, __last1); | |
| 3065 | if (__pred(*__first1, *__first2)) | |
| 3066 | break; | |
| 3067 | ++__first1; | |
| 3068 | } | |
| 3069 | // *__first1 matches *__first2, now match elements after here | |
| 3070 | _ForwardIterator1 __m1 = __first1; | |
| 3071 | _ForwardIterator2 __m2 = __first2; | |
| 3072 | while (true) | |
| 3073 | { | |
| 3074 | if (++__m2 == __last2) // If pattern exhausted, __first1 is the answer (works for 1 element pattern) | |
| 3075 | return _VSTD::make_pair(__first1, __m1); | |
| 3076 | if (++__m1 == __last1) // Otherwise if source exhaused, pattern not found | |
| 3077 | return _VSTD::make_pair(__last1, __last1); | |
| 3078 | if (!__pred(*__m1, *__m2)) // if there is a mismatch, restart with a new __first1 | |
| 3079 | { | |
| 3080 | ++__first1; | |
| 3081 | break; | |
| 3082 | } // else there is a match, check next elements | |
| 3083 | } | |
| 3084 | } | |
| 3085 | } | |
| 3086 | ||
| 3087 | template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> | |
| 3088 | _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 3089 | pair<_RandomAccessIterator1, _RandomAccessIterator1> | |
| 3090 | __search(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, | |
| 3091 | _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __pred, | |
| 3092 | random_access_iterator_tag, random_access_iterator_tag) | |
| 3093 | { | |
| 3094 | typedef typename iterator_traits<_RandomAccessIterator1>::difference_type _D1; | |
| 3095 | typedef typename iterator_traits<_RandomAccessIterator2>::difference_type _D2; | |
| 3096 | // Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern | |
| 3097 | const _D2 __len2 = __last2 - __first2; | |
| 3098 | if (__len2 == 0) | |
| 3099 | return _VSTD::make_pair(__first1, __first1); | |
| 3100 | const _D1 __len1 = __last1 - __first1; | |
| 3101 | if (__len1 < __len2) | |
| 3102 | return _VSTD::make_pair(__last1, __last1); | |
| 3103 | const _RandomAccessIterator1 __s = __last1 - (__len2 - 1); // Start of pattern match can't go beyond here | |
| 3104 | ||
| 3105 | while (true) | |
| 3106 | { | |
| 3107 | while (true) | |
| 3108 | { | |
| 3109 | if (__first1 == __s) | |
| 3110 | return _VSTD::make_pair(__last1, __last1); | |
| 3111 | if (__pred(*__first1, *__first2)) | |
| 3112 | break; | |
| 3113 | ++__first1; | |
| 3114 | } | |
| 3115 | ||
| 3116 | _RandomAccessIterator1 __m1 = __first1; | |
| 3117 | _RandomAccessIterator2 __m2 = __first2; | |
| 3118 | while (true) | |
| 3119 | { | |
| 3120 | if (++__m2 == __last2) | |
| 3121 | return _VSTD::make_pair(__first1, __first1 + __len2); | |
| 3122 | ++__m1; // no need to check range on __m1 because __s guarantees we have enough source | |
| 3123 | if (!__pred(*__m1, *__m2)) | |
| 3124 | { | |
| 3125 | ++__first1; | |
| 3126 | break; | |
| 3127 | } | |
| 3128 | } | |
| 3129 | } | |
| 3130 | } | |
| 3131 | ||
| 3132 | #if _LIBCPP_STD_VER > 14 | |
| 3133 | ||
| 3134 | // default searcher | |
| 3135 | template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> | |
| 3136 | class _LIBCPP_TYPE_VIS default_searcher { | |
| 3137 | public: | |
| 3138 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3139 | default_searcher(_ForwardIterator __f, _ForwardIterator __l, | |
| 3140 | _BinaryPredicate __p = _BinaryPredicate()) | |
| 3141 | : __first_(__f), __last_(__l), __pred_(__p) {} | |
| 3142 | ||
| 3143 | template <typename _ForwardIterator2> | |
| 3144 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3145 | pair<_ForwardIterator2, _ForwardIterator2> | |
| 3146 | operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const | |
| 3147 | { | |
| 3148 | return _VSTD::__search(__f, __l, __first_, __last_, __pred_, | |
| 3149 | typename _VSTD::iterator_traits<_ForwardIterator>::iterator_category(), | |
| 3150 | typename _VSTD::iterator_traits<_ForwardIterator2>::iterator_category()); | |
| 3151 | } | |
| 3152 | ||
| 3153 | private: | |
| 3154 | _ForwardIterator __first_; | |
| 3155 | _ForwardIterator __last_; | |
| 3156 | _BinaryPredicate __pred_; | |
| 3157 | }; | |
| 3158 | ||
| 3159 | #endif // _LIBCPP_STD_VER > 14 | |
| 3160 | ||
| 3161 | #if _LIBCPP_STD_VER > 17 | |
| 3162 | template <class _Tp> | |
| 3163 | using unwrap_reference_t = typename unwrap_reference<_Tp>::type; | |
| 3164 | ||
| 3165 | template <class _Tp> | |
| 3166 | using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; | |
| 3167 | #endif // > C++17 | |
| 3168 | ||
| 3169 | template <class _Container, class _Predicate> | |
| 3170 | inline typename _Container::size_type | |
| 3171 | __libcpp_erase_if_container(_Container& __c, _Predicate __pred) { | |
| 3172 | typename _Container::size_type __old_size = __c.size(); | |
| 3173 | ||
| 3174 | const typename _Container::iterator __last = __c.end(); | |
| 3175 | for (typename _Container::iterator __iter = __c.begin(); __iter != __last;) { | |
| 3176 | if (__pred(*__iter)) | |
| 3177 | __iter = __c.erase(__iter); | |
| 3178 | else | |
| 3179 | ++__iter; | |
| 3180 | } | |
| 3181 | ||
| 3182 | return __old_size - __c.size(); | |
| 3183 | } | |
| 3184 | ||
| 3185 | _LIBCPP_END_NAMESPACE_STD | |
| 3186 | ||
| 3187 | #endif // _LIBCPP_FUNCTIONAL | |
| 529 | #endif // _LIBCPP_FUNCTIONAL |
lib/libcxx/include/future+29-26| ... | ... | @@ -361,13 +361,18 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; |
| 361 | 361 | |
| 362 | 362 | */ |
| 363 | 363 | |
| 364 | #include <__config> | |
| 365 | 364 | #include <__availability> |
| 366 | #include <system_error> | |
| 367 | #include <memory> | |
| 365 | #include <__config> | |
| 366 | #include <__debug> | |
| 367 | #include <__memory/allocator_arg_t.h> | |
| 368 | #include <__memory/uses_allocator.h> | |
| 369 | #include <__utility/__decay_copy.h> | |
| 370 | #include <__utility/forward.h> | |
| 368 | 371 | #include <chrono> |
| 369 | 372 | #include <exception> |
| 373 | #include <memory> | |
| 370 | 374 | #include <mutex> |
| 375 | #include <system_error> | |
| 371 | 376 | #include <thread> |
| 372 | 377 | |
| 373 | 378 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -467,7 +472,7 @@ operator^=(launch& __x, launch __y) |
| 467 | 472 | __x = __x ^ __y; return __x; |
| 468 | 473 | } |
| 469 | 474 | |
| 470 | #endif // !_LIBCPP_HAS_NO_STRONG_ENUMS | |
| 475 | #endif // !_LIBCPP_HAS_NO_STRONG_ENUMS | |
| 471 | 476 | |
| 472 | 477 | //enum class future_status |
| 473 | 478 | _LIBCPP_DECLARE_STRONG_ENUM(future_status) |
| ... | ... | @@ -501,9 +506,7 @@ class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_FUTURE_ERROR future_error |
| 501 | 506 | error_code __ec_; |
| 502 | 507 | public: |
| 503 | 508 | future_error(error_code __ec); |
| 504 | #if _LIBCPP_STD_VERS > 14 | |
| 505 | explicit future_error(future_errc _Ev) : logic_error(), __ec_(make_error_code(_Ev)) {} | |
| 506 | #endif | |
| 509 | ||
| 507 | 510 | _LIBCPP_INLINE_VISIBILITY |
| 508 | 511 | const error_code& code() const _NOEXCEPT {return __ec_;} |
| 509 | 512 | |
| ... | ... | @@ -862,7 +865,7 @@ __deferred_assoc_state<_Rp, _Fp>::__execute() |
| 862 | 865 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 863 | 866 | try |
| 864 | 867 | { |
| 865 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 868 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 866 | 869 | this->set_value(__func_()); |
| 867 | 870 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 868 | 871 | } |
| ... | ... | @@ -870,7 +873,7 @@ __deferred_assoc_state<_Rp, _Fp>::__execute() |
| 870 | 873 | { |
| 871 | 874 | this->set_exception(current_exception()); |
| 872 | 875 | } |
| 873 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 876 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 874 | 877 | } |
| 875 | 878 | |
| 876 | 879 | template <class _Fp> |
| ... | ... | @@ -903,7 +906,7 @@ __deferred_assoc_state<void, _Fp>::__execute() |
| 903 | 906 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 904 | 907 | try |
| 905 | 908 | { |
| 906 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 909 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 907 | 910 | __func_(); |
| 908 | 911 | this->set_value(); |
| 909 | 912 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -912,7 +915,7 @@ __deferred_assoc_state<void, _Fp>::__execute() |
| 912 | 915 | { |
| 913 | 916 | this->set_exception(current_exception()); |
| 914 | 917 | } |
| 915 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 918 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 916 | 919 | } |
| 917 | 920 | |
| 918 | 921 | template <class _Rp, class _Fp> |
| ... | ... | @@ -945,7 +948,7 @@ __async_assoc_state<_Rp, _Fp>::__execute() |
| 945 | 948 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 946 | 949 | try |
| 947 | 950 | { |
| 948 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 951 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 949 | 952 | this->set_value(__func_()); |
| 950 | 953 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 951 | 954 | } |
| ... | ... | @@ -953,7 +956,7 @@ __async_assoc_state<_Rp, _Fp>::__execute() |
| 953 | 956 | { |
| 954 | 957 | this->set_exception(current_exception()); |
| 955 | 958 | } |
| 956 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 959 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 957 | 960 | } |
| 958 | 961 | |
| 959 | 962 | template <class _Rp, class _Fp> |
| ... | ... | @@ -994,7 +997,7 @@ __async_assoc_state<void, _Fp>::__execute() |
| 994 | 997 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 995 | 998 | try |
| 996 | 999 | { |
| 997 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1000 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 998 | 1001 | __func_(); |
| 999 | 1002 | this->set_value(); |
| 1000 | 1003 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -1003,7 +1006,7 @@ __async_assoc_state<void, _Fp>::__execute() |
| 1003 | 1006 | { |
| 1004 | 1007 | this->set_exception(current_exception()); |
| 1005 | 1008 | } |
| 1006 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1009 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1007 | 1010 | } |
| 1008 | 1011 | |
| 1009 | 1012 | template <class _Fp> |
| ... | ... | @@ -1953,7 +1956,7 @@ packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) |
| 1953 | 1956 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1954 | 1957 | try |
| 1955 | 1958 | { |
| 1956 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1959 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1957 | 1960 | __p_.set_value(__f_(_VSTD::forward<_ArgTypes>(__args)...)); |
| 1958 | 1961 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1959 | 1962 | } |
| ... | ... | @@ -1961,7 +1964,7 @@ packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) |
| 1961 | 1964 | { |
| 1962 | 1965 | __p_.set_exception(current_exception()); |
| 1963 | 1966 | } |
| 1964 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1967 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1965 | 1968 | } |
| 1966 | 1969 | |
| 1967 | 1970 | template<class _Rp, class ..._ArgTypes> |
| ... | ... | @@ -1975,7 +1978,7 @@ packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) |
| 1975 | 1978 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1976 | 1979 | try |
| 1977 | 1980 | { |
| 1978 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1981 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1979 | 1982 | __p_.set_value_at_thread_exit(__f_(_VSTD::forward<_ArgTypes>(__args)...)); |
| 1980 | 1983 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1981 | 1984 | } |
| ... | ... | @@ -1983,7 +1986,7 @@ packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) |
| 1983 | 1986 | { |
| 1984 | 1987 | __p_.set_exception_at_thread_exit(current_exception()); |
| 1985 | 1988 | } |
| 1986 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1989 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1987 | 1990 | } |
| 1988 | 1991 | |
| 1989 | 1992 | template<class _Rp, class ..._ArgTypes> |
| ... | ... | @@ -2082,7 +2085,7 @@ packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) |
| 2082 | 2085 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2083 | 2086 | try |
| 2084 | 2087 | { |
| 2085 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2088 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2086 | 2089 | __f_(_VSTD::forward<_ArgTypes>(__args)...); |
| 2087 | 2090 | __p_.set_value(); |
| 2088 | 2091 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2091,7 +2094,7 @@ packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) |
| 2091 | 2094 | { |
| 2092 | 2095 | __p_.set_exception(current_exception()); |
| 2093 | 2096 | } |
| 2094 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2097 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2095 | 2098 | } |
| 2096 | 2099 | |
| 2097 | 2100 | template<class ..._ArgTypes> |
| ... | ... | @@ -2105,7 +2108,7 @@ packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args |
| 2105 | 2108 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2106 | 2109 | try |
| 2107 | 2110 | { |
| 2108 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2111 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2109 | 2112 | __f_(_VSTD::forward<_ArgTypes>(__args)...); |
| 2110 | 2113 | __p_.set_value_at_thread_exit(); |
| 2111 | 2114 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2114,7 +2117,7 @@ packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args |
| 2114 | 2117 | { |
| 2115 | 2118 | __p_.set_exception_at_thread_exit(current_exception()); |
| 2116 | 2119 | } |
| 2117 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2120 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2118 | 2121 | } |
| 2119 | 2122 | |
| 2120 | 2123 | template<class ..._ArgTypes> |
| ... | ... | @@ -2126,10 +2129,10 @@ packaged_task<void(_ArgTypes...)>::reset() |
| 2126 | 2129 | __p_ = promise<result_type>(); |
| 2127 | 2130 | } |
| 2128 | 2131 | |
| 2129 | template <class _Callable> | |
| 2132 | template <class _Rp, class... _ArgTypes> | |
| 2130 | 2133 | inline _LIBCPP_INLINE_VISIBILITY |
| 2131 | 2134 | void |
| 2132 | swap(packaged_task<_Callable>& __x, packaged_task<_Callable>& __y) _NOEXCEPT | |
| 2135 | swap(packaged_task<_Rp(_ArgTypes...)>& __x, packaged_task<_Rp(_ArgTypes...)>& __y) _NOEXCEPT | |
| 2133 | 2136 | { |
| 2134 | 2137 | __x.swap(__y); |
| 2135 | 2138 | } |
| ... | ... | @@ -2456,4 +2459,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 2456 | 2459 | |
| 2457 | 2460 | #endif // !_LIBCPP_HAS_NO_THREADS |
| 2458 | 2461 | |
| 2459 | #endif // _LIBCPP_FUTURE | |
| 2462 | #endif // _LIBCPP_FUTURE |
lib/libcxx/include/initializer_list+2-2| ... | ... | @@ -110,8 +110,8 @@ end(initializer_list<_Ep> __il) _NOEXCEPT |
| 110 | 110 | return __il.end(); |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 113 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 114 | 114 | |
| 115 | 115 | } // std |
| 116 | 116 | |
| 117 | #endif // _LIBCPP_INITIALIZER_LIST | |
| 117 | #endif // _LIBCPP_INITIALIZER_LIST |
lib/libcxx/include/inttypes.h+1-1| ... | ... | @@ -259,4 +259,4 @@ uintmax_t wcstoumax(const wchar_t* restrict nptr, wchar_t** restrict endptr, int |
| 259 | 259 | |
| 260 | 260 | #endif // __cplusplus |
| 261 | 261 | |
| 262 | #endif // _LIBCPP_INTTYPES_H | |
| 262 | #endif // _LIBCPP_INTTYPES_H |
lib/libcxx/include/iomanip+10-10| ... | ... | @@ -304,7 +304,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t7<_MoneyT>& __x) |
| 304 | 304 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 305 | 305 | try |
| 306 | 306 | { |
| 307 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 307 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 308 | 308 | typename basic_istream<_CharT, _Traits>::sentry __s(__is); |
| 309 | 309 | if (__s) |
| 310 | 310 | { |
| ... | ... | @@ -321,7 +321,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t7<_MoneyT>& __x) |
| 321 | 321 | { |
| 322 | 322 | __is.__set_badbit_and_consider_rethrow(); |
| 323 | 323 | } |
| 324 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 324 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 325 | 325 | return __is; |
| 326 | 326 | } |
| 327 | 327 | |
| ... | ... | @@ -364,7 +364,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t8<_MoneyT>& __x) |
| 364 | 364 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 365 | 365 | try |
| 366 | 366 | { |
| 367 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 367 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 368 | 368 | typename basic_ostream<_CharT, _Traits>::sentry __s(__os); |
| 369 | 369 | if (__s) |
| 370 | 370 | { |
| ... | ... | @@ -380,7 +380,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t8<_MoneyT>& __x) |
| 380 | 380 | { |
| 381 | 381 | __os.__set_badbit_and_consider_rethrow(); |
| 382 | 382 | } |
| 383 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 383 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 384 | 384 | return __os; |
| 385 | 385 | } |
| 386 | 386 | |
| ... | ... | @@ -423,7 +423,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t9<_CharT>& __x) |
| 423 | 423 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 424 | 424 | try |
| 425 | 425 | { |
| 426 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 426 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 427 | 427 | typename basic_istream<_CharT, _Traits>::sentry __s(__is); |
| 428 | 428 | if (__s) |
| 429 | 429 | { |
| ... | ... | @@ -441,7 +441,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t9<_CharT>& __x) |
| 441 | 441 | { |
| 442 | 442 | __is.__set_badbit_and_consider_rethrow(); |
| 443 | 443 | } |
| 444 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 444 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 445 | 445 | return __is; |
| 446 | 446 | } |
| 447 | 447 | |
| ... | ... | @@ -484,7 +484,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t10<_CharT>& __x) |
| 484 | 484 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 485 | 485 | try |
| 486 | 486 | { |
| 487 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 487 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 488 | 488 | typename basic_ostream<_CharT, _Traits>::sentry __s(__os); |
| 489 | 489 | if (__s) |
| 490 | 490 | { |
| ... | ... | @@ -501,7 +501,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t10<_CharT>& __x) |
| 501 | 501 | { |
| 502 | 502 | __os.__set_badbit_and_consider_rethrow(); |
| 503 | 503 | } |
| 504 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 504 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 505 | 505 | return __os; |
| 506 | 506 | } |
| 507 | 507 | |
| ... | ... | @@ -518,7 +518,7 @@ basic_ostream<_CharT, _Traits> & |
| 518 | 518 | __quoted_output ( basic_ostream<_CharT, _Traits> &__os, |
| 519 | 519 | _ForwardIterator __first, _ForwardIterator __last, _CharT __delim, _CharT __escape ) |
| 520 | 520 | { |
| 521 | _VSTD::basic_string<_CharT, _Traits> __str; | |
| 521 | basic_string<_CharT, _Traits> __str; | |
| 522 | 522 | __str.push_back(__delim); |
| 523 | 523 | for ( ; __first != __last; ++ __first ) |
| 524 | 524 | { |
| ... | ... | @@ -667,4 +667,4 @@ quoted (basic_string_view <_CharT, _Traits> __sv, |
| 667 | 667 | |
| 668 | 668 | _LIBCPP_END_NAMESPACE_STD |
| 669 | 669 | |
| 670 | #endif // _LIBCPP_IOMANIP | |
| 670 | #endif // _LIBCPP_IOMANIP |
lib/libcxx/include/ios+7-19| ... | ... | @@ -211,8 +211,8 @@ storage-class-specifier const error_category& iostream_category() noexcept; |
| 211 | 211 | */ |
| 212 | 212 | |
| 213 | 213 | #include <__config> |
| 214 | #include <iosfwd> | |
| 215 | 214 | #include <__locale> |
| 215 | #include <iosfwd> | |
| 216 | 216 | #include <system_error> |
| 217 | 217 | |
| 218 | 218 | #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) |
| ... | ... | @@ -591,13 +591,6 @@ ios_base::exceptions(iostate __iostate) |
| 591 | 591 | clear(__rdstate_); |
| 592 | 592 | } |
| 593 | 593 | |
| 594 | #if defined(_LIBCPP_CXX03_LANG) | |
| 595 | struct _LIBCPP_TYPE_VIS __cxx03_bool { | |
| 596 | typedef void (__cxx03_bool::*__bool_type)(); | |
| 597 | void __true_value() {} | |
| 598 | }; | |
| 599 | #endif | |
| 600 | ||
| 601 | 594 | template <class _CharT, class _Traits> |
| 602 | 595 | class _LIBCPP_TEMPLATE_VIS basic_ios |
| 603 | 596 | : public ios_base |
| ... | ... | @@ -614,17 +607,14 @@ public: |
| 614 | 607 | static_assert((is_same<_CharT, typename traits_type::char_type>::value), |
| 615 | 608 | "traits_type::char_type must be the same type as CharT"); |
| 616 | 609 | |
| 617 | // __true_value will generate undefined references when linking unless | |
| 618 | // we give it internal linkage. | |
| 619 | ||
| 620 | #if defined(_LIBCPP_CXX03_LANG) | |
| 610 | #ifdef _LIBCPP_CXX03_LANG | |
| 611 | // Preserve the ability to compare with literal 0, | |
| 612 | // and implicitly convert to bool, but not implicitly convert to int. | |
| 621 | 613 | _LIBCPP_INLINE_VISIBILITY |
| 622 | operator __cxx03_bool::__bool_type() const { | |
| 623 | return !fail() ? &__cxx03_bool::__true_value : nullptr; | |
| 624 | } | |
| 614 | operator void*() const {return fail() ? nullptr : (void*)this;} | |
| 625 | 615 | #else |
| 626 | 616 | _LIBCPP_INLINE_VISIBILITY |
| 627 | _LIBCPP_EXPLICIT operator bool() const {return !fail();} | |
| 617 | explicit operator bool() const {return !fail();} | |
| 628 | 618 | #endif |
| 629 | 619 | |
| 630 | 620 | _LIBCPP_INLINE_VISIBILITY bool operator!() const {return fail();} |
| ... | ... | @@ -679,10 +669,8 @@ protected: |
| 679 | 669 | |
| 680 | 670 | _LIBCPP_INLINE_VISIBILITY |
| 681 | 671 | void move(basic_ios& __rhs); |
| 682 | #ifndef _LIBCPP_CXX03_LANG | |
| 683 | 672 | _LIBCPP_INLINE_VISIBILITY |
| 684 | 673 | void move(basic_ios&& __rhs) {move(__rhs);} |
| 685 | #endif | |
| 686 | 674 | _LIBCPP_INLINE_VISIBILITY |
| 687 | 675 | void swap(basic_ios& __rhs) _NOEXCEPT; |
| 688 | 676 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1037,4 +1025,4 @@ defaultfloat(ios_base& __str) |
| 1037 | 1025 | |
| 1038 | 1026 | _LIBCPP_END_NAMESPACE_STD |
| 1039 | 1027 | |
| 1040 | #endif // _LIBCPP_IOS | |
| 1028 | #endif // _LIBCPP_IOS |
lib/libcxx/include/iosfwd+9-6| ... | ... | @@ -84,8 +84,11 @@ typedef basic_ofstream<wchar_t> wofstream; |
| 84 | 84 | typedef basic_fstream<wchar_t> wfstream; |
| 85 | 85 | |
| 86 | 86 | template <class state> class fpos; |
| 87 | typedef fpos<char_traits<char>::state_type> streampos; | |
| 88 | typedef fpos<char_traits<wchar_t>::state_type> wstreampos; | |
| 87 | using streampos = fpos<char_traits<char>::state_type>; | |
| 88 | using wstreampos = fpos<char_traits<wchar_t>::state_type>; | |
| 89 | using u8streampos = fpos<char_traits<char8_t>::state_type>; // C++20 | |
| 90 | using u16streampos = fpos<char_traits<char16_t>::state_type>; | |
| 91 | using u32streampos = fpos<char_traits<char32_t>::state_type>; | |
| 89 | 92 | |
| 90 | 93 | } // std |
| 91 | 94 | |
| ... | ... | @@ -104,7 +107,7 @@ class _LIBCPP_TYPE_VIS ios_base; |
| 104 | 107 | |
| 105 | 108 | template<class _CharT> struct _LIBCPP_TEMPLATE_VIS char_traits; |
| 106 | 109 | template<> struct char_traits<char>; |
| 107 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 110 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 108 | 111 | template<> struct char_traits<char8_t>; |
| 109 | 112 | #endif |
| 110 | 113 | template<> struct char_traits<char16_t>; |
| ... | ... | @@ -218,13 +221,13 @@ template <class _CharT, class _Traits> |
| 218 | 221 | template <class _State> class _LIBCPP_TEMPLATE_VIS fpos; |
| 219 | 222 | typedef fpos<mbstate_t> streampos; |
| 220 | 223 | typedef fpos<mbstate_t> wstreampos; |
| 221 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 224 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 222 | 225 | typedef fpos<mbstate_t> u8streampos; |
| 223 | 226 | #endif |
| 224 | 227 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS |
| 225 | 228 | typedef fpos<mbstate_t> u16streampos; |
| 226 | 229 | typedef fpos<mbstate_t> u32streampos; |
| 227 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 230 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 228 | 231 | |
| 229 | 232 | #if defined(_NEWLIB_VERSION) |
| 230 | 233 | // On newlib, off_t is 'long int' |
| ... | ... | @@ -276,4 +279,4 @@ public: |
| 276 | 279 | |
| 277 | 280 | _LIBCPP_END_NAMESPACE_STD |
| 278 | 281 | |
| 279 | #endif // _LIBCPP_IOSFWD | |
| 282 | #endif // _LIBCPP_IOSFWD |
lib/libcxx/include/iostream+3-3| ... | ... | @@ -14,9 +14,9 @@ |
| 14 | 14 | iostream synopsis |
| 15 | 15 | |
| 16 | 16 | #include <ios> |
| 17 | #include <streambuf> | |
| 18 | 17 | #include <istream> |
| 19 | 18 | #include <ostream> |
| 19 | #include <streambuf> | |
| 20 | 20 | |
| 21 | 21 | namespace std { |
| 22 | 22 | |
| ... | ... | @@ -35,9 +35,9 @@ extern wostream wclog; |
| 35 | 35 | |
| 36 | 36 | #include <__config> |
| 37 | 37 | #include <ios> |
| 38 | #include <streambuf> | |
| 39 | 38 | #include <istream> |
| 40 | 39 | #include <ostream> |
| 40 | #include <streambuf> | |
| 41 | 41 | |
| 42 | 42 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 43 | 43 | #pragma GCC system_header |
| ... | ... | @@ -60,4 +60,4 @@ extern _LIBCPP_FUNC_VIS wostream wclog; |
| 60 | 60 | |
| 61 | 61 | _LIBCPP_END_NAMESPACE_STD |
| 62 | 62 | |
| 63 | #endif // _LIBCPP_IOSTREAM | |
| 63 | #endif // _LIBCPP_IOSTREAM |
lib/libcxx/include/istream+38-59| ... | ... | @@ -159,8 +159,9 @@ template <class Stream, class T> |
| 159 | 159 | */ |
| 160 | 160 | |
| 161 | 161 | #include <__config> |
| 162 | #include <version> | |
| 162 | #include <__utility/forward.h> | |
| 163 | 163 | #include <ostream> |
| 164 | #include <version> | |
| 164 | 165 | |
| 165 | 166 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 166 | 167 | #pragma GCC system_header |
| ... | ... | @@ -191,14 +192,12 @@ public: |
| 191 | 192 | { this->init(__sb); } |
| 192 | 193 | virtual ~basic_istream(); |
| 193 | 194 | protected: |
| 194 | #ifndef _LIBCPP_CXX03_LANG | |
| 195 | 195 | inline _LIBCPP_INLINE_VISIBILITY |
| 196 | 196 | basic_istream(basic_istream&& __rhs); |
| 197 | 197 | |
| 198 | 198 | // 27.7.1.1.2 Assign/swap: |
| 199 | 199 | inline _LIBCPP_INLINE_VISIBILITY |
| 200 | 200 | basic_istream& operator=(basic_istream&& __rhs); |
| 201 | #endif | |
| 202 | 201 | |
| 203 | 202 | inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 |
| 204 | 203 | void swap(basic_istream& __rhs) { |
| ... | ... | @@ -206,10 +205,8 @@ protected: |
| 206 | 205 | basic_ios<char_type, traits_type>::swap(__rhs); |
| 207 | 206 | } |
| 208 | 207 | |
| 209 | #ifndef _LIBCPP_CXX03_LANG | |
| 210 | 208 | basic_istream (const basic_istream& __rhs) = delete; |
| 211 | 209 | basic_istream& operator=(const basic_istream& __rhs) = delete; |
| 212 | #endif | |
| 213 | 210 | public: |
| 214 | 211 | |
| 215 | 212 | // 27.7.1.1.3 Prefix/suffix: |
| ... | ... | @@ -302,8 +299,7 @@ public: |
| 302 | 299 | // ~sentry() = default; |
| 303 | 300 | |
| 304 | 301 | _LIBCPP_INLINE_VISIBILITY |
| 305 | _LIBCPP_EXPLICIT | |
| 306 | operator bool() const {return __ok_;} | |
| 302 | explicit operator bool() const {return __ok_;} | |
| 307 | 303 | }; |
| 308 | 304 | |
| 309 | 305 | template <class _CharT, class _Traits> |
| ... | ... | @@ -333,8 +329,6 @@ basic_istream<_CharT, _Traits>::sentry::sentry(basic_istream<_CharT, _Traits>& _ |
| 333 | 329 | __is.setstate(ios_base::failbit); |
| 334 | 330 | } |
| 335 | 331 | |
| 336 | #ifndef _LIBCPP_CXX03_LANG | |
| 337 | ||
| 338 | 332 | template <class _CharT, class _Traits> |
| 339 | 333 | basic_istream<_CharT, _Traits>::basic_istream(basic_istream&& __rhs) |
| 340 | 334 | : __gc_(__rhs.__gc_) |
| ... | ... | @@ -351,8 +345,6 @@ basic_istream<_CharT, _Traits>::operator=(basic_istream&& __rhs) |
| 351 | 345 | return *this; |
| 352 | 346 | } |
| 353 | 347 | |
| 354 | #endif // _LIBCPP_CXX03_LANG | |
| 355 | ||
| 356 | 348 | template <class _CharT, class _Traits> |
| 357 | 349 | basic_istream<_CharT, _Traits>::~basic_istream() |
| 358 | 350 | { |
| ... | ... | @@ -369,7 +361,7 @@ __input_arithmetic(basic_istream<_CharT, _Traits>& __is, _Tp& __n) { |
| 369 | 361 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 370 | 362 | try |
| 371 | 363 | { |
| 372 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 364 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 373 | 365 | typedef istreambuf_iterator<_CharT, _Traits> _Ip; |
| 374 | 366 | typedef num_get<_CharT, _Ip> _Fp; |
| 375 | 367 | use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __state, __n); |
| ... | ... | @@ -478,7 +470,7 @@ __input_arithmetic_with_numeric_limits(basic_istream<_CharT, _Traits>& __is, _Tp |
| 478 | 470 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 479 | 471 | try |
| 480 | 472 | { |
| 481 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 473 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 482 | 474 | typedef istreambuf_iterator<_CharT, _Traits> _Ip; |
| 483 | 475 | typedef num_get<_CharT, _Ip> _Fp; |
| 484 | 476 | long __temp; |
| ... | ... | @@ -508,7 +500,7 @@ __input_arithmetic_with_numeric_limits(basic_istream<_CharT, _Traits>& __is, _Tp |
| 508 | 500 | throw; |
| 509 | 501 | } |
| 510 | 502 | } |
| 511 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 503 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 512 | 504 | __is.setstate(__state); |
| 513 | 505 | } |
| 514 | 506 | return __is; |
| ... | ... | @@ -636,7 +628,7 @@ operator>>(basic_istream<char, _Traits>& __is, signed char* __s) |
| 636 | 628 | return __is >> (char*)__s; |
| 637 | 629 | } |
| 638 | 630 | |
| 639 | #endif // _LIBCPP_STD_VER > 17 | |
| 631 | #endif // _LIBCPP_STD_VER > 17 | |
| 640 | 632 | |
| 641 | 633 | template<class _CharT, class _Traits> |
| 642 | 634 | basic_istream<_CharT, _Traits>& |
| ... | ... | @@ -734,7 +726,7 @@ basic_istream<_CharT, _Traits>::operator>>(basic_streambuf<char_type, traits_typ |
| 734 | 726 | throw; |
| 735 | 727 | } |
| 736 | 728 | } |
| 737 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 729 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 738 | 730 | } |
| 739 | 731 | else |
| 740 | 732 | { |
| ... | ... | @@ -854,7 +846,7 @@ basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __s |
| 854 | 846 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 855 | 847 | try |
| 856 | 848 | { |
| 857 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 849 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 858 | 850 | while (true) |
| 859 | 851 | { |
| 860 | 852 | typename traits_type::int_type __i = this->rdbuf()->sgetc(); |
| ... | ... | @@ -878,7 +870,7 @@ basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __s |
| 878 | 870 | __state |= ios_base::badbit; |
| 879 | 871 | // according to the spec, exceptions here are caught but not rethrown |
| 880 | 872 | } |
| 881 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 873 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 882 | 874 | if (__gc_ == 0) |
| 883 | 875 | __state |= ios_base::failbit; |
| 884 | 876 | this->setstate(__state); |
| ... | ... | @@ -898,7 +890,7 @@ basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_typ |
| 898 | 890 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 899 | 891 | try |
| 900 | 892 | { |
| 901 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 893 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 902 | 894 | while (true) |
| 903 | 895 | { |
| 904 | 896 | typename traits_type::int_type __i = this->rdbuf()->sgetc(); |
| ... | ... | @@ -938,7 +930,7 @@ basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_typ |
| 938 | 930 | throw; |
| 939 | 931 | } |
| 940 | 932 | } |
| 941 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 933 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 942 | 934 | } |
| 943 | 935 | if (__n > 0) |
| 944 | 936 | *__s = char_type(); |
| ... | ... | @@ -960,7 +952,7 @@ basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __dlm) |
| 960 | 952 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 961 | 953 | try |
| 962 | 954 | { |
| 963 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 955 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 964 | 956 | if (__n == numeric_limits<streamsize>::max()) |
| 965 | 957 | { |
| 966 | 958 | while (true) |
| ... | ... | @@ -1002,7 +994,7 @@ basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __dlm) |
| 1002 | 994 | throw; |
| 1003 | 995 | } |
| 1004 | 996 | } |
| 1005 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 997 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1006 | 998 | this->setstate(__state); |
| 1007 | 999 | } |
| 1008 | 1000 | return *this; |
| ... | ... | @@ -1021,7 +1013,7 @@ basic_istream<_CharT, _Traits>::peek() |
| 1021 | 1013 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1022 | 1014 | try |
| 1023 | 1015 | { |
| 1024 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1016 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1025 | 1017 | __r = this->rdbuf()->sgetc(); |
| 1026 | 1018 | if (traits_type::eq_int_type(__r, traits_type::eof())) |
| 1027 | 1019 | __state |= ios_base::eofbit; |
| ... | ... | @@ -1036,7 +1028,7 @@ basic_istream<_CharT, _Traits>::peek() |
| 1036 | 1028 | throw; |
| 1037 | 1029 | } |
| 1038 | 1030 | } |
| 1039 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1031 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1040 | 1032 | this->setstate(__state); |
| 1041 | 1033 | } |
| 1042 | 1034 | return __r; |
| ... | ... | @@ -1054,7 +1046,7 @@ basic_istream<_CharT, _Traits>::read(char_type* __s, streamsize __n) |
| 1054 | 1046 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1055 | 1047 | try |
| 1056 | 1048 | { |
| 1057 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1049 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1058 | 1050 | __gc_ = this->rdbuf()->sgetn(__s, __n); |
| 1059 | 1051 | if (__gc_ != __n) |
| 1060 | 1052 | __state |= ios_base::failbit | ios_base::eofbit; |
| ... | ... | @@ -1069,7 +1061,7 @@ basic_istream<_CharT, _Traits>::read(char_type* __s, streamsize __n) |
| 1069 | 1061 | throw; |
| 1070 | 1062 | } |
| 1071 | 1063 | } |
| 1072 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1064 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1073 | 1065 | } |
| 1074 | 1066 | else |
| 1075 | 1067 | { |
| ... | ... | @@ -1091,7 +1083,7 @@ basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __n) |
| 1091 | 1083 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1092 | 1084 | try |
| 1093 | 1085 | { |
| 1094 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1086 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1095 | 1087 | streamsize __c = this->rdbuf()->in_avail(); |
| 1096 | 1088 | switch (__c) |
| 1097 | 1089 | { |
| ... | ... | @@ -1118,7 +1110,7 @@ basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __n) |
| 1118 | 1110 | throw; |
| 1119 | 1111 | } |
| 1120 | 1112 | } |
| 1121 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1113 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1122 | 1114 | } |
| 1123 | 1115 | else |
| 1124 | 1116 | { |
| ... | ... | @@ -1141,7 +1133,7 @@ basic_istream<_CharT, _Traits>::putback(char_type __c) |
| 1141 | 1133 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1142 | 1134 | try |
| 1143 | 1135 | { |
| 1144 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1136 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1145 | 1137 | if (this->rdbuf() == nullptr || this->rdbuf()->sputbackc(__c) == traits_type::eof()) |
| 1146 | 1138 | __state |= ios_base::badbit; |
| 1147 | 1139 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -1155,7 +1147,7 @@ basic_istream<_CharT, _Traits>::putback(char_type __c) |
| 1155 | 1147 | throw; |
| 1156 | 1148 | } |
| 1157 | 1149 | } |
| 1158 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1150 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1159 | 1151 | } |
| 1160 | 1152 | else |
| 1161 | 1153 | { |
| ... | ... | @@ -1178,7 +1170,7 @@ basic_istream<_CharT, _Traits>::unget() |
| 1178 | 1170 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1179 | 1171 | try |
| 1180 | 1172 | { |
| 1181 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1173 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1182 | 1174 | if (this->rdbuf() == nullptr || this->rdbuf()->sungetc() == traits_type::eof()) |
| 1183 | 1175 | __state |= ios_base::badbit; |
| 1184 | 1176 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -1192,7 +1184,7 @@ basic_istream<_CharT, _Traits>::unget() |
| 1192 | 1184 | throw; |
| 1193 | 1185 | } |
| 1194 | 1186 | } |
| 1195 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1187 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1196 | 1188 | } |
| 1197 | 1189 | else |
| 1198 | 1190 | { |
| ... | ... | @@ -1214,7 +1206,7 @@ basic_istream<_CharT, _Traits>::sync() |
| 1214 | 1206 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1215 | 1207 | try |
| 1216 | 1208 | { |
| 1217 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1209 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1218 | 1210 | if (this->rdbuf() == nullptr) |
| 1219 | 1211 | return -1; |
| 1220 | 1212 | if (this->rdbuf()->pubsync() == -1) |
| ... | ... | @@ -1233,7 +1225,7 @@ basic_istream<_CharT, _Traits>::sync() |
| 1233 | 1225 | throw; |
| 1234 | 1226 | } |
| 1235 | 1227 | } |
| 1236 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1228 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1237 | 1229 | this->setstate(__state); |
| 1238 | 1230 | } |
| 1239 | 1231 | return __r; |
| ... | ... | @@ -1251,7 +1243,7 @@ basic_istream<_CharT, _Traits>::tellg() |
| 1251 | 1243 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1252 | 1244 | try |
| 1253 | 1245 | { |
| 1254 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1246 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1255 | 1247 | __r = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in); |
| 1256 | 1248 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1257 | 1249 | } |
| ... | ... | @@ -1264,7 +1256,7 @@ basic_istream<_CharT, _Traits>::tellg() |
| 1264 | 1256 | throw; |
| 1265 | 1257 | } |
| 1266 | 1258 | } |
| 1267 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1259 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1268 | 1260 | this->setstate(__state); |
| 1269 | 1261 | } |
| 1270 | 1262 | return __r; |
| ... | ... | @@ -1282,7 +1274,7 @@ basic_istream<_CharT, _Traits>::seekg(pos_type __pos) |
| 1282 | 1274 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1283 | 1275 | try |
| 1284 | 1276 | { |
| 1285 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1277 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1286 | 1278 | if (this->rdbuf()->pubseekpos(__pos, ios_base::in) == pos_type(-1)) |
| 1287 | 1279 | __state |= ios_base::failbit; |
| 1288 | 1280 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -1296,7 +1288,7 @@ basic_istream<_CharT, _Traits>::seekg(pos_type __pos) |
| 1296 | 1288 | throw; |
| 1297 | 1289 | } |
| 1298 | 1290 | } |
| 1299 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1291 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1300 | 1292 | this->setstate(__state); |
| 1301 | 1293 | } |
| 1302 | 1294 | return *this; |
| ... | ... | @@ -1314,7 +1306,7 @@ basic_istream<_CharT, _Traits>::seekg(off_type __off, ios_base::seekdir __dir) |
| 1314 | 1306 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1315 | 1307 | try |
| 1316 | 1308 | { |
| 1317 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1309 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1318 | 1310 | if (this->rdbuf()->pubseekoff(__off, __dir, ios_base::in) == pos_type(-1)) |
| 1319 | 1311 | __state |= ios_base::failbit; |
| 1320 | 1312 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -1328,7 +1320,7 @@ basic_istream<_CharT, _Traits>::seekg(off_type __off, ios_base::seekdir __dir) |
| 1328 | 1320 | throw; |
| 1329 | 1321 | } |
| 1330 | 1322 | } |
| 1331 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1323 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1332 | 1324 | this->setstate(__state); |
| 1333 | 1325 | } |
| 1334 | 1326 | return *this; |
| ... | ... | @@ -1345,7 +1337,7 @@ ws(basic_istream<_CharT, _Traits>& __is) |
| 1345 | 1337 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1346 | 1338 | try |
| 1347 | 1339 | { |
| 1348 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1340 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1349 | 1341 | const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc()); |
| 1350 | 1342 | while (true) |
| 1351 | 1343 | { |
| ... | ... | @@ -1370,25 +1362,23 @@ ws(basic_istream<_CharT, _Traits>& __is) |
| 1370 | 1362 | throw; |
| 1371 | 1363 | } |
| 1372 | 1364 | } |
| 1373 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1365 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1374 | 1366 | __is.setstate(__state); |
| 1375 | 1367 | } |
| 1376 | 1368 | return __is; |
| 1377 | 1369 | } |
| 1378 | 1370 | |
| 1379 | #ifndef _LIBCPP_CXX03_LANG | |
| 1380 | ||
| 1381 | 1371 | template <class _Stream, class _Tp, class = void> |
| 1382 | 1372 | struct __is_istreamable : false_type { }; |
| 1383 | 1373 | |
| 1384 | 1374 | template <class _Stream, class _Tp> |
| 1385 | 1375 | struct __is_istreamable<_Stream, _Tp, decltype( |
| 1386 | _VSTD::declval<_Stream>() >> _VSTD::declval<_Tp>(), void() | |
| 1376 | declval<_Stream>() >> declval<_Tp>(), void() | |
| 1387 | 1377 | )> : true_type { }; |
| 1388 | 1378 | |
| 1389 | 1379 | template <class _Stream, class _Tp, class = typename enable_if< |
| 1390 | 1380 | _And<is_base_of<ios_base, _Stream>, |
| 1391 | __is_istreamable<_Stream&, _Tp&&>>::value | |
| 1381 | __is_istreamable<_Stream&, _Tp&&> >::value | |
| 1392 | 1382 | >::type> |
| 1393 | 1383 | _LIBCPP_INLINE_VISIBILITY |
| 1394 | 1384 | _Stream&& operator>>(_Stream&& __is, _Tp&& __x) |
| ... | ... | @@ -1397,8 +1387,6 @@ _Stream&& operator>>(_Stream&& __is, _Tp&& __x) |
| 1397 | 1387 | return _VSTD::move(__is); |
| 1398 | 1388 | } |
| 1399 | 1389 | |
| 1400 | #endif // _LIBCPP_CXX03_LANG | |
| 1401 | ||
| 1402 | 1390 | template <class _CharT, class _Traits> |
| 1403 | 1391 | class _LIBCPP_TEMPLATE_VIS basic_iostream |
| 1404 | 1392 | : public basic_istream<_CharT, _Traits>, |
| ... | ... | @@ -1420,21 +1408,18 @@ public: |
| 1420 | 1408 | |
| 1421 | 1409 | virtual ~basic_iostream(); |
| 1422 | 1410 | protected: |
| 1423 | #ifndef _LIBCPP_CXX03_LANG | |
| 1424 | 1411 | inline _LIBCPP_INLINE_VISIBILITY |
| 1425 | 1412 | basic_iostream(basic_iostream&& __rhs); |
| 1426 | 1413 | |
| 1427 | 1414 | // assign/swap |
| 1428 | 1415 | inline _LIBCPP_INLINE_VISIBILITY |
| 1429 | 1416 | basic_iostream& operator=(basic_iostream&& __rhs); |
| 1430 | #endif | |
| 1417 | ||
| 1431 | 1418 | inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 |
| 1432 | 1419 | void swap(basic_iostream& __rhs) |
| 1433 | 1420 | { basic_istream<char_type, traits_type>::swap(__rhs); } |
| 1434 | 1421 | }; |
| 1435 | 1422 | |
| 1436 | #ifndef _LIBCPP_CXX03_LANG | |
| 1437 | ||
| 1438 | 1423 | template <class _CharT, class _Traits> |
| 1439 | 1424 | basic_iostream<_CharT, _Traits>::basic_iostream(basic_iostream&& __rhs) |
| 1440 | 1425 | : basic_istream<_CharT, _Traits>(_VSTD::move(__rhs)) |
| ... | ... | @@ -1449,8 +1434,6 @@ basic_iostream<_CharT, _Traits>::operator=(basic_iostream&& __rhs) |
| 1449 | 1434 | return *this; |
| 1450 | 1435 | } |
| 1451 | 1436 | |
| 1452 | #endif // _LIBCPP_CXX03_LANG | |
| 1453 | ||
| 1454 | 1437 | template <class _CharT, class _Traits> |
| 1455 | 1438 | basic_iostream<_CharT, _Traits>::~basic_iostream() |
| 1456 | 1439 | { |
| ... | ... | @@ -1574,8 +1557,6 @@ getline(basic_istream<_CharT, _Traits>& __is, |
| 1574 | 1557 | return getline(__is, __str, __is.widen('\n')); |
| 1575 | 1558 | } |
| 1576 | 1559 | |
| 1577 | #ifndef _LIBCPP_CXX03_LANG | |
| 1578 | ||
| 1579 | 1560 | template<class _CharT, class _Traits, class _Allocator> |
| 1580 | 1561 | inline _LIBCPP_INLINE_VISIBILITY |
| 1581 | 1562 | basic_istream<_CharT, _Traits>& |
| ... | ... | @@ -1594,8 +1575,6 @@ getline(basic_istream<_CharT, _Traits>&& __is, |
| 1594 | 1575 | return getline(__is, __str, __is.widen('\n')); |
| 1595 | 1576 | } |
| 1596 | 1577 | |
| 1597 | #endif // _LIBCPP_CXX03_LANG | |
| 1598 | ||
| 1599 | 1578 | template <class _CharT, class _Traits, size_t _Size> |
| 1600 | 1579 | basic_istream<_CharT, _Traits>& |
| 1601 | 1580 | operator>>(basic_istream<_CharT, _Traits>& __is, bitset<_Size>& __x) |
| ... | ... | @@ -1656,4 +1635,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 1656 | 1635 | |
| 1657 | 1636 | _LIBCPP_POP_MACROS |
| 1658 | 1637 | |
| 1659 | #endif // _LIBCPP_ISTREAM | |
| 1638 | #endif // _LIBCPP_ISTREAM |
lib/libcxx/include/iterator+256-1654| ... | ... | @@ -13,32 +13,140 @@ |
| 13 | 13 | /* |
| 14 | 14 | iterator synopsis |
| 15 | 15 | |
| 16 | #include <concepts> | |
| 17 | ||
| 16 | 18 | namespace std |
| 17 | 19 | { |
| 20 | template<class> struct incrementable_traits; // since C++20 | |
| 21 | template<class T> | |
| 22 | using iter_difference_t = see below; // since C++20 | |
| 23 | ||
| 24 | template<class> struct indirectly_readable_traits; // since C++20 | |
| 25 | template<class T> | |
| 26 | using iter_value_t = see below; // since C++20 | |
| 18 | 27 | |
| 19 | 28 | template<class Iterator> |
| 20 | struct iterator_traits | |
| 21 | { | |
| 22 | typedef typename Iterator::difference_type difference_type; | |
| 23 | typedef typename Iterator::value_type value_type; | |
| 24 | typedef typename Iterator::pointer pointer; | |
| 25 | typedef typename Iterator::reference reference; | |
| 26 | typedef typename Iterator::iterator_category iterator_category; | |
| 27 | }; | |
| 29 | struct iterator_traits; | |
| 28 | 30 | |
| 29 | 31 | template<class T> |
| 30 | struct iterator_traits<T*> | |
| 31 | { | |
| 32 | typedef ptrdiff_t difference_type; | |
| 33 | typedef T value_type; | |
| 34 | typedef T* pointer; | |
| 35 | typedef T& reference; | |
| 36 | typedef random_access_iterator_tag iterator_category; | |
| 37 | }; | |
| 32 | requires is_object_v<T> // since C++20 | |
| 33 | struct iterator_traits<T*>; | |
| 34 | ||
| 35 | template<dereferenceable T> | |
| 36 | using iter_reference_t = decltype(*declval<T&>()); | |
| 37 | ||
| 38 | namespace ranges::inline unspecified { | |
| 39 | inline constexpr unspecified iter_move = unspecified; // since C++20, nodiscard as an extension | |
| 40 | }} | |
| 41 | ||
| 42 | template<dereferenceable T> | |
| 43 | requires ... | |
| 44 | using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<T&>())); // since C++20 | |
| 45 | ||
| 46 | // [iterator.concepts], iterator concepts | |
| 47 | // [iterator.concept.readable], concept indirectly_readable | |
| 48 | template<class In> | |
| 49 | concept indirectly_readable = see below; // since C++20 | |
| 50 | ||
| 51 | template<indirectly_readable T> | |
| 52 | using iter_common_reference_t = | |
| 53 | common_reference_t<iter_reference_t<T>, iter_value_t<T>&>; // since C++20 | |
| 54 | ||
| 55 | // [iterator.concept.writable], concept indirectly_writable | |
| 56 | template<class Out, class T> | |
| 57 | concept indirectly_writable = see below; // since C++20 | |
| 58 | ||
| 59 | // [iterator.concept.winc], concept weakly_incrementable | |
| 60 | template<class I> | |
| 61 | concept weakly_incrementable = see below; // since C++20 | |
| 62 | ||
| 63 | // [iterator.concept.inc], concept incrementable | |
| 64 | template<class I> | |
| 65 | concept incrementable = see below; // since C++20 | |
| 66 | ||
| 67 | // [iterator.concept.iterator], concept input_or_output_iterator | |
| 68 | template<class I> | |
| 69 | concept input_or_output_iterator = see below; // since C++20 | |
| 70 | ||
| 71 | // [iterator.concept.sentinel], concept sentinel_for | |
| 72 | template<class S, class I> | |
| 73 | concept sentinel_for = see below; // since C++20 | |
| 74 | ||
| 75 | // [iterator.concept.sizedsentinel], concept sized_sentinel_for | |
| 76 | template<class S, class I> | |
| 77 | inline constexpr bool disable_sized_sentinel_for = false; | |
| 78 | ||
| 79 | template<class S, class I> | |
| 80 | concept sized_sentinel_for = see below; | |
| 81 | ||
| 82 | // [iterator.concept.input], concept input_iterator | |
| 83 | template<class I> | |
| 84 | concept input_iterator = see below; // since C++20 | |
| 85 | ||
| 86 | // [iterator.concept.output], concept output_iterator | |
| 87 | template<class I, class T> | |
| 88 | concept output_iterator = see below; // since C++20 | |
| 89 | ||
| 90 | // [iterator.concept.forward], concept forward_iterator | |
| 91 | template<class I> | |
| 92 | concept forward_iterator = see below; // since C++20 | |
| 93 | ||
| 94 | // [iterator.concept.bidir], concept bidirectional_iterator | |
| 95 | template<class I> | |
| 96 | concept bidirectional_iterator = see below; // since C++20 | |
| 97 | ||
| 98 | // [iterator.concept.random.access], concept random_access_iterator | |
| 99 | template<class I> | |
| 100 | concept random_access_iterator = see below; // since C++20 | |
| 101 | ||
| 102 | // [indirectcallable] | |
| 103 | // [indirectcallable.indirectinvocable] | |
| 104 | template<class F, class I> | |
| 105 | concept indirectly_unary_invocable = see below; // since C++20 | |
| 106 | ||
| 107 | template<class F, class I> | |
| 108 | concept indirectly_regular_unary_invocable = see below; // since C++20 | |
| 109 | ||
| 110 | template<class F, class I> | |
| 111 | concept indirect_unary_predicate = see below; // since C++20 | |
| 112 | ||
| 113 | template<class F, class I1, class I2> | |
| 114 | concept indirect_binary_predicate = see below; // since C++20 | |
| 115 | ||
| 116 | template<class F, class I1, class I2 = I1> | |
| 117 | concept indirect_equivalence_relation = see below; // since C++20 | |
| 118 | ||
| 119 | template<class F, class I1, class I2 = I1> | |
| 120 | concept indirect_strict_weak_order = see below; // since C++20 | |
| 121 | ||
| 122 | template<class F, class... Is> | |
| 123 | using indirect_result_t = see below; // since C++20 | |
| 124 | ||
| 125 | // [projected], projected | |
| 126 | template<indirectly_readable I, indirectly_regular_unary_invocable<I> Proj> | |
| 127 | struct projected; // since C++20 | |
| 128 | ||
| 129 | template<weakly_incrementable I, indirectly_regular_unary_invocable<I> Proj> | |
| 130 | struct incrementable_traits<projected<I, Proj>>; // since C++20 | |
| 131 | ||
| 132 | // [alg.req.ind.move], concept indirectly_movable | |
| 133 | template<class In, class Out> | |
| 134 | concept indirectly_movable = see below; // since C++20 | |
| 135 | ||
| 136 | template<class In, class Out> | |
| 137 | concept indirectly_movable_storable = see below; // since C++20 | |
| 138 | ||
| 139 | // [alg.req.ind.swap], concept indirectly_swappable | |
| 140 | template<class I1, class I2 = I1> | |
| 141 | concept indirectly_swappable = see below; // since C++20 | |
| 142 | ||
| 143 | template<input_or_output_iterator I, sentinel_for<I> S> | |
| 144 | requires (!same_as<I, S> && copyable<I>) | |
| 145 | class common_iterator; // since C++20 | |
| 38 | 146 | |
| 39 | 147 | template<class Category, class T, class Distance = ptrdiff_t, |
| 40 | 148 | class Pointer = T*, class Reference = T&> |
| 41 | struct iterator | |
| 149 | struct iterator // deprecated in C++17 | |
| 42 | 150 | { |
| 43 | 151 | typedef T value_type; |
| 44 | 152 | typedef Distance difference_type; |
| ... | ... | @@ -69,9 +177,20 @@ template <class BidirectionalIterator> // constexpr in C++17 |
| 69 | 177 | constexpr BidirectionalIterator prev(BidirectionalIterator x, |
| 70 | 178 | typename iterator_traits<BidirectionalIterator>::difference_type n = 1); |
| 71 | 179 | |
| 180 | // [range.iter.ops], range iterator operations | |
| 181 | namespace ranges { | |
| 182 | // [range.iter.op.advance], ranges::advance | |
| 183 | template<input_or_output_iterator I> | |
| 184 | constexpr void advance(I& i, iter_difference_t<I> n); // since C++20 | |
| 185 | template<input_or_output_iterator I, sentinel_for<I> S> | |
| 186 | constexpr void advance(I& i, S bound); // since C++20 | |
| 187 | template<input_or_output_iterator I, sentinel_for<I> S> | |
| 188 | constexpr iter_difference_t<I> advance(I& i, iter_difference_t<I> n, S bound); // since C++20 | |
| 189 | } | |
| 190 | ||
| 72 | 191 | template <class Iterator> |
| 73 | 192 | class reverse_iterator |
| 74 | : public iterator<typename iterator_traits<Iterator>::iterator_category, | |
| 193 | : public iterator<typename iterator_traits<Iterator>::iterator_category, // until C++17 | |
| 75 | 194 | typename iterator_traits<Iterator>::value_type, |
| 76 | 195 | typename iterator_traits<Iterator>::difference_type, |
| 77 | 196 | typename iterator_traits<Iterator>::pointer, |
| ... | ... | @@ -142,48 +261,53 @@ constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i); // C++14 |
| 142 | 261 | |
| 143 | 262 | template <class Container> |
| 144 | 263 | class back_insert_iterator |
| 264 | : public iterator<output_iterator_tag, void, void, void, void> // until C++17 | |
| 145 | 265 | { |
| 146 | 266 | protected: |
| 147 | 267 | Container* container; |
| 148 | 268 | public: |
| 149 | 269 | typedef Container container_type; |
| 150 | 270 | typedef void value_type; |
| 151 | typedef void difference_type; | |
| 271 | typedef void difference_type; // until C++20 | |
| 272 | typedef ptrdiff_t difference_type; // since C++20 | |
| 152 | 273 | typedef void reference; |
| 153 | 274 | typedef void pointer; |
| 154 | 275 | |
| 155 | explicit back_insert_iterator(Container& x); | |
| 156 | back_insert_iterator& operator=(const typename Container::value_type& value); | |
| 157 | back_insert_iterator& operator*(); | |
| 158 | back_insert_iterator& operator++(); | |
| 159 | back_insert_iterator operator++(int); | |
| 276 | explicit back_insert_iterator(Container& x); // constexpr in C++20 | |
| 277 | back_insert_iterator& operator=(const typename Container::value_type& value); // constexpr in C++20 | |
| 278 | back_insert_iterator& operator*(); // constexpr in C++20 | |
| 279 | back_insert_iterator& operator++(); // constexpr in C++20 | |
| 280 | back_insert_iterator operator++(int); // constexpr in C++20 | |
| 160 | 281 | }; |
| 161 | 282 | |
| 162 | template <class Container> back_insert_iterator<Container> back_inserter(Container& x); | |
| 283 | template <class Container> back_insert_iterator<Container> back_inserter(Container& x); // constexpr in C++20 | |
| 163 | 284 | |
| 164 | 285 | template <class Container> |
| 165 | 286 | class front_insert_iterator |
| 287 | : public iterator<output_iterator_tag, void, void, void, void> // until C++17 | |
| 166 | 288 | { |
| 167 | 289 | protected: |
| 168 | 290 | Container* container; |
| 169 | 291 | public: |
| 170 | 292 | typedef Container container_type; |
| 171 | 293 | typedef void value_type; |
| 172 | typedef void difference_type; | |
| 294 | typedef void difference_type; // until C++20 | |
| 295 | typedef ptrdiff_t difference_type; // since C++20 | |
| 173 | 296 | typedef void reference; |
| 174 | 297 | typedef void pointer; |
| 175 | 298 | |
| 176 | explicit front_insert_iterator(Container& x); | |
| 177 | front_insert_iterator& operator=(const typename Container::value_type& value); | |
| 178 | front_insert_iterator& operator*(); | |
| 179 | front_insert_iterator& operator++(); | |
| 180 | front_insert_iterator operator++(int); | |
| 299 | explicit front_insert_iterator(Container& x); // constexpr in C++20 | |
| 300 | front_insert_iterator& operator=(const typename Container::value_type& value); // constexpr in C++20 | |
| 301 | front_insert_iterator& operator*(); // constexpr in C++20 | |
| 302 | front_insert_iterator& operator++(); // constexpr in C++20 | |
| 303 | front_insert_iterator operator++(int); // constexpr in C++20 | |
| 181 | 304 | }; |
| 182 | 305 | |
| 183 | template <class Container> front_insert_iterator<Container> front_inserter(Container& x); | |
| 306 | template <class Container> front_insert_iterator<Container> front_inserter(Container& x); // constexpr in C++20 | |
| 184 | 307 | |
| 185 | 308 | template <class Container> |
| 186 | 309 | class insert_iterator |
| 310 | : public iterator<output_iterator_tag, void, void, void, void> // until C++17 | |
| 187 | 311 | { |
| 188 | 312 | protected: |
| 189 | 313 | Container* container; |
| ... | ... | @@ -191,19 +315,20 @@ protected: |
| 191 | 315 | public: |
| 192 | 316 | typedef Container container_type; |
| 193 | 317 | typedef void value_type; |
| 194 | typedef void difference_type; | |
| 318 | typedef void difference_type; // until C++20 | |
| 319 | typedef ptrdiff_t difference_type; // since C++20 | |
| 195 | 320 | typedef void reference; |
| 196 | 321 | typedef void pointer; |
| 197 | 322 | |
| 198 | insert_iterator(Container& x, typename Container::iterator i); | |
| 199 | insert_iterator& operator=(const typename Container::value_type& value); | |
| 200 | insert_iterator& operator*(); | |
| 201 | insert_iterator& operator++(); | |
| 202 | insert_iterator& operator++(int); | |
| 323 | insert_iterator(Container& x, typename Container::iterator i); // constexpr in C++20 | |
| 324 | insert_iterator& operator=(const typename Container::value_type& value); // constexpr in C++20 | |
| 325 | insert_iterator& operator*(); // constexpr in C++20 | |
| 326 | insert_iterator& operator++(); // constexpr in C++20 | |
| 327 | insert_iterator& operator++(int); // constexpr in C++20 | |
| 203 | 328 | }; |
| 204 | 329 | |
| 205 | 330 | template <class Container, class Iterator> |
| 206 | insert_iterator<Container> inserter(Container& x, Iterator i); | |
| 331 | insert_iterator<Container> inserter(Container& x, Iterator i); // constexpr in C++20 | |
| 207 | 332 | |
| 208 | 333 | template <class Iterator> |
| 209 | 334 | class move_iterator { |
| ... | ... | @@ -274,15 +399,31 @@ constexpr move_iterator<Iterator> operator+( // constexpr in C++17 |
| 274 | 399 | template <class Iterator> // constexpr in C++17 |
| 275 | 400 | constexpr move_iterator<Iterator> make_move_iterator(const Iterator& i); |
| 276 | 401 | |
| 402 | // [default.sentinel], default sentinel | |
| 403 | struct default_sentinel_t; | |
| 404 | inline constexpr default_sentinel_t default_sentinel{}; | |
| 405 | ||
| 406 | // [iterators.counted], counted iterators | |
| 407 | template<input_or_output_iterator I> class counted_iterator; | |
| 408 | ||
| 409 | template<input_iterator I> | |
| 410 | requires see below | |
| 411 | struct iterator_traits<counted_iterator<I>>; | |
| 277 | 412 | |
| 278 | 413 | template <class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t> |
| 279 | 414 | class istream_iterator |
| 280 | : public iterator<input_iterator_tag, T, Distance, const T*, const T&> | |
| 415 | : public iterator<input_iterator_tag, T, Distance, const T*, const T&> // until C++17 | |
| 281 | 416 | { |
| 282 | 417 | public: |
| 283 | typedef charT char_type; | |
| 284 | typedef traits traits_type; | |
| 285 | typedef basic_istream<charT,traits> istream_type; | |
| 418 | typedef input_iterator_tag iterator_category; | |
| 419 | typedef T value_type; | |
| 420 | typedef Distance difference_type; | |
| 421 | typedef const T* pointer; | |
| 422 | typedef const T& reference; | |
| 423 | ||
| 424 | typedef charT char_type; | |
| 425 | typedef traits traits_type; | |
| 426 | typedef basic_istream<charT, traits> istream_type; | |
| 286 | 427 | |
| 287 | 428 | constexpr istream_iterator(); |
| 288 | 429 | istream_iterator(istream_type& s); |
| ... | ... | @@ -304,9 +445,16 @@ bool operator!=(const istream_iterator<T,charT,traits,Distance>& x, |
| 304 | 445 | |
| 305 | 446 | template <class T, class charT = char, class traits = char_traits<charT> > |
| 306 | 447 | class ostream_iterator |
| 307 | : public iterator<output_iterator_tag, void, void, void ,void> | |
| 448 | : public iterator<output_iterator_tag, void, void, void, void> // until C++17 | |
| 308 | 449 | { |
| 309 | 450 | public: |
| 451 | typedef output_iterator_tag iterator_category; | |
| 452 | typedef void value_type; | |
| 453 | typedef void difference_type; // until C++20 | |
| 454 | typedef ptrdiff_t difference_type; // since C++20 | |
| 455 | typedef void pointer; | |
| 456 | typedef void reference; | |
| 457 | ||
| 310 | 458 | typedef charT char_type; |
| 311 | 459 | typedef traits traits_type; |
| 312 | 460 | typedef basic_ostream<charT,traits> ostream_type; |
| ... | ... | @@ -324,16 +472,20 @@ public: |
| 324 | 472 | |
| 325 | 473 | template<class charT, class traits = char_traits<charT> > |
| 326 | 474 | class istreambuf_iterator |
| 327 | : public iterator<input_iterator_tag, charT, | |
| 328 | typename traits::off_type, unspecified, | |
| 329 | charT> | |
| 475 | : public iterator<input_iterator_tag, charT, traits::off_type, unspecified, charT> // until C++17 | |
| 330 | 476 | { |
| 331 | 477 | public: |
| 332 | typedef charT char_type; | |
| 333 | typedef traits traits_type; | |
| 334 | typedef typename traits::int_type int_type; | |
| 335 | typedef basic_streambuf<charT,traits> streambuf_type; | |
| 336 | typedef basic_istream<charT,traits> istream_type; | |
| 478 | typedef input_iterator_tag iterator_category; | |
| 479 | typedef charT value_type; | |
| 480 | typedef traits::off_type difference_type; | |
| 481 | typedef unspecified pointer; | |
| 482 | typedef charT reference; | |
| 483 | ||
| 484 | typedef charT char_type; | |
| 485 | typedef traits traits_type; | |
| 486 | typedef traits::int_type int_type; | |
| 487 | typedef basic_streambuf<charT, traits> streambuf_type; | |
| 488 | typedef basic_istream<charT, traits> istream_type; | |
| 337 | 489 | |
| 338 | 490 | istreambuf_iterator() noexcept; |
| 339 | 491 | istreambuf_iterator(istream_type& s) noexcept; |
| ... | ... | @@ -357,13 +509,20 @@ bool operator!=(const istreambuf_iterator<charT,traits>& a, |
| 357 | 509 | |
| 358 | 510 | template <class charT, class traits = char_traits<charT> > |
| 359 | 511 | class ostreambuf_iterator |
| 360 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 512 | : public iterator<output_iterator_tag, void, void, void, void> // until C++17 | |
| 361 | 513 | { |
| 362 | 514 | public: |
| 363 | typedef charT char_type; | |
| 364 | typedef traits traits_type; | |
| 365 | typedef basic_streambuf<charT,traits> streambuf_type; | |
| 366 | typedef basic_ostream<charT,traits> ostream_type; | |
| 515 | typedef output_iterator_tag iterator_category; | |
| 516 | typedef void value_type; | |
| 517 | typedef void difference_type; // until C++20 | |
| 518 | typedef ptrdiff_t difference_type; // since C++20 | |
| 519 | typedef void pointer; | |
| 520 | typedef void reference; | |
| 521 | ||
| 522 | typedef charT char_type; | |
| 523 | typedef traits traits_type; | |
| 524 | typedef basic_streambuf<charT, traits> streambuf_type; | |
| 525 | typedef basic_ostream<charT, traits> ostream_type; | |
| 367 | 526 | |
| 368 | 527 | ostreambuf_iterator(ostream_type& s) noexcept; |
| 369 | 528 | ostreambuf_iterator(streambuf_type* s) noexcept; |
| ... | ... | @@ -399,7 +558,7 @@ template <class C> constexpr auto size(const C& c) -> decltype(c.size()); |
| 399 | 558 | template <class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept; // C++17 |
| 400 | 559 | |
| 401 | 560 | template <class C> constexpr auto ssize(const C& c) |
| 402 | -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>;				 // C++20 | |
| 561 | -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>; // C++20 | |
| 403 | 562 | template <class T, ptrdiff_t> constexpr ptrdiff_t ssize(const T (&array)[N]) noexcept; // C++20 |
| 404 | 563 | |
| 405 | 564 | template <class C> constexpr auto empty(const C& c) -> decltype(c.empty()); // C++17 |
| ... | ... | @@ -415,1608 +574,51 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept; |
| 415 | 574 | */ |
| 416 | 575 | |
| 417 | 576 | #include <__config> |
| 418 | #include <iosfwd> // for forward declarations of vector and string. | |
| 577 | #include <__debug> | |
| 419 | 578 | #include <__functional_base> |
| 420 | #include <type_traits> | |
| 579 | #include <__iterator/access.h> | |
| 580 | #include <__iterator/advance.h> | |
| 581 | #include <__iterator/back_insert_iterator.h> | |
| 582 | #include <__iterator/common_iterator.h> | |
| 583 | #include <__iterator/concepts.h> | |
| 584 | #include <__iterator/counted_iterator.h> | |
| 585 | #include <__iterator/data.h> | |
| 586 | #include <__iterator/default_sentinel.h> | |
| 587 | #include <__iterator/distance.h> | |
| 588 | #include <__iterator/empty.h> | |
| 589 | #include <__iterator/erase_if_container.h> | |
| 590 | #include <__iterator/front_insert_iterator.h> | |
| 591 | #include <__iterator/incrementable_traits.h> | |
| 592 | #include <__iterator/insert_iterator.h> | |
| 593 | #include <__iterator/istreambuf_iterator.h> | |
| 594 | #include <__iterator/istream_iterator.h> | |
| 595 | #include <__iterator/iterator.h> | |
| 596 | #include <__iterator/iterator_traits.h> | |
| 597 | #include <__iterator/iter_move.h> | |
| 598 | #include <__iterator/iter_swap.h> | |
| 599 | #include <__iterator/move_iterator.h> | |
| 600 | #include <__iterator/next.h> | |
| 601 | #include <__iterator/ostreambuf_iterator.h> | |
| 602 | #include <__iterator/ostream_iterator.h> | |
| 603 | #include <__iterator/prev.h> | |
| 604 | #include <__iterator/projected.h> | |
| 605 | #include <__iterator/readable_traits.h> | |
| 606 | #include <__iterator/reverse_access.h> | |
| 607 | #include <__iterator/reverse_iterator.h> | |
| 608 | #include <__iterator/size.h> | |
| 609 | #include <__iterator/wrap_iter.h> | |
| 610 | #include <__memory/addressof.h> | |
| 611 | #include <__memory/pointer_traits.h> | |
| 612 | #include <__utility/forward.h> | |
| 613 | #include <compare> | |
| 614 | #include <concepts> // Mandated by the Standard. | |
| 421 | 615 | #include <cstddef> |
| 422 | 616 | #include <initializer_list> |
| 423 | #include <__memory/base.h> | |
| 617 | #include <type_traits> | |
| 424 | 618 | #include <version> |
| 425 | 619 | |
| 426 | #include <__debug> | |
| 427 | ||
| 428 | 620 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 429 | 621 | #pragma GCC system_header |
| 430 | 622 | #endif |
| 431 | 623 | |
| 432 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 433 | template <class _Iter> | |
| 434 | struct _LIBCPP_TEMPLATE_VIS iterator_traits; | |
| 435 | ||
| 436 | struct _LIBCPP_TEMPLATE_VIS input_iterator_tag {}; | |
| 437 | struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {}; | |
| 438 | struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag : public input_iterator_tag {}; | |
| 439 | struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {}; | |
| 440 | struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {}; | |
| 441 | #if _LIBCPP_STD_VER > 17 | |
| 442 | // TODO(EricWF) contiguous_iterator_tag is provided as an extension prior to | |
| 443 | // C++20 to allow optimizations for users providing wrapped iterator types. | |
| 444 | struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag: public random_access_iterator_tag { }; | |
| 445 | #endif | |
| 446 | ||
| 447 | template <class _Iter> | |
| 448 | struct __iter_traits_cache { | |
| 449 | using type = _If< | |
| 450 | __is_primary_template<iterator_traits<_Iter> >::value, | |
| 451 | _Iter, | |
| 452 | iterator_traits<_Iter> | |
| 453 | >; | |
| 454 | }; | |
| 455 | template <class _Iter> | |
| 456 | using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type; | |
| 457 | ||
| 458 | struct __iter_concept_concept_test { | |
| 459 | template <class _Iter> | |
| 460 | using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept; | |
| 461 | }; | |
| 462 | struct __iter_concept_category_test { | |
| 463 | template <class _Iter> | |
| 464 | using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category; | |
| 465 | }; | |
| 466 | struct __iter_concept_random_fallback { | |
| 467 | template <class _Iter> | |
| 468 | using _Apply = _EnableIf< | |
| 469 | __is_primary_template<iterator_traits<_Iter> >::value, | |
| 470 | random_access_iterator_tag | |
| 471 | >; | |
| 472 | }; | |
| 473 | ||
| 474 | template <class _Iter, class _Tester> struct __test_iter_concept | |
| 475 | : _IsValidExpansion<_Tester::template _Apply, _Iter>, | |
| 476 | _Tester | |
| 477 | { | |
| 478 | }; | |
| 479 | ||
| 480 | template <class _Iter> | |
| 481 | struct __iter_concept_cache { | |
| 482 | using type = _Or< | |
| 483 | __test_iter_concept<_Iter, __iter_concept_concept_test>, | |
| 484 | __test_iter_concept<_Iter, __iter_concept_category_test>, | |
| 485 | __test_iter_concept<_Iter, __iter_concept_random_fallback> | |
| 486 | >; | |
| 487 | }; | |
| 488 | ||
| 489 | template <class _Iter> | |
| 490 | using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; | |
| 491 | ||
| 492 | ||
| 493 | template <class _Tp> | |
| 494 | struct __has_iterator_typedefs | |
| 495 | { | |
| 496 | private: | |
| 497 | struct __two {char __lx; char __lxx;}; | |
| 498 | template <class _Up> static __two __test(...); | |
| 499 | template <class _Up> static char __test(typename __void_t<typename _Up::iterator_category>::type* = 0, | |
| 500 | typename __void_t<typename _Up::difference_type>::type* = 0, | |
| 501 | typename __void_t<typename _Up::value_type>::type* = 0, | |
| 502 | typename __void_t<typename _Up::reference>::type* = 0, | |
| 503 | typename __void_t<typename _Up::pointer>::type* = 0); | |
| 504 | public: | |
| 505 | static const bool value = sizeof(__test<_Tp>(0,0,0,0,0)) == 1; | |
| 506 | }; | |
| 507 | ||
| 508 | ||
| 509 | template <class _Tp> | |
| 510 | struct __has_iterator_category | |
| 511 | { | |
| 512 | private: | |
| 513 | struct __two {char __lx; char __lxx;}; | |
| 514 | template <class _Up> static __two __test(...); | |
| 515 | template <class _Up> static char __test(typename _Up::iterator_category* = nullptr); | |
| 516 | public: | |
| 517 | static const bool value = sizeof(__test<_Tp>(nullptr)) == 1; | |
| 518 | }; | |
| 519 | ||
| 520 | template <class _Iter, bool> struct __iterator_traits_impl {}; | |
| 521 | ||
| 522 | template <class _Iter> | |
| 523 | struct __iterator_traits_impl<_Iter, true> | |
| 524 | { | |
| 525 | typedef typename _Iter::difference_type difference_type; | |
| 526 | typedef typename _Iter::value_type value_type; | |
| 527 | typedef typename _Iter::pointer pointer; | |
| 528 | typedef typename _Iter::reference reference; | |
| 529 | typedef typename _Iter::iterator_category iterator_category; | |
| 530 | }; | |
| 531 | ||
| 532 | template <class _Iter, bool> struct __iterator_traits {}; | |
| 533 | ||
| 534 | template <class _Iter> | |
| 535 | struct __iterator_traits<_Iter, true> | |
| 536 | : __iterator_traits_impl | |
| 537 | < | |
| 538 | _Iter, | |
| 539 | is_convertible<typename _Iter::iterator_category, input_iterator_tag>::value || | |
| 540 | is_convertible<typename _Iter::iterator_category, output_iterator_tag>::value | |
| 541 | > | |
| 542 | {}; | |
| 543 | ||
| 544 | // iterator_traits<Iterator> will only have the nested types if Iterator::iterator_category | |
| 545 | // exists. Else iterator_traits<Iterator> will be an empty class. This is a | |
| 546 | // conforming extension which allows some programs to compile and behave as | |
| 547 | // the client expects instead of failing at compile time. | |
| 548 | ||
| 549 | template <class _Iter> | |
| 550 | struct _LIBCPP_TEMPLATE_VIS iterator_traits | |
| 551 | : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { | |
| 552 | ||
| 553 | using __primary_template = iterator_traits; | |
| 554 | }; | |
| 555 | ||
| 556 | template<class _Tp> | |
| 557 | struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> | |
| 558 | { | |
| 559 | typedef ptrdiff_t difference_type; | |
| 560 | typedef typename remove_cv<_Tp>::type value_type; | |
| 561 | typedef _Tp* pointer; | |
| 562 | typedef _Tp& reference; | |
| 563 | typedef random_access_iterator_tag iterator_category; | |
| 564 | #if _LIBCPP_STD_VER > 17 | |
| 565 | typedef contiguous_iterator_tag iterator_concept; | |
| 566 | #endif | |
| 567 | }; | |
| 568 | ||
| 569 | template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value> | |
| 570 | struct __has_iterator_category_convertible_to | |
| 571 | : public integral_constant<bool, is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>::value> | |
| 572 | {}; | |
| 573 | ||
| 574 | template <class _Tp, class _Up> | |
| 575 | struct __has_iterator_category_convertible_to<_Tp, _Up, false> : public false_type {}; | |
| 576 | ||
| 577 | template <class _Tp> | |
| 578 | struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {}; | |
| 579 | ||
| 580 | template <class _Tp> | |
| 581 | struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {}; | |
| 582 | ||
| 583 | template <class _Tp> | |
| 584 | struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {}; | |
| 585 | ||
| 586 | template <class _Tp> | |
| 587 | struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {}; | |
| 588 | ||
| 589 | #if _LIBCPP_STD_VER > 17 | |
| 590 | template <class _Tp> | |
| 591 | struct __is_cpp17_contiguous_iterator : public __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag> {}; | |
| 592 | #else | |
| 593 | template <class _Tp> | |
| 594 | struct __is_cpp17_contiguous_iterator : public false_type {}; | |
| 595 | #endif | |
| 596 | ||
| 597 | ||
| 598 | template <class _Tp> | |
| 599 | struct __is_exactly_cpp17_input_iterator | |
| 600 | : public integral_constant<bool, | |
| 601 | __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value && | |
| 602 | !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; | |
| 603 | ||
| 604 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 605 | template<class _InputIterator> | |
| 606 | using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; | |
| 607 | ||
| 608 | template<class _InputIterator> | |
| 609 | using __iter_key_type = remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>; | |
| 610 | ||
| 611 | template<class _InputIterator> | |
| 612 | using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; | |
| 613 | ||
| 614 | template<class _InputIterator> | |
| 615 | using __iter_to_alloc_type = pair< | |
| 616 | add_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>, | |
| 617 | typename iterator_traits<_InputIterator>::value_type::second_type>; | |
| 618 | #endif | |
| 619 | ||
| 620 | template<class _Category, class _Tp, class _Distance = ptrdiff_t, | |
| 621 | class _Pointer = _Tp*, class _Reference = _Tp&> | |
| 622 | struct _LIBCPP_TEMPLATE_VIS iterator | |
| 623 | { | |
| 624 | typedef _Tp value_type; | |
| 625 | typedef _Distance difference_type; | |
| 626 | typedef _Pointer pointer; | |
| 627 | typedef _Reference reference; | |
| 628 | typedef _Category iterator_category; | |
| 629 | }; | |
| 630 | ||
| 631 | template <class _InputIter> | |
| 632 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 633 | void __advance(_InputIter& __i, | |
| 634 | typename iterator_traits<_InputIter>::difference_type __n, input_iterator_tag) | |
| 635 | { | |
| 636 | for (; __n > 0; --__n) | |
| 637 | ++__i; | |
| 638 | } | |
| 639 | ||
| 640 | template <class _BiDirIter> | |
| 641 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 642 | void __advance(_BiDirIter& __i, | |
| 643 | typename iterator_traits<_BiDirIter>::difference_type __n, bidirectional_iterator_tag) | |
| 644 | { | |
| 645 | if (__n >= 0) | |
| 646 | for (; __n > 0; --__n) | |
| 647 | ++__i; | |
| 648 | else | |
| 649 | for (; __n < 0; ++__n) | |
| 650 | --__i; | |
| 651 | } | |
| 652 | ||
| 653 | template <class _RandIter> | |
| 654 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 655 | void __advance(_RandIter& __i, | |
| 656 | typename iterator_traits<_RandIter>::difference_type __n, random_access_iterator_tag) | |
| 657 | { | |
| 658 | __i += __n; | |
| 659 | } | |
| 660 | ||
| 661 | template <class _InputIter, class _Distance> | |
| 662 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 663 | void advance(_InputIter& __i, _Distance __orig_n) | |
| 664 | { | |
| 665 | _LIBCPP_ASSERT(__orig_n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, | |
| 666 | "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); | |
| 667 | typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; | |
| 668 | _IntegralSize __n = __orig_n; | |
| 669 | _VSTD::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category()); | |
| 670 | } | |
| 671 | ||
| 672 | template <class _InputIter> | |
| 673 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 674 | typename iterator_traits<_InputIter>::difference_type | |
| 675 | __distance(_InputIter __first, _InputIter __last, input_iterator_tag) | |
| 676 | { | |
| 677 | typename iterator_traits<_InputIter>::difference_type __r(0); | |
| 678 | for (; __first != __last; ++__first) | |
| 679 | ++__r; | |
| 680 | return __r; | |
| 681 | } | |
| 682 | ||
| 683 | template <class _RandIter> | |
| 684 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 685 | typename iterator_traits<_RandIter>::difference_type | |
| 686 | __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag) | |
| 687 | { | |
| 688 | return __last - __first; | |
| 689 | } | |
| 690 | ||
| 691 | template <class _InputIter> | |
| 692 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 693 | typename iterator_traits<_InputIter>::difference_type | |
| 694 | distance(_InputIter __first, _InputIter __last) | |
| 695 | { | |
| 696 | return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); | |
| 697 | } | |
| 698 | ||
| 699 | template <class _InputIter> | |
| 700 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 701 | typename enable_if | |
| 702 | < | |
| 703 | __is_cpp17_input_iterator<_InputIter>::value, | |
| 704 | _InputIter | |
| 705 | >::type | |
| 706 | next(_InputIter __x, | |
| 707 | typename iterator_traits<_InputIter>::difference_type __n = 1) | |
| 708 | { | |
| 709 | _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, | |
| 710 | "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); | |
| 711 | ||
| 712 | _VSTD::advance(__x, __n); | |
| 713 | return __x; | |
| 714 | } | |
| 715 | ||
| 716 | template <class _InputIter> | |
| 717 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 718 | typename enable_if | |
| 719 | < | |
| 720 | __is_cpp17_input_iterator<_InputIter>::value, | |
| 721 | _InputIter | |
| 722 | >::type | |
| 723 | prev(_InputIter __x, | |
| 724 | typename iterator_traits<_InputIter>::difference_type __n = 1) | |
| 725 | { | |
| 726 | _LIBCPP_ASSERT(__n <= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, | |
| 727 | "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); | |
| 728 | _VSTD::advance(__x, -__n); | |
| 729 | return __x; | |
| 730 | } | |
| 731 | ||
| 732 | ||
| 733 | template <class _Tp, class = void> | |
| 734 | struct __is_stashing_iterator : false_type {}; | |
| 735 | ||
| 736 | template <class _Tp> | |
| 737 | struct __is_stashing_iterator<_Tp, typename __void_t<typename _Tp::__stashing_iterator_tag>::type> | |
| 738 | : true_type {}; | |
| 739 | ||
| 740 | template <class _Iter> | |
| 741 | class _LIBCPP_TEMPLATE_VIS reverse_iterator | |
| 742 | : public iterator<typename iterator_traits<_Iter>::iterator_category, | |
| 743 | typename iterator_traits<_Iter>::value_type, | |
| 744 | typename iterator_traits<_Iter>::difference_type, | |
| 745 | typename iterator_traits<_Iter>::pointer, | |
| 746 | typename iterator_traits<_Iter>::reference> | |
| 747 | { | |
| 748 | private: | |
| 749 | /*mutable*/ _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break | |
| 750 | ||
| 751 | static_assert(!__is_stashing_iterator<_Iter>::value, | |
| 752 | "The specified iterator type cannot be used with reverse_iterator; " | |
| 753 | "Using stashing iterators with reverse_iterator causes undefined behavior"); | |
| 754 | ||
| 755 | protected: | |
| 756 | _Iter current; | |
| 757 | public: | |
| 758 | typedef _Iter iterator_type; | |
| 759 | typedef typename iterator_traits<_Iter>::difference_type difference_type; | |
| 760 | typedef typename iterator_traits<_Iter>::reference reference; | |
| 761 | typedef typename iterator_traits<_Iter>::pointer pointer; | |
| 762 | ||
| 763 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 764 | reverse_iterator() : __t(), current() {} | |
| 765 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 766 | explicit reverse_iterator(_Iter __x) : __t(__x), current(__x) {} | |
| 767 | template <class _Up> | |
| 768 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 769 | reverse_iterator(const reverse_iterator<_Up>& __u) : __t(__u.base()), current(__u.base()) {} | |
| 770 | template <class _Up> | |
| 771 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 772 | reverse_iterator& operator=(const reverse_iterator<_Up>& __u) | |
| 773 | { __t = current = __u.base(); return *this; } | |
| 774 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 775 | _Iter base() const {return current;} | |
| 776 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 777 | reference operator*() const {_Iter __tmp = current; return *--__tmp;} | |
| 778 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 779 | pointer operator->() const {return _VSTD::addressof(operator*());} | |
| 780 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 781 | reverse_iterator& operator++() {--current; return *this;} | |
| 782 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 783 | reverse_iterator operator++(int) {reverse_iterator __tmp(*this); --current; return __tmp;} | |
| 784 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 785 | reverse_iterator& operator--() {++current; return *this;} | |
| 786 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 787 | reverse_iterator operator--(int) {reverse_iterator __tmp(*this); ++current; return __tmp;} | |
| 788 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 789 | reverse_iterator operator+ (difference_type __n) const {return reverse_iterator(current - __n);} | |
| 790 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 791 | reverse_iterator& operator+=(difference_type __n) {current -= __n; return *this;} | |
| 792 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 793 | reverse_iterator operator- (difference_type __n) const {return reverse_iterator(current + __n);} | |
| 794 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 795 | reverse_iterator& operator-=(difference_type __n) {current += __n; return *this;} | |
| 796 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 797 | reference operator[](difference_type __n) const {return *(*this + __n);} | |
| 798 | }; | |
| 799 | ||
| 800 | template <class _Iter1, class _Iter2> | |
| 801 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 802 | bool | |
| 803 | operator==(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 804 | { | |
| 805 | return __x.base() == __y.base(); | |
| 806 | } | |
| 807 | ||
| 808 | template <class _Iter1, class _Iter2> | |
| 809 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 810 | bool | |
| 811 | operator<(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 812 | { | |
| 813 | return __x.base() > __y.base(); | |
| 814 | } | |
| 815 | ||
| 816 | template <class _Iter1, class _Iter2> | |
| 817 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 818 | bool | |
| 819 | operator!=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 820 | { | |
| 821 | return __x.base() != __y.base(); | |
| 822 | } | |
| 823 | ||
| 824 | template <class _Iter1, class _Iter2> | |
| 825 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 826 | bool | |
| 827 | operator>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 828 | { | |
| 829 | return __x.base() < __y.base(); | |
| 830 | } | |
| 831 | ||
| 832 | template <class _Iter1, class _Iter2> | |
| 833 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 834 | bool | |
| 835 | operator>=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 836 | { | |
| 837 | return __x.base() <= __y.base(); | |
| 838 | } | |
| 839 | ||
| 840 | template <class _Iter1, class _Iter2> | |
| 841 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 842 | bool | |
| 843 | operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 844 | { | |
| 845 | return __x.base() >= __y.base(); | |
| 846 | } | |
| 847 | ||
| 848 | #ifndef _LIBCPP_CXX03_LANG | |
| 849 | template <class _Iter1, class _Iter2> | |
| 850 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 851 | auto | |
| 852 | operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 853 | -> decltype(__y.base() - __x.base()) | |
| 854 | { | |
| 855 | return __y.base() - __x.base(); | |
| 856 | } | |
| 857 | #else | |
| 858 | template <class _Iter1, class _Iter2> | |
| 859 | inline _LIBCPP_INLINE_VISIBILITY | |
| 860 | typename reverse_iterator<_Iter1>::difference_type | |
| 861 | operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) | |
| 862 | { | |
| 863 | return __y.base() - __x.base(); | |
| 864 | } | |
| 865 | #endif | |
| 866 | ||
| 867 | template <class _Iter> | |
| 868 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 869 | reverse_iterator<_Iter> | |
| 870 | operator+(typename reverse_iterator<_Iter>::difference_type __n, const reverse_iterator<_Iter>& __x) | |
| 871 | { | |
| 872 | return reverse_iterator<_Iter>(__x.base() - __n); | |
| 873 | } | |
| 874 | ||
| 875 | #if _LIBCPP_STD_VER > 11 | |
| 876 | template <class _Iter> | |
| 877 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 878 | reverse_iterator<_Iter> make_reverse_iterator(_Iter __i) | |
| 879 | { | |
| 880 | return reverse_iterator<_Iter>(__i); | |
| 881 | } | |
| 882 | #endif | |
| 883 | ||
| 884 | template <class _Container> | |
| 885 | class _LIBCPP_TEMPLATE_VIS back_insert_iterator | |
| 886 | : public iterator<output_iterator_tag, | |
| 887 | void, | |
| 888 | void, | |
| 889 | void, | |
| 890 | void> | |
| 891 | { | |
| 892 | protected: | |
| 893 | _Container* container; | |
| 894 | public: | |
| 895 | typedef _Container container_type; | |
| 896 | ||
| 897 | _LIBCPP_INLINE_VISIBILITY explicit back_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} | |
| 898 | _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator=(const typename _Container::value_type& __value_) | |
| 899 | {container->push_back(__value_); return *this;} | |
| 900 | #ifndef _LIBCPP_CXX03_LANG | |
| 901 | _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator=(typename _Container::value_type&& __value_) | |
| 902 | {container->push_back(_VSTD::move(__value_)); return *this;} | |
| 903 | #endif // _LIBCPP_CXX03_LANG | |
| 904 | _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator*() {return *this;} | |
| 905 | _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator++() {return *this;} | |
| 906 | _LIBCPP_INLINE_VISIBILITY back_insert_iterator operator++(int) {return *this;} | |
| 907 | }; | |
| 908 | ||
| 909 | template <class _Container> | |
| 910 | inline _LIBCPP_INLINE_VISIBILITY | |
| 911 | back_insert_iterator<_Container> | |
| 912 | back_inserter(_Container& __x) | |
| 913 | { | |
| 914 | return back_insert_iterator<_Container>(__x); | |
| 915 | } | |
| 916 | ||
| 917 | template <class _Container> | |
| 918 | class _LIBCPP_TEMPLATE_VIS front_insert_iterator | |
| 919 | : public iterator<output_iterator_tag, | |
| 920 | void, | |
| 921 | void, | |
| 922 | void, | |
| 923 | void> | |
| 924 | { | |
| 925 | protected: | |
| 926 | _Container* container; | |
| 927 | public: | |
| 928 | typedef _Container container_type; | |
| 929 | ||
| 930 | _LIBCPP_INLINE_VISIBILITY explicit front_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} | |
| 931 | _LIBCPP_INLINE_VISIBILITY front_insert_iterator& operator=(const typename _Container::value_type& __value_) | |
| 932 | {container->push_front(__value_); return *this;} | |
| 933 | #ifndef _LIBCPP_CXX03_LANG | |
| 934 | _LIBCPP_INLINE_VISIBILITY front_insert_iterator& operator=(typename _Container::value_type&& __value_) | |
| 935 | {container->push_front(_VSTD::move(__value_)); return *this;} | |
| 936 | #endif // _LIBCPP_CXX03_LANG | |
| 937 | _LIBCPP_INLINE_VISIBILITY front_insert_iterator& operator*() {return *this;} | |
| 938 | _LIBCPP_INLINE_VISIBILITY front_insert_iterator& operator++() {return *this;} | |
| 939 | _LIBCPP_INLINE_VISIBILITY front_insert_iterator operator++(int) {return *this;} | |
| 940 | }; | |
| 941 | ||
| 942 | template <class _Container> | |
| 943 | inline _LIBCPP_INLINE_VISIBILITY | |
| 944 | front_insert_iterator<_Container> | |
| 945 | front_inserter(_Container& __x) | |
| 946 | { | |
| 947 | return front_insert_iterator<_Container>(__x); | |
| 948 | } | |
| 949 | ||
| 950 | template <class _Container> | |
| 951 | class _LIBCPP_TEMPLATE_VIS insert_iterator | |
| 952 | : public iterator<output_iterator_tag, | |
| 953 | void, | |
| 954 | void, | |
| 955 | void, | |
| 956 | void> | |
| 957 | { | |
| 958 | protected: | |
| 959 | _Container* container; | |
| 960 | typename _Container::iterator iter; | |
| 961 | public: | |
| 962 | typedef _Container container_type; | |
| 963 | ||
| 964 | _LIBCPP_INLINE_VISIBILITY insert_iterator(_Container& __x, typename _Container::iterator __i) | |
| 965 | : container(_VSTD::addressof(__x)), iter(__i) {} | |
| 966 | _LIBCPP_INLINE_VISIBILITY insert_iterator& operator=(const typename _Container::value_type& __value_) | |
| 967 | {iter = container->insert(iter, __value_); ++iter; return *this;} | |
| 968 | #ifndef _LIBCPP_CXX03_LANG | |
| 969 | _LIBCPP_INLINE_VISIBILITY insert_iterator& operator=(typename _Container::value_type&& __value_) | |
| 970 | {iter = container->insert(iter, _VSTD::move(__value_)); ++iter; return *this;} | |
| 971 | #endif // _LIBCPP_CXX03_LANG | |
| 972 | _LIBCPP_INLINE_VISIBILITY insert_iterator& operator*() {return *this;} | |
| 973 | _LIBCPP_INLINE_VISIBILITY insert_iterator& operator++() {return *this;} | |
| 974 | _LIBCPP_INLINE_VISIBILITY insert_iterator& operator++(int) {return *this;} | |
| 975 | }; | |
| 976 | ||
| 977 | template <class _Container> | |
| 978 | inline _LIBCPP_INLINE_VISIBILITY | |
| 979 | insert_iterator<_Container> | |
| 980 | inserter(_Container& __x, typename _Container::iterator __i) | |
| 981 | { | |
| 982 | return insert_iterator<_Container>(__x, __i); | |
| 983 | } | |
| 984 | ||
| 985 | template <class _Tp, class _CharT = char, | |
| 986 | class _Traits = char_traits<_CharT>, class _Distance = ptrdiff_t> | |
| 987 | class _LIBCPP_TEMPLATE_VIS istream_iterator | |
| 988 | : public iterator<input_iterator_tag, _Tp, _Distance, const _Tp*, const _Tp&> | |
| 989 | { | |
| 990 | public: | |
| 991 | typedef _CharT char_type; | |
| 992 | typedef _Traits traits_type; | |
| 993 | typedef basic_istream<_CharT,_Traits> istream_type; | |
| 994 | private: | |
| 995 | istream_type* __in_stream_; | |
| 996 | _Tp __value_; | |
| 997 | public: | |
| 998 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istream_iterator() : __in_stream_(nullptr), __value_() {} | |
| 999 | _LIBCPP_INLINE_VISIBILITY istream_iterator(istream_type& __s) : __in_stream_(_VSTD::addressof(__s)) | |
| 1000 | { | |
| 1001 | if (!(*__in_stream_ >> __value_)) | |
| 1002 | __in_stream_ = nullptr; | |
| 1003 | } | |
| 1004 | ||
| 1005 | _LIBCPP_INLINE_VISIBILITY const _Tp& operator*() const {return __value_;} | |
| 1006 | _LIBCPP_INLINE_VISIBILITY const _Tp* operator->() const {return _VSTD::addressof((operator*()));} | |
| 1007 | _LIBCPP_INLINE_VISIBILITY istream_iterator& operator++() | |
| 1008 | { | |
| 1009 | if (!(*__in_stream_ >> __value_)) | |
| 1010 | __in_stream_ = nullptr; | |
| 1011 | return *this; | |
| 1012 | } | |
| 1013 | _LIBCPP_INLINE_VISIBILITY istream_iterator operator++(int) | |
| 1014 | {istream_iterator __t(*this); ++(*this); return __t;} | |
| 1015 | ||
| 1016 | template <class _Up, class _CharU, class _TraitsU, class _DistanceU> | |
| 1017 | friend _LIBCPP_INLINE_VISIBILITY | |
| 1018 | bool | |
| 1019 | operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, | |
| 1020 | const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); | |
| 1021 | ||
| 1022 | template <class _Up, class _CharU, class _TraitsU, class _DistanceU> | |
| 1023 | friend _LIBCPP_INLINE_VISIBILITY | |
| 1024 | bool | |
| 1025 | operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, | |
| 1026 | const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); | |
| 1027 | }; | |
| 1028 | ||
| 1029 | template <class _Tp, class _CharT, class _Traits, class _Distance> | |
| 1030 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1031 | bool | |
| 1032 | operator==(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x, | |
| 1033 | const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y) | |
| 1034 | { | |
| 1035 | return __x.__in_stream_ == __y.__in_stream_; | |
| 1036 | } | |
| 1037 | ||
| 1038 | template <class _Tp, class _CharT, class _Traits, class _Distance> | |
| 1039 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1040 | bool | |
| 1041 | operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x, | |
| 1042 | const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y) | |
| 1043 | { | |
| 1044 | return !(__x == __y); | |
| 1045 | } | |
| 1046 | ||
| 1047 | template <class _Tp, class _CharT = char, class _Traits = char_traits<_CharT> > | |
| 1048 | class _LIBCPP_TEMPLATE_VIS ostream_iterator | |
| 1049 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 1050 | { | |
| 1051 | public: | |
| 1052 | typedef output_iterator_tag iterator_category; | |
| 1053 | typedef void value_type; | |
| 1054 | #if _LIBCPP_STD_VER > 17 | |
| 1055 | typedef std::ptrdiff_t difference_type; | |
| 1056 | #else | |
| 1057 | typedef void difference_type; | |
| 1058 | #endif | |
| 1059 | typedef void pointer; | |
| 1060 | typedef void reference; | |
| 1061 | typedef _CharT char_type; | |
| 1062 | typedef _Traits traits_type; | |
| 1063 | typedef basic_ostream<_CharT, _Traits> ostream_type; | |
| 1064 | ||
| 1065 | private: | |
| 1066 | ostream_type* __out_stream_; | |
| 1067 | const char_type* __delim_; | |
| 1068 | public: | |
| 1069 | _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s) _NOEXCEPT | |
| 1070 | : __out_stream_(_VSTD::addressof(__s)), __delim_(nullptr) {} | |
| 1071 | _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s, const _CharT* __delimiter) _NOEXCEPT | |
| 1072 | : __out_stream_(_VSTD::addressof(__s)), __delim_(__delimiter) {} | |
| 1073 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator=(const _Tp& __value_) | |
| 1074 | { | |
| 1075 | *__out_stream_ << __value_; | |
| 1076 | if (__delim_) | |
| 1077 | *__out_stream_ << __delim_; | |
| 1078 | return *this; | |
| 1079 | } | |
| 1080 | ||
| 1081 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator*() {return *this;} | |
| 1082 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator++() {return *this;} | |
| 1083 | _LIBCPP_INLINE_VISIBILITY ostream_iterator& operator++(int) {return *this;} | |
| 1084 | }; | |
| 1085 | ||
| 1086 | template<class _CharT, class _Traits> | |
| 1087 | class _LIBCPP_TEMPLATE_VIS istreambuf_iterator | |
| 1088 | : public iterator<input_iterator_tag, _CharT, | |
| 1089 | typename _Traits::off_type, _CharT*, | |
| 1090 | _CharT> | |
| 1091 | { | |
| 1092 | public: | |
| 1093 | typedef _CharT char_type; | |
| 1094 | typedef _Traits traits_type; | |
| 1095 | typedef typename _Traits::int_type int_type; | |
| 1096 | typedef basic_streambuf<_CharT,_Traits> streambuf_type; | |
| 1097 | typedef basic_istream<_CharT,_Traits> istream_type; | |
| 1098 | private: | |
| 1099 | mutable streambuf_type* __sbuf_; | |
| 1100 | ||
| 1101 | class __proxy | |
| 1102 | { | |
| 1103 | char_type __keep_; | |
| 1104 | streambuf_type* __sbuf_; | |
| 1105 | _LIBCPP_INLINE_VISIBILITY __proxy(char_type __c, streambuf_type* __s) | |
| 1106 | : __keep_(__c), __sbuf_(__s) {} | |
| 1107 | friend class istreambuf_iterator; | |
| 1108 | public: | |
| 1109 | _LIBCPP_INLINE_VISIBILITY char_type operator*() const {return __keep_;} | |
| 1110 | }; | |
| 1111 | ||
| 1112 | _LIBCPP_INLINE_VISIBILITY | |
| 1113 | bool __test_for_eof() const | |
| 1114 | { | |
| 1115 | if (__sbuf_ && traits_type::eq_int_type(__sbuf_->sgetc(), traits_type::eof())) | |
| 1116 | __sbuf_ = nullptr; | |
| 1117 | return __sbuf_ == nullptr; | |
| 1118 | } | |
| 1119 | public: | |
| 1120 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(nullptr) {} | |
| 1121 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT | |
| 1122 | : __sbuf_(__s.rdbuf()) {} | |
| 1123 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT | |
| 1124 | : __sbuf_(__s) {} | |
| 1125 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(const __proxy& __p) _NOEXCEPT | |
| 1126 | : __sbuf_(__p.__sbuf_) {} | |
| 1127 | ||
| 1128 | _LIBCPP_INLINE_VISIBILITY char_type operator*() const | |
| 1129 | {return static_cast<char_type>(__sbuf_->sgetc());} | |
| 1130 | _LIBCPP_INLINE_VISIBILITY istreambuf_iterator& operator++() | |
| 1131 | { | |
| 1132 | __sbuf_->sbumpc(); | |
| 1133 | return *this; | |
| 1134 | } | |
| 1135 | _LIBCPP_INLINE_VISIBILITY __proxy operator++(int) | |
| 1136 | { | |
| 1137 | return __proxy(__sbuf_->sbumpc(), __sbuf_); | |
| 1138 | } | |
| 1139 | ||
| 1140 | _LIBCPP_INLINE_VISIBILITY bool equal(const istreambuf_iterator& __b) const | |
| 1141 | {return __test_for_eof() == __b.__test_for_eof();} | |
| 1142 | }; | |
| 1143 | ||
| 1144 | template <class _CharT, class _Traits> | |
| 1145 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1146 | bool operator==(const istreambuf_iterator<_CharT,_Traits>& __a, | |
| 1147 | const istreambuf_iterator<_CharT,_Traits>& __b) | |
| 1148 | {return __a.equal(__b);} | |
| 1149 | ||
| 1150 | template <class _CharT, class _Traits> | |
| 1151 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1152 | bool operator!=(const istreambuf_iterator<_CharT,_Traits>& __a, | |
| 1153 | const istreambuf_iterator<_CharT,_Traits>& __b) | |
| 1154 | {return !__a.equal(__b);} | |
| 1155 | ||
| 1156 | template <class _CharT, class _Traits> | |
| 1157 | class _LIBCPP_TEMPLATE_VIS ostreambuf_iterator | |
| 1158 | : public iterator<output_iterator_tag, void, void, void, void> | |
| 1159 | { | |
| 1160 | public: | |
| 1161 | typedef output_iterator_tag iterator_category; | |
| 1162 | typedef void value_type; | |
| 1163 | #if _LIBCPP_STD_VER > 17 | |
| 1164 | typedef std::ptrdiff_t difference_type; | |
| 1165 | #else | |
| 1166 | typedef void difference_type; | |
| 1167 | #endif | |
| 1168 | typedef void pointer; | |
| 1169 | typedef void reference; | |
| 1170 | typedef _CharT char_type; | |
| 1171 | typedef _Traits traits_type; | |
| 1172 | typedef basic_streambuf<_CharT, _Traits> streambuf_type; | |
| 1173 | typedef basic_ostream<_CharT, _Traits> ostream_type; | |
| 1174 | ||
| 1175 | private: | |
| 1176 | streambuf_type* __sbuf_; | |
| 1177 | public: | |
| 1178 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(ostream_type& __s) _NOEXCEPT | |
| 1179 | : __sbuf_(__s.rdbuf()) {} | |
| 1180 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(streambuf_type* __s) _NOEXCEPT | |
| 1181 | : __sbuf_(__s) {} | |
| 1182 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator=(_CharT __c) | |
| 1183 | { | |
| 1184 | if (__sbuf_ && traits_type::eq_int_type(__sbuf_->sputc(__c), traits_type::eof())) | |
| 1185 | __sbuf_ = nullptr; | |
| 1186 | return *this; | |
| 1187 | } | |
| 1188 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator*() {return *this;} | |
| 1189 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator++() {return *this;} | |
| 1190 | _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator& operator++(int) {return *this;} | |
| 1191 | _LIBCPP_INLINE_VISIBILITY bool failed() const _NOEXCEPT {return __sbuf_ == nullptr;} | |
| 1192 | ||
| 1193 | template <class _Ch, class _Tr> | |
| 1194 | friend | |
| 1195 | _LIBCPP_HIDDEN | |
| 1196 | ostreambuf_iterator<_Ch, _Tr> | |
| 1197 | __pad_and_output(ostreambuf_iterator<_Ch, _Tr> __s, | |
| 1198 | const _Ch* __ob, const _Ch* __op, const _Ch* __oe, | |
| 1199 | ios_base& __iob, _Ch __fl); | |
| 1200 | }; | |
| 1201 | ||
| 1202 | template <class _Iter> | |
| 1203 | class _LIBCPP_TEMPLATE_VIS move_iterator | |
| 1204 | { | |
| 1205 | private: | |
| 1206 | _Iter __i; | |
| 1207 | public: | |
| 1208 | typedef _Iter iterator_type; | |
| 1209 | typedef typename iterator_traits<iterator_type>::iterator_category iterator_category; | |
| 1210 | typedef typename iterator_traits<iterator_type>::value_type value_type; | |
| 1211 | typedef typename iterator_traits<iterator_type>::difference_type difference_type; | |
| 1212 | typedef iterator_type pointer; | |
| 1213 | #ifndef _LIBCPP_CXX03_LANG | |
| 1214 | typedef typename iterator_traits<iterator_type>::reference __reference; | |
| 1215 | typedef typename conditional< | |
| 1216 | is_reference<__reference>::value, | |
| 1217 | typename remove_reference<__reference>::type&&, | |
| 1218 | __reference | |
| 1219 | >::type reference; | |
| 1220 | #else | |
| 1221 | typedef typename iterator_traits<iterator_type>::reference reference; | |
| 1222 | #endif | |
| 1223 | ||
| 1224 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1225 | move_iterator() : __i() {} | |
| 1226 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1227 | explicit move_iterator(_Iter __x) : __i(__x) {} | |
| 1228 | template <class _Up> | |
| 1229 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1230 | move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {} | |
| 1231 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return __i;} | |
| 1232 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1233 | reference operator*() const { return static_cast<reference>(*__i); } | |
| 1234 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1235 | pointer operator->() const { return __i;} | |
| 1236 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1237 | move_iterator& operator++() {++__i; return *this;} | |
| 1238 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1239 | move_iterator operator++(int) {move_iterator __tmp(*this); ++__i; return __tmp;} | |
| 1240 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1241 | move_iterator& operator--() {--__i; return *this;} | |
| 1242 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1243 | move_iterator operator--(int) {move_iterator __tmp(*this); --__i; return __tmp;} | |
| 1244 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1245 | move_iterator operator+ (difference_type __n) const {return move_iterator(__i + __n);} | |
| 1246 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1247 | move_iterator& operator+=(difference_type __n) {__i += __n; return *this;} | |
| 1248 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1249 | move_iterator operator- (difference_type __n) const {return move_iterator(__i - __n);} | |
| 1250 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1251 | move_iterator& operator-=(difference_type __n) {__i -= __n; return *this;} | |
| 1252 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1253 | reference operator[](difference_type __n) const { return static_cast<reference>(__i[__n]); } | |
| 1254 | }; | |
| 1255 | ||
| 1256 | template <class _Iter1, class _Iter2> | |
| 1257 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1258 | bool | |
| 1259 | operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1260 | { | |
| 1261 | return __x.base() == __y.base(); | |
| 1262 | } | |
| 1263 | ||
| 1264 | template <class _Iter1, class _Iter2> | |
| 1265 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1266 | bool | |
| 1267 | operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1268 | { | |
| 1269 | return __x.base() < __y.base(); | |
| 1270 | } | |
| 1271 | ||
| 1272 | template <class _Iter1, class _Iter2> | |
| 1273 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1274 | bool | |
| 1275 | operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1276 | { | |
| 1277 | return __x.base() != __y.base(); | |
| 1278 | } | |
| 1279 | ||
| 1280 | template <class _Iter1, class _Iter2> | |
| 1281 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1282 | bool | |
| 1283 | operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1284 | { | |
| 1285 | return __x.base() > __y.base(); | |
| 1286 | } | |
| 1287 | ||
| 1288 | template <class _Iter1, class _Iter2> | |
| 1289 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1290 | bool | |
| 1291 | operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1292 | { | |
| 1293 | return __x.base() >= __y.base(); | |
| 1294 | } | |
| 1295 | ||
| 1296 | template <class _Iter1, class _Iter2> | |
| 1297 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1298 | bool | |
| 1299 | operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1300 | { | |
| 1301 | return __x.base() <= __y.base(); | |
| 1302 | } | |
| 1303 | ||
| 1304 | #ifndef _LIBCPP_CXX03_LANG | |
| 1305 | template <class _Iter1, class _Iter2> | |
| 1306 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1307 | auto | |
| 1308 | operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1309 | -> decltype(__x.base() - __y.base()) | |
| 1310 | { | |
| 1311 | return __x.base() - __y.base(); | |
| 1312 | } | |
| 1313 | #else | |
| 1314 | template <class _Iter1, class _Iter2> | |
| 1315 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1316 | typename move_iterator<_Iter1>::difference_type | |
| 1317 | operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) | |
| 1318 | { | |
| 1319 | return __x.base() - __y.base(); | |
| 1320 | } | |
| 1321 | #endif | |
| 1322 | ||
| 1323 | template <class _Iter> | |
| 1324 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1325 | move_iterator<_Iter> | |
| 1326 | operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) | |
| 1327 | { | |
| 1328 | return move_iterator<_Iter>(__x.base() + __n); | |
| 1329 | } | |
| 1330 | ||
| 1331 | template <class _Iter> | |
| 1332 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1333 | move_iterator<_Iter> | |
| 1334 | make_move_iterator(_Iter __i) | |
| 1335 | { | |
| 1336 | return move_iterator<_Iter>(__i); | |
| 1337 | } | |
| 1338 | ||
| 1339 | // __wrap_iter | |
| 1340 | ||
| 1341 | template <class _Iter> class __wrap_iter; | |
| 1342 | ||
| 1343 | template <class _Iter1, class _Iter2> | |
| 1344 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1345 | bool | |
| 1346 | operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1347 | ||
| 1348 | template <class _Iter1, class _Iter2> | |
| 1349 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1350 | bool | |
| 1351 | operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1352 | ||
| 1353 | template <class _Iter1, class _Iter2> | |
| 1354 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1355 | bool | |
| 1356 | operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1357 | ||
| 1358 | template <class _Iter1, class _Iter2> | |
| 1359 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1360 | bool | |
| 1361 | operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1362 | ||
| 1363 | template <class _Iter1, class _Iter2> | |
| 1364 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1365 | bool | |
| 1366 | operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1367 | ||
| 1368 | template <class _Iter1, class _Iter2> | |
| 1369 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1370 | bool | |
| 1371 | operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1372 | ||
| 1373 | #ifndef _LIBCPP_CXX03_LANG | |
| 1374 | template <class _Iter1, class _Iter2> | |
| 1375 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1376 | auto | |
| 1377 | operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1378 | -> decltype(__x.base() - __y.base()); | |
| 1379 | #else | |
| 1380 | template <class _Iter1, class _Iter2> | |
| 1381 | _LIBCPP_INLINE_VISIBILITY | |
| 1382 | typename __wrap_iter<_Iter1>::difference_type | |
| 1383 | operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1384 | #endif | |
| 1385 | ||
| 1386 | template <class _Iter> | |
| 1387 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1388 | __wrap_iter<_Iter> | |
| 1389 | operator+(typename __wrap_iter<_Iter>::difference_type, __wrap_iter<_Iter>) _NOEXCEPT; | |
| 1390 | ||
| 1391 | template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 copy(_Ip, _Ip, _Op); | |
| 1392 | template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 copy_backward(_B1, _B1, _B2); | |
| 1393 | template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 move(_Ip, _Ip, _Op); | |
| 1394 | template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 move_backward(_B1, _B1, _B2); | |
| 1395 | ||
| 1396 | #if _LIBCPP_DEBUG_LEVEL < 2 | |
| 1397 | ||
| 1398 | template <class _Tp> | |
| 1399 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1400 | typename enable_if | |
| 1401 | < | |
| 1402 | is_trivially_copy_assignable<_Tp>::value, | |
| 1403 | _Tp* | |
| 1404 | >::type | |
| 1405 | __unwrap_iter(__wrap_iter<_Tp*>); | |
| 1406 | ||
| 1407 | #else | |
| 1408 | ||
| 1409 | template <class _Tp> | |
| 1410 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1411 | typename enable_if | |
| 1412 | < | |
| 1413 | is_trivially_copy_assignable<_Tp>::value, | |
| 1414 | __wrap_iter<_Tp*> | |
| 1415 | >::type | |
| 1416 | __unwrap_iter(__wrap_iter<_Tp*> __i); | |
| 1417 | ||
| 1418 | #endif | |
| 1419 | ||
| 1420 | template <class _Iter> | |
| 1421 | class __wrap_iter | |
| 1422 | { | |
| 1423 | public: | |
| 1424 | typedef _Iter iterator_type; | |
| 1425 | typedef typename iterator_traits<iterator_type>::iterator_category iterator_category; | |
| 1426 | typedef typename iterator_traits<iterator_type>::value_type value_type; | |
| 1427 | typedef typename iterator_traits<iterator_type>::difference_type difference_type; | |
| 1428 | typedef typename iterator_traits<iterator_type>::pointer pointer; | |
| 1429 | typedef typename iterator_traits<iterator_type>::reference reference; | |
| 1430 | private: | |
| 1431 | iterator_type __i; | |
| 1432 | public: | |
| 1433 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter() _NOEXCEPT | |
| 1434 | #if _LIBCPP_STD_VER > 11 | |
| 1435 | : __i{} | |
| 1436 | #endif | |
| 1437 | { | |
| 1438 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1439 | __get_db()->__insert_i(this); | |
| 1440 | #endif | |
| 1441 | } | |
| 1442 | template <class _Up> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1443 | __wrap_iter(const __wrap_iter<_Up>& __u, | |
| 1444 | typename enable_if<is_convertible<_Up, iterator_type>::value>::type* = nullptr) _NOEXCEPT | |
| 1445 | : __i(__u.base()) | |
| 1446 | { | |
| 1447 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1448 | __get_db()->__iterator_copy(this, &__u); | |
| 1449 | #endif | |
| 1450 | } | |
| 1451 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1452 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1453 | __wrap_iter(const __wrap_iter& __x) | |
| 1454 | : __i(__x.base()) | |
| 1455 | { | |
| 1456 | __get_db()->__iterator_copy(this, &__x); | |
| 1457 | } | |
| 1458 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1459 | __wrap_iter& operator=(const __wrap_iter& __x) | |
| 1460 | { | |
| 1461 | if (this != &__x) | |
| 1462 | { | |
| 1463 | __get_db()->__iterator_copy(this, &__x); | |
| 1464 | __i = __x.__i; | |
| 1465 | } | |
| 1466 | return *this; | |
| 1467 | } | |
| 1468 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1469 | ~__wrap_iter() | |
| 1470 | { | |
| 1471 | __get_db()->__erase_i(this); | |
| 1472 | } | |
| 1473 | #endif | |
| 1474 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator*() const _NOEXCEPT | |
| 1475 | { | |
| 1476 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1477 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), | |
| 1478 | "Attempted to dereference a non-dereferenceable iterator"); | |
| 1479 | #endif | |
| 1480 | return *__i; | |
| 1481 | } | |
| 1482 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG pointer operator->() const _NOEXCEPT | |
| 1483 | { | |
| 1484 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1485 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), | |
| 1486 | "Attempted to dereference a non-dereferenceable iterator"); | |
| 1487 | #endif | |
| 1488 | return (pointer)_VSTD::addressof(*__i); | |
| 1489 | } | |
| 1490 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator++() _NOEXCEPT | |
| 1491 | { | |
| 1492 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1493 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), | |
| 1494 | "Attempted to increment non-incrementable iterator"); | |
| 1495 | #endif | |
| 1496 | ++__i; | |
| 1497 | return *this; | |
| 1498 | } | |
| 1499 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator++(int) _NOEXCEPT | |
| 1500 | {__wrap_iter __tmp(*this); ++(*this); return __tmp;} | |
| 1501 | ||
| 1502 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator--() _NOEXCEPT | |
| 1503 | { | |
| 1504 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1505 | _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), | |
| 1506 | "Attempted to decrement non-decrementable iterator"); | |
| 1507 | #endif | |
| 1508 | --__i; | |
| 1509 | return *this; | |
| 1510 | } | |
| 1511 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator--(int) _NOEXCEPT | |
| 1512 | {__wrap_iter __tmp(*this); --(*this); return __tmp;} | |
| 1513 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator+ (difference_type __n) const _NOEXCEPT | |
| 1514 | {__wrap_iter __w(*this); __w += __n; return __w;} | |
| 1515 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator+=(difference_type __n) _NOEXCEPT | |
| 1516 | { | |
| 1517 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1518 | _LIBCPP_ASSERT(__get_const_db()->__addable(this, __n), | |
| 1519 | "Attempted to add/subtract iterator outside of valid range"); | |
| 1520 | #endif | |
| 1521 | __i += __n; | |
| 1522 | return *this; | |
| 1523 | } | |
| 1524 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator- (difference_type __n) const _NOEXCEPT | |
| 1525 | {return *this + (-__n);} | |
| 1526 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator-=(difference_type __n) _NOEXCEPT | |
| 1527 | {*this += -__n; return *this;} | |
| 1528 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator[](difference_type __n) const _NOEXCEPT | |
| 1529 | { | |
| 1530 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1531 | _LIBCPP_ASSERT(__get_const_db()->__subscriptable(this, __n), | |
| 1532 | "Attempted to subscript iterator outside of valid range"); | |
| 1533 | #endif | |
| 1534 | return __i[__n]; | |
| 1535 | } | |
| 1536 | ||
| 1537 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG iterator_type base() const _NOEXCEPT {return __i;} | |
| 1538 | ||
| 1539 | private: | |
| 1540 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1541 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(const void* __p, iterator_type __x) : __i(__x) | |
| 1542 | { | |
| 1543 | __get_db()->__insert_ic(this, __p); | |
| 1544 | } | |
| 1545 | #else | |
| 1546 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(iterator_type __x) _NOEXCEPT : __i(__x) {} | |
| 1547 | #endif | |
| 1548 | ||
| 1549 | template <class _Up> friend class __wrap_iter; | |
| 1550 | template <class _CharT, class _Traits, class _Alloc> friend class basic_string; | |
| 1551 | template <class _Tp, class _Alloc> friend class _LIBCPP_TEMPLATE_VIS vector; | |
| 1552 | template <class _Tp, size_t> friend class _LIBCPP_TEMPLATE_VIS span; | |
| 1553 | ||
| 1554 | template <class _Iter1, class _Iter2> | |
| 1555 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1556 | bool | |
| 1557 | operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1558 | ||
| 1559 | template <class _Iter1, class _Iter2> | |
| 1560 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1561 | bool | |
| 1562 | operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1563 | ||
| 1564 | template <class _Iter1, class _Iter2> | |
| 1565 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1566 | bool | |
| 1567 | operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1568 | ||
| 1569 | template <class _Iter1, class _Iter2> | |
| 1570 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1571 | bool | |
| 1572 | operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1573 | ||
| 1574 | template <class _Iter1, class _Iter2> | |
| 1575 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1576 | bool | |
| 1577 | operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1578 | ||
| 1579 | template <class _Iter1, class _Iter2> | |
| 1580 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1581 | bool | |
| 1582 | operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1583 | ||
| 1584 | #ifndef _LIBCPP_CXX03_LANG | |
| 1585 | template <class _Iter1, class _Iter2> | |
| 1586 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1587 | auto | |
| 1588 | operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1589 | -> decltype(__x.base() - __y.base()); | |
| 1590 | #else | |
| 1591 | template <class _Iter1, class _Iter2> | |
| 1592 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1593 | typename __wrap_iter<_Iter1>::difference_type | |
| 1594 | operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT; | |
| 1595 | #endif | |
| 1596 | ||
| 1597 | template <class _Iter1> | |
| 1598 | _LIBCPP_CONSTEXPR_IF_NODEBUG friend | |
| 1599 | __wrap_iter<_Iter1> | |
| 1600 | operator+(typename __wrap_iter<_Iter1>::difference_type, __wrap_iter<_Iter1>) _NOEXCEPT; | |
| 1601 | ||
| 1602 | template <class _Ip, class _Op> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _Op copy(_Ip, _Ip, _Op); | |
| 1603 | template <class _B1, class _B2> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _B2 copy_backward(_B1, _B1, _B2); | |
| 1604 | template <class _Ip, class _Op> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _Op move(_Ip, _Ip, _Op); | |
| 1605 | template <class _B1, class _B2> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _B2 move_backward(_B1, _B1, _B2); | |
| 1606 | ||
| 1607 | #if _LIBCPP_DEBUG_LEVEL < 2 | |
| 1608 | template <class _Tp> | |
| 1609 | _LIBCPP_CONSTEXPR friend | |
| 1610 | typename enable_if | |
| 1611 | < | |
| 1612 | is_trivially_copy_assignable<_Tp>::value, | |
| 1613 | _Tp* | |
| 1614 | >::type | |
| 1615 | __unwrap_iter(__wrap_iter<_Tp*>); | |
| 1616 | #else | |
| 1617 | template <class _Tp> | |
| 1618 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR friend | |
| 1619 | typename enable_if | |
| 1620 | < | |
| 1621 | is_trivially_copy_assignable<_Tp>::value, | |
| 1622 | __wrap_iter<_Tp*> | |
| 1623 | >::type | |
| 1624 | __unwrap_iter(__wrap_iter<_Tp*> __i); | |
| 1625 | #endif | |
| 1626 | }; | |
| 1627 | ||
| 1628 | template <class _Iter1, class _Iter2> | |
| 1629 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1630 | bool | |
| 1631 | operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1632 | { | |
| 1633 | return __x.base() == __y.base(); | |
| 1634 | } | |
| 1635 | ||
| 1636 | template <class _Iter1, class _Iter2> | |
| 1637 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1638 | bool | |
| 1639 | operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1640 | { | |
| 1641 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1642 | _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), | |
| 1643 | "Attempted to compare incomparable iterators"); | |
| 1644 | #endif | |
| 1645 | return __x.base() < __y.base(); | |
| 1646 | } | |
| 1647 | ||
| 1648 | template <class _Iter1, class _Iter2> | |
| 1649 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1650 | bool | |
| 1651 | operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1652 | { | |
| 1653 | return !(__x == __y); | |
| 1654 | } | |
| 1655 | ||
| 1656 | template <class _Iter1, class _Iter2> | |
| 1657 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1658 | bool | |
| 1659 | operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1660 | { | |
| 1661 | return __y < __x; | |
| 1662 | } | |
| 1663 | ||
| 1664 | template <class _Iter1, class _Iter2> | |
| 1665 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1666 | bool | |
| 1667 | operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1668 | { | |
| 1669 | return !(__x < __y); | |
| 1670 | } | |
| 1671 | ||
| 1672 | template <class _Iter1, class _Iter2> | |
| 1673 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1674 | bool | |
| 1675 | operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1676 | { | |
| 1677 | return !(__y < __x); | |
| 1678 | } | |
| 1679 | ||
| 1680 | template <class _Iter1> | |
| 1681 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1682 | bool | |
| 1683 | operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 1684 | { | |
| 1685 | return !(__x == __y); | |
| 1686 | } | |
| 1687 | ||
| 1688 | template <class _Iter1> | |
| 1689 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1690 | bool | |
| 1691 | operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 1692 | { | |
| 1693 | return __y < __x; | |
| 1694 | } | |
| 1695 | ||
| 1696 | template <class _Iter1> | |
| 1697 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1698 | bool | |
| 1699 | operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 1700 | { | |
| 1701 | return !(__x < __y); | |
| 1702 | } | |
| 1703 | ||
| 1704 | template <class _Iter1> | |
| 1705 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1706 | bool | |
| 1707 | operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT | |
| 1708 | { | |
| 1709 | return !(__y < __x); | |
| 1710 | } | |
| 1711 | ||
| 1712 | #ifndef _LIBCPP_CXX03_LANG | |
| 1713 | template <class _Iter1, class _Iter2> | |
| 1714 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1715 | auto | |
| 1716 | operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1717 | -> decltype(__x.base() - __y.base()) | |
| 1718 | { | |
| 1719 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1720 | _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), | |
| 1721 | "Attempted to subtract incompatible iterators"); | |
| 1722 | #endif | |
| 1723 | return __x.base() - __y.base(); | |
| 1724 | } | |
| 1725 | #else | |
| 1726 | template <class _Iter1, class _Iter2> | |
| 1727 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1728 | typename __wrap_iter<_Iter1>::difference_type | |
| 1729 | operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT | |
| 1730 | { | |
| 1731 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1732 | _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), | |
| 1733 | "Attempted to subtract incompatible iterators"); | |
| 1734 | #endif | |
| 1735 | return __x.base() - __y.base(); | |
| 1736 | } | |
| 1737 | #endif | |
| 1738 | ||
| 1739 | template <class _Iter> | |
| 1740 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG | |
| 1741 | __wrap_iter<_Iter> | |
| 1742 | operator+(typename __wrap_iter<_Iter>::difference_type __n, | |
| 1743 | __wrap_iter<_Iter> __x) _NOEXCEPT | |
| 1744 | { | |
| 1745 | __x += __n; | |
| 1746 | return __x; | |
| 1747 | } | |
| 1748 | ||
| 1749 | template <class _Iter> | |
| 1750 | struct __libcpp_is_trivial_iterator | |
| 1751 | : public _LIBCPP_BOOL_CONSTANT(is_pointer<_Iter>::value) {}; | |
| 1752 | ||
| 1753 | template <class _Iter> | |
| 1754 | struct __libcpp_is_trivial_iterator<move_iterator<_Iter> > | |
| 1755 | : public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value) {}; | |
| 1756 | ||
| 1757 | template <class _Iter> | |
| 1758 | struct __libcpp_is_trivial_iterator<reverse_iterator<_Iter> > | |
| 1759 | : public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value) {}; | |
| 1760 | ||
| 1761 | template <class _Iter> | |
| 1762 | struct __libcpp_is_trivial_iterator<__wrap_iter<_Iter> > | |
| 1763 | : public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value) {}; | |
| 1764 | ||
| 1765 | ||
| 1766 | template <class _Tp, size_t _Np> | |
| 1767 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 1768 | _Tp* | |
| 1769 | begin(_Tp (&__array)[_Np]) | |
| 1770 | { | |
| 1771 | return __array; | |
| 1772 | } | |
| 1773 | ||
| 1774 | template <class _Tp, size_t _Np> | |
| 1775 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 1776 | _Tp* | |
| 1777 | end(_Tp (&__array)[_Np]) | |
| 1778 | { | |
| 1779 | return __array + _Np; | |
| 1780 | } | |
| 1781 | ||
| 1782 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 1783 | ||
| 1784 | template <class _Cp> | |
| 1785 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1786 | auto | |
| 1787 | begin(_Cp& __c) -> decltype(__c.begin()) | |
| 1788 | { | |
| 1789 | return __c.begin(); | |
| 1790 | } | |
| 1791 | ||
| 1792 | template <class _Cp> | |
| 1793 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1794 | auto | |
| 1795 | begin(const _Cp& __c) -> decltype(__c.begin()) | |
| 1796 | { | |
| 1797 | return __c.begin(); | |
| 1798 | } | |
| 1799 | ||
| 1800 | template <class _Cp> | |
| 1801 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1802 | auto | |
| 1803 | end(_Cp& __c) -> decltype(__c.end()) | |
| 1804 | { | |
| 1805 | return __c.end(); | |
| 1806 | } | |
| 1807 | ||
| 1808 | template <class _Cp> | |
| 1809 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1810 | auto | |
| 1811 | end(const _Cp& __c) -> decltype(__c.end()) | |
| 1812 | { | |
| 1813 | return __c.end(); | |
| 1814 | } | |
| 1815 | ||
| 1816 | #if _LIBCPP_STD_VER > 11 | |
| 1817 | ||
| 1818 | template <class _Tp, size_t _Np> | |
| 1819 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1820 | reverse_iterator<_Tp*> rbegin(_Tp (&__array)[_Np]) | |
| 1821 | { | |
| 1822 | return reverse_iterator<_Tp*>(__array + _Np); | |
| 1823 | } | |
| 1824 | ||
| 1825 | template <class _Tp, size_t _Np> | |
| 1826 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1827 | reverse_iterator<_Tp*> rend(_Tp (&__array)[_Np]) | |
| 1828 | { | |
| 1829 | return reverse_iterator<_Tp*>(__array); | |
| 1830 | } | |
| 1831 | ||
| 1832 | template <class _Ep> | |
| 1833 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1834 | reverse_iterator<const _Ep*> rbegin(initializer_list<_Ep> __il) | |
| 1835 | { | |
| 1836 | return reverse_iterator<const _Ep*>(__il.end()); | |
| 1837 | } | |
| 1838 | ||
| 1839 | template <class _Ep> | |
| 1840 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1841 | reverse_iterator<const _Ep*> rend(initializer_list<_Ep> __il) | |
| 1842 | { | |
| 1843 | return reverse_iterator<const _Ep*>(__il.begin()); | |
| 1844 | } | |
| 1845 | ||
| 1846 | template <class _Cp> | |
| 1847 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 1848 | auto cbegin(const _Cp& __c) -> decltype(_VSTD::begin(__c)) | |
| 1849 | { | |
| 1850 | return _VSTD::begin(__c); | |
| 1851 | } | |
| 1852 | ||
| 1853 | template <class _Cp> | |
| 1854 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 1855 | auto cend(const _Cp& __c) -> decltype(_VSTD::end(__c)) | |
| 1856 | { | |
| 1857 | return _VSTD::end(__c); | |
| 1858 | } | |
| 1859 | ||
| 1860 | template <class _Cp> | |
| 1861 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1862 | auto rbegin(_Cp& __c) -> decltype(__c.rbegin()) | |
| 1863 | { | |
| 1864 | return __c.rbegin(); | |
| 1865 | } | |
| 1866 | ||
| 1867 | template <class _Cp> | |
| 1868 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1869 | auto rbegin(const _Cp& __c) -> decltype(__c.rbegin()) | |
| 1870 | { | |
| 1871 | return __c.rbegin(); | |
| 1872 | } | |
| 1873 | ||
| 1874 | template <class _Cp> | |
| 1875 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1876 | auto rend(_Cp& __c) -> decltype(__c.rend()) | |
| 1877 | { | |
| 1878 | return __c.rend(); | |
| 1879 | } | |
| 1880 | ||
| 1881 | template <class _Cp> | |
| 1882 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1883 | auto rend(const _Cp& __c) -> decltype(__c.rend()) | |
| 1884 | { | |
| 1885 | return __c.rend(); | |
| 1886 | } | |
| 1887 | ||
| 1888 | template <class _Cp> | |
| 1889 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1890 | auto crbegin(const _Cp& __c) -> decltype(_VSTD::rbegin(__c)) | |
| 1891 | { | |
| 1892 | return _VSTD::rbegin(__c); | |
| 1893 | } | |
| 1894 | ||
| 1895 | template <class _Cp> | |
| 1896 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1897 | auto crend(const _Cp& __c) -> decltype(_VSTD::rend(__c)) | |
| 1898 | { | |
| 1899 | return _VSTD::rend(__c); | |
| 1900 | } | |
| 1901 | ||
| 1902 | #endif | |
| 1903 | ||
| 1904 | ||
| 1905 | #else // defined(_LIBCPP_CXX03_LANG) | |
| 1906 | ||
| 1907 | template <class _Cp> | |
| 1908 | _LIBCPP_INLINE_VISIBILITY | |
| 1909 | typename _Cp::iterator | |
| 1910 | begin(_Cp& __c) | |
| 1911 | { | |
| 1912 | return __c.begin(); | |
| 1913 | } | |
| 1914 | ||
| 1915 | template <class _Cp> | |
| 1916 | _LIBCPP_INLINE_VISIBILITY | |
| 1917 | typename _Cp::const_iterator | |
| 1918 | begin(const _Cp& __c) | |
| 1919 | { | |
| 1920 | return __c.begin(); | |
| 1921 | } | |
| 1922 | ||
| 1923 | template <class _Cp> | |
| 1924 | _LIBCPP_INLINE_VISIBILITY | |
| 1925 | typename _Cp::iterator | |
| 1926 | end(_Cp& __c) | |
| 1927 | { | |
| 1928 | return __c.end(); | |
| 1929 | } | |
| 1930 | ||
| 1931 | template <class _Cp> | |
| 1932 | _LIBCPP_INLINE_VISIBILITY | |
| 1933 | typename _Cp::const_iterator | |
| 1934 | end(const _Cp& __c) | |
| 1935 | { | |
| 1936 | return __c.end(); | |
| 1937 | } | |
| 1938 | ||
| 1939 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 1940 | ||
| 1941 | #if _LIBCPP_STD_VER > 14 | |
| 1942 | ||
| 1943 | // #if _LIBCPP_STD_VER > 11 | |
| 1944 | // template <> | |
| 1945 | // struct _LIBCPP_TEMPLATE_VIS plus<void> | |
| 1946 | // { | |
| 1947 | // template <class _T1, class _T2> | |
| 1948 | // _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 1949 | // auto operator()(_T1&& __t, _T2&& __u) const | |
| 1950 | // _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u))) | |
| 1951 | // -> decltype (_VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u)) | |
| 1952 | // { return _VSTD::forward<_T1>(__t) + _VSTD::forward<_T2>(__u); } | |
| 1953 | // typedef void is_transparent; | |
| 1954 | // }; | |
| 1955 | // #endif | |
| 1956 | ||
| 1957 | template <class _Cont> | |
| 1958 | _LIBCPP_INLINE_VISIBILITY | |
| 1959 | constexpr auto size(const _Cont& __c) | |
| 1960 | _NOEXCEPT_(noexcept(__c.size())) | |
| 1961 | -> decltype (__c.size()) | |
| 1962 | { return __c.size(); } | |
| 1963 | ||
| 1964 | template <class _Tp, size_t _Sz> | |
| 1965 | _LIBCPP_INLINE_VISIBILITY | |
| 1966 | constexpr size_t size(const _Tp (&)[_Sz]) noexcept { return _Sz; } | |
| 1967 | ||
| 1968 | #if _LIBCPP_STD_VER > 17 | |
| 1969 | template <class _Cont> | |
| 1970 | _LIBCPP_INLINE_VISIBILITY | |
| 1971 | constexpr auto ssize(const _Cont& __c) | |
| 1972 | _NOEXCEPT_(noexcept(static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(__c.size())>>>(__c.size()))) | |
| 1973 | -> common_type_t<ptrdiff_t, make_signed_t<decltype(__c.size())>> | |
| 1974 | { return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(__c.size())>>>(__c.size()); } | |
| 1975 | ||
| 1976 | template <class _Tp, ptrdiff_t _Sz> | |
| 1977 | _LIBCPP_INLINE_VISIBILITY | |
| 1978 | constexpr ptrdiff_t ssize(const _Tp (&)[_Sz]) noexcept { return _Sz; } | |
| 1979 | #endif | |
| 1980 | ||
| 1981 | template <class _Cont> | |
| 1982 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 1983 | constexpr auto empty(const _Cont& __c) | |
| 1984 | _NOEXCEPT_(noexcept(__c.empty())) | |
| 1985 | -> decltype (__c.empty()) | |
| 1986 | { return __c.empty(); } | |
| 1987 | ||
| 1988 | template <class _Tp, size_t _Sz> | |
| 1989 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 1990 | constexpr bool empty(const _Tp (&)[_Sz]) noexcept { return false; } | |
| 1991 | ||
| 1992 | template <class _Ep> | |
| 1993 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 1994 | constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } | |
| 1995 | ||
| 1996 | template <class _Cont> constexpr | |
| 1997 | _LIBCPP_INLINE_VISIBILITY | |
| 1998 | auto data(_Cont& __c) | |
| 1999 | _NOEXCEPT_(noexcept(__c.data())) | |
| 2000 | -> decltype (__c.data()) | |
| 2001 | { return __c.data(); } | |
| 2002 | ||
| 2003 | template <class _Cont> constexpr | |
| 2004 | _LIBCPP_INLINE_VISIBILITY | |
| 2005 | auto data(const _Cont& __c) | |
| 2006 | _NOEXCEPT_(noexcept(__c.data())) | |
| 2007 | -> decltype (__c.data()) | |
| 2008 | { return __c.data(); } | |
| 2009 | ||
| 2010 | template <class _Tp, size_t _Sz> | |
| 2011 | _LIBCPP_INLINE_VISIBILITY | |
| 2012 | constexpr _Tp* data(_Tp (&__array)[_Sz]) noexcept { return __array; } | |
| 2013 | ||
| 2014 | template <class _Ep> | |
| 2015 | _LIBCPP_INLINE_VISIBILITY | |
| 2016 | constexpr const _Ep* data(initializer_list<_Ep> __il) noexcept { return __il.begin(); } | |
| 2017 | #endif | |
| 2018 | ||
| 2019 | ||
| 2020 | _LIBCPP_END_NAMESPACE_STD | |
| 2021 | ||
| 2022 | #endif // _LIBCPP_ITERATOR | |
| 624 | #endif // _LIBCPP_ITERATOR |
lib/libcxx/include/latch+1-1| ... | ... | @@ -40,8 +40,8 @@ namespace std |
| 40 | 40 | |
| 41 | 41 | */ |
| 42 | 42 | |
| 43 | #include <__config> | |
| 44 | 43 | #include <__availability> |
| 44 | #include <__config> | |
| 45 | 45 | #include <atomic> |
| 46 | 46 | |
| 47 | 47 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
lib/libcxx/include/limits+1-1| ... | ... | @@ -815,4 +815,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 815 | 815 | |
| 816 | 816 | _LIBCPP_POP_MACROS |
| 817 | 817 | |
| 818 | #endif // _LIBCPP_LIMITS | |
| 818 | #endif // _LIBCPP_LIMITS |
lib/libcxx/include/limits.h+1-1| ... | ... | @@ -61,4 +61,4 @@ Macros: |
| 61 | 61 | #include_next <limits.h> |
| 62 | 62 | #endif // __GNUC__ |
| 63 | 63 | |
| 64 | #endif // _LIBCPP_LIMITS_H | |
| 64 | #endif // _LIBCPP_LIMITS_H |
lib/libcxx/include/list+47-45| ... | ... | @@ -181,17 +181,16 @@ template <class T, class Allocator, class Predicate> |
| 181 | 181 | */ |
| 182 | 182 | |
| 183 | 183 | #include <__config> |
| 184 | ||
| 185 | #include <memory> | |
| 186 | #include <limits> | |
| 184 | #include <__debug> | |
| 185 | #include <__utility/forward.h> | |
| 186 | #include <algorithm> | |
| 187 | 187 | #include <initializer_list> |
| 188 | 188 | #include <iterator> |
| 189 | #include <algorithm> | |
| 189 | #include <limits> | |
| 190 | #include <memory> | |
| 190 | 191 | #include <type_traits> |
| 191 | 192 | #include <version> |
| 192 | 193 | |
| 193 | #include <__debug> | |
| 194 | ||
| 195 | 194 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 196 | 195 | #pragma GCC system_header |
| 197 | 196 | #endif |
| ... | ... | @@ -267,7 +266,7 @@ struct __list_node_base |
| 267 | 266 | }; |
| 268 | 267 | |
| 269 | 268 | template <class _Tp, class _VoidPtr> |
| 270 | struct __list_node | |
| 269 | struct _LIBCPP_STANDALONE_DEBUG __list_node | |
| 271 | 270 | : public __list_node_base<_Tp, _VoidPtr> |
| 272 | 271 | { |
| 273 | 272 | _Tp __value_; |
| ... | ... | @@ -351,7 +350,7 @@ public: |
| 351 | 350 | return *this; |
| 352 | 351 | } |
| 353 | 352 | |
| 354 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 353 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 355 | 354 | |
| 356 | 355 | _LIBCPP_INLINE_VISIBILITY |
| 357 | 356 | reference operator*() const |
| ... | ... | @@ -377,7 +376,7 @@ public: |
| 377 | 376 | { |
| 378 | 377 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 379 | 378 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
| 380 | "Attempted to increment non-incrementable list::iterator"); | |
| 379 | "Attempted to increment a non-incrementable list::iterator"); | |
| 381 | 380 | #endif |
| 382 | 381 | __ptr_ = __ptr_->__next_; |
| 383 | 382 | return *this; |
| ... | ... | @@ -390,7 +389,7 @@ public: |
| 390 | 389 | { |
| 391 | 390 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 392 | 391 | _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), |
| 393 | "Attempted to decrement non-decrementable list::iterator"); | |
| 392 | "Attempted to decrement a non-decrementable list::iterator"); | |
| 394 | 393 | #endif |
| 395 | 394 | __ptr_ = __ptr_->__prev_; |
| 396 | 395 | return *this; |
| ... | ... | @@ -479,7 +478,7 @@ public: |
| 479 | 478 | return *this; |
| 480 | 479 | } |
| 481 | 480 | |
| 482 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 481 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 483 | 482 | _LIBCPP_INLINE_VISIBILITY |
| 484 | 483 | reference operator*() const |
| 485 | 484 | { |
| ... | ... | @@ -504,7 +503,7 @@ public: |
| 504 | 503 | { |
| 505 | 504 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 506 | 505 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
| 507 | "Attempted to increment non-incrementable list::const_iterator"); | |
| 506 | "Attempted to increment a non-incrementable list::const_iterator"); | |
| 508 | 507 | #endif |
| 509 | 508 | __ptr_ = __ptr_->__next_; |
| 510 | 509 | return *this; |
| ... | ... | @@ -517,7 +516,7 @@ public: |
| 517 | 516 | { |
| 518 | 517 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 519 | 518 | _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), |
| 520 | "Attempted to decrement non-decrementable list::const_iterator"); | |
| 519 | "Attempted to decrement a non-decrementable list::const_iterator"); | |
| 521 | 520 | #endif |
| 522 | 521 | __ptr_ = __ptr_->__prev_; |
| 523 | 522 | return *this; |
| ... | ... | @@ -895,7 +894,7 @@ public: |
| 895 | 894 | typename enable_if<__is_cpp17_input_iterator<_InpIter>::value>::type* = 0); |
| 896 | 895 | |
| 897 | 896 | list(const list& __c); |
| 898 | list(const list& __c, const allocator_type& __a); | |
| 897 | list(const list& __c, const __identity_t<allocator_type>& __a); | |
| 899 | 898 | _LIBCPP_INLINE_VISIBILITY |
| 900 | 899 | list& operator=(const list& __c); |
| 901 | 900 | #ifndef _LIBCPP_CXX03_LANG |
| ... | ... | @@ -906,7 +905,7 @@ public: |
| 906 | 905 | list(list&& __c) |
| 907 | 906 | _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value); |
| 908 | 907 | _LIBCPP_INLINE_VISIBILITY |
| 909 | list(list&& __c, const allocator_type& __a); | |
| 908 | list(list&& __c, const __identity_t<allocator_type>& __a); | |
| 910 | 909 | _LIBCPP_INLINE_VISIBILITY |
| 911 | 910 | list& operator=(list&& __c) |
| 912 | 911 | _NOEXCEPT_( |
| ... | ... | @@ -920,7 +919,7 @@ public: |
| 920 | 919 | _LIBCPP_INLINE_VISIBILITY |
| 921 | 920 | void assign(initializer_list<value_type> __il) |
| 922 | 921 | {assign(__il.begin(), __il.end());} |
| 923 | #endif // _LIBCPP_CXX03_LANG | |
| 922 | #endif // _LIBCPP_CXX03_LANG | |
| 924 | 923 | |
| 925 | 924 | template <class _InpIter> |
| 926 | 925 | void assign(_InpIter __f, _InpIter __l, |
| ... | ... | @@ -1023,7 +1022,7 @@ public: |
| 1023 | 1022 | _LIBCPP_INLINE_VISIBILITY |
| 1024 | 1023 | iterator insert(const_iterator __p, initializer_list<value_type> __il) |
| 1025 | 1024 | {return insert(__p, __il.begin(), __il.end());} |
| 1026 | #endif // _LIBCPP_CXX03_LANG | |
| 1025 | #endif // _LIBCPP_CXX03_LANG | |
| 1027 | 1026 | |
| 1028 | 1027 | void push_front(const value_type& __x); |
| 1029 | 1028 | void push_back(const value_type& __x); |
| ... | ... | @@ -1124,7 +1123,7 @@ public: |
| 1124 | 1123 | bool __addable(const const_iterator* __i, ptrdiff_t __n) const; |
| 1125 | 1124 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; |
| 1126 | 1125 | |
| 1127 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1126 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1128 | 1127 | |
| 1129 | 1128 | private: |
| 1130 | 1129 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1144,18 +1143,18 @@ private: |
| 1144 | 1143 | |
| 1145 | 1144 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 1146 | 1145 | template<class _InputIterator, |
| 1147 | class _Alloc = allocator<typename iterator_traits<_InputIterator>::value_type>, | |
| 1148 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 1146 | class _Alloc = allocator<__iter_value_type<_InputIterator>>, | |
| 1147 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 1149 | 1148 | > |
| 1150 | 1149 | list(_InputIterator, _InputIterator) |
| 1151 | -> list<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 1150 | -> list<__iter_value_type<_InputIterator>, _Alloc>; | |
| 1152 | 1151 | |
| 1153 | 1152 | template<class _InputIterator, |
| 1154 | 1153 | class _Alloc, |
| 1155 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 1154 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 1156 | 1155 | > |
| 1157 | 1156 | list(_InputIterator, _InputIterator, _Alloc) |
| 1158 | -> list<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 1157 | -> list<__iter_value_type<_InputIterator>, _Alloc>; | |
| 1159 | 1158 | #endif |
| 1160 | 1159 | |
| 1161 | 1160 | // Link in nodes [__f, __l] just prior to __p |
| ... | ... | @@ -1288,7 +1287,7 @@ list<_Tp, _Alloc>::list(const list& __c) |
| 1288 | 1287 | } |
| 1289 | 1288 | |
| 1290 | 1289 | template <class _Tp, class _Alloc> |
| 1291 | list<_Tp, _Alloc>::list(const list& __c, const allocator_type& __a) | |
| 1290 | list<_Tp, _Alloc>::list(const list& __c, const __identity_t<allocator_type>& __a) | |
| 1292 | 1291 | : base(__a) |
| 1293 | 1292 | { |
| 1294 | 1293 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| ... | ... | @@ -1335,7 +1334,7 @@ inline list<_Tp, _Alloc>::list(list&& __c) |
| 1335 | 1334 | |
| 1336 | 1335 | template <class _Tp, class _Alloc> |
| 1337 | 1336 | inline |
| 1338 | list<_Tp, _Alloc>::list(list&& __c, const allocator_type& __a) | |
| 1337 | list<_Tp, _Alloc>::list(list&& __c, const __identity_t<allocator_type>& __a) | |
| 1339 | 1338 | : base(__a) |
| 1340 | 1339 | { |
| 1341 | 1340 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| ... | ... | @@ -1386,7 +1385,7 @@ list<_Tp, _Alloc>::__move_assign(list& __c, true_type) |
| 1386 | 1385 | splice(end(), __c); |
| 1387 | 1386 | } |
| 1388 | 1387 | |
| 1389 | #endif // _LIBCPP_CXX03_LANG | |
| 1388 | #endif // _LIBCPP_CXX03_LANG | |
| 1390 | 1389 | |
| 1391 | 1390 | template <class _Tp, class _Alloc> |
| 1392 | 1391 | inline |
| ... | ... | @@ -1495,7 +1494,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _ |
| 1495 | 1494 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1496 | 1495 | try |
| 1497 | 1496 | { |
| 1498 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1497 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1499 | 1498 | for (--__n; __n != 0; --__n, ++__e, ++__ds) |
| 1500 | 1499 | { |
| 1501 | 1500 | __hold.reset(__node_alloc_traits::allocate(__na, 1)); |
| ... | ... | @@ -1523,7 +1522,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _ |
| 1523 | 1522 | } |
| 1524 | 1523 | throw; |
| 1525 | 1524 | } |
| 1526 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1525 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1527 | 1526 | __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); |
| 1528 | 1527 | base::__sz() += __ds; |
| 1529 | 1528 | } |
| ... | ... | @@ -1561,7 +1560,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, _InpIter __f, _InpIter __l, |
| 1561 | 1560 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1562 | 1561 | try |
| 1563 | 1562 | { |
| 1564 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1563 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1565 | 1564 | for (++__f; __f != __l; ++__f, (void) ++__e, (void) ++__ds) |
| 1566 | 1565 | { |
| 1567 | 1566 | __hold.reset(__node_alloc_traits::allocate(__na, 1)); |
| ... | ... | @@ -1589,7 +1588,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, _InpIter __f, _InpIter __l, |
| 1589 | 1588 | } |
| 1590 | 1589 | throw; |
| 1591 | 1590 | } |
| 1592 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1591 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1593 | 1592 | __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); |
| 1594 | 1593 | base::__sz() += __ds; |
| 1595 | 1594 | } |
| ... | ... | @@ -1737,7 +1736,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, value_type&& __x) |
| 1737 | 1736 | #endif |
| 1738 | 1737 | } |
| 1739 | 1738 | |
| 1740 | #endif // _LIBCPP_CXX03_LANG | |
| 1739 | #endif // _LIBCPP_CXX03_LANG | |
| 1741 | 1740 | |
| 1742 | 1741 | template <class _Tp, class _Alloc> |
| 1743 | 1742 | void |
| ... | ... | @@ -1772,7 +1771,7 @@ template <class _Tp, class _Alloc> |
| 1772 | 1771 | void |
| 1773 | 1772 | list<_Tp, _Alloc>::pop_back() |
| 1774 | 1773 | { |
| 1775 | _LIBCPP_ASSERT(!empty(), "list::pop_back() called with empty list"); | |
| 1774 | _LIBCPP_ASSERT(!empty(), "list::pop_back() called on an empty list"); | |
| 1776 | 1775 | __node_allocator& __na = base::__node_alloc(); |
| 1777 | 1776 | __link_pointer __n = base::__end_.__prev_; |
| 1778 | 1777 | base::__unlink_nodes(__n, __n); |
| ... | ... | @@ -1909,7 +1908,7 @@ list<_Tp, _Alloc>::resize(size_type __n) |
| 1909 | 1908 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1910 | 1909 | try |
| 1911 | 1910 | { |
| 1912 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1911 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1913 | 1912 | for (--__n; __n != 0; --__n, ++__e, ++__ds) |
| 1914 | 1913 | { |
| 1915 | 1914 | __hold.reset(__node_alloc_traits::allocate(__na, 1)); |
| ... | ... | @@ -1937,7 +1936,7 @@ list<_Tp, _Alloc>::resize(size_type __n) |
| 1937 | 1936 | } |
| 1938 | 1937 | throw; |
| 1939 | 1938 | } |
| 1940 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1939 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1941 | 1940 | __link_nodes_at_back(__r.__ptr_, __e.__ptr_); |
| 1942 | 1941 | base::__sz() += __ds; |
| 1943 | 1942 | } |
| ... | ... | @@ -1967,7 +1966,7 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) |
| 1967 | 1966 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1968 | 1967 | try |
| 1969 | 1968 | { |
| 1970 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1969 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1971 | 1970 | for (--__n; __n != 0; --__n, ++__e, ++__ds) |
| 1972 | 1971 | { |
| 1973 | 1972 | __hold.reset(__node_alloc_traits::allocate(__na, 1)); |
| ... | ... | @@ -1995,7 +1994,7 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) |
| 1995 | 1994 | } |
| 1996 | 1995 | throw; |
| 1997 | 1996 | } |
| 1998 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1997 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1999 | 1998 | __link_nodes(base::__end_as_link(), __r.__ptr_, __e.__ptr_); |
| 2000 | 1999 | base::__sz() += __ds; |
| 2001 | 2000 | } |
| ... | ... | @@ -2049,14 +2048,14 @@ list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __i) |
| 2049 | 2048 | { |
| 2050 | 2049 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 2051 | 2050 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, |
| 2052 | "list::splice(iterator, list, iterator) called with first iterator not" | |
| 2053 | " referring to this list"); | |
| 2051 | "list::splice(iterator, list, iterator) called with the first iterator" | |
| 2052 | " not referring to this list"); | |
| 2054 | 2053 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__i) == &__c, |
| 2055 | "list::splice(iterator, list, iterator) called with second iterator not" | |
| 2056 | " referring to list argument"); | |
| 2054 | "list::splice(iterator, list, iterator) called with the second iterator" | |
| 2055 | " not referring to the list argument"); | |
| 2057 | 2056 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(&__i), |
| 2058 | "list::splice(iterator, list, iterator) called with second iterator not" | |
| 2059 | " dereferenceable"); | |
| 2057 | "list::splice(iterator, list, iterator) called with the second iterator" | |
| 2058 | " not dereferenceable"); | |
| 2060 | 2059 | #endif |
| 2061 | 2060 | if (__p.__ptr_ != __i.__ptr_ && __p.__ptr_ != __i.__ptr_->__next_) |
| 2062 | 2061 | { |
| ... | ... | @@ -2098,7 +2097,10 @@ list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __f, con |
| 2098 | 2097 | " referring to this list"); |
| 2099 | 2098 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__f) == &__c, |
| 2100 | 2099 | "list::splice(iterator, list, iterator, iterator) called with second iterator not" |
| 2101 | " referring to list argument"); | |
| 2100 | " referring to the list argument"); | |
| 2101 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__l) == &__c, | |
| 2102 | "list::splice(iterator, list, iterator, iterator) called with third iterator not" | |
| 2103 | " referring to the list argument"); | |
| 2102 | 2104 | if (this == &__c) |
| 2103 | 2105 | { |
| 2104 | 2106 | for (const_iterator __i = __f; __i != __l; ++__i) |
| ... | ... | @@ -2412,7 +2414,7 @@ list<_Tp, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const |
| 2412 | 2414 | return false; |
| 2413 | 2415 | } |
| 2414 | 2416 | |
| 2415 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2417 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2416 | 2418 | |
| 2417 | 2419 | template <class _Tp, class _Alloc> |
| 2418 | 2420 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -2489,4 +2491,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 2489 | 2491 | |
| 2490 | 2492 | _LIBCPP_POP_MACROS |
| 2491 | 2493 | |
| 2492 | #endif // _LIBCPP_LIST | |
| 2494 | #endif // _LIBCPP_LIST |
lib/libcxx/include/locale+45-34| ... | ... | @@ -188,23 +188,28 @@ template <class charT> class messages_byname; |
| 188 | 188 | */ |
| 189 | 189 | |
| 190 | 190 | #include <__config> |
| 191 | #include <__locale> | |
| 192 | 191 | #include <__debug> |
| 192 | #include <__locale> | |
| 193 | 193 | #include <algorithm> |
| 194 | #include <memory> | |
| 195 | #include <ios> | |
| 196 | #include <streambuf> | |
| 197 | #include <iterator> | |
| 198 | #include <limits> | |
| 199 | #include <version> | |
| 200 | 194 | #ifndef __APPLE__ |
| 201 | #include <cstdarg> | |
| 195 | # include <cstdarg> | |
| 202 | 196 | #endif |
| 197 | #include <cstdio> | |
| 203 | 198 | #include <cstdlib> |
| 204 | 199 | #include <ctime> |
| 205 | #include <cstdio> | |
| 206 | #ifdef _LIBCPP_HAS_CATOPEN | |
| 207 | #include <nl_types.h> | |
| 200 | #include <ios> | |
| 201 | #include <iterator> | |
| 202 | #include <limits> | |
| 203 | #include <memory> | |
| 204 | #include <streambuf> | |
| 205 | #include <version> | |
| 206 | ||
| 207 | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) | |
| 208 | // Most unix variants have catopen. These are the specific ones that don't. | |
| 209 | # if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) | |
| 210 | # define _LIBCPP_HAS_CATOPEN 1 | |
| 211 | # include <nl_types.h> | |
| 212 | # endif | |
| 208 | 213 | #endif |
| 209 | 214 | |
| 210 | 215 | #ifdef _LIBCPP_LOCALE__L_EXTENSIONS |
| ... | ... | @@ -1453,10 +1458,12 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, |
| 1453 | 1458 | char __fmt[6] = {'%', 0}; |
| 1454 | 1459 | const char* __len = "l"; |
| 1455 | 1460 | this->__format_int(__fmt+1, __len, true, __iob.flags()); |
| 1456 | const unsigned __nbuf = (numeric_limits<long>::digits / 3) | |
| 1457 | + ((numeric_limits<long>::digits % 3) != 0) | |
| 1458 | + ((__iob.flags() & ios_base::showbase) != 0) | |
| 1459 | + 2; | |
| 1461 | // Worst case is octal, with showbase enabled. Note that octal is always | |
| 1462 | // printed as an unsigned value. | |
| 1463 | _LIBCPP_CONSTEXPR const unsigned __nbuf | |
| 1464 | = (numeric_limits<unsigned long>::digits / 3) // 1 char per 3 bits | |
| 1465 | + ((numeric_limits<unsigned long>::digits % 3) != 0) // round up | |
| 1466 | + 2; // base prefix + terminating null character | |
| 1460 | 1467 | char __nar[__nbuf]; |
| 1461 | 1468 | int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); |
| 1462 | 1469 | char* __ne = __nar + __nc; |
| ... | ... | @@ -1480,10 +1487,12 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, |
| 1480 | 1487 | char __fmt[8] = {'%', 0}; |
| 1481 | 1488 | const char* __len = "ll"; |
| 1482 | 1489 | this->__format_int(__fmt+1, __len, true, __iob.flags()); |
| 1483 | const unsigned __nbuf = (numeric_limits<long long>::digits / 3) | |
| 1484 | + ((numeric_limits<long long>::digits % 3) != 0) | |
| 1485 | + ((__iob.flags() & ios_base::showbase) != 0) | |
| 1486 | + 2; | |
| 1490 | // Worst case is octal, with showbase enabled. Note that octal is always | |
| 1491 | // printed as an unsigned value. | |
| 1492 | _LIBCPP_CONSTEXPR const unsigned __nbuf | |
| 1493 | = (numeric_limits<unsigned long long>::digits / 3) // 1 char per 3 bits | |
| 1494 | + ((numeric_limits<unsigned long long>::digits % 3) != 0) // round up | |
| 1495 | + 2; // base prefix + terminating null character | |
| 1487 | 1496 | char __nar[__nbuf]; |
| 1488 | 1497 | int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); |
| 1489 | 1498 | char* __ne = __nar + __nc; |
| ... | ... | @@ -1507,10 +1516,11 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, |
| 1507 | 1516 | char __fmt[6] = {'%', 0}; |
| 1508 | 1517 | const char* __len = "l"; |
| 1509 | 1518 | this->__format_int(__fmt+1, __len, false, __iob.flags()); |
| 1510 | const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3) | |
| 1511 | + ((numeric_limits<unsigned long>::digits % 3) != 0) | |
| 1512 | + ((__iob.flags() & ios_base::showbase) != 0) | |
| 1513 | + 1; | |
| 1519 | // Worst case is octal, with showbase enabled. | |
| 1520 | _LIBCPP_CONSTEXPR const unsigned __nbuf | |
| 1521 | = (numeric_limits<unsigned long>::digits / 3) // 1 char per 3 bits | |
| 1522 | + ((numeric_limits<unsigned long>::digits % 3) != 0) // round up | |
| 1523 | + 2; // base prefix + terminating null character | |
| 1514 | 1524 | char __nar[__nbuf]; |
| 1515 | 1525 | int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); |
| 1516 | 1526 | char* __ne = __nar + __nc; |
| ... | ... | @@ -1534,10 +1544,11 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, |
| 1534 | 1544 | char __fmt[8] = {'%', 0}; |
| 1535 | 1545 | const char* __len = "ll"; |
| 1536 | 1546 | this->__format_int(__fmt+1, __len, false, __iob.flags()); |
| 1537 | const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3) | |
| 1538 | + ((numeric_limits<unsigned long long>::digits % 3) != 0) | |
| 1539 | + ((__iob.flags() & ios_base::showbase) != 0) | |
| 1540 | + 1; | |
| 1547 | // Worst case is octal, with showbase enabled. | |
| 1548 | _LIBCPP_CONSTEXPR const unsigned __nbuf | |
| 1549 | = (numeric_limits<unsigned long long>::digits / 3) // 1 char per 3 bits | |
| 1550 | + ((numeric_limits<unsigned long long>::digits % 3) != 0) // round up | |
| 1551 | + 2; // base prefix + terminating null character | |
| 1541 | 1552 | char __nar[__nbuf]; |
| 1542 | 1553 | int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); |
| 1543 | 1554 | char* __ne = __nar + __nc; |
| ... | ... | @@ -3567,7 +3578,7 @@ messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const |
| 3567 | 3578 | __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1)); |
| 3568 | 3579 | return __cat; |
| 3569 | 3580 | #else // !_LIBCPP_HAS_CATOPEN |
| 3570 | _LIBCPP_UNUSED_VAR(__nm); | |
| 3581 | (void)__nm; | |
| 3571 | 3582 | return -1; |
| 3572 | 3583 | #endif // _LIBCPP_HAS_CATOPEN |
| 3573 | 3584 | } |
| ... | ... | @@ -3591,9 +3602,9 @@ messages<_CharT>::do_get(catalog __c, int __set, int __msgid, |
| 3591 | 3602 | __n, __n + _VSTD::strlen(__n)); |
| 3592 | 3603 | return __w; |
| 3593 | 3604 | #else // !_LIBCPP_HAS_CATOPEN |
| 3594 | _LIBCPP_UNUSED_VAR(__c); | |
| 3595 | _LIBCPP_UNUSED_VAR(__set); | |
| 3596 | _LIBCPP_UNUSED_VAR(__msgid); | |
| 3605 | (void)__c; | |
| 3606 | (void)__set; | |
| 3607 | (void)__msgid; | |
| 3597 | 3608 | return __dflt; |
| 3598 | 3609 | #endif // _LIBCPP_HAS_CATOPEN |
| 3599 | 3610 | } |
| ... | ... | @@ -3608,7 +3619,7 @@ messages<_CharT>::do_close(catalog __c) const |
| 3608 | 3619 | nl_catd __cat = (nl_catd)__c; |
| 3609 | 3620 | catclose(__cat); |
| 3610 | 3621 | #else // !_LIBCPP_HAS_CATOPEN |
| 3611 | _LIBCPP_UNUSED_VAR(__c); | |
| 3622 | (void)__c; | |
| 3612 | 3623 | #endif // _LIBCPP_HAS_CATOPEN |
| 3613 | 3624 | } |
| 3614 | 3625 | |
| ... | ... | @@ -3748,7 +3759,7 @@ wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: |
| 3748 | 3759 | __wc.__cvtptr_ = nullptr; |
| 3749 | 3760 | } |
| 3750 | 3761 | |
| 3751 | #endif // _LIBCPP_CXX03_LANG | |
| 3762 | #endif // _LIBCPP_CXX03_LANG | |
| 3752 | 3763 | |
| 3753 | 3764 | template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> |
| 3754 | 3765 | wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert() |
| ... | ... | @@ -4376,4 +4387,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 4376 | 4387 | |
| 4377 | 4388 | _LIBCPP_POP_MACROS |
| 4378 | 4389 | |
| 4379 | #endif // _LIBCPP_LOCALE | |
| 4390 | #endif // _LIBCPP_LOCALE |
lib/libcxx/include/locale.h+1-1| ... | ... | @@ -45,4 +45,4 @@ Functions: |
| 45 | 45 | |
| 46 | 46 | #include_next <locale.h> |
| 47 | 47 | |
| 48 | #endif // _LIBCPP_LOCALE_H | |
| 48 | #endif // _LIBCPP_LOCALE_H |
lib/libcxx/include/map+64-22| ... | ... | @@ -43,7 +43,6 @@ public: |
| 43 | 43 | typedef INSERT_RETURN_TYPE<iterator, node_type> insert_return_type; // C++17 |
| 44 | 44 | |
| 45 | 45 | class value_compare |
| 46 | : public binary_function<value_type, value_type, bool> | |
| 47 | 46 | { |
| 48 | 47 | friend class map; |
| 49 | 48 | protected: |
| ... | ... | @@ -51,6 +50,9 @@ public: |
| 51 | 50 | |
| 52 | 51 | value_compare(key_compare c); |
| 53 | 52 | public: |
| 53 | typedef bool result_type; // deprecated in C++17, removed in C++20 | |
| 54 | typedef value_type first_argument_type; // deprecated in C++17, removed in C++20 | |
| 55 | typedef value_type second_argument_type; // deprecated in C++17, removed in C++20 | |
| 54 | 56 | bool operator()(const value_type& x, const value_type& y) const; |
| 55 | 57 | }; |
| 56 | 58 | |
| ... | ... | @@ -191,10 +193,14 @@ public: |
| 191 | 193 | iterator find(const K& x); // C++14 |
| 192 | 194 | template<typename K> |
| 193 | 195 | const_iterator find(const K& x) const; // C++14 |
| 196 | ||
| 194 | 197 | template<typename K> |
| 195 | 198 | size_type count(const K& x) const; // C++14 |
| 196 | 199 | size_type count(const key_type& k) const; |
| 197 | bool contains(const key_type& x) const; // C++20 | |
| 200 | ||
| 201 | bool contains(const key_type& x) const; // C++20 | |
| 202 | template<class K> bool contains(const K& x) const; // C++20 | |
| 203 | ||
| 198 | 204 | iterator lower_bound(const key_type& k); |
| 199 | 205 | const_iterator lower_bound(const key_type& k) const; |
| 200 | 206 | template<typename K> |
| ... | ... | @@ -283,13 +289,15 @@ public: |
| 283 | 289 | typedef unspecified node_type; // C++17 |
| 284 | 290 | |
| 285 | 291 | class value_compare |
| 286 | : public binary_function<value_type,value_type,bool> | |
| 287 | 292 | { |
| 288 | 293 | friend class multimap; |
| 289 | 294 | protected: |
| 290 | 295 | key_compare comp; |
| 291 | 296 | value_compare(key_compare c); |
| 292 | 297 | public: |
| 298 | typedef bool result_type; // deprecated in C++17, removed in C++20 | |
| 299 | typedef value_type first_argument_type; // deprecated in C++17, removed in C++20 | |
| 300 | typedef value_type second_argument_type; // deprecated in C++17, removed in C++20 | |
| 293 | 301 | bool operator()(const value_type& x, const value_type& y) const; |
| 294 | 302 | }; |
| 295 | 303 | |
| ... | ... | @@ -406,10 +414,14 @@ public: |
| 406 | 414 | iterator find(const K& x); // C++14 |
| 407 | 415 | template<typename K> |
| 408 | 416 | const_iterator find(const K& x) const; // C++14 |
| 417 | ||
| 409 | 418 | template<typename K> |
| 410 | 419 | size_type count(const K& x) const; // C++14 |
| 411 | 420 | size_type count(const key_type& k) const; |
| 412 | bool contains(const key_type& x) const; // C++20 | |
| 421 | ||
| 422 | bool contains(const key_type& x) const; // C++20 | |
| 423 | template<class K> bool contains(const K& x) const; // C++20 | |
| 424 | ||
| 413 | 425 | iterator lower_bound(const key_type& k); |
| 414 | 426 | const_iterator lower_bound(const key_type& k) const; |
| 415 | 427 | template<typename K> |
| ... | ... | @@ -478,14 +490,18 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20 |
| 478 | 490 | */ |
| 479 | 491 | |
| 480 | 492 | #include <__config> |
| 481 | #include <__tree> | |
| 493 | #include <__debug> | |
| 494 | #include <__functional/is_transparent.h> | |
| 482 | 495 | #include <__node_handle> |
| 483 | #include <iterator> | |
| 484 | #include <memory> | |
| 485 | #include <utility> | |
| 496 | #include <__tree> | |
| 497 | #include <__utility/forward.h> | |
| 498 | #include <compare> | |
| 486 | 499 | #include <functional> |
| 487 | 500 | #include <initializer_list> |
| 501 | #include <iterator> // __libcpp_erase_if_container | |
| 502 | #include <memory> | |
| 488 | 503 | #include <type_traits> |
| 504 | #include <utility> | |
| 489 | 505 | #include <version> |
| 490 | 506 | |
| 491 | 507 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -633,7 +649,7 @@ public: |
| 633 | 649 | { |
| 634 | 650 | __x.__value_constructed = false; |
| 635 | 651 | } |
| 636 | #endif // _LIBCPP_CXX03_LANG | |
| 652 | #endif // _LIBCPP_CXX03_LANG | |
| 637 | 653 | |
| 638 | 654 | _LIBCPP_INLINE_VISIBILITY |
| 639 | 655 | void operator()(pointer __p) _NOEXCEPT |
| ... | ... | @@ -656,7 +672,7 @@ template <class _TreeIterator> class __map_const_iterator; |
| 656 | 672 | #ifndef _LIBCPP_CXX03_LANG |
| 657 | 673 | |
| 658 | 674 | template <class _Key, class _Tp> |
| 659 | struct __value_type | |
| 675 | struct _LIBCPP_STANDALONE_DEBUG __value_type | |
| 660 | 676 | { |
| 661 | 677 | typedef _Key key_type; |
| 662 | 678 | typedef _Tp mapped_type; |
| ... | ... | @@ -904,23 +920,32 @@ public: |
| 904 | 920 | typedef _Key key_type; |
| 905 | 921 | typedef _Tp mapped_type; |
| 906 | 922 | typedef pair<const key_type, mapped_type> value_type; |
| 907 | typedef typename __identity<_Compare>::type key_compare; | |
| 908 | typedef typename __identity<_Allocator>::type allocator_type; | |
| 923 | typedef __identity_t<_Compare> key_compare; | |
| 924 | typedef __identity_t<_Allocator> allocator_type; | |
| 909 | 925 | typedef value_type& reference; |
| 910 | 926 | typedef const value_type& const_reference; |
| 911 | 927 | |
| 912 | 928 | static_assert((is_same<typename allocator_type::value_type, value_type>::value), |
| 913 | 929 | "Allocator::value_type must be same type as value_type"); |
| 914 | 930 | |
| 931 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 915 | 932 | class _LIBCPP_TEMPLATE_VIS value_compare |
| 933 | #if defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 916 | 934 | : public binary_function<value_type, value_type, bool> |
| 935 | #endif | |
| 917 | 936 | { |
| 937 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 918 | 938 | friend class map; |
| 919 | 939 | protected: |
| 920 | 940 | key_compare comp; |
| 921 | 941 | |
| 922 | 942 | _LIBCPP_INLINE_VISIBILITY value_compare(key_compare c) : comp(c) {} |
| 923 | 943 | public: |
| 944 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 945 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 946 | _LIBCPP_DEPRECATED_IN_CXX17 typedef value_type first_argument_type; | |
| 947 | _LIBCPP_DEPRECATED_IN_CXX17 typedef value_type second_argument_type; | |
| 948 | #endif | |
| 924 | 949 | _LIBCPP_INLINE_VISIBILITY |
| 925 | 950 | bool operator()(const value_type& __x, const value_type& __y) const |
| 926 | 951 | {return comp(__x.first, __y.first);} |
| ... | ... | @@ -1071,7 +1096,7 @@ public: |
| 1071 | 1096 | return *this; |
| 1072 | 1097 | } |
| 1073 | 1098 | |
| 1074 | #endif // _LIBCPP_CXX03_LANG | |
| 1099 | #endif // _LIBCPP_CXX03_LANG | |
| 1075 | 1100 | |
| 1076 | 1101 | _LIBCPP_INLINE_VISIBILITY |
| 1077 | 1102 | explicit map(const allocator_type& __a) |
| ... | ... | @@ -1168,7 +1193,7 @@ public: |
| 1168 | 1193 | iterator insert(const_iterator __pos, _Pp&& __p) |
| 1169 | 1194 | {return __tree_.__insert_unique(__pos.__i_, _VSTD::forward<_Pp>(__p));} |
| 1170 | 1195 | |
| 1171 | #endif // _LIBCPP_CXX03_LANG | |
| 1196 | #endif // _LIBCPP_CXX03_LANG | |
| 1172 | 1197 | |
| 1173 | 1198 | _LIBCPP_INLINE_VISIBILITY |
| 1174 | 1199 | pair<iterator, bool> |
| ... | ... | @@ -1404,6 +1429,10 @@ public: |
| 1404 | 1429 | #if _LIBCPP_STD_VER > 17 |
| 1405 | 1430 | _LIBCPP_INLINE_VISIBILITY |
| 1406 | 1431 | bool contains(const key_type& __k) const {return find(__k) != end();} |
| 1432 | template <typename _K2> | |
| 1433 | _LIBCPP_INLINE_VISIBILITY | |
| 1434 | typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type | |
| 1435 | contains(const _K2& __k) const { return find(__k) != end(); } | |
| 1407 | 1436 | #endif // _LIBCPP_STD_VER > 17 |
| 1408 | 1437 | |
| 1409 | 1438 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1565,7 +1594,7 @@ map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) |
| 1565 | 1594 | return __r->__value_.__get_value().second; |
| 1566 | 1595 | } |
| 1567 | 1596 | |
| 1568 | #endif // _LIBCPP_CXX03_LANG | |
| 1597 | #endif // _LIBCPP_CXX03_LANG | |
| 1569 | 1598 | |
| 1570 | 1599 | template <class _Key, class _Tp, class _Compare, class _Allocator> |
| 1571 | 1600 | _Tp& |
| ... | ... | @@ -1660,7 +1689,7 @@ template <class _Key, class _Tp, class _Compare, class _Allocator, |
| 1660 | 1689 | inline _LIBCPP_INLINE_VISIBILITY |
| 1661 | 1690 | typename map<_Key, _Tp, _Compare, _Allocator>::size_type |
| 1662 | 1691 | erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) { |
| 1663 | return __libcpp_erase_if_container(__c, __pred); | |
| 1692 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 1664 | 1693 | } |
| 1665 | 1694 | #endif |
| 1666 | 1695 | |
| ... | ... | @@ -1674,17 +1703,21 @@ public: |
| 1674 | 1703 | typedef _Key key_type; |
| 1675 | 1704 | typedef _Tp mapped_type; |
| 1676 | 1705 | typedef pair<const key_type, mapped_type> value_type; |
| 1677 | typedef typename __identity<_Compare>::type key_compare; | |
| 1678 | typedef typename __identity<_Allocator>::type allocator_type; | |
| 1706 | typedef __identity_t<_Compare> key_compare; | |
| 1707 | typedef __identity_t<_Allocator> allocator_type; | |
| 1679 | 1708 | typedef value_type& reference; |
| 1680 | 1709 | typedef const value_type& const_reference; |
| 1681 | 1710 | |
| 1682 | 1711 | static_assert((is_same<typename allocator_type::value_type, value_type>::value), |
| 1683 | 1712 | "Allocator::value_type must be same type as value_type"); |
| 1684 | 1713 | |
| 1714 | _LIBCPP_SUPPRESS_DEPRECATED_PUSH | |
| 1685 | 1715 | class _LIBCPP_TEMPLATE_VIS value_compare |
| 1716 | #if defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 1686 | 1717 | : public binary_function<value_type, value_type, bool> |
| 1718 | #endif | |
| 1687 | 1719 | { |
| 1720 | _LIBCPP_SUPPRESS_DEPRECATED_POP | |
| 1688 | 1721 | friend class multimap; |
| 1689 | 1722 | protected: |
| 1690 | 1723 | key_compare comp; |
| ... | ... | @@ -1692,6 +1725,11 @@ public: |
| 1692 | 1725 | _LIBCPP_INLINE_VISIBILITY |
| 1693 | 1726 | value_compare(key_compare c) : comp(c) {} |
| 1694 | 1727 | public: |
| 1728 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 1729 | _LIBCPP_DEPRECATED_IN_CXX17 typedef bool result_type; | |
| 1730 | _LIBCPP_DEPRECATED_IN_CXX17 typedef value_type first_argument_type; | |
| 1731 | _LIBCPP_DEPRECATED_IN_CXX17 typedef value_type second_argument_type; | |
| 1732 | #endif | |
| 1695 | 1733 | _LIBCPP_INLINE_VISIBILITY |
| 1696 | 1734 | bool operator()(const value_type& __x, const value_type& __y) const |
| 1697 | 1735 | {return comp(__x.first, __y.first);} |
| ... | ... | @@ -1842,7 +1880,7 @@ public: |
| 1842 | 1880 | return *this; |
| 1843 | 1881 | } |
| 1844 | 1882 | |
| 1845 | #endif // _LIBCPP_CXX03_LANG | |
| 1883 | #endif // _LIBCPP_CXX03_LANG | |
| 1846 | 1884 | |
| 1847 | 1885 | _LIBCPP_INLINE_VISIBILITY |
| 1848 | 1886 | explicit multimap(const allocator_type& __a) |
| ... | ... | @@ -1945,7 +1983,7 @@ public: |
| 1945 | 1983 | void insert(initializer_list<value_type> __il) |
| 1946 | 1984 | {insert(__il.begin(), __il.end());} |
| 1947 | 1985 | |
| 1948 | #endif // _LIBCPP_CXX03_LANG | |
| 1986 | #endif // _LIBCPP_CXX03_LANG | |
| 1949 | 1987 | |
| 1950 | 1988 | _LIBCPP_INLINE_VISIBILITY |
| 1951 | 1989 | iterator insert(const value_type& __v) {return __tree_.__insert_multi(__v);} |
| ... | ... | @@ -2070,6 +2108,10 @@ public: |
| 2070 | 2108 | #if _LIBCPP_STD_VER > 17 |
| 2071 | 2109 | _LIBCPP_INLINE_VISIBILITY |
| 2072 | 2110 | bool contains(const key_type& __k) const {return find(__k) != end();} |
| 2111 | template <typename _K2> | |
| 2112 | _LIBCPP_INLINE_VISIBILITY | |
| 2113 | typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type | |
| 2114 | contains(const _K2& __k) const { return find(__k) != end(); } | |
| 2073 | 2115 | #endif // _LIBCPP_STD_VER > 17 |
| 2074 | 2116 | |
| 2075 | 2117 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -2246,10 +2288,10 @@ inline _LIBCPP_INLINE_VISIBILITY |
| 2246 | 2288 | typename multimap<_Key, _Tp, _Compare, _Allocator>::size_type |
| 2247 | 2289 | erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, |
| 2248 | 2290 | _Predicate __pred) { |
| 2249 | return __libcpp_erase_if_container(__c, __pred); | |
| 2291 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 2250 | 2292 | } |
| 2251 | 2293 | #endif |
| 2252 | 2294 | |
| 2253 | 2295 | _LIBCPP_END_NAMESPACE_STD |
| 2254 | 2296 | |
| 2255 | #endif // _LIBCPP_MAP | |
| 2297 | #endif // _LIBCPP_MAP |
lib/libcxx/include/math.h+278-42| ... | ... | @@ -318,7 +318,11 @@ _LIBCPP_INLINE_VISIBILITY |
| 318 | 318 | bool |
| 319 | 319 | __libcpp_signbit(_A1 __lcpp_x) _NOEXCEPT |
| 320 | 320 | { |
| 321 | #if __has_builtin(__builtin_signbit) | |
| 322 | return __builtin_signbit(__lcpp_x); | |
| 323 | #else | |
| 321 | 324 | return signbit(__lcpp_x); |
| 325 | #endif | |
| 322 | 326 | } |
| 323 | 327 | |
| 324 | 328 | #undef signbit |
| ... | ... | @@ -369,7 +373,7 @@ typename std::enable_if< |
| 369 | 373 | signbit(_A1) _NOEXCEPT |
| 370 | 374 | { return false; } |
| 371 | 375 | |
| 372 | #endif // signbit | |
| 376 | #endif // signbit | |
| 373 | 377 | |
| 374 | 378 | // fpclassify |
| 375 | 379 | |
| ... | ... | @@ -380,7 +384,12 @@ _LIBCPP_INLINE_VISIBILITY |
| 380 | 384 | int |
| 381 | 385 | __libcpp_fpclassify(_A1 __lcpp_x) _NOEXCEPT |
| 382 | 386 | { |
| 387 | #if __has_builtin(__builtin_fpclassify) | |
| 388 | return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, | |
| 389 | FP_ZERO, __lcpp_x); | |
| 390 | #else | |
| 383 | 391 | return fpclassify(__lcpp_x); |
| 392 | #endif | |
| 384 | 393 | } |
| 385 | 394 | |
| 386 | 395 | #undef fpclassify |
| ... | ... | @@ -415,7 +424,7 @@ typename std::enable_if<std::is_integral<_A1>::value, int>::type |
| 415 | 424 | fpclassify(_A1 __lcpp_x) _NOEXCEPT |
| 416 | 425 | { return __lcpp_x == 0 ? FP_ZERO : FP_NORMAL; } |
| 417 | 426 | |
| 418 | #endif // fpclassify | |
| 427 | #endif // fpclassify | |
| 419 | 428 | |
| 420 | 429 | // isfinite |
| 421 | 430 | |
| ... | ... | @@ -426,7 +435,11 @@ _LIBCPP_INLINE_VISIBILITY |
| 426 | 435 | bool |
| 427 | 436 | __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT |
| 428 | 437 | { |
| 438 | #if __has_builtin(__builtin_isfinite) | |
| 439 | return __builtin_isfinite(__lcpp_x); | |
| 440 | #else | |
| 429 | 441 | return isfinite(__lcpp_x); |
| 442 | #endif | |
| 430 | 443 | } |
| 431 | 444 | |
| 432 | 445 | #undef isfinite |
| ... | ... | @@ -449,7 +462,7 @@ typename std::enable_if< |
| 449 | 462 | isfinite(_A1) _NOEXCEPT |
| 450 | 463 | { return true; } |
| 451 | 464 | |
| 452 | #endif // isfinite | |
| 465 | #endif // isfinite | |
| 453 | 466 | |
| 454 | 467 | // isinf |
| 455 | 468 | |
| ... | ... | @@ -460,7 +473,11 @@ _LIBCPP_INLINE_VISIBILITY |
| 460 | 473 | bool |
| 461 | 474 | __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT |
| 462 | 475 | { |
| 476 | #if __has_builtin(__builtin_isinf) | |
| 477 | return __builtin_isinf(__lcpp_x); | |
| 478 | #else | |
| 463 | 479 | return isinf(__lcpp_x); |
| 480 | #endif | |
| 464 | 481 | } |
| 465 | 482 | |
| 466 | 483 | #undef isinf |
| ... | ... | @@ -497,7 +514,7 @@ bool |
| 497 | 514 | isinf(long double __lcpp_x) _NOEXCEPT { return __libcpp_isinf(__lcpp_x); } |
| 498 | 515 | #endif |
| 499 | 516 | |
| 500 | #endif // isinf | |
| 517 | #endif // isinf | |
| 501 | 518 | |
| 502 | 519 | // isnan |
| 503 | 520 | |
| ... | ... | @@ -545,7 +562,7 @@ bool |
| 545 | 562 | isnan(long double __lcpp_x) _NOEXCEPT { return __libcpp_isnan(__lcpp_x); } |
| 546 | 563 | #endif |
| 547 | 564 | |
| 548 | #endif // isnan | |
| 565 | #endif // isnan | |
| 549 | 566 | |
| 550 | 567 | // isnormal |
| 551 | 568 | |
| ... | ... | @@ -556,7 +573,11 @@ _LIBCPP_INLINE_VISIBILITY |
| 556 | 573 | bool |
| 557 | 574 | __libcpp_isnormal(_A1 __lcpp_x) _NOEXCEPT |
| 558 | 575 | { |
| 576 | #if __has_builtin(__builtin_isnormal) | |
| 577 | return __builtin_isnormal(__lcpp_x); | |
| 578 | #else | |
| 559 | 579 | return isnormal(__lcpp_x); |
| 580 | #endif | |
| 560 | 581 | } |
| 561 | 582 | |
| 562 | 583 | #undef isnormal |
| ... | ... | @@ -575,7 +596,7 @@ typename std::enable_if<std::is_integral<_A1>::value, bool>::type |
| 575 | 596 | isnormal(_A1 __lcpp_x) _NOEXCEPT |
| 576 | 597 | { return __lcpp_x != 0; } |
| 577 | 598 | |
| 578 | #endif // isnormal | |
| 599 | #endif // isnormal | |
| 579 | 600 | |
| 580 | 601 | // isgreater |
| 581 | 602 | |
| ... | ... | @@ -605,7 +626,7 @@ isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT |
| 605 | 626 | return __libcpp_isgreater((type)__lcpp_x, (type)__lcpp_y); |
| 606 | 627 | } |
| 607 | 628 | |
| 608 | #endif // isgreater | |
| 629 | #endif // isgreater | |
| 609 | 630 | |
| 610 | 631 | // isgreaterequal |
| 611 | 632 | |
| ... | ... | @@ -635,7 +656,7 @@ isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT |
| 635 | 656 | return __libcpp_isgreaterequal((type)__lcpp_x, (type)__lcpp_y); |
| 636 | 657 | } |
| 637 | 658 | |
| 638 | #endif // isgreaterequal | |
| 659 | #endif // isgreaterequal | |
| 639 | 660 | |
| 640 | 661 | // isless |
| 641 | 662 | |
| ... | ... | @@ -665,7 +686,7 @@ isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT |
| 665 | 686 | return __libcpp_isless((type)__lcpp_x, (type)__lcpp_y); |
| 666 | 687 | } |
| 667 | 688 | |
| 668 | #endif // isless | |
| 689 | #endif // isless | |
| 669 | 690 | |
| 670 | 691 | // islessequal |
| 671 | 692 | |
| ... | ... | @@ -695,7 +716,7 @@ islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT |
| 695 | 716 | return __libcpp_islessequal((type)__lcpp_x, (type)__lcpp_y); |
| 696 | 717 | } |
| 697 | 718 | |
| 698 | #endif // islessequal | |
| 719 | #endif // islessequal | |
| 699 | 720 | |
| 700 | 721 | // islessgreater |
| 701 | 722 | |
| ... | ... | @@ -725,7 +746,7 @@ islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT |
| 725 | 746 | return __libcpp_islessgreater((type)__lcpp_x, (type)__lcpp_y); |
| 726 | 747 | } |
| 727 | 748 | |
| 728 | #endif // islessgreater | |
| 749 | #endif // islessgreater | |
| 729 | 750 | |
| 730 | 751 | // isunordered |
| 731 | 752 | |
| ... | ... | @@ -755,7 +776,7 @@ isunordered(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT |
| 755 | 776 | return __libcpp_isunordered((type)__lcpp_x, (type)__lcpp_y); |
| 756 | 777 | } |
| 757 | 778 | |
| 758 | #endif // isunordered | |
| 779 | #endif // isunordered | |
| 759 | 780 | |
| 760 | 781 | // abs |
| 761 | 782 | // |
| ... | ... | @@ -1099,16 +1120,43 @@ cbrt(_A1 __lcpp_x) _NOEXCEPT {return ::cbrt((double)__lcpp_x);} |
| 1099 | 1120 | |
| 1100 | 1121 | // copysign |
| 1101 | 1122 | |
| 1102 | inline _LIBCPP_INLINE_VISIBILITY float copysign(float __lcpp_x, | |
| 1103 | float __lcpp_y) _NOEXCEPT { | |
| 1123 | #if __has_builtin(__builtin_copysignf) | |
| 1124 | _LIBCPP_CONSTEXPR | |
| 1125 | #endif | |
| 1126 | inline _LIBCPP_INLINE_VISIBILITY float __libcpp_copysign(float __lcpp_x, float __lcpp_y) _NOEXCEPT { | |
| 1127 | #if __has_builtin(__builtin_copysignf) | |
| 1128 | return __builtin_copysignf(__lcpp_x, __lcpp_y); | |
| 1129 | #else | |
| 1104 | 1130 | return ::copysignf(__lcpp_x, __lcpp_y); |
| 1131 | #endif | |
| 1132 | } | |
| 1133 | ||
| 1134 | #if __has_builtin(__builtin_copysign) | |
| 1135 | _LIBCPP_CONSTEXPR | |
| 1136 | #endif | |
| 1137 | inline _LIBCPP_INLINE_VISIBILITY double __libcpp_copysign(double __lcpp_x, double __lcpp_y) _NOEXCEPT { | |
| 1138 | #if __has_builtin(__builtin_copysign) | |
| 1139 | return __builtin_copysign(__lcpp_x, __lcpp_y); | |
| 1140 | #else | |
| 1141 | return ::copysign(__lcpp_x, __lcpp_y); | |
| 1142 | #endif | |
| 1105 | 1143 | } |
| 1106 | inline _LIBCPP_INLINE_VISIBILITY long double | |
| 1107 | copysign(long double __lcpp_x, long double __lcpp_y) _NOEXCEPT { | |
| 1144 | ||
| 1145 | #if __has_builtin(__builtin_copysignl) | |
| 1146 | _LIBCPP_CONSTEXPR | |
| 1147 | #endif | |
| 1148 | inline _LIBCPP_INLINE_VISIBILITY long double __libcpp_copysign(long double __lcpp_x, long double __lcpp_y) _NOEXCEPT { | |
| 1149 | #if __has_builtin(__builtin_copysignl) | |
| 1150 | return __builtin_copysignl(__lcpp_x, __lcpp_y); | |
| 1151 | #else | |
| 1108 | 1152 | return ::copysignl(__lcpp_x, __lcpp_y); |
| 1153 | #endif | |
| 1109 | 1154 | } |
| 1110 | 1155 | |
| 1111 | 1156 | template <class _A1, class _A2> |
| 1157 | #if __has_builtin(__builtin_copysign) | |
| 1158 | _LIBCPP_CONSTEXPR | |
| 1159 | #endif | |
| 1112 | 1160 | inline _LIBCPP_INLINE_VISIBILITY |
| 1113 | 1161 | typename std::_EnableIf |
| 1114 | 1162 | < |
| ... | ... | @@ -1116,12 +1164,35 @@ typename std::_EnableIf |
| 1116 | 1164 | std::is_arithmetic<_A2>::value, |
| 1117 | 1165 | std::__promote<_A1, _A2> |
| 1118 | 1166 | >::type |
| 1119 | copysign(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT | |
| 1120 | { | |
| 1167 | __libcpp_copysign(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { | |
| 1121 | 1168 | typedef typename std::__promote<_A1, _A2>::type __result_type; |
| 1122 | 1169 | static_assert((!(std::_IsSame<_A1, __result_type>::value && |
| 1123 | 1170 | std::_IsSame<_A2, __result_type>::value)), ""); |
| 1171 | #if __has_builtin(__builtin_copysign) | |
| 1172 | return __builtin_copysign((__result_type)__lcpp_x, (__result_type)__lcpp_y); | |
| 1173 | #else | |
| 1124 | 1174 | return ::copysign((__result_type)__lcpp_x, (__result_type)__lcpp_y); |
| 1175 | #endif | |
| 1176 | } | |
| 1177 | ||
| 1178 | inline _LIBCPP_INLINE_VISIBILITY float copysign(float __lcpp_x, float __lcpp_y) _NOEXCEPT { | |
| 1179 | return ::__libcpp_copysign(__lcpp_x, __lcpp_y); | |
| 1180 | } | |
| 1181 | ||
| 1182 | inline _LIBCPP_INLINE_VISIBILITY long double copysign(long double __lcpp_x, long double __lcpp_y) _NOEXCEPT { | |
| 1183 | return ::__libcpp_copysign(__lcpp_x, __lcpp_y); | |
| 1184 | } | |
| 1185 | ||
| 1186 | template <class _A1, class _A2> | |
| 1187 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1188 | typename std::_EnableIf | |
| 1189 | < | |
| 1190 | std::is_arithmetic<_A1>::value && | |
| 1191 | std::is_arithmetic<_A2>::value, | |
| 1192 | std::__promote<_A1, _A2> | |
| 1193 | >::type | |
| 1194 | copysign(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { | |
| 1195 | return ::__libcpp_copysign(__lcpp_x, __lcpp_y); | |
| 1125 | 1196 | } |
| 1126 | 1197 | |
| 1127 | 1198 | // erf |
| ... | ... | @@ -1187,8 +1258,22 @@ fdim(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT |
| 1187 | 1258 | |
| 1188 | 1259 | // fma |
| 1189 | 1260 | |
| 1190 | inline _LIBCPP_INLINE_VISIBILITY float fma(float __lcpp_x, float __lcpp_y, float __lcpp_z) _NOEXCEPT {return ::fmaf(__lcpp_x, __lcpp_y, __lcpp_z);} | |
| 1191 | inline _LIBCPP_INLINE_VISIBILITY long double fma(long double __lcpp_x, long double __lcpp_y, long double __lcpp_z) _NOEXCEPT {return ::fmal(__lcpp_x, __lcpp_y, __lcpp_z);} | |
| 1261 | inline _LIBCPP_INLINE_VISIBILITY float fma(float __lcpp_x, float __lcpp_y, float __lcpp_z) _NOEXCEPT | |
| 1262 | { | |
| 1263 | #if __has_builtin(__builtin_fmaf) | |
| 1264 | return __builtin_fmaf(__lcpp_x, __lcpp_y, __lcpp_z); | |
| 1265 | #else | |
| 1266 | return ::fmaf(__lcpp_x, __lcpp_y, __lcpp_z); | |
| 1267 | #endif | |
| 1268 | } | |
| 1269 | inline _LIBCPP_INLINE_VISIBILITY long double fma(long double __lcpp_x, long double __lcpp_y, long double __lcpp_z) _NOEXCEPT | |
| 1270 | { | |
| 1271 | #if __has_builtin(__builtin_fmal) | |
| 1272 | return __builtin_fmal(__lcpp_x, __lcpp_y, __lcpp_z); | |
| 1273 | #else | |
| 1274 | return ::fmal(__lcpp_x, __lcpp_y, __lcpp_z); | |
| 1275 | #endif | |
| 1276 | } | |
| 1192 | 1277 | |
| 1193 | 1278 | template <class _A1, class _A2, class _A3> |
| 1194 | 1279 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1205,7 +1290,11 @@ fma(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT |
| 1205 | 1290 | static_assert((!(std::_IsSame<_A1, __result_type>::value && |
| 1206 | 1291 | std::_IsSame<_A2, __result_type>::value && |
| 1207 | 1292 | std::_IsSame<_A3, __result_type>::value)), ""); |
| 1293 | #if __has_builtin(__builtin_fma) | |
| 1294 | return __builtin_fma((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z); | |
| 1295 | #else | |
| 1208 | 1296 | return ::fma((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z); |
| 1297 | #endif | |
| 1209 | 1298 | } |
| 1210 | 1299 | |
| 1211 | 1300 | // fmax |
| ... | ... | @@ -1293,23 +1382,65 @@ lgamma(_A1 __lcpp_x) _NOEXCEPT {return ::lgamma((double)__lcpp_x);} |
| 1293 | 1382 | |
| 1294 | 1383 | // llrint |
| 1295 | 1384 | |
| 1296 | inline _LIBCPP_INLINE_VISIBILITY long long llrint(float __lcpp_x) _NOEXCEPT {return ::llrintf(__lcpp_x);} | |
| 1297 | inline _LIBCPP_INLINE_VISIBILITY long long llrint(long double __lcpp_x) _NOEXCEPT {return ::llrintl(__lcpp_x);} | |
| 1385 | inline _LIBCPP_INLINE_VISIBILITY long long llrint(float __lcpp_x) _NOEXCEPT | |
| 1386 | { | |
| 1387 | #if __has_builtin(__builtin_llrintf) | |
| 1388 | return __builtin_llrintf(__lcpp_x); | |
| 1389 | #else | |
| 1390 | return ::llrintf(__lcpp_x); | |
| 1391 | #endif | |
| 1392 | } | |
| 1393 | inline _LIBCPP_INLINE_VISIBILITY long long llrint(long double __lcpp_x) _NOEXCEPT | |
| 1394 | { | |
| 1395 | #if __has_builtin(__builtin_llrintl) | |
| 1396 | return __builtin_llrintl(__lcpp_x); | |
| 1397 | #else | |
| 1398 | return ::llrintl(__lcpp_x); | |
| 1399 | #endif | |
| 1400 | } | |
| 1298 | 1401 | |
| 1299 | 1402 | template <class _A1> |
| 1300 | 1403 | inline _LIBCPP_INLINE_VISIBILITY |
| 1301 | 1404 | typename std::enable_if<std::is_integral<_A1>::value, long long>::type |
| 1302 | llrint(_A1 __lcpp_x) _NOEXCEPT {return ::llrint((double)__lcpp_x);} | |
| 1405 | llrint(_A1 __lcpp_x) _NOEXCEPT | |
| 1406 | { | |
| 1407 | #if __has_builtin(__builtin_llrint) | |
| 1408 | return __builtin_llrint((double)__lcpp_x); | |
| 1409 | #else | |
| 1410 | return ::llrint((double)__lcpp_x); | |
| 1411 | #endif | |
| 1412 | } | |
| 1303 | 1413 | |
| 1304 | 1414 | // llround |
| 1305 | 1415 | |
| 1306 | inline _LIBCPP_INLINE_VISIBILITY long long llround(float __lcpp_x) _NOEXCEPT {return ::llroundf(__lcpp_x);} | |
| 1307 | inline _LIBCPP_INLINE_VISIBILITY long long llround(long double __lcpp_x) _NOEXCEPT {return ::llroundl(__lcpp_x);} | |
| 1416 | inline _LIBCPP_INLINE_VISIBILITY long long llround(float __lcpp_x) _NOEXCEPT | |
| 1417 | { | |
| 1418 | #if __has_builtin(__builtin_llroundf) | |
| 1419 | return __builtin_llroundf(__lcpp_x); | |
| 1420 | #else | |
| 1421 | return ::llroundf(__lcpp_x); | |
| 1422 | #endif | |
| 1423 | } | |
| 1424 | inline _LIBCPP_INLINE_VISIBILITY long long llround(long double __lcpp_x) _NOEXCEPT | |
| 1425 | { | |
| 1426 | #if __has_builtin(__builtin_llroundl) | |
| 1427 | return __builtin_llroundl(__lcpp_x); | |
| 1428 | #else | |
| 1429 | return ::llroundl(__lcpp_x); | |
| 1430 | #endif | |
| 1431 | } | |
| 1308 | 1432 | |
| 1309 | 1433 | template <class _A1> |
| 1310 | 1434 | inline _LIBCPP_INLINE_VISIBILITY |
| 1311 | 1435 | typename std::enable_if<std::is_integral<_A1>::value, long long>::type |
| 1312 | llround(_A1 __lcpp_x) _NOEXCEPT {return ::llround((double)__lcpp_x);} | |
| 1436 | llround(_A1 __lcpp_x) _NOEXCEPT | |
| 1437 | { | |
| 1438 | #if __has_builtin(__builtin_llround) | |
| 1439 | return __builtin_llround((double)__lcpp_x); | |
| 1440 | #else | |
| 1441 | return ::llround((double)__lcpp_x); | |
| 1442 | #endif | |
| 1443 | } | |
| 1313 | 1444 | |
| 1314 | 1445 | // log1p |
| 1315 | 1446 | |
| ... | ... | @@ -1343,23 +1474,65 @@ logb(_A1 __lcpp_x) _NOEXCEPT {return ::logb((double)__lcpp_x);} |
| 1343 | 1474 | |
| 1344 | 1475 | // lrint |
| 1345 | 1476 | |
| 1346 | inline _LIBCPP_INLINE_VISIBILITY long lrint(float __lcpp_x) _NOEXCEPT {return ::lrintf(__lcpp_x);} | |
| 1347 | inline _LIBCPP_INLINE_VISIBILITY long lrint(long double __lcpp_x) _NOEXCEPT {return ::lrintl(__lcpp_x);} | |
| 1477 | inline _LIBCPP_INLINE_VISIBILITY long lrint(float __lcpp_x) _NOEXCEPT | |
| 1478 | { | |
| 1479 | #if __has_builtin(__builtin_lrintf) | |
| 1480 | return __builtin_lrintf(__lcpp_x); | |
| 1481 | #else | |
| 1482 | return ::lrintf(__lcpp_x); | |
| 1483 | #endif | |
| 1484 | } | |
| 1485 | inline _LIBCPP_INLINE_VISIBILITY long lrint(long double __lcpp_x) _NOEXCEPT | |
| 1486 | { | |
| 1487 | #if __has_builtin(__builtin_lrintl) | |
| 1488 | return __builtin_lrintl(__lcpp_x); | |
| 1489 | #else | |
| 1490 | return ::lrintl(__lcpp_x); | |
| 1491 | #endif | |
| 1492 | } | |
| 1348 | 1493 | |
| 1349 | 1494 | template <class _A1> |
| 1350 | 1495 | inline _LIBCPP_INLINE_VISIBILITY |
| 1351 | 1496 | typename std::enable_if<std::is_integral<_A1>::value, long>::type |
| 1352 | lrint(_A1 __lcpp_x) _NOEXCEPT {return ::lrint((double)__lcpp_x);} | |
| 1497 | lrint(_A1 __lcpp_x) _NOEXCEPT | |
| 1498 | { | |
| 1499 | #if __has_builtin(__builtin_lrint) | |
| 1500 | return __builtin_lrint((double)__lcpp_x); | |
| 1501 | #else | |
| 1502 | return ::lrint((double)__lcpp_x); | |
| 1503 | #endif | |
| 1504 | } | |
| 1353 | 1505 | |
| 1354 | 1506 | // lround |
| 1355 | 1507 | |
| 1356 | inline _LIBCPP_INLINE_VISIBILITY long lround(float __lcpp_x) _NOEXCEPT {return ::lroundf(__lcpp_x);} | |
| 1357 | inline _LIBCPP_INLINE_VISIBILITY long lround(long double __lcpp_x) _NOEXCEPT {return ::lroundl(__lcpp_x);} | |
| 1508 | inline _LIBCPP_INLINE_VISIBILITY long lround(float __lcpp_x) _NOEXCEPT | |
| 1509 | { | |
| 1510 | #if __has_builtin(__builtin_lroundf) | |
| 1511 | return __builtin_lroundf(__lcpp_x); | |
| 1512 | #else | |
| 1513 | return ::lroundf(__lcpp_x); | |
| 1514 | #endif | |
| 1515 | } | |
| 1516 | inline _LIBCPP_INLINE_VISIBILITY long lround(long double __lcpp_x) _NOEXCEPT | |
| 1517 | { | |
| 1518 | #if __has_builtin(__builtin_lroundl) | |
| 1519 | return __builtin_lroundl(__lcpp_x); | |
| 1520 | #else | |
| 1521 | return ::lroundl(__lcpp_x); | |
| 1522 | #endif | |
| 1523 | } | |
| 1358 | 1524 | |
| 1359 | 1525 | template <class _A1> |
| 1360 | 1526 | inline _LIBCPP_INLINE_VISIBILITY |
| 1361 | 1527 | typename std::enable_if<std::is_integral<_A1>::value, long>::type |
| 1362 | lround(_A1 __lcpp_x) _NOEXCEPT {return ::lround((double)__lcpp_x);} | |
| 1528 | lround(_A1 __lcpp_x) _NOEXCEPT | |
| 1529 | { | |
| 1530 | #if __has_builtin(__builtin_lround) | |
| 1531 | return __builtin_lround((double)__lcpp_x); | |
| 1532 | #else | |
| 1533 | return ::lround((double)__lcpp_x); | |
| 1534 | #endif | |
| 1535 | } | |
| 1363 | 1536 | |
| 1364 | 1537 | // nan |
| 1365 | 1538 | |
| ... | ... | @@ -1448,23 +1621,65 @@ remquo(_A1 __lcpp_x, _A2 __lcpp_y, int* __lcpp_z) _NOEXCEPT |
| 1448 | 1621 | |
| 1449 | 1622 | // rint |
| 1450 | 1623 | |
| 1451 | inline _LIBCPP_INLINE_VISIBILITY float rint(float __lcpp_x) _NOEXCEPT {return ::rintf(__lcpp_x);} | |
| 1452 | inline _LIBCPP_INLINE_VISIBILITY long double rint(long double __lcpp_x) _NOEXCEPT {return ::rintl(__lcpp_x);} | |
| 1624 | inline _LIBCPP_INLINE_VISIBILITY float rint(float __lcpp_x) _NOEXCEPT | |
| 1625 | { | |
| 1626 | #if __has_builtin(__builtin_rintf) | |
| 1627 | return __builtin_rintf(__lcpp_x); | |
| 1628 | #else | |
| 1629 | return ::rintf(__lcpp_x); | |
| 1630 | #endif | |
| 1631 | } | |
| 1632 | inline _LIBCPP_INLINE_VISIBILITY long double rint(long double __lcpp_x) _NOEXCEPT | |
| 1633 | { | |
| 1634 | #if __has_builtin(__builtin_rintl) | |
| 1635 | return __builtin_rintl(__lcpp_x); | |
| 1636 | #else | |
| 1637 | return ::rintl(__lcpp_x); | |
| 1638 | #endif | |
| 1639 | } | |
| 1453 | 1640 | |
| 1454 | 1641 | template <class _A1> |
| 1455 | 1642 | inline _LIBCPP_INLINE_VISIBILITY |
| 1456 | 1643 | typename std::enable_if<std::is_integral<_A1>::value, double>::type |
| 1457 | rint(_A1 __lcpp_x) _NOEXCEPT {return ::rint((double)__lcpp_x);} | |
| 1644 | rint(_A1 __lcpp_x) _NOEXCEPT | |
| 1645 | { | |
| 1646 | #if __has_builtin(__builtin_rint) | |
| 1647 | return __builtin_rint((double)__lcpp_x); | |
| 1648 | #else | |
| 1649 | return ::rint((double)__lcpp_x); | |
| 1650 | #endif | |
| 1651 | } | |
| 1458 | 1652 | |
| 1459 | 1653 | // round |
| 1460 | 1654 | |
| 1461 | inline _LIBCPP_INLINE_VISIBILITY float round(float __lcpp_x) _NOEXCEPT {return ::roundf(__lcpp_x);} | |
| 1462 | inline _LIBCPP_INLINE_VISIBILITY long double round(long double __lcpp_x) _NOEXCEPT {return ::roundl(__lcpp_x);} | |
| 1655 | inline _LIBCPP_INLINE_VISIBILITY float round(float __lcpp_x) _NOEXCEPT | |
| 1656 | { | |
| 1657 | #if __has_builtin(__builtin_round) | |
| 1658 | return __builtin_round(__lcpp_x); | |
| 1659 | #else | |
| 1660 | return ::round(__lcpp_x); | |
| 1661 | #endif | |
| 1662 | } | |
| 1663 | inline _LIBCPP_INLINE_VISIBILITY long double round(long double __lcpp_x) _NOEXCEPT | |
| 1664 | { | |
| 1665 | #if __has_builtin(__builtin_roundl) | |
| 1666 | return __builtin_roundl(__lcpp_x); | |
| 1667 | #else | |
| 1668 | return ::roundl(__lcpp_x); | |
| 1669 | #endif | |
| 1670 | } | |
| 1463 | 1671 | |
| 1464 | 1672 | template <class _A1> |
| 1465 | 1673 | inline _LIBCPP_INLINE_VISIBILITY |
| 1466 | 1674 | typename std::enable_if<std::is_integral<_A1>::value, double>::type |
| 1467 | round(_A1 __lcpp_x) _NOEXCEPT {return ::round((double)__lcpp_x);} | |
| 1675 | round(_A1 __lcpp_x) _NOEXCEPT | |
| 1676 | { | |
| 1677 | #if __has_builtin(__builtin_round) | |
| 1678 | return __builtin_round((double)__lcpp_x); | |
| 1679 | #else | |
| 1680 | return ::round((double)__lcpp_x); | |
| 1681 | #endif | |
| 1682 | } | |
| 1468 | 1683 | |
| 1469 | 1684 | // scalbln |
| 1470 | 1685 | |
| ... | ... | @@ -1498,13 +1713,34 @@ tgamma(_A1 __lcpp_x) _NOEXCEPT {return ::tgamma((double)__lcpp_x);} |
| 1498 | 1713 | |
| 1499 | 1714 | // trunc |
| 1500 | 1715 | |
| 1501 | inline _LIBCPP_INLINE_VISIBILITY float trunc(float __lcpp_x) _NOEXCEPT {return ::truncf(__lcpp_x);} | |
| 1502 | inline _LIBCPP_INLINE_VISIBILITY long double trunc(long double __lcpp_x) _NOEXCEPT {return ::truncl(__lcpp_x);} | |
| 1716 | inline _LIBCPP_INLINE_VISIBILITY float trunc(float __lcpp_x) _NOEXCEPT | |
| 1717 | { | |
| 1718 | #if __has_builtin(__builtin_trunc) | |
| 1719 | return __builtin_trunc(__lcpp_x); | |
| 1720 | #else | |
| 1721 | return ::trunc(__lcpp_x); | |
| 1722 | #endif | |
| 1723 | } | |
| 1724 | inline _LIBCPP_INLINE_VISIBILITY long double trunc(long double __lcpp_x) _NOEXCEPT | |
| 1725 | { | |
| 1726 | #if __has_builtin(__builtin_truncl) | |
| 1727 | return __builtin_truncl(__lcpp_x); | |
| 1728 | #else | |
| 1729 | return ::truncl(__lcpp_x); | |
| 1730 | #endif | |
| 1731 | } | |
| 1503 | 1732 | |
| 1504 | 1733 | template <class _A1> |
| 1505 | 1734 | inline _LIBCPP_INLINE_VISIBILITY |
| 1506 | 1735 | typename std::enable_if<std::is_integral<_A1>::value, double>::type |
| 1507 | trunc(_A1 __lcpp_x) _NOEXCEPT {return ::trunc((double)__lcpp_x);} | |
| 1736 | trunc(_A1 __lcpp_x) _NOEXCEPT | |
| 1737 | { | |
| 1738 | #if __has_builtin(__builtin_trunc) | |
| 1739 | return __builtin_trunc((double)__lcpp_x); | |
| 1740 | #else | |
| 1741 | return ::trunc((double)__lcpp_x); | |
| 1742 | #endif | |
| 1743 | } | |
| 1508 | 1744 | |
| 1509 | 1745 | } // extern "C++" |
| 1510 | 1746 | |
| ... | ... | @@ -1524,4 +1760,4 @@ trunc(_A1 __lcpp_x) _NOEXCEPT {return ::trunc((double)__lcpp_x);} |
| 1524 | 1760 | #include_next <math.h> |
| 1525 | 1761 | #endif |
| 1526 | 1762 | |
| 1527 | #endif // _LIBCPP_MATH_H | |
| 1763 | #endif // _LIBCPP_MATH_H |
lib/libcxx/include/memory+75-3400| ... | ... | @@ -99,7 +99,7 @@ struct allocator_traits |
| 99 | 99 | }; |
| 100 | 100 | |
| 101 | 101 | template <> |
| 102 | class allocator<void> // deprecated in C++17, removed in C++20 | |
| 102 | class allocator<void> // removed in C++20 | |
| 103 | 103 | { |
| 104 | 104 | public: |
| 105 | 105 | typedef void* pointer; |
| ... | ... | @@ -153,14 +153,17 @@ template <class T, class U> |
| 153 | 153 | bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // constexpr in C++20 |
| 154 | 154 | |
| 155 | 155 | template <class OutputIterator, class T> |
| 156 | class raw_storage_iterator | |
| 157 | : public iterator<output_iterator_tag, | |
| 158 | T, // purposefully not C++03 | |
| 159 | ptrdiff_t, // purposefully not C++03 | |
| 160 | T*, // purposefully not C++03 | |
| 161 | raw_storage_iterator&> // purposefully not C++03 | |
| 156 | class raw_storage_iterator // deprecated in C++17, removed in C++20 | |
| 157 | : public iterator<output_iterator_tag, void, void, void, void> // until C++17 | |
| 162 | 158 | { |
| 163 | 159 | public: |
| 160 | typedef output_iterator_tag iterator_category; | |
| 161 | typedef void value_type; | |
| 162 | typedef void difference_type; // until C++20 | |
| 163 | typedef ptrdiff_t difference_type; // since C++20 | |
| 164 | typedef void pointer; | |
| 165 | typedef void reference; | |
| 166 | ||
| 164 | 167 | explicit raw_storage_iterator(OutputIterator x); |
| 165 | 168 | raw_storage_iterator& operator*(); |
| 166 | 169 | raw_storage_iterator& operator=(const T& element); |
| ... | ... | @@ -651,12 +654,12 @@ template <class T, class Alloc> |
| 651 | 654 | inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; |
| 652 | 655 | |
| 653 | 656 | // Pointer safety |
| 654 | enum class pointer_safety { relaxed, preferred, strict }; | |
| 655 | void declare_reachable(void *p); | |
| 656 | template <class T> T *undeclare_reachable(T *p); | |
| 657 | void declare_no_pointers(char *p, size_t n); | |
| 658 | void undeclare_no_pointers(char *p, size_t n); | |
| 659 | pointer_safety get_pointer_safety() noexcept; | |
| 657 | enum class pointer_safety { relaxed, preferred, strict }; // since C++11 | |
| 658 | void declare_reachable(void *p); // since C++11 | |
| 659 | template <class T> T *undeclare_reachable(T *p); // since C++11 | |
| 660 | void declare_no_pointers(char *p, size_t n); // since C++11 | |
| 661 | void undeclare_no_pointers(char *p, size_t n); // since C++11 | |
| 662 | pointer_safety get_pointer_safety() noexcept; // since C++11 | |
| 660 | 663 | |
| 661 | 664 | void* align(size_t alignment, size_t size, void*& ptr, size_t& space); |
| 662 | 665 | |
| ... | ... | @@ -665,29 +668,40 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space); |
| 665 | 668 | */ |
| 666 | 669 | |
| 667 | 670 | #include <__config> |
| 668 | #include <__availability> | |
| 669 | #include <type_traits> | |
| 670 | #include <typeinfo> | |
| 671 | #include <__functional_base> | |
| 672 | #include <__memory/addressof.h> | |
| 673 | #include <__memory/allocation_guard.h> | |
| 674 | #include <__memory/allocator.h> | |
| 675 | #include <__memory/allocator_arg_t.h> | |
| 676 | #include <__memory/allocator_traits.h> | |
| 677 | #include <__memory/compressed_pair.h> | |
| 678 | #include <__memory/construct_at.h> | |
| 679 | #include <__memory/pointer_safety.h> | |
| 680 | #include <__memory/pointer_traits.h> | |
| 681 | #include <__memory/raw_storage_iterator.h> | |
| 682 | #include <__memory/shared_ptr.h> | |
| 683 | #include <__memory/temporary_buffer.h> | |
| 684 | #include <__memory/uninitialized_algorithms.h> | |
| 685 | #include <__memory/unique_ptr.h> | |
| 686 | #include <__memory/uses_allocator.h> | |
| 687 | #include <compare> | |
| 671 | 688 | #include <cstddef> |
| 672 | 689 | #include <cstdint> |
| 673 | #include <new> | |
| 674 | #include <utility> | |
| 675 | #include <limits> | |
| 676 | #include <iterator> | |
| 677 | #include <__functional_base> | |
| 690 | #include <cstring> | |
| 678 | 691 | #include <iosfwd> |
| 679 | #include <tuple> | |
| 692 | #include <iterator> | |
| 693 | #include <new> | |
| 680 | 694 | #include <stdexcept> |
| 681 | #include <cstring> | |
| 682 | #include <__memory/allocator_traits.h> | |
| 683 | #include <__memory/base.h> | |
| 684 | #include <__memory/pointer_traits.h> | |
| 685 | #include <__memory/utilities.h> | |
| 686 | #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) | |
| 687 | # include <atomic> | |
| 688 | #endif | |
| 695 | #include <tuple> | |
| 696 | #include <type_traits> | |
| 697 | #include <typeinfo> | |
| 698 | #include <utility> | |
| 689 | 699 | #include <version> |
| 690 | 700 | |
| 701 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 702 | # include <__memory/auto_ptr.h> | |
| 703 | #endif | |
| 704 | ||
| 691 | 705 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 692 | 706 | #pragma GCC system_header |
| 693 | 707 | #endif |
| ... | ... | @@ -698,286 +712,6 @@ _LIBCPP_PUSH_MACROS |
| 698 | 712 | |
| 699 | 713 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 700 | 714 | |
| 701 | template <class _ValueType> | |
| 702 | inline _LIBCPP_INLINE_VISIBILITY | |
| 703 | _ValueType __libcpp_relaxed_load(_ValueType const* __value) { | |
| 704 | #if !defined(_LIBCPP_HAS_NO_THREADS) && \ | |
| 705 | defined(__ATOMIC_RELAXED) && \ | |
| 706 | (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) | |
| 707 | return __atomic_load_n(__value, __ATOMIC_RELAXED); | |
| 708 | #else | |
| 709 | return *__value; | |
| 710 | #endif | |
| 711 | } | |
| 712 | ||
| 713 | template <class _ValueType> | |
| 714 | inline _LIBCPP_INLINE_VISIBILITY | |
| 715 | _ValueType __libcpp_acquire_load(_ValueType const* __value) { | |
| 716 | #if !defined(_LIBCPP_HAS_NO_THREADS) && \ | |
| 717 | defined(__ATOMIC_ACQUIRE) && \ | |
| 718 | (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) | |
| 719 | return __atomic_load_n(__value, __ATOMIC_ACQUIRE); | |
| 720 | #else | |
| 721 | return *__value; | |
| 722 | #endif | |
| 723 | } | |
| 724 | ||
| 725 | template <bool _UsePointerTraits> struct __to_address_helper; | |
| 726 | ||
| 727 | template <> struct __to_address_helper<true> { | |
| 728 | template <class _Pointer> | |
| 729 | using __return_type = decltype(pointer_traits<_Pointer>::to_address(_VSTD::declval<const _Pointer&>())); | |
| 730 | ||
| 731 | template <class _Pointer> | |
| 732 | _LIBCPP_CONSTEXPR | |
| 733 | static __return_type<_Pointer> | |
| 734 | __do_it(const _Pointer &__p) _NOEXCEPT { return pointer_traits<_Pointer>::to_address(__p); } | |
| 735 | }; | |
| 736 | ||
| 737 | template <class _Pointer, bool _Dummy = true> | |
| 738 | using __choose_to_address = __to_address_helper<_IsValidExpansion<__to_address_helper<_Dummy>::template __return_type, _Pointer>::value>; | |
| 739 | ||
| 740 | ||
| 741 | template <class _Tp> | |
| 742 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 743 | _Tp* | |
| 744 | __to_address(_Tp* __p) _NOEXCEPT | |
| 745 | { | |
| 746 | static_assert(!is_function<_Tp>::value, "_Tp is a function type"); | |
| 747 | return __p; | |
| 748 | } | |
| 749 | ||
| 750 | template <class _Pointer> | |
| 751 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 752 | typename __choose_to_address<_Pointer>::template __return_type<_Pointer> | |
| 753 | __to_address(const _Pointer& __p) _NOEXCEPT { | |
| 754 | return __choose_to_address<_Pointer>::__do_it(__p); | |
| 755 | } | |
| 756 | ||
| 757 | template <> struct __to_address_helper<false> { | |
| 758 | template <class _Pointer> | |
| 759 | using __return_type = typename pointer_traits<_Pointer>::element_type*; | |
| 760 | ||
| 761 | template <class _Pointer> | |
| 762 | _LIBCPP_CONSTEXPR | |
| 763 | static __return_type<_Pointer> | |
| 764 | __do_it(const _Pointer &__p) _NOEXCEPT { return _VSTD::__to_address(__p.operator->()); } | |
| 765 | }; | |
| 766 | ||
| 767 | ||
| 768 | #if _LIBCPP_STD_VER > 17 | |
| 769 | template <class _Tp> | |
| 770 | inline _LIBCPP_INLINE_VISIBILITY constexpr | |
| 771 | _Tp* | |
| 772 | to_address(_Tp* __p) _NOEXCEPT | |
| 773 | { | |
| 774 | static_assert(!is_function_v<_Tp>, "_Tp is a function type"); | |
| 775 | return __p; | |
| 776 | } | |
| 777 | ||
| 778 | template <class _Pointer> | |
| 779 | inline _LIBCPP_INLINE_VISIBILITY constexpr | |
| 780 | auto | |
| 781 | to_address(const _Pointer& __p) _NOEXCEPT | |
| 782 | { | |
| 783 | return _VSTD::__to_address(__p); | |
| 784 | } | |
| 785 | #endif | |
| 786 | ||
| 787 | template <class _Tp> class allocator; | |
| 788 | ||
| 789 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) | |
| 790 | template <> | |
| 791 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator<void> | |
| 792 | { | |
| 793 | public: | |
| 794 | typedef void* pointer; | |
| 795 | typedef const void* const_pointer; | |
| 796 | typedef void value_type; | |
| 797 | ||
| 798 | template <class _Up> struct rebind {typedef allocator<_Up> other;}; | |
| 799 | }; | |
| 800 | ||
| 801 | template <> | |
| 802 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator<const void> | |
| 803 | { | |
| 804 | public: | |
| 805 | typedef const void* pointer; | |
| 806 | typedef const void* const_pointer; | |
| 807 | typedef const void value_type; | |
| 808 | ||
| 809 | template <class _Up> struct rebind {typedef allocator<_Up> other;}; | |
| 810 | }; | |
| 811 | #endif | |
| 812 | ||
| 813 | // allocator | |
| 814 | ||
| 815 | template <class _Tp> | |
| 816 | class _LIBCPP_TEMPLATE_VIS allocator | |
| 817 | { | |
| 818 | public: | |
| 819 | typedef size_t size_type; | |
| 820 | typedef ptrdiff_t difference_type; | |
| 821 | typedef _Tp value_type; | |
| 822 | typedef true_type propagate_on_container_move_assignment; | |
| 823 | typedef true_type is_always_equal; | |
| 824 | ||
| 825 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 826 | allocator() _NOEXCEPT { } | |
| 827 | ||
| 828 | template <class _Up> | |
| 829 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 830 | allocator(const allocator<_Up>&) _NOEXCEPT { } | |
| 831 | ||
| 832 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 833 | _Tp* allocate(size_t __n) { | |
| 834 | if (__n > allocator_traits<allocator>::max_size(*this)) | |
| 835 | __throw_length_error("allocator<T>::allocate(size_t n)" | |
| 836 | " 'n' exceeds maximum supported size"); | |
| 837 | if (__libcpp_is_constant_evaluated()) { | |
| 838 | return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); | |
| 839 | } else { | |
| 840 | return static_cast<_Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); | |
| 841 | } | |
| 842 | } | |
| 843 | ||
| 844 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 845 | void deallocate(_Tp* __p, size_t __n) _NOEXCEPT { | |
| 846 | if (__libcpp_is_constant_evaluated()) { | |
| 847 | ::operator delete(__p); | |
| 848 | } else { | |
| 849 | _VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); | |
| 850 | } | |
| 851 | } | |
| 852 | ||
| 853 | // C++20 Removed members | |
| 854 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) | |
| 855 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp* pointer; | |
| 856 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; | |
| 857 | _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp& reference; | |
| 858 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& const_reference; | |
| 859 | ||
| 860 | template <class _Up> | |
| 861 | struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { | |
| 862 | typedef allocator<_Up> other; | |
| 863 | }; | |
| 864 | ||
| 865 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 866 | pointer address(reference __x) const _NOEXCEPT { | |
| 867 | return _VSTD::addressof(__x); | |
| 868 | } | |
| 869 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 870 | const_pointer address(const_reference __x) const _NOEXCEPT { | |
| 871 | return _VSTD::addressof(__x); | |
| 872 | } | |
| 873 | ||
| 874 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_IN_CXX17 | |
| 875 | _Tp* allocate(size_t __n, const void*) { | |
| 876 | return allocate(__n); | |
| 877 | } | |
| 878 | ||
| 879 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT { | |
| 880 | return size_type(~0) / sizeof(_Tp); | |
| 881 | } | |
| 882 | ||
| 883 | template <class _Up, class... _Args> | |
| 884 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 885 | void construct(_Up* __p, _Args&&... __args) { | |
| 886 | ::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); | |
| 887 | } | |
| 888 | ||
| 889 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 890 | void destroy(pointer __p) { | |
| 891 | __p->~_Tp(); | |
| 892 | } | |
| 893 | #endif | |
| 894 | }; | |
| 895 | ||
| 896 | template <class _Tp> | |
| 897 | class _LIBCPP_TEMPLATE_VIS allocator<const _Tp> | |
| 898 | { | |
| 899 | public: | |
| 900 | typedef size_t size_type; | |
| 901 | typedef ptrdiff_t difference_type; | |
| 902 | typedef const _Tp value_type; | |
| 903 | typedef true_type propagate_on_container_move_assignment; | |
| 904 | typedef true_type is_always_equal; | |
| 905 | ||
| 906 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 907 | allocator() _NOEXCEPT { } | |
| 908 | ||
| 909 | template <class _Up> | |
| 910 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 911 | allocator(const allocator<_Up>&) _NOEXCEPT { } | |
| 912 | ||
| 913 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 914 | const _Tp* allocate(size_t __n) { | |
| 915 | if (__n > allocator_traits<allocator>::max_size(*this)) | |
| 916 | __throw_length_error("allocator<const T>::allocate(size_t n)" | |
| 917 | " 'n' exceeds maximum supported size"); | |
| 918 | if (__libcpp_is_constant_evaluated()) { | |
| 919 | return static_cast<const _Tp*>(::operator new(__n * sizeof(_Tp))); | |
| 920 | } else { | |
| 921 | return static_cast<const _Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); | |
| 922 | } | |
| 923 | } | |
| 924 | ||
| 925 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 926 | void deallocate(const _Tp* __p, size_t __n) { | |
| 927 | if (__libcpp_is_constant_evaluated()) { | |
| 928 | ::operator delete(const_cast<_Tp*>(__p)); | |
| 929 | } else { | |
| 930 | _VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); | |
| 931 | } | |
| 932 | } | |
| 933 | ||
| 934 | // C++20 Removed members | |
| 935 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) | |
| 936 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* pointer; | |
| 937 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; | |
| 938 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& reference; | |
| 939 | _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& const_reference; | |
| 940 | ||
| 941 | template <class _Up> | |
| 942 | struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { | |
| 943 | typedef allocator<_Up> other; | |
| 944 | }; | |
| 945 | ||
| 946 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 947 | const_pointer address(const_reference __x) const _NOEXCEPT { | |
| 948 | return _VSTD::addressof(__x); | |
| 949 | } | |
| 950 | ||
| 951 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_IN_CXX17 | |
| 952 | const _Tp* allocate(size_t __n, const void*) { | |
| 953 | return allocate(__n); | |
| 954 | } | |
| 955 | ||
| 956 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT { | |
| 957 | return size_type(~0) / sizeof(_Tp); | |
| 958 | } | |
| 959 | ||
| 960 | template <class _Up, class... _Args> | |
| 961 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 962 | void construct(_Up* __p, _Args&&... __args) { | |
| 963 | ::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); | |
| 964 | } | |
| 965 | ||
| 966 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VISIBILITY | |
| 967 | void destroy(pointer __p) { | |
| 968 | __p->~_Tp(); | |
| 969 | } | |
| 970 | #endif | |
| 971 | }; | |
| 972 | ||
| 973 | template <class _Tp, class _Up> | |
| 974 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 975 | bool operator==(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return true;} | |
| 976 | ||
| 977 | template <class _Tp, class _Up> | |
| 978 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 979 | bool operator!=(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return false;} | |
| 980 | ||
| 981 | 715 | template <class _Alloc, class _Ptr> |
| 982 | 716 | _LIBCPP_INLINE_VISIBILITY |
| 983 | 717 | void __construct_forward_with_exception_guarantees(_Alloc& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2) { |
| ... | ... | @@ -1062,3107 +796,48 @@ void __construct_backward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* |
| 1062 | 796 | ptrdiff_t _Np = __end1 - __begin1; |
| 1063 | 797 | __end2 -= _Np; |
| 1064 | 798 | if (_Np > 0) |
| 1065 | _VSTD::memcpy(__end2, __begin1, _Np * sizeof(_Tp)); | |
| 1066 | } | |
| 1067 | ||
| 1068 | template <class _OutputIterator, class _Tp> | |
| 1069 | class _LIBCPP_TEMPLATE_VIS raw_storage_iterator | |
| 1070 | : public iterator<output_iterator_tag, | |
| 1071 | _Tp, // purposefully not C++03 | |
| 1072 | ptrdiff_t, // purposefully not C++03 | |
| 1073 | _Tp*, // purposefully not C++03 | |
| 1074 | raw_storage_iterator<_OutputIterator, _Tp>&> // purposefully not C++03 | |
| 1075 | { | |
| 1076 | private: | |
| 1077 | _OutputIterator __x_; | |
| 1078 | public: | |
| 1079 | _LIBCPP_INLINE_VISIBILITY explicit raw_storage_iterator(_OutputIterator __x) : __x_(__x) {} | |
| 1080 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator*() {return *this;} | |
| 1081 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(const _Tp& __element) | |
| 1082 | {::new ((void*)_VSTD::addressof(*__x_)) _Tp(__element); return *this;} | |
| 1083 | #if _LIBCPP_STD_VER >= 14 | |
| 1084 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(_Tp&& __element) | |
| 1085 | {::new ((void*)_VSTD::addressof(*__x_)) _Tp(_VSTD::move(__element)); return *this;} | |
| 1086 | #endif | |
| 1087 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator++() {++__x_; return *this;} | |
| 1088 | _LIBCPP_INLINE_VISIBILITY raw_storage_iterator operator++(int) | |
| 1089 | {raw_storage_iterator __t(*this); ++__x_; return __t;} | |
| 1090 | #if _LIBCPP_STD_VER >= 14 | |
| 1091 | _LIBCPP_INLINE_VISIBILITY _OutputIterator base() const { return __x_; } | |
| 1092 | #endif | |
| 1093 | }; | |
| 1094 | ||
| 1095 | template <class _Tp> | |
| 1096 | _LIBCPP_NODISCARD_EXT _LIBCPP_NO_CFI | |
| 1097 | pair<_Tp*, ptrdiff_t> | |
| 1098 | get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT | |
| 1099 | { | |
| 1100 | pair<_Tp*, ptrdiff_t> __r(0, 0); | |
| 1101 | const ptrdiff_t __m = (~ptrdiff_t(0) ^ | |
| 1102 | ptrdiff_t(ptrdiff_t(1) << (sizeof(ptrdiff_t) * __CHAR_BIT__ - 1))) | |
| 1103 | / sizeof(_Tp); | |
| 1104 | if (__n > __m) | |
| 1105 | __n = __m; | |
| 1106 | while (__n > 0) | |
| 1107 | { | |
| 1108 | #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) | |
| 1109 | if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) | |
| 1110 | { | |
| 1111 | align_val_t __al = | |
| 1112 | align_val_t(alignment_of<_Tp>::value); | |
| 1113 | __r.first = static_cast<_Tp*>(::operator new( | |
| 1114 | __n * sizeof(_Tp), __al, nothrow)); | |
| 1115 | } else { | |
| 1116 | __r.first = static_cast<_Tp*>(::operator new( | |
| 1117 | __n * sizeof(_Tp), nothrow)); | |
| 1118 | } | |
| 1119 | #else | |
| 1120 | if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) | |
| 1121 | { | |
| 1122 | // Since aligned operator new is unavailable, return an empty | |
| 1123 | // buffer rather than one with invalid alignment. | |
| 1124 | return __r; | |
| 1125 | } | |
| 1126 | ||
| 1127 | __r.first = static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), nothrow)); | |
| 1128 | #endif | |
| 1129 | ||
| 1130 | if (__r.first) | |
| 1131 | { | |
| 1132 | __r.second = __n; | |
| 1133 | break; | |
| 1134 | } | |
| 1135 | __n /= 2; | |
| 1136 | } | |
| 1137 | return __r; | |
| 1138 | } | |
| 1139 | ||
| 1140 | template <class _Tp> | |
| 1141 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1142 | void return_temporary_buffer(_Tp* __p) _NOEXCEPT | |
| 1143 | { | |
| 1144 | _VSTD::__libcpp_deallocate_unsized((void*)__p, _LIBCPP_ALIGNOF(_Tp)); | |
| 799 | _VSTD::memcpy(static_cast<void*>(__end2), static_cast<void const*>(__begin1), _Np * sizeof(_Tp)); | |
| 1145 | 800 | } |
| 1146 | 801 | |
| 1147 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 1148 | template <class _Tp> | |
| 1149 | struct _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr_ref | |
| 1150 | { | |
| 1151 | _Tp* __ptr_; | |
| 1152 | }; | |
| 1153 | ||
| 1154 | template<class _Tp> | |
| 1155 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr | |
| 1156 | { | |
| 1157 | private: | |
| 1158 | _Tp* __ptr_; | |
| 1159 | public: | |
| 1160 | typedef _Tp element_type; | |
| 1161 | ||
| 1162 | _LIBCPP_INLINE_VISIBILITY explicit auto_ptr(_Tp* __p = 0) _NOEXCEPT : __ptr_(__p) {} | |
| 1163 | _LIBCPP_INLINE_VISIBILITY auto_ptr(auto_ptr& __p) _NOEXCEPT : __ptr_(__p.release()) {} | |
| 1164 | template<class _Up> _LIBCPP_INLINE_VISIBILITY auto_ptr(auto_ptr<_Up>& __p) _NOEXCEPT | |
| 1165 | : __ptr_(__p.release()) {} | |
| 1166 | _LIBCPP_INLINE_VISIBILITY auto_ptr& operator=(auto_ptr& __p) _NOEXCEPT | |
| 1167 | {reset(__p.release()); return *this;} | |
| 1168 | template<class _Up> _LIBCPP_INLINE_VISIBILITY auto_ptr& operator=(auto_ptr<_Up>& __p) _NOEXCEPT | |
| 1169 | {reset(__p.release()); return *this;} | |
| 1170 | _LIBCPP_INLINE_VISIBILITY auto_ptr& operator=(auto_ptr_ref<_Tp> __p) _NOEXCEPT | |
| 1171 | {reset(__p.__ptr_); return *this;} | |
| 1172 | _LIBCPP_INLINE_VISIBILITY ~auto_ptr() _NOEXCEPT {delete __ptr_;} | |
| 1173 | ||
| 1174 | _LIBCPP_INLINE_VISIBILITY _Tp& operator*() const _NOEXCEPT | |
| 1175 | {return *__ptr_;} | |
| 1176 | _LIBCPP_INLINE_VISIBILITY _Tp* operator->() const _NOEXCEPT {return __ptr_;} | |
| 1177 | _LIBCPP_INLINE_VISIBILITY _Tp* get() const _NOEXCEPT {return __ptr_;} | |
| 1178 | _LIBCPP_INLINE_VISIBILITY _Tp* release() _NOEXCEPT | |
| 1179 | { | |
| 1180 | _Tp* __t = __ptr_; | |
| 1181 | __ptr_ = nullptr; | |
| 1182 | return __t; | |
| 1183 | } | |
| 1184 | _LIBCPP_INLINE_VISIBILITY void reset(_Tp* __p = 0) _NOEXCEPT | |
| 1185 | { | |
| 1186 | if (__ptr_ != __p) | |
| 1187 | delete __ptr_; | |
| 1188 | __ptr_ = __p; | |
| 1189 | } | |
| 1190 | ||
| 1191 | _LIBCPP_INLINE_VISIBILITY auto_ptr(auto_ptr_ref<_Tp> __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} | |
| 1192 | template<class _Up> _LIBCPP_INLINE_VISIBILITY operator auto_ptr_ref<_Up>() _NOEXCEPT | |
| 1193 | {auto_ptr_ref<_Up> __t; __t.__ptr_ = release(); return __t;} | |
| 1194 | template<class _Up> _LIBCPP_INLINE_VISIBILITY operator auto_ptr<_Up>() _NOEXCEPT | |
| 1195 | {return auto_ptr<_Up>(release());} | |
| 1196 | }; | |
| 1197 | ||
| 1198 | template <> | |
| 1199 | class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr<void> | |
| 802 | struct __destruct_n | |
| 1200 | 803 | { |
| 1201 | public: | |
| 1202 | typedef void element_type; | |
| 1203 | }; | |
| 1204 | #endif | |
| 1205 | ||
| 1206 | // Tag used to default initialize one or both of the pair's elements. | |
| 1207 | struct __default_init_tag {}; | |
| 1208 | struct __value_init_tag {}; | |
| 1209 | ||
| 1210 | template <class _Tp, int _Idx, | |
| 1211 | bool _CanBeEmptyBase = | |
| 1212 | is_empty<_Tp>::value && !__libcpp_is_final<_Tp>::value> | |
| 1213 | struct __compressed_pair_elem { | |
| 1214 | typedef _Tp _ParamT; | |
| 1215 | typedef _Tp& reference; | |
| 1216 | typedef const _Tp& const_reference; | |
| 1217 | ||
| 1218 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1219 | __compressed_pair_elem(__default_init_tag) {} | |
| 1220 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1221 | __compressed_pair_elem(__value_init_tag) : __value_() {} | |
| 1222 | ||
| 1223 | template <class _Up, class = typename enable_if< | |
| 1224 | !is_same<__compressed_pair_elem, typename decay<_Up>::type>::value | |
| 1225 | >::type> | |
| 1226 | _LIBCPP_INLINE_VISIBILITY | |
| 1227 | _LIBCPP_CONSTEXPR explicit | |
| 1228 | __compressed_pair_elem(_Up&& __u) | |
| 1229 | : __value_(_VSTD::forward<_Up>(__u)) | |
| 1230 | { | |
| 1231 | } | |
| 1232 | ||
| 1233 | ||
| 1234 | #ifndef _LIBCPP_CXX03_LANG | |
| 1235 | template <class... _Args, size_t... _Indexes> | |
| 1236 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1237 | __compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args, | |
| 1238 | __tuple_indices<_Indexes...>) | |
| 1239 | : __value_(_VSTD::forward<_Args>(_VSTD::get<_Indexes>(__args))...) {} | |
| 1240 | #endif | |
| 1241 | ||
| 1242 | ||
| 1243 | _LIBCPP_INLINE_VISIBILITY reference __get() _NOEXCEPT { return __value_; } | |
| 1244 | _LIBCPP_INLINE_VISIBILITY | |
| 1245 | const_reference __get() const _NOEXCEPT { return __value_; } | |
| 1246 | ||
| 1247 | 804 | private: |
| 1248 | _Tp __value_; | |
| 1249 | }; | |
| 1250 | ||
| 1251 | template <class _Tp, int _Idx> | |
| 1252 | struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { | |
| 1253 | typedef _Tp _ParamT; | |
| 1254 | typedef _Tp& reference; | |
| 1255 | typedef const _Tp& const_reference; | |
| 1256 | typedef _Tp __value_type; | |
| 1257 | ||
| 1258 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __compressed_pair_elem() = default; | |
| 1259 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1260 | __compressed_pair_elem(__default_init_tag) {} | |
| 1261 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1262 | __compressed_pair_elem(__value_init_tag) : __value_type() {} | |
| 1263 | ||
| 1264 | template <class _Up, class = typename enable_if< | |
| 1265 | !is_same<__compressed_pair_elem, typename decay<_Up>::type>::value | |
| 1266 | >::type> | |
| 1267 | _LIBCPP_INLINE_VISIBILITY | |
| 1268 | _LIBCPP_CONSTEXPR explicit | |
| 1269 | __compressed_pair_elem(_Up&& __u) | |
| 1270 | : __value_type(_VSTD::forward<_Up>(__u)) | |
| 1271 | {} | |
| 1272 | ||
| 1273 | #ifndef _LIBCPP_CXX03_LANG | |
| 1274 | template <class... _Args, size_t... _Indexes> | |
| 1275 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1276 | __compressed_pair_elem(piecewise_construct_t, tuple<_Args...> __args, | |
| 1277 | __tuple_indices<_Indexes...>) | |
| 1278 | : __value_type(_VSTD::forward<_Args>(_VSTD::get<_Indexes>(__args))...) {} | |
| 1279 | #endif | |
| 1280 | ||
| 1281 | _LIBCPP_INLINE_VISIBILITY reference __get() _NOEXCEPT { return *this; } | |
| 1282 | _LIBCPP_INLINE_VISIBILITY | |
| 1283 | const_reference __get() const _NOEXCEPT { return *this; } | |
| 1284 | }; | |
| 1285 | ||
| 1286 | template <class _T1, class _T2> | |
| 1287 | class __compressed_pair : private __compressed_pair_elem<_T1, 0>, | |
| 1288 | private __compressed_pair_elem<_T2, 1> { | |
| 1289 | public: | |
| 1290 | // NOTE: This static assert should never fire because __compressed_pair | |
| 1291 | // is *almost never* used in a scenario where it's possible for T1 == T2. | |
| 1292 | // (The exception is std::function where it is possible that the function | |
| 1293 | // object and the allocator have the same type). | |
| 1294 | static_assert((!is_same<_T1, _T2>::value), | |
| 1295 | "__compressed_pair cannot be instantiated when T1 and T2 are the same type; " | |
| 1296 | "The current implementation is NOT ABI-compatible with the previous " | |
| 1297 | "implementation for this configuration"); | |
| 1298 | ||
| 1299 | typedef _LIBCPP_NODEBUG_TYPE __compressed_pair_elem<_T1, 0> _Base1; | |
| 1300 | typedef _LIBCPP_NODEBUG_TYPE __compressed_pair_elem<_T2, 1> _Base2; | |
| 1301 | ||
| 1302 | template <bool _Dummy = true, | |
| 1303 | class = typename enable_if< | |
| 1304 | __dependent_type<is_default_constructible<_T1>, _Dummy>::value && | |
| 1305 | __dependent_type<is_default_constructible<_T2>, _Dummy>::value | |
| 1306 | >::type | |
| 1307 | > | |
| 1308 | _LIBCPP_INLINE_VISIBILITY | |
| 1309 | _LIBCPP_CONSTEXPR __compressed_pair() : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {} | |
| 1310 | ||
| 1311 | template <class _U1, class _U2> | |
| 1312 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1313 | __compressed_pair(_U1&& __t1, _U2&& __t2) | |
| 1314 | : _Base1(_VSTD::forward<_U1>(__t1)), _Base2(_VSTD::forward<_U2>(__t2)) {} | |
| 1315 | ||
| 1316 | #ifndef _LIBCPP_CXX03_LANG | |
| 1317 | template <class... _Args1, class... _Args2> | |
| 1318 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 | |
| 1319 | __compressed_pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, | |
| 1320 | tuple<_Args2...> __second_args) | |
| 1321 | : _Base1(__pc, _VSTD::move(__first_args), | |
| 1322 | typename __make_tuple_indices<sizeof...(_Args1)>::type()), | |
| 1323 | _Base2(__pc, _VSTD::move(__second_args), | |
| 1324 | typename __make_tuple_indices<sizeof...(_Args2)>::type()) {} | |
| 1325 | #endif | |
| 1326 | ||
| 1327 | _LIBCPP_INLINE_VISIBILITY | |
| 1328 | typename _Base1::reference first() _NOEXCEPT { | |
| 1329 | return static_cast<_Base1&>(*this).__get(); | |
| 1330 | } | |
| 1331 | ||
| 1332 | _LIBCPP_INLINE_VISIBILITY | |
| 1333 | typename _Base1::const_reference first() const _NOEXCEPT { | |
| 1334 | return static_cast<_Base1 const&>(*this).__get(); | |
| 1335 | } | |
| 1336 | ||
| 1337 | _LIBCPP_INLINE_VISIBILITY | |
| 1338 | typename _Base2::reference second() _NOEXCEPT { | |
| 1339 | return static_cast<_Base2&>(*this).__get(); | |
| 1340 | } | |
| 1341 | ||
| 1342 | _LIBCPP_INLINE_VISIBILITY | |
| 1343 | typename _Base2::const_reference second() const _NOEXCEPT { | |
| 1344 | return static_cast<_Base2 const&>(*this).__get(); | |
| 1345 | } | |
| 1346 | ||
| 1347 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1348 | static _Base1* __get_first_base(__compressed_pair* __pair) _NOEXCEPT { | |
| 1349 | return static_cast<_Base1*>(__pair); | |
| 1350 | } | |
| 1351 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 1352 | static _Base2* __get_second_base(__compressed_pair* __pair) _NOEXCEPT { | |
| 1353 | return static_cast<_Base2*>(__pair); | |
| 1354 | } | |
| 1355 | ||
| 1356 | _LIBCPP_INLINE_VISIBILITY | |
| 1357 | void swap(__compressed_pair& __x) | |
| 1358 | _NOEXCEPT_(__is_nothrow_swappable<_T1>::value && | |
| 1359 | __is_nothrow_swappable<_T2>::value) | |
| 1360 | { | |
| 1361 | using _VSTD::swap; | |
| 1362 | swap(first(), __x.first()); | |
| 1363 | swap(second(), __x.second()); | |
| 1364 | } | |
| 1365 | }; | |
| 1366 | ||
| 1367 | template <class _T1, class _T2> | |
| 1368 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1369 | void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) | |
| 1370 | _NOEXCEPT_(__is_nothrow_swappable<_T1>::value && | |
| 1371 | __is_nothrow_swappable<_T2>::value) { | |
| 1372 | __x.swap(__y); | |
| 1373 | } | |
| 805 | size_t __size_; | |
| 1374 | 806 | |
| 1375 | // default_delete | |
| 807 | template <class _Tp> | |
| 808 | _LIBCPP_INLINE_VISIBILITY void __process(_Tp* __p, false_type) _NOEXCEPT | |
| 809 | {for (size_t __i = 0; __i < __size_; ++__i, ++__p) __p->~_Tp();} | |
| 1376 | 810 | |
| 1377 | template <class _Tp> | |
| 1378 | struct _LIBCPP_TEMPLATE_VIS default_delete { | |
| 1379 | static_assert(!is_function<_Tp>::value, | |
| 1380 | "default_delete cannot be instantiated for function types"); | |
| 1381 | #ifndef _LIBCPP_CXX03_LANG | |
| 1382 | _LIBCPP_INLINE_VISIBILITY constexpr default_delete() _NOEXCEPT = default; | |
| 1383 | #else | |
| 1384 | _LIBCPP_INLINE_VISIBILITY default_delete() {} | |
| 1385 | #endif | |
| 1386 | template <class _Up> | |
| 1387 | _LIBCPP_INLINE_VISIBILITY | |
| 1388 | default_delete(const default_delete<_Up>&, | |
| 1389 | typename enable_if<is_convertible<_Up*, _Tp*>::value>::type* = | |
| 1390 | 0) _NOEXCEPT {} | |
| 1391 | ||
| 1392 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __ptr) const _NOEXCEPT { | |
| 1393 | static_assert(sizeof(_Tp) > 0, | |
| 1394 | "default_delete can not delete incomplete type"); | |
| 1395 | static_assert(!is_void<_Tp>::value, | |
| 1396 | "default_delete can not delete incomplete type"); | |
| 1397 | delete __ptr; | |
| 1398 | } | |
| 1399 | }; | |
| 811 | template <class _Tp> | |
| 812 | _LIBCPP_INLINE_VISIBILITY void __process(_Tp*, true_type) _NOEXCEPT | |
| 813 | {} | |
| 1400 | 814 | |
| 1401 | template <class _Tp> | |
| 1402 | struct _LIBCPP_TEMPLATE_VIS default_delete<_Tp[]> { | |
| 1403 | private: | |
| 1404 | template <class _Up> | |
| 1405 | struct _EnableIfConvertible | |
| 1406 | : enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value> {}; | |
| 815 | _LIBCPP_INLINE_VISIBILITY void __incr(false_type) _NOEXCEPT | |
| 816 | {++__size_;} | |
| 817 | _LIBCPP_INLINE_VISIBILITY void __incr(true_type) _NOEXCEPT | |
| 818 | {} | |
| 1407 | 819 | |
| 820 | _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, false_type) _NOEXCEPT | |
| 821 | {__size_ = __s;} | |
| 822 | _LIBCPP_INLINE_VISIBILITY void __set(size_t, true_type) _NOEXCEPT | |
| 823 | {} | |
| 1408 | 824 | public: |
| 1409 | #ifndef _LIBCPP_CXX03_LANG | |
| 1410 | _LIBCPP_INLINE_VISIBILITY constexpr default_delete() _NOEXCEPT = default; | |
| 1411 | #else | |
| 1412 | _LIBCPP_INLINE_VISIBILITY default_delete() {} | |
| 1413 | #endif | |
| 1414 | ||
| 1415 | template <class _Up> | |
| 1416 | _LIBCPP_INLINE_VISIBILITY | |
| 1417 | default_delete(const default_delete<_Up[]>&, | |
| 1418 | typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPT {} | |
| 1419 | ||
| 1420 | template <class _Up> | |
| 1421 | _LIBCPP_INLINE_VISIBILITY | |
| 1422 | typename _EnableIfConvertible<_Up>::type | |
| 1423 | operator()(_Up* __ptr) const _NOEXCEPT { | |
| 1424 | static_assert(sizeof(_Tp) > 0, | |
| 1425 | "default_delete can not delete incomplete type"); | |
| 1426 | static_assert(!is_void<_Tp>::value, | |
| 1427 | "default_delete can not delete void type"); | |
| 1428 | delete[] __ptr; | |
| 1429 | } | |
| 1430 | }; | |
| 825 | _LIBCPP_INLINE_VISIBILITY explicit __destruct_n(size_t __s) _NOEXCEPT | |
| 826 | : __size_(__s) {} | |
| 1431 | 827 | |
| 1432 | template <class _Deleter> | |
| 1433 | struct __unique_ptr_deleter_sfinae { | |
| 1434 | static_assert(!is_reference<_Deleter>::value, "incorrect specialization"); | |
| 1435 | typedef const _Deleter& __lval_ref_type; | |
| 1436 | typedef _Deleter&& __good_rval_ref_type; | |
| 1437 | typedef true_type __enable_rval_overload; | |
| 1438 | }; | |
| 828 | template <class _Tp> | |
| 829 | _LIBCPP_INLINE_VISIBILITY void __incr() _NOEXCEPT | |
| 830 | {__incr(integral_constant<bool, is_trivially_destructible<_Tp>::value>());} | |
| 1439 | 831 | |
| 1440 | template <class _Deleter> | |
| 1441 | struct __unique_ptr_deleter_sfinae<_Deleter const&> { | |
| 1442 | typedef const _Deleter& __lval_ref_type; | |
| 1443 | typedef const _Deleter&& __bad_rval_ref_type; | |
| 1444 | typedef false_type __enable_rval_overload; | |
| 1445 | }; | |
| 832 | template <class _Tp> | |
| 833 | _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, _Tp*) _NOEXCEPT | |
| 834 | {__set(__s, integral_constant<bool, is_trivially_destructible<_Tp>::value>());} | |
| 1446 | 835 | |
| 1447 | template <class _Deleter> | |
| 1448 | struct __unique_ptr_deleter_sfinae<_Deleter&> { | |
| 1449 | typedef _Deleter& __lval_ref_type; | |
| 1450 | typedef _Deleter&& __bad_rval_ref_type; | |
| 1451 | typedef false_type __enable_rval_overload; | |
| 836 | template <class _Tp> | |
| 837 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) _NOEXCEPT | |
| 838 | {__process(__p, integral_constant<bool, is_trivially_destructible<_Tp>::value>());} | |
| 1452 | 839 | }; |
| 1453 | 840 | |
| 1454 | #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI) | |
| 1455 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) | |
| 1456 | #else | |
| 1457 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI | |
| 1458 | #endif | |
| 1459 | ||
| 1460 | template <class _Tp, class _Dp = default_delete<_Tp> > | |
| 1461 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { | |
| 1462 | public: | |
| 1463 | typedef _Tp element_type; | |
| 1464 | typedef _Dp deleter_type; | |
| 1465 | typedef _LIBCPP_NODEBUG_TYPE typename __pointer<_Tp, deleter_type>::type pointer; | |
| 1466 | ||
| 1467 | static_assert(!is_rvalue_reference<deleter_type>::value, | |
| 1468 | "the specified deleter type cannot be an rvalue reference"); | |
| 1469 | ||
| 1470 | private: | |
| 1471 | __compressed_pair<pointer, deleter_type> __ptr_; | |
| 1472 | ||
| 1473 | struct __nat { int __for_bool_; }; | |
| 1474 | ||
| 1475 | typedef _LIBCPP_NODEBUG_TYPE __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; | |
| 1476 | ||
| 1477 | template <bool _Dummy> | |
| 1478 | using _LValRefType _LIBCPP_NODEBUG_TYPE = | |
| 1479 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; | |
| 1480 | ||
| 1481 | template <bool _Dummy> | |
| 1482 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 1483 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; | |
| 1484 | ||
| 1485 | template <bool _Dummy> | |
| 1486 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 1487 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; | |
| 1488 | ||
| 1489 | template <bool _Dummy, class _Deleter = typename __dependent_type< | |
| 1490 | __identity<deleter_type>, _Dummy>::type> | |
| 1491 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE = | |
| 1492 | typename enable_if<is_default_constructible<_Deleter>::value && | |
| 1493 | !is_pointer<_Deleter>::value>::type; | |
| 1494 | ||
| 1495 | template <class _ArgType> | |
| 1496 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE = | |
| 1497 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; | |
| 1498 | ||
| 1499 | template <class _UPtr, class _Up> | |
| 1500 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 1501 | is_convertible<typename _UPtr::pointer, pointer>::value && | |
| 1502 | !is_array<_Up>::value | |
| 1503 | >::type; | |
| 1504 | ||
| 1505 | template <class _UDel> | |
| 1506 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 1507 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || | |
| 1508 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) | |
| 1509 | >::type; | |
| 1510 | ||
| 1511 | template <class _UDel> | |
| 1512 | using _EnableIfDeleterAssignable = typename enable_if< | |
| 1513 | is_assignable<_Dp&, _UDel&&>::value | |
| 1514 | >::type; | |
| 1515 | ||
| 1516 | public: | |
| 1517 | template <bool _Dummy = true, | |
| 1518 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 1519 | _LIBCPP_INLINE_VISIBILITY | |
| 1520 | _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 1521 | ||
| 1522 | template <bool _Dummy = true, | |
| 1523 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 1524 | _LIBCPP_INLINE_VISIBILITY | |
| 1525 | _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 1526 | ||
| 1527 | template <bool _Dummy = true, | |
| 1528 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 1529 | _LIBCPP_INLINE_VISIBILITY | |
| 1530 | explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __default_init_tag()) {} | |
| 1531 | ||
| 1532 | template <bool _Dummy = true, | |
| 1533 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > | |
| 1534 | _LIBCPP_INLINE_VISIBILITY | |
| 1535 | unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT | |
| 1536 | : __ptr_(__p, __d) {} | |
| 1537 | ||
| 1538 | template <bool _Dummy = true, | |
| 1539 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > | |
| 1540 | _LIBCPP_INLINE_VISIBILITY | |
| 1541 | unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT | |
| 1542 | : __ptr_(__p, _VSTD::move(__d)) { | |
| 1543 | static_assert(!is_reference<deleter_type>::value, | |
| 1544 | "rvalue deleter bound to reference"); | |
| 1545 | } | |
| 1546 | ||
| 1547 | template <bool _Dummy = true, | |
| 1548 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > > | |
| 1549 | _LIBCPP_INLINE_VISIBILITY | |
| 1550 | unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete; | |
| 1551 | ||
| 1552 | _LIBCPP_INLINE_VISIBILITY | |
| 1553 | unique_ptr(unique_ptr&& __u) _NOEXCEPT | |
| 1554 | : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { | |
| 1555 | } | |
| 1556 | ||
| 1557 | template <class _Up, class _Ep, | |
| 1558 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 1559 | class = _EnableIfDeleterConvertible<_Ep> | |
| 1560 | > | |
| 1561 | _LIBCPP_INLINE_VISIBILITY | |
| 1562 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT | |
| 1563 | : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {} | |
| 1564 | ||
| 1565 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 1566 | template <class _Up> | |
| 1567 | _LIBCPP_INLINE_VISIBILITY | |
| 1568 | unique_ptr(auto_ptr<_Up>&& __p, | |
| 1569 | typename enable_if<is_convertible<_Up*, _Tp*>::value && | |
| 1570 | is_same<_Dp, default_delete<_Tp> >::value, | |
| 1571 | __nat>::type = __nat()) _NOEXCEPT | |
| 1572 | : __ptr_(__p.release(), __default_init_tag()) {} | |
| 1573 | #endif | |
| 1574 | ||
| 1575 | _LIBCPP_INLINE_VISIBILITY | |
| 1576 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { | |
| 1577 | reset(__u.release()); | |
| 1578 | __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter()); | |
| 1579 | return *this; | |
| 1580 | } | |
| 1581 | ||
| 1582 | template <class _Up, class _Ep, | |
| 1583 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 1584 | class = _EnableIfDeleterAssignable<_Ep> | |
| 1585 | > | |
| 1586 | _LIBCPP_INLINE_VISIBILITY | |
| 1587 | unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { | |
| 1588 | reset(__u.release()); | |
| 1589 | __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); | |
| 1590 | return *this; | |
| 1591 | } | |
| 1592 | ||
| 1593 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 1594 | template <class _Up> | |
| 1595 | _LIBCPP_INLINE_VISIBILITY | |
| 1596 | typename enable_if<is_convertible<_Up*, _Tp*>::value && | |
| 1597 | is_same<_Dp, default_delete<_Tp> >::value, | |
| 1598 | unique_ptr&>::type | |
| 1599 | operator=(auto_ptr<_Up> __p) { | |
| 1600 | reset(__p.release()); | |
| 1601 | return *this; | |
| 1602 | } | |
| 1603 | #endif | |
| 1604 | ||
| 1605 | #ifdef _LIBCPP_CXX03_LANG | |
| 1606 | unique_ptr(unique_ptr const&) = delete; | |
| 1607 | unique_ptr& operator=(unique_ptr const&) = delete; | |
| 1608 | #endif | |
| 1609 | ||
| 1610 | ||
| 1611 | _LIBCPP_INLINE_VISIBILITY | |
| 1612 | ~unique_ptr() { reset(); } | |
| 1613 | ||
| 1614 | _LIBCPP_INLINE_VISIBILITY | |
| 1615 | unique_ptr& operator=(nullptr_t) _NOEXCEPT { | |
| 1616 | reset(); | |
| 1617 | return *this; | |
| 1618 | } | |
| 1619 | ||
| 1620 | _LIBCPP_INLINE_VISIBILITY | |
| 1621 | typename add_lvalue_reference<_Tp>::type | |
| 1622 | operator*() const { | |
| 1623 | return *__ptr_.first(); | |
| 1624 | } | |
| 1625 | _LIBCPP_INLINE_VISIBILITY | |
| 1626 | pointer operator->() const _NOEXCEPT { | |
| 1627 | return __ptr_.first(); | |
| 1628 | } | |
| 1629 | _LIBCPP_INLINE_VISIBILITY | |
| 1630 | pointer get() const _NOEXCEPT { | |
| 1631 | return __ptr_.first(); | |
| 1632 | } | |
| 1633 | _LIBCPP_INLINE_VISIBILITY | |
| 1634 | deleter_type& get_deleter() _NOEXCEPT { | |
| 1635 | return __ptr_.second(); | |
| 1636 | } | |
| 1637 | _LIBCPP_INLINE_VISIBILITY | |
| 1638 | const deleter_type& get_deleter() const _NOEXCEPT { | |
| 1639 | return __ptr_.second(); | |
| 1640 | } | |
| 1641 | _LIBCPP_INLINE_VISIBILITY | |
| 1642 | _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT { | |
| 1643 | return __ptr_.first() != nullptr; | |
| 1644 | } | |
| 1645 | ||
| 1646 | _LIBCPP_INLINE_VISIBILITY | |
| 1647 | pointer release() _NOEXCEPT { | |
| 1648 | pointer __t = __ptr_.first(); | |
| 1649 | __ptr_.first() = pointer(); | |
| 1650 | return __t; | |
| 1651 | } | |
| 1652 | ||
| 1653 | _LIBCPP_INLINE_VISIBILITY | |
| 1654 | void reset(pointer __p = pointer()) _NOEXCEPT { | |
| 1655 | pointer __tmp = __ptr_.first(); | |
| 1656 | __ptr_.first() = __p; | |
| 1657 | if (__tmp) | |
| 1658 | __ptr_.second()(__tmp); | |
| 1659 | } | |
| 1660 | ||
| 1661 | _LIBCPP_INLINE_VISIBILITY | |
| 1662 | void swap(unique_ptr& __u) _NOEXCEPT { | |
| 1663 | __ptr_.swap(__u.__ptr_); | |
| 1664 | } | |
| 1665 | }; | |
| 1666 | ||
| 1667 | ||
| 1668 | template <class _Tp, class _Dp> | |
| 1669 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> { | |
| 1670 | public: | |
| 1671 | typedef _Tp element_type; | |
| 1672 | typedef _Dp deleter_type; | |
| 1673 | typedef typename __pointer<_Tp, deleter_type>::type pointer; | |
| 1674 | ||
| 1675 | private: | |
| 1676 | __compressed_pair<pointer, deleter_type> __ptr_; | |
| 1677 | ||
| 1678 | template <class _From> | |
| 1679 | struct _CheckArrayPointerConversion : is_same<_From, pointer> {}; | |
| 1680 | ||
| 1681 | template <class _FromElem> | |
| 1682 | struct _CheckArrayPointerConversion<_FromElem*> | |
| 1683 | : integral_constant<bool, | |
| 1684 | is_same<_FromElem*, pointer>::value || | |
| 1685 | (is_same<pointer, element_type*>::value && | |
| 1686 | is_convertible<_FromElem(*)[], element_type(*)[]>::value) | |
| 1687 | > | |
| 1688 | {}; | |
| 1689 | ||
| 1690 | typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; | |
| 1691 | ||
| 1692 | template <bool _Dummy> | |
| 1693 | using _LValRefType _LIBCPP_NODEBUG_TYPE = | |
| 1694 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; | |
| 1695 | ||
| 1696 | template <bool _Dummy> | |
| 1697 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 1698 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; | |
| 1699 | ||
| 1700 | template <bool _Dummy> | |
| 1701 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE = | |
| 1702 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; | |
| 1703 | ||
| 1704 | template <bool _Dummy, class _Deleter = typename __dependent_type< | |
| 1705 | __identity<deleter_type>, _Dummy>::type> | |
| 1706 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE = | |
| 1707 | typename enable_if<is_default_constructible<_Deleter>::value && | |
| 1708 | !is_pointer<_Deleter>::value>::type; | |
| 1709 | ||
| 1710 | template <class _ArgType> | |
| 1711 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE = | |
| 1712 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; | |
| 1713 | ||
| 1714 | template <class _Pp> | |
| 1715 | using _EnableIfPointerConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 1716 | _CheckArrayPointerConversion<_Pp>::value | |
| 1717 | >::type; | |
| 1718 | ||
| 1719 | template <class _UPtr, class _Up, | |
| 1720 | class _ElemT = typename _UPtr::element_type> | |
| 1721 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 1722 | is_array<_Up>::value && | |
| 1723 | is_same<pointer, element_type*>::value && | |
| 1724 | is_same<typename _UPtr::pointer, _ElemT*>::value && | |
| 1725 | is_convertible<_ElemT(*)[], element_type(*)[]>::value | |
| 1726 | >::type; | |
| 1727 | ||
| 1728 | template <class _UDel> | |
| 1729 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 1730 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || | |
| 1731 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) | |
| 1732 | >::type; | |
| 1733 | ||
| 1734 | template <class _UDel> | |
| 1735 | using _EnableIfDeleterAssignable _LIBCPP_NODEBUG_TYPE = typename enable_if< | |
| 1736 | is_assignable<_Dp&, _UDel&&>::value | |
| 1737 | >::type; | |
| 1738 | ||
| 1739 | public: | |
| 1740 | template <bool _Dummy = true, | |
| 1741 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 1742 | _LIBCPP_INLINE_VISIBILITY | |
| 1743 | _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 1744 | ||
| 1745 | template <bool _Dummy = true, | |
| 1746 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > | |
| 1747 | _LIBCPP_INLINE_VISIBILITY | |
| 1748 | _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {} | |
| 1749 | ||
| 1750 | template <class _Pp, bool _Dummy = true, | |
| 1751 | class = _EnableIfDeleterDefaultConstructible<_Dummy>, | |
| 1752 | class = _EnableIfPointerConvertible<_Pp> > | |
| 1753 | _LIBCPP_INLINE_VISIBILITY | |
| 1754 | explicit unique_ptr(_Pp __p) _NOEXCEPT | |
| 1755 | : __ptr_(__p, __default_init_tag()) {} | |
| 1756 | ||
| 1757 | template <class _Pp, bool _Dummy = true, | |
| 1758 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >, | |
| 1759 | class = _EnableIfPointerConvertible<_Pp> > | |
| 1760 | _LIBCPP_INLINE_VISIBILITY | |
| 1761 | unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPT | |
| 1762 | : __ptr_(__p, __d) {} | |
| 1763 | ||
| 1764 | template <bool _Dummy = true, | |
| 1765 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > | |
| 1766 | _LIBCPP_INLINE_VISIBILITY | |
| 1767 | unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPT | |
| 1768 | : __ptr_(nullptr, __d) {} | |
| 1769 | ||
| 1770 | template <class _Pp, bool _Dummy = true, | |
| 1771 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >, | |
| 1772 | class = _EnableIfPointerConvertible<_Pp> > | |
| 1773 | _LIBCPP_INLINE_VISIBILITY | |
| 1774 | unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT | |
| 1775 | : __ptr_(__p, _VSTD::move(__d)) { | |
| 1776 | static_assert(!is_reference<deleter_type>::value, | |
| 1777 | "rvalue deleter bound to reference"); | |
| 1778 | } | |
| 1779 | ||
| 1780 | template <bool _Dummy = true, | |
| 1781 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > | |
| 1782 | _LIBCPP_INLINE_VISIBILITY | |
| 1783 | unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPT | |
| 1784 | : __ptr_(nullptr, _VSTD::move(__d)) { | |
| 1785 | static_assert(!is_reference<deleter_type>::value, | |
| 1786 | "rvalue deleter bound to reference"); | |
| 1787 | } | |
| 1788 | ||
| 1789 | template <class _Pp, bool _Dummy = true, | |
| 1790 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >, | |
| 1791 | class = _EnableIfPointerConvertible<_Pp> > | |
| 1792 | _LIBCPP_INLINE_VISIBILITY | |
| 1793 | unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete; | |
| 1794 | ||
| 1795 | _LIBCPP_INLINE_VISIBILITY | |
| 1796 | unique_ptr(unique_ptr&& __u) _NOEXCEPT | |
| 1797 | : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { | |
| 1798 | } | |
| 1799 | ||
| 1800 | _LIBCPP_INLINE_VISIBILITY | |
| 1801 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { | |
| 1802 | reset(__u.release()); | |
| 1803 | __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter()); | |
| 1804 | return *this; | |
| 1805 | } | |
| 1806 | ||
| 1807 | template <class _Up, class _Ep, | |
| 1808 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 1809 | class = _EnableIfDeleterConvertible<_Ep> | |
| 1810 | > | |
| 1811 | _LIBCPP_INLINE_VISIBILITY | |
| 1812 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT | |
| 1813 | : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) { | |
| 1814 | } | |
| 1815 | ||
| 1816 | template <class _Up, class _Ep, | |
| 1817 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, | |
| 1818 | class = _EnableIfDeleterAssignable<_Ep> | |
| 1819 | > | |
| 1820 | _LIBCPP_INLINE_VISIBILITY | |
| 1821 | unique_ptr& | |
| 1822 | operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { | |
| 1823 | reset(__u.release()); | |
| 1824 | __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); | |
| 1825 | return *this; | |
| 1826 | } | |
| 1827 | ||
| 1828 | #ifdef _LIBCPP_CXX03_LANG | |
| 1829 | unique_ptr(unique_ptr const&) = delete; | |
| 1830 | unique_ptr& operator=(unique_ptr const&) = delete; | |
| 1831 | #endif | |
| 1832 | ||
| 1833 | public: | |
| 1834 | _LIBCPP_INLINE_VISIBILITY | |
| 1835 | ~unique_ptr() { reset(); } | |
| 1836 | ||
| 1837 | _LIBCPP_INLINE_VISIBILITY | |
| 1838 | unique_ptr& operator=(nullptr_t) _NOEXCEPT { | |
| 1839 | reset(); | |
| 1840 | return *this; | |
| 1841 | } | |
| 1842 | ||
| 1843 | _LIBCPP_INLINE_VISIBILITY | |
| 1844 | typename add_lvalue_reference<_Tp>::type | |
| 1845 | operator[](size_t __i) const { | |
| 1846 | return __ptr_.first()[__i]; | |
| 1847 | } | |
| 1848 | _LIBCPP_INLINE_VISIBILITY | |
| 1849 | pointer get() const _NOEXCEPT { | |
| 1850 | return __ptr_.first(); | |
| 1851 | } | |
| 1852 | ||
| 1853 | _LIBCPP_INLINE_VISIBILITY | |
| 1854 | deleter_type& get_deleter() _NOEXCEPT { | |
| 1855 | return __ptr_.second(); | |
| 1856 | } | |
| 1857 | ||
| 1858 | _LIBCPP_INLINE_VISIBILITY | |
| 1859 | const deleter_type& get_deleter() const _NOEXCEPT { | |
| 1860 | return __ptr_.second(); | |
| 1861 | } | |
| 1862 | _LIBCPP_INLINE_VISIBILITY | |
| 1863 | _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT { | |
| 1864 | return __ptr_.first() != nullptr; | |
| 1865 | } | |
| 1866 | ||
| 1867 | _LIBCPP_INLINE_VISIBILITY | |
| 1868 | pointer release() _NOEXCEPT { | |
| 1869 | pointer __t = __ptr_.first(); | |
| 1870 | __ptr_.first() = pointer(); | |
| 1871 | return __t; | |
| 1872 | } | |
| 1873 | ||
| 1874 | template <class _Pp> | |
| 1875 | _LIBCPP_INLINE_VISIBILITY | |
| 1876 | typename enable_if< | |
| 1877 | _CheckArrayPointerConversion<_Pp>::value | |
| 1878 | >::type | |
| 1879 | reset(_Pp __p) _NOEXCEPT { | |
| 1880 | pointer __tmp = __ptr_.first(); | |
| 1881 | __ptr_.first() = __p; | |
| 1882 | if (__tmp) | |
| 1883 | __ptr_.second()(__tmp); | |
| 1884 | } | |
| 1885 | ||
| 1886 | _LIBCPP_INLINE_VISIBILITY | |
| 1887 | void reset(nullptr_t = nullptr) _NOEXCEPT { | |
| 1888 | pointer __tmp = __ptr_.first(); | |
| 1889 | __ptr_.first() = nullptr; | |
| 1890 | if (__tmp) | |
| 1891 | __ptr_.second()(__tmp); | |
| 1892 | } | |
| 1893 | ||
| 1894 | _LIBCPP_INLINE_VISIBILITY | |
| 1895 | void swap(unique_ptr& __u) _NOEXCEPT { | |
| 1896 | __ptr_.swap(__u.__ptr_); | |
| 1897 | } | |
| 1898 | ||
| 1899 | }; | |
| 1900 | ||
| 1901 | template <class _Tp, class _Dp> | |
| 1902 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1903 | typename enable_if< | |
| 1904 | __is_swappable<_Dp>::value, | |
| 1905 | void | |
| 1906 | >::type | |
| 1907 | swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT {__x.swap(__y);} | |
| 1908 | ||
| 1909 | template <class _T1, class _D1, class _T2, class _D2> | |
| 1910 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1911 | bool | |
| 1912 | operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() == __y.get();} | |
| 1913 | ||
| 1914 | template <class _T1, class _D1, class _T2, class _D2> | |
| 1915 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1916 | bool | |
| 1917 | operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x == __y);} | |
| 1918 | ||
| 1919 | template <class _T1, class _D1, class _T2, class _D2> | |
| 1920 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1921 | bool | |
| 1922 | operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) | |
| 1923 | { | |
| 1924 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; | |
| 1925 | typedef typename unique_ptr<_T2, _D2>::pointer _P2; | |
| 1926 | typedef typename common_type<_P1, _P2>::type _Vp; | |
| 1927 | return less<_Vp>()(__x.get(), __y.get()); | |
| 1928 | } | |
| 1929 | ||
| 1930 | template <class _T1, class _D1, class _T2, class _D2> | |
| 1931 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1932 | bool | |
| 1933 | operator> (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __y < __x;} | |
| 1934 | ||
| 1935 | template <class _T1, class _D1, class _T2, class _D2> | |
| 1936 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1937 | bool | |
| 1938 | operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__y < __x);} | |
| 1939 | ||
| 1940 | template <class _T1, class _D1, class _T2, class _D2> | |
| 1941 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1942 | bool | |
| 1943 | operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} | |
| 1944 | ||
| 1945 | template <class _T1, class _D1> | |
| 1946 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1947 | bool | |
| 1948 | operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT | |
| 1949 | { | |
| 1950 | return !__x; | |
| 1951 | } | |
| 1952 | ||
| 1953 | template <class _T1, class _D1> | |
| 1954 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1955 | bool | |
| 1956 | operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT | |
| 1957 | { | |
| 1958 | return !__x; | |
| 1959 | } | |
| 1960 | ||
| 1961 | template <class _T1, class _D1> | |
| 1962 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1963 | bool | |
| 1964 | operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT | |
| 1965 | { | |
| 1966 | return static_cast<bool>(__x); | |
| 1967 | } | |
| 1968 | ||
| 1969 | template <class _T1, class _D1> | |
| 1970 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1971 | bool | |
| 1972 | operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT | |
| 1973 | { | |
| 1974 | return static_cast<bool>(__x); | |
| 1975 | } | |
| 1976 | ||
| 1977 | template <class _T1, class _D1> | |
| 1978 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1979 | bool | |
| 1980 | operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 1981 | { | |
| 1982 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; | |
| 1983 | return less<_P1>()(__x.get(), nullptr); | |
| 1984 | } | |
| 1985 | ||
| 1986 | template <class _T1, class _D1> | |
| 1987 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1988 | bool | |
| 1989 | operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 1990 | { | |
| 1991 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; | |
| 1992 | return less<_P1>()(nullptr, __x.get()); | |
| 1993 | } | |
| 1994 | ||
| 1995 | template <class _T1, class _D1> | |
| 1996 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1997 | bool | |
| 1998 | operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 1999 | { | |
| 2000 | return nullptr < __x; | |
| 2001 | } | |
| 2002 | ||
| 2003 | template <class _T1, class _D1> | |
| 2004 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2005 | bool | |
| 2006 | operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 2007 | { | |
| 2008 | return __x < nullptr; | |
| 2009 | } | |
| 2010 | ||
| 2011 | template <class _T1, class _D1> | |
| 2012 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2013 | bool | |
| 2014 | operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 2015 | { | |
| 2016 | return !(nullptr < __x); | |
| 2017 | } | |
| 2018 | ||
| 2019 | template <class _T1, class _D1> | |
| 2020 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2021 | bool | |
| 2022 | operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 2023 | { | |
| 2024 | return !(__x < nullptr); | |
| 2025 | } | |
| 2026 | ||
| 2027 | template <class _T1, class _D1> | |
| 2028 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2029 | bool | |
| 2030 | operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) | |
| 2031 | { | |
| 2032 | return !(__x < nullptr); | |
| 2033 | } | |
| 2034 | ||
| 2035 | template <class _T1, class _D1> | |
| 2036 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2037 | bool | |
| 2038 | operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) | |
| 2039 | { | |
| 2040 | return !(nullptr < __x); | |
| 2041 | } | |
| 2042 | ||
| 2043 | #if _LIBCPP_STD_VER > 11 | |
| 2044 | ||
| 2045 | template<class _Tp> | |
| 2046 | struct __unique_if | |
| 2047 | { | |
| 2048 | typedef unique_ptr<_Tp> __unique_single; | |
| 2049 | }; | |
| 2050 | ||
| 2051 | template<class _Tp> | |
| 2052 | struct __unique_if<_Tp[]> | |
| 2053 | { | |
| 2054 | typedef unique_ptr<_Tp[]> __unique_array_unknown_bound; | |
| 2055 | }; | |
| 2056 | ||
| 2057 | template<class _Tp, size_t _Np> | |
| 2058 | struct __unique_if<_Tp[_Np]> | |
| 2059 | { | |
| 2060 | typedef void __unique_array_known_bound; | |
| 2061 | }; | |
| 2062 | ||
| 2063 | template<class _Tp, class... _Args> | |
| 2064 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2065 | typename __unique_if<_Tp>::__unique_single | |
| 2066 | make_unique(_Args&&... __args) | |
| 2067 | { | |
| 2068 | return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...)); | |
| 2069 | } | |
| 2070 | ||
| 2071 | template<class _Tp> | |
| 2072 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2073 | typename __unique_if<_Tp>::__unique_array_unknown_bound | |
| 2074 | make_unique(size_t __n) | |
| 2075 | { | |
| 2076 | typedef typename remove_extent<_Tp>::type _Up; | |
| 2077 | return unique_ptr<_Tp>(new _Up[__n]()); | |
| 2078 | } | |
| 2079 | ||
| 2080 | template<class _Tp, class... _Args> | |
| 2081 | typename __unique_if<_Tp>::__unique_array_known_bound | |
| 2082 | make_unique(_Args&&...) = delete; | |
| 2083 | ||
| 2084 | #endif // _LIBCPP_STD_VER > 11 | |
| 2085 | ||
| 2086 | template <class _Tp, class _Dp> | |
| 2087 | #ifdef _LIBCPP_CXX03_LANG | |
| 2088 | struct _LIBCPP_TEMPLATE_VIS hash<unique_ptr<_Tp, _Dp> > | |
| 2089 | #else | |
| 2090 | struct _LIBCPP_TEMPLATE_VIS hash<__enable_hash_helper< | |
| 2091 | unique_ptr<_Tp, _Dp>, typename unique_ptr<_Tp, _Dp>::pointer> > | |
| 2092 | #endif | |
| 2093 | { | |
| 2094 | typedef unique_ptr<_Tp, _Dp> argument_type; | |
| 2095 | typedef size_t result_type; | |
| 2096 | _LIBCPP_INLINE_VISIBILITY | |
| 2097 | result_type operator()(const argument_type& __ptr) const | |
| 2098 | { | |
| 2099 | typedef typename argument_type::pointer pointer; | |
| 2100 | return hash<pointer>()(__ptr.get()); | |
| 2101 | } | |
| 2102 | }; | |
| 2103 | ||
| 2104 | struct __destruct_n | |
| 2105 | { | |
| 2106 | private: | |
| 2107 | size_t __size_; | |
| 2108 | ||
| 2109 | template <class _Tp> | |
| 2110 | _LIBCPP_INLINE_VISIBILITY void __process(_Tp* __p, false_type) _NOEXCEPT | |
| 2111 | {for (size_t __i = 0; __i < __size_; ++__i, ++__p) __p->~_Tp();} | |
| 2112 | ||
| 2113 | template <class _Tp> | |
| 2114 | _LIBCPP_INLINE_VISIBILITY void __process(_Tp*, true_type) _NOEXCEPT | |
| 2115 | {} | |
| 2116 | ||
| 2117 | _LIBCPP_INLINE_VISIBILITY void __incr(false_type) _NOEXCEPT | |
| 2118 | {++__size_;} | |
| 2119 | _LIBCPP_INLINE_VISIBILITY void __incr(true_type) _NOEXCEPT | |
| 2120 | {} | |
| 2121 | ||
| 2122 | _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, false_type) _NOEXCEPT | |
| 2123 | {__size_ = __s;} | |
| 2124 | _LIBCPP_INLINE_VISIBILITY void __set(size_t, true_type) _NOEXCEPT | |
| 2125 | {} | |
| 2126 | public: | |
| 2127 | _LIBCPP_INLINE_VISIBILITY explicit __destruct_n(size_t __s) _NOEXCEPT | |
| 2128 | : __size_(__s) {} | |
| 2129 | ||
| 2130 | template <class _Tp> | |
| 2131 | _LIBCPP_INLINE_VISIBILITY void __incr() _NOEXCEPT | |
| 2132 | {__incr(integral_constant<bool, is_trivially_destructible<_Tp>::value>());} | |
| 2133 | ||
| 2134 | template <class _Tp> | |
| 2135 | _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, _Tp*) _NOEXCEPT | |
| 2136 | {__set(__s, integral_constant<bool, is_trivially_destructible<_Tp>::value>());} | |
| 2137 | ||
| 2138 | template <class _Tp> | |
| 2139 | _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) _NOEXCEPT | |
| 2140 | {__process(__p, integral_constant<bool, is_trivially_destructible<_Tp>::value>());} | |
| 2141 | }; | |
| 2142 | ||
| 2143 | template <class _Alloc> | |
| 2144 | class __allocator_destructor | |
| 2145 | { | |
| 2146 | typedef _LIBCPP_NODEBUG_TYPE allocator_traits<_Alloc> __alloc_traits; | |
| 2147 | public: | |
| 2148 | typedef _LIBCPP_NODEBUG_TYPE typename __alloc_traits::pointer pointer; | |
| 2149 | typedef _LIBCPP_NODEBUG_TYPE typename __alloc_traits::size_type size_type; | |
| 2150 | private: | |
| 2151 | _Alloc& __alloc_; | |
| 2152 | size_type __s_; | |
| 2153 | public: | |
| 2154 | _LIBCPP_INLINE_VISIBILITY __allocator_destructor(_Alloc& __a, size_type __s) | |
| 2155 | _NOEXCEPT | |
| 2156 | : __alloc_(__a), __s_(__s) {} | |
| 2157 | _LIBCPP_INLINE_VISIBILITY | |
| 2158 | void operator()(pointer __p) _NOEXCEPT | |
| 2159 | {__alloc_traits::deallocate(__alloc_, __p, __s_);} | |
| 2160 | }; | |
| 2161 | ||
| 2162 | template <class _InputIterator, class _ForwardIterator> | |
| 2163 | _ForwardIterator | |
| 2164 | uninitialized_copy(_InputIterator __f, _InputIterator __l, _ForwardIterator __r) | |
| 2165 | { | |
| 2166 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 2167 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2168 | _ForwardIterator __s = __r; | |
| 2169 | try | |
| 2170 | { | |
| 2171 | #endif | |
| 2172 | for (; __f != __l; ++__f, (void) ++__r) | |
| 2173 | ::new ((void*)_VSTD::addressof(*__r)) value_type(*__f); | |
| 2174 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2175 | } | |
| 2176 | catch (...) | |
| 2177 | { | |
| 2178 | for (; __s != __r; ++__s) | |
| 2179 | __s->~value_type(); | |
| 2180 | throw; | |
| 2181 | } | |
| 2182 | #endif | |
| 2183 | return __r; | |
| 2184 | } | |
| 2185 | ||
| 2186 | template <class _InputIterator, class _Size, class _ForwardIterator> | |
| 2187 | _ForwardIterator | |
| 2188 | uninitialized_copy_n(_InputIterator __f, _Size __n, _ForwardIterator __r) | |
| 2189 | { | |
| 2190 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 2191 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2192 | _ForwardIterator __s = __r; | |
| 2193 | try | |
| 2194 | { | |
| 2195 | #endif | |
| 2196 | for (; __n > 0; ++__f, (void) ++__r, (void) --__n) | |
| 2197 | ::new ((void*)_VSTD::addressof(*__r)) value_type(*__f); | |
| 2198 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2199 | } | |
| 2200 | catch (...) | |
| 2201 | { | |
| 2202 | for (; __s != __r; ++__s) | |
| 2203 | __s->~value_type(); | |
| 2204 | throw; | |
| 2205 | } | |
| 2206 | #endif | |
| 2207 | return __r; | |
| 2208 | } | |
| 2209 | ||
| 2210 | template <class _ForwardIterator, class _Tp> | |
| 2211 | void | |
| 2212 | uninitialized_fill(_ForwardIterator __f, _ForwardIterator __l, const _Tp& __x) | |
| 2213 | { | |
| 2214 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 2215 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2216 | _ForwardIterator __s = __f; | |
| 2217 | try | |
| 2218 | { | |
| 2219 | #endif | |
| 2220 | for (; __f != __l; ++__f) | |
| 2221 | ::new ((void*)_VSTD::addressof(*__f)) value_type(__x); | |
| 2222 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2223 | } | |
| 2224 | catch (...) | |
| 2225 | { | |
| 2226 | for (; __s != __f; ++__s) | |
| 2227 | __s->~value_type(); | |
| 2228 | throw; | |
| 2229 | } | |
| 2230 | #endif | |
| 2231 | } | |
| 2232 | ||
| 2233 | template <class _ForwardIterator, class _Size, class _Tp> | |
| 2234 | _ForwardIterator | |
| 2235 | uninitialized_fill_n(_ForwardIterator __f, _Size __n, const _Tp& __x) | |
| 2236 | { | |
| 2237 | typedef typename iterator_traits<_ForwardIterator>::value_type value_type; | |
| 2238 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2239 | _ForwardIterator __s = __f; | |
| 2240 | try | |
| 2241 | { | |
| 2242 | #endif | |
| 2243 | for (; __n > 0; ++__f, (void) --__n) | |
| 2244 | ::new ((void*)_VSTD::addressof(*__f)) value_type(__x); | |
| 2245 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2246 | } | |
| 2247 | catch (...) | |
| 2248 | { | |
| 2249 | for (; __s != __f; ++__s) | |
| 2250 | __s->~value_type(); | |
| 2251 | throw; | |
| 2252 | } | |
| 2253 | #endif | |
| 2254 | return __f; | |
| 2255 | } | |
| 2256 | ||
| 2257 | #if _LIBCPP_STD_VER > 14 | |
| 2258 | ||
| 2259 | template <class _ForwardIterator> | |
| 2260 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2261 | void destroy(_ForwardIterator __first, _ForwardIterator __last) { | |
| 2262 | for (; __first != __last; ++__first) | |
| 2263 | _VSTD::destroy_at(_VSTD::addressof(*__first)); | |
| 2264 | } | |
| 2265 | ||
| 2266 | template <class _ForwardIterator, class _Size> | |
| 2267 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 2268 | _ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) { | |
| 2269 | for (; __n > 0; (void)++__first, --__n) | |
| 2270 | _VSTD::destroy_at(_VSTD::addressof(*__first)); | |
| 2271 | return __first; | |
| 2272 | } | |
| 2273 | ||
| 2274 | template <class _ForwardIterator> | |
| 2275 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2276 | void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) { | |
| 2277 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 2278 | auto __idx = __first; | |
| 2279 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2280 | try { | |
| 2281 | #endif | |
| 2282 | for (; __idx != __last; ++__idx) | |
| 2283 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt; | |
| 2284 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2285 | } catch (...) { | |
| 2286 | _VSTD::destroy(__first, __idx); | |
| 2287 | throw; | |
| 2288 | } | |
| 2289 | #endif | |
| 2290 | } | |
| 2291 | ||
| 2292 | template <class _ForwardIterator, class _Size> | |
| 2293 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2294 | _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { | |
| 2295 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 2296 | auto __idx = __first; | |
| 2297 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2298 | try { | |
| 2299 | #endif | |
| 2300 | for (; __n > 0; (void)++__idx, --__n) | |
| 2301 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt; | |
| 2302 | return __idx; | |
| 2303 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2304 | } catch (...) { | |
| 2305 | _VSTD::destroy(__first, __idx); | |
| 2306 | throw; | |
| 2307 | } | |
| 2308 | #endif | |
| 2309 | } | |
| 2310 | ||
| 2311 | ||
| 2312 | template <class _ForwardIterator> | |
| 2313 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2314 | void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) { | |
| 2315 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 2316 | auto __idx = __first; | |
| 2317 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2318 | try { | |
| 2319 | #endif | |
| 2320 | for (; __idx != __last; ++__idx) | |
| 2321 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(); | |
| 2322 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2323 | } catch (...) { | |
| 2324 | _VSTD::destroy(__first, __idx); | |
| 2325 | throw; | |
| 2326 | } | |
| 2327 | #endif | |
| 2328 | } | |
| 2329 | ||
| 2330 | template <class _ForwardIterator, class _Size> | |
| 2331 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2332 | _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { | |
| 2333 | using _Vt = typename iterator_traits<_ForwardIterator>::value_type; | |
| 2334 | auto __idx = __first; | |
| 2335 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2336 | try { | |
| 2337 | #endif | |
| 2338 | for (; __n > 0; (void)++__idx, --__n) | |
| 2339 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(); | |
| 2340 | return __idx; | |
| 2341 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2342 | } catch (...) { | |
| 2343 | _VSTD::destroy(__first, __idx); | |
| 2344 | throw; | |
| 2345 | } | |
| 2346 | #endif | |
| 2347 | } | |
| 2348 | ||
| 2349 | ||
| 2350 | template <class _InputIt, class _ForwardIt> | |
| 2351 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2352 | _ForwardIt uninitialized_move(_InputIt __first, _InputIt __last, _ForwardIt __first_res) { | |
| 2353 | using _Vt = typename iterator_traits<_ForwardIt>::value_type; | |
| 2354 | auto __idx = __first_res; | |
| 2355 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2356 | try { | |
| 2357 | #endif | |
| 2358 | for (; __first != __last; (void)++__idx, ++__first) | |
| 2359 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(_VSTD::move(*__first)); | |
| 2360 | return __idx; | |
| 2361 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2362 | } catch (...) { | |
| 2363 | _VSTD::destroy(__first_res, __idx); | |
| 2364 | throw; | |
| 2365 | } | |
| 2366 | #endif | |
| 2367 | } | |
| 2368 | ||
| 2369 | template <class _InputIt, class _Size, class _ForwardIt> | |
| 2370 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2371 | pair<_InputIt, _ForwardIt> | |
| 2372 | uninitialized_move_n(_InputIt __first, _Size __n, _ForwardIt __first_res) { | |
| 2373 | using _Vt = typename iterator_traits<_ForwardIt>::value_type; | |
| 2374 | auto __idx = __first_res; | |
| 2375 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2376 | try { | |
| 2377 | #endif | |
| 2378 | for (; __n > 0; ++__idx, (void)++__first, --__n) | |
| 2379 | ::new ((void*)_VSTD::addressof(*__idx)) _Vt(_VSTD::move(*__first)); | |
| 2380 | return {__first, __idx}; | |
| 2381 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2382 | } catch (...) { | |
| 2383 | _VSTD::destroy(__first_res, __idx); | |
| 2384 | throw; | |
| 2385 | } | |
| 2386 | #endif | |
| 2387 | } | |
| 2388 | ||
| 2389 | ||
| 2390 | #endif // _LIBCPP_STD_VER > 14 | |
| 2391 | ||
| 2392 | // NOTE: Relaxed and acq/rel atomics (for increment and decrement respectively) | |
| 2393 | // should be sufficient for thread safety. | |
| 2394 | // See https://bugs.llvm.org/show_bug.cgi?id=22803 | |
| 2395 | #if defined(__clang__) && __has_builtin(__atomic_add_fetch) \ | |
| 2396 | && defined(__ATOMIC_RELAXED) \ | |
| 2397 | && defined(__ATOMIC_ACQ_REL) | |
| 2398 | # define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT | |
| 2399 | #elif defined(_LIBCPP_COMPILER_GCC) | |
| 2400 | # define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT | |
| 2401 | #endif | |
| 2402 | ||
| 2403 | template <class _Tp> | |
| 2404 | inline _LIBCPP_INLINE_VISIBILITY _Tp | |
| 2405 | __libcpp_atomic_refcount_increment(_Tp& __t) _NOEXCEPT | |
| 2406 | { | |
| 2407 | #if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS) | |
| 2408 | return __atomic_add_fetch(&__t, 1, __ATOMIC_RELAXED); | |
| 2409 | #else | |
| 2410 | return __t += 1; | |
| 2411 | #endif | |
| 2412 | } | |
| 2413 | ||
| 2414 | template <class _Tp> | |
| 2415 | inline _LIBCPP_INLINE_VISIBILITY _Tp | |
| 2416 | __libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT | |
| 2417 | { | |
| 2418 | #if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS) | |
| 2419 | return __atomic_add_fetch(&__t, -1, __ATOMIC_ACQ_REL); | |
| 2420 | #else | |
| 2421 | return __t -= 1; | |
| 2422 | #endif | |
| 2423 | } | |
| 2424 | ||
| 2425 | class _LIBCPP_EXCEPTION_ABI bad_weak_ptr | |
| 2426 | : public std::exception | |
| 2427 | { | |
| 2428 | public: | |
| 2429 | bad_weak_ptr() _NOEXCEPT = default; | |
| 2430 | bad_weak_ptr(const bad_weak_ptr&) _NOEXCEPT = default; | |
| 2431 | virtual ~bad_weak_ptr() _NOEXCEPT; | |
| 2432 | virtual const char* what() const _NOEXCEPT; | |
| 2433 | }; | |
| 2434 | ||
| 2435 | _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY | |
| 2436 | void __throw_bad_weak_ptr() | |
| 2437 | { | |
| 2438 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2439 | throw bad_weak_ptr(); | |
| 2440 | #else | |
| 2441 | _VSTD::abort(); | |
| 2442 | #endif | |
| 2443 | } | |
| 2444 | ||
| 2445 | template<class _Tp> class _LIBCPP_TEMPLATE_VIS weak_ptr; | |
| 2446 | ||
| 2447 | class _LIBCPP_TYPE_VIS __shared_count | |
| 2448 | { | |
| 2449 | __shared_count(const __shared_count&); | |
| 2450 | __shared_count& operator=(const __shared_count&); | |
| 2451 | ||
| 2452 | protected: | |
| 2453 | long __shared_owners_; | |
| 2454 | virtual ~__shared_count(); | |
| 2455 | private: | |
| 2456 | virtual void __on_zero_shared() _NOEXCEPT = 0; | |
| 2457 | ||
| 2458 | public: | |
| 2459 | _LIBCPP_INLINE_VISIBILITY | |
| 2460 | explicit __shared_count(long __refs = 0) _NOEXCEPT | |
| 2461 | : __shared_owners_(__refs) {} | |
| 2462 | ||
| 2463 | #if defined(_LIBCPP_BUILDING_LIBRARY) && \ | |
| 2464 | defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) | |
| 2465 | void __add_shared() _NOEXCEPT; | |
| 2466 | bool __release_shared() _NOEXCEPT; | |
| 2467 | #else | |
| 2468 | _LIBCPP_INLINE_VISIBILITY | |
| 2469 | void __add_shared() _NOEXCEPT { | |
| 2470 | __libcpp_atomic_refcount_increment(__shared_owners_); | |
| 2471 | } | |
| 2472 | _LIBCPP_INLINE_VISIBILITY | |
| 2473 | bool __release_shared() _NOEXCEPT { | |
| 2474 | if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) { | |
| 2475 | __on_zero_shared(); | |
| 2476 | return true; | |
| 2477 | } | |
| 2478 | return false; | |
| 2479 | } | |
| 2480 | #endif | |
| 2481 | _LIBCPP_INLINE_VISIBILITY | |
| 2482 | long use_count() const _NOEXCEPT { | |
| 2483 | return __libcpp_relaxed_load(&__shared_owners_) + 1; | |
| 2484 | } | |
| 2485 | }; | |
| 2486 | ||
| 2487 | class _LIBCPP_TYPE_VIS __shared_weak_count | |
| 2488 | : private __shared_count | |
| 2489 | { | |
| 2490 | long __shared_weak_owners_; | |
| 2491 | ||
| 2492 | public: | |
| 2493 | _LIBCPP_INLINE_VISIBILITY | |
| 2494 | explicit __shared_weak_count(long __refs = 0) _NOEXCEPT | |
| 2495 | : __shared_count(__refs), | |
| 2496 | __shared_weak_owners_(__refs) {} | |
| 2497 | protected: | |
| 2498 | virtual ~__shared_weak_count(); | |
| 2499 | ||
| 2500 | public: | |
| 2501 | #if defined(_LIBCPP_BUILDING_LIBRARY) && \ | |
| 2502 | defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) | |
| 2503 | void __add_shared() _NOEXCEPT; | |
| 2504 | void __add_weak() _NOEXCEPT; | |
| 2505 | void __release_shared() _NOEXCEPT; | |
| 2506 | #else | |
| 2507 | _LIBCPP_INLINE_VISIBILITY | |
| 2508 | void __add_shared() _NOEXCEPT { | |
| 2509 | __shared_count::__add_shared(); | |
| 2510 | } | |
| 2511 | _LIBCPP_INLINE_VISIBILITY | |
| 2512 | void __add_weak() _NOEXCEPT { | |
| 2513 | __libcpp_atomic_refcount_increment(__shared_weak_owners_); | |
| 2514 | } | |
| 2515 | _LIBCPP_INLINE_VISIBILITY | |
| 2516 | void __release_shared() _NOEXCEPT { | |
| 2517 | if (__shared_count::__release_shared()) | |
| 2518 | __release_weak(); | |
| 2519 | } | |
| 2520 | #endif | |
| 2521 | void __release_weak() _NOEXCEPT; | |
| 2522 | _LIBCPP_INLINE_VISIBILITY | |
| 2523 | long use_count() const _NOEXCEPT {return __shared_count::use_count();} | |
| 2524 | __shared_weak_count* lock() _NOEXCEPT; | |
| 2525 | ||
| 2526 | virtual const void* __get_deleter(const type_info&) const _NOEXCEPT; | |
| 2527 | private: | |
| 2528 | virtual void __on_zero_shared_weak() _NOEXCEPT = 0; | |
| 2529 | }; | |
| 2530 | ||
| 2531 | template <class _Tp, class _Dp, class _Alloc> | |
| 2532 | class __shared_ptr_pointer | |
| 2533 | : public __shared_weak_count | |
| 2534 | { | |
| 2535 | __compressed_pair<__compressed_pair<_Tp, _Dp>, _Alloc> __data_; | |
| 2536 | public: | |
| 2537 | _LIBCPP_INLINE_VISIBILITY | |
| 2538 | __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a) | |
| 2539 | : __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {} | |
| 2540 | ||
| 2541 | #ifndef _LIBCPP_NO_RTTI | |
| 2542 | virtual const void* __get_deleter(const type_info&) const _NOEXCEPT; | |
| 2543 | #endif | |
| 2544 | ||
| 2545 | private: | |
| 2546 | virtual void __on_zero_shared() _NOEXCEPT; | |
| 2547 | virtual void __on_zero_shared_weak() _NOEXCEPT; | |
| 2548 | }; | |
| 2549 | ||
| 2550 | #ifndef _LIBCPP_NO_RTTI | |
| 2551 | ||
| 2552 | template <class _Tp, class _Dp, class _Alloc> | |
| 2553 | const void* | |
| 2554 | __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) const _NOEXCEPT | |
| 2555 | { | |
| 2556 | return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : nullptr; | |
| 2557 | } | |
| 2558 | ||
| 2559 | #endif // _LIBCPP_NO_RTTI | |
| 2560 | ||
| 2561 | template <class _Tp, class _Dp, class _Alloc> | |
| 2562 | void | |
| 2563 | __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared() _NOEXCEPT | |
| 2564 | { | |
| 2565 | __data_.first().second()(__data_.first().first()); | |
| 2566 | __data_.first().second().~_Dp(); | |
| 2567 | } | |
| 2568 | ||
| 2569 | template <class _Tp, class _Dp, class _Alloc> | |
| 2570 | void | |
| 2571 | __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT | |
| 2572 | { | |
| 2573 | typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_pointer>::type _Al; | |
| 2574 | typedef allocator_traits<_Al> _ATraits; | |
| 2575 | typedef pointer_traits<typename _ATraits::pointer> _PTraits; | |
| 2576 | ||
| 2577 | _Al __a(__data_.second()); | |
| 2578 | __data_.second().~_Alloc(); | |
| 2579 | __a.deallocate(_PTraits::pointer_to(*this), 1); | |
| 2580 | } | |
| 2581 | ||
| 2582 | template <class _Tp, class _Alloc> | |
| 2583 | struct __shared_ptr_emplace | |
| 2584 | : __shared_weak_count | |
| 2585 | { | |
| 2586 | template<class ..._Args> | |
| 2587 | _LIBCPP_HIDE_FROM_ABI | |
| 2588 | explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...__args) | |
| 2589 | : __storage_(_VSTD::move(__a)) | |
| 2590 | { | |
| 2591 | #if _LIBCPP_STD_VER > 17 | |
| 2592 | using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; | |
| 2593 | _TpAlloc __tmp(*__get_alloc()); | |
| 2594 | allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); | |
| 2595 | #else | |
| 2596 | ::new ((void*)__get_elem()) _Tp(_VSTD::forward<_Args>(__args)...); | |
| 2597 | #endif | |
| 2598 | } | |
| 2599 | ||
| 2600 | _LIBCPP_HIDE_FROM_ABI | |
| 2601 | _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); } | |
| 2602 | ||
| 2603 | _LIBCPP_HIDE_FROM_ABI | |
| 2604 | _Tp* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); } | |
| 2605 | ||
| 2606 | private: | |
| 2607 | virtual void __on_zero_shared() _NOEXCEPT { | |
| 2608 | #if _LIBCPP_STD_VER > 17 | |
| 2609 | using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; | |
| 2610 | _TpAlloc __tmp(*__get_alloc()); | |
| 2611 | allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); | |
| 2612 | #else | |
| 2613 | __get_elem()->~_Tp(); | |
| 2614 | #endif | |
| 2615 | } | |
| 2616 | ||
| 2617 | virtual void __on_zero_shared_weak() _NOEXCEPT { | |
| 2618 | using _ControlBlockAlloc = typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type; | |
| 2619 | using _ControlBlockPointer = typename allocator_traits<_ControlBlockAlloc>::pointer; | |
| 2620 | _ControlBlockAlloc __tmp(*__get_alloc()); | |
| 2621 | __storage_.~_Storage(); | |
| 2622 | allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, | |
| 2623 | pointer_traits<_ControlBlockPointer>::pointer_to(*this), 1); | |
| 2624 | } | |
| 2625 | ||
| 2626 | // This class implements the control block for non-array shared pointers created | |
| 2627 | // through `std::allocate_shared` and `std::make_shared`. | |
| 2628 | // | |
| 2629 | // In previous versions of the library, we used a compressed pair to store | |
| 2630 | // both the _Alloc and the _Tp. This implies using EBO, which is incompatible | |
| 2631 | // with Allocator construction for _Tp. To allow implementing P0674 in C++20, | |
| 2632 | // we now use a properly aligned char buffer while making sure that we maintain | |
| 2633 | // the same layout that we had when we used a compressed pair. | |
| 2634 | using _CompressedPair = __compressed_pair<_Alloc, _Tp>; | |
| 2635 | struct _ALIGNAS_TYPE(_CompressedPair) _Storage { | |
| 2636 | char __blob_[sizeof(_CompressedPair)]; | |
| 2637 | ||
| 2638 | _LIBCPP_HIDE_FROM_ABI explicit _Storage(_Alloc&& __a) { | |
| 2639 | ::new ((void*)__get_alloc()) _Alloc(_VSTD::move(__a)); | |
| 2640 | } | |
| 2641 | _LIBCPP_HIDE_FROM_ABI ~_Storage() { | |
| 2642 | __get_alloc()->~_Alloc(); | |
| 2643 | } | |
| 2644 | _Alloc* __get_alloc() _NOEXCEPT { | |
| 2645 | _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); | |
| 2646 | typename _CompressedPair::_Base1* __first = _CompressedPair::__get_first_base(__as_pair); | |
| 2647 | _Alloc *__alloc = reinterpret_cast<_Alloc*>(__first); | |
| 2648 | return __alloc; | |
| 2649 | } | |
| 2650 | _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { | |
| 2651 | _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); | |
| 2652 | typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair); | |
| 2653 | _Tp *__elem = reinterpret_cast<_Tp*>(__second); | |
| 2654 | return __elem; | |
| 2655 | } | |
| 2656 | }; | |
| 2657 | ||
| 2658 | static_assert(_LIBCPP_ALIGNOF(_Storage) == _LIBCPP_ALIGNOF(_CompressedPair), ""); | |
| 2659 | static_assert(sizeof(_Storage) == sizeof(_CompressedPair), ""); | |
| 2660 | _Storage __storage_; | |
| 2661 | }; | |
| 2662 | ||
| 2663 | struct __shared_ptr_dummy_rebind_allocator_type; | |
| 2664 | template <> | |
| 2665 | class _LIBCPP_TEMPLATE_VIS allocator<__shared_ptr_dummy_rebind_allocator_type> | |
| 2666 | { | |
| 2667 | public: | |
| 2668 | template <class _Other> | |
| 2669 | struct rebind | |
| 2670 | { | |
| 2671 | typedef allocator<_Other> other; | |
| 2672 | }; | |
| 2673 | }; | |
| 2674 | ||
| 2675 | template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; | |
| 2676 | ||
| 2677 | template<class _Tp, class _Up> | |
| 2678 | struct __compatible_with | |
| 2679 | #if _LIBCPP_STD_VER > 14 | |
| 2680 | : is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {}; | |
| 2681 | #else | |
| 2682 | : is_convertible<_Tp*, _Up*> {}; | |
| 2683 | #endif // _LIBCPP_STD_VER > 14 | |
| 2684 | ||
| 2685 | #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) | |
| 2686 | # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) | |
| 2687 | #else | |
| 2688 | # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI | |
| 2689 | #endif | |
| 2690 | ||
| 2691 | template<class _Tp> | |
| 2692 | class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr | |
| 2693 | { | |
| 2694 | public: | |
| 2695 | #if _LIBCPP_STD_VER > 14 | |
| 2696 | typedef weak_ptr<_Tp> weak_type; | |
| 2697 | typedef remove_extent_t<_Tp> element_type; | |
| 2698 | #else | |
| 2699 | typedef _Tp element_type; | |
| 2700 | #endif | |
| 2701 | ||
| 2702 | private: | |
| 2703 | element_type* __ptr_; | |
| 2704 | __shared_weak_count* __cntrl_; | |
| 2705 | ||
| 2706 | struct __nat {int __for_bool_;}; | |
| 2707 | public: | |
| 2708 | _LIBCPP_INLINE_VISIBILITY | |
| 2709 | _LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT; | |
| 2710 | _LIBCPP_INLINE_VISIBILITY | |
| 2711 | _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT; | |
| 2712 | template<class _Yp> | |
| 2713 | explicit shared_ptr(_Yp* __p, | |
| 2714 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); | |
| 2715 | template<class _Yp, class _Dp> | |
| 2716 | shared_ptr(_Yp* __p, _Dp __d, | |
| 2717 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); | |
| 2718 | template<class _Yp, class _Dp, class _Alloc> | |
| 2719 | shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, | |
| 2720 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()); | |
| 2721 | template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d); | |
| 2722 | template <class _Dp, class _Alloc> shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a); | |
| 2723 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT; | |
| 2724 | _LIBCPP_INLINE_VISIBILITY | |
| 2725 | shared_ptr(const shared_ptr& __r) _NOEXCEPT; | |
| 2726 | template<class _Yp> | |
| 2727 | _LIBCPP_INLINE_VISIBILITY | |
| 2728 | shared_ptr(const shared_ptr<_Yp>& __r, | |
| 2729 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) | |
| 2730 | _NOEXCEPT; | |
| 2731 | _LIBCPP_INLINE_VISIBILITY | |
| 2732 | shared_ptr(shared_ptr&& __r) _NOEXCEPT; | |
| 2733 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r, | |
| 2734 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat()) | |
| 2735 | _NOEXCEPT; | |
| 2736 | template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r, | |
| 2737 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type= __nat()); | |
| 2738 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 2739 | template<class _Yp> | |
| 2740 | shared_ptr(auto_ptr<_Yp>&& __r, | |
| 2741 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat()); | |
| 2742 | #endif | |
| 2743 | template <class _Yp, class _Dp> | |
| 2744 | shared_ptr(unique_ptr<_Yp, _Dp>&&, | |
| 2745 | typename enable_if | |
| 2746 | < | |
| 2747 | !is_lvalue_reference<_Dp>::value && | |
| 2748 | !is_array<_Yp>::value && | |
| 2749 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 2750 | __nat | |
| 2751 | >::type = __nat()); | |
| 2752 | template <class _Yp, class _Dp> | |
| 2753 | shared_ptr(unique_ptr<_Yp, _Dp>&&, | |
| 2754 | typename enable_if | |
| 2755 | < | |
| 2756 | is_lvalue_reference<_Dp>::value && | |
| 2757 | !is_array<_Yp>::value && | |
| 2758 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 2759 | __nat | |
| 2760 | >::type = __nat()); | |
| 2761 | ||
| 2762 | ~shared_ptr(); | |
| 2763 | ||
| 2764 | _LIBCPP_INLINE_VISIBILITY | |
| 2765 | shared_ptr& operator=(const shared_ptr& __r) _NOEXCEPT; | |
| 2766 | template<class _Yp> | |
| 2767 | typename enable_if | |
| 2768 | < | |
| 2769 | __compatible_with<_Yp, element_type>::value, | |
| 2770 | shared_ptr& | |
| 2771 | >::type | |
| 2772 | _LIBCPP_INLINE_VISIBILITY | |
| 2773 | operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT; | |
| 2774 | _LIBCPP_INLINE_VISIBILITY | |
| 2775 | shared_ptr& operator=(shared_ptr&& __r) _NOEXCEPT; | |
| 2776 | template<class _Yp> | |
| 2777 | typename enable_if | |
| 2778 | < | |
| 2779 | __compatible_with<_Yp, element_type>::value, | |
| 2780 | shared_ptr& | |
| 2781 | >::type | |
| 2782 | _LIBCPP_INLINE_VISIBILITY | |
| 2783 | operator=(shared_ptr<_Yp>&& __r); | |
| 2784 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 2785 | template<class _Yp> | |
| 2786 | _LIBCPP_INLINE_VISIBILITY | |
| 2787 | typename enable_if | |
| 2788 | < | |
| 2789 | !is_array<_Yp>::value && | |
| 2790 | is_convertible<_Yp*, element_type*>::value, | |
| 2791 | shared_ptr | |
| 2792 | >::type& | |
| 2793 | operator=(auto_ptr<_Yp>&& __r); | |
| 2794 | #endif | |
| 2795 | template <class _Yp, class _Dp> | |
| 2796 | typename enable_if | |
| 2797 | < | |
| 2798 | !is_array<_Yp>::value && | |
| 2799 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 2800 | shared_ptr& | |
| 2801 | >::type | |
| 2802 | _LIBCPP_INLINE_VISIBILITY | |
| 2803 | operator=(unique_ptr<_Yp, _Dp>&& __r); | |
| 2804 | ||
| 2805 | _LIBCPP_INLINE_VISIBILITY | |
| 2806 | void swap(shared_ptr& __r) _NOEXCEPT; | |
| 2807 | _LIBCPP_INLINE_VISIBILITY | |
| 2808 | void reset() _NOEXCEPT; | |
| 2809 | template<class _Yp> | |
| 2810 | typename enable_if | |
| 2811 | < | |
| 2812 | __compatible_with<_Yp, element_type>::value, | |
| 2813 | void | |
| 2814 | >::type | |
| 2815 | _LIBCPP_INLINE_VISIBILITY | |
| 2816 | reset(_Yp* __p); | |
| 2817 | template<class _Yp, class _Dp> | |
| 2818 | typename enable_if | |
| 2819 | < | |
| 2820 | __compatible_with<_Yp, element_type>::value, | |
| 2821 | void | |
| 2822 | >::type | |
| 2823 | _LIBCPP_INLINE_VISIBILITY | |
| 2824 | reset(_Yp* __p, _Dp __d); | |
| 2825 | template<class _Yp, class _Dp, class _Alloc> | |
| 2826 | typename enable_if | |
| 2827 | < | |
| 2828 | __compatible_with<_Yp, element_type>::value, | |
| 2829 | void | |
| 2830 | >::type | |
| 2831 | _LIBCPP_INLINE_VISIBILITY | |
| 2832 | reset(_Yp* __p, _Dp __d, _Alloc __a); | |
| 2833 | ||
| 2834 | _LIBCPP_INLINE_VISIBILITY | |
| 2835 | element_type* get() const _NOEXCEPT {return __ptr_;} | |
| 2836 | _LIBCPP_INLINE_VISIBILITY | |
| 2837 | typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT | |
| 2838 | {return *__ptr_;} | |
| 2839 | _LIBCPP_INLINE_VISIBILITY | |
| 2840 | element_type* operator->() const _NOEXCEPT | |
| 2841 | { | |
| 2842 | static_assert(!_VSTD::is_array<_Tp>::value, | |
| 2843 | "std::shared_ptr<T>::operator-> is only valid when T is not an array type."); | |
| 2844 | return __ptr_; | |
| 2845 | } | |
| 2846 | _LIBCPP_INLINE_VISIBILITY | |
| 2847 | long use_count() const _NOEXCEPT {return __cntrl_ ? __cntrl_->use_count() : 0;} | |
| 2848 | _LIBCPP_INLINE_VISIBILITY | |
| 2849 | bool unique() const _NOEXCEPT {return use_count() == 1;} | |
| 2850 | _LIBCPP_INLINE_VISIBILITY | |
| 2851 | _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return get() != nullptr;} | |
| 2852 | template <class _Up> | |
| 2853 | _LIBCPP_INLINE_VISIBILITY | |
| 2854 | bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT | |
| 2855 | {return __cntrl_ < __p.__cntrl_;} | |
| 2856 | template <class _Up> | |
| 2857 | _LIBCPP_INLINE_VISIBILITY | |
| 2858 | bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT | |
| 2859 | {return __cntrl_ < __p.__cntrl_;} | |
| 2860 | _LIBCPP_INLINE_VISIBILITY | |
| 2861 | bool | |
| 2862 | __owner_equivalent(const shared_ptr& __p) const | |
| 2863 | {return __cntrl_ == __p.__cntrl_;} | |
| 2864 | ||
| 2865 | #if _LIBCPP_STD_VER > 14 | |
| 2866 | typename add_lvalue_reference<element_type>::type | |
| 2867 | _LIBCPP_INLINE_VISIBILITY | |
| 2868 | operator[](ptrdiff_t __i) const | |
| 2869 | { | |
| 2870 | static_assert(_VSTD::is_array<_Tp>::value, | |
| 2871 | "std::shared_ptr<T>::operator[] is only valid when T is an array type."); | |
| 2872 | return __ptr_[__i]; | |
| 2873 | } | |
| 2874 | #endif | |
| 2875 | ||
| 2876 | #ifndef _LIBCPP_NO_RTTI | |
| 2877 | template <class _Dp> | |
| 2878 | _LIBCPP_INLINE_VISIBILITY | |
| 2879 | _Dp* __get_deleter() const _NOEXCEPT | |
| 2880 | {return static_cast<_Dp*>(__cntrl_ | |
| 2881 | ? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp))) | |
| 2882 | : nullptr);} | |
| 2883 | #endif // _LIBCPP_NO_RTTI | |
| 2884 | ||
| 2885 | template<class _Yp, class _CntrlBlk> | |
| 2886 | static shared_ptr<_Tp> | |
| 2887 | __create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl) _NOEXCEPT | |
| 2888 | { | |
| 2889 | shared_ptr<_Tp> __r; | |
| 2890 | __r.__ptr_ = __p; | |
| 2891 | __r.__cntrl_ = __cntrl; | |
| 2892 | __r.__enable_weak_this(__r.__ptr_, __r.__ptr_); | |
| 2893 | return __r; | |
| 2894 | } | |
| 2895 | ||
| 2896 | private: | |
| 2897 | template <class _Yp, bool = is_function<_Yp>::value> | |
| 2898 | struct __shared_ptr_default_allocator | |
| 2899 | { | |
| 2900 | typedef allocator<_Yp> type; | |
| 2901 | }; | |
| 2902 | ||
| 2903 | template <class _Yp> | |
| 2904 | struct __shared_ptr_default_allocator<_Yp, true> | |
| 2905 | { | |
| 2906 | typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type; | |
| 2907 | }; | |
| 2908 | ||
| 2909 | template <class _Yp, class _OrigPtr> | |
| 2910 | _LIBCPP_INLINE_VISIBILITY | |
| 2911 | typename enable_if<is_convertible<_OrigPtr*, | |
| 2912 | const enable_shared_from_this<_Yp>* | |
| 2913 | >::value, | |
| 2914 | void>::type | |
| 2915 | __enable_weak_this(const enable_shared_from_this<_Yp>* __e, | |
| 2916 | _OrigPtr* __ptr) _NOEXCEPT | |
| 2917 | { | |
| 2918 | typedef typename remove_cv<_Yp>::type _RawYp; | |
| 2919 | if (__e && __e->__weak_this_.expired()) | |
| 2920 | { | |
| 2921 | __e->__weak_this_ = shared_ptr<_RawYp>(*this, | |
| 2922 | const_cast<_RawYp*>(static_cast<const _Yp*>(__ptr))); | |
| 2923 | } | |
| 2924 | } | |
| 2925 | ||
| 2926 | _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {} | |
| 2927 | ||
| 2928 | template <class, class _Yp> | |
| 2929 | struct __shared_ptr_default_delete | |
| 2930 | : default_delete<_Yp> {}; | |
| 2931 | ||
| 2932 | template <class _Yp, class _Un, size_t _Sz> | |
| 2933 | struct __shared_ptr_default_delete<_Yp[_Sz], _Un> | |
| 2934 | : default_delete<_Yp[]> {}; | |
| 2935 | ||
| 2936 | template <class _Yp, class _Un> | |
| 2937 | struct __shared_ptr_default_delete<_Yp[], _Un> | |
| 2938 | : default_delete<_Yp[]> {}; | |
| 2939 | ||
| 2940 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr; | |
| 2941 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; | |
| 2942 | }; | |
| 2943 | ||
| 2944 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 2945 | template<class _Tp> | |
| 2946 | shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>; | |
| 2947 | template<class _Tp, class _Dp> | |
| 2948 | shared_ptr(unique_ptr<_Tp, _Dp>) -> shared_ptr<_Tp>; | |
| 2949 | #endif | |
| 2950 | ||
| 2951 | template<class _Tp> | |
| 2952 | inline | |
| 2953 | _LIBCPP_CONSTEXPR | |
| 2954 | shared_ptr<_Tp>::shared_ptr() _NOEXCEPT | |
| 2955 | : __ptr_(nullptr), | |
| 2956 | __cntrl_(nullptr) | |
| 2957 | { | |
| 2958 | } | |
| 2959 | ||
| 2960 | template<class _Tp> | |
| 2961 | inline | |
| 2962 | _LIBCPP_CONSTEXPR | |
| 2963 | shared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT | |
| 2964 | : __ptr_(nullptr), | |
| 2965 | __cntrl_(nullptr) | |
| 2966 | { | |
| 2967 | } | |
| 2968 | ||
| 2969 | template<class _Tp> | |
| 2970 | template<class _Yp> | |
| 2971 | shared_ptr<_Tp>::shared_ptr(_Yp* __p, | |
| 2972 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) | |
| 2973 | : __ptr_(__p) | |
| 2974 | { | |
| 2975 | unique_ptr<_Yp> __hold(__p); | |
| 2976 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 2977 | typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT > _CntrlBlk; | |
| 2978 | __cntrl_ = new _CntrlBlk(__p, __shared_ptr_default_delete<_Tp, _Yp>(), _AllocT()); | |
| 2979 | __hold.release(); | |
| 2980 | __enable_weak_this(__p, __p); | |
| 2981 | } | |
| 2982 | ||
| 2983 | template<class _Tp> | |
| 2984 | template<class _Yp, class _Dp> | |
| 2985 | shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, | |
| 2986 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) | |
| 2987 | : __ptr_(__p) | |
| 2988 | { | |
| 2989 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2990 | try | |
| 2991 | { | |
| 2992 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2993 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 2994 | typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; | |
| 2995 | __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); | |
| 2996 | __enable_weak_this(__p, __p); | |
| 2997 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2998 | } | |
| 2999 | catch (...) | |
| 3000 | { | |
| 3001 | __d(__p); | |
| 3002 | throw; | |
| 3003 | } | |
| 3004 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3005 | } | |
| 3006 | ||
| 3007 | template<class _Tp> | |
| 3008 | template<class _Dp> | |
| 3009 | shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d) | |
| 3010 | : __ptr_(nullptr) | |
| 3011 | { | |
| 3012 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 3013 | try | |
| 3014 | { | |
| 3015 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3016 | typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; | |
| 3017 | typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT > _CntrlBlk; | |
| 3018 | __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); | |
| 3019 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 3020 | } | |
| 3021 | catch (...) | |
| 3022 | { | |
| 3023 | __d(__p); | |
| 3024 | throw; | |
| 3025 | } | |
| 3026 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3027 | } | |
| 3028 | ||
| 3029 | template<class _Tp> | |
| 3030 | template<class _Yp, class _Dp, class _Alloc> | |
| 3031 | shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a, | |
| 3032 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) | |
| 3033 | : __ptr_(__p) | |
| 3034 | { | |
| 3035 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 3036 | try | |
| 3037 | { | |
| 3038 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3039 | typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk; | |
| 3040 | typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; | |
| 3041 | typedef __allocator_destructor<_A2> _D2; | |
| 3042 | _A2 __a2(__a); | |
| 3043 | unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); | |
| 3044 | ::new ((void*)_VSTD::addressof(*__hold2.get())) _CntrlBlk(__p, __d, __a); | |
| 3045 | __cntrl_ = _VSTD::addressof(*__hold2.release()); | |
| 3046 | __enable_weak_this(__p, __p); | |
| 3047 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 3048 | } | |
| 3049 | catch (...) | |
| 3050 | { | |
| 3051 | __d(__p); | |
| 3052 | throw; | |
| 3053 | } | |
| 3054 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3055 | } | |
| 3056 | ||
| 3057 | template<class _Tp> | |
| 3058 | template<class _Dp, class _Alloc> | |
| 3059 | shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a) | |
| 3060 | : __ptr_(nullptr) | |
| 3061 | { | |
| 3062 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 3063 | try | |
| 3064 | { | |
| 3065 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3066 | typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk; | |
| 3067 | typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; | |
| 3068 | typedef __allocator_destructor<_A2> _D2; | |
| 3069 | _A2 __a2(__a); | |
| 3070 | unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); | |
| 3071 | ::new ((void*)_VSTD::addressof(*__hold2.get())) _CntrlBlk(__p, __d, __a); | |
| 3072 | __cntrl_ = _VSTD::addressof(*__hold2.release()); | |
| 3073 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 3074 | } | |
| 3075 | catch (...) | |
| 3076 | { | |
| 3077 | __d(__p); | |
| 3078 | throw; | |
| 3079 | } | |
| 3080 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3081 | } | |
| 3082 | ||
| 3083 | template<class _Tp> | |
| 3084 | template<class _Yp> | |
| 3085 | inline | |
| 3086 | shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, element_type *__p) _NOEXCEPT | |
| 3087 | : __ptr_(__p), | |
| 3088 | __cntrl_(__r.__cntrl_) | |
| 3089 | { | |
| 3090 | if (__cntrl_) | |
| 3091 | __cntrl_->__add_shared(); | |
| 3092 | } | |
| 3093 | ||
| 3094 | template<class _Tp> | |
| 3095 | inline | |
| 3096 | shared_ptr<_Tp>::shared_ptr(const shared_ptr& __r) _NOEXCEPT | |
| 3097 | : __ptr_(__r.__ptr_), | |
| 3098 | __cntrl_(__r.__cntrl_) | |
| 3099 | { | |
| 3100 | if (__cntrl_) | |
| 3101 | __cntrl_->__add_shared(); | |
| 3102 | } | |
| 3103 | ||
| 3104 | template<class _Tp> | |
| 3105 | template<class _Yp> | |
| 3106 | inline | |
| 3107 | shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r, | |
| 3108 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) | |
| 3109 | _NOEXCEPT | |
| 3110 | : __ptr_(__r.__ptr_), | |
| 3111 | __cntrl_(__r.__cntrl_) | |
| 3112 | { | |
| 3113 | if (__cntrl_) | |
| 3114 | __cntrl_->__add_shared(); | |
| 3115 | } | |
| 3116 | ||
| 3117 | template<class _Tp> | |
| 3118 | inline | |
| 3119 | shared_ptr<_Tp>::shared_ptr(shared_ptr&& __r) _NOEXCEPT | |
| 3120 | : __ptr_(__r.__ptr_), | |
| 3121 | __cntrl_(__r.__cntrl_) | |
| 3122 | { | |
| 3123 | __r.__ptr_ = nullptr; | |
| 3124 | __r.__cntrl_ = nullptr; | |
| 3125 | } | |
| 3126 | ||
| 3127 | template<class _Tp> | |
| 3128 | template<class _Yp> | |
| 3129 | inline | |
| 3130 | shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r, | |
| 3131 | typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type) | |
| 3132 | _NOEXCEPT | |
| 3133 | : __ptr_(__r.__ptr_), | |
| 3134 | __cntrl_(__r.__cntrl_) | |
| 3135 | { | |
| 3136 | __r.__ptr_ = nullptr; | |
| 3137 | __r.__cntrl_ = nullptr; | |
| 3138 | } | |
| 3139 | ||
| 3140 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 3141 | template<class _Tp> | |
| 3142 | template<class _Yp> | |
| 3143 | shared_ptr<_Tp>::shared_ptr(auto_ptr<_Yp>&& __r, | |
| 3144 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type) | |
| 3145 | : __ptr_(__r.get()) | |
| 3146 | { | |
| 3147 | typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk; | |
| 3148 | __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<_Yp>()); | |
| 3149 | __enable_weak_this(__r.get(), __r.get()); | |
| 3150 | __r.release(); | |
| 3151 | } | |
| 3152 | #endif | |
| 3153 | ||
| 3154 | template<class _Tp> | |
| 3155 | template <class _Yp, class _Dp> | |
| 3156 | shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, | |
| 3157 | typename enable_if | |
| 3158 | < | |
| 3159 | !is_lvalue_reference<_Dp>::value && | |
| 3160 | !is_array<_Yp>::value && | |
| 3161 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 3162 | __nat | |
| 3163 | >::type) | |
| 3164 | : __ptr_(__r.get()) | |
| 3165 | { | |
| 3166 | #if _LIBCPP_STD_VER > 11 | |
| 3167 | if (__ptr_ == nullptr) | |
| 3168 | __cntrl_ = nullptr; | |
| 3169 | else | |
| 3170 | #endif | |
| 3171 | { | |
| 3172 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 3173 | typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; | |
| 3174 | __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); | |
| 3175 | __enable_weak_this(__r.get(), __r.get()); | |
| 3176 | } | |
| 3177 | __r.release(); | |
| 3178 | } | |
| 3179 | ||
| 3180 | template<class _Tp> | |
| 3181 | template <class _Yp, class _Dp> | |
| 3182 | shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r, | |
| 3183 | typename enable_if | |
| 3184 | < | |
| 3185 | is_lvalue_reference<_Dp>::value && | |
| 3186 | !is_array<_Yp>::value && | |
| 3187 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, | |
| 3188 | __nat | |
| 3189 | >::type) | |
| 3190 | : __ptr_(__r.get()) | |
| 3191 | { | |
| 3192 | #if _LIBCPP_STD_VER > 11 | |
| 3193 | if (__ptr_ == nullptr) | |
| 3194 | __cntrl_ = nullptr; | |
| 3195 | else | |
| 3196 | #endif | |
| 3197 | { | |
| 3198 | typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; | |
| 3199 | typedef __shared_ptr_pointer<_Yp*, | |
| 3200 | reference_wrapper<typename remove_reference<_Dp>::type>, | |
| 3201 | _AllocT > _CntrlBlk; | |
| 3202 | __cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT()); | |
| 3203 | __enable_weak_this(__r.get(), __r.get()); | |
| 3204 | } | |
| 3205 | __r.release(); | |
| 3206 | } | |
| 3207 | ||
| 3208 | template<class _Tp> | |
| 3209 | shared_ptr<_Tp>::~shared_ptr() | |
| 3210 | { | |
| 3211 | if (__cntrl_) | |
| 3212 | __cntrl_->__release_shared(); | |
| 3213 | } | |
| 3214 | ||
| 3215 | template<class _Tp> | |
| 3216 | inline | |
| 3217 | shared_ptr<_Tp>& | |
| 3218 | shared_ptr<_Tp>::operator=(const shared_ptr& __r) _NOEXCEPT | |
| 3219 | { | |
| 3220 | shared_ptr(__r).swap(*this); | |
| 3221 | return *this; | |
| 3222 | } | |
| 3223 | ||
| 3224 | template<class _Tp> | |
| 3225 | template<class _Yp> | |
| 3226 | inline | |
| 3227 | typename enable_if | |
| 3228 | < | |
| 3229 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 3230 | shared_ptr<_Tp>& | |
| 3231 | >::type | |
| 3232 | shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT | |
| 3233 | { | |
| 3234 | shared_ptr(__r).swap(*this); | |
| 3235 | return *this; | |
| 3236 | } | |
| 3237 | ||
| 3238 | template<class _Tp> | |
| 3239 | inline | |
| 3240 | shared_ptr<_Tp>& | |
| 3241 | shared_ptr<_Tp>::operator=(shared_ptr&& __r) _NOEXCEPT | |
| 3242 | { | |
| 3243 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 3244 | return *this; | |
| 3245 | } | |
| 3246 | ||
| 3247 | template<class _Tp> | |
| 3248 | template<class _Yp> | |
| 3249 | inline | |
| 3250 | typename enable_if | |
| 3251 | < | |
| 3252 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 3253 | shared_ptr<_Tp>& | |
| 3254 | >::type | |
| 3255 | shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r) | |
| 3256 | { | |
| 3257 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 3258 | return *this; | |
| 3259 | } | |
| 3260 | ||
| 3261 | #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) | |
| 3262 | template<class _Tp> | |
| 3263 | template<class _Yp> | |
| 3264 | inline | |
| 3265 | typename enable_if | |
| 3266 | < | |
| 3267 | !is_array<_Yp>::value && | |
| 3268 | is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, | |
| 3269 | shared_ptr<_Tp> | |
| 3270 | >::type& | |
| 3271 | shared_ptr<_Tp>::operator=(auto_ptr<_Yp>&& __r) | |
| 3272 | { | |
| 3273 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 3274 | return *this; | |
| 3275 | } | |
| 3276 | #endif | |
| 3277 | ||
| 3278 | template<class _Tp> | |
| 3279 | template <class _Yp, class _Dp> | |
| 3280 | inline | |
| 3281 | typename enable_if | |
| 3282 | < | |
| 3283 | !is_array<_Yp>::value && | |
| 3284 | is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, | |
| 3285 | typename shared_ptr<_Tp>::element_type*>::value, | |
| 3286 | shared_ptr<_Tp>& | |
| 3287 | >::type | |
| 3288 | shared_ptr<_Tp>::operator=(unique_ptr<_Yp, _Dp>&& __r) | |
| 3289 | { | |
| 3290 | shared_ptr(_VSTD::move(__r)).swap(*this); | |
| 3291 | return *this; | |
| 3292 | } | |
| 3293 | ||
| 3294 | template<class _Tp> | |
| 3295 | inline | |
| 3296 | void | |
| 3297 | shared_ptr<_Tp>::swap(shared_ptr& __r) _NOEXCEPT | |
| 3298 | { | |
| 3299 | _VSTD::swap(__ptr_, __r.__ptr_); | |
| 3300 | _VSTD::swap(__cntrl_, __r.__cntrl_); | |
| 3301 | } | |
| 3302 | ||
| 3303 | template<class _Tp> | |
| 3304 | inline | |
| 3305 | void | |
| 3306 | shared_ptr<_Tp>::reset() _NOEXCEPT | |
| 3307 | { | |
| 3308 | shared_ptr().swap(*this); | |
| 3309 | } | |
| 3310 | ||
| 3311 | template<class _Tp> | |
| 3312 | template<class _Yp> | |
| 3313 | inline | |
| 3314 | typename enable_if | |
| 3315 | < | |
| 3316 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 3317 | void | |
| 3318 | >::type | |
| 3319 | shared_ptr<_Tp>::reset(_Yp* __p) | |
| 3320 | { | |
| 3321 | shared_ptr(__p).swap(*this); | |
| 3322 | } | |
| 3323 | ||
| 3324 | template<class _Tp> | |
| 3325 | template<class _Yp, class _Dp> | |
| 3326 | inline | |
| 3327 | typename enable_if | |
| 3328 | < | |
| 3329 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 3330 | void | |
| 3331 | >::type | |
| 3332 | shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d) | |
| 3333 | { | |
| 3334 | shared_ptr(__p, __d).swap(*this); | |
| 3335 | } | |
| 3336 | ||
| 3337 | template<class _Tp> | |
| 3338 | template<class _Yp, class _Dp, class _Alloc> | |
| 3339 | inline | |
| 3340 | typename enable_if | |
| 3341 | < | |
| 3342 | __compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value, | |
| 3343 | void | |
| 3344 | >::type | |
| 3345 | shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a) | |
| 3346 | { | |
| 3347 | shared_ptr(__p, __d, __a).swap(*this); | |
| 3348 | } | |
| 3349 | ||
| 3350 | // | |
| 3351 | // std::allocate_shared and std::make_shared | |
| 3352 | // | |
| 3353 | template<class _Tp, class _Alloc, class ..._Args, class = _EnableIf<!is_array<_Tp>::value> > | |
| 3354 | _LIBCPP_HIDE_FROM_ABI | |
| 3355 | shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&& ...__args) | |
| 3356 | { | |
| 3357 | using _ControlBlock = __shared_ptr_emplace<_Tp, _Alloc>; | |
| 3358 | using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type; | |
| 3359 | __allocation_guard<_ControlBlockAllocator> __guard(__a, 1); | |
| 3360 | ::new ((void*)_VSTD::addressof(*__guard.__get())) _ControlBlock(__a, _VSTD::forward<_Args>(__args)...); | |
| 3361 | auto __control_block = __guard.__release_ptr(); | |
| 3362 | return shared_ptr<_Tp>::__create_with_control_block((*__control_block).__get_elem(), _VSTD::addressof(*__control_block)); | |
| 3363 | } | |
| 3364 | ||
| 3365 | template<class _Tp, class ..._Args, class = _EnableIf<!is_array<_Tp>::value> > | |
| 3366 | _LIBCPP_HIDE_FROM_ABI | |
| 3367 | shared_ptr<_Tp> make_shared(_Args&& ...__args) | |
| 3368 | { | |
| 3369 | return _VSTD::allocate_shared<_Tp>(allocator<_Tp>(), _VSTD::forward<_Args>(__args)...); | |
| 3370 | } | |
| 3371 | ||
| 3372 | template<class _Tp, class _Up> | |
| 3373 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3374 | bool | |
| 3375 | operator==(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 3376 | { | |
| 3377 | return __x.get() == __y.get(); | |
| 3378 | } | |
| 3379 | ||
| 3380 | template<class _Tp, class _Up> | |
| 3381 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3382 | bool | |
| 3383 | operator!=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 3384 | { | |
| 3385 | return !(__x == __y); | |
| 3386 | } | |
| 3387 | ||
| 3388 | template<class _Tp, class _Up> | |
| 3389 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3390 | bool | |
| 3391 | operator<(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 3392 | { | |
| 3393 | #if _LIBCPP_STD_VER <= 11 | |
| 3394 | typedef typename common_type<_Tp*, _Up*>::type _Vp; | |
| 3395 | return less<_Vp>()(__x.get(), __y.get()); | |
| 3396 | #else | |
| 3397 | return less<>()(__x.get(), __y.get()); | |
| 3398 | #endif | |
| 3399 | ||
| 3400 | } | |
| 3401 | ||
| 3402 | template<class _Tp, class _Up> | |
| 3403 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3404 | bool | |
| 3405 | operator>(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 3406 | { | |
| 3407 | return __y < __x; | |
| 3408 | } | |
| 3409 | ||
| 3410 | template<class _Tp, class _Up> | |
| 3411 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3412 | bool | |
| 3413 | operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 3414 | { | |
| 3415 | return !(__y < __x); | |
| 3416 | } | |
| 3417 | ||
| 3418 | template<class _Tp, class _Up> | |
| 3419 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3420 | bool | |
| 3421 | operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT | |
| 3422 | { | |
| 3423 | return !(__x < __y); | |
| 3424 | } | |
| 3425 | ||
| 3426 | template<class _Tp> | |
| 3427 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3428 | bool | |
| 3429 | operator==(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 3430 | { | |
| 3431 | return !__x; | |
| 3432 | } | |
| 3433 | ||
| 3434 | template<class _Tp> | |
| 3435 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3436 | bool | |
| 3437 | operator==(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 3438 | { | |
| 3439 | return !__x; | |
| 3440 | } | |
| 3441 | ||
| 3442 | template<class _Tp> | |
| 3443 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3444 | bool | |
| 3445 | operator!=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 3446 | { | |
| 3447 | return static_cast<bool>(__x); | |
| 3448 | } | |
| 3449 | ||
| 3450 | template<class _Tp> | |
| 3451 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3452 | bool | |
| 3453 | operator!=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 3454 | { | |
| 3455 | return static_cast<bool>(__x); | |
| 3456 | } | |
| 3457 | ||
| 3458 | template<class _Tp> | |
| 3459 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3460 | bool | |
| 3461 | operator<(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 3462 | { | |
| 3463 | return less<_Tp*>()(__x.get(), nullptr); | |
| 3464 | } | |
| 3465 | ||
| 3466 | template<class _Tp> | |
| 3467 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3468 | bool | |
| 3469 | operator<(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 3470 | { | |
| 3471 | return less<_Tp*>()(nullptr, __x.get()); | |
| 3472 | } | |
| 3473 | ||
| 3474 | template<class _Tp> | |
| 3475 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3476 | bool | |
| 3477 | operator>(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 3478 | { | |
| 3479 | return nullptr < __x; | |
| 3480 | } | |
| 3481 | ||
| 3482 | template<class _Tp> | |
| 3483 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3484 | bool | |
| 3485 | operator>(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 3486 | { | |
| 3487 | return __x < nullptr; | |
| 3488 | } | |
| 3489 | ||
| 3490 | template<class _Tp> | |
| 3491 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3492 | bool | |
| 3493 | operator<=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 3494 | { | |
| 3495 | return !(nullptr < __x); | |
| 3496 | } | |
| 3497 | ||
| 3498 | template<class _Tp> | |
| 3499 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3500 | bool | |
| 3501 | operator<=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 3502 | { | |
| 3503 | return !(__x < nullptr); | |
| 3504 | } | |
| 3505 | ||
| 3506 | template<class _Tp> | |
| 3507 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3508 | bool | |
| 3509 | operator>=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT | |
| 3510 | { | |
| 3511 | return !(__x < nullptr); | |
| 3512 | } | |
| 3513 | ||
| 3514 | template<class _Tp> | |
| 3515 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3516 | bool | |
| 3517 | operator>=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT | |
| 3518 | { | |
| 3519 | return !(nullptr < __x); | |
| 3520 | } | |
| 3521 | ||
| 3522 | template<class _Tp> | |
| 3523 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3524 | void | |
| 3525 | swap(shared_ptr<_Tp>& __x, shared_ptr<_Tp>& __y) _NOEXCEPT | |
| 3526 | { | |
| 3527 | __x.swap(__y); | |
| 3528 | } | |
| 3529 | ||
| 3530 | template<class _Tp, class _Up> | |
| 3531 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3532 | shared_ptr<_Tp> | |
| 3533 | static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 3534 | { | |
| 3535 | return shared_ptr<_Tp>(__r, | |
| 3536 | static_cast< | |
| 3537 | typename shared_ptr<_Tp>::element_type*>(__r.get())); | |
| 3538 | } | |
| 3539 | ||
| 3540 | template<class _Tp, class _Up> | |
| 3541 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3542 | shared_ptr<_Tp> | |
| 3543 | dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 3544 | { | |
| 3545 | typedef typename shared_ptr<_Tp>::element_type _ET; | |
| 3546 | _ET* __p = dynamic_cast<_ET*>(__r.get()); | |
| 3547 | return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>(); | |
| 3548 | } | |
| 3549 | ||
| 3550 | template<class _Tp, class _Up> | |
| 3551 | shared_ptr<_Tp> | |
| 3552 | const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 3553 | { | |
| 3554 | typedef typename shared_ptr<_Tp>::element_type _RTp; | |
| 3555 | return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get())); | |
| 3556 | } | |
| 3557 | ||
| 3558 | template<class _Tp, class _Up> | |
| 3559 | shared_ptr<_Tp> | |
| 3560 | reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT | |
| 3561 | { | |
| 3562 | return shared_ptr<_Tp>(__r, | |
| 3563 | reinterpret_cast< | |
| 3564 | typename shared_ptr<_Tp>::element_type*>(__r.get())); | |
| 3565 | } | |
| 3566 | ||
| 3567 | #ifndef _LIBCPP_NO_RTTI | |
| 3568 | ||
| 3569 | template<class _Dp, class _Tp> | |
| 3570 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3571 | _Dp* | |
| 3572 | get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT | |
| 3573 | { | |
| 3574 | return __p.template __get_deleter<_Dp>(); | |
| 3575 | } | |
| 3576 | ||
| 3577 | #endif // _LIBCPP_NO_RTTI | |
| 3578 | ||
| 3579 | template<class _Tp> | |
| 3580 | class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr | |
| 3581 | { | |
| 3582 | public: | |
| 3583 | typedef _Tp element_type; | |
| 3584 | private: | |
| 3585 | element_type* __ptr_; | |
| 3586 | __shared_weak_count* __cntrl_; | |
| 3587 | ||
| 3588 | public: | |
| 3589 | _LIBCPP_INLINE_VISIBILITY | |
| 3590 | _LIBCPP_CONSTEXPR weak_ptr() _NOEXCEPT; | |
| 3591 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(shared_ptr<_Yp> const& __r, | |
| 3592 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0) | |
| 3593 | _NOEXCEPT; | |
| 3594 | _LIBCPP_INLINE_VISIBILITY | |
| 3595 | weak_ptr(weak_ptr const& __r) _NOEXCEPT; | |
| 3596 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp> const& __r, | |
| 3597 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0) | |
| 3598 | _NOEXCEPT; | |
| 3599 | ||
| 3600 | _LIBCPP_INLINE_VISIBILITY | |
| 3601 | weak_ptr(weak_ptr&& __r) _NOEXCEPT; | |
| 3602 | template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp>&& __r, | |
| 3603 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0) | |
| 3604 | _NOEXCEPT; | |
| 3605 | ~weak_ptr(); | |
| 3606 | ||
| 3607 | _LIBCPP_INLINE_VISIBILITY | |
| 3608 | weak_ptr& operator=(weak_ptr const& __r) _NOEXCEPT; | |
| 3609 | template<class _Yp> | |
| 3610 | typename enable_if | |
| 3611 | < | |
| 3612 | is_convertible<_Yp*, element_type*>::value, | |
| 3613 | weak_ptr& | |
| 3614 | >::type | |
| 3615 | _LIBCPP_INLINE_VISIBILITY | |
| 3616 | operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT; | |
| 3617 | ||
| 3618 | _LIBCPP_INLINE_VISIBILITY | |
| 3619 | weak_ptr& operator=(weak_ptr&& __r) _NOEXCEPT; | |
| 3620 | template<class _Yp> | |
| 3621 | typename enable_if | |
| 3622 | < | |
| 3623 | is_convertible<_Yp*, element_type*>::value, | |
| 3624 | weak_ptr& | |
| 3625 | >::type | |
| 3626 | _LIBCPP_INLINE_VISIBILITY | |
| 3627 | operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT; | |
| 3628 | ||
| 3629 | template<class _Yp> | |
| 3630 | typename enable_if | |
| 3631 | < | |
| 3632 | is_convertible<_Yp*, element_type*>::value, | |
| 3633 | weak_ptr& | |
| 3634 | >::type | |
| 3635 | _LIBCPP_INLINE_VISIBILITY | |
| 3636 | operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT; | |
| 3637 | ||
| 3638 | _LIBCPP_INLINE_VISIBILITY | |
| 3639 | void swap(weak_ptr& __r) _NOEXCEPT; | |
| 3640 | _LIBCPP_INLINE_VISIBILITY | |
| 3641 | void reset() _NOEXCEPT; | |
| 3642 | ||
| 3643 | _LIBCPP_INLINE_VISIBILITY | |
| 3644 | long use_count() const _NOEXCEPT | |
| 3645 | {return __cntrl_ ? __cntrl_->use_count() : 0;} | |
| 3646 | _LIBCPP_INLINE_VISIBILITY | |
| 3647 | bool expired() const _NOEXCEPT | |
| 3648 | {return __cntrl_ == nullptr || __cntrl_->use_count() == 0;} | |
| 3649 | shared_ptr<_Tp> lock() const _NOEXCEPT; | |
| 3650 | template<class _Up> | |
| 3651 | _LIBCPP_INLINE_VISIBILITY | |
| 3652 | bool owner_before(const shared_ptr<_Up>& __r) const _NOEXCEPT | |
| 3653 | {return __cntrl_ < __r.__cntrl_;} | |
| 3654 | template<class _Up> | |
| 3655 | _LIBCPP_INLINE_VISIBILITY | |
| 3656 | bool owner_before(const weak_ptr<_Up>& __r) const _NOEXCEPT | |
| 3657 | {return __cntrl_ < __r.__cntrl_;} | |
| 3658 | ||
| 3659 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; | |
| 3660 | template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr; | |
| 3661 | }; | |
| 3662 | ||
| 3663 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 3664 | template<class _Tp> | |
| 3665 | weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>; | |
| 3666 | #endif | |
| 3667 | ||
| 3668 | template<class _Tp> | |
| 3669 | inline | |
| 3670 | _LIBCPP_CONSTEXPR | |
| 3671 | weak_ptr<_Tp>::weak_ptr() _NOEXCEPT | |
| 3672 | : __ptr_(nullptr), | |
| 3673 | __cntrl_(nullptr) | |
| 3674 | { | |
| 3675 | } | |
| 3676 | ||
| 3677 | template<class _Tp> | |
| 3678 | inline | |
| 3679 | weak_ptr<_Tp>::weak_ptr(weak_ptr const& __r) _NOEXCEPT | |
| 3680 | : __ptr_(__r.__ptr_), | |
| 3681 | __cntrl_(__r.__cntrl_) | |
| 3682 | { | |
| 3683 | if (__cntrl_) | |
| 3684 | __cntrl_->__add_weak(); | |
| 3685 | } | |
| 3686 | ||
| 3687 | template<class _Tp> | |
| 3688 | template<class _Yp> | |
| 3689 | inline | |
| 3690 | weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r, | |
| 3691 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type) | |
| 3692 | _NOEXCEPT | |
| 3693 | : __ptr_(__r.__ptr_), | |
| 3694 | __cntrl_(__r.__cntrl_) | |
| 3695 | { | |
| 3696 | if (__cntrl_) | |
| 3697 | __cntrl_->__add_weak(); | |
| 3698 | } | |
| 3699 | ||
| 3700 | template<class _Tp> | |
| 3701 | template<class _Yp> | |
| 3702 | inline | |
| 3703 | weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp> const& __r, | |
| 3704 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type) | |
| 3705 | _NOEXCEPT | |
| 3706 | : __ptr_(__r.__ptr_), | |
| 3707 | __cntrl_(__r.__cntrl_) | |
| 3708 | { | |
| 3709 | if (__cntrl_) | |
| 3710 | __cntrl_->__add_weak(); | |
| 3711 | } | |
| 3712 | ||
| 3713 | template<class _Tp> | |
| 3714 | inline | |
| 3715 | weak_ptr<_Tp>::weak_ptr(weak_ptr&& __r) _NOEXCEPT | |
| 3716 | : __ptr_(__r.__ptr_), | |
| 3717 | __cntrl_(__r.__cntrl_) | |
| 3718 | { | |
| 3719 | __r.__ptr_ = nullptr; | |
| 3720 | __r.__cntrl_ = nullptr; | |
| 3721 | } | |
| 3722 | ||
| 3723 | template<class _Tp> | |
| 3724 | template<class _Yp> | |
| 3725 | inline | |
| 3726 | weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp>&& __r, | |
| 3727 | typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type) | |
| 3728 | _NOEXCEPT | |
| 3729 | : __ptr_(__r.__ptr_), | |
| 3730 | __cntrl_(__r.__cntrl_) | |
| 3731 | { | |
| 3732 | __r.__ptr_ = nullptr; | |
| 3733 | __r.__cntrl_ = nullptr; | |
| 3734 | } | |
| 3735 | ||
| 3736 | template<class _Tp> | |
| 3737 | weak_ptr<_Tp>::~weak_ptr() | |
| 3738 | { | |
| 3739 | if (__cntrl_) | |
| 3740 | __cntrl_->__release_weak(); | |
| 3741 | } | |
| 3742 | ||
| 3743 | template<class _Tp> | |
| 3744 | inline | |
| 3745 | weak_ptr<_Tp>& | |
| 3746 | weak_ptr<_Tp>::operator=(weak_ptr const& __r) _NOEXCEPT | |
| 3747 | { | |
| 3748 | weak_ptr(__r).swap(*this); | |
| 3749 | return *this; | |
| 3750 | } | |
| 3751 | ||
| 3752 | template<class _Tp> | |
| 3753 | template<class _Yp> | |
| 3754 | inline | |
| 3755 | typename enable_if | |
| 3756 | < | |
| 3757 | is_convertible<_Yp*, _Tp*>::value, | |
| 3758 | weak_ptr<_Tp>& | |
| 3759 | >::type | |
| 3760 | weak_ptr<_Tp>::operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT | |
| 3761 | { | |
| 3762 | weak_ptr(__r).swap(*this); | |
| 3763 | return *this; | |
| 3764 | } | |
| 3765 | ||
| 3766 | template<class _Tp> | |
| 3767 | inline | |
| 3768 | weak_ptr<_Tp>& | |
| 3769 | weak_ptr<_Tp>::operator=(weak_ptr&& __r) _NOEXCEPT | |
| 3770 | { | |
| 3771 | weak_ptr(_VSTD::move(__r)).swap(*this); | |
| 3772 | return *this; | |
| 3773 | } | |
| 3774 | ||
| 3775 | template<class _Tp> | |
| 3776 | template<class _Yp> | |
| 3777 | inline | |
| 3778 | typename enable_if | |
| 3779 | < | |
| 3780 | is_convertible<_Yp*, _Tp*>::value, | |
| 3781 | weak_ptr<_Tp>& | |
| 3782 | >::type | |
| 3783 | weak_ptr<_Tp>::operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT | |
| 3784 | { | |
| 3785 | weak_ptr(_VSTD::move(__r)).swap(*this); | |
| 3786 | return *this; | |
| 3787 | } | |
| 3788 | ||
| 3789 | template<class _Tp> | |
| 3790 | template<class _Yp> | |
| 3791 | inline | |
| 3792 | typename enable_if | |
| 3793 | < | |
| 3794 | is_convertible<_Yp*, _Tp*>::value, | |
| 3795 | weak_ptr<_Tp>& | |
| 3796 | >::type | |
| 3797 | weak_ptr<_Tp>::operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT | |
| 3798 | { | |
| 3799 | weak_ptr(__r).swap(*this); | |
| 3800 | return *this; | |
| 3801 | } | |
| 3802 | ||
| 3803 | template<class _Tp> | |
| 3804 | inline | |
| 3805 | void | |
| 3806 | weak_ptr<_Tp>::swap(weak_ptr& __r) _NOEXCEPT | |
| 3807 | { | |
| 3808 | _VSTD::swap(__ptr_, __r.__ptr_); | |
| 3809 | _VSTD::swap(__cntrl_, __r.__cntrl_); | |
| 3810 | } | |
| 3811 | ||
| 3812 | template<class _Tp> | |
| 3813 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3814 | void | |
| 3815 | swap(weak_ptr<_Tp>& __x, weak_ptr<_Tp>& __y) _NOEXCEPT | |
| 3816 | { | |
| 3817 | __x.swap(__y); | |
| 3818 | } | |
| 3819 | ||
| 3820 | template<class _Tp> | |
| 3821 | inline | |
| 3822 | void | |
| 3823 | weak_ptr<_Tp>::reset() _NOEXCEPT | |
| 3824 | { | |
| 3825 | weak_ptr().swap(*this); | |
| 3826 | } | |
| 3827 | ||
| 3828 | template<class _Tp> | |
| 3829 | template<class _Yp> | |
| 3830 | shared_ptr<_Tp>::shared_ptr(const weak_ptr<_Yp>& __r, | |
| 3831 | typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type) | |
| 3832 | : __ptr_(__r.__ptr_), | |
| 3833 | __cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_) | |
| 3834 | { | |
| 3835 | if (__cntrl_ == nullptr) | |
| 3836 | __throw_bad_weak_ptr(); | |
| 3837 | } | |
| 3838 | ||
| 3839 | template<class _Tp> | |
| 3840 | shared_ptr<_Tp> | |
| 3841 | weak_ptr<_Tp>::lock() const _NOEXCEPT | |
| 3842 | { | |
| 3843 | shared_ptr<_Tp> __r; | |
| 3844 | __r.__cntrl_ = __cntrl_ ? __cntrl_->lock() : __cntrl_; | |
| 3845 | if (__r.__cntrl_) | |
| 3846 | __r.__ptr_ = __ptr_; | |
| 3847 | return __r; | |
| 3848 | } | |
| 3849 | ||
| 3850 | #if _LIBCPP_STD_VER > 14 | |
| 3851 | template <class _Tp = void> struct owner_less; | |
| 3852 | #else | |
| 3853 | template <class _Tp> struct owner_less; | |
| 3854 | #endif | |
| 3855 | ||
| 3856 | template <class _Tp> | |
| 3857 | struct _LIBCPP_TEMPLATE_VIS owner_less<shared_ptr<_Tp> > | |
| 3858 | : binary_function<shared_ptr<_Tp>, shared_ptr<_Tp>, bool> | |
| 3859 | { | |
| 3860 | typedef bool result_type; | |
| 3861 | _LIBCPP_INLINE_VISIBILITY | |
| 3862 | bool operator()(shared_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 3863 | {return __x.owner_before(__y);} | |
| 3864 | _LIBCPP_INLINE_VISIBILITY | |
| 3865 | bool operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 3866 | {return __x.owner_before(__y);} | |
| 3867 | _LIBCPP_INLINE_VISIBILITY | |
| 3868 | bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 3869 | {return __x.owner_before(__y);} | |
| 3870 | }; | |
| 3871 | ||
| 3872 | template <class _Tp> | |
| 3873 | struct _LIBCPP_TEMPLATE_VIS owner_less<weak_ptr<_Tp> > | |
| 3874 | : binary_function<weak_ptr<_Tp>, weak_ptr<_Tp>, bool> | |
| 3875 | { | |
| 3876 | typedef bool result_type; | |
| 3877 | _LIBCPP_INLINE_VISIBILITY | |
| 3878 | bool operator()( weak_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 3879 | {return __x.owner_before(__y);} | |
| 3880 | _LIBCPP_INLINE_VISIBILITY | |
| 3881 | bool operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 3882 | {return __x.owner_before(__y);} | |
| 3883 | _LIBCPP_INLINE_VISIBILITY | |
| 3884 | bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT | |
| 3885 | {return __x.owner_before(__y);} | |
| 3886 | }; | |
| 3887 | ||
| 3888 | #if _LIBCPP_STD_VER > 14 | |
| 3889 | template <> | |
| 3890 | struct _LIBCPP_TEMPLATE_VIS owner_less<void> | |
| 3891 | { | |
| 3892 | template <class _Tp, class _Up> | |
| 3893 | _LIBCPP_INLINE_VISIBILITY | |
| 3894 | bool operator()( shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const _NOEXCEPT | |
| 3895 | {return __x.owner_before(__y);} | |
| 3896 | template <class _Tp, class _Up> | |
| 3897 | _LIBCPP_INLINE_VISIBILITY | |
| 3898 | bool operator()( shared_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const _NOEXCEPT | |
| 3899 | {return __x.owner_before(__y);} | |
| 3900 | template <class _Tp, class _Up> | |
| 3901 | _LIBCPP_INLINE_VISIBILITY | |
| 3902 | bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const _NOEXCEPT | |
| 3903 | {return __x.owner_before(__y);} | |
| 3904 | template <class _Tp, class _Up> | |
| 3905 | _LIBCPP_INLINE_VISIBILITY | |
| 3906 | bool operator()( weak_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const _NOEXCEPT | |
| 3907 | {return __x.owner_before(__y);} | |
| 3908 | typedef void is_transparent; | |
| 3909 | }; | |
| 3910 | #endif | |
| 3911 | ||
| 3912 | template<class _Tp> | |
| 3913 | class _LIBCPP_TEMPLATE_VIS enable_shared_from_this | |
| 3914 | { | |
| 3915 | mutable weak_ptr<_Tp> __weak_this_; | |
| 3916 | protected: | |
| 3917 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 3918 | enable_shared_from_this() _NOEXCEPT {} | |
| 3919 | _LIBCPP_INLINE_VISIBILITY | |
| 3920 | enable_shared_from_this(enable_shared_from_this const&) _NOEXCEPT {} | |
| 3921 | _LIBCPP_INLINE_VISIBILITY | |
| 3922 | enable_shared_from_this& operator=(enable_shared_from_this const&) _NOEXCEPT | |
| 3923 | {return *this;} | |
| 3924 | _LIBCPP_INLINE_VISIBILITY | |
| 3925 | ~enable_shared_from_this() {} | |
| 3926 | public: | |
| 3927 | _LIBCPP_INLINE_VISIBILITY | |
| 3928 | shared_ptr<_Tp> shared_from_this() | |
| 3929 | {return shared_ptr<_Tp>(__weak_this_);} | |
| 3930 | _LIBCPP_INLINE_VISIBILITY | |
| 3931 | shared_ptr<_Tp const> shared_from_this() const | |
| 3932 | {return shared_ptr<const _Tp>(__weak_this_);} | |
| 3933 | ||
| 3934 | #if _LIBCPP_STD_VER > 14 | |
| 3935 | _LIBCPP_INLINE_VISIBILITY | |
| 3936 | weak_ptr<_Tp> weak_from_this() _NOEXCEPT | |
| 3937 | { return __weak_this_; } | |
| 3938 | ||
| 3939 | _LIBCPP_INLINE_VISIBILITY | |
| 3940 | weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT | |
| 3941 | { return __weak_this_; } | |
| 3942 | #endif // _LIBCPP_STD_VER > 14 | |
| 3943 | ||
| 3944 | template <class _Up> friend class shared_ptr; | |
| 3945 | }; | |
| 3946 | ||
| 3947 | template <class _Tp> | |
| 3948 | struct _LIBCPP_TEMPLATE_VIS hash<shared_ptr<_Tp> > | |
| 3949 | { | |
| 3950 | typedef shared_ptr<_Tp> argument_type; | |
| 3951 | typedef size_t result_type; | |
| 3952 | ||
| 3953 | _LIBCPP_INLINE_VISIBILITY | |
| 3954 | result_type operator()(const argument_type& __ptr) const _NOEXCEPT | |
| 3955 | { | |
| 3956 | return hash<typename shared_ptr<_Tp>::element_type*>()(__ptr.get()); | |
| 3957 | } | |
| 3958 | }; | |
| 3959 | ||
| 3960 | template<class _CharT, class _Traits, class _Yp> | |
| 3961 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3962 | basic_ostream<_CharT, _Traits>& | |
| 3963 | operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p); | |
| 3964 | ||
| 3965 | ||
| 3966 | #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) | |
| 3967 | ||
| 3968 | class _LIBCPP_TYPE_VIS __sp_mut | |
| 3969 | { | |
| 3970 | void* __lx; | |
| 3971 | public: | |
| 3972 | void lock() _NOEXCEPT; | |
| 3973 | void unlock() _NOEXCEPT; | |
| 3974 | ||
| 3975 | private: | |
| 3976 | _LIBCPP_CONSTEXPR __sp_mut(void*) _NOEXCEPT; | |
| 3977 | __sp_mut(const __sp_mut&); | |
| 3978 | __sp_mut& operator=(const __sp_mut&); | |
| 3979 | ||
| 3980 | friend _LIBCPP_FUNC_VIS __sp_mut& __get_sp_mut(const void*); | |
| 3981 | }; | |
| 3982 | ||
| 3983 | _LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 3984 | __sp_mut& __get_sp_mut(const void*); | |
| 3985 | ||
| 3986 | template <class _Tp> | |
| 3987 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3988 | bool | |
| 3989 | atomic_is_lock_free(const shared_ptr<_Tp>*) | |
| 3990 | { | |
| 3991 | return false; | |
| 3992 | } | |
| 3993 | ||
| 3994 | template <class _Tp> | |
| 3995 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 3996 | shared_ptr<_Tp> | |
| 3997 | atomic_load(const shared_ptr<_Tp>* __p) | |
| 3998 | { | |
| 3999 | __sp_mut& __m = __get_sp_mut(__p); | |
| 4000 | __m.lock(); | |
| 4001 | shared_ptr<_Tp> __q = *__p; | |
| 4002 | __m.unlock(); | |
| 4003 | return __q; | |
| 4004 | } | |
| 4005 | ||
| 4006 | template <class _Tp> | |
| 4007 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4008 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4009 | shared_ptr<_Tp> | |
| 4010 | atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order) | |
| 4011 | { | |
| 4012 | return atomic_load(__p); | |
| 4013 | } | |
| 4014 | ||
| 4015 | template <class _Tp> | |
| 4016 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4017 | void | |
| 4018 | atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) | |
| 4019 | { | |
| 4020 | __sp_mut& __m = __get_sp_mut(__p); | |
| 4021 | __m.lock(); | |
| 4022 | __p->swap(__r); | |
| 4023 | __m.unlock(); | |
| 4024 | } | |
| 4025 | ||
| 4026 | template <class _Tp> | |
| 4027 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4028 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4029 | void | |
| 4030 | atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) | |
| 4031 | { | |
| 4032 | atomic_store(__p, __r); | |
| 4033 | } | |
| 4034 | ||
| 4035 | template <class _Tp> | |
| 4036 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4037 | shared_ptr<_Tp> | |
| 4038 | atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) | |
| 4039 | { | |
| 4040 | __sp_mut& __m = __get_sp_mut(__p); | |
| 4041 | __m.lock(); | |
| 4042 | __p->swap(__r); | |
| 4043 | __m.unlock(); | |
| 4044 | return __r; | |
| 4045 | } | |
| 4046 | ||
| 4047 | template <class _Tp> | |
| 4048 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4049 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4050 | shared_ptr<_Tp> | |
| 4051 | atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) | |
| 4052 | { | |
| 4053 | return atomic_exchange(__p, __r); | |
| 4054 | } | |
| 4055 | ||
| 4056 | template <class _Tp> | |
| 4057 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4058 | bool | |
| 4059 | atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) | |
| 4060 | { | |
| 4061 | shared_ptr<_Tp> __temp; | |
| 4062 | __sp_mut& __m = __get_sp_mut(__p); | |
| 4063 | __m.lock(); | |
| 4064 | if (__p->__owner_equivalent(*__v)) | |
| 4065 | { | |
| 4066 | _VSTD::swap(__temp, *__p); | |
| 4067 | *__p = __w; | |
| 4068 | __m.unlock(); | |
| 4069 | return true; | |
| 4070 | } | |
| 4071 | _VSTD::swap(__temp, *__v); | |
| 4072 | *__v = *__p; | |
| 4073 | __m.unlock(); | |
| 4074 | return false; | |
| 4075 | } | |
| 4076 | ||
| 4077 | template <class _Tp> | |
| 4078 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4079 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4080 | bool | |
| 4081 | atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) | |
| 4082 | { | |
| 4083 | return atomic_compare_exchange_strong(__p, __v, __w); | |
| 4084 | } | |
| 4085 | ||
| 4086 | template <class _Tp> | |
| 4087 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4088 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4089 | bool | |
| 4090 | atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, | |
| 4091 | shared_ptr<_Tp> __w, memory_order, memory_order) | |
| 4092 | { | |
| 4093 | return atomic_compare_exchange_strong(__p, __v, __w); | |
| 4094 | } | |
| 4095 | ||
| 4096 | template <class _Tp> | |
| 4097 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4098 | _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR | |
| 4099 | bool | |
| 4100 | atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, | |
| 4101 | shared_ptr<_Tp> __w, memory_order, memory_order) | |
| 4102 | { | |
| 4103 | return atomic_compare_exchange_weak(__p, __v, __w); | |
| 4104 | } | |
| 4105 | ||
| 4106 | #endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) | |
| 4107 | ||
| 4108 | //enum class | |
| 4109 | #if defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) | |
| 4110 | # ifndef _LIBCPP_CXX03_LANG | |
| 4111 | enum class pointer_safety : unsigned char { | |
| 4112 | relaxed, | |
| 4113 | preferred, | |
| 4114 | strict | |
| 4115 | }; | |
| 4116 | # endif | |
| 4117 | #else | |
| 4118 | struct _LIBCPP_TYPE_VIS pointer_safety | |
| 4119 | { | |
| 4120 | enum __lx | |
| 4121 | { | |
| 4122 | relaxed, | |
| 4123 | preferred, | |
| 4124 | strict | |
| 4125 | }; | |
| 4126 | ||
| 4127 | __lx __v_; | |
| 4128 | ||
| 4129 | _LIBCPP_INLINE_VISIBILITY | |
| 4130 | pointer_safety() : __v_() {} | |
| 4131 | ||
| 4132 | _LIBCPP_INLINE_VISIBILITY | |
| 4133 | pointer_safety(__lx __v) : __v_(__v) {} | |
| 4134 | _LIBCPP_INLINE_VISIBILITY | |
| 4135 | operator int() const {return __v_;} | |
| 4136 | }; | |
| 4137 | #endif | |
| 4138 | ||
| 4139 | #if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) && \ | |
| 4140 | defined(_LIBCPP_BUILDING_LIBRARY) | |
| 4141 | _LIBCPP_FUNC_VIS pointer_safety get_pointer_safety() _NOEXCEPT; | |
| 4142 | #else | |
| 4143 | // This function is only offered in C++03 under ABI v1. | |
| 4144 | # if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) || !defined(_LIBCPP_CXX03_LANG) | |
| 4145 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4146 | pointer_safety get_pointer_safety() _NOEXCEPT { | |
| 4147 | return pointer_safety::relaxed; | |
| 4148 | } | |
| 4149 | # endif | |
| 4150 | #endif | |
| 4151 | ||
| 4152 | ||
| 4153 | _LIBCPP_FUNC_VIS void declare_reachable(void* __p); | |
| 4154 | _LIBCPP_FUNC_VIS void declare_no_pointers(char* __p, size_t __n); | |
| 4155 | _LIBCPP_FUNC_VIS void undeclare_no_pointers(char* __p, size_t __n); | |
| 4156 | _LIBCPP_FUNC_VIS void* __undeclare_reachable(void* __p); | |
| 4157 | ||
| 4158 | template <class _Tp> | |
| 4159 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4160 | _Tp* | |
| 4161 | undeclare_reachable(_Tp* __p) | |
| 4162 | { | |
| 4163 | return static_cast<_Tp*>(__undeclare_reachable(__p)); | |
| 4164 | } | |
| 4165 | ||
| 4166 | 841 | _LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); |
| 4167 | 842 | |
| 4168 | 843 | // --- Helper for container swap -- |
| ... | ... | @@ -4193,7 +868,7 @@ void __swap_allocator(_Alloc & __a1, _Alloc & __a2) |
| 4193 | 868 | #endif |
| 4194 | 869 | { |
| 4195 | 870 | _VSTD::__swap_allocator(__a1, __a2, |
| 4196 | integral_constant<bool, _VSTD::allocator_traits<_Alloc>::propagate_on_container_swap::value>()); | |
| 871 | integral_constant<bool, allocator_traits<_Alloc>::propagate_on_container_swap::value>()); | |
| 4197 | 872 | } |
| 4198 | 873 | |
| 4199 | 874 | template <typename _Alloc, typename _Traits=allocator_traits<_Alloc> > |
| ... | ... | @@ -4233,7 +908,7 @@ struct __is_allocator : false_type {}; |
| 4233 | 908 | template<typename _Alloc> |
| 4234 | 909 | struct __is_allocator<_Alloc, |
| 4235 | 910 | typename __void_t<typename _Alloc::value_type>::type, |
| 4236 | typename __void_t<decltype(_VSTD::declval<_Alloc&>().allocate(size_t(0)))>::type | |
| 911 | typename __void_t<decltype(declval<_Alloc&>().allocate(size_t(0)))>::type | |
| 4237 | 912 | > |
| 4238 | 913 | : true_type {}; |
| 4239 | 914 | |
| ... | ... | @@ -4291,4 +966,4 @@ _LIBCPP_POP_MACROS |
| 4291 | 966 | # include <__pstl_memory> |
| 4292 | 967 | #endif |
| 4293 | 968 | |
| 4294 | #endif // _LIBCPP_MEMORY | |
| 969 | #endif // _LIBCPP_MEMORY |
lib/libcxx/include/module.modulemap+277-16| ... | ... | @@ -217,6 +217,102 @@ module std [system] { |
| 217 | 217 | header "algorithm" |
| 218 | 218 | export initializer_list |
| 219 | 219 | export * |
| 220 | ||
| 221 | module __algorithm { | |
| 222 | module adjacent_find { private header "__algorithm/adjacent_find.h" } | |
| 223 | module all_of { private header "__algorithm/all_of.h" } | |
| 224 | module any_of { private header "__algorithm/any_of.h" } | |
| 225 | module binary_search { private header "__algorithm/binary_search.h" } | |
| 226 | module clamp { private header "__algorithm/clamp.h" } | |
| 227 | module comp { private header "__algorithm/comp.h" } | |
| 228 | module comp_ref_type { private header "__algorithm/comp_ref_type.h" } | |
| 229 | module copy { private header "__algorithm/copy.h" } | |
| 230 | module copy_backward { private header "__algorithm/copy_backward.h" } | |
| 231 | module copy_if { private header "__algorithm/copy_if.h" } | |
| 232 | module copy_n { private header "__algorithm/copy_n.h" } | |
| 233 | module count { private header "__algorithm/count.h" } | |
| 234 | module count_if { private header "__algorithm/count_if.h" } | |
| 235 | module equal { private header "__algorithm/equal.h" } | |
| 236 | module equal_range { private header "__algorithm/equal_range.h" } | |
| 237 | module fill { private header "__algorithm/fill.h" } | |
| 238 | module fill_n { private header "__algorithm/fill_n.h" } | |
| 239 | module find { private header "__algorithm/find.h" } | |
| 240 | module find_end { private header "__algorithm/find_end.h" } | |
| 241 | module find_first_of { private header "__algorithm/find_first_of.h" } | |
| 242 | module find_if { private header "__algorithm/find_if.h" } | |
| 243 | module find_if_not { private header "__algorithm/find_if_not.h" } | |
| 244 | module for_each { private header "__algorithm/for_each.h" } | |
| 245 | module for_each_n { private header "__algorithm/for_each_n.h" } | |
| 246 | module generate { private header "__algorithm/generate.h" } | |
| 247 | module generate_n { private header "__algorithm/generate_n.h" } | |
| 248 | module half_positive { private header "__algorithm/half_positive.h" } | |
| 249 | module includes { private header "__algorithm/includes.h" } | |
| 250 | module inplace_merge { private header "__algorithm/inplace_merge.h" } | |
| 251 | module is_heap { private header "__algorithm/is_heap.h" } | |
| 252 | module is_heap_until { private header "__algorithm/is_heap_until.h" } | |
| 253 | module is_partitioned { private header "__algorithm/is_partitioned.h" } | |
| 254 | module is_permutation { private header "__algorithm/is_permutation.h" } | |
| 255 | module is_sorted { private header "__algorithm/is_sorted.h" } | |
| 256 | module is_sorted_until { private header "__algorithm/is_sorted_until.h" } | |
| 257 | module iter_swap { private header "__algorithm/iter_swap.h" } | |
| 258 | module lexicographical_compare { private header "__algorithm/lexicographical_compare.h" } | |
| 259 | module lower_bound { private header "__algorithm/lower_bound.h" } | |
| 260 | module make_heap { private header "__algorithm/make_heap.h" } | |
| 261 | module max { private header "__algorithm/max.h" } | |
| 262 | module max_element { private header "__algorithm/max_element.h" } | |
| 263 | module merge { private header "__algorithm/merge.h" } | |
| 264 | module min { private header "__algorithm/min.h" } | |
| 265 | module min_element { private header "__algorithm/min_element.h" } | |
| 266 | module minmax { private header "__algorithm/minmax.h" } | |
| 267 | module minmax_element { private header "__algorithm/minmax_element.h" } | |
| 268 | module mismatch { private header "__algorithm/mismatch.h" } | |
| 269 | module move { private header "__algorithm/move.h" } | |
| 270 | module move_backward { private header "__algorithm/move_backward.h" } | |
| 271 | module next_permutation { private header "__algorithm/next_permutation.h" } | |
| 272 | module none_of { private header "__algorithm/none_of.h" } | |
| 273 | module nth_element { private header "__algorithm/nth_element.h" } | |
| 274 | module partial_sort { private header "__algorithm/partial_sort.h" } | |
| 275 | module partial_sort_copy { private header "__algorithm/partial_sort_copy.h" } | |
| 276 | module partition { private header "__algorithm/partition.h" } | |
| 277 | module partition_copy { private header "__algorithm/partition_copy.h" } | |
| 278 | module partition_point { private header "__algorithm/partition_point.h" } | |
| 279 | module pop_heap { private header "__algorithm/pop_heap.h" } | |
| 280 | module prev_permutation { private header "__algorithm/prev_permutation.h" } | |
| 281 | module push_heap { private header "__algorithm/push_heap.h" } | |
| 282 | module remove { private header "__algorithm/remove.h" } | |
| 283 | module remove_copy { private header "__algorithm/remove_copy.h" } | |
| 284 | module remove_copy_if { private header "__algorithm/remove_copy_if.h" } | |
| 285 | module remove_if { private header "__algorithm/remove_if.h" } | |
| 286 | module replace { private header "__algorithm/replace.h" } | |
| 287 | module replace_copy { private header "__algorithm/replace_copy.h" } | |
| 288 | module replace_copy_if { private header "__algorithm/replace_copy_if.h" } | |
| 289 | module replace_if { private header "__algorithm/replace_if.h" } | |
| 290 | module reverse { private header "__algorithm/reverse.h" } | |
| 291 | module reverse_copy { private header "__algorithm/reverse_copy.h" } | |
| 292 | module rotate { private header "__algorithm/rotate.h" } | |
| 293 | module rotate_copy { private header "__algorithm/rotate_copy.h" } | |
| 294 | module sample { private header "__algorithm/sample.h" } | |
| 295 | module search { private header "__algorithm/search.h" } | |
| 296 | module search_n { private header "__algorithm/search_n.h" } | |
| 297 | module set_difference { private header "__algorithm/set_difference.h" } | |
| 298 | module set_intersection { private header "__algorithm/set_intersection.h" } | |
| 299 | module set_symmetric_difference { private header "__algorithm/set_symmetric_difference.h" } | |
| 300 | module set_union { private header "__algorithm/set_union.h" } | |
| 301 | module shift_left { private header "__algorithm/shift_left.h" } | |
| 302 | module shift_right { private header "__algorithm/shift_right.h" } | |
| 303 | module shuffle { private header "__algorithm/shuffle.h" } | |
| 304 | module sift_down { private header "__algorithm/sift_down.h" } | |
| 305 | module sort { private header "__algorithm/sort.h" } | |
| 306 | module sort_heap { private header "__algorithm/sort_heap.h" } | |
| 307 | module stable_partition { private header "__algorithm/stable_partition.h" } | |
| 308 | module stable_sort { private header "__algorithm/stable_sort.h" } | |
| 309 | module swap_ranges { private header "__algorithm/swap_ranges.h" } | |
| 310 | module transform { private header "__algorithm/transform.h" } | |
| 311 | module unique { private header "__algorithm/unique.h" } | |
| 312 | module unique_copy { private header "__algorithm/unique_copy.h" } | |
| 313 | module unwrap_iter { private header "__algorithm/unwrap_iter.h" } | |
| 314 | module upper_bound { private header "__algorithm/upper_bound.h" } | |
| 315 | } | |
| 220 | 316 | } |
| 221 | 317 | module any { |
| 222 | 318 | header "any" |
| ... | ... | @@ -292,6 +388,15 @@ module std [system] { |
| 292 | 388 | header "filesystem" |
| 293 | 389 | export * |
| 294 | 390 | } |
| 391 | module format { | |
| 392 | header "format" | |
| 393 | export * | |
| 394 | ||
| 395 | module __format { | |
| 396 | module format_error { private header "__format/format_error.h" } | |
| 397 | module format_parse_context { private header "__format/format_parse_context.h" } | |
| 398 | } | |
| 399 | } | |
| 295 | 400 | module forward_list { |
| 296 | 401 | header "forward_list" |
| 297 | 402 | export initializer_list |
| ... | ... | @@ -304,6 +409,34 @@ module std [system] { |
| 304 | 409 | module functional { |
| 305 | 410 | header "functional" |
| 306 | 411 | export * |
| 412 | ||
| 413 | module __functional { | |
| 414 | module binary_function { private header "__functional/binary_function.h" } | |
| 415 | module binary_negate { private header "__functional/binary_negate.h" } | |
| 416 | module bind { private header "__functional/bind.h" } | |
| 417 | module bind_front { private header "__functional/bind_front.h" } | |
| 418 | module binder1st { private header "__functional/binder1st.h" } | |
| 419 | module binder2nd { private header "__functional/binder2nd.h" } | |
| 420 | module default_searcher { private header "__functional/default_searcher.h" } | |
| 421 | module function { private header "__functional/function.h" } | |
| 422 | module hash { private header "__functional/hash.h" } | |
| 423 | module identity { private header "__functional/identity.h" } | |
| 424 | module is_transparent { private header "__functional/is_transparent.h" } | |
| 425 | module invoke { private header "__functional/invoke.h" } | |
| 426 | module mem_fn { private header "__functional/mem_fn.h" } | |
| 427 | module mem_fun_ref { private header "__functional/mem_fun_ref.h" } | |
| 428 | module not_fn { private header "__functional/not_fn.h" } | |
| 429 | module operations { private header "__functional/operations.h" } | |
| 430 | module perfect_forward { private header "__functional/perfect_forward.h" } | |
| 431 | module pointer_to_binary_function { private header "__functional/pointer_to_binary_function.h" } | |
| 432 | module pointer_to_unary_function { private header "__functional/pointer_to_unary_function.h" } | |
| 433 | module ranges_operations { private header "__functional/ranges_operations.h" } | |
| 434 | module reference_wrapper { private header "__functional/reference_wrapper.h" } | |
| 435 | module unary_function { private header "__functional/unary_function.h" } | |
| 436 | module unary_negate { private header "__functional/unary_negate.h" } | |
| 437 | module unwrap_ref { private header "__functional/unwrap_ref.h" } | |
| 438 | module weak_result_type { private header "__functional/weak_result_type.h" } | |
| 439 | } | |
| 307 | 440 | } |
| 308 | 441 | module future { |
| 309 | 442 | header "future" |
| ... | ... | @@ -342,6 +475,49 @@ module std [system] { |
| 342 | 475 | module iterator { |
| 343 | 476 | header "iterator" |
| 344 | 477 | export * |
| 478 | ||
| 479 | module __iterator { | |
| 480 | module access { private header "__iterator/access.h" } | |
| 481 | module advance { | |
| 482 | private header "__iterator/advance.h" | |
| 483 | export __function_like | |
| 484 | } | |
| 485 | module back_insert_iterator { private header "__iterator/back_insert_iterator.h" } | |
| 486 | module common_iterator { private header "__iterator/common_iterator.h" } | |
| 487 | module concepts { private header "__iterator/concepts.h" } | |
| 488 | module counted_iterator { private header "__iterator/counted_iterator.h" } | |
| 489 | module data { private header "__iterator/data.h" } | |
| 490 | module default_sentinel { private header "__iterator/default_sentinel.h" } | |
| 491 | module distance { private header "__iterator/distance.h" } | |
| 492 | module empty { private header "__iterator/empty.h" } | |
| 493 | module erase_if_container { private header "__iterator/erase_if_container.h" } | |
| 494 | module front_insert_iterator { private header "__iterator/front_insert_iterator.h" } | |
| 495 | module incrementable_traits { private header "__iterator/incrementable_traits.h" } | |
| 496 | module insert_iterator { private header "__iterator/insert_iterator.h" } | |
| 497 | module istream_iterator { private header "__iterator/istream_iterator.h" } | |
| 498 | module istreambuf_iterator { private header "__iterator/istreambuf_iterator.h" } | |
| 499 | module iter_move { private header "__iterator/iter_move.h" } | |
| 500 | module iter_swap { private header "__iterator/iter_swap.h" } | |
| 501 | module iterator { private header "__iterator/iterator.h" } | |
| 502 | module iterator_traits { private header "__iterator/iterator_traits.h" } | |
| 503 | module move_iterator { private header "__iterator/move_iterator.h" } | |
| 504 | module next { | |
| 505 | private header "__iterator/next.h" | |
| 506 | export __function_like | |
| 507 | } | |
| 508 | module ostream_iterator { private header "__iterator/ostream_iterator.h" } | |
| 509 | module ostreambuf_iterator { private header "__iterator/ostreambuf_iterator.h" } | |
| 510 | module prev { | |
| 511 | private header "__iterator/prev.h" | |
| 512 | export __function_like | |
| 513 | } | |
| 514 | module projected { private header "__iterator/projected.h" } | |
| 515 | module readable_traits { private header "__iterator/readable_traits.h" } | |
| 516 | module reverse_access { private header "__iterator/reverse_access.h" } | |
| 517 | module reverse_iterator { private header "__iterator/reverse_iterator.h" } | |
| 518 | module size { private header "__iterator/size.h" } | |
| 519 | module wrap_iter { private header "__iterator/wrap_iter.h" } | |
| 520 | } | |
| 345 | 521 | } |
| 346 | 522 | module latch { |
| 347 | 523 | requires cplusplus14 |
| ... | ... | @@ -369,6 +545,25 @@ module std [system] { |
| 369 | 545 | module memory { |
| 370 | 546 | header "memory" |
| 371 | 547 | export * |
| 548 | ||
| 549 | module __memory { | |
| 550 | module addressof { private header "__memory/addressof.h" } | |
| 551 | module allocation_guard { private header "__memory/allocation_guard.h" } | |
| 552 | module allocator { private header "__memory/allocator.h" } | |
| 553 | module allocator_arg_t { private header "__memory/allocator_arg_t.h" } | |
| 554 | module allocator_traits { private header "__memory/allocator_traits.h" } | |
| 555 | module auto_ptr { private header "__memory/auto_ptr.h" } | |
| 556 | module compressed_pair { private header "__memory/compressed_pair.h" } | |
| 557 | module construct_at { private header "__memory/construct_at.h" } | |
| 558 | module pointer_safety { private header "__memory/pointer_safety.h" } | |
| 559 | module pointer_traits { private header "__memory/pointer_traits.h" } | |
| 560 | module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" } | |
| 561 | module shared_ptr { private header "__memory/shared_ptr.h" } | |
| 562 | module temporary_buffer { private header "__memory/temporary_buffer.h" } | |
| 563 | module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" } | |
| 564 | module unique_ptr { private header "__memory/unique_ptr.h" } | |
| 565 | module uses_allocator { private header "__memory/uses_allocator.h" } | |
| 566 | } | |
| 372 | 567 | } |
| 373 | 568 | module mutex { |
| 374 | 569 | header "mutex" |
| ... | ... | @@ -404,6 +599,38 @@ module std [system] { |
| 404 | 599 | header "random" |
| 405 | 600 | export initializer_list |
| 406 | 601 | export * |
| 602 | ||
| 603 | module __random { | |
| 604 | module uniform_int_distribution { private header "__random/uniform_int_distribution.h" } | |
| 605 | } | |
| 606 | } | |
| 607 | module ranges { | |
| 608 | header "ranges" | |
| 609 | export compare | |
| 610 | export initializer_list | |
| 611 | export iterator | |
| 612 | export * | |
| 613 | ||
| 614 | module __ranges { | |
| 615 | module access { private header "__ranges/access.h" } | |
| 616 | module all { private header "__ranges/all.h" } | |
| 617 | module common_view { private header "__ranges/common_view.h" } | |
| 618 | module concepts { private header "__ranges/concepts.h" } | |
| 619 | module copyable_box { private header "__ranges/copyable_box.h" } | |
| 620 | module dangling { private header "__ranges/dangling.h" } | |
| 621 | module data { private header "__ranges/data.h" } | |
| 622 | module drop_view { private header "__ranges/drop_view.h" } | |
| 623 | module empty { private header "__ranges/empty.h" } | |
| 624 | module empty_view { private header "__ranges/empty_view.h" } | |
| 625 | module enable_borrowed_range { private header "__ranges/enable_borrowed_range.h" } | |
| 626 | module enable_view { private header "__ranges/enable_view.h" } | |
| 627 | module non_propagating_cache { private header "__ranges/non_propagating_cache.h" } | |
| 628 | module ref_view { private header "__ranges/ref_view.h" } | |
| 629 | module size { private header "__ranges/size.h" } | |
| 630 | module subrange { private header "__ranges/subrange.h" } | |
| 631 | module transform_view { private header "__ranges/transform_view.h" } | |
| 632 | module view_interface { private header "__ranges/view_interface.h" } | |
| 633 | } | |
| 407 | 634 | } |
| 408 | 635 | module ratio { |
| 409 | 636 | header "ratio" |
| ... | ... | @@ -428,6 +655,15 @@ module std [system] { |
| 428 | 655 | export initializer_list |
| 429 | 656 | export * |
| 430 | 657 | } |
| 658 | module shared_mutex { | |
| 659 | header "shared_mutex" | |
| 660 | export version | |
| 661 | } | |
| 662 | module span { | |
| 663 | header "span" | |
| 664 | export ranges.__ranges.enable_borrowed_range | |
| 665 | export version | |
| 666 | } | |
| 431 | 667 | module sstream { |
| 432 | 668 | header "sstream" |
| 433 | 669 | // FIXME: should re-export istream, ostream, ios, streambuf, string? |
| ... | ... | @@ -477,6 +713,7 @@ module std [system] { |
| 477 | 713 | } |
| 478 | 714 | module type_traits { |
| 479 | 715 | header "type_traits" |
| 716 | export functional.__functional.unwrap_ref | |
| 480 | 717 | export * |
| 481 | 718 | } |
| 482 | 719 | module typeindex { |
| ... | ... | @@ -501,6 +738,23 @@ module std [system] { |
| 501 | 738 | header "utility" |
| 502 | 739 | export initializer_list |
| 503 | 740 | export * |
| 741 | ||
| 742 | module __utility { | |
| 743 | module __decay_copy { private header "__utility/__decay_copy.h" } | |
| 744 | module as_const { private header "__utility/as_const.h" } | |
| 745 | module cmp { private header "__utility/cmp.h" } | |
| 746 | module declval { private header "__utility/declval.h" } | |
| 747 | module exchange { private header "__utility/exchange.h" } | |
| 748 | module forward { private header "__utility/forward.h" } | |
| 749 | module in_place { private header "__utility/in_place.h" } | |
| 750 | module integer_sequence { private header "__utility/integer_sequence.h" } | |
| 751 | module move { private header "__utility/move.h" } | |
| 752 | module pair { private header "__utility/pair.h" } | |
| 753 | module piecewise_construct { private header "__utility/piecewise_construct.h" } | |
| 754 | module rel_ops { private header "__utility/rel_ops.h" } | |
| 755 | module swap { private header "__utility/swap.h" } | |
| 756 | module to_underlying { private header "__utility/to_underlying.h" } | |
| 757 | } | |
| 504 | 758 | } |
| 505 | 759 | module valarray { |
| 506 | 760 | header "valarray" |
| ... | ... | @@ -510,6 +764,10 @@ module std [system] { |
| 510 | 764 | module variant { |
| 511 | 765 | header "variant" |
| 512 | 766 | export * |
| 767 | ||
| 768 | module __variant { | |
| 769 | module monostate { private header "__variant/monostate.h" } | |
| 770 | } | |
| 513 | 771 | } |
| 514 | 772 | module vector { |
| 515 | 773 | header "vector" |
| ... | ... | @@ -521,23 +779,26 @@ module std [system] { |
| 521 | 779 | export * |
| 522 | 780 | } |
| 523 | 781 | |
| 782 | // __config not modularised due to a bug in Clang | |
| 524 | 783 | // FIXME: These should be private. |
| 525 | module __bits { header "__bits" export * } | |
| 526 | module __bit_reference { header "__bit_reference" export * } | |
| 527 | module __debug { header "__debug" export * } | |
| 528 | module __errc { header "__errc" export * } | |
| 529 | module __functional_base { header "__functional_base" export * } | |
| 530 | module __hash_table { header "__hash_table" export * } | |
| 531 | module __locale { header "__locale" export * } | |
| 532 | module __mutex_base { header "__mutex_base" export * } | |
| 533 | module __split_buffer { header "__split_buffer" export * } | |
| 534 | module __sso_allocator { header "__sso_allocator" export * } | |
| 535 | module __std_stream { header "__std_stream" export * } | |
| 536 | module __string { header "__string" export * } | |
| 537 | module __tree { header "__tree" export * } | |
| 538 | module __tuple { header "__tuple" export * } | |
| 539 | module __undef_macros { header "__undef_macros" export * } | |
| 540 | module __node_handle { header "__node_handle" export * } | |
| 784 | module __availability { private header "__availability" export * } | |
| 785 | module __bit_reference { private header "__bit_reference" export * } | |
| 786 | module __bits { private header "__bits" export * } | |
| 787 | module __debug { header "__debug" export * } | |
| 788 | module __errc { private header "__errc" export * } | |
| 789 | module __function_like { private header "__function_like.h" export * } | |
| 790 | module __hash_table { header "__hash_table" export * } | |
| 791 | module __locale { private header "__locale" export * } | |
| 792 | module __mutex_base { private header "__mutex_base" export * } | |
| 793 | module __node_handle { private header "__node_handle" export * } | |
| 794 | module __nullptr { header "__nullptr" export * } | |
| 795 | module __split_buffer { private header "__split_buffer" export * } | |
| 796 | module __std_stream { private header "__std_stream" export * } | |
| 797 | module __string { private header "__string" export * } | |
| 798 | module __threading_support { header "__threading_support" export * } | |
| 799 | module __tree { header "__tree" export * } | |
| 800 | module __tuple { private header "__tuple" export * } | |
| 801 | module __undef_macros { header "__undef_macros" export * } | |
| 541 | 802 | |
| 542 | 803 | module experimental { |
| 543 | 804 | requires cplusplus11 |
lib/libcxx/include/mutex+9-8| ... | ... | @@ -188,14 +188,15 @@ template<class Callable, class ...Args> |
| 188 | 188 | |
| 189 | 189 | #include <__config> |
| 190 | 190 | #include <__mutex_base> |
| 191 | #include <__threading_support> | |
| 192 | #include <__utility/forward.h> | |
| 191 | 193 | #include <cstdint> |
| 192 | 194 | #include <functional> |
| 193 | 195 | #include <memory> |
| 194 | 196 | #ifndef _LIBCPP_CXX03_LANG |
| 195 | #include <tuple> | |
| 197 | # include <tuple> | |
| 196 | 198 | #endif |
| 197 | 199 | #include <version> |
| 198 | #include <__threading_support> | |
| 199 | 200 | |
| 200 | 201 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 201 | 202 | #pragma GCC system_header |
| ... | ... | @@ -365,7 +366,7 @@ try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) |
| 365 | 366 | return __r; |
| 366 | 367 | } |
| 367 | 368 | |
| 368 | #endif // _LIBCPP_CXX03_LANG | |
| 369 | #endif // _LIBCPP_CXX03_LANG | |
| 369 | 370 | |
| 370 | 371 | template <class _L0, class _L1> |
| 371 | 372 | void |
| ... | ... | @@ -469,7 +470,7 @@ void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { |
| 469 | 470 | _VSTD::__unlock(__l2, __l3...); |
| 470 | 471 | } |
| 471 | 472 | |
| 472 | #endif // _LIBCPP_CXX03_LANG | |
| 473 | #endif // _LIBCPP_CXX03_LANG | |
| 473 | 474 | |
| 474 | 475 | #if _LIBCPP_STD_VER > 14 |
| 475 | 476 | template <class ..._Mutexes> |
| ... | ... | @@ -568,7 +569,7 @@ template<class _Callable> |
| 568 | 569 | _LIBCPP_INLINE_VISIBILITY |
| 569 | 570 | void call_once(once_flag&, const _Callable&); |
| 570 | 571 | |
| 571 | #endif // _LIBCPP_CXX03_LANG | |
| 572 | #endif // _LIBCPP_CXX03_LANG | |
| 572 | 573 | |
| 573 | 574 | struct _LIBCPP_TEMPLATE_VIS once_flag |
| 574 | 575 | { |
| ... | ... | @@ -601,7 +602,7 @@ private: |
| 601 | 602 | template<class _Callable> |
| 602 | 603 | friend |
| 603 | 604 | void call_once(once_flag&, const _Callable&); |
| 604 | #endif // _LIBCPP_CXX03_LANG | |
| 605 | #endif // _LIBCPP_CXX03_LANG | |
| 605 | 606 | }; |
| 606 | 607 | |
| 607 | 608 | #ifndef _LIBCPP_CXX03_LANG |
| ... | ... | @@ -702,10 +703,10 @@ call_once(once_flag& __flag, const _Callable& __func) |
| 702 | 703 | } |
| 703 | 704 | } |
| 704 | 705 | |
| 705 | #endif // _LIBCPP_CXX03_LANG | |
| 706 | #endif // _LIBCPP_CXX03_LANG | |
| 706 | 707 | |
| 707 | 708 | _LIBCPP_END_NAMESPACE_STD |
| 708 | 709 | |
| 709 | 710 | _LIBCPP_POP_MACROS |
| 710 | 711 | |
| 711 | #endif // _LIBCPP_MUTEX | |
| 712 | #endif // _LIBCPP_MUTEX |
lib/libcxx/include/new+3-3| ... | ... | @@ -86,8 +86,8 @@ void operator delete[](void* ptr, void*) noexcept; |
| 86 | 86 | |
| 87 | 87 | */ |
| 88 | 88 | |
| 89 | #include <__config> | |
| 90 | 89 | #include <__availability> |
| 90 | #include <__config> | |
| 91 | 91 | #include <cstddef> |
| 92 | 92 | #include <cstdlib> |
| 93 | 93 | #include <exception> |
| ... | ... | @@ -314,7 +314,7 @@ void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) { |
| 314 | 314 | return ::_aligned_malloc(__size, __alignment); |
| 315 | 315 | #else |
| 316 | 316 | void* __result = nullptr; |
| 317 | ::posix_memalign(&__result, __alignment, __size); | |
| 317 | (void)::posix_memalign(&__result, __alignment, __size); | |
| 318 | 318 | // If posix_memalign fails, __result is unmodified so we still return `nullptr`. |
| 319 | 319 | return __result; |
| 320 | 320 | #endif |
| ... | ... | @@ -356,4 +356,4 @@ constexpr _Tp* launder(_Tp* __p) noexcept |
| 356 | 356 | |
| 357 | 357 | _LIBCPP_END_NAMESPACE_STD |
| 358 | 358 | |
| 359 | #endif // _LIBCPP_NEW | |
| 359 | #endif // _LIBCPP_NEW |
lib/libcxx/include/numbers+17-20| ... | ... | @@ -59,12 +59,12 @@ namespace std::numbers { |
| 59 | 59 | */ |
| 60 | 60 | |
| 61 | 61 | #include <__config> |
| 62 | ||
| 63 | #if _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L | |
| 64 | ||
| 62 | #include <concepts> | |
| 65 | 63 | #include <type_traits> |
| 66 | 64 | #include <version> |
| 67 | 65 | |
| 66 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 67 | ||
| 68 | 68 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 69 | 69 | #pragma GCC system_header |
| 70 | 70 | #endif |
| ... | ... | @@ -99,22 +99,19 @@ template <class T> inline constexpr T inv_sqrt3_v = __illformed<T>{}; |
| 99 | 99 | template <class T> inline constexpr T egamma_v = __illformed<T>{}; |
| 100 | 100 | template <class T> inline constexpr T phi_v = __illformed<T>{}; |
| 101 | 101 | |
| 102 | template <class T> | |
| 103 | concept __floating_point = is_floating_point_v<T>; | |
| 104 | ||
| 105 | template <__floating_point T> inline constexpr T e_v<T> = 2.718281828459045235360287471352662; | |
| 106 | template <__floating_point T> inline constexpr T log2e_v<T> = 1.442695040888963407359924681001892; | |
| 107 | template <__floating_point T> inline constexpr T log10e_v<T> = 0.434294481903251827651128918916605; | |
| 108 | template <__floating_point T> inline constexpr T pi_v<T> = 3.141592653589793238462643383279502; | |
| 109 | template <__floating_point T> inline constexpr T inv_pi_v<T> = 0.318309886183790671537767526745028; | |
| 110 | template <__floating_point T> inline constexpr T inv_sqrtpi_v<T> = 0.564189583547756286948079451560772; | |
| 111 | template <__floating_point T> inline constexpr T ln2_v<T> = 0.693147180559945309417232121458176; | |
| 112 | template <__floating_point T> inline constexpr T ln10_v<T> = 2.302585092994045684017991454684364; | |
| 113 | template <__floating_point T> inline constexpr T sqrt2_v<T> = 1.414213562373095048801688724209698; | |
| 114 | template <__floating_point T> inline constexpr T sqrt3_v<T> = 1.732050807568877293527446341505872; | |
| 115 | template <__floating_point T> inline constexpr T inv_sqrt3_v<T> = 0.577350269189625764509148780501957; | |
| 116 | template <__floating_point T> inline constexpr T egamma_v<T> = 0.577215664901532860606512090082402; | |
| 117 | template <__floating_point T> inline constexpr T phi_v<T> = 1.618033988749894848204586834365638; | |
| 102 | template <floating_point T> inline constexpr T e_v<T> = 2.718281828459045235360287471352662; | |
| 103 | template <floating_point T> inline constexpr T log2e_v<T> = 1.442695040888963407359924681001892; | |
| 104 | template <floating_point T> inline constexpr T log10e_v<T> = 0.434294481903251827651128918916605; | |
| 105 | template <floating_point T> inline constexpr T pi_v<T> = 3.141592653589793238462643383279502; | |
| 106 | template <floating_point T> inline constexpr T inv_pi_v<T> = 0.318309886183790671537767526745028; | |
| 107 | template <floating_point T> inline constexpr T inv_sqrtpi_v<T> = 0.564189583547756286948079451560772; | |
| 108 | template <floating_point T> inline constexpr T ln2_v<T> = 0.693147180559945309417232121458176; | |
| 109 | template <floating_point T> inline constexpr T ln10_v<T> = 2.302585092994045684017991454684364; | |
| 110 | template <floating_point T> inline constexpr T sqrt2_v<T> = 1.414213562373095048801688724209698; | |
| 111 | template <floating_point T> inline constexpr T sqrt3_v<T> = 1.732050807568877293527446341505872; | |
| 112 | template <floating_point T> inline constexpr T inv_sqrt3_v<T> = 0.577350269189625764509148780501957; | |
| 113 | template <floating_point T> inline constexpr T egamma_v<T> = 0.577215664901532860606512090082402; | |
| 114 | template <floating_point T> inline constexpr T phi_v<T> = 1.618033988749894848204586834365638; | |
| 118 | 115 | |
| 119 | 116 | inline constexpr double e = e_v<double>; |
| 120 | 117 | inline constexpr double log2e = log2e_v<double>; |
| ... | ... | @@ -136,6 +133,6 @@ _LIBCPP_END_NAMESPACE_STD |
| 136 | 133 | |
| 137 | 134 | _LIBCPP_POP_MACROS |
| 138 | 135 | |
| 139 | #endif //_LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L | |
| 136 | #endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 140 | 137 | |
| 141 | 138 | #endif // _LIBCPP_NUMBERS |
lib/libcxx/include/numeric+6-5| ... | ... | @@ -145,10 +145,11 @@ template<class T> |
| 145 | 145 | */ |
| 146 | 146 | |
| 147 | 147 | #include <__config> |
| 148 | #include <__debug> | |
| 149 | #include <cmath> // for isnormal | |
| 150 | #include <functional> | |
| 148 | 151 | #include <iterator> |
| 149 | 152 | #include <limits> // for numeric_limits |
| 150 | #include <functional> | |
| 151 | #include <cmath> // for isnormal | |
| 152 | 153 | #include <version> |
| 153 | 154 | |
| 154 | 155 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -613,8 +614,8 @@ _LIBCPP_INLINE_VISIBILITY constexpr |
| 613 | 614 | enable_if_t<is_floating_point_v<_Fp>, _Fp> |
| 614 | 615 | midpoint(_Fp __a, _Fp __b) noexcept |
| 615 | 616 | { |
| 616 | 	constexpr _Fp __lo = numeric_limits<_Fp>::min()*2; | |
| 617 | 	constexpr _Fp __hi = numeric_limits<_Fp>::max()/2; | |
| 617 | constexpr _Fp __lo = numeric_limits<_Fp>::min()*2; | |
| 618 | constexpr _Fp __hi = numeric_limits<_Fp>::max()/2; | |
| 618 | 619 | return __fp_abs(__a) <= __hi && __fp_abs(__b) <= __hi ? // typical case: overflow is impossible |
| 619 | 620 | (__a + __b)/2 : // always correctly rounded |
| 620 | 621 | __fp_abs(__a) < __lo ? __a + __b/2 : // not safe to halve a |
| ... | ... | @@ -632,4 +633,4 @@ _LIBCPP_POP_MACROS |
| 632 | 633 | # include <__pstl_numeric> |
| 633 | 634 | #endif |
| 634 | 635 | |
| 635 | #endif // _LIBCPP_NUMERIC | |
| 636 | #endif // _LIBCPP_NUMERIC |
lib/libcxx/include/optional+100-93| ... | ... | @@ -69,7 +69,7 @@ namespace std { |
| 69 | 69 | template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&); |
| 70 | 70 | |
| 71 | 71 | // 23.6.9, specialized algorithms |
| 72 | template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); | |
| 72 | template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20 | |
| 73 | 73 | template <class T> constexpr optional<see below > make_optional(T&&); |
| 74 | 74 | template <class T, class... Args> |
| 75 | 75 | constexpr optional<T> make_optional(Args&&... args); |
| ... | ... | @@ -95,26 +95,26 @@ namespace std { |
| 95 | 95 | template <class U = T> |
| 96 | 96 | constexpr EXPLICIT optional(U &&); |
| 97 | 97 | template <class U> |
| 98 | constexpr EXPLICIT optional(const optional<U> &); | |
| 98 | EXPLICIT optional(const optional<U> &); // constexpr in C++20 | |
| 99 | 99 | template <class U> |
| 100 | constexpr EXPLICIT optional(optional<U> &&); | |
| 100 | EXPLICIT optional(optional<U> &&); // constexpr in C++20 | |
| 101 | 101 | |
| 102 | 102 | // 23.6.3.2, destructor |
| 103 | ~optional(); | |
| 103 | ~optional(); // constexpr in C++20 | |
| 104 | 104 | |
| 105 | 105 | // 23.6.3.3, assignment |
| 106 | optional &operator=(nullopt_t) noexcept; | |
| 107 | optional &operator=(const optional &); // constexpr in C++20 | |
| 108 | optional &operator=(optional &&) noexcept(see below); // constexpr in C++20 | |
| 109 | template <class U = T> optional &operator=(U &&); | |
| 110 | template <class U> optional &operator=(const optional<U> &); | |
| 111 | template <class U> optional &operator=(optional<U> &&); | |
| 112 | template <class... Args> T& emplace(Args &&...); | |
| 106 | optional &operator=(nullopt_t) noexcept; // constexpr in C++20 | |
| 107 | optional &operator=(const optional &); // constexpr in C++20 | |
| 108 | optional &operator=(optional &&) noexcept(see below); // constexpr in C++20 | |
| 109 | template <class U = T> optional &operator=(U &&); // constexpr in C++20 | |
| 110 | template <class U> optional &operator=(const optional<U> &); // constexpr in C++20 | |
| 111 | template <class U> optional &operator=(optional<U> &&); // constexpr in C++20 | |
| 112 | template <class... Args> T& emplace(Args &&...); // constexpr in C++20 | |
| 113 | 113 | template <class U, class... Args> |
| 114 | T& emplace(initializer_list<U>, Args &&...); | |
| 114 | T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20 | |
| 115 | 115 | |
| 116 | 116 | // 23.6.3.4, swap |
| 117 | void swap(optional &) noexcept(see below ); | |
| 117 | void swap(optional &) noexcept(see below ); // constexpr in C++20 | |
| 118 | 118 | |
| 119 | 119 | // 23.6.3.5, observers |
| 120 | 120 | constexpr T const *operator->() const; |
| ... | ... | @@ -133,7 +133,7 @@ namespace std { |
| 133 | 133 | template <class U> constexpr T value_or(U &&) &&; |
| 134 | 134 | |
| 135 | 135 | // 23.6.3.6, modifiers |
| 136 | void reset() noexcept; | |
| 136 | void reset() noexcept; // constexpr in C++20 | |
| 137 | 137 | |
| 138 | 138 | private: |
| 139 | 139 | T *val; // exposition only |
| ... | ... | @@ -146,10 +146,11 @@ template<class T> |
| 146 | 146 | |
| 147 | 147 | */ |
| 148 | 148 | |
| 149 | #include <__config> | |
| 150 | 149 | #include <__availability> |
| 150 | #include <__config> | |
| 151 | 151 | #include <__debug> |
| 152 | 152 | #include <__functional_base> |
| 153 | #include <compare> | |
| 153 | 154 | #include <functional> |
| 154 | 155 | #include <initializer_list> |
| 155 | 156 | #include <new> |
| ... | ... | @@ -220,7 +221,7 @@ struct __optional_destruct_base<_Tp, false> |
| 220 | 221 | bool __engaged_; |
| 221 | 222 | |
| 222 | 223 | _LIBCPP_INLINE_VISIBILITY |
| 223 | ~__optional_destruct_base() | |
| 224 | _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base() | |
| 224 | 225 | { |
| 225 | 226 | if (__engaged_) |
| 226 | 227 | __val_.~value_type(); |
| ... | ... | @@ -238,7 +239,7 @@ struct __optional_destruct_base<_Tp, false> |
| 238 | 239 | __engaged_(true) {} |
| 239 | 240 | |
| 240 | 241 | _LIBCPP_INLINE_VISIBILITY |
| 241 | void reset() noexcept | |
| 242 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept | |
| 242 | 243 | { |
| 243 | 244 | if (__engaged_) |
| 244 | 245 | { |
| ... | ... | @@ -273,7 +274,7 @@ struct __optional_destruct_base<_Tp, true> |
| 273 | 274 | __engaged_(true) {} |
| 274 | 275 | |
| 275 | 276 | _LIBCPP_INLINE_VISIBILITY |
| 276 | void reset() noexcept | |
| 277 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept | |
| 277 | 278 | { |
| 278 | 279 | if (__engaged_) |
| 279 | 280 | { |
| ... | ... | @@ -318,16 +319,20 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> |
| 318 | 319 | |
| 319 | 320 | template <class... _Args> |
| 320 | 321 | _LIBCPP_INLINE_VISIBILITY |
| 321 | void __construct(_Args&&... __args) | |
| 322 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args) | |
| 322 | 323 | { |
| 323 | 324 | _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); |
| 325 | #if _LIBCPP_STD_VER > 17 | |
| 326 | _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...); | |
| 327 | #else | |
| 324 | 328 | ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); |
| 329 | #endif | |
| 325 | 330 | this->__engaged_ = true; |
| 326 | 331 | } |
| 327 | 332 | |
| 328 | 333 | template <class _That> |
| 329 | 334 | _LIBCPP_INLINE_VISIBILITY |
| 330 | void __construct_from(_That&& __opt) | |
| 335 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) | |
| 331 | 336 | { |
| 332 | 337 | if (__opt.has_value()) |
| 333 | 338 | __construct(_VSTD::forward<_That>(__opt).__get()); |
| ... | ... | @@ -335,7 +340,7 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> |
| 335 | 340 | |
| 336 | 341 | template <class _That> |
| 337 | 342 | _LIBCPP_INLINE_VISIBILITY |
| 338 | void __assign_from(_That&& __opt) | |
| 343 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) | |
| 339 | 344 | { |
| 340 | 345 | if (this->__engaged_ == __opt.has_value()) |
| 341 | 346 | { |
| ... | ... | @@ -393,7 +398,7 @@ struct __optional_storage_base<_Tp, true> |
| 393 | 398 | } |
| 394 | 399 | |
| 395 | 400 | _LIBCPP_INLINE_VISIBILITY |
| 396 | void reset() noexcept { __value_ = nullptr; } | |
| 401 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; } | |
| 397 | 402 | |
| 398 | 403 | _LIBCPP_INLINE_VISIBILITY |
| 399 | 404 | constexpr bool has_value() const noexcept |
| ... | ... | @@ -409,7 +414,7 @@ struct __optional_storage_base<_Tp, true> |
| 409 | 414 | |
| 410 | 415 | template <class _UArg> |
| 411 | 416 | _LIBCPP_INLINE_VISIBILITY |
| 412 | void __construct(_UArg&& __val) | |
| 417 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val) | |
| 413 | 418 | { |
| 414 | 419 | _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); |
| 415 | 420 | static_assert(__can_bind_reference<_UArg>(), |
| ... | ... | @@ -420,7 +425,7 @@ struct __optional_storage_base<_Tp, true> |
| 420 | 425 | |
| 421 | 426 | template <class _That> |
| 422 | 427 | _LIBCPP_INLINE_VISIBILITY |
| 423 | void __construct_from(_That&& __opt) | |
| 428 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt) | |
| 424 | 429 | { |
| 425 | 430 | if (__opt.has_value()) |
| 426 | 431 | __construct(_VSTD::forward<_That>(__opt).__get()); |
| ... | ... | @@ -428,7 +433,7 @@ struct __optional_storage_base<_Tp, true> |
| 428 | 433 | |
| 429 | 434 | template <class _That> |
| 430 | 435 | _LIBCPP_INLINE_VISIBILITY |
| 431 | void __assign_from(_That&& __opt) | |
| 436 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt) | |
| 432 | 437 | { |
| 433 | 438 | if (has_value() == __opt.has_value()) |
| 434 | 439 | { |
| ... | ... | @@ -460,7 +465,7 @@ struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> |
| 460 | 465 | __optional_copy_base() = default; |
| 461 | 466 | |
| 462 | 467 | _LIBCPP_INLINE_VISIBILITY |
| 463 | __optional_copy_base(const __optional_copy_base& __opt) | |
| 468 | _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt) | |
| 464 | 469 | { |
| 465 | 470 | this->__construct_from(__opt); |
| 466 | 471 | } |
| ... | ... | @@ -491,7 +496,7 @@ struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> |
| 491 | 496 | __optional_move_base(const __optional_move_base&) = default; |
| 492 | 497 | |
| 493 | 498 | _LIBCPP_INLINE_VISIBILITY |
| 494 | __optional_move_base(__optional_move_base&& __opt) | |
| 499 | _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt) | |
| 495 | 500 | noexcept(is_nothrow_move_constructible_v<value_type>) |
| 496 | 501 | { |
| 497 | 502 | this->__construct_from(_VSTD::move(__opt)); |
| ... | ... | @@ -525,7 +530,7 @@ struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> |
| 525 | 530 | __optional_copy_assign_base(__optional_copy_assign_base&&) = default; |
| 526 | 531 | |
| 527 | 532 | _LIBCPP_INLINE_VISIBILITY |
| 528 | __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) | |
| 533 | _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) | |
| 529 | 534 | { |
| 530 | 535 | this->__assign_from(__opt); |
| 531 | 536 | return *this; |
| ... | ... | @@ -560,7 +565,7 @@ struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp |
| 560 | 565 | __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; |
| 561 | 566 | |
| 562 | 567 | _LIBCPP_INLINE_VISIBILITY |
| 563 | __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) | |
| 568 | _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) | |
| 564 | 569 | noexcept(is_nothrow_move_assignable_v<value_type> && |
| 565 | 570 | is_nothrow_move_constructible_v<value_type>) |
| 566 | 571 | { |
| ... | ... | @@ -727,7 +732,7 @@ public: |
| 727 | 732 | _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() |
| 728 | 733 | , int> = 0> |
| 729 | 734 | _LIBCPP_INLINE_VISIBILITY |
| 730 | optional(const optional<_Up>& __v) | |
| 735 | _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v) | |
| 731 | 736 | { |
| 732 | 737 | this->__construct_from(__v); |
| 733 | 738 | } |
| ... | ... | @@ -735,7 +740,7 @@ public: |
| 735 | 740 | _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() |
| 736 | 741 | , int> = 0> |
| 737 | 742 | _LIBCPP_INLINE_VISIBILITY |
| 738 | explicit optional(const optional<_Up>& __v) | |
| 743 | _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v) | |
| 739 | 744 | { |
| 740 | 745 | this->__construct_from(__v); |
| 741 | 746 | } |
| ... | ... | @@ -745,7 +750,7 @@ public: |
| 745 | 750 | _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() |
| 746 | 751 | , int> = 0> |
| 747 | 752 | _LIBCPP_INLINE_VISIBILITY |
| 748 | optional(optional<_Up>&& __v) | |
| 753 | _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v) | |
| 749 | 754 | { |
| 750 | 755 | this->__construct_from(_VSTD::move(__v)); |
| 751 | 756 | } |
| ... | ... | @@ -753,13 +758,13 @@ public: |
| 753 | 758 | _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() |
| 754 | 759 | , int> = 0> |
| 755 | 760 | _LIBCPP_INLINE_VISIBILITY |
| 756 | explicit optional(optional<_Up>&& __v) | |
| 761 | _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v) | |
| 757 | 762 | { |
| 758 | 763 | this->__construct_from(_VSTD::move(__v)); |
| 759 | 764 | } |
| 760 | 765 | |
| 761 | 766 | _LIBCPP_INLINE_VISIBILITY |
| 762 | optional& operator=(nullopt_t) noexcept | |
| 767 | _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept | |
| 763 | 768 | { |
| 764 | 769 | reset(); |
| 765 | 770 | return *this; |
| ... | ... | @@ -782,7 +787,7 @@ public: |
| 782 | 787 | >::value> |
| 783 | 788 | > |
| 784 | 789 | _LIBCPP_INLINE_VISIBILITY |
| 785 | optional& | |
| 790 | _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& | |
| 786 | 791 | operator=(_Up&& __v) |
| 787 | 792 | { |
| 788 | 793 | if (this->has_value()) |
| ... | ... | @@ -797,7 +802,7 @@ public: |
| 797 | 802 | _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() |
| 798 | 803 | , int> = 0> |
| 799 | 804 | _LIBCPP_INLINE_VISIBILITY |
| 800 | optional& | |
| 805 | _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& | |
| 801 | 806 | operator=(const optional<_Up>& __v) |
| 802 | 807 | { |
| 803 | 808 | this->__assign_from(__v); |
| ... | ... | @@ -809,7 +814,7 @@ public: |
| 809 | 814 | _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() |
| 810 | 815 | , int> = 0> |
| 811 | 816 | _LIBCPP_INLINE_VISIBILITY |
| 812 | optional& | |
| 817 | _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& | |
| 813 | 818 | operator=(optional<_Up>&& __v) |
| 814 | 819 | { |
| 815 | 820 | this->__assign_from(_VSTD::move(__v)); |
| ... | ... | @@ -823,7 +828,7 @@ public: |
| 823 | 828 | > |
| 824 | 829 | > |
| 825 | 830 | _LIBCPP_INLINE_VISIBILITY |
| 826 | _Tp & | |
| 831 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & | |
| 827 | 832 | emplace(_Args&&... __args) |
| 828 | 833 | { |
| 829 | 834 | reset(); |
| ... | ... | @@ -838,7 +843,7 @@ public: |
| 838 | 843 | > |
| 839 | 844 | > |
| 840 | 845 | _LIBCPP_INLINE_VISIBILITY |
| 841 | _Tp & | |
| 846 | _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & | |
| 842 | 847 | emplace(initializer_list<_Up> __il, _Args&&... __args) |
| 843 | 848 | { |
| 844 | 849 | reset(); |
| ... | ... | @@ -847,7 +852,7 @@ public: |
| 847 | 852 | } |
| 848 | 853 | |
| 849 | 854 | _LIBCPP_INLINE_VISIBILITY |
| 850 | void swap(optional& __opt) | |
| 855 | _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt) | |
| 851 | 856 | noexcept(is_nothrow_move_constructible_v<value_type> && |
| 852 | 857 | is_nothrow_swappable_v<value_type>) |
| 853 | 858 | { |
| ... | ... | @@ -877,7 +882,7 @@ public: |
| 877 | 882 | add_pointer_t<value_type const> |
| 878 | 883 | operator->() const |
| 879 | 884 | { |
| 880 | _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); | |
| 885 | _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); | |
| 881 | 886 | #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF |
| 882 | 887 | return _VSTD::addressof(this->__get()); |
| 883 | 888 | #else |
| ... | ... | @@ -890,7 +895,7 @@ public: |
| 890 | 895 | add_pointer_t<value_type> |
| 891 | 896 | operator->() |
| 892 | 897 | { |
| 893 | _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); | |
| 898 | _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); | |
| 894 | 899 | #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF |
| 895 | 900 | return _VSTD::addressof(this->__get()); |
| 896 | 901 | #else |
| ... | ... | @@ -901,36 +906,36 @@ public: |
| 901 | 906 | _LIBCPP_INLINE_VISIBILITY |
| 902 | 907 | constexpr |
| 903 | 908 | const value_type& |
| 904 | operator*() const& | |
| 909 | operator*() const& noexcept | |
| 905 | 910 | { |
| 906 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| 911 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); | |
| 907 | 912 | return this->__get(); |
| 908 | 913 | } |
| 909 | 914 | |
| 910 | 915 | _LIBCPP_INLINE_VISIBILITY |
| 911 | 916 | constexpr |
| 912 | 917 | value_type& |
| 913 | operator*() & | |
| 918 | operator*() & noexcept | |
| 914 | 919 | { |
| 915 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| 920 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); | |
| 916 | 921 | return this->__get(); |
| 917 | 922 | } |
| 918 | 923 | |
| 919 | 924 | _LIBCPP_INLINE_VISIBILITY |
| 920 | 925 | constexpr |
| 921 | 926 | value_type&& |
| 922 | operator*() && | |
| 927 | operator*() && noexcept | |
| 923 | 928 | { |
| 924 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| 929 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); | |
| 925 | 930 | return _VSTD::move(this->__get()); |
| 926 | 931 | } |
| 927 | 932 | |
| 928 | 933 | _LIBCPP_INLINE_VISIBILITY |
| 929 | 934 | constexpr |
| 930 | 935 | const value_type&& |
| 931 | operator*() const&& | |
| 936 | operator*() const&& noexcept | |
| 932 | 937 | { |
| 933 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| 938 | _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); | |
| 934 | 939 | return _VSTD::move(this->__get()); |
| 935 | 940 | } |
| 936 | 941 | |
| ... | ... | @@ -1005,7 +1010,7 @@ public: |
| 1005 | 1010 | private: |
| 1006 | 1011 | template <class _Up> |
| 1007 | 1012 | _LIBCPP_INLINE_VISIBILITY |
| 1008 | static _Up* | |
| 1013 | static _LIBCPP_CONSTEXPR_AFTER_CXX17 _Up* | |
| 1009 | 1014 | __operator_arrow(true_type, _Up& __x) |
| 1010 | 1015 | { |
| 1011 | 1016 | return _VSTD::addressof(__x); |
| ... | ... | @@ -1029,8 +1034,8 @@ template<class T> |
| 1029 | 1034 | template <class _Tp, class _Up> |
| 1030 | 1035 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1031 | 1036 | _EnableIf< |
| 1032 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == | |
| 1033 | _VSTD::declval<const _Up&>()), bool>, | |
| 1037 | is_convertible_v<decltype(declval<const _Tp&>() == | |
| 1038 | declval<const _Up&>()), bool>, | |
| 1034 | 1039 | bool |
| 1035 | 1040 | > |
| 1036 | 1041 | operator==(const optional<_Tp>& __x, const optional<_Up>& __y) |
| ... | ... | @@ -1045,8 +1050,8 @@ operator==(const optional<_Tp>& __x, const optional<_Up>& __y) |
| 1045 | 1050 | template <class _Tp, class _Up> |
| 1046 | 1051 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1047 | 1052 | _EnableIf< |
| 1048 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != | |
| 1049 | _VSTD::declval<const _Up&>()), bool>, | |
| 1053 | is_convertible_v<decltype(declval<const _Tp&>() != | |
| 1054 | declval<const _Up&>()), bool>, | |
| 1050 | 1055 | bool |
| 1051 | 1056 | > |
| 1052 | 1057 | operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) |
| ... | ... | @@ -1061,8 +1066,8 @@ operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) |
| 1061 | 1066 | template <class _Tp, class _Up> |
| 1062 | 1067 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1063 | 1068 | _EnableIf< |
| 1064 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < | |
| 1065 | _VSTD::declval<const _Up&>()), bool>, | |
| 1069 | is_convertible_v<decltype(declval<const _Tp&>() < | |
| 1070 | declval<const _Up&>()), bool>, | |
| 1066 | 1071 | bool |
| 1067 | 1072 | > |
| 1068 | 1073 | operator<(const optional<_Tp>& __x, const optional<_Up>& __y) |
| ... | ... | @@ -1077,8 +1082,8 @@ operator<(const optional<_Tp>& __x, const optional<_Up>& __y) |
| 1077 | 1082 | template <class _Tp, class _Up> |
| 1078 | 1083 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1079 | 1084 | _EnableIf< |
| 1080 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > | |
| 1081 | _VSTD::declval<const _Up&>()), bool>, | |
| 1085 | is_convertible_v<decltype(declval<const _Tp&>() > | |
| 1086 | declval<const _Up&>()), bool>, | |
| 1082 | 1087 | bool |
| 1083 | 1088 | > |
| 1084 | 1089 | operator>(const optional<_Tp>& __x, const optional<_Up>& __y) |
| ... | ... | @@ -1093,8 +1098,8 @@ operator>(const optional<_Tp>& __x, const optional<_Up>& __y) |
| 1093 | 1098 | template <class _Tp, class _Up> |
| 1094 | 1099 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1095 | 1100 | _EnableIf< |
| 1096 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= | |
| 1097 | _VSTD::declval<const _Up&>()), bool>, | |
| 1101 | is_convertible_v<decltype(declval<const _Tp&>() <= | |
| 1102 | declval<const _Up&>()), bool>, | |
| 1098 | 1103 | bool |
| 1099 | 1104 | > |
| 1100 | 1105 | operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) |
| ... | ... | @@ -1109,8 +1114,8 @@ operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) |
| 1109 | 1114 | template <class _Tp, class _Up> |
| 1110 | 1115 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1111 | 1116 | _EnableIf< |
| 1112 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= | |
| 1113 | _VSTD::declval<const _Up&>()), bool>, | |
| 1117 | is_convertible_v<decltype(declval<const _Tp&>() >= | |
| 1118 | declval<const _Up&>()), bool>, | |
| 1114 | 1119 | bool |
| 1115 | 1120 | > |
| 1116 | 1121 | operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) |
| ... | ... | @@ -1223,8 +1228,8 @@ operator>=(nullopt_t, const optional<_Tp>& __x) noexcept |
| 1223 | 1228 | template <class _Tp, class _Up> |
| 1224 | 1229 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1225 | 1230 | _EnableIf< |
| 1226 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == | |
| 1227 | _VSTD::declval<const _Up&>()), bool>, | |
| 1231 | is_convertible_v<decltype(declval<const _Tp&>() == | |
| 1232 | declval<const _Up&>()), bool>, | |
| 1228 | 1233 | bool |
| 1229 | 1234 | > |
| 1230 | 1235 | operator==(const optional<_Tp>& __x, const _Up& __v) |
| ... | ... | @@ -1235,8 +1240,8 @@ operator==(const optional<_Tp>& __x, const _Up& __v) |
| 1235 | 1240 | template <class _Tp, class _Up> |
| 1236 | 1241 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1237 | 1242 | _EnableIf< |
| 1238 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == | |
| 1239 | _VSTD::declval<const _Up&>()), bool>, | |
| 1243 | is_convertible_v<decltype(declval<const _Tp&>() == | |
| 1244 | declval<const _Up&>()), bool>, | |
| 1240 | 1245 | bool |
| 1241 | 1246 | > |
| 1242 | 1247 | operator==(const _Tp& __v, const optional<_Up>& __x) |
| ... | ... | @@ -1247,8 +1252,8 @@ operator==(const _Tp& __v, const optional<_Up>& __x) |
| 1247 | 1252 | template <class _Tp, class _Up> |
| 1248 | 1253 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1249 | 1254 | _EnableIf< |
| 1250 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != | |
| 1251 | _VSTD::declval<const _Up&>()), bool>, | |
| 1255 | is_convertible_v<decltype(declval<const _Tp&>() != | |
| 1256 | declval<const _Up&>()), bool>, | |
| 1252 | 1257 | bool |
| 1253 | 1258 | > |
| 1254 | 1259 | operator!=(const optional<_Tp>& __x, const _Up& __v) |
| ... | ... | @@ -1259,8 +1264,8 @@ operator!=(const optional<_Tp>& __x, const _Up& __v) |
| 1259 | 1264 | template <class _Tp, class _Up> |
| 1260 | 1265 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1261 | 1266 | _EnableIf< |
| 1262 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != | |
| 1263 | _VSTD::declval<const _Up&>()), bool>, | |
| 1267 | is_convertible_v<decltype(declval<const _Tp&>() != | |
| 1268 | declval<const _Up&>()), bool>, | |
| 1264 | 1269 | bool |
| 1265 | 1270 | > |
| 1266 | 1271 | operator!=(const _Tp& __v, const optional<_Up>& __x) |
| ... | ... | @@ -1271,8 +1276,8 @@ operator!=(const _Tp& __v, const optional<_Up>& __x) |
| 1271 | 1276 | template <class _Tp, class _Up> |
| 1272 | 1277 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1273 | 1278 | _EnableIf< |
| 1274 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < | |
| 1275 | _VSTD::declval<const _Up&>()), bool>, | |
| 1279 | is_convertible_v<decltype(declval<const _Tp&>() < | |
| 1280 | declval<const _Up&>()), bool>, | |
| 1276 | 1281 | bool |
| 1277 | 1282 | > |
| 1278 | 1283 | operator<(const optional<_Tp>& __x, const _Up& __v) |
| ... | ... | @@ -1283,8 +1288,8 @@ operator<(const optional<_Tp>& __x, const _Up& __v) |
| 1283 | 1288 | template <class _Tp, class _Up> |
| 1284 | 1289 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1285 | 1290 | _EnableIf< |
| 1286 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < | |
| 1287 | _VSTD::declval<const _Up&>()), bool>, | |
| 1291 | is_convertible_v<decltype(declval<const _Tp&>() < | |
| 1292 | declval<const _Up&>()), bool>, | |
| 1288 | 1293 | bool |
| 1289 | 1294 | > |
| 1290 | 1295 | operator<(const _Tp& __v, const optional<_Up>& __x) |
| ... | ... | @@ -1295,8 +1300,8 @@ operator<(const _Tp& __v, const optional<_Up>& __x) |
| 1295 | 1300 | template <class _Tp, class _Up> |
| 1296 | 1301 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1297 | 1302 | _EnableIf< |
| 1298 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= | |
| 1299 | _VSTD::declval<const _Up&>()), bool>, | |
| 1303 | is_convertible_v<decltype(declval<const _Tp&>() <= | |
| 1304 | declval<const _Up&>()), bool>, | |
| 1300 | 1305 | bool |
| 1301 | 1306 | > |
| 1302 | 1307 | operator<=(const optional<_Tp>& __x, const _Up& __v) |
| ... | ... | @@ -1307,8 +1312,8 @@ operator<=(const optional<_Tp>& __x, const _Up& __v) |
| 1307 | 1312 | template <class _Tp, class _Up> |
| 1308 | 1313 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1309 | 1314 | _EnableIf< |
| 1310 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= | |
| 1311 | _VSTD::declval<const _Up&>()), bool>, | |
| 1315 | is_convertible_v<decltype(declval<const _Tp&>() <= | |
| 1316 | declval<const _Up&>()), bool>, | |
| 1312 | 1317 | bool |
| 1313 | 1318 | > |
| 1314 | 1319 | operator<=(const _Tp& __v, const optional<_Up>& __x) |
| ... | ... | @@ -1319,8 +1324,8 @@ operator<=(const _Tp& __v, const optional<_Up>& __x) |
| 1319 | 1324 | template <class _Tp, class _Up> |
| 1320 | 1325 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1321 | 1326 | _EnableIf< |
| 1322 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > | |
| 1323 | _VSTD::declval<const _Up&>()), bool>, | |
| 1327 | is_convertible_v<decltype(declval<const _Tp&>() > | |
| 1328 | declval<const _Up&>()), bool>, | |
| 1324 | 1329 | bool |
| 1325 | 1330 | > |
| 1326 | 1331 | operator>(const optional<_Tp>& __x, const _Up& __v) |
| ... | ... | @@ -1331,8 +1336,8 @@ operator>(const optional<_Tp>& __x, const _Up& __v) |
| 1331 | 1336 | template <class _Tp, class _Up> |
| 1332 | 1337 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1333 | 1338 | _EnableIf< |
| 1334 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > | |
| 1335 | _VSTD::declval<const _Up&>()), bool>, | |
| 1339 | is_convertible_v<decltype(declval<const _Tp&>() > | |
| 1340 | declval<const _Up&>()), bool>, | |
| 1336 | 1341 | bool |
| 1337 | 1342 | > |
| 1338 | 1343 | operator>(const _Tp& __v, const optional<_Up>& __x) |
| ... | ... | @@ -1343,8 +1348,8 @@ operator>(const _Tp& __v, const optional<_Up>& __x) |
| 1343 | 1348 | template <class _Tp, class _Up> |
| 1344 | 1349 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1345 | 1350 | _EnableIf< |
| 1346 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= | |
| 1347 | _VSTD::declval<const _Up&>()), bool>, | |
| 1351 | is_convertible_v<decltype(declval<const _Tp&>() >= | |
| 1352 | declval<const _Up&>()), bool>, | |
| 1348 | 1353 | bool |
| 1349 | 1354 | > |
| 1350 | 1355 | operator>=(const optional<_Tp>& __x, const _Up& __v) |
| ... | ... | @@ -1355,8 +1360,8 @@ operator>=(const optional<_Tp>& __x, const _Up& __v) |
| 1355 | 1360 | template <class _Tp, class _Up> |
| 1356 | 1361 | _LIBCPP_INLINE_VISIBILITY constexpr |
| 1357 | 1362 | _EnableIf< |
| 1358 | is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= | |
| 1359 | _VSTD::declval<const _Up&>()), bool>, | |
| 1363 | is_convertible_v<decltype(declval<const _Tp&>() >= | |
| 1364 | declval<const _Up&>()), bool>, | |
| 1360 | 1365 | bool |
| 1361 | 1366 | > |
| 1362 | 1367 | operator>=(const _Tp& __v, const optional<_Up>& __x) |
| ... | ... | @@ -1366,7 +1371,7 @@ operator>=(const _Tp& __v, const optional<_Up>& __x) |
| 1366 | 1371 | |
| 1367 | 1372 | |
| 1368 | 1373 | template <class _Tp> |
| 1369 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1374 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1370 | 1375 | _EnableIf< |
| 1371 | 1376 | is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, |
| 1372 | 1377 | void |
| ... | ... | @@ -1402,11 +1407,13 @@ struct _LIBCPP_TEMPLATE_VIS hash< |
| 1402 | 1407 | __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> |
| 1403 | 1408 | > |
| 1404 | 1409 | { |
| 1405 | typedef optional<_Tp> argument_type; | |
| 1406 | typedef size_t result_type; | |
| 1410 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) | |
| 1411 | _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; | |
| 1412 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; | |
| 1413 | #endif | |
| 1407 | 1414 | |
| 1408 | 1415 | _LIBCPP_INLINE_VISIBILITY |
| 1409 | result_type operator()(const argument_type& __opt) const | |
| 1416 | size_t operator()(const optional<_Tp>& __opt) const | |
| 1410 | 1417 | { |
| 1411 | 1418 | return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; |
| 1412 | 1419 | } |
| ... | ... | @@ -1414,8 +1421,8 @@ struct _LIBCPP_TEMPLATE_VIS hash< |
| 1414 | 1421 | |
| 1415 | 1422 | _LIBCPP_END_NAMESPACE_STD |
| 1416 | 1423 | |
| 1417 | #endif // _LIBCPP_STD_VER > 14 | |
| 1424 | #endif // _LIBCPP_STD_VER > 14 | |
| 1418 | 1425 | |
| 1419 | 1426 | _LIBCPP_POP_MACROS |
| 1420 | 1427 | |
| 1421 | #endif // _LIBCPP_OPTIONAL | |
| 1428 | #endif // _LIBCPP_OPTIONAL |
lib/libcxx/include/ostream+53-68| ... | ... | @@ -134,11 +134,11 @@ template <class Stream, class T> |
| 134 | 134 | */ |
| 135 | 135 | |
| 136 | 136 | #include <__config> |
| 137 | #include <bitset> | |
| 137 | 138 | #include <ios> |
| 138 | #include <streambuf> | |
| 139 | #include <locale> | |
| 140 | 139 | #include <iterator> |
| 141 | #include <bitset> | |
| 140 | #include <locale> | |
| 141 | #include <streambuf> | |
| 142 | 142 | #include <version> |
| 143 | 143 | |
| 144 | 144 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -165,27 +165,21 @@ public: |
| 165 | 165 | { this->init(__sb); } |
| 166 | 166 | virtual ~basic_ostream(); |
| 167 | 167 | protected: |
| 168 | #ifndef _LIBCPP_CXX03_LANG | |
| 169 | 168 | inline _LIBCPP_INLINE_VISIBILITY |
| 170 | 169 | basic_ostream(basic_ostream&& __rhs); |
| 171 | 170 | |
| 172 | 171 | // 27.7.2.3 Assign/swap |
| 173 | 172 | inline _LIBCPP_INLINE_VISIBILITY |
| 174 | 173 | basic_ostream& operator=(basic_ostream&& __rhs); |
| 175 | #endif | |
| 174 | ||
| 176 | 175 | inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 |
| 177 | 176 | void swap(basic_ostream& __rhs) |
| 178 | 177 | { basic_ios<char_type, traits_type>::swap(__rhs); } |
| 179 | 178 | |
| 180 | #ifndef _LIBCPP_CXX03_LANG | |
| 181 | 179 | basic_ostream (const basic_ostream& __rhs) = delete; |
| 182 | 180 | basic_ostream& operator=(const basic_ostream& __rhs) = delete; |
| 183 | #else | |
| 184 | basic_ostream (const basic_ostream& __rhs); // not defined | |
| 185 | basic_ostream& operator=(const basic_ostream& __rhs); // not defined | |
| 186 | #endif | |
| 187 | public: | |
| 188 | 181 | |
| 182 | public: | |
| 189 | 183 | // 27.7.2.4 Prefix/suffix: |
| 190 | 184 | class _LIBCPP_TEMPLATE_VIS sentry; |
| 191 | 185 | |
| ... | ... | @@ -254,8 +248,7 @@ public: |
| 254 | 248 | ~sentry(); |
| 255 | 249 | |
| 256 | 250 | _LIBCPP_INLINE_VISIBILITY |
| 257 | _LIBCPP_EXPLICIT | |
| 258 | operator bool() const {return __ok_;} | |
| 251 | explicit operator bool() const {return __ok_;} | |
| 259 | 252 | }; |
| 260 | 253 | |
| 261 | 254 | template <class _CharT, class _Traits> |
| ... | ... | @@ -280,7 +273,7 @@ basic_ostream<_CharT, _Traits>::sentry::~sentry() |
| 280 | 273 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 281 | 274 | try |
| 282 | 275 | { |
| 283 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 276 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 284 | 277 | if (__os_.rdbuf()->pubsync() == -1) |
| 285 | 278 | __os_.setstate(ios_base::badbit); |
| 286 | 279 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -288,12 +281,10 @@ basic_ostream<_CharT, _Traits>::sentry::~sentry() |
| 288 | 281 | catch (...) |
| 289 | 282 | { |
| 290 | 283 | } |
| 291 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 284 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 292 | 285 | } |
| 293 | 286 | } |
| 294 | 287 | |
| 295 | #ifndef _LIBCPP_CXX03_LANG | |
| 296 | ||
| 297 | 288 | template <class _CharT, class _Traits> |
| 298 | 289 | basic_ostream<_CharT, _Traits>::basic_ostream(basic_ostream&& __rhs) |
| 299 | 290 | { |
| ... | ... | @@ -308,8 +299,6 @@ basic_ostream<_CharT, _Traits>::operator=(basic_ostream&& __rhs) |
| 308 | 299 | return *this; |
| 309 | 300 | } |
| 310 | 301 | |
| 311 | #endif // _LIBCPP_CXX03_LANG | |
| 312 | ||
| 313 | 302 | template <class _CharT, class _Traits> |
| 314 | 303 | basic_ostream<_CharT, _Traits>::~basic_ostream() |
| 315 | 304 | { |
| ... | ... | @@ -322,7 +311,7 @@ basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<char_type, traits_typ |
| 322 | 311 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 323 | 312 | try |
| 324 | 313 | { |
| 325 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 314 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 326 | 315 | sentry __s(*this); |
| 327 | 316 | if (__s) |
| 328 | 317 | { |
| ... | ... | @@ -331,7 +320,7 @@ basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<char_type, traits_typ |
| 331 | 320 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 332 | 321 | try |
| 333 | 322 | { |
| 334 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 323 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 335 | 324 | typedef istreambuf_iterator<_CharT, _Traits> _Ip; |
| 336 | 325 | typedef ostreambuf_iterator<_CharT, _Traits> _Op; |
| 337 | 326 | _Ip __i(__sb); |
| ... | ... | @@ -352,7 +341,7 @@ basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<char_type, traits_typ |
| 352 | 341 | { |
| 353 | 342 | this->__set_failbit_and_consider_rethrow(); |
| 354 | 343 | } |
| 355 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 344 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 356 | 345 | } |
| 357 | 346 | else |
| 358 | 347 | this->setstate(ios_base::badbit); |
| ... | ... | @@ -363,7 +352,7 @@ basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<char_type, traits_typ |
| 363 | 352 | { |
| 364 | 353 | this->__set_badbit_and_consider_rethrow(); |
| 365 | 354 | } |
| 366 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 355 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 367 | 356 | return *this; |
| 368 | 357 | } |
| 369 | 358 | |
| ... | ... | @@ -374,7 +363,7 @@ basic_ostream<_CharT, _Traits>::operator<<(bool __n) |
| 374 | 363 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 375 | 364 | try |
| 376 | 365 | { |
| 377 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 366 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 378 | 367 | sentry __s(*this); |
| 379 | 368 | if (__s) |
| 380 | 369 | { |
| ... | ... | @@ -389,7 +378,7 @@ basic_ostream<_CharT, _Traits>::operator<<(bool __n) |
| 389 | 378 | { |
| 390 | 379 | this->__set_badbit_and_consider_rethrow(); |
| 391 | 380 | } |
| 392 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 381 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 393 | 382 | return *this; |
| 394 | 383 | } |
| 395 | 384 | |
| ... | ... | @@ -400,7 +389,7 @@ basic_ostream<_CharT, _Traits>::operator<<(short __n) |
| 400 | 389 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 401 | 390 | try |
| 402 | 391 | { |
| 403 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 392 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 404 | 393 | sentry __s(*this); |
| 405 | 394 | if (__s) |
| 406 | 395 | { |
| ... | ... | @@ -419,7 +408,7 @@ basic_ostream<_CharT, _Traits>::operator<<(short __n) |
| 419 | 408 | { |
| 420 | 409 | this->__set_badbit_and_consider_rethrow(); |
| 421 | 410 | } |
| 422 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 411 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 423 | 412 | return *this; |
| 424 | 413 | } |
| 425 | 414 | |
| ... | ... | @@ -430,7 +419,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned short __n) |
| 430 | 419 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 431 | 420 | try |
| 432 | 421 | { |
| 433 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 422 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 434 | 423 | sentry __s(*this); |
| 435 | 424 | if (__s) |
| 436 | 425 | { |
| ... | ... | @@ -445,7 +434,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned short __n) |
| 445 | 434 | { |
| 446 | 435 | this->__set_badbit_and_consider_rethrow(); |
| 447 | 436 | } |
| 448 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 437 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 449 | 438 | return *this; |
| 450 | 439 | } |
| 451 | 440 | |
| ... | ... | @@ -456,7 +445,7 @@ basic_ostream<_CharT, _Traits>::operator<<(int __n) |
| 456 | 445 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 457 | 446 | try |
| 458 | 447 | { |
| 459 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 448 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 460 | 449 | sentry __s(*this); |
| 461 | 450 | if (__s) |
| 462 | 451 | { |
| ... | ... | @@ -475,7 +464,7 @@ basic_ostream<_CharT, _Traits>::operator<<(int __n) |
| 475 | 464 | { |
| 476 | 465 | this->__set_badbit_and_consider_rethrow(); |
| 477 | 466 | } |
| 478 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 467 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 479 | 468 | return *this; |
| 480 | 469 | } |
| 481 | 470 | |
| ... | ... | @@ -486,7 +475,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned int __n) |
| 486 | 475 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 487 | 476 | try |
| 488 | 477 | { |
| 489 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 478 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 490 | 479 | sentry __s(*this); |
| 491 | 480 | if (__s) |
| 492 | 481 | { |
| ... | ... | @@ -501,7 +490,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned int __n) |
| 501 | 490 | { |
| 502 | 491 | this->__set_badbit_and_consider_rethrow(); |
| 503 | 492 | } |
| 504 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 493 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 505 | 494 | return *this; |
| 506 | 495 | } |
| 507 | 496 | |
| ... | ... | @@ -512,7 +501,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long __n) |
| 512 | 501 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 513 | 502 | try |
| 514 | 503 | { |
| 515 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 504 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 516 | 505 | sentry __s(*this); |
| 517 | 506 | if (__s) |
| 518 | 507 | { |
| ... | ... | @@ -527,7 +516,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long __n) |
| 527 | 516 | { |
| 528 | 517 | this->__set_badbit_and_consider_rethrow(); |
| 529 | 518 | } |
| 530 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 519 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 531 | 520 | return *this; |
| 532 | 521 | } |
| 533 | 522 | |
| ... | ... | @@ -538,7 +527,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n) |
| 538 | 527 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 539 | 528 | try |
| 540 | 529 | { |
| 541 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 530 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 542 | 531 | sentry __s(*this); |
| 543 | 532 | if (__s) |
| 544 | 533 | { |
| ... | ... | @@ -553,7 +542,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n) |
| 553 | 542 | { |
| 554 | 543 | this->__set_badbit_and_consider_rethrow(); |
| 555 | 544 | } |
| 556 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 545 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 557 | 546 | return *this; |
| 558 | 547 | } |
| 559 | 548 | |
| ... | ... | @@ -564,7 +553,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long long __n) |
| 564 | 553 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 565 | 554 | try |
| 566 | 555 | { |
| 567 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 556 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 568 | 557 | sentry __s(*this); |
| 569 | 558 | if (__s) |
| 570 | 559 | { |
| ... | ... | @@ -579,7 +568,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long long __n) |
| 579 | 568 | { |
| 580 | 569 | this->__set_badbit_and_consider_rethrow(); |
| 581 | 570 | } |
| 582 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 571 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 583 | 572 | return *this; |
| 584 | 573 | } |
| 585 | 574 | |
| ... | ... | @@ -590,7 +579,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) |
| 590 | 579 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 591 | 580 | try |
| 592 | 581 | { |
| 593 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 582 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 594 | 583 | sentry __s(*this); |
| 595 | 584 | if (__s) |
| 596 | 585 | { |
| ... | ... | @@ -605,7 +594,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) |
| 605 | 594 | { |
| 606 | 595 | this->__set_badbit_and_consider_rethrow(); |
| 607 | 596 | } |
| 608 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 597 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 609 | 598 | return *this; |
| 610 | 599 | } |
| 611 | 600 | |
| ... | ... | @@ -616,7 +605,7 @@ basic_ostream<_CharT, _Traits>::operator<<(float __n) |
| 616 | 605 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 617 | 606 | try |
| 618 | 607 | { |
| 619 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 608 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 620 | 609 | sentry __s(*this); |
| 621 | 610 | if (__s) |
| 622 | 611 | { |
| ... | ... | @@ -631,7 +620,7 @@ basic_ostream<_CharT, _Traits>::operator<<(float __n) |
| 631 | 620 | { |
| 632 | 621 | this->__set_badbit_and_consider_rethrow(); |
| 633 | 622 | } |
| 634 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 623 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 635 | 624 | return *this; |
| 636 | 625 | } |
| 637 | 626 | |
| ... | ... | @@ -642,7 +631,7 @@ basic_ostream<_CharT, _Traits>::operator<<(double __n) |
| 642 | 631 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 643 | 632 | try |
| 644 | 633 | { |
| 645 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 634 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 646 | 635 | sentry __s(*this); |
| 647 | 636 | if (__s) |
| 648 | 637 | { |
| ... | ... | @@ -657,7 +646,7 @@ basic_ostream<_CharT, _Traits>::operator<<(double __n) |
| 657 | 646 | { |
| 658 | 647 | this->__set_badbit_and_consider_rethrow(); |
| 659 | 648 | } |
| 660 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 649 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 661 | 650 | return *this; |
| 662 | 651 | } |
| 663 | 652 | |
| ... | ... | @@ -668,7 +657,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long double __n) |
| 668 | 657 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 669 | 658 | try |
| 670 | 659 | { |
| 671 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 660 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 672 | 661 | sentry __s(*this); |
| 673 | 662 | if (__s) |
| 674 | 663 | { |
| ... | ... | @@ -683,7 +672,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long double __n) |
| 683 | 672 | { |
| 684 | 673 | this->__set_badbit_and_consider_rethrow(); |
| 685 | 674 | } |
| 686 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 675 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 687 | 676 | return *this; |
| 688 | 677 | } |
| 689 | 678 | |
| ... | ... | @@ -694,7 +683,7 @@ basic_ostream<_CharT, _Traits>::operator<<(const void* __n) |
| 694 | 683 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 695 | 684 | try |
| 696 | 685 | { |
| 697 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 686 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 698 | 687 | sentry __s(*this); |
| 699 | 688 | if (__s) |
| 700 | 689 | { |
| ... | ... | @@ -709,7 +698,7 @@ basic_ostream<_CharT, _Traits>::operator<<(const void* __n) |
| 709 | 698 | { |
| 710 | 699 | this->__set_badbit_and_consider_rethrow(); |
| 711 | 700 | } |
| 712 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 701 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 713 | 702 | return *this; |
| 714 | 703 | } |
| 715 | 704 | |
| ... | ... | @@ -721,7 +710,7 @@ __put_character_sequence(basic_ostream<_CharT, _Traits>& __os, |
| 721 | 710 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 722 | 711 | try |
| 723 | 712 | { |
| 724 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 713 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 725 | 714 | typename basic_ostream<_CharT, _Traits>::sentry __s(__os); |
| 726 | 715 | if (__s) |
| 727 | 716 | { |
| ... | ... | @@ -742,7 +731,7 @@ __put_character_sequence(basic_ostream<_CharT, _Traits>& __os, |
| 742 | 731 | { |
| 743 | 732 | __os.__set_badbit_and_consider_rethrow(); |
| 744 | 733 | } |
| 745 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 734 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 746 | 735 | return __os; |
| 747 | 736 | } |
| 748 | 737 | |
| ... | ... | @@ -761,7 +750,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, char __cn) |
| 761 | 750 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 762 | 751 | try |
| 763 | 752 | { |
| 764 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 753 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 765 | 754 | typename basic_ostream<_CharT, _Traits>::sentry __s(__os); |
| 766 | 755 | if (__s) |
| 767 | 756 | { |
| ... | ... | @@ -783,7 +772,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, char __cn) |
| 783 | 772 | { |
| 784 | 773 | __os.__set_badbit_and_consider_rethrow(); |
| 785 | 774 | } |
| 786 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 775 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 787 | 776 | return __os; |
| 788 | 777 | } |
| 789 | 778 | |
| ... | ... | @@ -822,7 +811,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const char* __strn) |
| 822 | 811 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 823 | 812 | try |
| 824 | 813 | { |
| 825 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 814 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 826 | 815 | typename basic_ostream<_CharT, _Traits>::sentry __s(__os); |
| 827 | 816 | if (__s) |
| 828 | 817 | { |
| ... | ... | @@ -857,7 +846,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const char* __strn) |
| 857 | 846 | { |
| 858 | 847 | __os.__set_badbit_and_consider_rethrow(); |
| 859 | 848 | } |
| 860 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 849 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 861 | 850 | return __os; |
| 862 | 851 | } |
| 863 | 852 | |
| ... | ... | @@ -891,7 +880,7 @@ basic_ostream<_CharT, _Traits>::put(char_type __c) |
| 891 | 880 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 892 | 881 | try |
| 893 | 882 | { |
| 894 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 883 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 895 | 884 | sentry __s(*this); |
| 896 | 885 | if (__s) |
| 897 | 886 | { |
| ... | ... | @@ -907,7 +896,7 @@ basic_ostream<_CharT, _Traits>::put(char_type __c) |
| 907 | 896 | { |
| 908 | 897 | this->__set_badbit_and_consider_rethrow(); |
| 909 | 898 | } |
| 910 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 899 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 911 | 900 | return *this; |
| 912 | 901 | } |
| 913 | 902 | |
| ... | ... | @@ -918,7 +907,7 @@ basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) |
| 918 | 907 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 919 | 908 | try |
| 920 | 909 | { |
| 921 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 910 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 922 | 911 | sentry __sen(*this); |
| 923 | 912 | if (__sen && __n) |
| 924 | 913 | { |
| ... | ... | @@ -931,7 +920,7 @@ basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) |
| 931 | 920 | { |
| 932 | 921 | this->__set_badbit_and_consider_rethrow(); |
| 933 | 922 | } |
| 934 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 923 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 935 | 924 | return *this; |
| 936 | 925 | } |
| 937 | 926 | |
| ... | ... | @@ -942,7 +931,7 @@ basic_ostream<_CharT, _Traits>::flush() |
| 942 | 931 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 943 | 932 | try |
| 944 | 933 | { |
| 945 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 934 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 946 | 935 | if (this->rdbuf()) |
| 947 | 936 | { |
| 948 | 937 | sentry __s(*this); |
| ... | ... | @@ -958,7 +947,7 @@ basic_ostream<_CharT, _Traits>::flush() |
| 958 | 947 | { |
| 959 | 948 | this->__set_badbit_and_consider_rethrow(); |
| 960 | 949 | } |
| 961 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 950 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 962 | 951 | return *this; |
| 963 | 952 | } |
| 964 | 953 | |
| ... | ... | @@ -1025,19 +1014,17 @@ flush(basic_ostream<_CharT, _Traits>& __os) |
| 1025 | 1014 | return __os; |
| 1026 | 1015 | } |
| 1027 | 1016 | |
| 1028 | #ifndef _LIBCPP_CXX03_LANG | |
| 1029 | ||
| 1030 | 1017 | template <class _Stream, class _Tp, class = void> |
| 1031 | 1018 | struct __is_ostreamable : false_type { }; |
| 1032 | 1019 | |
| 1033 | 1020 | template <class _Stream, class _Tp> |
| 1034 | 1021 | struct __is_ostreamable<_Stream, _Tp, decltype( |
| 1035 | _VSTD::declval<_Stream>() << _VSTD::declval<_Tp>(), void() | |
| 1022 | declval<_Stream>() << declval<_Tp>(), void() | |
| 1036 | 1023 | )> : true_type { }; |
| 1037 | 1024 | |
| 1038 | 1025 | template <class _Stream, class _Tp, class = typename enable_if< |
| 1039 | 1026 | _And<is_base_of<ios_base, _Stream>, |
| 1040 | __is_ostreamable<_Stream&, const _Tp&>>::value | |
| 1027 | __is_ostreamable<_Stream&, const _Tp&> >::value | |
| 1041 | 1028 | >::type> |
| 1042 | 1029 | _LIBCPP_INLINE_VISIBILITY |
| 1043 | 1030 | _Stream&& operator<<(_Stream&& __os, const _Tp& __x) |
| ... | ... | @@ -1046,8 +1033,6 @@ _Stream&& operator<<(_Stream&& __os, const _Tp& __x) |
| 1046 | 1033 | return _VSTD::move(__os); |
| 1047 | 1034 | } |
| 1048 | 1035 | |
| 1049 | #endif // _LIBCPP_CXX03_LANG | |
| 1050 | ||
| 1051 | 1036 | template<class _CharT, class _Traits, class _Allocator> |
| 1052 | 1037 | basic_ostream<_CharT, _Traits>& |
| 1053 | 1038 | operator<<(basic_ostream<_CharT, _Traits>& __os, |
| ... | ... | @@ -1106,4 +1091,4 @@ _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<wch |
| 1106 | 1091 | |
| 1107 | 1092 | _LIBCPP_END_NAMESPACE_STD |
| 1108 | 1093 | |
| 1109 | #endif // _LIBCPP_OSTREAM | |
| 1094 | #endif // _LIBCPP_OSTREAM |
lib/libcxx/include/queue+53-71| ... | ... | @@ -179,10 +179,13 @@ template <class T, class Container, class Compare> |
| 179 | 179 | */ |
| 180 | 180 | |
| 181 | 181 | #include <__config> |
| 182 | #include <__memory/uses_allocator.h> | |
| 183 | #include <__utility/forward.h> | |
| 184 | #include <algorithm> | |
| 185 | #include <compare> | |
| 182 | 186 | #include <deque> |
| 183 | #include <vector> | |
| 184 | 187 | #include <functional> |
| 185 | #include <algorithm> | |
| 188 | #include <vector> | |
| 186 | 189 | |
| 187 | 190 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 188 | 191 | #pragma GCC system_header |
| ... | ... | @@ -238,47 +241,42 @@ public: |
| 238 | 241 | queue& operator=(queue&& __q) |
| 239 | 242 | _NOEXCEPT_(is_nothrow_move_assignable<container_type>::value) |
| 240 | 243 | {c = _VSTD::move(__q.c); return *this;} |
| 241 | #endif // _LIBCPP_CXX03_LANG | |
| 244 | #endif // _LIBCPP_CXX03_LANG | |
| 242 | 245 | |
| 243 | 246 | _LIBCPP_INLINE_VISIBILITY |
| 244 | 247 | explicit queue(const container_type& __c) : c(__c) {} |
| 245 | 248 | #ifndef _LIBCPP_CXX03_LANG |
| 246 | 249 | _LIBCPP_INLINE_VISIBILITY |
| 247 | 250 | explicit queue(container_type&& __c) : c(_VSTD::move(__c)) {} |
| 248 | #endif // _LIBCPP_CXX03_LANG | |
| 251 | #endif // _LIBCPP_CXX03_LANG | |
| 249 | 252 | template <class _Alloc> |
| 250 | 253 | _LIBCPP_INLINE_VISIBILITY |
| 251 | 254 | explicit queue(const _Alloc& __a, |
| 252 | typename enable_if<uses_allocator<container_type, | |
| 253 | _Alloc>::value>::type* = 0) | |
| 255 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 254 | 256 | : c(__a) {} |
| 255 | 257 | template <class _Alloc> |
| 256 | 258 | _LIBCPP_INLINE_VISIBILITY |
| 257 | 259 | queue(const queue& __q, const _Alloc& __a, |
| 258 | typename enable_if<uses_allocator<container_type, | |
| 259 | _Alloc>::value>::type* = 0) | |
| 260 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 260 | 261 | : c(__q.c, __a) {} |
| 261 | 262 | template <class _Alloc> |
| 262 | 263 | _LIBCPP_INLINE_VISIBILITY |
| 263 | 264 | queue(const container_type& __c, const _Alloc& __a, |
| 264 | typename enable_if<uses_allocator<container_type, | |
| 265 | _Alloc>::value>::type* = 0) | |
| 265 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 266 | 266 | : c(__c, __a) {} |
| 267 | 267 | #ifndef _LIBCPP_CXX03_LANG |
| 268 | 268 | template <class _Alloc> |
| 269 | 269 | _LIBCPP_INLINE_VISIBILITY |
| 270 | 270 | queue(container_type&& __c, const _Alloc& __a, |
| 271 | typename enable_if<uses_allocator<container_type, | |
| 272 | _Alloc>::value>::type* = 0) | |
| 271 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 273 | 272 | : c(_VSTD::move(__c), __a) {} |
| 274 | 273 | template <class _Alloc> |
| 275 | 274 | _LIBCPP_INLINE_VISIBILITY |
| 276 | 275 | queue(queue&& __q, const _Alloc& __a, |
| 277 | typename enable_if<uses_allocator<container_type, | |
| 278 | _Alloc>::value>::type* = 0) | |
| 276 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 279 | 277 | : c(_VSTD::move(__q.c), __a) {} |
| 280 | 278 | |
| 281 | #endif // _LIBCPP_CXX03_LANG | |
| 279 | #endif // _LIBCPP_CXX03_LANG | |
| 282 | 280 | |
| 283 | 281 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY |
| 284 | 282 | bool empty() const {return c.empty();} |
| ... | ... | @@ -308,7 +306,7 @@ public: |
| 308 | 306 | void emplace(_Args&&... __args) |
| 309 | 307 | { c.emplace_back(_VSTD::forward<_Args>(__args)...);} |
| 310 | 308 | #endif |
| 311 | #endif // _LIBCPP_CXX03_LANG | |
| 309 | #endif // _LIBCPP_CXX03_LANG | |
| 312 | 310 | _LIBCPP_INLINE_VISIBILITY |
| 313 | 311 | void pop() {c.pop_front();} |
| 314 | 312 | |
| ... | ... | @@ -335,15 +333,15 @@ public: |
| 335 | 333 | |
| 336 | 334 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 337 | 335 | template<class _Container, |
| 338 | class = typename enable_if<!__is_allocator<_Container>::value, nullptr_t>::type | |
| 336 | class = _EnableIf<!__is_allocator<_Container>::value> | |
| 339 | 337 | > |
| 340 | 338 | queue(_Container) |
| 341 | 339 | -> queue<typename _Container::value_type, _Container>; |
| 342 | 340 | |
| 343 | 341 | template<class _Container, |
| 344 | 342 | class _Alloc, |
| 345 | class = typename enable_if<!__is_allocator<_Container>::value, nullptr_t>::type, | |
| 346 | class = typename enable_if< __is_allocator<_Alloc>::value, nullptr_t>::type | |
| 343 | class = _EnableIf<!__is_allocator<_Container>::value>, | |
| 344 | class = _EnableIf<uses_allocator<_Container, _Alloc>::value> | |
| 347 | 345 | > |
| 348 | 346 | queue(_Container, _Alloc) |
| 349 | 347 | -> queue<typename _Container::value_type, _Container>; |
| ... | ... | @@ -399,10 +397,7 @@ operator<=(const queue<_Tp, _Container>& __x,const queue<_Tp, _Container>& __y) |
| 399 | 397 | |
| 400 | 398 | template <class _Tp, class _Container> |
| 401 | 399 | inline _LIBCPP_INLINE_VISIBILITY |
| 402 | typename enable_if< | |
| 403 | __is_swappable<_Container>::value, | |
| 404 | void | |
| 405 | >::type | |
| 400 | _EnableIf<__is_swappable<_Container>::value, void> | |
| 406 | 401 | swap(queue<_Tp, _Container>& __x, queue<_Tp, _Container>& __y) |
| 407 | 402 | _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) |
| 408 | 403 | { |
| ... | ... | @@ -458,7 +453,7 @@ public: |
| 458 | 453 | _NOEXCEPT_(is_nothrow_move_assignable<container_type>::value && |
| 459 | 454 | is_nothrow_move_assignable<value_compare>::value) |
| 460 | 455 | {c = _VSTD::move(__q.c); comp = _VSTD::move(__q.comp); return *this;} |
| 461 | #endif // _LIBCPP_CXX03_LANG | |
| 456 | #endif // _LIBCPP_CXX03_LANG | |
| 462 | 457 | |
| 463 | 458 | _LIBCPP_INLINE_VISIBILITY |
| 464 | 459 | explicit priority_queue(const value_compare& __comp) |
| ... | ... | @@ -482,41 +477,35 @@ public: |
| 482 | 477 | _LIBCPP_INLINE_VISIBILITY |
| 483 | 478 | priority_queue(_InputIter __f, _InputIter __l, |
| 484 | 479 | const value_compare& __comp, container_type&& __c); |
| 485 | #endif // _LIBCPP_CXX03_LANG | |
| 480 | #endif // _LIBCPP_CXX03_LANG | |
| 486 | 481 | template <class _Alloc> |
| 487 | 482 | _LIBCPP_INLINE_VISIBILITY |
| 488 | 483 | explicit priority_queue(const _Alloc& __a, |
| 489 | typename enable_if<uses_allocator<container_type, | |
| 490 | _Alloc>::value>::type* = 0); | |
| 484 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0); | |
| 491 | 485 | template <class _Alloc> |
| 492 | 486 | _LIBCPP_INLINE_VISIBILITY |
| 493 | 487 | priority_queue(const value_compare& __comp, const _Alloc& __a, |
| 494 | typename enable_if<uses_allocator<container_type, | |
| 495 | _Alloc>::value>::type* = 0); | |
| 488 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0); | |
| 496 | 489 | template <class _Alloc> |
| 497 | 490 | _LIBCPP_INLINE_VISIBILITY |
| 498 | 491 | priority_queue(const value_compare& __comp, const container_type& __c, |
| 499 | 492 | const _Alloc& __a, |
| 500 | typename enable_if<uses_allocator<container_type, | |
| 501 | _Alloc>::value>::type* = 0); | |
| 493 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0); | |
| 502 | 494 | template <class _Alloc> |
| 503 | 495 | _LIBCPP_INLINE_VISIBILITY |
| 504 | 496 | priority_queue(const priority_queue& __q, const _Alloc& __a, |
| 505 | typename enable_if<uses_allocator<container_type, | |
| 506 | _Alloc>::value>::type* = 0); | |
| 497 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0); | |
| 507 | 498 | #ifndef _LIBCPP_CXX03_LANG |
| 508 | 499 | template <class _Alloc> |
| 509 | 500 | _LIBCPP_INLINE_VISIBILITY |
| 510 | 501 | priority_queue(const value_compare& __comp, container_type&& __c, |
| 511 | 502 | const _Alloc& __a, |
| 512 | typename enable_if<uses_allocator<container_type, | |
| 513 | _Alloc>::value>::type* = 0); | |
| 503 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0); | |
| 514 | 504 | template <class _Alloc> |
| 515 | 505 | _LIBCPP_INLINE_VISIBILITY |
| 516 | 506 | priority_queue(priority_queue&& __q, const _Alloc& __a, |
| 517 | typename enable_if<uses_allocator<container_type, | |
| 518 | _Alloc>::value>::type* = 0); | |
| 519 | #endif // _LIBCPP_CXX03_LANG | |
| 507 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0); | |
| 508 | #endif // _LIBCPP_CXX03_LANG | |
| 520 | 509 | |
| 521 | 510 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY |
| 522 | 511 | bool empty() const {return c.empty();} |
| ... | ... | @@ -533,7 +522,7 @@ public: |
| 533 | 522 | template <class... _Args> |
| 534 | 523 | _LIBCPP_INLINE_VISIBILITY |
| 535 | 524 | void emplace(_Args&&... __args); |
| 536 | #endif // _LIBCPP_CXX03_LANG | |
| 525 | #endif // _LIBCPP_CXX03_LANG | |
| 537 | 526 | _LIBCPP_INLINE_VISIBILITY |
| 538 | 527 | void pop(); |
| 539 | 528 | |
| ... | ... | @@ -546,28 +535,28 @@ public: |
| 546 | 535 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 547 | 536 | template <class _Compare, |
| 548 | 537 | class _Container, |
| 549 | class = typename enable_if<!__is_allocator<_Compare>::value, nullptr_t>::type, | |
| 550 | class = typename enable_if<!__is_allocator<_Container>::value, nullptr_t>::type | |
| 538 | class = _EnableIf<!__is_allocator<_Compare>::value>, | |
| 539 | class = _EnableIf<!__is_allocator<_Container>::value> | |
| 551 | 540 | > |
| 552 | 541 | priority_queue(_Compare, _Container) |
| 553 | 542 | -> priority_queue<typename _Container::value_type, _Container, _Compare>; |
| 554 | 543 | |
| 555 | 544 | template<class _InputIterator, |
| 556 | class _Compare = less<typename iterator_traits<_InputIterator>::value_type>, | |
| 557 | class _Container = vector<typename iterator_traits<_InputIterator>::value_type>, | |
| 558 | class = typename enable_if< __is_cpp17_input_iterator<_InputIterator>::value, nullptr_t>::type, | |
| 559 | class = typename enable_if<!__is_allocator<_Compare>::value, nullptr_t>::type, | |
| 560 | class = typename enable_if<!__is_allocator<_Container>::value, nullptr_t>::type | |
| 545 | class _Compare = less<__iter_value_type<_InputIterator>>, | |
| 546 | class _Container = vector<__iter_value_type<_InputIterator>>, | |
| 547 | class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value>, | |
| 548 | class = _EnableIf<!__is_allocator<_Compare>::value>, | |
| 549 | class = _EnableIf<!__is_allocator<_Container>::value> | |
| 561 | 550 | > |
| 562 | 551 | priority_queue(_InputIterator, _InputIterator, _Compare = _Compare(), _Container = _Container()) |
| 563 | -> priority_queue<typename iterator_traits<_InputIterator>::value_type, _Container, _Compare>; | |
| 552 | -> priority_queue<__iter_value_type<_InputIterator>, _Container, _Compare>; | |
| 564 | 553 | |
| 565 | 554 | template<class _Compare, |
| 566 | 555 | class _Container, |
| 567 | 556 | class _Alloc, |
| 568 | class = typename enable_if<!__is_allocator<_Compare>::value, nullptr_t>::type, | |
| 569 | class = typename enable_if<!__is_allocator<_Container>::value, nullptr_t>::type, | |
| 570 | class = typename enable_if< __is_allocator<_Alloc>::value, nullptr_t>::type | |
| 557 | class = _EnableIf<!__is_allocator<_Compare>::value>, | |
| 558 | class = _EnableIf<!__is_allocator<_Container>::value>, | |
| 559 | class = _EnableIf<uses_allocator<_Container, _Alloc>::value> | |
| 571 | 560 | > |
| 572 | 561 | priority_queue(_Compare, _Container, _Alloc) |
| 573 | 562 | -> priority_queue<typename _Container::value_type, _Container, _Compare>; |
| ... | ... | @@ -595,7 +584,7 @@ priority_queue<_Tp, _Container, _Compare>::priority_queue(const value_compare& _ |
| 595 | 584 | _VSTD::make_heap(c.begin(), c.end(), comp); |
| 596 | 585 | } |
| 597 | 586 | |
| 598 | #endif // _LIBCPP_CXX03_LANG | |
| 587 | #endif // _LIBCPP_CXX03_LANG | |
| 599 | 588 | |
| 600 | 589 | template <class _Tp, class _Container, class _Compare> |
| 601 | 590 | template <class _InputIter> |
| ... | ... | @@ -636,14 +625,13 @@ priority_queue<_Tp, _Container, _Compare>::priority_queue(_InputIter __f, _Input |
| 636 | 625 | _VSTD::make_heap(c.begin(), c.end(), comp); |
| 637 | 626 | } |
| 638 | 627 | |
| 639 | #endif // _LIBCPP_CXX03_LANG | |
| 628 | #endif // _LIBCPP_CXX03_LANG | |
| 640 | 629 | |
| 641 | 630 | template <class _Tp, class _Container, class _Compare> |
| 642 | 631 | template <class _Alloc> |
| 643 | 632 | inline |
| 644 | 633 | priority_queue<_Tp, _Container, _Compare>::priority_queue(const _Alloc& __a, |
| 645 | typename enable_if<uses_allocator<container_type, | |
| 646 | _Alloc>::value>::type*) | |
| 634 | _EnableIf<uses_allocator<container_type, _Alloc>::value>*) | |
| 647 | 635 | : c(__a) |
| 648 | 636 | { |
| 649 | 637 | } |
| ... | ... | @@ -653,8 +641,7 @@ template <class _Alloc> |
| 653 | 641 | inline |
| 654 | 642 | priority_queue<_Tp, _Container, _Compare>::priority_queue(const value_compare& __comp, |
| 655 | 643 | const _Alloc& __a, |
| 656 | typename enable_if<uses_allocator<container_type, | |
| 657 | _Alloc>::value>::type*) | |
| 644 | _EnableIf<uses_allocator<container_type, _Alloc>::value>*) | |
| 658 | 645 | : c(__a), |
| 659 | 646 | comp(__comp) |
| 660 | 647 | { |
| ... | ... | @@ -666,8 +653,7 @@ inline |
| 666 | 653 | priority_queue<_Tp, _Container, _Compare>::priority_queue(const value_compare& __comp, |
| 667 | 654 | const container_type& __c, |
| 668 | 655 | const _Alloc& __a, |
| 669 | typename enable_if<uses_allocator<container_type, | |
| 670 | _Alloc>::value>::type*) | |
| 656 | _EnableIf<uses_allocator<container_type, _Alloc>::value>*) | |
| 671 | 657 | : c(__c, __a), |
| 672 | 658 | comp(__comp) |
| 673 | 659 | { |
| ... | ... | @@ -679,8 +665,7 @@ template <class _Alloc> |
| 679 | 665 | inline |
| 680 | 666 | priority_queue<_Tp, _Container, _Compare>::priority_queue(const priority_queue& __q, |
| 681 | 667 | const _Alloc& __a, |
| 682 | typename enable_if<uses_allocator<container_type, | |
| 683 | _Alloc>::value>::type*) | |
| 668 | _EnableIf<uses_allocator<container_type, _Alloc>::value>*) | |
| 684 | 669 | : c(__q.c, __a), |
| 685 | 670 | comp(__q.comp) |
| 686 | 671 | { |
| ... | ... | @@ -695,8 +680,7 @@ inline |
| 695 | 680 | priority_queue<_Tp, _Container, _Compare>::priority_queue(const value_compare& __comp, |
| 696 | 681 | container_type&& __c, |
| 697 | 682 | const _Alloc& __a, |
| 698 | typename enable_if<uses_allocator<container_type, | |
| 699 | _Alloc>::value>::type*) | |
| 683 | _EnableIf<uses_allocator<container_type, _Alloc>::value>*) | |
| 700 | 684 | : c(_VSTD::move(__c), __a), |
| 701 | 685 | comp(__comp) |
| 702 | 686 | { |
| ... | ... | @@ -708,15 +692,14 @@ template <class _Alloc> |
| 708 | 692 | inline |
| 709 | 693 | priority_queue<_Tp, _Container, _Compare>::priority_queue(priority_queue&& __q, |
| 710 | 694 | const _Alloc& __a, |
| 711 | typename enable_if<uses_allocator<container_type, | |
| 712 | _Alloc>::value>::type*) | |
| 695 | _EnableIf<uses_allocator<container_type, _Alloc>::value>*) | |
| 713 | 696 | : c(_VSTD::move(__q.c), __a), |
| 714 | 697 | comp(_VSTD::move(__q.comp)) |
| 715 | 698 | { |
| 716 | 699 | _VSTD::make_heap(c.begin(), c.end(), comp); |
| 717 | 700 | } |
| 718 | 701 | |
| 719 | #endif // _LIBCPP_CXX03_LANG | |
| 702 | #endif // _LIBCPP_CXX03_LANG | |
| 720 | 703 | |
| 721 | 704 | template <class _Tp, class _Container, class _Compare> |
| 722 | 705 | inline |
| ... | ... | @@ -748,7 +731,7 @@ priority_queue<_Tp, _Container, _Compare>::emplace(_Args&&... __args) |
| 748 | 731 | _VSTD::push_heap(c.begin(), c.end(), comp); |
| 749 | 732 | } |
| 750 | 733 | |
| 751 | #endif // _LIBCPP_CXX03_LANG | |
| 734 | #endif // _LIBCPP_CXX03_LANG | |
| 752 | 735 | |
| 753 | 736 | template <class _Tp, class _Container, class _Compare> |
| 754 | 737 | inline |
| ... | ... | @@ -773,11 +756,10 @@ priority_queue<_Tp, _Container, _Compare>::swap(priority_queue& __q) |
| 773 | 756 | |
| 774 | 757 | template <class _Tp, class _Container, class _Compare> |
| 775 | 758 | inline _LIBCPP_INLINE_VISIBILITY |
| 776 | typename enable_if< | |
| 777 | __is_swappable<_Container>::value | |
| 778 | && __is_swappable<_Compare>::value, | |
| 759 | _EnableIf< | |
| 760 | __is_swappable<_Container>::value && __is_swappable<_Compare>::value, | |
| 779 | 761 | void |
| 780 | >::type | |
| 762 | > | |
| 781 | 763 | swap(priority_queue<_Tp, _Container, _Compare>& __x, |
| 782 | 764 | priority_queue<_Tp, _Container, _Compare>& __y) |
| 783 | 765 | _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) |
| ... | ... | @@ -793,4 +775,4 @@ struct _LIBCPP_TEMPLATE_VIS uses_allocator<priority_queue<_Tp, _Container, _Comp |
| 793 | 775 | |
| 794 | 776 | _LIBCPP_END_NAMESPACE_STD |
| 795 | 777 | |
| 796 | #endif // _LIBCPP_QUEUE | |
| 778 | #endif // _LIBCPP_QUEUE |
lib/libcxx/include/random+42-60| ... | ... | @@ -17,6 +17,9 @@ |
| 17 | 17 | |
| 18 | 18 | namespace std |
| 19 | 19 | { |
| 20 | // [rand.req.urng], uniform random bit generator requirements | |
| 21 | template<class G> | |
| 22 | concept uniform_random_bit_generator = see below; // C++20 | |
| 20 | 23 | |
| 21 | 24 | // Engines |
| 22 | 25 | |
| ... | ... | @@ -1675,17 +1678,19 @@ class piecewise_linear_distribution |
| 1675 | 1678 | */ |
| 1676 | 1679 | |
| 1677 | 1680 | #include <__config> |
| 1681 | #include <__random/uniform_int_distribution.h> | |
| 1682 | #include <algorithm> | |
| 1683 | #include <cmath> | |
| 1684 | #include <concepts> | |
| 1678 | 1685 | #include <cstddef> |
| 1679 | 1686 | #include <cstdint> |
| 1680 | #include <cmath> | |
| 1681 | #include <type_traits> | |
| 1682 | 1687 | #include <initializer_list> |
| 1688 | #include <iosfwd> | |
| 1683 | 1689 | #include <limits> |
| 1684 | #include <algorithm> | |
| 1685 | 1690 | #include <numeric> |
| 1686 | #include <vector> | |
| 1687 | 1691 | #include <string> |
| 1688 | #include <iosfwd> | |
| 1692 | #include <type_traits> | |
| 1693 | #include <vector> | |
| 1689 | 1694 | |
| 1690 | 1695 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 1691 | 1696 | #pragma GCC system_header |
| ... | ... | @@ -1697,6 +1702,20 @@ _LIBCPP_PUSH_MACROS |
| 1697 | 1702 | |
| 1698 | 1703 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 1699 | 1704 | |
| 1705 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 1706 | ||
| 1707 | // [rand.req.urng] | |
| 1708 | template<class _Gen> | |
| 1709 | concept uniform_random_bit_generator = | |
| 1710 | invocable<_Gen&> && unsigned_integral<invoke_result_t<_Gen&>> && | |
| 1711 | requires { | |
| 1712 | { _Gen::min() } -> same_as<invoke_result_t<_Gen&>>; | |
| 1713 | { _Gen::max() } -> same_as<invoke_result_t<_Gen&>>; | |
| 1714 | requires bool_constant<(_Gen::min() < _Gen::max())>::value; | |
| 1715 | }; | |
| 1716 | ||
| 1717 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 1718 | ||
| 1700 | 1719 | // __is_seed_sequence |
| 1701 | 1720 | |
| 1702 | 1721 | template <class _Sseq, class _Engine> |
| ... | ... | @@ -1712,7 +1731,7 @@ struct __is_seed_sequence |
| 1712 | 1731 | template <unsigned long long __a, unsigned long long __c, |
| 1713 | 1732 | unsigned long long __m, unsigned long long _Mp, |
| 1714 | 1733 | bool _MightOverflow = (__a != 0 && __m != 0 && __m-1 > (_Mp-__c)/__a), |
| 1715 | bool _OverflowOK = ((__m|__m-1) > __m), // m = 2^n | |
| 1734 | bool _OverflowOK = ((__m | (__m-1)) > __m), // m = 2^n | |
| 1716 | 1735 | bool _SchrageOK = (__a != 0 && __m != 0 && __m % __a <= __m / __a)> // r <= q |
| 1717 | 1736 | struct __lce_alg_picker |
| 1718 | 1737 | { |
| ... | ... | @@ -1901,7 +1920,7 @@ private: |
| 1901 | 1920 | |
| 1902 | 1921 | static_assert(__m == 0 || __a < __m, "linear_congruential_engine invalid parameters"); |
| 1903 | 1922 | static_assert(__m == 0 || __c < __m, "linear_congruential_engine invalid parameters"); |
| 1904 | static_assert(_VSTD::is_unsigned<_UIntType>::value, "_UIntType must be unsigned type"); | |
| 1923 | static_assert(is_unsigned<_UIntType>::value, "_UIntType must be unsigned type"); | |
| 1905 | 1924 | public: |
| 1906 | 1925 | static _LIBCPP_CONSTEXPR const result_type _Min = __c == 0u ? 1u: 0u; |
| 1907 | 1926 | static _LIBCPP_CONSTEXPR const result_type _Max = __m - 1u; |
| ... | ... | @@ -2940,7 +2959,7 @@ public: |
| 2940 | 2959 | _LIBCPP_INLINE_VISIBILITY |
| 2941 | 2960 | explicit discard_block_engine(_Engine&& __e) |
| 2942 | 2961 | : __e_(_VSTD::move(__e)), __n_(0) {} |
| 2943 | #endif // _LIBCPP_CXX03_LANG | |
| 2962 | #endif // _LIBCPP_CXX03_LANG | |
| 2944 | 2963 | _LIBCPP_INLINE_VISIBILITY |
| 2945 | 2964 | explicit discard_block_engine(result_type __sd) : __e_(__sd), __n_(0) {} |
| 2946 | 2965 | template<class _Sseq> |
| ... | ... | @@ -3152,7 +3171,7 @@ public: |
| 3152 | 3171 | _LIBCPP_INLINE_VISIBILITY |
| 3153 | 3172 | explicit independent_bits_engine(_Engine&& __e) |
| 3154 | 3173 | : __e_(_VSTD::move(__e)) {} |
| 3155 | #endif // _LIBCPP_CXX03_LANG | |
| 3174 | #endif // _LIBCPP_CXX03_LANG | |
| 3156 | 3175 | _LIBCPP_INLINE_VISIBILITY |
| 3157 | 3176 | explicit independent_bits_engine(result_type __sd) : __e_(__sd) {} |
| 3158 | 3177 | template<class _Sseq> |
| ... | ... | @@ -3382,7 +3401,7 @@ public: |
| 3382 | 3401 | _LIBCPP_INLINE_VISIBILITY |
| 3383 | 3402 | explicit shuffle_order_engine(_Engine&& __e) |
| 3384 | 3403 | : __e_(_VSTD::move(__e)) {__init();} |
| 3385 | #endif // _LIBCPP_CXX03_LANG | |
| 3404 | #endif // _LIBCPP_CXX03_LANG | |
| 3386 | 3405 | _LIBCPP_INLINE_VISIBILITY |
| 3387 | 3406 | explicit shuffle_order_engine(result_type __sd) : __e_(__sd) {__init();} |
| 3388 | 3407 | template<class _Sseq> |
| ... | ... | @@ -3634,7 +3653,7 @@ public: |
| 3634 | 3653 | template<class _Tp> |
| 3635 | 3654 | _LIBCPP_INLINE_VISIBILITY |
| 3636 | 3655 | seed_seq(initializer_list<_Tp> __il) {init(__il.begin(), __il.end());} |
| 3637 | #endif // _LIBCPP_CXX03_LANG | |
| 3656 | #endif // _LIBCPP_CXX03_LANG | |
| 3638 | 3657 | |
| 3639 | 3658 | template<class _InputIterator> |
| 3640 | 3659 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -3755,42 +3774,6 @@ generate_canonical(_URNG& __g) |
| 3755 | 3774 | return _Sp / __base; |
| 3756 | 3775 | } |
| 3757 | 3776 | |
| 3758 | // uniform_int_distribution | |
| 3759 | ||
| 3760 | // in <algorithm> | |
| 3761 | ||
| 3762 | template <class _CharT, class _Traits, class _IT> | |
| 3763 | basic_ostream<_CharT, _Traits>& | |
| 3764 | operator<<(basic_ostream<_CharT, _Traits>& __os, | |
| 3765 | const uniform_int_distribution<_IT>& __x) | |
| 3766 | { | |
| 3767 | __save_flags<_CharT, _Traits> __lx(__os); | |
| 3768 | typedef basic_ostream<_CharT, _Traits> _Ostream; | |
| 3769 | __os.flags(_Ostream::dec | _Ostream::left); | |
| 3770 | _CharT __sp = __os.widen(' '); | |
| 3771 | __os.fill(__sp); | |
| 3772 | return __os << __x.a() << __sp << __x.b(); | |
| 3773 | } | |
| 3774 | ||
| 3775 | template <class _CharT, class _Traits, class _IT> | |
| 3776 | basic_istream<_CharT, _Traits>& | |
| 3777 | operator>>(basic_istream<_CharT, _Traits>& __is, | |
| 3778 | uniform_int_distribution<_IT>& __x) | |
| 3779 | { | |
| 3780 | typedef uniform_int_distribution<_IT> _Eng; | |
| 3781 | typedef typename _Eng::result_type result_type; | |
| 3782 | typedef typename _Eng::param_type param_type; | |
| 3783 | __save_flags<_CharT, _Traits> __lx(__is); | |
| 3784 | typedef basic_istream<_CharT, _Traits> _Istream; | |
| 3785 | __is.flags(_Istream::dec | _Istream::skipws); | |
| 3786 | result_type __a; | |
| 3787 | result_type __b; | |
| 3788 | __is >> __a >> __b; | |
| 3789 | if (!__is.fail()) | |
| 3790 | __x.param(param_type(__a, __b)); | |
| 3791 | return __is; | |
| 3792 | } | |
| 3793 | ||
| 3794 | 3777 | // uniform_real_distribution |
| 3795 | 3778 | |
| 3796 | 3779 | template<class _RealType = double> |
| ... | ... | @@ -4142,7 +4125,7 @@ inline _LIBCPP_INLINE_VISIBILITY double __libcpp_lgamma(double __d) { |
| 4142 | 4125 | } |
| 4143 | 4126 | |
| 4144 | 4127 | template<class _IntType> |
| 4145 | binomial_distribution<_IntType>::param_type::param_type(const result_type __t, const double __p) | |
| 4128 | binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p) | |
| 4146 | 4129 | : __t_(__t), __p_(__p) |
| 4147 | 4130 | { |
| 4148 | 4131 | if (0 < __p_ && __p_ < 1) |
| ... | ... | @@ -6145,7 +6128,7 @@ public: |
| 6145 | 6128 | _LIBCPP_INLINE_VISIBILITY |
| 6146 | 6129 | param_type(initializer_list<double> __wl) |
| 6147 | 6130 | : __p_(__wl.begin(), __wl.end()) {__init();} |
| 6148 | #endif // _LIBCPP_CXX03_LANG | |
| 6131 | #endif // _LIBCPP_CXX03_LANG | |
| 6149 | 6132 | template<class _UnaryOperation> |
| 6150 | 6133 | param_type(size_t __nw, double __xmin, double __xmax, |
| 6151 | 6134 | _UnaryOperation __fw); |
| ... | ... | @@ -6192,7 +6175,7 @@ public: |
| 6192 | 6175 | _LIBCPP_INLINE_VISIBILITY |
| 6193 | 6176 | discrete_distribution(initializer_list<double> __wl) |
| 6194 | 6177 | : __p_(__wl) {} |
| 6195 | #endif // _LIBCPP_CXX03_LANG | |
| 6178 | #endif // _LIBCPP_CXX03_LANG | |
| 6196 | 6179 | template<class _UnaryOperation> |
| 6197 | 6180 | _LIBCPP_INLINE_VISIBILITY |
| 6198 | 6181 | discrete_distribution(size_t __nw, double __xmin, double __xmax, |
| ... | ... | @@ -6274,8 +6257,7 @@ discrete_distribution<_IntType>::param_type::__init() |
| 6274 | 6257 | if (__p_.size() > 1) |
| 6275 | 6258 | { |
| 6276 | 6259 | double __s = _VSTD::accumulate(__p_.begin(), __p_.end(), 0.0); |
| 6277 | for (_VSTD::vector<double>::iterator __i = __p_.begin(), __e = __p_.end(); | |
| 6278 | __i < __e; ++__i) | |
| 6260 | for (vector<double>::iterator __i = __p_.begin(), __e = __p_.end(); __i < __e; ++__i) | |
| 6279 | 6261 | *__i /= __s; |
| 6280 | 6262 | vector<double> __t(__p_.size() - 1); |
| 6281 | 6263 | _VSTD::partial_sum(__p_.begin(), __p_.end() - 1, __t.begin()); |
| ... | ... | @@ -6294,7 +6276,7 @@ vector<double> |
| 6294 | 6276 | discrete_distribution<_IntType>::param_type::probabilities() const |
| 6295 | 6277 | { |
| 6296 | 6278 | size_t __n = __p_.size(); |
| 6297 | _VSTD::vector<double> __p(__n+1); | |
| 6279 | vector<double> __p(__n+1); | |
| 6298 | 6280 | _VSTD::adjacent_difference(__p_.begin(), __p_.end(), __p.begin()); |
| 6299 | 6281 | if (__n > 0) |
| 6300 | 6282 | __p[__n] = 1 - __p_[__n-1]; |
| ... | ... | @@ -6374,7 +6356,7 @@ public: |
| 6374 | 6356 | #ifndef _LIBCPP_CXX03_LANG |
| 6375 | 6357 | template<class _UnaryOperation> |
| 6376 | 6358 | param_type(initializer_list<result_type> __bl, _UnaryOperation __fw); |
| 6377 | #endif // _LIBCPP_CXX03_LANG | |
| 6359 | #endif // _LIBCPP_CXX03_LANG | |
| 6378 | 6360 | template<class _UnaryOperation> |
| 6379 | 6361 | param_type(size_t __nw, result_type __xmin, result_type __xmax, |
| 6380 | 6362 | _UnaryOperation __fw); |
| ... | ... | @@ -6431,7 +6413,7 @@ public: |
| 6431 | 6413 | piecewise_constant_distribution(initializer_list<result_type> __bl, |
| 6432 | 6414 | _UnaryOperation __fw) |
| 6433 | 6415 | : __p_(__bl, __fw) {} |
| 6434 | #endif // _LIBCPP_CXX03_LANG | |
| 6416 | #endif // _LIBCPP_CXX03_LANG | |
| 6435 | 6417 | |
| 6436 | 6418 | template<class _UnaryOperation> |
| 6437 | 6419 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -6586,7 +6568,7 @@ piecewise_constant_distribution<_RealType>::param_type::param_type( |
| 6586 | 6568 | } |
| 6587 | 6569 | } |
| 6588 | 6570 | |
| 6589 | #endif // _LIBCPP_CXX03_LANG | |
| 6571 | #endif // _LIBCPP_CXX03_LANG | |
| 6590 | 6572 | |
| 6591 | 6573 | template<class _RealType> |
| 6592 | 6574 | template<class _UnaryOperation> |
| ... | ... | @@ -6700,7 +6682,7 @@ public: |
| 6700 | 6682 | #ifndef _LIBCPP_CXX03_LANG |
| 6701 | 6683 | template<class _UnaryOperation> |
| 6702 | 6684 | param_type(initializer_list<result_type> __bl, _UnaryOperation __fw); |
| 6703 | #endif // _LIBCPP_CXX03_LANG | |
| 6685 | #endif // _LIBCPP_CXX03_LANG | |
| 6704 | 6686 | template<class _UnaryOperation> |
| 6705 | 6687 | param_type(size_t __nw, result_type __xmin, result_type __xmax, |
| 6706 | 6688 | _UnaryOperation __fw); |
| ... | ... | @@ -6757,7 +6739,7 @@ public: |
| 6757 | 6739 | piecewise_linear_distribution(initializer_list<result_type> __bl, |
| 6758 | 6740 | _UnaryOperation __fw) |
| 6759 | 6741 | : __p_(__bl, __fw) {} |
| 6760 | #endif // _LIBCPP_CXX03_LANG | |
| 6742 | #endif // _LIBCPP_CXX03_LANG | |
| 6761 | 6743 | |
| 6762 | 6744 | template<class _UnaryOperation> |
| 6763 | 6745 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -6916,7 +6898,7 @@ piecewise_linear_distribution<_RealType>::param_type::param_type( |
| 6916 | 6898 | } |
| 6917 | 6899 | } |
| 6918 | 6900 | |
| 6919 | #endif // _LIBCPP_CXX03_LANG | |
| 6901 | #endif // _LIBCPP_CXX03_LANG | |
| 6920 | 6902 | |
| 6921 | 6903 | template<class _RealType> |
| 6922 | 6904 | template<class _UnaryOperation> |
| ... | ... | @@ -7022,4 +7004,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 7022 | 7004 | |
| 7023 | 7005 | _LIBCPP_POP_MACROS |
| 7024 | 7006 | |
| 7025 | #endif // _LIBCPP_RANDOM | |
| 7007 | #endif // _LIBCPP_RANDOM |
lib/libcxx/include/ranges created+209| ... | ... | @@ -0,0 +1,209 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===--------------------------- ranges -----------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP_RANGES | |
| 11 | #define _LIBCPP_RANGES | |
| 12 | ||
| 13 | /* | |
| 14 | ||
| 15 | #include <compare> // see [compare.syn] | |
| 16 | #include <initializer_list> // see [initializer.list.syn] | |
| 17 | #include <iterator> // see [iterator.synopsis] | |
| 18 | ||
| 19 | namespace std::ranges { | |
| 20 | inline namespace unspecified { | |
| 21 | // [range.access], range access | |
| 22 | inline constexpr unspecified begin = unspecified; | |
| 23 | inline constexpr unspecified end = unspecified; | |
| 24 | inline constexpr unspecified cbegin = unspecified; | |
| 25 | inline constexpr unspecified cend = unspecified; | |
| 26 | ||
| 27 | inline constexpr unspecified size = unspecified; | |
| 28 | inline constexpr unspecified ssize = unspecified; | |
| 29 | } | |
| 30 | ||
| 31 | // [range.range], ranges | |
| 32 | template<class T> | |
| 33 | concept range = see below; | |
| 34 | ||
| 35 | template<class T> | |
| 36 | inline constexpr bool enable_borrowed_range = false; | |
| 37 | ||
| 38 | template<class T> | |
| 39 | using iterator_t = decltype(ranges::begin(declval<R&>())); | |
| 40 | template<range R> | |
| 41 | using sentinel_t = decltype(ranges::end(declval<R&>())); | |
| 42 | template<range R> | |
| 43 | using range_difference_t = iter_difference_t<iterator_t<R>>; | |
| 44 | template<sized_range R> | |
| 45 | using range_size_t = decltype(ranges::size(declval<R&>())); | |
| 46 | template<range R> | |
| 47 | using range_value_t = iter_value_t<iterator_t<R>>; | |
| 48 | template<range R> | |
| 49 | using range_reference_t = iter_reference_t<iterator_t<R>>; | |
| 50 | template<range R> | |
| 51 | using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>; | |
| 52 | ||
| 53 | // [range.sized], sized ranges | |
| 54 | template<class> | |
| 55 | inline constexpr bool disable_sized_range = false; | |
| 56 | ||
| 57 | template<class T> | |
| 58 | concept sized_range = ...; | |
| 59 | ||
| 60 | // [range.view], views | |
| 61 | template<class T> | |
| 62 | inline constexpr bool enable_view = ...; | |
| 63 | ||
| 64 | struct view_base { }; | |
| 65 | ||
| 66 | template<class T> | |
| 67 | concept view = ...; | |
| 68 | ||
| 69 | // [range.refinements], other range refinements | |
| 70 | template<class R, class T> | |
| 71 | concept output_range = see below; | |
| 72 | ||
| 73 | template<class T> | |
| 74 | concept input_range = see below; | |
| 75 | ||
| 76 | template<class T> | |
| 77 | concept forward_range = see below; | |
| 78 | ||
| 79 | template<class T> | |
| 80 | concept bidirectional_range = see below; | |
| 81 | ||
| 82 | template<class T> | |
| 83 | concept random_access_range = see below; | |
| 84 | ||
| 85 | template<class T> | |
| 86 | concept contiguous_range = see below; | |
| 87 | ||
| 88 | template <class _Tp> | |
| 89 | concept common_range = see below; | |
| 90 | ||
| 91 | template<class T> | |
| 92 | concept viewable_range = see below; | |
| 93 | ||
| 94 | // [view.interface], class template view_interface | |
| 95 | template<class D> | |
| 96 | requires is_class_v<D> && same_as<D, remove_cv_t<D>> | |
| 97 | class view_interface; | |
| 98 | ||
| 99 | // [range.subrange], sub-ranges | |
| 100 | enum class subrange_kind : bool { unsized, sized }; | |
| 101 | ||
| 102 | template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K = see below> | |
| 103 | requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>) | |
| 104 | class subrange; | |
| 105 | ||
| 106 | template<class I, class S, subrange_kind K> | |
| 107 | inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true; | |
| 108 | ||
| 109 | // [range.dangling], dangling iterator handling | |
| 110 | struct dangling; | |
| 111 | ||
| 112 | template<range R> | |
| 113 | using borrowed_iterator_t = see below; | |
| 114 | ||
| 115 | template<range R> | |
| 116 | using borrowed_subrange_t = see below; | |
| 117 | ||
| 118 | // [range.empty], empty view | |
| 119 | template<class T> | |
| 120 | requires is_object_v<T> | |
| 121 | class empty_view; | |
| 122 | ||
| 123 | // [range.all], all view | |
| 124 | namespace views { | |
| 125 | inline constexpr unspecified all = unspecified; | |
| 126 | ||
| 127 | template<viewable_range R> | |
| 128 | using all_t = decltype(all(declval<R>())); | |
| 129 | } | |
| 130 | ||
| 131 | template<range R> | |
| 132 | requires is_object_v<R> | |
| 133 | class ref_view; | |
| 134 | ||
| 135 | template<class T> | |
| 136 | inline constexpr bool enable_borrowed_range<ref_view<T>> = true; | |
| 137 | ||
| 138 | // [range.drop], drop view | |
| 139 | template<view V> | |
| 140 | class drop_view; | |
| 141 | ||
| 142 | template<class T> | |
| 143 | inline constexpr bool enable_borrowed_range<drop_view<T>> = enable_borrowed_range<T>; | |
| 144 | ||
| 145 | // [range.transform], transform view | |
| 146 | template<input_range V, copy_constructible F> | |
| 147 | requires view<V> && is_object_v<F> && | |
| 148 | regular_invocable<F&, range_reference_t<V>> && | |
| 149 | can-reference<invoke_result_t<F&, range_reference_t<V>>> | |
| 150 | class transform_view; | |
| 151 | ||
| 152 | // [range.common], common view | |
| 153 | template<view V> | |
| 154 | requires (!common_range<V> && copyable<iterator_t<V>>) | |
| 155 | class common_view; | |
| 156 | ||
| 157 | template<class T> | |
| 158 | inline constexpr bool enable_borrowed_range<common_view<T>> = enable_borrowed_range<T>; | |
| 159 | } | |
| 160 | ||
| 161 | */ | |
| 162 | ||
| 163 | // Make sure all feature tests macros are always available. | |
| 164 | #include <version> | |
| 165 | // Only enable the contents of the header when libc++ was build with LIBCXX_ENABLE_INCOMPLETE_FEATURES enabled | |
| 166 | #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | |
| 167 | ||
| 168 | #include <__config> | |
| 169 | #include <__ranges/access.h> | |
| 170 | #include <__ranges/all.h> | |
| 171 | #include <__ranges/common_view.h> | |
| 172 | #include <__ranges/concepts.h> | |
| 173 | #include <__ranges/dangling.h> | |
| 174 | #include <__ranges/data.h> | |
| 175 | #include <__ranges/drop_view.h> | |
| 176 | #include <__ranges/empty.h> | |
| 177 | #include <__ranges/empty_view.h> | |
| 178 | #include <__ranges/enable_borrowed_range.h> | |
| 179 | #include <__ranges/enable_view.h> | |
| 180 | #include <__ranges/ref_view.h> | |
| 181 | #include <__ranges/size.h> | |
| 182 | #include <__ranges/subrange.h> | |
| 183 | #include <__ranges/transform_view.h> | |
| 184 | #include <__ranges/view_interface.h> | |
| 185 | #include <compare> // Required by the standard. | |
| 186 | #include <initializer_list> // Required by the standard. | |
| 187 | #include <iterator> // Required by the standard. | |
| 188 | #include <type_traits> | |
| 189 | ||
| 190 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 191 | #pragma GCC system_header | |
| 192 | #endif | |
| 193 | ||
| 194 | _LIBCPP_PUSH_MACROS | |
| 195 | #include <__undef_macros> | |
| 196 | ||
| 197 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 198 | ||
| 199 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) | |
| 200 | ||
| 201 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) | |
| 202 | ||
| 203 | _LIBCPP_END_NAMESPACE_STD | |
| 204 | ||
| 205 | _LIBCPP_POP_MACROS | |
| 206 | ||
| 207 | #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | |
| 208 | ||
| 209 | #endif // _LIBCPP_RANGES |
lib/libcxx/include/ratio+6-6| ... | ... | @@ -78,8 +78,8 @@ typedef ratio<1000000000000000000000000, 1> yotta; // not supported |
| 78 | 78 | */ |
| 79 | 79 | |
| 80 | 80 | #include <__config> |
| 81 | #include <cstdint> | |
| 82 | 81 | #include <climits> |
| 82 | #include <cstdint> | |
| 83 | 83 | #include <type_traits> |
| 84 | 84 | |
| 85 | 85 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -312,7 +312,7 @@ template <class _R1, class _R2> |
| 312 | 312 | struct _LIBCPP_TEMPLATE_VIS ratio_multiply |
| 313 | 313 | : public __ratio_multiply<_R1, _R2>::type {}; |
| 314 | 314 | |
| 315 | #endif // _LIBCPP_CXX03_LANG | |
| 315 | #endif // _LIBCPP_CXX03_LANG | |
| 316 | 316 | |
| 317 | 317 | template <class _R1, class _R2> |
| 318 | 318 | struct __ratio_divide |
| ... | ... | @@ -339,7 +339,7 @@ template <class _R1, class _R2> |
| 339 | 339 | struct _LIBCPP_TEMPLATE_VIS ratio_divide |
| 340 | 340 | : public __ratio_divide<_R1, _R2>::type {}; |
| 341 | 341 | |
| 342 | #endif // _LIBCPP_CXX03_LANG | |
| 342 | #endif // _LIBCPP_CXX03_LANG | |
| 343 | 343 | |
| 344 | 344 | template <class _R1, class _R2> |
| 345 | 345 | struct __ratio_add |
| ... | ... | @@ -374,7 +374,7 @@ template <class _R1, class _R2> |
| 374 | 374 | struct _LIBCPP_TEMPLATE_VIS ratio_add |
| 375 | 375 | : public __ratio_add<_R1, _R2>::type {}; |
| 376 | 376 | |
| 377 | #endif // _LIBCPP_CXX03_LANG | |
| 377 | #endif // _LIBCPP_CXX03_LANG | |
| 378 | 378 | |
| 379 | 379 | template <class _R1, class _R2> |
| 380 | 380 | struct __ratio_subtract |
| ... | ... | @@ -409,7 +409,7 @@ template <class _R1, class _R2> |
| 409 | 409 | struct _LIBCPP_TEMPLATE_VIS ratio_subtract |
| 410 | 410 | : public __ratio_subtract<_R1, _R2>::type {}; |
| 411 | 411 | |
| 412 | #endif // _LIBCPP_CXX03_LANG | |
| 412 | #endif // _LIBCPP_CXX03_LANG | |
| 413 | 413 | |
| 414 | 414 | // ratio_equal |
| 415 | 415 | |
| ... | ... | @@ -529,4 +529,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 529 | 529 | |
| 530 | 530 | _LIBCPP_POP_MACROS |
| 531 | 531 | |
| 532 | #endif // _LIBCPP_RATIO | |
| 532 | #endif // _LIBCPP_RATIO |
lib/libcxx/include/regex+17-19| ... | ... | @@ -763,15 +763,18 @@ typedef regex_token_iterator<wstring::const_iterator> wsregex_token_iterator; |
| 763 | 763 | */ |
| 764 | 764 | |
| 765 | 765 | #include <__config> |
| 766 | #include <stdexcept> | |
| 766 | #include <__debug> | |
| 767 | #include <__iterator/wrap_iter.h> | |
| 767 | 768 | #include <__locale> |
| 769 | #include <compare> | |
| 770 | #include <deque> | |
| 768 | 771 | #include <initializer_list> |
| 769 | #include <utility> | |
| 770 | 772 | #include <iterator> |
| 771 | #include <string> | |
| 772 | 773 | #include <memory> |
| 774 | #include <stdexcept> | |
| 775 | #include <string> | |
| 776 | #include <utility> | |
| 773 | 777 | #include <vector> |
| 774 | #include <deque> | |
| 775 | 778 | #include <version> |
| 776 | 779 | |
| 777 | 780 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -2000,14 +2003,14 @@ class __l_anchor_multiline |
| 2000 | 2003 | { |
| 2001 | 2004 | typedef __owns_one_state<_CharT> base; |
| 2002 | 2005 | |
| 2003 | bool __multiline; | |
| 2006 | bool __multiline_; | |
| 2004 | 2007 | |
| 2005 | 2008 | public: |
| 2006 | 2009 | typedef _VSTD::__state<_CharT> __state; |
| 2007 | 2010 | |
| 2008 | 2011 | _LIBCPP_INLINE_VISIBILITY |
| 2009 | 2012 | __l_anchor_multiline(bool __multiline, __node<_CharT>* __s) |
| 2010 | : base(__s), __multiline(__multiline) {} | |
| 2013 | : base(__s), __multiline_(__multiline) {} | |
| 2011 | 2014 | |
| 2012 | 2015 | virtual void __exec(__state&) const; |
| 2013 | 2016 | }; |
| ... | ... | @@ -2022,7 +2025,7 @@ __l_anchor_multiline<_CharT>::__exec(__state& __s) const |
| 2022 | 2025 | __s.__do_ = __state::__accept_but_not_consume; |
| 2023 | 2026 | __s.__node_ = this->first(); |
| 2024 | 2027 | } |
| 2025 | else if (__multiline && | |
| 2028 | else if (__multiline_ && | |
| 2026 | 2029 | !__s.__at_first_ && |
| 2027 | 2030 | __is_eol(*_VSTD::prev(__s.__current_))) |
| 2028 | 2031 | { |
| ... | ... | @@ -2634,7 +2637,7 @@ public: |
| 2634 | 2637 | { |
| 2635 | 2638 | __init(__il.begin(), __il.end()); |
| 2636 | 2639 | } |
| 2637 | #endif // _LIBCPP_CXX03_LANG | |
| 2640 | #endif // _LIBCPP_CXX03_LANG | |
| 2638 | 2641 | |
| 2639 | 2642 | // ~basic_regex() = default; |
| 2640 | 2643 | |
| ... | ... | @@ -2647,7 +2650,7 @@ public: |
| 2647 | 2650 | _LIBCPP_INLINE_VISIBILITY |
| 2648 | 2651 | basic_regex& operator=(initializer_list<value_type> __il) |
| 2649 | 2652 | {return assign(__il);} |
| 2650 | #endif // _LIBCPP_CXX03_LANG | |
| 2653 | #endif // _LIBCPP_CXX03_LANG | |
| 2651 | 2654 | template <class _ST, class _SA> |
| 2652 | 2655 | _LIBCPP_INLINE_VISIBILITY |
| 2653 | 2656 | basic_regex& operator=(const basic_string<value_type, _ST, _SA>& __p) |
| ... | ... | @@ -2721,7 +2724,7 @@ public: |
| 2721 | 2724 | flag_type __f = regex_constants::ECMAScript) |
| 2722 | 2725 | {return assign(__il.begin(), __il.end(), __f);} |
| 2723 | 2726 | |
| 2724 | #endif // _LIBCPP_CXX03_LANG | |
| 2727 | #endif // _LIBCPP_CXX03_LANG | |
| 2725 | 2728 | |
| 2726 | 2729 | // const operations: |
| 2727 | 2730 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -4571,7 +4574,7 @@ basic_regex<_CharT, _Traits>::__parse_character_escape(_ForwardIterator __first, |
| 4571 | 4574 | if (__hd == -1) |
| 4572 | 4575 | __throw_regex_error<regex_constants::error_escape>(); |
| 4573 | 4576 | __sum = 16 * __sum + static_cast<unsigned>(__hd); |
| 4574 | // drop through | |
| 4577 | // fallthrough | |
| 4575 | 4578 | case 'x': |
| 4576 | 4579 | ++__first; |
| 4577 | 4580 | if (__first == __last) |
| ... | ... | @@ -5882,7 +5885,6 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( |
| 5882 | 5885 | { |
| 5883 | 5886 | vector<__state> __states; |
| 5884 | 5887 | __state __best_state; |
| 5885 | ptrdiff_t __j = 0; | |
| 5886 | 5888 | ptrdiff_t __highest_j = 0; |
| 5887 | 5889 | ptrdiff_t _Np = _VSTD::distance(__first, __last); |
| 5888 | 5890 | __node* __st = __start_.get(); |
| ... | ... | @@ -5903,7 +5905,6 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( |
| 5903 | 5905 | __states.back().__node_ = __st; |
| 5904 | 5906 | __states.back().__flags_ = __flags; |
| 5905 | 5907 | __states.back().__at_first_ = __at_first; |
| 5906 | const _CharT* __current = __first; | |
| 5907 | 5908 | bool __matched = false; |
| 5908 | 5909 | int __counter = 0; |
| 5909 | 5910 | int __length = __last - __first; |
| ... | ... | @@ -5943,9 +5944,6 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( |
| 5943 | 5944 | __states.pop_back(); |
| 5944 | 5945 | break; |
| 5945 | 5946 | case __state::__accept_and_consume: |
| 5946 | __j += __s.__current_ - __current; | |
| 5947 | __current = __s.__current_; | |
| 5948 | break; | |
| 5949 | 5947 | case __state::__repeat: |
| 5950 | 5948 | case __state::__accept_but_not_consume: |
| 5951 | 5949 | break; |
| ... | ... | @@ -6442,7 +6440,7 @@ public: |
| 6442 | 6440 | regex_constants::match_flag_type __m = |
| 6443 | 6441 | regex_constants::match_default) = delete; |
| 6444 | 6442 | #endif |
| 6445 | #endif // _LIBCPP_CXX03_LANG | |
| 6443 | #endif // _LIBCPP_CXX03_LANG | |
| 6446 | 6444 | template <size_t _Np> |
| 6447 | 6445 | regex_token_iterator(_BidirectionalIterator __a, |
| 6448 | 6446 | _BidirectionalIterator __b, |
| ... | ... | @@ -6557,7 +6555,7 @@ regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: |
| 6557 | 6555 | __init(__a, __b); |
| 6558 | 6556 | } |
| 6559 | 6557 | |
| 6560 | #endif // _LIBCPP_CXX03_LANG | |
| 6558 | #endif // _LIBCPP_CXX03_LANG | |
| 6561 | 6559 | |
| 6562 | 6560 | template <class _BidirectionalIterator, class _CharT, class _Traits> |
| 6563 | 6561 | template <size_t _Np> |
| ... | ... | @@ -6774,4 +6772,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 6774 | 6772 | |
| 6775 | 6773 | _LIBCPP_POP_MACROS |
| 6776 | 6774 | |
| 6777 | #endif // _LIBCPP_REGEX | |
| 6775 | #endif // _LIBCPP_REGEX |
lib/libcxx/include/scoped_allocator+4-3| ... | ... | @@ -106,6 +106,7 @@ template <class OuterA1, class OuterA2, class... InnerAllocs> |
| 106 | 106 | */ |
| 107 | 107 | |
| 108 | 108 | #include <__config> |
| 109 | #include <__utility/forward.h> | |
| 109 | 110 | #include <memory> |
| 110 | 111 | #include <version> |
| 111 | 112 | |
| ... | ... | @@ -375,7 +376,7 @@ struct __outermost<_Alloc, true> |
| 375 | 376 | { |
| 376 | 377 | typedef typename remove_reference |
| 377 | 378 | < |
| 378 | decltype(_VSTD::declval<_Alloc>().outer_allocator()) | |
| 379 | decltype(declval<_Alloc>().outer_allocator()) | |
| 379 | 380 | >::type _OuterAlloc; |
| 380 | 381 | typedef typename __outermost<_OuterAlloc>::type type; |
| 381 | 382 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -676,8 +677,8 @@ operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a, |
| 676 | 677 | return !(__a == __b); |
| 677 | 678 | } |
| 678 | 679 | |
| 679 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 680 | #endif // !defined(_LIBCPP_CXX03_LANG) | |
| 680 | 681 | |
| 681 | 682 | _LIBCPP_END_NAMESPACE_STD |
| 682 | 683 | |
| 683 | #endif // _LIBCPP_SCOPED_ALLOCATOR | |
| 684 | #endif // _LIBCPP_SCOPED_ALLOCATOR |
lib/libcxx/include/semaphore+3-3| ... | ... | @@ -45,8 +45,8 @@ using binary_semaphore = counting_semaphore<1>; |
| 45 | 45 | |
| 46 | 46 | */ |
| 47 | 47 | |
| 48 | #include <__config> | |
| 49 | 48 | #include <__availability> |
| 49 | #include <__config> | |
| 50 | 50 | #include <__threading_support> |
| 51 | 51 | #include <atomic> |
| 52 | 52 | |
| ... | ... | @@ -98,7 +98,7 @@ public: |
| 98 | 98 | _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY |
| 99 | 99 | void acquire() |
| 100 | 100 | { |
| 101 | auto const __test_fn = [=]() -> bool { | |
| 101 | auto const __test_fn = [this]() -> bool { | |
| 102 | 102 | auto __old = __a.load(memory_order_relaxed); |
| 103 | 103 | return (__old != 0) && __a.compare_exchange_strong(__old, __old - 1, memory_order_acquire, memory_order_relaxed); |
| 104 | 104 | }; |
| ... | ... | @@ -108,7 +108,7 @@ public: |
| 108 | 108 | _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY |
| 109 | 109 | bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time) |
| 110 | 110 | { |
| 111 | auto const __test_fn = [=]() -> bool { | |
| 111 | auto const __test_fn = [this]() -> bool { | |
| 112 | 112 | auto __old = __a.load(memory_order_acquire); |
| 113 | 113 | while(1) { |
| 114 | 114 | if (__old == 0) |
lib/libcxx/include/set+60-38| ... | ... | @@ -154,10 +154,14 @@ public: |
| 154 | 154 | iterator find(const K& x); |
| 155 | 155 | template<typename K> |
| 156 | 156 | const_iterator find(const K& x) const; // C++14 |
| 157 | ||
| 157 | 158 | template<typename K> |
| 158 | 159 | size_type count(const K& x) const; // C++14 |
| 159 | 160 | size_type count(const key_type& k) const; |
| 160 | bool contains(const key_type& x) const; // C++20 | |
| 161 | ||
| 162 | bool contains(const key_type& x) const; // C++20 | |
| 163 | template<class K> bool contains(const K& x) const; // C++20 | |
| 164 | ||
| 161 | 165 | iterator lower_bound(const key_type& k); |
| 162 | 166 | const_iterator lower_bound(const key_type& k) const; |
| 163 | 167 | template<typename K> |
| ... | ... | @@ -355,10 +359,14 @@ public: |
| 355 | 359 | iterator find(const K& x); |
| 356 | 360 | template<typename K> |
| 357 | 361 | const_iterator find(const K& x) const; // C++14 |
| 362 | ||
| 358 | 363 | template<typename K> |
| 359 | 364 | size_type count(const K& x) const; // C++14 |
| 360 | 365 | size_type count(const key_type& k) const; |
| 361 | bool contains(const key_type& x) const; // C++20 | |
| 366 | ||
| 367 | bool contains(const key_type& x) const; // C++20 | |
| 368 | template<class K> bool contains(const K& x) const; // C++20 | |
| 369 | ||
| 362 | 370 | iterator lower_bound(const key_type& k); |
| 363 | 371 | const_iterator lower_bound(const key_type& k) const; |
| 364 | 372 | template<typename K> |
| ... | ... | @@ -426,9 +434,15 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20 |
| 426 | 434 | */ |
| 427 | 435 | |
| 428 | 436 | #include <__config> |
| 429 | #include <__tree> | |
| 437 | #include <__debug> | |
| 438 | #include <__functional/is_transparent.h> | |
| 430 | 439 | #include <__node_handle> |
| 440 | #include <__tree> | |
| 441 | #include <__utility/forward.h> | |
| 442 | #include <compare> | |
| 431 | 443 | #include <functional> |
| 444 | #include <initializer_list> | |
| 445 | #include <iterator> // __libcpp_erase_if_container | |
| 432 | 446 | #include <version> |
| 433 | 447 | |
| 434 | 448 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -450,7 +464,7 @@ public: |
| 450 | 464 | typedef key_type value_type; |
| 451 | 465 | typedef _Compare key_compare; |
| 452 | 466 | typedef key_compare value_compare; |
| 453 | typedef typename __identity<_Allocator>::type allocator_type; | |
| 467 | typedef __identity_t<_Allocator> allocator_type; | |
| 454 | 468 | typedef value_type& reference; |
| 455 | 469 | typedef const value_type& const_reference; |
| 456 | 470 | |
| ... | ... | @@ -546,7 +560,7 @@ public: |
| 546 | 560 | set(set&& __s) |
| 547 | 561 | _NOEXCEPT_(is_nothrow_move_constructible<__base>::value) |
| 548 | 562 | : __tree_(_VSTD::move(__s.__tree_)) {} |
| 549 | #endif // _LIBCPP_CXX03_LANG | |
| 563 | #endif // _LIBCPP_CXX03_LANG | |
| 550 | 564 | |
| 551 | 565 | _LIBCPP_INLINE_VISIBILITY |
| 552 | 566 | explicit set(const allocator_type& __a) |
| ... | ... | @@ -597,7 +611,7 @@ public: |
| 597 | 611 | __tree_ = _VSTD::move(__s.__tree_); |
| 598 | 612 | return *this; |
| 599 | 613 | } |
| 600 | #endif // _LIBCPP_CXX03_LANG | |
| 614 | #endif // _LIBCPP_CXX03_LANG | |
| 601 | 615 | |
| 602 | 616 | _LIBCPP_INLINE_VISIBILITY |
| 603 | 617 | ~set() { |
| ... | ... | @@ -652,7 +666,7 @@ public: |
| 652 | 666 | _LIBCPP_INLINE_VISIBILITY |
| 653 | 667 | iterator emplace_hint(const_iterator __p, _Args&&... __args) |
| 654 | 668 | {return __tree_.__emplace_hint_unique(__p, _VSTD::forward<_Args>(__args)...);} |
| 655 | #endif // _LIBCPP_CXX03_LANG | |
| 669 | #endif // _LIBCPP_CXX03_LANG | |
| 656 | 670 | |
| 657 | 671 | _LIBCPP_INLINE_VISIBILITY |
| 658 | 672 | pair<iterator,bool> insert(const value_type& __v) |
| ... | ... | @@ -681,7 +695,7 @@ public: |
| 681 | 695 | _LIBCPP_INLINE_VISIBILITY |
| 682 | 696 | void insert(initializer_list<value_type> __il) |
| 683 | 697 | {insert(__il.begin(), __il.end());} |
| 684 | #endif // _LIBCPP_CXX03_LANG | |
| 698 | #endif // _LIBCPP_CXX03_LANG | |
| 685 | 699 | |
| 686 | 700 | _LIBCPP_INLINE_VISIBILITY |
| 687 | 701 | iterator erase(const_iterator __p) {return __tree_.erase(__p);} |
| ... | ... | @@ -795,6 +809,10 @@ public: |
| 795 | 809 | #if _LIBCPP_STD_VER > 17 |
| 796 | 810 | _LIBCPP_INLINE_VISIBILITY |
| 797 | 811 | bool contains(const key_type& __k) const {return find(__k) != end();} |
| 812 | template <typename _K2> | |
| 813 | _LIBCPP_INLINE_VISIBILITY | |
| 814 | typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type | |
| 815 | contains(const _K2& __k) const { return find(__k) != end(); } | |
| 798 | 816 | #endif // _LIBCPP_STD_VER > 17 |
| 799 | 817 | |
| 800 | 818 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -852,12 +870,12 @@ public: |
| 852 | 870 | |
| 853 | 871 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 854 | 872 | template<class _InputIterator, |
| 855 | class _Compare = less<typename iterator_traits<_InputIterator>::value_type>, | |
| 856 | class _Allocator = allocator<typename iterator_traits<_InputIterator>::value_type>, | |
| 873 | class _Compare = less<__iter_value_type<_InputIterator>>, | |
| 874 | class _Allocator = allocator<__iter_value_type<_InputIterator>>, | |
| 857 | 875 | class = _EnableIf<__is_allocator<_Allocator>::value, void>, |
| 858 | 876 | class = _EnableIf<!__is_allocator<_Compare>::value, void>> |
| 859 | 877 | set(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) |
| 860 | -> set<typename iterator_traits<_InputIterator>::value_type, _Compare, _Allocator>; | |
| 878 | -> set<__iter_value_type<_InputIterator>, _Compare, _Allocator>; | |
| 861 | 879 | |
| 862 | 880 | template<class _Key, class _Compare = less<_Key>, |
| 863 | 881 | class _Allocator = allocator<_Key>, |
| ... | ... | @@ -869,8 +887,8 @@ set(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator()) |
| 869 | 887 | template<class _InputIterator, class _Allocator, |
| 870 | 888 | class = _EnableIf<__is_allocator<_Allocator>::value, void>> |
| 871 | 889 | set(_InputIterator, _InputIterator, _Allocator) |
| 872 | -> set<typename iterator_traits<_InputIterator>::value_type, | |
| 873 | less<typename iterator_traits<_InputIterator>::value_type>, _Allocator>; | |
| 890 | -> set<__iter_value_type<_InputIterator>, | |
| 891 | less<__iter_value_type<_InputIterator>>, _Allocator>; | |
| 874 | 892 | |
| 875 | 893 | template<class _Key, class _Allocator, |
| 876 | 894 | class = _EnableIf<__is_allocator<_Allocator>::value, void>> |
| ... | ... | @@ -892,7 +910,7 @@ set<_Key, _Compare, _Allocator>::set(set&& __s, const allocator_type& __a) |
| 892 | 910 | } |
| 893 | 911 | } |
| 894 | 912 | |
| 895 | #endif // _LIBCPP_CXX03_LANG | |
| 913 | #endif // _LIBCPP_CXX03_LANG | |
| 896 | 914 | |
| 897 | 915 | template <class _Key, class _Compare, class _Allocator> |
| 898 | 916 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -964,7 +982,7 @@ template <class _Key, class _Compare, class _Allocator, class _Predicate> |
| 964 | 982 | inline _LIBCPP_INLINE_VISIBILITY |
| 965 | 983 | typename set<_Key, _Compare, _Allocator>::size_type |
| 966 | 984 | erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred) { |
| 967 | return __libcpp_erase_if_container(__c, __pred); | |
| 985 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 968 | 986 | } |
| 969 | 987 | #endif |
| 970 | 988 | |
| ... | ... | @@ -974,11 +992,11 @@ class _LIBCPP_TEMPLATE_VIS multiset |
| 974 | 992 | { |
| 975 | 993 | public: |
| 976 | 994 | // types: |
| 977 | typedef _Key key_type; | |
| 995 | typedef _Key key_type; | |
| 978 | 996 | typedef key_type value_type; |
| 979 | typedef _Compare key_compare; | |
| 997 | typedef _Compare key_compare; | |
| 980 | 998 | typedef key_compare value_compare; |
| 981 | typedef typename __identity<_Allocator>::type allocator_type; | |
| 999 | typedef __identity_t<_Allocator> allocator_type; | |
| 982 | 1000 | typedef value_type& reference; |
| 983 | 1001 | typedef const value_type& const_reference; |
| 984 | 1002 | |
| ... | ... | @@ -1077,7 +1095,7 @@ public: |
| 1077 | 1095 | : __tree_(_VSTD::move(__s.__tree_)) {} |
| 1078 | 1096 | |
| 1079 | 1097 | multiset(multiset&& __s, const allocator_type& __a); |
| 1080 | #endif // _LIBCPP_CXX03_LANG | |
| 1098 | #endif // _LIBCPP_CXX03_LANG | |
| 1081 | 1099 | _LIBCPP_INLINE_VISIBILITY |
| 1082 | 1100 | explicit multiset(const allocator_type& __a) |
| 1083 | 1101 | : __tree_(__a) {} |
| ... | ... | @@ -1124,7 +1142,7 @@ public: |
| 1124 | 1142 | __tree_ = _VSTD::move(__s.__tree_); |
| 1125 | 1143 | return *this; |
| 1126 | 1144 | } |
| 1127 | #endif // _LIBCPP_CXX03_LANG | |
| 1145 | #endif // _LIBCPP_CXX03_LANG | |
| 1128 | 1146 | |
| 1129 | 1147 | _LIBCPP_INLINE_VISIBILITY |
| 1130 | 1148 | ~multiset() { |
| ... | ... | @@ -1179,7 +1197,7 @@ public: |
| 1179 | 1197 | _LIBCPP_INLINE_VISIBILITY |
| 1180 | 1198 | iterator emplace_hint(const_iterator __p, _Args&&... __args) |
| 1181 | 1199 | {return __tree_.__emplace_hint_multi(__p, _VSTD::forward<_Args>(__args)...);} |
| 1182 | #endif // _LIBCPP_CXX03_LANG | |
| 1200 | #endif // _LIBCPP_CXX03_LANG | |
| 1183 | 1201 | |
| 1184 | 1202 | _LIBCPP_INLINE_VISIBILITY |
| 1185 | 1203 | iterator insert(const value_type& __v) |
| ... | ... | @@ -1208,7 +1226,7 @@ public: |
| 1208 | 1226 | _LIBCPP_INLINE_VISIBILITY |
| 1209 | 1227 | void insert(initializer_list<value_type> __il) |
| 1210 | 1228 | {insert(__il.begin(), __il.end());} |
| 1211 | #endif // _LIBCPP_CXX03_LANG | |
| 1229 | #endif // _LIBCPP_CXX03_LANG | |
| 1212 | 1230 | |
| 1213 | 1231 | _LIBCPP_INLINE_VISIBILITY |
| 1214 | 1232 | iterator erase(const_iterator __p) {return __tree_.erase(__p);} |
| ... | ... | @@ -1301,11 +1319,11 @@ public: |
| 1301 | 1319 | #if _LIBCPP_STD_VER > 11 |
| 1302 | 1320 | template <typename _K2> |
| 1303 | 1321 | _LIBCPP_INLINE_VISIBILITY |
| 1304 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,iterator>::type | |
| 1322 | typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type | |
| 1305 | 1323 | find(const _K2& __k) {return __tree_.find(__k);} |
| 1306 | 1324 | template <typename _K2> |
| 1307 | 1325 | _LIBCPP_INLINE_VISIBILITY |
| 1308 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,const_iterator>::type | |
| 1326 | typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type | |
| 1309 | 1327 | find(const _K2& __k) const {return __tree_.find(__k);} |
| 1310 | 1328 | #endif |
| 1311 | 1329 | |
| ... | ... | @@ -1322,6 +1340,10 @@ public: |
| 1322 | 1340 | #if _LIBCPP_STD_VER > 17 |
| 1323 | 1341 | _LIBCPP_INLINE_VISIBILITY |
| 1324 | 1342 | bool contains(const key_type& __k) const {return find(__k) != end();} |
| 1343 | template <typename _K2> | |
| 1344 | _LIBCPP_INLINE_VISIBILITY | |
| 1345 | typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type | |
| 1346 | contains(const _K2& __k) const { return find(__k) != end(); } | |
| 1325 | 1347 | #endif // _LIBCPP_STD_VER > 17 |
| 1326 | 1348 | |
| 1327 | 1349 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1333,12 +1355,12 @@ public: |
| 1333 | 1355 | #if _LIBCPP_STD_VER > 11 |
| 1334 | 1356 | template <typename _K2> |
| 1335 | 1357 | _LIBCPP_INLINE_VISIBILITY |
| 1336 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,iterator>::type | |
| 1358 | typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type | |
| 1337 | 1359 | lower_bound(const _K2& __k) {return __tree_.lower_bound(__k);} |
| 1338 | 1360 | |
| 1339 | 1361 | template <typename _K2> |
| 1340 | 1362 | _LIBCPP_INLINE_VISIBILITY |
| 1341 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,const_iterator>::type | |
| 1363 | typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type | |
| 1342 | 1364 | lower_bound(const _K2& __k) const {return __tree_.lower_bound(__k);} |
| 1343 | 1365 | #endif |
| 1344 | 1366 | |
| ... | ... | @@ -1351,11 +1373,11 @@ public: |
| 1351 | 1373 | #if _LIBCPP_STD_VER > 11 |
| 1352 | 1374 | template <typename _K2> |
| 1353 | 1375 | _LIBCPP_INLINE_VISIBILITY |
| 1354 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,iterator>::type | |
| 1376 | typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type | |
| 1355 | 1377 | upper_bound(const _K2& __k) {return __tree_.upper_bound(__k);} |
| 1356 | 1378 | template <typename _K2> |
| 1357 | 1379 | _LIBCPP_INLINE_VISIBILITY |
| 1358 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,const_iterator>::type | |
| 1380 | typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type | |
| 1359 | 1381 | upper_bound(const _K2& __k) const {return __tree_.upper_bound(__k);} |
| 1360 | 1382 | #endif |
| 1361 | 1383 | |
| ... | ... | @@ -1368,23 +1390,23 @@ public: |
| 1368 | 1390 | #if _LIBCPP_STD_VER > 11 |
| 1369 | 1391 | template <typename _K2> |
| 1370 | 1392 | _LIBCPP_INLINE_VISIBILITY |
| 1371 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,pair<iterator,iterator>>::type | |
| 1393 | typename enable_if<__is_transparent<_Compare, _K2>::value,pair<iterator,iterator>>::type | |
| 1372 | 1394 | equal_range(const _K2& __k) {return __tree_.__equal_range_multi(__k);} |
| 1373 | 1395 | template <typename _K2> |
| 1374 | 1396 | _LIBCPP_INLINE_VISIBILITY |
| 1375 | typename _VSTD::enable_if<_VSTD::__is_transparent<_Compare, _K2>::value,pair<const_iterator,const_iterator>>::type | |
| 1397 | typename enable_if<__is_transparent<_Compare, _K2>::value,pair<const_iterator,const_iterator>>::type | |
| 1376 | 1398 | equal_range(const _K2& __k) const {return __tree_.__equal_range_multi(__k);} |
| 1377 | 1399 | #endif |
| 1378 | 1400 | }; |
| 1379 | 1401 | |
| 1380 | 1402 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 1381 | 1403 | template<class _InputIterator, |
| 1382 | class _Compare = less<typename iterator_traits<_InputIterator>::value_type>, | |
| 1383 | class _Allocator = allocator<typename iterator_traits<_InputIterator>::value_type>, | |
| 1404 | class _Compare = less<__iter_value_type<_InputIterator>>, | |
| 1405 | class _Allocator = allocator<__iter_value_type<_InputIterator>>, | |
| 1384 | 1406 | class = _EnableIf<__is_allocator<_Allocator>::value, void>, |
| 1385 | 1407 | class = _EnableIf<!__is_allocator<_Compare>::value, void>> |
| 1386 | 1408 | multiset(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) |
| 1387 | -> multiset<typename iterator_traits<_InputIterator>::value_type, _Compare, _Allocator>; | |
| 1409 | -> multiset<__iter_value_type<_InputIterator>, _Compare, _Allocator>; | |
| 1388 | 1410 | |
| 1389 | 1411 | template<class _Key, class _Compare = less<_Key>, |
| 1390 | 1412 | class _Allocator = allocator<_Key>, |
| ... | ... | @@ -1396,8 +1418,8 @@ multiset(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator( |
| 1396 | 1418 | template<class _InputIterator, class _Allocator, |
| 1397 | 1419 | class = _EnableIf<__is_allocator<_Allocator>::value, void>> |
| 1398 | 1420 | multiset(_InputIterator, _InputIterator, _Allocator) |
| 1399 | -> multiset<typename iterator_traits<_InputIterator>::value_type, | |
| 1400 | less<typename iterator_traits<_InputIterator>::value_type>, _Allocator>; | |
| 1421 | -> multiset<__iter_value_type<_InputIterator>, | |
| 1422 | less<__iter_value_type<_InputIterator>>, _Allocator>; | |
| 1401 | 1423 | |
| 1402 | 1424 | template<class _Key, class _Allocator, |
| 1403 | 1425 | class = _EnableIf<__is_allocator<_Allocator>::value, void>> |
| ... | ... | @@ -1419,7 +1441,7 @@ multiset<_Key, _Compare, _Allocator>::multiset(multiset&& __s, const allocator_t |
| 1419 | 1441 | } |
| 1420 | 1442 | } |
| 1421 | 1443 | |
| 1422 | #endif // _LIBCPP_CXX03_LANG | |
| 1444 | #endif // _LIBCPP_CXX03_LANG | |
| 1423 | 1445 | |
| 1424 | 1446 | template <class _Key, class _Compare, class _Allocator> |
| 1425 | 1447 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1490,10 +1512,10 @@ template <class _Key, class _Compare, class _Allocator, class _Predicate> |
| 1490 | 1512 | inline _LIBCPP_INLINE_VISIBILITY |
| 1491 | 1513 | typename multiset<_Key, _Compare, _Allocator>::size_type |
| 1492 | 1514 | erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred) { |
| 1493 | return __libcpp_erase_if_container(__c, __pred); | |
| 1515 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 1494 | 1516 | } |
| 1495 | 1517 | #endif |
| 1496 | 1518 | |
| 1497 | 1519 | _LIBCPP_END_NAMESPACE_STD |
| 1498 | 1520 | |
| 1499 | #endif // _LIBCPP_SET | |
| 1521 | #endif // _LIBCPP_SET |
lib/libcxx/include/setjmp.h+1-1| ... | ... | @@ -41,4 +41,4 @@ void longjmp(jmp_buf env, int val); |
| 41 | 41 | |
| 42 | 42 | #endif // __cplusplus |
| 43 | 43 | |
| 44 | #endif // _LIBCPP_SETJMP_H | |
| 44 | #endif // _LIBCPP_SETJMP_H |
lib/libcxx/include/shared_mutex+4-4| ... | ... | @@ -122,8 +122,8 @@ template <class Mutex> |
| 122 | 122 | |
| 123 | 123 | */ |
| 124 | 124 | |
| 125 | #include <__config> | |
| 126 | 125 | #include <__availability> |
| 126 | #include <__config> | |
| 127 | 127 | #include <version> |
| 128 | 128 | |
| 129 | 129 | _LIBCPP_PUSH_MACROS |
| ... | ... | @@ -500,10 +500,10 @@ swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT |
| 500 | 500 | |
| 501 | 501 | _LIBCPP_END_NAMESPACE_STD |
| 502 | 502 | |
| 503 | #endif // !_LIBCPP_HAS_NO_THREADS | |
| 503 | #endif // !_LIBCPP_HAS_NO_THREADS | |
| 504 | 504 | |
| 505 | #endif // _LIBCPP_STD_VER > 11 | |
| 505 | #endif // _LIBCPP_STD_VER > 11 | |
| 506 | 506 | |
| 507 | 507 | _LIBCPP_POP_MACROS |
| 508 | 508 | |
| 509 | #endif // _LIBCPP_SHARED_MUTEX | |
| 509 | #endif // _LIBCPP_SHARED_MUTEX |
lib/libcxx/include/span+30-3| ... | ... | @@ -22,6 +22,12 @@ inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max(); |
| 22 | 22 | template <class ElementType, size_t Extent = dynamic_extent> |
| 23 | 23 | class span; |
| 24 | 24 | |
| 25 | template<class ElementType, size_t Extent> | |
| 26 | inline constexpr bool ranges::enable_view<span<ElementType, Extent>> = true; | |
| 27 | ||
| 28 | template<class ElementType, size_t Extent> | |
| 29 | inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true; | |
| 30 | ||
| 25 | 31 | // [span.objectrep], views of object representation |
| 26 | 32 | template <class ElementType, size_t Extent> |
| 27 | 33 | span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : |
| ... | ... | @@ -32,7 +38,6 @@ template <class ElementType, size_t Extent> |
| 32 | 38 | (sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept; |
| 33 | 39 | |
| 34 | 40 | |
| 35 | namespace std { | |
| 36 | 41 | template <class ElementType, size_t Extent = dynamic_extent> |
| 37 | 42 | class span { |
| 38 | 43 | public: |
| ... | ... | @@ -123,10 +128,16 @@ template<class Container> |
| 123 | 128 | */ |
| 124 | 129 | |
| 125 | 130 | #include <__config> |
| 131 | #include <__debug> | |
| 132 | #include <__iterator/wrap_iter.h> | |
| 133 | #include <__ranges/enable_borrowed_range.h> | |
| 134 | #include <__ranges/enable_view.h> | |
| 126 | 135 | #include <array> // for array |
| 127 | 136 | #include <cstddef> // for byte |
| 128 | 137 | #include <iterator> // for iterators |
| 138 | #include <limits> | |
| 129 | 139 | #include <type_traits> // for remove_cv, etc |
| 140 | #include <version> | |
| 130 | 141 | |
| 131 | 142 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 132 | 143 | #pragma GCC system_header |
| ... | ... | @@ -197,7 +208,11 @@ public: |
| 197 | 208 | using const_pointer = const _Tp *; |
| 198 | 209 | using reference = _Tp &; |
| 199 | 210 | using const_reference = const _Tp &; |
| 200 | using iterator = __wrap_iter<pointer>; | |
| 211 | #if (_LIBCPP_DEBUG_LEVEL == 2) || defined(_LIBCPP_ABI_SPAN_POINTER_ITERATORS) | |
| 212 | using iterator = pointer; | |
| 213 | #else | |
| 214 | using iterator = __wrap_iter<pointer>; | |
| 215 | #endif | |
| 201 | 216 | using reverse_iterator = _VSTD::reverse_iterator<iterator>; |
| 202 | 217 | |
| 203 | 218 | static constexpr size_type extent = _Extent; |
| ... | ... | @@ -372,7 +387,11 @@ public: |
| 372 | 387 | using const_pointer = const _Tp *; |
| 373 | 388 | using reference = _Tp &; |
| 374 | 389 | using const_reference = const _Tp &; |
| 375 | using iterator = __wrap_iter<pointer>; | |
| 390 | #if (_LIBCPP_DEBUG_LEVEL == 2) || defined(_LIBCPP_ABI_SPAN_POINTER_ITERATORS) | |
| 391 | using iterator = pointer; | |
| 392 | #else | |
| 393 | using iterator = __wrap_iter<pointer>; | |
| 394 | #endif | |
| 376 | 395 | using reverse_iterator = _VSTD::reverse_iterator<iterator>; |
| 377 | 396 | |
| 378 | 397 | static constexpr size_type extent = dynamic_extent; |
| ... | ... | @@ -516,6 +535,14 @@ private: |
| 516 | 535 | size_type __size; |
| 517 | 536 | }; |
| 518 | 537 | |
| 538 | #if !defined(_LIBCPP_HAS_NO_RANGES) | |
| 539 | template <class _Tp, size_t _Extent> | |
| 540 | inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true; | |
| 541 | ||
| 542 | template <class _ElementType, size_t _Extent> | |
| 543 | inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true; | |
| 544 | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | |
| 545 | ||
| 519 | 546 | // as_bytes & as_writable_bytes |
| 520 | 547 | template <class _Tp, size_t _Extent> |
| 521 | 548 | _LIBCPP_INLINE_VISIBILITY |
lib/libcxx/include/sstream+13-37| ... | ... | @@ -181,8 +181,8 @@ typedef basic_stringstream<wchar_t> wstringstream; |
| 181 | 181 | */ |
| 182 | 182 | |
| 183 | 183 | #include <__config> |
| 184 | #include <ostream> | |
| 185 | 184 | #include <istream> |
| 185 | #include <ostream> | |
| 186 | 186 | #include <string> |
| 187 | 187 | |
| 188 | 188 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -219,19 +219,13 @@ private: |
| 219 | 219 | |
| 220 | 220 | public: |
| 221 | 221 | // 30.8.2.1 [stringbuf.cons], constructors |
| 222 | #ifndef _LIBCPP_CXX03_LANG | |
| 223 | 222 | _LIBCPP_INLINE_VISIBILITY |
| 224 | basic_stringbuf() : basic_stringbuf(ios_base::in | ios_base::out) {} | |
| 223 | basic_stringbuf() | |
| 224 | : __hm_(nullptr), __mode_(ios_base::in | ios_base::out) {} | |
| 225 | 225 | |
| 226 | 226 | _LIBCPP_INLINE_VISIBILITY |
| 227 | 227 | explicit basic_stringbuf(ios_base::openmode __wch) |
| 228 | 228 | : __hm_(nullptr), __mode_(__wch) {} |
| 229 | #else | |
| 230 | _LIBCPP_INLINE_VISIBILITY | |
| 231 | explicit basic_stringbuf(ios_base::openmode __wch = ios_base::in | | |
| 232 | ios_base::out) | |
| 233 | : __hm_(nullptr), __mode_(__wch) {} | |
| 234 | #endif | |
| 235 | 229 | |
| 236 | 230 | _LIBCPP_INLINE_VISIBILITY |
| 237 | 231 | explicit basic_stringbuf(const string_type& __s, |
| ... | ... | @@ -542,7 +536,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::overflow(int_type __c) |
| 542 | 536 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 543 | 537 | try |
| 544 | 538 | { |
| 545 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 539 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 546 | 540 | ptrdiff_t __nout = this->pptr() - this->pbase(); |
| 547 | 541 | ptrdiff_t __hm = __hm_ - this->pbase(); |
| 548 | 542 | __str_.push_back(char_type()); |
| ... | ... | @@ -557,7 +551,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::overflow(int_type __c) |
| 557 | 551 | { |
| 558 | 552 | return traits_type::eof(); |
| 559 | 553 | } |
| 560 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 554 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 561 | 555 | } |
| 562 | 556 | __hm_ = _VSTD::max(this->pptr() + 1, __hm_); |
| 563 | 557 | if (__mode_ & ios_base::in) |
| ... | ... | @@ -643,18 +637,13 @@ private: |
| 643 | 637 | |
| 644 | 638 | public: |
| 645 | 639 | // 30.8.3.1 [istringstream.cons], constructors |
| 646 | #ifndef _LIBCPP_CXX03_LANG | |
| 647 | 640 | _LIBCPP_INLINE_VISIBILITY |
| 648 | basic_istringstream() : basic_istringstream(ios_base::in) {} | |
| 641 | basic_istringstream() | |
| 642 | : basic_istream<_CharT, _Traits>(&__sb_), __sb_(ios_base::in) {} | |
| 649 | 643 | |
| 650 | 644 | _LIBCPP_INLINE_VISIBILITY |
| 651 | 645 | explicit basic_istringstream(ios_base::openmode __wch) |
| 652 | 646 | : basic_istream<_CharT, _Traits>(&__sb_), __sb_(__wch | ios_base::in) {} |
| 653 | #else | |
| 654 | _LIBCPP_INLINE_VISIBILITY | |
| 655 | explicit basic_istringstream(ios_base::openmode __wch = ios_base::in) | |
| 656 | : basic_istream<_CharT, _Traits>(&__sb_), __sb_(__wch | ios_base::in) {} | |
| 657 | #endif | |
| 658 | 647 | |
| 659 | 648 | _LIBCPP_INLINE_VISIBILITY |
| 660 | 649 | explicit basic_istringstream(const string_type& __s, |
| ... | ... | @@ -728,20 +717,13 @@ private: |
| 728 | 717 | |
| 729 | 718 | public: |
| 730 | 719 | // 30.8.4.1 [ostringstream.cons], constructors |
| 731 | #ifndef _LIBCPP_CXX03_LANG | |
| 732 | 720 | _LIBCPP_INLINE_VISIBILITY |
| 733 | basic_ostringstream() : basic_ostringstream(ios_base::out) {} | |
| 721 | basic_ostringstream() | |
| 722 | : basic_ostream<_CharT, _Traits>(&__sb_), __sb_(ios_base::out) {} | |
| 734 | 723 | |
| 735 | 724 | _LIBCPP_INLINE_VISIBILITY |
| 736 | 725 | explicit basic_ostringstream(ios_base::openmode __wch) |
| 737 | : basic_ostream<_CharT, _Traits>(&__sb_), | |
| 738 | __sb_(__wch | ios_base::out) {} | |
| 739 | #else | |
| 740 | _LIBCPP_INLINE_VISIBILITY | |
| 741 | explicit basic_ostringstream(ios_base::openmode __wch = ios_base::out) | |
| 742 | : basic_ostream<_CharT, _Traits>(&__sb_), | |
| 743 | __sb_(__wch | ios_base::out) {} | |
| 744 | #endif | |
| 726 | : basic_ostream<_CharT, _Traits>(&__sb_), __sb_(__wch | ios_base::out) {} | |
| 745 | 727 | |
| 746 | 728 | _LIBCPP_INLINE_VISIBILITY |
| 747 | 729 | explicit basic_ostringstream(const string_type& __s, |
| ... | ... | @@ -816,19 +798,13 @@ private: |
| 816 | 798 | |
| 817 | 799 | public: |
| 818 | 800 | // 30.8.5.1 [stringstream.cons], constructors |
| 819 | #ifndef _LIBCPP_CXX03_LANG | |
| 820 | 801 | _LIBCPP_INLINE_VISIBILITY |
| 821 | basic_stringstream() : basic_stringstream(ios_base::in | ios_base::out) {} | |
| 802 | basic_stringstream() | |
| 803 | : basic_iostream<_CharT, _Traits>(&__sb_), __sb_(ios_base::in | ios_base::out) {} | |
| 822 | 804 | |
| 823 | 805 | _LIBCPP_INLINE_VISIBILITY |
| 824 | 806 | explicit basic_stringstream(ios_base::openmode __wch) |
| 825 | 807 | : basic_iostream<_CharT, _Traits>(&__sb_), __sb_(__wch) {} |
| 826 | #else | |
| 827 | _LIBCPP_INLINE_VISIBILITY | |
| 828 | explicit basic_stringstream(ios_base::openmode __wch = ios_base::in | | |
| 829 | ios_base::out) | |
| 830 | : basic_iostream<_CharT, _Traits>(&__sb_), __sb_(__wch) {} | |
| 831 | #endif | |
| 832 | 808 | |
| 833 | 809 | _LIBCPP_INLINE_VISIBILITY |
| 834 | 810 | explicit basic_stringstream(const string_type& __s, |
| ... | ... | @@ -892,4 +868,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 892 | 868 | |
| 893 | 869 | _LIBCPP_POP_MACROS |
| 894 | 870 | |
| 895 | #endif // _LIBCPP_SSTREAM | |
| 871 | #endif // _LIBCPP_SSTREAM |
lib/libcxx/include/stack+15-21| ... | ... | @@ -88,6 +88,8 @@ template <class T, class Container> |
| 88 | 88 | */ |
| 89 | 89 | |
| 90 | 90 | #include <__config> |
| 91 | #include <__memory/uses_allocator.h> | |
| 92 | #include <__utility/forward.h> | |
| 91 | 93 | #include <deque> |
| 92 | 94 | |
| 93 | 95 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -148,7 +150,7 @@ public: |
| 148 | 150 | |
| 149 | 151 | _LIBCPP_INLINE_VISIBILITY |
| 150 | 152 | explicit stack(container_type&& __c) : c(_VSTD::move(__c)) {} |
| 151 | #endif // _LIBCPP_CXX03_LANG | |
| 153 | #endif // _LIBCPP_CXX03_LANG | |
| 152 | 154 | |
| 153 | 155 | _LIBCPP_INLINE_VISIBILITY |
| 154 | 156 | explicit stack(const container_type& __c) : c(__c) {} |
| ... | ... | @@ -156,35 +158,30 @@ public: |
| 156 | 158 | template <class _Alloc> |
| 157 | 159 | _LIBCPP_INLINE_VISIBILITY |
| 158 | 160 | explicit stack(const _Alloc& __a, |
| 159 | typename enable_if<uses_allocator<container_type, | |
| 160 | _Alloc>::value>::type* = 0) | |
| 161 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 161 | 162 | : c(__a) {} |
| 162 | 163 | template <class _Alloc> |
| 163 | 164 | _LIBCPP_INLINE_VISIBILITY |
| 164 | 165 | stack(const container_type& __c, const _Alloc& __a, |
| 165 | typename enable_if<uses_allocator<container_type, | |
| 166 | _Alloc>::value>::type* = 0) | |
| 166 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 167 | 167 | : c(__c, __a) {} |
| 168 | 168 | template <class _Alloc> |
| 169 | 169 | _LIBCPP_INLINE_VISIBILITY |
| 170 | 170 | stack(const stack& __s, const _Alloc& __a, |
| 171 | typename enable_if<uses_allocator<container_type, | |
| 172 | _Alloc>::value>::type* = 0) | |
| 171 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 173 | 172 | : c(__s.c, __a) {} |
| 174 | 173 | #ifndef _LIBCPP_CXX03_LANG |
| 175 | 174 | template <class _Alloc> |
| 176 | 175 | _LIBCPP_INLINE_VISIBILITY |
| 177 | 176 | stack(container_type&& __c, const _Alloc& __a, |
| 178 | typename enable_if<uses_allocator<container_type, | |
| 179 | _Alloc>::value>::type* = 0) | |
| 177 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 180 | 178 | : c(_VSTD::move(__c), __a) {} |
| 181 | 179 | template <class _Alloc> |
| 182 | 180 | _LIBCPP_INLINE_VISIBILITY |
| 183 | 181 | stack(stack&& __s, const _Alloc& __a, |
| 184 | typename enable_if<uses_allocator<container_type, | |
| 185 | _Alloc>::value>::type* = 0) | |
| 182 | _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0) | |
| 186 | 183 | : c(_VSTD::move(__s.c), __a) {} |
| 187 | #endif // _LIBCPP_CXX03_LANG | |
| 184 | #endif // _LIBCPP_CXX03_LANG | |
| 188 | 185 | |
| 189 | 186 | _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY |
| 190 | 187 | bool empty() const {return c.empty();} |
| ... | ... | @@ -210,7 +207,7 @@ public: |
| 210 | 207 | void emplace(_Args&&... __args) |
| 211 | 208 | { c.emplace_back(_VSTD::forward<_Args>(__args)...);} |
| 212 | 209 | #endif |
| 213 | #endif // _LIBCPP_CXX03_LANG | |
| 210 | #endif // _LIBCPP_CXX03_LANG | |
| 214 | 211 | |
| 215 | 212 | _LIBCPP_INLINE_VISIBILITY |
| 216 | 213 | void pop() {c.pop_back();} |
| ... | ... | @@ -236,15 +233,15 @@ public: |
| 236 | 233 | |
| 237 | 234 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 238 | 235 | template<class _Container, |
| 239 | class = typename enable_if<!__is_allocator<_Container>::value, nullptr_t>::type | |
| 236 | class = _EnableIf<!__is_allocator<_Container>::value> | |
| 240 | 237 | > |
| 241 | 238 | stack(_Container) |
| 242 | 239 | -> stack<typename _Container::value_type, _Container>; |
| 243 | 240 | |
| 244 | 241 | template<class _Container, |
| 245 | 242 | class _Alloc, |
| 246 | class = typename enable_if<!__is_allocator<_Container>::value, nullptr_t>::type, | |
| 247 | class = typename enable_if< __is_allocator<_Alloc>::value, nullptr_t>::type | |
| 243 | class = _EnableIf<!__is_allocator<_Container>::value>, | |
| 244 | class = _EnableIf<uses_allocator<_Container, _Alloc>::value> | |
| 248 | 245 | > |
| 249 | 246 | stack(_Container, _Alloc) |
| 250 | 247 | -> stack<typename _Container::value_type, _Container>; |
| ... | ... | @@ -300,10 +297,7 @@ operator<=(const stack<_Tp, _Container>& __x, const stack<_Tp, _Container>& __y) |
| 300 | 297 | |
| 301 | 298 | template <class _Tp, class _Container> |
| 302 | 299 | inline _LIBCPP_INLINE_VISIBILITY |
| 303 | typename enable_if< | |
| 304 | __is_swappable<_Container>::value, | |
| 305 | void | |
| 306 | >::type | |
| 300 | _EnableIf<__is_swappable<_Container>::value, void> | |
| 307 | 301 | swap(stack<_Tp, _Container>& __x, stack<_Tp, _Container>& __y) |
| 308 | 302 | _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) |
| 309 | 303 | { |
| ... | ... | @@ -318,4 +312,4 @@ struct _LIBCPP_TEMPLATE_VIS uses_allocator<stack<_Tp, _Container>, _Alloc> |
| 318 | 312 | |
| 319 | 313 | _LIBCPP_END_NAMESPACE_STD |
| 320 | 314 | |
| 321 | #endif // _LIBCPP_STACK | |
| 315 | #endif // _LIBCPP_STACK |
lib/libcxx/include/stdbool.h+1-1| ... | ... | @@ -35,4 +35,4 @@ Macros: |
| 35 | 35 | #define __bool_true_false_are_defined 1 |
| 36 | 36 | #endif |
| 37 | 37 | |
| 38 | #endif // _LIBCPP_STDBOOL_H | |
| 38 | #endif // _LIBCPP_STDBOOL_H |
lib/libcxx/include/stddef.h+1-1| ... | ... | @@ -53,4 +53,4 @@ using std::nullptr_t; |
| 53 | 53 | |
| 54 | 54 | #endif |
| 55 | 55 | |
| 56 | #endif // _LIBCPP_STDDEF_H | |
| 56 | #endif // _LIBCPP_STDDEF_H |
lib/libcxx/include/stdexcept+2-2| ... | ... | @@ -42,9 +42,9 @@ public: |
| 42 | 42 | */ |
| 43 | 43 | |
| 44 | 44 | #include <__config> |
| 45 | #include <cstdlib> | |
| 46 | 45 | #include <exception> |
| 47 | 46 | #include <iosfwd> // for string forward decl |
| 47 | #include <cstdlib> | |
| 48 | 48 | |
| 49 | 49 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 50 | 50 | #pragma GCC system_header |
| ... | ... | @@ -306,4 +306,4 @@ void __throw_underflow_error(const char*__msg) |
| 306 | 306 | |
| 307 | 307 | _LIBCPP_END_NAMESPACE_STD |
| 308 | 308 | |
| 309 | #endif // _LIBCPP_STDEXCEPT | |
| 309 | #endif // _LIBCPP_STDEXCEPT |
lib/libcxx/include/stdint.h+1-1| ... | ... | @@ -122,4 +122,4 @@ Macros: |
| 122 | 122 | |
| 123 | 123 | #include_next <stdint.h> |
| 124 | 124 | |
| 125 | #endif // _LIBCPP_STDINT_H | |
| 125 | #endif // _LIBCPP_STDINT_H |
lib/libcxx/include/stdio.h+1-1| ... | ... | @@ -116,4 +116,4 @@ void perror(const char* s); |
| 116 | 116 | |
| 117 | 117 | #endif |
| 118 | 118 | |
| 119 | #endif // _LIBCPP_STDIO_H | |
| 119 | #endif // _LIBCPP_STDIO_H |
lib/libcxx/include/stdlib.h+8-8| ... | ... | @@ -103,7 +103,7 @@ extern "C++" { |
| 103 | 103 | #endif |
| 104 | 104 | |
| 105 | 105 | // MSVCRT already has the correct prototype in <stdlib.h> if __cplusplus is defined |
| 106 | #if !defined(_LIBCPP_MSVCRT) && !defined(__sun__) && !defined(_AIX) | |
| 106 | #if !defined(_LIBCPP_MSVCRT) && !defined(__sun__) | |
| 107 | 107 | inline _LIBCPP_INLINE_VISIBILITY long abs(long __x) _NOEXCEPT { |
| 108 | 108 | return __builtin_labs(__x); |
| 109 | 109 | } |
| ... | ... | @@ -112,9 +112,9 @@ inline _LIBCPP_INLINE_VISIBILITY long long abs(long long __x) _NOEXCEPT { |
| 112 | 112 | return __builtin_llabs(__x); |
| 113 | 113 | } |
| 114 | 114 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 115 | #endif // !defined(_LIBCPP_MSVCRT) && !defined(__sun__) && !defined(_AIX) | |
| 115 | #endif // !defined(_LIBCPP_MSVCRT) && !defined(__sun__) | |
| 116 | 116 | |
| 117 | #if !(defined(_AIX) || defined(__sun__)) | |
| 117 | #if !defined(__sun__) | |
| 118 | 118 | inline _LIBCPP_INLINE_VISIBILITY float abs(float __lcpp_x) _NOEXCEPT { |
| 119 | 119 | return __builtin_fabsf(__lcpp_x); // Use builtins to prevent needing math.h |
| 120 | 120 | } |
| ... | ... | @@ -127,7 +127,7 @@ inline _LIBCPP_INLINE_VISIBILITY long double |
| 127 | 127 | abs(long double __lcpp_x) _NOEXCEPT { |
| 128 | 128 | return __builtin_fabsl(__lcpp_x); |
| 129 | 129 | } |
| 130 | #endif // !(defined(_AIX) || defined(__sun__)) | |
| 130 | #endif // !defined(__sun__) | |
| 131 | 131 | |
| 132 | 132 | // div |
| 133 | 133 | |
| ... | ... | @@ -138,7 +138,7 @@ abs(long double __lcpp_x) _NOEXCEPT { |
| 138 | 138 | #endif |
| 139 | 139 | |
| 140 | 140 | // MSVCRT already has the correct prototype in <stdlib.h> if __cplusplus is defined |
| 141 | #if !defined(_LIBCPP_MSVCRT) && !defined(__sun__) && !defined(_AIX) | |
| 141 | #if !defined(_LIBCPP_MSVCRT) && !defined(__sun__) | |
| 142 | 142 | inline _LIBCPP_INLINE_VISIBILITY ldiv_t div(long __x, long __y) _NOEXCEPT { |
| 143 | 143 | return ::ldiv(__x, __y); |
| 144 | 144 | } |
| ... | ... | @@ -148,8 +148,8 @@ inline _LIBCPP_INLINE_VISIBILITY lldiv_t div(long long __x, |
| 148 | 148 | return ::lldiv(__x, __y); |
| 149 | 149 | } |
| 150 | 150 | #endif // _LIBCPP_HAS_NO_LONG_LONG |
| 151 | #endif // _LIBCPP_MSVCRT / __sun__ / _AIX | |
| 151 | #endif // _LIBCPP_MSVCRT / __sun__ | |
| 152 | 152 | } // extern "C++" |
| 153 | #endif // __cplusplus | |
| 153 | #endif // __cplusplus | |
| 154 | 154 | |
| 155 | #endif // _LIBCPP_STDLIB_H | |
| 155 | #endif // _LIBCPP_STDLIB_H |
lib/libcxx/include/streambuf+4-4| ... | ... | @@ -7,8 +7,8 @@ |
| 7 | 7 | // |
| 8 | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | |
| 10 | #ifndef _LIBCPP_STEAMBUF | |
| 11 | #define _LIBCPP_STEAMBUF | |
| 10 | #ifndef _LIBCPP_STREAMBUF | |
| 11 | #define _LIBCPP_STREAMBUF | |
| 12 | 12 | |
| 13 | 13 | /* |
| 14 | 14 | streambuf synopsis |
| ... | ... | @@ -108,8 +108,8 @@ protected: |
| 108 | 108 | */ |
| 109 | 109 | |
| 110 | 110 | #include <__config> |
| 111 | #include <iosfwd> | |
| 112 | 111 | #include <ios> |
| 112 | #include <iosfwd> | |
| 113 | 113 | |
| 114 | 114 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 115 | 115 | #pragma GCC system_header |
| ... | ... | @@ -495,4 +495,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 495 | 495 | |
| 496 | 496 | _LIBCPP_POP_MACROS |
| 497 | 497 | |
| 498 | #endif // _LIBCPP_STEAMBUF | |
| 498 | #endif // _LIBCPP_STREAMBUF |
lib/libcxx/include/string+179-176| ... | ... | @@ -69,6 +69,9 @@ struct char_traits |
| 69 | 69 | |
| 70 | 70 | template <> struct char_traits<char>; |
| 71 | 71 | template <> struct char_traits<wchar_t>; |
| 72 | template <> struct char_traits<char8_t>; // C++20 | |
| 73 | template <> struct char_traits<char16_t>; | |
| 74 | template <> struct char_traits<char32_t>; | |
| 72 | 75 | |
| 73 | 76 | template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > |
| 74 | 77 | class basic_string |
| ... | ... | @@ -107,6 +110,7 @@ public: |
| 107 | 110 | explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17 |
| 108 | 111 | basic_string(const value_type* s, const allocator_type& a = allocator_type()); |
| 109 | 112 | basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); |
| 113 | basic_string(nullptr_t) = delete; // C++2b | |
| 110 | 114 | basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); |
| 111 | 115 | template<class InputIterator> |
| 112 | 116 | basic_string(InputIterator begin, InputIterator end, |
| ... | ... | @@ -127,6 +131,7 @@ public: |
| 127 | 131 | allocator_type::propagate_on_container_move_assignment::value || |
| 128 | 132 | allocator_type::is_always_equal::value ); // C++17 |
| 129 | 133 | basic_string& operator=(const value_type* s); |
| 134 | basic_string& operator=(nullptr_t) = delete; // C++2b | |
| 130 | 135 | basic_string& operator=(value_type c); |
| 131 | 136 | basic_string& operator=(initializer_list<value_type>); |
| 132 | 137 | |
| ... | ... | @@ -262,49 +267,49 @@ public: |
| 262 | 267 | |
| 263 | 268 | size_type find(const basic_string& str, size_type pos = 0) const noexcept; |
| 264 | 269 | template <class T> |
| 265 | size_type find(const T& t, size_type pos = 0) const; // C++17 | |
| 270 | size_type find(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension | |
| 266 | 271 | size_type find(const value_type* s, size_type pos, size_type n) const noexcept; |
| 267 | 272 | size_type find(const value_type* s, size_type pos = 0) const noexcept; |
| 268 | 273 | size_type find(value_type c, size_type pos = 0) const noexcept; |
| 269 | 274 | |
| 270 | 275 | size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; |
| 271 | 276 | template <class T> |
| 272 | size_type rfind(const T& t, size_type pos = npos) const; // C++17 | |
| 277 | size_type rfind(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension | |
| 273 | 278 | size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept; |
| 274 | 279 | size_type rfind(const value_type* s, size_type pos = npos) const noexcept; |
| 275 | 280 | size_type rfind(value_type c, size_type pos = npos) const noexcept; |
| 276 | 281 | |
| 277 | 282 | size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; |
| 278 | 283 | template <class T> |
| 279 | size_type find_first_of(const T& t, size_type pos = 0) const; // C++17 | |
| 284 | size_type find_first_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension | |
| 280 | 285 | size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept; |
| 281 | 286 | size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept; |
| 282 | 287 | size_type find_first_of(value_type c, size_type pos = 0) const noexcept; |
| 283 | 288 | |
| 284 | 289 | size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept; |
| 285 | 290 | template <class T> |
| 286 | size_type find_last_of(const T& t, size_type pos = npos) const noexcept; // C++17 | |
| 291 | size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept; // C++17, noexcept as an extension | |
| 287 | 292 | size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept; |
| 288 | 293 | size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept; |
| 289 | 294 | size_type find_last_of(value_type c, size_type pos = npos) const noexcept; |
| 290 | 295 | |
| 291 | 296 | size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; |
| 292 | 297 | template <class T> |
| 293 | size_type find_first_not_of(const T& t, size_type pos = 0) const; // C++17 | |
| 298 | size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension | |
| 294 | 299 | size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; |
| 295 | 300 | size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept; |
| 296 | 301 | size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept; |
| 297 | 302 | |
| 298 | 303 | size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept; |
| 299 | 304 | template <class T> |
| 300 | size_type find_last_not_of(const T& t, size_type pos = npos) const; // C++17 | |
| 305 | size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension | |
| 301 | 306 | size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; |
| 302 | 307 | size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept; |
| 303 | 308 | size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept; |
| 304 | 309 | |
| 305 | 310 | int compare(const basic_string& str) const noexcept; |
| 306 | 311 | template <class T> |
| 307 | int compare(const T& t) const noexcept; // C++17 | |
| 312 | int compare(const T& t) const noexcept; // C++17, noexcept as an extension | |
| 308 | 313 | int compare(size_type pos1, size_type n1, const basic_string& str) const; |
| 309 | 314 | template <class T> |
| 310 | 315 | int compare(size_type pos1, size_type n1, const T& t) const; // C++17 |
| ... | ... | @@ -450,6 +455,7 @@ erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20 |
| 450 | 455 | |
| 451 | 456 | typedef basic_string<char> string; |
| 452 | 457 | typedef basic_string<wchar_t> wstring; |
| 458 | typedef basic_string<char8_t> u8string; // C++20 | |
| 453 | 459 | typedef basic_string<char16_t> u16string; |
| 454 | 460 | typedef basic_string<char32_t> u32string; |
| 455 | 461 | |
| ... | ... | @@ -494,12 +500,14 @@ wstring to_wstring(double val); |
| 494 | 500 | wstring to_wstring(long double val); |
| 495 | 501 | |
| 496 | 502 | template <> struct hash<string>; |
| 503 | template <> struct hash<u8string>; // C++20 | |
| 497 | 504 | template <> struct hash<u16string>; |
| 498 | 505 | template <> struct hash<u32string>; |
| 499 | 506 | template <> struct hash<wstring>; |
| 500 | 507 | |
| 501 | 508 | basic_string<char> operator "" s( const char *str, size_t len ); // C++14 |
| 502 | 509 | basic_string<wchar_t> operator "" s( const wchar_t *str, size_t len ); // C++14 |
| 510 | basic_string<char8_t> operator "" s( const char8_t *str, size_t len ); // C++20 | |
| 503 | 511 | basic_string<char16_t> operator "" s( const char16_t *str, size_t len ); // C++14 |
| 504 | 512 | basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); // C++14 |
| 505 | 513 | |
| ... | ... | @@ -508,26 +516,28 @@ basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); // C++1 |
| 508 | 516 | */ |
| 509 | 517 | |
| 510 | 518 | #include <__config> |
| 511 | #include <string_view> | |
| 512 | #include <iosfwd> | |
| 519 | #include <__debug> | |
| 520 | #include <__functional_base> | |
| 521 | #include <__iterator/wrap_iter.h> | |
| 522 | #include <algorithm> | |
| 523 | #include <compare> | |
| 524 | #include <cstdio> // EOF | |
| 513 | 525 | #include <cstring> |
| 514 | #include <cstdio> // For EOF. | |
| 515 | 526 | #include <cwchar> |
| 516 | #include <algorithm> | |
| 527 | #include <initializer_list> | |
| 528 | #include <iosfwd> | |
| 517 | 529 | #include <iterator> |
| 518 | #include <utility> | |
| 519 | 530 | #include <memory> |
| 520 | 531 | #include <stdexcept> |
| 532 | #include <string_view> | |
| 521 | 533 | #include <type_traits> |
| 522 | #include <initializer_list> | |
| 523 | #include <__functional_base> | |
| 534 | #include <utility> | |
| 524 | 535 | #include <version> |
| 536 | ||
| 525 | 537 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS |
| 526 | #include <cstdint> | |
| 538 | # include <cstdint> | |
| 527 | 539 | #endif |
| 528 | 540 | |
| 529 | #include <__debug> | |
| 530 | ||
| 531 | 541 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 532 | 542 | #pragma GCC system_header |
| 533 | 543 | #endif |
| ... | ... | @@ -625,29 +635,16 @@ __basic_string_common<__b>::__throw_out_of_range() const |
| 625 | 635 | |
| 626 | 636 | _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __basic_string_common<true>) |
| 627 | 637 | |
| 628 | #ifdef _LIBCPP_NO_EXCEPTIONS | |
| 629 | template <class _Iter> | |
| 630 | struct __libcpp_string_gets_noexcept_iterator_impl : public true_type {}; | |
| 631 | #elif defined(_LIBCPP_HAS_NO_NOEXCEPT) | |
| 632 | 638 | template <class _Iter> |
| 633 | struct __libcpp_string_gets_noexcept_iterator_impl : public false_type {}; | |
| 634 | #else | |
| 635 | template <class _Iter, bool = __is_cpp17_forward_iterator<_Iter>::value> | |
| 636 | struct __libcpp_string_gets_noexcept_iterator_impl : public _LIBCPP_BOOL_CONSTANT(( | |
| 637 | noexcept(++(declval<_Iter&>())) && | |
| 638 | is_nothrow_assignable<_Iter&, _Iter>::value && | |
| 639 | noexcept(declval<_Iter>() == declval<_Iter>()) && | |
| 640 | noexcept(*declval<_Iter>()) | |
| 641 | )) {}; | |
| 642 | ||
| 643 | template <class _Iter> | |
| 644 | struct __libcpp_string_gets_noexcept_iterator_impl<_Iter, false> : public false_type {}; | |
| 645 | #endif | |
| 639 | struct __string_is_trivial_iterator : public false_type {}; | |
| 646 | 640 | |
| 641 | template <class _Tp> | |
| 642 | struct __string_is_trivial_iterator<_Tp*> | |
| 643 | : public is_arithmetic<_Tp> {}; | |
| 647 | 644 | |
| 648 | 645 | template <class _Iter> |
| 649 | struct __libcpp_string_gets_noexcept_iterator | |
| 650 | : public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value || __libcpp_string_gets_noexcept_iterator_impl<_Iter>::value) {}; | |
| 646 | struct __string_is_trivial_iterator<__wrap_iter<_Iter> > | |
| 647 | : public __string_is_trivial_iterator<_Iter> {}; | |
| 651 | 648 | |
| 652 | 649 | template <class _CharT, class _Traits, class _Tp> |
| 653 | 650 | struct __can_be_converted_to_string_view : public _BoolConstant< |
| ... | ... | @@ -668,21 +665,21 @@ struct __padding<_CharT, 1> |
| 668 | 665 | { |
| 669 | 666 | }; |
| 670 | 667 | |
| 671 | #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT | |
| 668 | #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT | |
| 672 | 669 | |
| 673 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 670 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 674 | 671 | typedef basic_string<char8_t> u8string; |
| 675 | 672 | #endif |
| 676 | 673 | |
| 677 | 674 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS |
| 678 | 675 | typedef basic_string<char16_t> u16string; |
| 679 | 676 | typedef basic_string<char32_t> u32string; |
| 680 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 677 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 681 | 678 | |
| 682 | 679 | template<class _CharT, class _Traits, class _Allocator> |
| 683 | 680 | class |
| 684 | 681 | _LIBCPP_TEMPLATE_VIS |
| 685 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 682 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 686 | 683 | _LIBCPP_PREFERRED_NAME(u8string) |
| 687 | 684 | #endif |
| 688 | 685 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS |
| ... | ... | @@ -736,7 +733,7 @@ private: |
| 736 | 733 | #else // _LIBCPP_BIG_ENDIAN |
| 737 | 734 | static const size_type __short_mask = 0x80; |
| 738 | 735 | static const size_type __long_mask = ~(size_type(~0) >> 1); |
| 739 | #endif // _LIBCPP_BIG_ENDIAN | |
| 736 | #endif // _LIBCPP_BIG_ENDIAN | |
| 740 | 737 | |
| 741 | 738 | enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? |
| 742 | 739 | (sizeof(__long) - 1)/sizeof(value_type) : 2}; |
| ... | ... | @@ -766,7 +763,7 @@ private: |
| 766 | 763 | #else // _LIBCPP_BIG_ENDIAN |
| 767 | 764 | static const size_type __short_mask = 0x01; |
| 768 | 765 | static const size_type __long_mask = 0x1ul; |
| 769 | #endif // _LIBCPP_BIG_ENDIAN | |
| 766 | #endif // _LIBCPP_BIG_ENDIAN | |
| 770 | 767 | |
| 771 | 768 | enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? |
| 772 | 769 | (sizeof(__long) - 1)/sizeof(value_type) : 2}; |
| ... | ... | @@ -781,7 +778,7 @@ private: |
| 781 | 778 | value_type __data_[__min_cap]; |
| 782 | 779 | }; |
| 783 | 780 | |
| 784 | #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT | |
| 781 | #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT | |
| 785 | 782 | |
| 786 | 783 | union __ulx{__long __lx; __short __lxx;}; |
| 787 | 784 | |
| ... | ... | @@ -805,7 +802,7 @@ private: |
| 805 | 802 | __compressed_pair<__rep, allocator_type> __r_; |
| 806 | 803 | |
| 807 | 804 | public: |
| 808 | _LIBCPP_FUNC_VIS | |
| 805 | _LIBCPP_TEMPLATE_DATA_VIS | |
| 809 | 806 | static const size_type npos = -1; |
| 810 | 807 | |
| 811 | 808 | _LIBCPP_INLINE_VISIBILITY basic_string() |
| ... | ... | @@ -832,7 +829,7 @@ public: |
| 832 | 829 | |
| 833 | 830 | _LIBCPP_INLINE_VISIBILITY |
| 834 | 831 | basic_string(basic_string&& __str, const allocator_type& __a); |
| 835 | #endif // _LIBCPP_CXX03_LANG | |
| 832 | #endif // _LIBCPP_CXX03_LANG | |
| 836 | 833 | |
| 837 | 834 | template <class = _EnableIf<__is_allocator<_Allocator>::value, nullptr_t> > |
| 838 | 835 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -848,6 +845,10 @@ public: |
| 848 | 845 | _LIBCPP_INLINE_VISIBILITY |
| 849 | 846 | basic_string(const _CharT* __s, const _Allocator& __a); |
| 850 | 847 | |
| 848 | #if _LIBCPP_STD_VER > 20 | |
| 849 | basic_string(nullptr_t) = delete; | |
| 850 | #endif | |
| 851 | ||
| 851 | 852 | _LIBCPP_INLINE_VISIBILITY |
| 852 | 853 | basic_string(const _CharT* __s, size_type __n); |
| 853 | 854 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -890,7 +891,7 @@ public: |
| 890 | 891 | basic_string(initializer_list<_CharT> __il); |
| 891 | 892 | _LIBCPP_INLINE_VISIBILITY |
| 892 | 893 | basic_string(initializer_list<_CharT> __il, const _Allocator& __a); |
| 893 | #endif // _LIBCPP_CXX03_LANG | |
| 894 | #endif // _LIBCPP_CXX03_LANG | |
| 894 | 895 | |
| 895 | 896 | inline ~basic_string(); |
| 896 | 897 | |
| ... | ... | @@ -911,6 +912,9 @@ public: |
| 911 | 912 | basic_string& operator=(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());} |
| 912 | 913 | #endif |
| 913 | 914 | _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);} |
| 915 | #if _LIBCPP_STD_VER > 20 | |
| 916 | basic_string& operator=(nullptr_t) = delete; | |
| 917 | #endif | |
| 914 | 918 | basic_string& operator=(value_type __c); |
| 915 | 919 | |
| 916 | 920 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| ... | ... | @@ -939,7 +943,7 @@ public: |
| 939 | 943 | _LIBCPP_INLINE_VISIBILITY |
| 940 | 944 | const_iterator end() const _NOEXCEPT |
| 941 | 945 | {return const_iterator(__get_pointer() + size());} |
| 942 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 946 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 943 | 947 | _LIBCPP_INLINE_VISIBILITY |
| 944 | 948 | reverse_iterator rbegin() _NOEXCEPT |
| 945 | 949 | {return reverse_iterator(end());} |
| ... | ... | @@ -1010,7 +1014,7 @@ public: |
| 1010 | 1014 | _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(value_type __c) {push_back(__c); return *this;} |
| 1011 | 1015 | #ifndef _LIBCPP_CXX03_LANG |
| 1012 | 1016 | _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(initializer_list<value_type> __il) {return append(__il);} |
| 1013 | #endif // _LIBCPP_CXX03_LANG | |
| 1017 | #endif // _LIBCPP_CXX03_LANG | |
| 1014 | 1018 | |
| 1015 | 1019 | _LIBCPP_INLINE_VISIBILITY |
| 1016 | 1020 | basic_string& append(const basic_string& __str); |
| ... | ... | @@ -1041,20 +1045,16 @@ public: |
| 1041 | 1045 | _LIBCPP_INLINE_VISIBILITY |
| 1042 | 1046 | void __append_default_init(size_type __n); |
| 1043 | 1047 | |
| 1044 | template <class _ForwardIterator> | |
| 1045 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS | |
| 1046 | basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator); | |
| 1047 | 1048 | template<class _InputIterator> |
| 1048 | 1049 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| 1049 | 1050 | _EnableIf |
| 1050 | 1051 | < |
| 1051 | __is_exactly_cpp17_input_iterator<_InputIterator>::value | |
| 1052 | || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, | |
| 1052 | __is_exactly_cpp17_input_iterator<_InputIterator>::value, | |
| 1053 | 1053 | basic_string& |
| 1054 | 1054 | > |
| 1055 | 1055 | _LIBCPP_INLINE_VISIBILITY |
| 1056 | 1056 | append(_InputIterator __first, _InputIterator __last) { |
| 1057 | const basic_string __temp (__first, __last, __alloc()); | |
| 1057 | const basic_string __temp(__first, __last, __alloc()); | |
| 1058 | 1058 | append(__temp.data(), __temp.size()); |
| 1059 | 1059 | return *this; |
| 1060 | 1060 | } |
| ... | ... | @@ -1062,19 +1062,16 @@ public: |
| 1062 | 1062 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| 1063 | 1063 | _EnableIf |
| 1064 | 1064 | < |
| 1065 | __is_cpp17_forward_iterator<_ForwardIterator>::value | |
| 1066 | && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, | |
| 1065 | __is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 1067 | 1066 | basic_string& |
| 1068 | 1067 | > |
| 1069 | 1068 | _LIBCPP_INLINE_VISIBILITY |
| 1070 | append(_ForwardIterator __first, _ForwardIterator __last) { | |
| 1071 | return __append_forward_unsafe(__first, __last); | |
| 1072 | } | |
| 1069 | append(_ForwardIterator __first, _ForwardIterator __last); | |
| 1073 | 1070 | |
| 1074 | 1071 | #ifndef _LIBCPP_CXX03_LANG |
| 1075 | 1072 | _LIBCPP_INLINE_VISIBILITY |
| 1076 | 1073 | basic_string& append(initializer_list<value_type> __il) {return append(__il.begin(), __il.size());} |
| 1077 | #endif // _LIBCPP_CXX03_LANG | |
| 1074 | #endif // _LIBCPP_CXX03_LANG | |
| 1078 | 1075 | |
| 1079 | 1076 | void push_back(value_type __c); |
| 1080 | 1077 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1117,8 +1114,7 @@ public: |
| 1117 | 1114 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| 1118 | 1115 | _EnableIf |
| 1119 | 1116 | < |
| 1120 | __is_exactly_cpp17_input_iterator<_InputIterator>::value | |
| 1121 | || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, | |
| 1117 | __is_exactly_cpp17_input_iterator<_InputIterator>::value, | |
| 1122 | 1118 | basic_string& |
| 1123 | 1119 | > |
| 1124 | 1120 | assign(_InputIterator __first, _InputIterator __last); |
| ... | ... | @@ -1126,15 +1122,14 @@ public: |
| 1126 | 1122 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| 1127 | 1123 | _EnableIf |
| 1128 | 1124 | < |
| 1129 | __is_cpp17_forward_iterator<_ForwardIterator>::value | |
| 1130 | && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, | |
| 1125 | __is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 1131 | 1126 | basic_string& |
| 1132 | 1127 | > |
| 1133 | 1128 | assign(_ForwardIterator __first, _ForwardIterator __last); |
| 1134 | 1129 | #ifndef _LIBCPP_CXX03_LANG |
| 1135 | 1130 | _LIBCPP_INLINE_VISIBILITY |
| 1136 | 1131 | basic_string& assign(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());} |
| 1137 | #endif // _LIBCPP_CXX03_LANG | |
| 1132 | #endif // _LIBCPP_CXX03_LANG | |
| 1138 | 1133 | |
| 1139 | 1134 | _LIBCPP_INLINE_VISIBILITY |
| 1140 | 1135 | basic_string& insert(size_type __pos1, const basic_string& __str); |
| ... | ... | @@ -1168,8 +1163,7 @@ public: |
| 1168 | 1163 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| 1169 | 1164 | _EnableIf |
| 1170 | 1165 | < |
| 1171 | __is_exactly_cpp17_input_iterator<_InputIterator>::value | |
| 1172 | || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, | |
| 1166 | __is_exactly_cpp17_input_iterator<_InputIterator>::value, | |
| 1173 | 1167 | iterator |
| 1174 | 1168 | > |
| 1175 | 1169 | insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); |
| ... | ... | @@ -1177,8 +1171,7 @@ public: |
| 1177 | 1171 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| 1178 | 1172 | _EnableIf |
| 1179 | 1173 | < |
| 1180 | __is_cpp17_forward_iterator<_ForwardIterator>::value | |
| 1181 | && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, | |
| 1174 | __is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 1182 | 1175 | iterator |
| 1183 | 1176 | > |
| 1184 | 1177 | insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); |
| ... | ... | @@ -1186,7 +1179,7 @@ public: |
| 1186 | 1179 | _LIBCPP_INLINE_VISIBILITY |
| 1187 | 1180 | iterator insert(const_iterator __pos, initializer_list<value_type> __il) |
| 1188 | 1181 | {return insert(__pos, __il.begin(), __il.end());} |
| 1189 | #endif // _LIBCPP_CXX03_LANG | |
| 1182 | #endif // _LIBCPP_CXX03_LANG | |
| 1190 | 1183 | |
| 1191 | 1184 | basic_string& erase(size_type __pos = 0, size_type __n = npos); |
| 1192 | 1185 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1247,7 +1240,7 @@ public: |
| 1247 | 1240 | _LIBCPP_INLINE_VISIBILITY |
| 1248 | 1241 | basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<value_type> __il) |
| 1249 | 1242 | {return replace(__i1, __i2, __il.begin(), __il.end());} |
| 1250 | #endif // _LIBCPP_CXX03_LANG | |
| 1243 | #endif // _LIBCPP_CXX03_LANG | |
| 1251 | 1244 | |
| 1252 | 1245 | size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const; |
| 1253 | 1246 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1284,7 +1277,7 @@ public: |
| 1284 | 1277 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 1285 | 1278 | size_type |
| 1286 | 1279 | > |
| 1287 | find(const _Tp& __t, size_type __pos = 0) const; | |
| 1280 | find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; | |
| 1288 | 1281 | size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; |
| 1289 | 1282 | _LIBCPP_INLINE_VISIBILITY |
| 1290 | 1283 | size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; |
| ... | ... | @@ -1300,7 +1293,7 @@ public: |
| 1300 | 1293 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 1301 | 1294 | size_type |
| 1302 | 1295 | > |
| 1303 | rfind(const _Tp& __t, size_type __pos = npos) const; | |
| 1296 | rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; | |
| 1304 | 1297 | size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; |
| 1305 | 1298 | _LIBCPP_INLINE_VISIBILITY |
| 1306 | 1299 | size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; |
| ... | ... | @@ -1316,7 +1309,7 @@ public: |
| 1316 | 1309 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 1317 | 1310 | size_type |
| 1318 | 1311 | > |
| 1319 | find_first_of(const _Tp& __t, size_type __pos = 0) const; | |
| 1312 | find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; | |
| 1320 | 1313 | size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; |
| 1321 | 1314 | _LIBCPP_INLINE_VISIBILITY |
| 1322 | 1315 | size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; |
| ... | ... | @@ -1333,7 +1326,7 @@ public: |
| 1333 | 1326 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 1334 | 1327 | size_type |
| 1335 | 1328 | > |
| 1336 | find_last_of(const _Tp& __t, size_type __pos = npos) const; | |
| 1329 | find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; | |
| 1337 | 1330 | size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; |
| 1338 | 1331 | _LIBCPP_INLINE_VISIBILITY |
| 1339 | 1332 | size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; |
| ... | ... | @@ -1350,7 +1343,7 @@ public: |
| 1350 | 1343 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 1351 | 1344 | size_type |
| 1352 | 1345 | > |
| 1353 | find_first_not_of(const _Tp &__t, size_type __pos = 0) const; | |
| 1346 | find_first_not_of(const _Tp &__t, size_type __pos = 0) const _NOEXCEPT; | |
| 1354 | 1347 | size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; |
| 1355 | 1348 | _LIBCPP_INLINE_VISIBILITY |
| 1356 | 1349 | size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; |
| ... | ... | @@ -1367,7 +1360,7 @@ public: |
| 1367 | 1360 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 1368 | 1361 | size_type |
| 1369 | 1362 | > |
| 1370 | find_last_not_of(const _Tp& __t, size_type __pos = npos) const; | |
| 1363 | find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; | |
| 1371 | 1364 | size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; |
| 1372 | 1365 | _LIBCPP_INLINE_VISIBILITY |
| 1373 | 1366 | size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; |
| ... | ... | @@ -1384,7 +1377,7 @@ public: |
| 1384 | 1377 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 1385 | 1378 | int |
| 1386 | 1379 | > |
| 1387 | compare(const _Tp &__t) const; | |
| 1380 | compare(const _Tp &__t) const _NOEXCEPT; | |
| 1388 | 1381 | |
| 1389 | 1382 | template <class _Tp> |
| 1390 | 1383 | _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS |
| ... | ... | @@ -1468,7 +1461,7 @@ public: |
| 1468 | 1461 | bool __addable(const const_iterator* __i, ptrdiff_t __n) const; |
| 1469 | 1462 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; |
| 1470 | 1463 | |
| 1471 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1464 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1472 | 1465 | |
| 1473 | 1466 | private: |
| 1474 | 1467 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1514,7 +1507,7 @@ private: |
| 1514 | 1507 | {return __r_.first().__s.__size_ >> 1;} |
| 1515 | 1508 | # endif |
| 1516 | 1509 | |
| 1517 | #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT | |
| 1510 | #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT | |
| 1518 | 1511 | |
| 1519 | 1512 | _LIBCPP_INLINE_VISIBILITY |
| 1520 | 1513 | void __set_long_size(size_type __s) _NOEXCEPT |
| ... | ... | @@ -1714,6 +1707,13 @@ private: |
| 1714 | 1707 | _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators(); |
| 1715 | 1708 | _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(size_type); |
| 1716 | 1709 | |
| 1710 | template<class _Tp> | |
| 1711 | _LIBCPP_INLINE_VISIBILITY | |
| 1712 | bool __addr_in_range(_Tp&& __t) const { | |
| 1713 | const volatile void *__p = _VSTD::addressof(__t); | |
| 1714 | return data() <= __p && __p <= data() + size(); | |
| 1715 | } | |
| 1716 | ||
| 1717 | 1717 | friend basic_string operator+<>(const basic_string&, const basic_string&); |
| 1718 | 1718 | friend basic_string operator+<>(const value_type*, const basic_string&); |
| 1719 | 1719 | friend basic_string operator+<>(value_type, const basic_string&); |
| ... | ... | @@ -1734,7 +1734,7 @@ _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE, wchar_t) |
| 1734 | 1734 | |
| 1735 | 1735 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 1736 | 1736 | template<class _InputIterator, |
| 1737 | class _CharT = typename iterator_traits<_InputIterator>::value_type, | |
| 1737 | class _CharT = __iter_value_type<_InputIterator>, | |
| 1738 | 1738 | class _Allocator = allocator<_CharT>, |
| 1739 | 1739 | class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value>, |
| 1740 | 1740 | class = _EnableIf<__is_allocator<_Allocator>::value> |
| ... | ... | @@ -1773,11 +1773,7 @@ basic_string<_CharT, _Traits, _Allocator>::__invalidate_all_iterators() |
| 1773 | 1773 | template <class _CharT, class _Traits, class _Allocator> |
| 1774 | 1774 | inline |
| 1775 | 1775 | void |
| 1776 | basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type | |
| 1777 | #if _LIBCPP_DEBUG_LEVEL == 2 | |
| 1778 | __pos | |
| 1779 | #endif | |
| 1780 | ) | |
| 1776 | basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type __pos) | |
| 1781 | 1777 | { |
| 1782 | 1778 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| 1783 | 1779 | __c_node* __c = __get_db()->__find_c_and_lock(this); |
| ... | ... | @@ -1797,7 +1793,9 @@ basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type |
| 1797 | 1793 | } |
| 1798 | 1794 | __get_db()->unlock(); |
| 1799 | 1795 | } |
| 1800 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1796 | #else | |
| 1797 | (void)__pos; | |
| 1798 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1801 | 1799 | } |
| 1802 | 1800 | |
| 1803 | 1801 | template <class _CharT, class _Traits, class _Allocator> |
| ... | ... | @@ -2001,7 +1999,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, co |
| 2001 | 1999 | #endif |
| 2002 | 2000 | } |
| 2003 | 2001 | |
| 2004 | #endif // _LIBCPP_CXX03_LANG | |
| 2002 | #endif // _LIBCPP_CXX03_LANG | |
| 2005 | 2003 | |
| 2006 | 2004 | template <class _CharT, class _Traits, class _Allocator> |
| 2007 | 2005 | void |
| ... | ... | @@ -2129,7 +2127,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _Input |
| 2129 | 2127 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2130 | 2128 | try |
| 2131 | 2129 | { |
| 2132 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2130 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2133 | 2131 | for (; __first != __last; ++__first) |
| 2134 | 2132 | push_back(*__first); |
| 2135 | 2133 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2140,7 +2138,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _Input |
| 2140 | 2138 | __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); |
| 2141 | 2139 | throw; |
| 2142 | 2140 | } |
| 2143 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2141 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2144 | 2142 | } |
| 2145 | 2143 | |
| 2146 | 2144 | template <class _CharT, class _Traits, class _Allocator> |
| ... | ... | @@ -2168,9 +2166,23 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _For |
| 2168 | 2166 | __set_long_cap(__cap+1); |
| 2169 | 2167 | __set_long_size(__sz); |
| 2170 | 2168 | } |
| 2169 | ||
| 2170 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2171 | try | |
| 2172 | { | |
| 2173 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2171 | 2174 | for (; __first != __last; ++__first, (void) ++__p) |
| 2172 | 2175 | traits_type::assign(*__p, *__first); |
| 2173 | 2176 | traits_type::assign(*__p, value_type()); |
| 2177 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 2178 | } | |
| 2179 | catch (...) | |
| 2180 | { | |
| 2181 | if (__is_long()) | |
| 2182 | __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); | |
| 2183 | throw; | |
| 2184 | } | |
| 2185 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2174 | 2186 | } |
| 2175 | 2187 | |
| 2176 | 2188 | template <class _CharT, class _Traits, class _Allocator> |
| ... | ... | @@ -2225,7 +2237,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string( |
| 2225 | 2237 | #endif |
| 2226 | 2238 | } |
| 2227 | 2239 | |
| 2228 | #endif // _LIBCPP_CXX03_LANG | |
| 2240 | #endif // _LIBCPP_CXX03_LANG | |
| 2229 | 2241 | |
| 2230 | 2242 | template <class _CharT, class _Traits, class _Allocator> |
| 2231 | 2243 | basic_string<_CharT, _Traits, _Allocator>::~basic_string() |
| ... | ... | @@ -2357,12 +2369,11 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) |
| 2357 | 2369 | size_type __sz = size(); |
| 2358 | 2370 | __grow_by(__cap, __n - __cap, __sz, 0, __sz); |
| 2359 | 2371 | } |
| 2360 | else | |
| 2361 | __invalidate_iterators_past(__n); | |
| 2362 | 2372 | value_type* __p = _VSTD::__to_address(__get_pointer()); |
| 2363 | 2373 | traits_type::assign(__p, __n, __c); |
| 2364 | 2374 | traits_type::assign(__p[__n], value_type()); |
| 2365 | 2375 | __set_size(__n); |
| 2376 | __invalidate_iterators_past(__n); | |
| 2366 | 2377 | return *this; |
| 2367 | 2378 | } |
| 2368 | 2379 | |
| ... | ... | @@ -2463,8 +2474,7 @@ template <class _CharT, class _Traits, class _Allocator> |
| 2463 | 2474 | template<class _InputIterator> |
| 2464 | 2475 | _EnableIf |
| 2465 | 2476 | < |
| 2466 | __is_exactly_cpp17_input_iterator <_InputIterator>::value | |
| 2467 | || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, | |
| 2477 | __is_exactly_cpp17_input_iterator<_InputIterator>::value, | |
| 2468 | 2478 | basic_string<_CharT, _Traits, _Allocator>& |
| 2469 | 2479 | > |
| 2470 | 2480 | basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) |
| ... | ... | @@ -2478,26 +2488,35 @@ template <class _CharT, class _Traits, class _Allocator> |
| 2478 | 2488 | template<class _ForwardIterator> |
| 2479 | 2489 | _EnableIf |
| 2480 | 2490 | < |
| 2481 | __is_cpp17_forward_iterator<_ForwardIterator>::value | |
| 2482 | && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, | |
| 2491 | __is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 2483 | 2492 | basic_string<_CharT, _Traits, _Allocator>& |
| 2484 | 2493 | > |
| 2485 | 2494 | basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) |
| 2486 | 2495 | { |
| 2487 | size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last)); | |
| 2488 | 2496 | size_type __cap = capacity(); |
| 2489 | if (__cap < __n) | |
| 2497 | size_type __n = __string_is_trivial_iterator<_ForwardIterator>::value ? | |
| 2498 | static_cast<size_type>(_VSTD::distance(__first, __last)) : 0; | |
| 2499 | ||
| 2500 | if (__string_is_trivial_iterator<_ForwardIterator>::value && | |
| 2501 | (__cap >= __n || !__addr_in_range(*__first))) | |
| 2490 | 2502 | { |
| 2491 | size_type __sz = size(); | |
| 2492 | __grow_by(__cap, __n - __cap, __sz, 0, __sz); | |
| 2503 | if (__cap < __n) | |
| 2504 | { | |
| 2505 | size_type __sz = size(); | |
| 2506 | __grow_by(__cap, __n - __cap, __sz, 0, __sz); | |
| 2507 | } | |
| 2508 | pointer __p = __get_pointer(); | |
| 2509 | for (; __first != __last; ++__first, ++__p) | |
| 2510 | traits_type::assign(*__p, *__first); | |
| 2511 | traits_type::assign(*__p, value_type()); | |
| 2512 | __set_size(__n); | |
| 2513 | __invalidate_iterators_past(__n); | |
| 2493 | 2514 | } |
| 2494 | 2515 | else |
| 2495 | __invalidate_iterators_past(__n); | |
| 2496 | pointer __p = __get_pointer(); | |
| 2497 | for (; __first != __last; ++__first, ++__p) | |
| 2498 | traits_type::assign(*__p, *__first); | |
| 2499 | traits_type::assign(*__p, value_type()); | |
| 2500 | __set_size(__n); | |
| 2516 | { | |
| 2517 | const basic_string __temp(__first, __last, __alloc()); | |
| 2518 | assign(__temp.data(), __temp.size()); | |
| 2519 | } | |
| 2501 | 2520 | return *this; |
| 2502 | 2521 | } |
| 2503 | 2522 | |
| ... | ... | @@ -2644,39 +2663,23 @@ basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) |
| 2644 | 2663 | traits_type::assign(*++__p, value_type()); |
| 2645 | 2664 | } |
| 2646 | 2665 | |
| 2647 | template <class _Tp> | |
| 2648 | bool __ptr_in_range (const _Tp* __p, const _Tp* __first, const _Tp* __last) | |
| 2649 | { | |
| 2650 | return __first <= __p && __p < __last; | |
| 2651 | } | |
| 2652 | ||
| 2653 | template <class _Tp1, class _Tp2> | |
| 2654 | bool __ptr_in_range (const _Tp1*, const _Tp2*, const _Tp2*) | |
| 2655 | { | |
| 2656 | return false; | |
| 2657 | } | |
| 2658 | ||
| 2659 | 2666 | template <class _CharT, class _Traits, class _Allocator> |
| 2660 | 2667 | template<class _ForwardIterator> |
| 2661 | basic_string<_CharT, _Traits, _Allocator>& | |
| 2662 | basic_string<_CharT, _Traits, _Allocator>::__append_forward_unsafe( | |
| 2668 | _EnableIf | |
| 2669 | < | |
| 2670 | __is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 2671 | basic_string<_CharT, _Traits, _Allocator>& | |
| 2672 | > | |
| 2673 | basic_string<_CharT, _Traits, _Allocator>::append( | |
| 2663 | 2674 | _ForwardIterator __first, _ForwardIterator __last) |
| 2664 | 2675 | { |
| 2665 | static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 2666 | "function requires a ForwardIterator"); | |
| 2667 | 2676 | size_type __sz = size(); |
| 2668 | 2677 | size_type __cap = capacity(); |
| 2669 | 2678 | size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last)); |
| 2670 | 2679 | if (__n) |
| 2671 | 2680 | { |
| 2672 | typedef typename iterator_traits<_ForwardIterator>::reference _CharRef; | |
| 2673 | _CharRef __tmp_ref = *__first; | |
| 2674 | if (__ptr_in_range(_VSTD::addressof(__tmp_ref), data(), data() + size())) | |
| 2675 | { | |
| 2676 | const basic_string __temp (__first, __last, __alloc()); | |
| 2677 | append(__temp.data(), __temp.size()); | |
| 2678 | } | |
| 2679 | else | |
| 2681 | if (__string_is_trivial_iterator<_ForwardIterator>::value && | |
| 2682 | !__addr_in_range(*__first)) | |
| 2680 | 2683 | { |
| 2681 | 2684 | if (__cap - __sz < __n) |
| 2682 | 2685 | __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); |
| ... | ... | @@ -2686,6 +2689,11 @@ basic_string<_CharT, _Traits, _Allocator>::__append_forward_unsafe( |
| 2686 | 2689 | traits_type::assign(*__p, value_type()); |
| 2687 | 2690 | __set_size(__sz + __n); |
| 2688 | 2691 | } |
| 2692 | else | |
| 2693 | { | |
| 2694 | const basic_string __temp(__first, __last, __alloc()); | |
| 2695 | append(__temp.data(), __temp.size()); | |
| 2696 | } | |
| 2689 | 2697 | } |
| 2690 | 2698 | return *this; |
| 2691 | 2699 | } |
| ... | ... | @@ -2801,8 +2809,7 @@ template <class _CharT, class _Traits, class _Allocator> |
| 2801 | 2809 | template<class _InputIterator> |
| 2802 | 2810 | _EnableIf |
| 2803 | 2811 | < |
| 2804 | __is_exactly_cpp17_input_iterator<_InputIterator>::value | |
| 2805 | || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, | |
| 2812 | __is_exactly_cpp17_input_iterator<_InputIterator>::value, | |
| 2806 | 2813 | typename basic_string<_CharT, _Traits, _Allocator>::iterator |
| 2807 | 2814 | > |
| 2808 | 2815 | basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) |
| ... | ... | @@ -2820,8 +2827,7 @@ template <class _CharT, class _Traits, class _Allocator> |
| 2820 | 2827 | template<class _ForwardIterator> |
| 2821 | 2828 | _EnableIf |
| 2822 | 2829 | < |
| 2823 | __is_cpp17_forward_iterator<_ForwardIterator>::value | |
| 2824 | && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, | |
| 2830 | __is_cpp17_forward_iterator<_ForwardIterator>::value, | |
| 2825 | 2831 | typename basic_string<_CharT, _Traits, _Allocator>::iterator |
| 2826 | 2832 | > |
| 2827 | 2833 | basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) |
| ... | ... | @@ -2835,34 +2841,35 @@ basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _Forward |
| 2835 | 2841 | size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last)); |
| 2836 | 2842 | if (__n) |
| 2837 | 2843 | { |
| 2838 | typedef typename iterator_traits<_ForwardIterator>::reference _CharRef; | |
| 2839 | _CharRef __tmp_char = *__first; | |
| 2840 | if (__ptr_in_range(_VSTD::addressof(__tmp_char), data(), data() + size())) | |
| 2844 | if (__string_is_trivial_iterator<_ForwardIterator>::value && | |
| 2845 | !__addr_in_range(*__first)) | |
| 2841 | 2846 | { |
| 2842 | const basic_string __temp(__first, __last, __alloc()); | |
| 2843 | return insert(__pos, __temp.data(), __temp.data() + __temp.size()); | |
| 2844 | } | |
| 2845 | ||
| 2846 | size_type __sz = size(); | |
| 2847 | size_type __cap = capacity(); | |
| 2848 | value_type* __p; | |
| 2849 | if (__cap - __sz >= __n) | |
| 2850 | { | |
| 2851 | __p = _VSTD::__to_address(__get_pointer()); | |
| 2852 | size_type __n_move = __sz - __ip; | |
| 2853 | if (__n_move != 0) | |
| 2854 | traits_type::move(__p + __ip + __n, __p + __ip, __n_move); | |
| 2847 | size_type __sz = size(); | |
| 2848 | size_type __cap = capacity(); | |
| 2849 | value_type* __p; | |
| 2850 | if (__cap - __sz >= __n) | |
| 2851 | { | |
| 2852 | __p = _VSTD::__to_address(__get_pointer()); | |
| 2853 | size_type __n_move = __sz - __ip; | |
| 2854 | if (__n_move != 0) | |
| 2855 | traits_type::move(__p + __ip + __n, __p + __ip, __n_move); | |
| 2856 | } | |
| 2857 | else | |
| 2858 | { | |
| 2859 | __grow_by(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); | |
| 2860 | __p = _VSTD::__to_address(__get_long_pointer()); | |
| 2861 | } | |
| 2862 | __sz += __n; | |
| 2863 | __set_size(__sz); | |
| 2864 | traits_type::assign(__p[__sz], value_type()); | |
| 2865 | for (__p += __ip; __first != __last; ++__p, ++__first) | |
| 2866 | traits_type::assign(*__p, *__first); | |
| 2855 | 2867 | } |
| 2856 | 2868 | else |
| 2857 | 2869 | { |
| 2858 | __grow_by(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); | |
| 2859 | __p = _VSTD::__to_address(__get_long_pointer()); | |
| 2870 | const basic_string __temp(__first, __last, __alloc()); | |
| 2871 | return insert(__pos, __temp.data(), __temp.data() + __temp.size()); | |
| 2860 | 2872 | } |
| 2861 | __sz += __n; | |
| 2862 | __set_size(__sz); | |
| 2863 | traits_type::assign(__p[__sz], value_type()); | |
| 2864 | for (__p += __ip; __first != __last; ++__p, ++__first) | |
| 2865 | traits_type::assign(*__p, *__first); | |
| 2866 | 2873 | } |
| 2867 | 2874 | return begin() + __ip; |
| 2868 | 2875 | } |
| ... | ... | @@ -3353,7 +3360,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target |
| 3353 | 3360 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 3354 | 3361 | try |
| 3355 | 3362 | { |
| 3356 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3363 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3357 | 3364 | __new_data = __alloc_traits::allocate(__alloc(), __target_capacity+1); |
| 3358 | 3365 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 3359 | 3366 | } |
| ... | ... | @@ -3364,7 +3371,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target |
| 3364 | 3371 | #else // _LIBCPP_NO_EXCEPTIONS |
| 3365 | 3372 | if (__new_data == nullptr) |
| 3366 | 3373 | return; |
| 3367 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3374 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3368 | 3375 | } |
| 3369 | 3376 | __now_long = true; |
| 3370 | 3377 | __was_long = __is_long(); |
| ... | ... | @@ -3543,7 +3550,7 @@ _EnableIf |
| 3543 | 3550 | typename basic_string<_CharT, _Traits, _Allocator>::size_type |
| 3544 | 3551 | > |
| 3545 | 3552 | basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t, |
| 3546 | size_type __pos) const | |
| 3553 | size_type __pos) const _NOEXCEPT | |
| 3547 | 3554 | { |
| 3548 | 3555 | __self_view __sv = __t; |
| 3549 | 3556 | return __str_find<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -3601,7 +3608,7 @@ _EnableIf |
| 3601 | 3608 | typename basic_string<_CharT, _Traits, _Allocator>::size_type |
| 3602 | 3609 | > |
| 3603 | 3610 | basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, |
| 3604 | size_type __pos) const | |
| 3611 | size_type __pos) const _NOEXCEPT | |
| 3605 | 3612 | { |
| 3606 | 3613 | __self_view __sv = __t; |
| 3607 | 3614 | return __str_rfind<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -3659,7 +3666,7 @@ _EnableIf |
| 3659 | 3666 | typename basic_string<_CharT, _Traits, _Allocator>::size_type |
| 3660 | 3667 | > |
| 3661 | 3668 | basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, |
| 3662 | size_type __pos) const | |
| 3669 | size_type __pos) const _NOEXCEPT | |
| 3663 | 3670 | { |
| 3664 | 3671 | __self_view __sv = __t; |
| 3665 | 3672 | return __str_find_first_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -3717,7 +3724,7 @@ _EnableIf |
| 3717 | 3724 | typename basic_string<_CharT, _Traits, _Allocator>::size_type |
| 3718 | 3725 | > |
| 3719 | 3726 | basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, |
| 3720 | size_type __pos) const | |
| 3727 | size_type __pos) const _NOEXCEPT | |
| 3721 | 3728 | { |
| 3722 | 3729 | __self_view __sv = __t; |
| 3723 | 3730 | return __str_find_last_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -3775,7 +3782,7 @@ _EnableIf |
| 3775 | 3782 | typename basic_string<_CharT, _Traits, _Allocator>::size_type |
| 3776 | 3783 | > |
| 3777 | 3784 | basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, |
| 3778 | size_type __pos) const | |
| 3785 | size_type __pos) const _NOEXCEPT | |
| 3779 | 3786 | { |
| 3780 | 3787 | __self_view __sv = __t; |
| 3781 | 3788 | return __str_find_first_not_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -3834,7 +3841,7 @@ _EnableIf |
| 3834 | 3841 | typename basic_string<_CharT, _Traits, _Allocator>::size_type |
| 3835 | 3842 | > |
| 3836 | 3843 | basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, |
| 3837 | size_type __pos) const | |
| 3844 | size_type __pos) const _NOEXCEPT | |
| 3838 | 3845 | { |
| 3839 | 3846 | __self_view __sv = __t; |
| 3840 | 3847 | return __str_find_last_not_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -3871,7 +3878,7 @@ _EnableIf |
| 3871 | 3878 | __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, |
| 3872 | 3879 | int |
| 3873 | 3880 | > |
| 3874 | basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const | |
| 3881 | basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT | |
| 3875 | 3882 | { |
| 3876 | 3883 | __self_view __sv = __t; |
| 3877 | 3884 | size_t __lhs_sz = size(); |
| ... | ... | @@ -4349,7 +4356,7 @@ operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs) |
| 4349 | 4356 | return _VSTD::move(__lhs); |
| 4350 | 4357 | } |
| 4351 | 4358 | |
| 4352 | #endif // _LIBCPP_CXX03_LANG | |
| 4359 | #endif // _LIBCPP_CXX03_LANG | |
| 4353 | 4360 | |
| 4354 | 4361 | // swap |
| 4355 | 4362 | |
| ... | ... | @@ -4404,7 +4411,7 @@ _LIBCPP_FUNC_VIS wstring to_wstring(double __val); |
| 4404 | 4411 | _LIBCPP_FUNC_VIS wstring to_wstring(long double __val); |
| 4405 | 4412 | |
| 4406 | 4413 | template<class _CharT, class _Traits, class _Allocator> |
| 4407 | _LIBCPP_FUNC_VIS | |
| 4414 | _LIBCPP_TEMPLATE_DATA_VIS | |
| 4408 | 4415 | const typename basic_string<_CharT, _Traits, _Allocator>::size_type |
| 4409 | 4416 | basic_string<_CharT, _Traits, _Allocator>::npos; |
| 4410 | 4417 | |
| ... | ... | @@ -4441,8 +4448,6 @@ basic_istream<_CharT, _Traits>& |
| 4441 | 4448 | getline(basic_istream<_CharT, _Traits>& __is, |
| 4442 | 4449 | basic_string<_CharT, _Traits, _Allocator>& __str); |
| 4443 | 4450 | |
| 4444 | #ifndef _LIBCPP_CXX03_LANG | |
| 4445 | ||
| 4446 | 4451 | template<class _CharT, class _Traits, class _Allocator> |
| 4447 | 4452 | inline _LIBCPP_INLINE_VISIBILITY |
| 4448 | 4453 | basic_istream<_CharT, _Traits>& |
| ... | ... | @@ -4455,8 +4460,6 @@ basic_istream<_CharT, _Traits>& |
| 4455 | 4460 | getline(basic_istream<_CharT, _Traits>&& __is, |
| 4456 | 4461 | basic_string<_CharT, _Traits, _Allocator>& __str); |
| 4457 | 4462 | |
| 4458 | #endif // _LIBCPP_CXX03_LANG | |
| 4459 | ||
| 4460 | 4463 | #if _LIBCPP_STD_VER > 17 |
| 4461 | 4464 | template <class _CharT, class _Traits, class _Allocator, class _Up> |
| 4462 | 4465 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -4513,7 +4516,7 @@ basic_string<_CharT, _Traits, _Allocator>::__subscriptable(const const_iterator* |
| 4513 | 4516 | return this->data() <= __p && __p < this->data() + this->size(); |
| 4514 | 4517 | } |
| 4515 | 4518 | |
| 4516 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 4519 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 4517 | 4520 | |
| 4518 | 4521 | #if _LIBCPP_STD_VER > 11 |
| 4519 | 4522 | // Literal suffixes for basic_string [basic.string.literals] |
| ... | ... | @@ -4533,7 +4536,7 @@ inline namespace literals |
| 4533 | 4536 | return basic_string<wchar_t> (__str, __len); |
| 4534 | 4537 | } |
| 4535 | 4538 | |
| 4536 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 4539 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 4537 | 4540 | inline _LIBCPP_INLINE_VISIBILITY |
| 4538 | 4541 | basic_string<char8_t> operator "" s(const char8_t *__str, size_t __len) _NOEXCEPT |
| 4539 | 4542 | { |
| ... | ... | @@ -4560,4 +4563,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 4560 | 4563 | |
| 4561 | 4564 | _LIBCPP_POP_MACROS |
| 4562 | 4565 | |
| 4563 | #endif // _LIBCPP_STRING | |
| 4566 | #endif // _LIBCPP_STRING |
lib/libcxx/include/string.h+1-1| ... | ... | @@ -106,4 +106,4 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD |
| 106 | 106 | } |
| 107 | 107 | #endif |
| 108 | 108 | |
| 109 | #endif // _LIBCPP_STRING_H | |
| 109 | #endif // _LIBCPP_STRING_H |
lib/libcxx/include/string_view+55-31| ... | ... | @@ -19,6 +19,12 @@ namespace std { |
| 19 | 19 | template<class charT, class traits = char_traits<charT>> |
| 20 | 20 | class basic_string_view; |
| 21 | 21 | |
| 22 | template<class charT, class traits> | |
| 23 | inline constexpr bool ranges::enable_view<basic_string_view<charT, traits>> = true; | |
| 24 | ||
| 25 | template<class charT, class traits> | |
| 26 | inline constexpr bool ranges::enable_borrowed_range<basic_string_view<charT, traits>> = true; // C++20 | |
| 27 | ||
| 22 | 28 | // 7.9, basic_string_view non-member comparison functions |
| 23 | 29 | template<class charT, class traits> |
| 24 | 30 | constexpr bool operator==(basic_string_view<charT, traits> x, |
| ... | ... | @@ -48,6 +54,7 @@ namespace std { |
| 48 | 54 | |
| 49 | 55 | // basic_string_view typedef names |
| 50 | 56 | typedef basic_string_view<char> string_view; |
| 57 | typedef basic_string_view<char8_t> u8string_view; // C++20 | |
| 51 | 58 | typedef basic_string_view<char16_t> u16string_view; |
| 52 | 59 | typedef basic_string_view<char32_t> u32string_view; |
| 53 | 60 | typedef basic_string_view<wchar_t> wstring_view; |
| ... | ... | @@ -76,6 +83,7 @@ namespace std { |
| 76 | 83 | basic_string_view& operator=(const basic_string_view&) noexcept = default; |
| 77 | 84 | template<class Allocator> |
| 78 | 85 | constexpr basic_string_view(const charT* str); |
| 86 | basic_string_view(nullptr_t) = delete; // C++2b | |
| 79 | 87 | constexpr basic_string_view(const charT* str, size_type len); |
| 80 | 88 | |
| 81 | 89 | // 7.4, basic_string_view iterator support |
| ... | ... | @@ -106,7 +114,7 @@ namespace std { |
| 106 | 114 | constexpr void remove_suffix(size_type n); |
| 107 | 115 | constexpr void swap(basic_string_view& s) noexcept; |
| 108 | 116 | |
| 109 | size_type copy(charT* s, size_type n, size_type pos = 0) const; | |
| 117 | size_type copy(charT* s, size_type n, size_type pos = 0) const; // constexpr in C++20 | |
| 110 | 118 | |
| 111 | 119 | constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; |
| 112 | 120 | constexpr int compare(basic_string_view s) const noexcept; |
| ... | ... | @@ -119,28 +127,28 @@ namespace std { |
| 119 | 127 | const charT* s, size_type n2) const; |
| 120 | 128 | constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept; |
| 121 | 129 | constexpr size_type find(charT c, size_type pos = 0) const noexcept; |
| 122 | constexpr size_type find(const charT* s, size_type pos, size_type n) const; | |
| 123 | constexpr size_type find(const charT* s, size_type pos = 0) const; | |
| 130 | constexpr size_type find(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension | |
| 131 | constexpr size_type find(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension | |
| 124 | 132 | constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept; |
| 125 | 133 | constexpr size_type rfind(charT c, size_type pos = npos) const noexcept; |
| 126 | constexpr size_type rfind(const charT* s, size_type pos, size_type n) const; | |
| 127 | constexpr size_type rfind(const charT* s, size_type pos = npos) const; | |
| 134 | constexpr size_type rfind(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension | |
| 135 | constexpr size_type rfind(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension | |
| 128 | 136 | constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept; |
| 129 | 137 | constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept; |
| 130 | constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const; | |
| 131 | constexpr size_type find_first_of(const charT* s, size_type pos = 0) const; | |
| 138 | constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension | |
| 139 | constexpr size_type find_first_of(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension | |
| 132 | 140 | constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept; |
| 133 | 141 | constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept; |
| 134 | constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const; | |
| 135 | constexpr size_type find_last_of(const charT* s, size_type pos = npos) const; | |
| 142 | constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension | |
| 143 | constexpr size_type find_last_of(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension | |
| 136 | 144 | constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept; |
| 137 | 145 | constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept; |
| 138 | constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const; | |
| 139 | constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const; | |
| 146 | constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension | |
| 147 | constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const noexcept; // noexcept as an extension | |
| 140 | 148 | constexpr size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept; |
| 141 | 149 | constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept; |
| 142 | constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const; | |
| 143 | constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; | |
| 150 | constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const noexcept; // noexcept as an extension | |
| 151 | constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const noexcept; // noexcept as an extension | |
| 144 | 152 | |
| 145 | 153 | constexpr bool starts_with(basic_string_view s) const noexcept; // C++20 |
| 146 | 154 | constexpr bool starts_with(charT c) const noexcept; // C++20 |
| ... | ... | @@ -161,12 +169,14 @@ namespace std { |
| 161 | 169 | // 7.11, Hash support |
| 162 | 170 | template <class T> struct hash; |
| 163 | 171 | template <> struct hash<string_view>; |
| 172 | template <> struct hash<u8string_view>; // C++20 | |
| 164 | 173 | template <> struct hash<u16string_view>; |
| 165 | 174 | template <> struct hash<u32string_view>; |
| 166 | 175 | template <> struct hash<wstring_view>; |
| 167 | 176 | |
| 168 | 177 | constexpr basic_string_view<char> operator "" sv( const char *str, size_t len ) noexcept; |
| 169 | 178 | constexpr basic_string_view<wchar_t> operator "" sv( const wchar_t *str, size_t len ) noexcept; |
| 179 | constexpr basic_string_view<char8_t> operator "" sv( const char8_t *str, size_t len ) noexcept; // C++20 | |
| 170 | 180 | constexpr basic_string_view<char16_t> operator "" sv( const char16_t *str, size_t len ) noexcept; |
| 171 | 181 | constexpr basic_string_view<char32_t> operator "" sv( const char32_t *str, size_t len ) noexcept; |
| 172 | 182 | |
| ... | ... | @@ -176,14 +186,17 @@ namespace std { |
| 176 | 186 | */ |
| 177 | 187 | |
| 178 | 188 | #include <__config> |
| 189 | #include <__debug> | |
| 190 | #include <__ranges/enable_borrowed_range.h> | |
| 191 | #include <__ranges/enable_view.h> | |
| 179 | 192 | #include <__string> |
| 180 | #include <iosfwd> | |
| 181 | 193 | #include <algorithm> |
| 194 | #include <compare> | |
| 195 | #include <iosfwd> | |
| 182 | 196 | #include <iterator> |
| 183 | 197 | #include <limits> |
| 184 | 198 | #include <stdexcept> |
| 185 | 199 | #include <version> |
| 186 | #include <__debug> | |
| 187 | 200 | |
| 188 | 201 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 189 | 202 | #pragma GCC system_header |
| ... | ... | @@ -199,7 +212,7 @@ template<class _CharT, class _Traits = char_traits<_CharT> > |
| 199 | 212 | class _LIBCPP_TEMPLATE_VIS basic_string_view; |
| 200 | 213 | |
| 201 | 214 | typedef basic_string_view<char> string_view; |
| 202 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 215 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 203 | 216 | typedef basic_string_view<char8_t> u8string_view; |
| 204 | 217 | #endif |
| 205 | 218 | typedef basic_string_view<char16_t> u16string_view; |
| ... | ... | @@ -209,7 +222,7 @@ typedef basic_string_view<wchar_t> wstring_view; |
| 209 | 222 | template<class _CharT, class _Traits> |
| 210 | 223 | class |
| 211 | 224 | _LIBCPP_PREFERRED_NAME(string_view) |
| 212 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 225 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 213 | 226 | _LIBCPP_PREFERRED_NAME(u8string_view) |
| 214 | 227 | #endif |
| 215 | 228 | _LIBCPP_PREFERRED_NAME(u16string_view) |
| ... | ... | @@ -261,6 +274,10 @@ public: |
| 261 | 274 | basic_string_view(const _CharT* __s) |
| 262 | 275 | : __data(__s), __size(_VSTD::__char_traits_length_checked<_Traits>(__s)) {} |
| 263 | 276 | |
| 277 | #if _LIBCPP_STD_VER > 20 | |
| 278 | basic_string_view(nullptr_t) = delete; | |
| 279 | #endif | |
| 280 | ||
| 264 | 281 | // [string.view.iterators], iterators |
| 265 | 282 | _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY |
| 266 | 283 | const_iterator begin() const _NOEXCEPT { return cbegin(); } |
| ... | ... | @@ -356,7 +373,7 @@ public: |
| 356 | 373 | __other.__size = __sz; |
| 357 | 374 | } |
| 358 | 375 | |
| 359 | _LIBCPP_INLINE_VISIBILITY | |
| 376 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 360 | 377 | size_type copy(_CharT* __s, size_type __n, size_type __pos = 0) const |
| 361 | 378 | { |
| 362 | 379 | if (__pos > size()) |
| ... | ... | @@ -431,7 +448,7 @@ public: |
| 431 | 448 | } |
| 432 | 449 | |
| 433 | 450 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 434 | size_type find(const _CharT* __s, size_type __pos, size_type __n) const | |
| 451 | size_type find(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT | |
| 435 | 452 | { |
| 436 | 453 | _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find(): received nullptr"); |
| 437 | 454 | return __str_find<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -439,7 +456,7 @@ public: |
| 439 | 456 | } |
| 440 | 457 | |
| 441 | 458 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 442 | size_type find(const _CharT* __s, size_type __pos = 0) const | |
| 459 | size_type find(const _CharT* __s, size_type __pos = 0) const _NOEXCEPT | |
| 443 | 460 | { |
| 444 | 461 | _LIBCPP_ASSERT(__s != nullptr, "string_view::find(): received nullptr"); |
| 445 | 462 | return __str_find<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -463,7 +480,7 @@ public: |
| 463 | 480 | } |
| 464 | 481 | |
| 465 | 482 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 466 | size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const | |
| 483 | size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT | |
| 467 | 484 | { |
| 468 | 485 | _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr"); |
| 469 | 486 | return __str_rfind<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -471,7 +488,7 @@ public: |
| 471 | 488 | } |
| 472 | 489 | |
| 473 | 490 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 474 | size_type rfind(const _CharT* __s, size_type __pos=npos) const | |
| 491 | size_type rfind(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT | |
| 475 | 492 | { |
| 476 | 493 | _LIBCPP_ASSERT(__s != nullptr, "string_view::rfind(): received nullptr"); |
| 477 | 494 | return __str_rfind<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -492,7 +509,7 @@ public: |
| 492 | 509 | { return find(__c, __pos); } |
| 493 | 510 | |
| 494 | 511 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 495 | size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const | |
| 512 | size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT | |
| 496 | 513 | { |
| 497 | 514 | _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr"); |
| 498 | 515 | return __str_find_first_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -500,7 +517,7 @@ public: |
| 500 | 517 | } |
| 501 | 518 | |
| 502 | 519 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 503 | size_type find_first_of(const _CharT* __s, size_type __pos=0) const | |
| 520 | size_type find_first_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT | |
| 504 | 521 | { |
| 505 | 522 | _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_of(): received nullptr"); |
| 506 | 523 | return __str_find_first_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -521,7 +538,7 @@ public: |
| 521 | 538 | { return rfind(__c, __pos); } |
| 522 | 539 | |
| 523 | 540 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 524 | size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const | |
| 541 | size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT | |
| 525 | 542 | { |
| 526 | 543 | _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr"); |
| 527 | 544 | return __str_find_last_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -529,7 +546,7 @@ public: |
| 529 | 546 | } |
| 530 | 547 | |
| 531 | 548 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 532 | size_type find_last_of(const _CharT* __s, size_type __pos=npos) const | |
| 549 | size_type find_last_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT | |
| 533 | 550 | { |
| 534 | 551 | _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_of(): received nullptr"); |
| 535 | 552 | return __str_find_last_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -553,7 +570,7 @@ public: |
| 553 | 570 | } |
| 554 | 571 | |
| 555 | 572 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 556 | size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const | |
| 573 | size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT | |
| 557 | 574 | { |
| 558 | 575 | _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr"); |
| 559 | 576 | return __str_find_first_not_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -561,7 +578,7 @@ public: |
| 561 | 578 | } |
| 562 | 579 | |
| 563 | 580 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 564 | size_type find_first_not_of(const _CharT* __s, size_type __pos=0) const | |
| 581 | size_type find_first_not_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT | |
| 565 | 582 | { |
| 566 | 583 | _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_not_of(): received nullptr"); |
| 567 | 584 | return __str_find_first_not_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -585,7 +602,7 @@ public: |
| 585 | 602 | } |
| 586 | 603 | |
| 587 | 604 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 588 | size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const | |
| 605 | size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT | |
| 589 | 606 | { |
| 590 | 607 | _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr"); |
| 591 | 608 | return __str_find_last_not_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -593,7 +610,7 @@ public: |
| 593 | 610 | } |
| 594 | 611 | |
| 595 | 612 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY |
| 596 | size_type find_last_not_of(const _CharT* __s, size_type __pos=npos) const | |
| 613 | size_type find_last_not_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT | |
| 597 | 614 | { |
| 598 | 615 | _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_not_of(): received nullptr"); |
| 599 | 616 | return __str_find_last_not_of<value_type, size_type, traits_type, npos> |
| ... | ... | @@ -645,6 +662,13 @@ private: |
| 645 | 662 | size_type __size; |
| 646 | 663 | }; |
| 647 | 664 | |
| 665 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) | |
| 666 | template <class _CharT, class _Traits> | |
| 667 | inline constexpr bool ranges::enable_view<basic_string_view<_CharT, _Traits>> = true; | |
| 668 | ||
| 669 | template <class _CharT, class _Traits> | |
| 670 | inline constexpr bool ranges::enable_borrowed_range<basic_string_view<_CharT, _Traits> > = true; | |
| 671 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES) | |
| 648 | 672 | |
| 649 | 673 | // [string.view.comparison] |
| 650 | 674 | // operator == |
| ... | ... | @@ -842,7 +866,7 @@ inline namespace literals |
| 842 | 866 | return basic_string_view<wchar_t> (__str, __len); |
| 843 | 867 | } |
| 844 | 868 | |
| 845 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 869 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 846 | 870 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR |
| 847 | 871 | basic_string_view<char8_t> operator "" sv(const char8_t *__str, size_t __len) _NOEXCEPT |
| 848 | 872 | { |
lib/libcxx/include/strstream+7-7| ... | ... | @@ -130,8 +130,8 @@ private: |
| 130 | 130 | */ |
| 131 | 131 | |
| 132 | 132 | #include <__config> |
| 133 | #include <ostream> | |
| 134 | 133 | #include <istream> |
| 134 | #include <ostream> | |
| 135 | 135 | |
| 136 | 136 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 137 | 137 | #pragma GCC system_header |
| ... | ... | @@ -163,7 +163,7 @@ public: |
| 163 | 163 | strstreambuf(strstreambuf&& __rhs); |
| 164 | 164 | _LIBCPP_INLINE_VISIBILITY |
| 165 | 165 | strstreambuf& operator=(strstreambuf&& __rhs); |
| 166 | #endif // _LIBCPP_CXX03_LANG | |
| 166 | #endif // _LIBCPP_CXX03_LANG | |
| 167 | 167 | |
| 168 | 168 | virtual ~strstreambuf(); |
| 169 | 169 | |
| ... | ... | @@ -233,7 +233,7 @@ strstreambuf::operator=(strstreambuf&& __rhs) |
| 233 | 233 | return *this; |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | #endif // _LIBCPP_CXX03_LANG | |
| 236 | #endif // _LIBCPP_CXX03_LANG | |
| 237 | 237 | |
| 238 | 238 | class _LIBCPP_TYPE_VIS istrstream |
| 239 | 239 | : public istream |
| ... | ... | @@ -268,7 +268,7 @@ public: |
| 268 | 268 | __sb_ = _VSTD::move(__rhs.__sb_); |
| 269 | 269 | return *this; |
| 270 | 270 | } |
| 271 | #endif // _LIBCPP_CXX03_LANG | |
| 271 | #endif // _LIBCPP_CXX03_LANG | |
| 272 | 272 | |
| 273 | 273 | virtual ~istrstream(); |
| 274 | 274 | |
| ... | ... | @@ -317,7 +317,7 @@ public: |
| 317 | 317 | __sb_ = _VSTD::move(__rhs.__sb_); |
| 318 | 318 | return *this; |
| 319 | 319 | } |
| 320 | #endif // _LIBCPP_CXX03_LANG | |
| 320 | #endif // _LIBCPP_CXX03_LANG | |
| 321 | 321 | |
| 322 | 322 | virtual ~ostrstream(); |
| 323 | 323 | |
| ... | ... | @@ -377,7 +377,7 @@ public: |
| 377 | 377 | __sb_ = _VSTD::move(__rhs.__sb_); |
| 378 | 378 | return *this; |
| 379 | 379 | } |
| 380 | #endif // _LIBCPP_CXX03_LANG | |
| 380 | #endif // _LIBCPP_CXX03_LANG | |
| 381 | 381 | |
| 382 | 382 | virtual ~strstream(); |
| 383 | 383 | |
| ... | ... | @@ -404,4 +404,4 @@ private: |
| 404 | 404 | |
| 405 | 405 | _LIBCPP_END_NAMESPACE_STD |
| 406 | 406 | |
| 407 | #endif // _LIBCPP_STRSTREAM | |
| 407 | #endif // _LIBCPP_STRSTREAM |
lib/libcxx/include/system_error+8-7| ... | ... | @@ -142,11 +142,14 @@ template <> struct hash<std::error_condition>; |
| 142 | 142 | |
| 143 | 143 | */ |
| 144 | 144 | |
| 145 | #include <__config> | |
| 145 | 146 | #include <__errc> |
| 146 | #include <type_traits> | |
| 147 | #include <stdexcept> | |
| 147 | #include <__functional/unary_function.h> | |
| 148 | 148 | #include <__functional_base> |
| 149 | #include <compare> | |
| 150 | #include <stdexcept> | |
| 149 | 151 | #include <string> |
| 152 | #include <type_traits> | |
| 150 | 153 | |
| 151 | 154 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 152 | 155 | #pragma GCC system_header |
| ... | ... | @@ -289,8 +292,7 @@ public: |
| 289 | 292 | string message() const; |
| 290 | 293 | |
| 291 | 294 | _LIBCPP_INLINE_VISIBILITY |
| 292 | _LIBCPP_EXPLICIT | |
| 293 | operator bool() const _NOEXCEPT {return __val_ != 0;} | |
| 295 | explicit operator bool() const _NOEXCEPT {return __val_ != 0;} | |
| 294 | 296 | }; |
| 295 | 297 | |
| 296 | 298 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -366,8 +368,7 @@ public: |
| 366 | 368 | string message() const; |
| 367 | 369 | |
| 368 | 370 | _LIBCPP_INLINE_VISIBILITY |
| 369 | _LIBCPP_EXPLICIT | |
| 370 | operator bool() const _NOEXCEPT {return __val_ != 0;} | |
| 371 | explicit operator bool() const _NOEXCEPT {return __val_ != 0;} | |
| 371 | 372 | }; |
| 372 | 373 | |
| 373 | 374 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -484,4 +485,4 @@ void __throw_system_error(int ev, const char* what_arg); |
| 484 | 485 | |
| 485 | 486 | _LIBCPP_END_NAMESPACE_STD |
| 486 | 487 | |
| 487 | #endif // _LIBCPP_SYSTEM_ERROR | |
| 488 | #endif // _LIBCPP_SYSTEM_ERROR |
lib/libcxx/include/tgmath.h+2-2| ... | ... | @@ -31,6 +31,6 @@ |
| 31 | 31 | |
| 32 | 32 | #include_next <tgmath.h> |
| 33 | 33 | |
| 34 | #endif // __cplusplus | |
| 34 | #endif // __cplusplus | |
| 35 | 35 | |
| 36 | #endif // _LIBCPP_TGMATH_H | |
| 36 | #endif // _LIBCPP_TGMATH_H |
lib/libcxx/include/thread+15-16| ... | ... | @@ -83,20 +83,20 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time); |
| 83 | 83 | */ |
| 84 | 84 | |
| 85 | 85 | #include <__config> |
| 86 | #include <iosfwd> | |
| 86 | #include <__debug> | |
| 87 | 87 | #include <__functional_base> |
| 88 | #include <type_traits> | |
| 88 | #include <__mutex_base> | |
| 89 | #include <__threading_support> | |
| 90 | #include <__utility/__decay_copy.h> | |
| 91 | #include <__utility/forward.h> | |
| 92 | #include <chrono> | |
| 89 | 93 | #include <cstddef> |
| 90 | 94 | #include <functional> |
| 95 | #include <iosfwd> | |
| 91 | 96 | #include <memory> |
| 92 | 97 | #include <system_error> |
| 93 | #include <chrono> | |
| 94 | #include <__mutex_base> | |
| 95 | #ifndef _LIBCPP_CXX03_LANG | |
| 96 | 98 | #include <tuple> |
| 97 | #endif | |
| 98 | #include <__threading_support> | |
| 99 | #include <__debug> | |
| 99 | #include <type_traits> | |
| 100 | 100 | |
| 101 | 101 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 102 | 102 | #pragma GCC system_header |
| ... | ... | @@ -346,7 +346,7 @@ thread::thread(_Fp __f) |
| 346 | 346 | __throw_system_error(__ec, "thread constructor failed"); |
| 347 | 347 | } |
| 348 | 348 | |
| 349 | #endif // _LIBCPP_CXX03_LANG | |
| 349 | #endif // _LIBCPP_CXX03_LANG | |
| 350 | 350 | |
| 351 | 351 | inline _LIBCPP_INLINE_VISIBILITY |
| 352 | 352 | void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} |
| ... | ... | @@ -362,12 +362,11 @@ sleep_for(const chrono::duration<_Rep, _Period>& __d) |
| 362 | 362 | { |
| 363 | 363 | if (__d > chrono::duration<_Rep, _Period>::zero()) |
| 364 | 364 | { |
| 365 | #if defined(_LIBCPP_COMPILER_GCC) && (__powerpc__ || __POWERPC__) | |
| 366 | // GCC's long double const folding is incomplete for IBM128 long doubles. | |
| 367 | _LIBCPP_CONSTEXPR chrono::duration<long double> _Max = chrono::duration<long double>(ULLONG_MAX/1000000000ULL) ; | |
| 368 | #else | |
| 369 | _LIBCPP_CONSTEXPR chrono::duration<long double> _Max = chrono::nanoseconds::max(); | |
| 370 | #endif | |
| 365 | // The standard guarantees a 64bit signed integer resolution for nanoseconds, | |
| 366 | // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits> | |
| 367 | // and issues with long double folding on PowerPC with GCC. | |
| 368 | _LIBCPP_CONSTEXPR chrono::duration<long double> _Max = | |
| 369 | chrono::duration<long double>(9223372036.0L); | |
| 371 | 370 | chrono::nanoseconds __ns; |
| 372 | 371 | if (__d < _Max) |
| 373 | 372 | { |
| ... | ... | @@ -411,4 +410,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 411 | 410 | |
| 412 | 411 | _LIBCPP_POP_MACROS |
| 413 | 412 | |
| 414 | #endif // _LIBCPP_THREAD | |
| 413 | #endif // _LIBCPP_THREAD |
lib/libcxx/include/tuple+601-480| ... | ... | @@ -38,35 +38,39 @@ public: |
| 38 | 38 | template <class Alloc> |
| 39 | 39 | tuple(allocator_arg_t, const Alloc& a); |
| 40 | 40 | template <class Alloc> |
| 41 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const T&...); | |
| 41 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const T&...); // constexpr in C++20 | |
| 42 | 42 | template <class Alloc, class... U> |
| 43 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, U&&...); | |
| 43 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, U&&...); // constexpr in C++20 | |
| 44 | 44 | template <class Alloc> |
| 45 | tuple(allocator_arg_t, const Alloc& a, const tuple&); | |
| 45 | tuple(allocator_arg_t, const Alloc& a, const tuple&); // constexpr in C++20 | |
| 46 | 46 | template <class Alloc> |
| 47 | tuple(allocator_arg_t, const Alloc& a, tuple&&); | |
| 47 | tuple(allocator_arg_t, const Alloc& a, tuple&&); // constexpr in C++20 | |
| 48 | 48 | template <class Alloc, class... U> |
| 49 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const tuple<U...>&); | |
| 49 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const tuple<U...>&); // constexpr in C++20 | |
| 50 | 50 | template <class Alloc, class... U> |
| 51 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, tuple<U...>&&); | |
| 51 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, tuple<U...>&&); // constexpr in C++20 | |
| 52 | 52 | template <class Alloc, class U1, class U2> |
| 53 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); | |
| 53 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); // constexpr in C++20 | |
| 54 | 54 | template <class Alloc, class U1, class U2> |
| 55 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); | |
| 55 | explicit(see-below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); // constexpr in C++20 | |
| 56 | 56 | |
| 57 | tuple& operator=(const tuple&); | |
| 58 | tuple& | |
| 59 | operator=(tuple&&) noexcept(AND(is_nothrow_move_assignable<T>::value ...)); | |
| 57 | tuple& operator=(const tuple&); // constexpr in C++20 | |
| 58 | tuple& operator=(tuple&&) noexcept(is_nothrow_move_assignable_v<T> && ...); // constexpr in C++20 | |
| 60 | 59 | template <class... U> |
| 61 | tuple& operator=(const tuple<U...>&); | |
| 60 | tuple& operator=(const tuple<U...>&); // constexpr in C++20 | |
| 62 | 61 | template <class... U> |
| 63 | tuple& operator=(tuple<U...>&&); | |
| 62 | tuple& operator=(tuple<U...>&&); // constexpr in C++20 | |
| 64 | 63 | template <class U1, class U2> |
| 65 | tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2 | |
| 64 | tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2 // constexpr in C++20 | |
| 66 | 65 | template <class U1, class U2> |
| 67 | tuple& operator=(pair<U1, U2>&&); // iff sizeof...(T) == 2 | |
| 66 | tuple& operator=(pair<U1, U2>&&); // iff sizeof...(T) == 2 // constexpr in C++20 | |
| 68 | 67 | |
| 69 | void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...)); | |
| 68 | template<class U, size_t N> | |
| 69 | tuple& operator=(array<U, N> const&) // iff sizeof...(T) == N, EXTENSION | |
| 70 | template<class U, size_t N> | |
| 71 | tuple& operator=(array<U, N>&&) // iff sizeof...(T) == N, EXTENSION | |
| 72 | ||
| 73 | void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...)); // constexpr in C++20 | |
| 70 | 74 | }; |
| 71 | 75 | |
| 72 | 76 | template <class ...T> |
| ... | ... | @@ -146,10 +150,16 @@ template <class... Types> |
| 146 | 150 | */ |
| 147 | 151 | |
| 148 | 152 | #include <__config> |
| 153 | #include <__functional/unwrap_ref.h> | |
| 154 | #include <__functional_base> | |
| 155 | #include <__memory/allocator_arg_t.h> | |
| 156 | #include <__memory/uses_allocator.h> | |
| 149 | 157 | #include <__tuple> |
| 158 | #include <__utility/forward.h> | |
| 159 | #include <__utility/move.h> | |
| 160 | #include <compare> | |
| 150 | 161 | #include <cstddef> |
| 151 | 162 | #include <type_traits> |
| 152 | #include <__functional_base> | |
| 153 | 163 | #include <utility> |
| 154 | 164 | #include <version> |
| 155 | 165 | |
| ... | ... | @@ -170,7 +180,7 @@ template <size_t _Ip, class _Hp, |
| 170 | 180 | class __tuple_leaf; |
| 171 | 181 | |
| 172 | 182 | template <size_t _Ip, class _Hp, bool _Ep> |
| 173 | inline _LIBCPP_INLINE_VISIBILITY | |
| 183 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 174 | 184 | void swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y) |
| 175 | 185 | _NOEXCEPT_(__is_nothrow_swappable<_Hp>::value) |
| 176 | 186 | { |
| ... | ... | @@ -191,29 +201,30 @@ class __tuple_leaf |
| 191 | 201 | #endif |
| 192 | 202 | } |
| 193 | 203 | |
| 204 | _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 194 | 205 | __tuple_leaf& operator=(const __tuple_leaf&); |
| 195 | 206 | public: |
| 196 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __tuple_leaf() | |
| 207 | _LIBCPP_INLINE_VISIBILITY constexpr __tuple_leaf() | |
| 197 | 208 | _NOEXCEPT_(is_nothrow_default_constructible<_Hp>::value) : __value_() |
| 198 | 209 | {static_assert(!is_reference<_Hp>::value, |
| 199 | 210 | "Attempted to default construct a reference element in a tuple");} |
| 200 | 211 | |
| 201 | 212 | template <class _Alloc> |
| 202 | _LIBCPP_INLINE_VISIBILITY | |
| 213 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 203 | 214 | __tuple_leaf(integral_constant<int, 0>, const _Alloc&) |
| 204 | 215 | : __value_() |
| 205 | 216 | {static_assert(!is_reference<_Hp>::value, |
| 206 | 217 | "Attempted to default construct a reference element in a tuple");} |
| 207 | 218 | |
| 208 | 219 | template <class _Alloc> |
| 209 | _LIBCPP_INLINE_VISIBILITY | |
| 220 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 210 | 221 | __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a) |
| 211 | 222 | : __value_(allocator_arg_t(), __a) |
| 212 | 223 | {static_assert(!is_reference<_Hp>::value, |
| 213 | 224 | "Attempted to default construct a reference element in a tuple");} |
| 214 | 225 | |
| 215 | 226 | template <class _Alloc> |
| 216 | _LIBCPP_INLINE_VISIBILITY | |
| 227 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 217 | 228 | __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) |
| 218 | 229 | : __value_(__a) |
| 219 | 230 | {static_assert(!is_reference<_Hp>::value, |
| ... | ... | @@ -234,21 +245,21 @@ public: |
| 234 | 245 | "Attempted construction of reference element binds to a temporary whose lifetime has ended");} |
| 235 | 246 | |
| 236 | 247 | template <class _Tp, class _Alloc> |
| 237 | _LIBCPP_INLINE_VISIBILITY | |
| 248 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 238 | 249 | explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t) |
| 239 | 250 | : __value_(_VSTD::forward<_Tp>(__t)) |
| 240 | 251 | {static_assert(__can_bind_reference<_Tp&&>(), |
| 241 | 252 | "Attempted construction of reference element binds to a temporary whose lifetime has ended");} |
| 242 | 253 | |
| 243 | 254 | template <class _Tp, class _Alloc> |
| 244 | _LIBCPP_INLINE_VISIBILITY | |
| 255 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 245 | 256 | explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t) |
| 246 | 257 | : __value_(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t)) |
| 247 | 258 | {static_assert(!is_reference<_Hp>::value, |
| 248 | 259 | "Attempted to uses-allocator construct a reference element in a tuple");} |
| 249 | 260 | |
| 250 | 261 | template <class _Tp, class _Alloc> |
| 251 | _LIBCPP_INLINE_VISIBILITY | |
| 262 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 252 | 263 | explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t) |
| 253 | 264 | : __value_(_VSTD::forward<_Tp>(__t), __a) |
| 254 | 265 | {static_assert(!is_reference<_Hp>::value, |
| ... | ... | @@ -257,16 +268,7 @@ public: |
| 257 | 268 | __tuple_leaf(const __tuple_leaf& __t) = default; |
| 258 | 269 | __tuple_leaf(__tuple_leaf&& __t) = default; |
| 259 | 270 | |
| 260 | template <class _Tp> | |
| 261 | _LIBCPP_INLINE_VISIBILITY | |
| 262 | __tuple_leaf& | |
| 263 | operator=(_Tp&& __t) _NOEXCEPT_((is_nothrow_assignable<_Hp&, _Tp>::value)) | |
| 264 | { | |
| 265 | __value_ = _VSTD::forward<_Tp>(__t); | |
| 266 | return *this; | |
| 267 | } | |
| 268 | ||
| 269 | _LIBCPP_INLINE_VISIBILITY | |
| 271 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 270 | 272 | int swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value) |
| 271 | 273 | { |
| 272 | 274 | _VSTD::swap(*this, __t); |
| ... | ... | @@ -281,23 +283,23 @@ template <size_t _Ip, class _Hp> |
| 281 | 283 | class __tuple_leaf<_Ip, _Hp, true> |
| 282 | 284 | : private _Hp |
| 283 | 285 | { |
| 284 | ||
| 286 | _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 285 | 287 | __tuple_leaf& operator=(const __tuple_leaf&); |
| 286 | 288 | public: |
| 287 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __tuple_leaf() | |
| 289 | _LIBCPP_INLINE_VISIBILITY constexpr __tuple_leaf() | |
| 288 | 290 | _NOEXCEPT_(is_nothrow_default_constructible<_Hp>::value) {} |
| 289 | 291 | |
| 290 | 292 | template <class _Alloc> |
| 291 | _LIBCPP_INLINE_VISIBILITY | |
| 293 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 292 | 294 | __tuple_leaf(integral_constant<int, 0>, const _Alloc&) {} |
| 293 | 295 | |
| 294 | 296 | template <class _Alloc> |
| 295 | _LIBCPP_INLINE_VISIBILITY | |
| 297 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 296 | 298 | __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a) |
| 297 | 299 | : _Hp(allocator_arg_t(), __a) {} |
| 298 | 300 | |
| 299 | 301 | template <class _Alloc> |
| 300 | _LIBCPP_INLINE_VISIBILITY | |
| 302 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 301 | 303 | __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) |
| 302 | 304 | : _Hp(__a) {} |
| 303 | 305 | |
| ... | ... | @@ -314,33 +316,24 @@ public: |
| 314 | 316 | : _Hp(_VSTD::forward<_Tp>(__t)) {} |
| 315 | 317 | |
| 316 | 318 | template <class _Tp, class _Alloc> |
| 317 | _LIBCPP_INLINE_VISIBILITY | |
| 319 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 318 | 320 | explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t) |
| 319 | 321 | : _Hp(_VSTD::forward<_Tp>(__t)) {} |
| 320 | 322 | |
| 321 | 323 | template <class _Tp, class _Alloc> |
| 322 | _LIBCPP_INLINE_VISIBILITY | |
| 324 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 323 | 325 | explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t) |
| 324 | 326 | : _Hp(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t)) {} |
| 325 | 327 | |
| 326 | 328 | template <class _Tp, class _Alloc> |
| 327 | _LIBCPP_INLINE_VISIBILITY | |
| 329 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 328 | 330 | explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t) |
| 329 | 331 | : _Hp(_VSTD::forward<_Tp>(__t), __a) {} |
| 330 | 332 | |
| 331 | 333 | __tuple_leaf(__tuple_leaf const &) = default; |
| 332 | 334 | __tuple_leaf(__tuple_leaf &&) = default; |
| 333 | 335 | |
| 334 | template <class _Tp> | |
| 335 | _LIBCPP_INLINE_VISIBILITY | |
| 336 | __tuple_leaf& | |
| 337 | operator=(_Tp&& __t) _NOEXCEPT_((is_nothrow_assignable<_Hp&, _Tp>::value)) | |
| 338 | { | |
| 339 | _Hp::operator=(_VSTD::forward<_Tp>(__t)); | |
| 340 | return *this; | |
| 341 | } | |
| 342 | ||
| 343 | _LIBCPP_INLINE_VISIBILITY | |
| 336 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 344 | 337 | int |
| 345 | 338 | swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value) |
| 346 | 339 | { |
| ... | ... | @@ -353,7 +346,7 @@ public: |
| 353 | 346 | }; |
| 354 | 347 | |
| 355 | 348 | template <class ..._Tp> |
| 356 | _LIBCPP_INLINE_VISIBILITY | |
| 349 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 357 | 350 | void __swallow(_Tp&&...) _NOEXCEPT {} |
| 358 | 351 | |
| 359 | 352 | template <class _Tp> |
| ... | ... | @@ -373,7 +366,7 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES __tuple_impl<__tuple_indices<_Indx...>, _Tp. |
| 373 | 366 | : public __tuple_leaf<_Indx, _Tp>... |
| 374 | 367 | { |
| 375 | 368 | _LIBCPP_INLINE_VISIBILITY |
| 376 | _LIBCPP_CONSTEXPR __tuple_impl() | |
| 369 | constexpr __tuple_impl() | |
| 377 | 370 | _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {} |
| 378 | 371 | |
| 379 | 372 | template <size_t ..._Uf, class ..._Tf, |
| ... | ... | @@ -391,7 +384,7 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES __tuple_impl<__tuple_indices<_Indx...>, _Tp. |
| 391 | 384 | |
| 392 | 385 | template <class _Alloc, size_t ..._Uf, class ..._Tf, |
| 393 | 386 | size_t ..._Ul, class ..._Tl, class ..._Up> |
| 394 | _LIBCPP_INLINE_VISIBILITY | |
| 387 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 395 | 388 | explicit |
| 396 | 389 | __tuple_impl(allocator_arg_t, const _Alloc& __a, |
| 397 | 390 | __tuple_indices<_Uf...>, __tuple_types<_Tf...>, |
| ... | ... | @@ -421,7 +414,7 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES __tuple_impl<__tuple_indices<_Indx...>, _Tp. |
| 421 | 414 | __tuple_constructible<_Tuple, tuple<_Tp...> >::value |
| 422 | 415 | >::type |
| 423 | 416 | > |
| 424 | _LIBCPP_INLINE_VISIBILITY | |
| 417 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 425 | 418 | __tuple_impl(allocator_arg_t, const _Alloc& __a, _Tuple&& __t) |
| 426 | 419 | : __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, typename tuple_element<_Indx, |
| 427 | 420 | typename __make_tuple_types<_Tuple>::type>::type>(), __a, |
| ... | ... | @@ -429,49 +422,30 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES __tuple_impl<__tuple_indices<_Indx...>, _Tp. |
| 429 | 422 | typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))... |
| 430 | 423 | {} |
| 431 | 424 | |
| 432 | template <class _Tuple> | |
| 433 | _LIBCPP_INLINE_VISIBILITY | |
| 434 | typename enable_if | |
| 435 | < | |
| 436 | __tuple_assignable<_Tuple, tuple<_Tp...> >::value, | |
| 437 | __tuple_impl& | |
| 438 | >::type | |
| 439 | operator=(_Tuple&& __t) _NOEXCEPT_((__all<is_nothrow_assignable<_Tp&, typename tuple_element<_Indx, | |
| 440 | typename __make_tuple_types<_Tuple>::type>::type>::value...>::value)) | |
| 441 | { | |
| 442 | __swallow(__tuple_leaf<_Indx, _Tp>::operator=(_VSTD::forward<typename tuple_element<_Indx, | |
| 443 | typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...); | |
| 444 | return *this; | |
| 445 | } | |
| 446 | ||
| 447 | 425 | __tuple_impl(const __tuple_impl&) = default; |
| 448 | 426 | __tuple_impl(__tuple_impl&&) = default; |
| 449 | 427 | |
| 450 | _LIBCPP_INLINE_VISIBILITY | |
| 451 | __tuple_impl& | |
| 452 | operator=(const __tuple_impl& __t) _NOEXCEPT_((__all<is_nothrow_copy_assignable<_Tp>::value...>::value)) | |
| 453 | { | |
| 454 | __swallow(__tuple_leaf<_Indx, _Tp>::operator=(static_cast<const __tuple_leaf<_Indx, _Tp>&>(__t).get())...); | |
| 455 | return *this; | |
| 456 | } | |
| 457 | ||
| 458 | _LIBCPP_INLINE_VISIBILITY | |
| 459 | __tuple_impl& | |
| 460 | operator=(__tuple_impl&& __t) _NOEXCEPT_((__all<is_nothrow_move_assignable<_Tp>::value...>::value)) | |
| 461 | { | |
| 462 | __swallow(__tuple_leaf<_Indx, _Tp>::operator=(_VSTD::forward<_Tp>(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t).get()))...); | |
| 463 | return *this; | |
| 464 | } | |
| 465 | ||
| 466 | _LIBCPP_INLINE_VISIBILITY | |
| 428 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 467 | 429 | void swap(__tuple_impl& __t) |
| 468 | 430 | _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value) |
| 469 | 431 | { |
| 470 | __swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...); | |
| 432 | _VSTD::__swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...); | |
| 471 | 433 | } |
| 472 | 434 | }; |
| 473 | 435 | |
| 436 | template<class _Dest, class _Source, size_t ..._Np> | |
| 437 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 438 | void __memberwise_copy_assign(_Dest& __dest, _Source const& __source, __tuple_indices<_Np...>) { | |
| 439 | _VSTD::__swallow(((_VSTD::get<_Np>(__dest) = _VSTD::get<_Np>(__source)), void(), 0)...); | |
| 440 | } | |
| 474 | 441 | |
| 442 | template<class _Dest, class _Source, class ..._Up, size_t ..._Np> | |
| 443 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 444 | void __memberwise_forward_assign(_Dest& __dest, _Source&& __source, __tuple_types<_Up...>, __tuple_indices<_Np...>) { | |
| 445 | _VSTD::__swallow((( | |
| 446 | _VSTD::get<_Np>(__dest) = _VSTD::forward<_Up>(_VSTD::get<_Np>(__source)) | |
| 447 | ), void(), 0)...); | |
| 448 | } | |
| 475 | 449 | |
| 476 | 450 | template <class ..._Tp> |
| 477 | 451 | class _LIBCPP_TEMPLATE_VIS tuple |
| ... | ... | @@ -480,165 +454,6 @@ class _LIBCPP_TEMPLATE_VIS tuple |
| 480 | 454 | |
| 481 | 455 | _BaseT __base_; |
| 482 | 456 | |
| 483 | #if defined(_LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION) | |
| 484 | static constexpr bool _EnableImplicitReducedArityExtension = true; | |
| 485 | #else | |
| 486 | static constexpr bool _EnableImplicitReducedArityExtension = false; | |
| 487 | #endif | |
| 488 | ||
| 489 | template <class ..._Args> | |
| 490 | struct _PackExpandsToThisTuple : false_type {}; | |
| 491 | ||
| 492 | template <class _Arg> | |
| 493 | struct _PackExpandsToThisTuple<_Arg> | |
| 494 | : is_same<typename __uncvref<_Arg>::type, tuple> {}; | |
| 495 | ||
| 496 | template <bool _MaybeEnable, class _Dummy = void> | |
| 497 | struct _CheckArgsConstructor : __check_tuple_constructor_fail {}; | |
| 498 | ||
| 499 | template <class _Dummy> | |
| 500 | struct _CheckArgsConstructor<true, _Dummy> | |
| 501 | { | |
| 502 | template <int&...> | |
| 503 | static constexpr bool __enable_implicit_default() { | |
| 504 | return __all<__is_implicitly_default_constructible<_Tp>::value... >::value; | |
| 505 | } | |
| 506 | ||
| 507 | template <int&...> | |
| 508 | static constexpr bool __enable_explicit_default() { | |
| 509 | return | |
| 510 | __all<is_default_constructible<_Tp>::value...>::value && | |
| 511 | !__enable_implicit_default< >(); | |
| 512 | } | |
| 513 | ||
| 514 | ||
| 515 | template <class ..._Args> | |
| 516 | static constexpr bool __enable_explicit() { | |
| 517 | return | |
| 518 | __tuple_constructible< | |
| 519 | tuple<_Args...>, | |
| 520 | typename __make_tuple_types<tuple, | |
| 521 | sizeof...(_Args) < sizeof...(_Tp) ? | |
| 522 | sizeof...(_Args) : | |
| 523 | sizeof...(_Tp)>::type | |
| 524 | >::value && | |
| 525 | !__tuple_convertible< | |
| 526 | tuple<_Args...>, | |
| 527 | typename __make_tuple_types<tuple, | |
| 528 | sizeof...(_Args) < sizeof...(_Tp) ? | |
| 529 | sizeof...(_Args) : | |
| 530 | sizeof...(_Tp)>::type | |
| 531 | >::value && | |
| 532 | __all_default_constructible< | |
| 533 | typename __make_tuple_types<tuple, sizeof...(_Tp), | |
| 534 | sizeof...(_Args) < sizeof...(_Tp) ? | |
| 535 | sizeof...(_Args) : | |
| 536 | sizeof...(_Tp)>::type | |
| 537 | >::value; | |
| 538 | } | |
| 539 | ||
| 540 | template <class ..._Args> | |
| 541 | static constexpr bool __enable_implicit() { | |
| 542 | return | |
| 543 | __tuple_constructible< | |
| 544 | tuple<_Args...>, | |
| 545 | typename __make_tuple_types<tuple, | |
| 546 | sizeof...(_Args) < sizeof...(_Tp) ? | |
| 547 | sizeof...(_Args) : | |
| 548 | sizeof...(_Tp)>::type | |
| 549 | >::value && | |
| 550 | __tuple_convertible< | |
| 551 | tuple<_Args...>, | |
| 552 | typename __make_tuple_types<tuple, | |
| 553 | sizeof...(_Args) < sizeof...(_Tp) ? | |
| 554 | sizeof...(_Args) : | |
| 555 | sizeof...(_Tp)>::type | |
| 556 | >::value && | |
| 557 | __all_default_constructible< | |
| 558 | typename __make_tuple_types<tuple, sizeof...(_Tp), | |
| 559 | sizeof...(_Args) < sizeof...(_Tp) ? | |
| 560 | sizeof...(_Args) : | |
| 561 | sizeof...(_Tp)>::type | |
| 562 | >::value; | |
| 563 | } | |
| 564 | }; | |
| 565 | ||
| 566 | template <bool _MaybeEnable, | |
| 567 | bool = sizeof...(_Tp) == 1, | |
| 568 | class _Dummy = void> | |
| 569 | struct _CheckTupleLikeConstructor : __check_tuple_constructor_fail {}; | |
| 570 | ||
| 571 | template <class _Dummy> | |
| 572 | struct _CheckTupleLikeConstructor<true, false, _Dummy> | |
| 573 | { | |
| 574 | template <class _Tuple> | |
| 575 | static constexpr bool __enable_implicit() { | |
| 576 | return __tuple_constructible<_Tuple, tuple>::value | |
| 577 | && __tuple_convertible<_Tuple, tuple>::value; | |
| 578 | } | |
| 579 | ||
| 580 | template <class _Tuple> | |
| 581 | static constexpr bool __enable_explicit() { | |
| 582 | return __tuple_constructible<_Tuple, tuple>::value | |
| 583 | && !__tuple_convertible<_Tuple, tuple>::value; | |
| 584 | } | |
| 585 | }; | |
| 586 | ||
| 587 | template <class _Dummy> | |
| 588 | struct _CheckTupleLikeConstructor<true, true, _Dummy> | |
| 589 | { | |
| 590 | // This trait is used to disable the tuple-like constructor when | |
| 591 | // the UTypes... constructor should be selected instead. | |
| 592 | // See LWG issue #2549. | |
| 593 | template <class _Tuple> | |
| 594 | using _PreferTupleLikeConstructor = _Or< | |
| 595 | // Don't attempt the two checks below if the tuple we are given | |
| 596 | // has the same type as this tuple. | |
| 597 | _IsSame<__uncvref_t<_Tuple>, tuple>, | |
| 598 | _Lazy<_And, | |
| 599 | _Not<is_constructible<_Tp..., _Tuple>>, | |
| 600 | _Not<is_convertible<_Tuple, _Tp...>> | |
| 601 | > | |
| 602 | >; | |
| 603 | ||
| 604 | template <class _Tuple> | |
| 605 | static constexpr bool __enable_implicit() { | |
| 606 | return _And< | |
| 607 | __tuple_constructible<_Tuple, tuple>, | |
| 608 | __tuple_convertible<_Tuple, tuple>, | |
| 609 | _PreferTupleLikeConstructor<_Tuple> | |
| 610 | >::value; | |
| 611 | } | |
| 612 | ||
| 613 | template <class _Tuple> | |
| 614 | static constexpr bool __enable_explicit() { | |
| 615 | return _And< | |
| 616 | __tuple_constructible<_Tuple, tuple>, | |
| 617 | _PreferTupleLikeConstructor<_Tuple>, | |
| 618 | _Not<__tuple_convertible<_Tuple, tuple>> | |
| 619 | >::value; | |
| 620 | } | |
| 621 | }; | |
| 622 | ||
| 623 | template <class _Tuple, bool _DisableIfLValue> | |
| 624 | using _EnableImplicitTupleLikeConstructor = _EnableIf< | |
| 625 | _CheckTupleLikeConstructor< | |
| 626 | __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value | |
| 627 | && !_PackExpandsToThisTuple<_Tuple>::value | |
| 628 | && (!is_lvalue_reference<_Tuple>::value || !_DisableIfLValue) | |
| 629 | >::template __enable_implicit<_Tuple>(), | |
| 630 | bool | |
| 631 | >; | |
| 632 | ||
| 633 | template <class _Tuple, bool _DisableIfLValue> | |
| 634 | using _EnableExplicitTupleLikeConstructor = _EnableIf< | |
| 635 | _CheckTupleLikeConstructor< | |
| 636 | __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value | |
| 637 | && !_PackExpandsToThisTuple<_Tuple>::value | |
| 638 | && (!is_lvalue_reference<_Tuple>::value || !_DisableIfLValue) | |
| 639 | >::template __enable_explicit<_Tuple>(), | |
| 640 | bool | |
| 641 | >; | |
| 642 | 457 | template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 643 | 458 | typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT; |
| 644 | 459 | template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| ... | ... | @@ -648,57 +463,69 @@ class _LIBCPP_TEMPLATE_VIS tuple |
| 648 | 463 | template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 649 | 464 | const typename tuple_element<_Jp, tuple<_Up...> >::type&& get(const tuple<_Up...>&&) _NOEXCEPT; |
| 650 | 465 | public: |
| 651 | ||
| 652 | template <bool _Dummy = true, _EnableIf< | |
| 653 | _CheckArgsConstructor<_Dummy>::__enable_implicit_default() | |
| 654 | , void*> = nullptr> | |
| 466 | // [tuple.cnstr] | |
| 467 | ||
| 468 | // tuple() constructors (including allocator_arg_t variants) | |
| 469 | template <template<class...> class _IsImpDefault = __is_implicitly_default_constructible, _EnableIf< | |
| 470 | _And< | |
| 471 | _IsImpDefault<_Tp>... // explicit check | |
| 472 | >::value | |
| 473 | , int> = 0> | |
| 655 | 474 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR |
| 656 | 475 | tuple() |
| 657 | _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {} | |
| 658 | ||
| 659 | template <bool _Dummy = true, _EnableIf< | |
| 660 | _CheckArgsConstructor<_Dummy>::__enable_explicit_default() | |
| 661 | , void*> = nullptr> | |
| 662 | explicit _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 663 | tuple() | |
| 664 | _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {} | |
| 665 | ||
| 666 | tuple(tuple const&) = default; | |
| 667 | tuple(tuple&&) = default; | |
| 668 | ||
| 669 | template <class _AllocArgT, class _Alloc, _EnableIf< | |
| 670 | _CheckArgsConstructor<_IsSame<allocator_arg_t, _AllocArgT>::value >::__enable_implicit_default() | |
| 671 | , void*> = nullptr | |
| 672 | > | |
| 673 | _LIBCPP_INLINE_VISIBILITY | |
| 674 | tuple(_AllocArgT, _Alloc const& __a) | |
| 476 | _NOEXCEPT_(_And<is_nothrow_default_constructible<_Tp>...>::value) | |
| 477 | { } | |
| 478 | ||
| 479 | template <template<class...> class _IsImpDefault = __is_implicitly_default_constructible, | |
| 480 | template<class...> class _IsDefault = is_default_constructible, _EnableIf< | |
| 481 | _And< | |
| 482 | _IsDefault<_Tp>..., | |
| 483 | _Not<_Lazy<_And, _IsImpDefault<_Tp>...> > // explicit check | |
| 484 | >::value | |
| 485 | , int> = 0> | |
| 486 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 487 | explicit tuple() | |
| 488 | _NOEXCEPT_(_And<is_nothrow_default_constructible<_Tp>...>::value) | |
| 489 | { } | |
| 490 | ||
| 491 | template <class _Alloc, template<class...> class _IsImpDefault = __is_implicitly_default_constructible, _EnableIf< | |
| 492 | _And< | |
| 493 | _IsImpDefault<_Tp>... // explicit check | |
| 494 | >::value | |
| 495 | , int> = 0> | |
| 496 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 497 | tuple(allocator_arg_t, _Alloc const& __a) | |
| 675 | 498 | : __base_(allocator_arg_t(), __a, |
| 676 | 499 | __tuple_indices<>(), __tuple_types<>(), |
| 677 | 500 | typename __make_tuple_indices<sizeof...(_Tp), 0>::type(), |
| 678 | 501 | __tuple_types<_Tp...>()) {} |
| 679 | 502 | |
| 680 | template <class _AllocArgT, class _Alloc, _EnableIf< | |
| 681 | _CheckArgsConstructor<_IsSame<allocator_arg_t, _AllocArgT>::value>::__enable_explicit_default() | |
| 682 | , void*> = nullptr | |
| 683 | > | |
| 684 | explicit _LIBCPP_INLINE_VISIBILITY | |
| 685 | tuple(_AllocArgT, _Alloc const& __a) | |
| 503 | template <class _Alloc, | |
| 504 | template<class...> class _IsImpDefault = __is_implicitly_default_constructible, | |
| 505 | template<class...> class _IsDefault = is_default_constructible, _EnableIf< | |
| 506 | _And< | |
| 507 | _IsDefault<_Tp>..., | |
| 508 | _Not<_Lazy<_And, _IsImpDefault<_Tp>...> > // explicit check | |
| 509 | >::value | |
| 510 | , int> = 0> | |
| 511 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 512 | explicit tuple(allocator_arg_t, _Alloc const& __a) | |
| 686 | 513 | : __base_(allocator_arg_t(), __a, |
| 687 | 514 | __tuple_indices<>(), __tuple_types<>(), |
| 688 | 515 | typename __make_tuple_indices<sizeof...(_Tp), 0>::type(), |
| 689 | 516 | __tuple_types<_Tp...>()) {} |
| 690 | 517 | |
| 691 | template <bool _Dummy = true, | |
| 692 | typename enable_if | |
| 693 | < | |
| 694 | _CheckArgsConstructor< | |
| 695 | _Dummy | |
| 696 | >::template __enable_implicit<_Tp const&...>(), | |
| 697 | bool | |
| 698 | >::type = false | |
| 699 | > | |
| 518 | // tuple(const T&...) constructors (including allocator_arg_t variants) | |
| 519 | template <template<class...> class _And = _And, _EnableIf< | |
| 520 | _And< | |
| 521 | _BoolConstant<sizeof...(_Tp) >= 1>, | |
| 522 | is_copy_constructible<_Tp>..., | |
| 523 | is_convertible<const _Tp&, _Tp>... // explicit check | |
| 524 | >::value | |
| 525 | , int> = 0> | |
| 700 | 526 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 701 | tuple(const _Tp& ... __t) _NOEXCEPT_((__all<is_nothrow_copy_constructible<_Tp>::value...>::value)) | |
| 527 | tuple(const _Tp& ... __t) | |
| 528 | _NOEXCEPT_(_And<is_nothrow_copy_constructible<_Tp>...>::value) | |
| 702 | 529 | : __base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(), |
| 703 | 530 | typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(), |
| 704 | 531 | typename __make_tuple_indices<0>::type(), |
| ... | ... | @@ -706,17 +533,16 @@ public: |
| 706 | 533 | __t... |
| 707 | 534 | ) {} |
| 708 | 535 | |
| 709 | template <bool _Dummy = true, | |
| 710 | typename enable_if | |
| 711 | < | |
| 712 | _CheckArgsConstructor< | |
| 713 | _Dummy | |
| 714 | >::template __enable_explicit<_Tp const&...>(), | |
| 715 | bool | |
| 716 | >::type = false | |
| 717 | > | |
| 536 | template <template<class...> class _And = _And, _EnableIf< | |
| 537 | _And< | |
| 538 | _BoolConstant<sizeof...(_Tp) >= 1>, | |
| 539 | is_copy_constructible<_Tp>..., | |
| 540 | _Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> > // explicit check | |
| 541 | >::value | |
| 542 | , int> = 0> | |
| 718 | 543 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 |
| 719 | explicit tuple(const _Tp& ... __t) _NOEXCEPT_((__all<is_nothrow_copy_constructible<_Tp>::value...>::value)) | |
| 544 | explicit tuple(const _Tp& ... __t) | |
| 545 | _NOEXCEPT_(_And<is_nothrow_copy_constructible<_Tp>...>::value) | |
| 720 | 546 | : __base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(), |
| 721 | 547 | typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(), |
| 722 | 548 | typename __make_tuple_indices<0>::type(), |
| ... | ... | @@ -724,17 +550,15 @@ public: |
| 724 | 550 | __t... |
| 725 | 551 | ) {} |
| 726 | 552 | |
| 727 | template <class _Alloc, bool _Dummy = true, | |
| 728 | typename enable_if | |
| 729 | < | |
| 730 | _CheckArgsConstructor< | |
| 731 | _Dummy | |
| 732 | >::template __enable_implicit<_Tp const&...>(), | |
| 733 | bool | |
| 734 | >::type = false | |
| 735 | > | |
| 736 | _LIBCPP_INLINE_VISIBILITY | |
| 737 | tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t) | |
| 553 | template <class _Alloc, template<class...> class _And = _And, _EnableIf< | |
| 554 | _And< | |
| 555 | _BoolConstant<sizeof...(_Tp) >= 1>, | |
| 556 | is_copy_constructible<_Tp>..., | |
| 557 | is_convertible<const _Tp&, _Tp>... // explicit check | |
| 558 | >::value | |
| 559 | , int> = 0> | |
| 560 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 561 | tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t) | |
| 738 | 562 | : __base_(allocator_arg_t(), __a, |
| 739 | 563 | typename __make_tuple_indices<sizeof...(_Tp)>::type(), |
| 740 | 564 | typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(), |
| ... | ... | @@ -743,18 +567,15 @@ public: |
| 743 | 567 | __t... |
| 744 | 568 | ) {} |
| 745 | 569 | |
| 746 | template <class _Alloc, bool _Dummy = true, | |
| 747 | typename enable_if | |
| 748 | < | |
| 749 | _CheckArgsConstructor< | |
| 750 | _Dummy | |
| 751 | >::template __enable_explicit<_Tp const&...>(), | |
| 752 | bool | |
| 753 | >::type = false | |
| 754 | > | |
| 755 | _LIBCPP_INLINE_VISIBILITY | |
| 756 | explicit | |
| 757 | tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t) | |
| 570 | template <class _Alloc, template<class...> class _And = _And, _EnableIf< | |
| 571 | _And< | |
| 572 | _BoolConstant<sizeof...(_Tp) >= 1>, | |
| 573 | is_copy_constructible<_Tp>..., | |
| 574 | _Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> > // explicit check | |
| 575 | >::value | |
| 576 | , int> = 0> | |
| 577 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 578 | explicit tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t) | |
| 758 | 579 | : __base_(allocator_arg_t(), __a, |
| 759 | 580 | typename __make_tuple_indices<sizeof...(_Tp)>::type(), |
| 760 | 581 | typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(), |
| ... | ... | @@ -763,193 +584,493 @@ public: |
| 763 | 584 | __t... |
| 764 | 585 | ) {} |
| 765 | 586 | |
| 766 | template <class ..._Up, | |
| 767 | bool _PackIsTuple = _PackExpandsToThisTuple<_Up...>::value, | |
| 768 | typename enable_if | |
| 769 | < | |
| 770 | _CheckArgsConstructor< | |
| 771 | sizeof...(_Up) == sizeof...(_Tp) | |
| 772 | && !_PackIsTuple | |
| 773 | >::template __enable_implicit<_Up...>() || | |
| 774 | _CheckArgsConstructor< | |
| 775 | _EnableImplicitReducedArityExtension | |
| 776 | && sizeof...(_Up) < sizeof...(_Tp) | |
| 777 | && !_PackIsTuple | |
| 778 | >::template __enable_implicit<_Up...>(), | |
| 779 | bool | |
| 780 | >::type = false | |
| 781 | > | |
| 782 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 783 | tuple(_Up&&... __u) | |
| 784 | _NOEXCEPT_(( | |
| 785 | is_nothrow_constructible<_BaseT, | |
| 786 | typename __make_tuple_indices<sizeof...(_Up)>::type, | |
| 787 | typename __make_tuple_types<tuple, sizeof...(_Up)>::type, | |
| 788 | typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type, | |
| 789 | typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type, | |
| 790 | _Up... | |
| 791 | >::value | |
| 792 | )) | |
| 793 | : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(), | |
| 587 | // tuple(U&& ...) constructors (including allocator_arg_t variants) | |
| 588 | template <class ..._Up> struct _IsThisTuple : false_type { }; | |
| 589 | template <class _Up> struct _IsThisTuple<_Up> : is_same<__uncvref_t<_Up>, tuple> { }; | |
| 590 | ||
| 591 | template <class ..._Up> | |
| 592 | struct _EnableUTypesCtor : _And< | |
| 593 | _BoolConstant<sizeof...(_Tp) >= 1>, | |
| 594 | _Not<_IsThisTuple<_Up...> >, // extension to allow mis-behaved user constructors | |
| 595 | is_constructible<_Tp, _Up>... | |
| 596 | > { }; | |
| 597 | ||
| 598 | template <class ..._Up, _EnableIf< | |
| 599 | _And< | |
| 600 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 601 | _EnableUTypesCtor<_Up...>, | |
| 602 | is_convertible<_Up, _Tp>... // explicit check | |
| 603 | >::value | |
| 604 | , int> = 0> | |
| 605 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 606 | tuple(_Up&&... __u) | |
| 607 | _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value)) | |
| 608 | : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(), | |
| 794 | 609 | typename __make_tuple_types<tuple, sizeof...(_Up)>::type(), |
| 795 | 610 | typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 796 | 611 | typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 797 | 612 | _VSTD::forward<_Up>(__u)...) {} |
| 798 | 613 | |
| 799 | template <class ..._Up, | |
| 800 | typename enable_if | |
| 801 | < | |
| 802 | _CheckArgsConstructor< | |
| 803 | sizeof...(_Up) <= sizeof...(_Tp) | |
| 804 | && !_PackExpandsToThisTuple<_Up...>::value | |
| 805 | >::template __enable_explicit<_Up...>() || | |
| 806 | _CheckArgsConstructor< | |
| 807 | !_EnableImplicitReducedArityExtension | |
| 808 | && sizeof...(_Up) < sizeof...(_Tp) | |
| 809 | && !_PackExpandsToThisTuple<_Up...>::value | |
| 810 | >::template __enable_implicit<_Up...>(), | |
| 811 | bool | |
| 812 | >::type = false | |
| 813 | > | |
| 814 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 815 | explicit | |
| 816 | tuple(_Up&&... __u) | |
| 817 | _NOEXCEPT_(( | |
| 818 | is_nothrow_constructible<_BaseT, | |
| 819 | typename __make_tuple_indices<sizeof...(_Up)>::type, | |
| 820 | typename __make_tuple_types<tuple, sizeof...(_Up)>::type, | |
| 821 | typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type, | |
| 822 | typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type, | |
| 823 | _Up... | |
| 824 | >::value | |
| 825 | )) | |
| 826 | : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(), | |
| 614 | template <class ..._Up, _EnableIf< | |
| 615 | _And< | |
| 616 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 617 | _EnableUTypesCtor<_Up...>, | |
| 618 | _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check | |
| 619 | >::value | |
| 620 | , int> = 0> | |
| 621 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 622 | explicit tuple(_Up&&... __u) | |
| 623 | _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value)) | |
| 624 | : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(), | |
| 827 | 625 | typename __make_tuple_types<tuple, sizeof...(_Up)>::type(), |
| 828 | 626 | typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 829 | 627 | typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 830 | 628 | _VSTD::forward<_Up>(__u)...) {} |
| 831 | 629 | |
| 832 | template <class _Alloc, class ..._Up, | |
| 833 | typename enable_if | |
| 834 | < | |
| 835 | _CheckArgsConstructor< | |
| 836 | sizeof...(_Up) == sizeof...(_Tp) && | |
| 837 | !_PackExpandsToThisTuple<_Up...>::value | |
| 838 | >::template __enable_implicit<_Up...>(), | |
| 839 | bool | |
| 840 | >::type = false | |
| 841 | > | |
| 842 | _LIBCPP_INLINE_VISIBILITY | |
| 843 | tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u) | |
| 844 | : __base_(allocator_arg_t(), __a, | |
| 630 | template <class _Alloc, class ..._Up, _EnableIf< | |
| 631 | _And< | |
| 632 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 633 | _EnableUTypesCtor<_Up...>, | |
| 634 | is_convertible<_Up, _Tp>... // explicit check | |
| 635 | >::value | |
| 636 | , int> = 0> | |
| 637 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 638 | tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u) | |
| 639 | : __base_(allocator_arg_t(), __a, | |
| 845 | 640 | typename __make_tuple_indices<sizeof...(_Up)>::type(), |
| 846 | 641 | typename __make_tuple_types<tuple, sizeof...(_Up)>::type(), |
| 847 | 642 | typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 848 | 643 | typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 849 | 644 | _VSTD::forward<_Up>(__u)...) {} |
| 850 | 645 | |
| 851 | template <class _Alloc, class ..._Up, | |
| 852 | typename enable_if | |
| 853 | < | |
| 854 | _CheckArgsConstructor< | |
| 855 | sizeof...(_Up) == sizeof...(_Tp) && | |
| 856 | !_PackExpandsToThisTuple<_Up...>::value | |
| 857 | >::template __enable_explicit<_Up...>(), | |
| 858 | bool | |
| 859 | >::type = false | |
| 860 | > | |
| 861 | _LIBCPP_INLINE_VISIBILITY | |
| 862 | explicit | |
| 863 | tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u) | |
| 864 | : __base_(allocator_arg_t(), __a, | |
| 646 | template <class _Alloc, class ..._Up, _EnableIf< | |
| 647 | _And< | |
| 648 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 649 | _EnableUTypesCtor<_Up...>, | |
| 650 | _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check | |
| 651 | >::value | |
| 652 | , int> = 0> | |
| 653 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 654 | explicit tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u) | |
| 655 | : __base_(allocator_arg_t(), __a, | |
| 865 | 656 | typename __make_tuple_indices<sizeof...(_Up)>::type(), |
| 866 | 657 | typename __make_tuple_types<tuple, sizeof...(_Up)>::type(), |
| 867 | 658 | typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 868 | 659 | typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(), |
| 869 | 660 | _VSTD::forward<_Up>(__u)...) {} |
| 870 | 661 | |
| 871 | template <class _Tuple, _EnableImplicitTupleLikeConstructor<_Tuple, true> = false> | |
| 872 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 873 | tuple(_Tuple&& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, _Tuple>::value)) | |
| 874 | : __base_(_VSTD::forward<_Tuple>(__t)) {} | |
| 662 | // Copy and move constructors (including the allocator_arg_t variants) | |
| 663 | tuple(const tuple&) = default; | |
| 664 | tuple(tuple&&) = default; | |
| 875 | 665 | |
| 876 | template <class _Tuple, _EnableImplicitTupleLikeConstructor<const _Tuple&, false> = false> | |
| 877 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 878 | tuple(const _Tuple& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, const _Tuple&>::value)) | |
| 879 | : __base_(__t) {} | |
| 880 | template <class _Tuple, _EnableExplicitTupleLikeConstructor<_Tuple, true> = false> | |
| 881 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 882 | explicit | |
| 883 | tuple(_Tuple&& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, _Tuple>::value)) | |
| 884 | : __base_(_VSTD::forward<_Tuple>(__t)) {} | |
| 666 | template <class _Alloc, template<class...> class _And = _And, _EnableIf< | |
| 667 | _And<is_copy_constructible<_Tp>...>::value | |
| 668 | , int> = 0> | |
| 669 | tuple(allocator_arg_t, const _Alloc& __alloc, const tuple& __t) | |
| 670 | : __base_(allocator_arg_t(), __alloc, __t) | |
| 671 | { } | |
| 672 | ||
| 673 | template <class _Alloc, template<class...> class _And = _And, _EnableIf< | |
| 674 | _And<is_move_constructible<_Tp>...>::value | |
| 675 | , int> = 0> | |
| 676 | tuple(allocator_arg_t, const _Alloc& __alloc, tuple&& __t) | |
| 677 | : __base_(allocator_arg_t(), __alloc, _VSTD::move(__t)) | |
| 678 | { } | |
| 679 | ||
| 680 | // tuple(const tuple<U...>&) constructors (including allocator_arg_t variants) | |
| 681 | template <class ..._Up> | |
| 682 | struct _EnableCopyFromOtherTuple : _And< | |
| 683 | _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >, | |
| 684 | _Lazy<_Or, | |
| 685 | _BoolConstant<sizeof...(_Tp) != 1>, | |
| 686 | // _Tp and _Up are 1-element packs - the pack expansions look | |
| 687 | // weird to avoid tripping up the type traits in degenerate cases | |
| 688 | _Lazy<_And, | |
| 689 | _Not<is_convertible<const tuple<_Up>&, _Tp> >..., | |
| 690 | _Not<is_constructible<_Tp, const tuple<_Up>&> >... | |
| 691 | > | |
| 692 | >, | |
| 693 | is_constructible<_Tp, const _Up&>... | |
| 694 | > { }; | |
| 695 | ||
| 696 | template <class ..._Up, _EnableIf< | |
| 697 | _And< | |
| 698 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 699 | _EnableCopyFromOtherTuple<_Up...>, | |
| 700 | is_convertible<const _Up&, _Tp>... // explicit check | |
| 701 | >::value | |
| 702 | , int> = 0> | |
| 703 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 704 | tuple(const tuple<_Up...>& __t) | |
| 705 | _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, const _Up&>...>::value)) | |
| 706 | : __base_(__t) | |
| 707 | { } | |
| 708 | ||
| 709 | template <class ..._Up, _EnableIf< | |
| 710 | _And< | |
| 711 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 712 | _EnableCopyFromOtherTuple<_Up...>, | |
| 713 | _Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> > // explicit check | |
| 714 | >::value | |
| 715 | , int> = 0> | |
| 716 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 717 | explicit tuple(const tuple<_Up...>& __t) | |
| 718 | _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, const _Up&>...>::value)) | |
| 719 | : __base_(__t) | |
| 720 | { } | |
| 721 | ||
| 722 | template <class ..._Up, class _Alloc, _EnableIf< | |
| 723 | _And< | |
| 724 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 725 | _EnableCopyFromOtherTuple<_Up...>, | |
| 726 | is_convertible<const _Up&, _Tp>... // explicit check | |
| 727 | >::value | |
| 728 | , int> = 0> | |
| 729 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 730 | tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t) | |
| 731 | : __base_(allocator_arg_t(), __a, __t) | |
| 732 | { } | |
| 733 | ||
| 734 | template <class ..._Up, class _Alloc, _EnableIf< | |
| 735 | _And< | |
| 736 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 737 | _EnableCopyFromOtherTuple<_Up...>, | |
| 738 | _Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> > // explicit check | |
| 739 | >::value | |
| 740 | , int> = 0> | |
| 741 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 742 | explicit tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t) | |
| 743 | : __base_(allocator_arg_t(), __a, __t) | |
| 744 | { } | |
| 745 | ||
| 746 | // tuple(tuple<U...>&&) constructors (including allocator_arg_t variants) | |
| 747 | template <class ..._Up> | |
| 748 | struct _EnableMoveFromOtherTuple : _And< | |
| 749 | _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >, | |
| 750 | _Lazy<_Or, | |
| 751 | _BoolConstant<sizeof...(_Tp) != 1>, | |
| 752 | // _Tp and _Up are 1-element packs - the pack expansions look | |
| 753 | // weird to avoid tripping up the type traits in degenerate cases | |
| 754 | _Lazy<_And, | |
| 755 | _Not<is_convertible<tuple<_Up>, _Tp> >..., | |
| 756 | _Not<is_constructible<_Tp, tuple<_Up> > >... | |
| 757 | > | |
| 758 | >, | |
| 759 | is_constructible<_Tp, _Up>... | |
| 760 | > { }; | |
| 761 | ||
| 762 | template <class ..._Up, _EnableIf< | |
| 763 | _And< | |
| 764 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 765 | _EnableMoveFromOtherTuple<_Up...>, | |
| 766 | is_convertible<_Up, _Tp>... // explicit check | |
| 767 | >::value | |
| 768 | , int> = 0> | |
| 769 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 770 | tuple(tuple<_Up...>&& __t) | |
| 771 | _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value)) | |
| 772 | : __base_(_VSTD::move(__t)) | |
| 773 | { } | |
| 774 | ||
| 775 | template <class ..._Up, _EnableIf< | |
| 776 | _And< | |
| 777 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 778 | _EnableMoveFromOtherTuple<_Up...>, | |
| 779 | _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check | |
| 780 | >::value | |
| 781 | , int> = 0> | |
| 782 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 783 | explicit tuple(tuple<_Up...>&& __t) | |
| 784 | _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value)) | |
| 785 | : __base_(_VSTD::move(__t)) | |
| 786 | { } | |
| 787 | ||
| 788 | template <class _Alloc, class ..._Up, _EnableIf< | |
| 789 | _And< | |
| 790 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 791 | _EnableMoveFromOtherTuple<_Up...>, | |
| 792 | is_convertible<_Up, _Tp>... // explicit check | |
| 793 | >::value | |
| 794 | , int> = 0> | |
| 795 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 796 | tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t) | |
| 797 | : __base_(allocator_arg_t(), __a, _VSTD::move(__t)) | |
| 798 | { } | |
| 799 | ||
| 800 | template <class _Alloc, class ..._Up, _EnableIf< | |
| 801 | _And< | |
| 802 | _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, | |
| 803 | _EnableMoveFromOtherTuple<_Up...>, | |
| 804 | _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check | |
| 805 | >::value | |
| 806 | , int> = 0> | |
| 807 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 808 | explicit tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t) | |
| 809 | : __base_(allocator_arg_t(), __a, _VSTD::move(__t)) | |
| 810 | { } | |
| 811 | ||
| 812 | // tuple(const pair<U1, U2>&) constructors (including allocator_arg_t variants) | |
| 813 | template <class _Up1, class _Up2, class ..._DependentTp> | |
| 814 | struct _EnableImplicitCopyFromPair : _And< | |
| 815 | is_constructible<_FirstType<_DependentTp...>, const _Up1&>, | |
| 816 | is_constructible<_SecondType<_DependentTp...>, const _Up2&>, | |
| 817 | is_convertible<const _Up1&, _FirstType<_DependentTp...> >, // explicit check | |
| 818 | is_convertible<const _Up2&, _SecondType<_DependentTp...> > | |
| 819 | > { }; | |
| 820 | ||
| 821 | template <class _Up1, class _Up2, class ..._DependentTp> | |
| 822 | struct _EnableExplicitCopyFromPair : _And< | |
| 823 | is_constructible<_FirstType<_DependentTp...>, const _Up1&>, | |
| 824 | is_constructible<_SecondType<_DependentTp...>, const _Up2&>, | |
| 825 | _Not<is_convertible<const _Up1&, _FirstType<_DependentTp...> > >, // explicit check | |
| 826 | _Not<is_convertible<const _Up2&, _SecondType<_DependentTp...> > > | |
| 827 | > { }; | |
| 828 | ||
| 829 | template <class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 830 | _And< | |
| 831 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 832 | _EnableImplicitCopyFromPair<_Up1, _Up2, _Tp...> | |
| 833 | >::value | |
| 834 | , int> = 0> | |
| 835 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 836 | tuple(const pair<_Up1, _Up2>& __p) | |
| 837 | _NOEXCEPT_((_And< | |
| 838 | is_nothrow_constructible<_FirstType<_Tp...>, const _Up1&>, | |
| 839 | is_nothrow_constructible<_SecondType<_Tp...>, const _Up2&> | |
| 840 | >::value)) | |
| 841 | : __base_(__p) | |
| 842 | { } | |
| 843 | ||
| 844 | template <class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 845 | _And< | |
| 846 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 847 | _EnableExplicitCopyFromPair<_Up1, _Up2, _Tp...> | |
| 848 | >::value | |
| 849 | , int> = 0> | |
| 850 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 851 | explicit tuple(const pair<_Up1, _Up2>& __p) | |
| 852 | _NOEXCEPT_((_And< | |
| 853 | is_nothrow_constructible<_FirstType<_Tp...>, const _Up1&>, | |
| 854 | is_nothrow_constructible<_SecondType<_Tp...>, const _Up2&> | |
| 855 | >::value)) | |
| 856 | : __base_(__p) | |
| 857 | { } | |
| 858 | ||
| 859 | template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 860 | _And< | |
| 861 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 862 | _EnableImplicitCopyFromPair<_Up1, _Up2, _Tp...> | |
| 863 | >::value | |
| 864 | , int> = 0> | |
| 865 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 866 | tuple(allocator_arg_t, const _Alloc& __a, const pair<_Up1, _Up2>& __p) | |
| 867 | : __base_(allocator_arg_t(), __a, __p) | |
| 868 | { } | |
| 869 | ||
| 870 | template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 871 | _And< | |
| 872 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 873 | _EnableExplicitCopyFromPair<_Up1, _Up2, _Tp...> | |
| 874 | >::value | |
| 875 | , int> = 0> | |
| 876 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 877 | explicit tuple(allocator_arg_t, const _Alloc& __a, const pair<_Up1, _Up2>& __p) | |
| 878 | : __base_(allocator_arg_t(), __a, __p) | |
| 879 | { } | |
| 880 | ||
| 881 | // tuple(pair<U1, U2>&&) constructors (including allocator_arg_t variants) | |
| 882 | template <class _Up1, class _Up2, class ..._DependentTp> | |
| 883 | struct _EnableImplicitMoveFromPair : _And< | |
| 884 | is_constructible<_FirstType<_DependentTp...>, _Up1>, | |
| 885 | is_constructible<_SecondType<_DependentTp...>, _Up2>, | |
| 886 | is_convertible<_Up1, _FirstType<_DependentTp...> >, // explicit check | |
| 887 | is_convertible<_Up2, _SecondType<_DependentTp...> > | |
| 888 | > { }; | |
| 889 | ||
| 890 | template <class _Up1, class _Up2, class ..._DependentTp> | |
| 891 | struct _EnableExplicitMoveFromPair : _And< | |
| 892 | is_constructible<_FirstType<_DependentTp...>, _Up1>, | |
| 893 | is_constructible<_SecondType<_DependentTp...>, _Up2>, | |
| 894 | _Not<is_convertible<_Up1, _FirstType<_DependentTp...> > >, // explicit check | |
| 895 | _Not<is_convertible<_Up2, _SecondType<_DependentTp...> > > | |
| 896 | > { }; | |
| 897 | ||
| 898 | template <class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 899 | _And< | |
| 900 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 901 | _EnableImplicitMoveFromPair<_Up1, _Up2, _Tp...> | |
| 902 | >::value | |
| 903 | , int> = 0> | |
| 904 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 905 | tuple(pair<_Up1, _Up2>&& __p) | |
| 906 | _NOEXCEPT_((_And< | |
| 907 | is_nothrow_constructible<_FirstType<_Tp...>, _Up1>, | |
| 908 | is_nothrow_constructible<_SecondType<_Tp...>, _Up2> | |
| 909 | >::value)) | |
| 910 | : __base_(_VSTD::move(__p)) | |
| 911 | { } | |
| 912 | ||
| 913 | template <class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 914 | _And< | |
| 915 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 916 | _EnableExplicitMoveFromPair<_Up1, _Up2, _Tp...> | |
| 917 | >::value | |
| 918 | , int> = 0> | |
| 919 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 920 | explicit tuple(pair<_Up1, _Up2>&& __p) | |
| 921 | _NOEXCEPT_((_And< | |
| 922 | is_nothrow_constructible<_FirstType<_Tp...>, _Up1>, | |
| 923 | is_nothrow_constructible<_SecondType<_Tp...>, _Up2> | |
| 924 | >::value)) | |
| 925 | : __base_(_VSTD::move(__p)) | |
| 926 | { } | |
| 927 | ||
| 928 | template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 929 | _And< | |
| 930 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 931 | _EnableImplicitMoveFromPair<_Up1, _Up2, _Tp...> | |
| 932 | >::value | |
| 933 | , int> = 0> | |
| 934 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 935 | tuple(allocator_arg_t, const _Alloc& __a, pair<_Up1, _Up2>&& __p) | |
| 936 | : __base_(allocator_arg_t(), __a, _VSTD::move(__p)) | |
| 937 | { } | |
| 938 | ||
| 939 | template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, _EnableIf< | |
| 940 | _And< | |
| 941 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 942 | _EnableExplicitMoveFromPair<_Up1, _Up2, _Tp...> | |
| 943 | >::value | |
| 944 | , int> = 0> | |
| 945 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 946 | explicit tuple(allocator_arg_t, const _Alloc& __a, pair<_Up1, _Up2>&& __p) | |
| 947 | : __base_(allocator_arg_t(), __a, _VSTD::move(__p)) | |
| 948 | { } | |
| 949 | ||
| 950 | // [tuple.assign] | |
| 951 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 952 | tuple& operator=(_If<_And<is_copy_assignable<_Tp>...>::value, tuple, __nat> const& __tuple) | |
| 953 | _NOEXCEPT_((_And<is_nothrow_copy_assignable<_Tp>...>::value)) | |
| 954 | { | |
| 955 | _VSTD::__memberwise_copy_assign(*this, __tuple, | |
| 956 | typename __make_tuple_indices<sizeof...(_Tp)>::type()); | |
| 957 | return *this; | |
| 958 | } | |
| 885 | 959 | |
| 886 | template <class _Tuple, _EnableExplicitTupleLikeConstructor<const _Tuple&, false> = false> | |
| 887 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 888 | explicit | |
| 889 | tuple(const _Tuple& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, const _Tuple&>::value)) | |
| 890 | : __base_(__t) {} | |
| 960 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 961 | tuple& operator=(_If<_And<is_move_assignable<_Tp>...>::value, tuple, __nat>&& __tuple) | |
| 962 | _NOEXCEPT_((_And<is_nothrow_move_assignable<_Tp>...>::value)) | |
| 963 | { | |
| 964 | _VSTD::__memberwise_forward_assign(*this, _VSTD::move(__tuple), | |
| 965 | __tuple_types<_Tp...>(), | |
| 966 | typename __make_tuple_indices<sizeof...(_Tp)>::type()); | |
| 967 | return *this; | |
| 968 | } | |
| 891 | 969 | |
| 892 | template <class _Alloc, class _Tuple, | |
| 893 | typename enable_if | |
| 894 | < | |
| 895 | _CheckTupleLikeConstructor< | |
| 896 | __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value | |
| 897 | >::template __enable_implicit<_Tuple>(), | |
| 898 | bool | |
| 899 | >::type = false | |
| 900 | > | |
| 901 | _LIBCPP_INLINE_VISIBILITY | |
| 902 | tuple(allocator_arg_t, const _Alloc& __a, _Tuple&& __t) | |
| 903 | : __base_(allocator_arg_t(), __a, _VSTD::forward<_Tuple>(__t)) {} | |
| 970 | template<class... _Up, _EnableIf< | |
| 971 | _And< | |
| 972 | _BoolConstant<sizeof...(_Tp) == sizeof...(_Up)>, | |
| 973 | is_assignable<_Tp&, _Up const&>... | |
| 974 | >::value | |
| 975 | ,int> = 0> | |
| 976 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 977 | tuple& operator=(tuple<_Up...> const& __tuple) | |
| 978 | _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up const&>...>::value)) | |
| 979 | { | |
| 980 | _VSTD::__memberwise_copy_assign(*this, __tuple, | |
| 981 | typename __make_tuple_indices<sizeof...(_Tp)>::type()); | |
| 982 | return *this; | |
| 983 | } | |
| 904 | 984 | |
| 905 | template <class _Alloc, class _Tuple, | |
| 906 | typename enable_if | |
| 907 | < | |
| 908 | _CheckTupleLikeConstructor< | |
| 909 | __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value | |
| 910 | >::template __enable_explicit<_Tuple>(), | |
| 911 | bool | |
| 912 | >::type = false | |
| 913 | > | |
| 914 | _LIBCPP_INLINE_VISIBILITY | |
| 915 | explicit | |
| 916 | tuple(allocator_arg_t, const _Alloc& __a, _Tuple&& __t) | |
| 917 | : __base_(allocator_arg_t(), __a, _VSTD::forward<_Tuple>(__t)) {} | |
| 985 | template<class... _Up, _EnableIf< | |
| 986 | _And< | |
| 987 | _BoolConstant<sizeof...(_Tp) == sizeof...(_Up)>, | |
| 988 | is_assignable<_Tp&, _Up>... | |
| 989 | >::value | |
| 990 | ,int> = 0> | |
| 991 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 992 | tuple& operator=(tuple<_Up...>&& __tuple) | |
| 993 | _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up>...>::value)) | |
| 994 | { | |
| 995 | _VSTD::__memberwise_forward_assign(*this, _VSTD::move(__tuple), | |
| 996 | __tuple_types<_Up...>(), | |
| 997 | typename __make_tuple_indices<sizeof...(_Tp)>::type()); | |
| 998 | return *this; | |
| 999 | } | |
| 918 | 1000 | |
| 919 | using _CanCopyAssign = __all<is_copy_assignable<_Tp>::value...>; | |
| 920 | using _CanMoveAssign = __all<is_move_assignable<_Tp>::value...>; | |
| 1001 | template<class _Up1, class _Up2, class _Dep = true_type, _EnableIf< | |
| 1002 | _And<_Dep, | |
| 1003 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 1004 | is_assignable<_FirstType<_Tp..., _Dep>&, _Up1 const&>, | |
| 1005 | is_assignable<_SecondType<_Tp..., _Dep>&, _Up2 const&> | |
| 1006 | >::value | |
| 1007 | ,int> = 0> | |
| 1008 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1009 | tuple& operator=(pair<_Up1, _Up2> const& __pair) | |
| 1010 | _NOEXCEPT_((_And< | |
| 1011 | is_nothrow_assignable<_FirstType<_Tp...>&, _Up1 const&>, | |
| 1012 | is_nothrow_assignable<_SecondType<_Tp...>&, _Up2 const&> | |
| 1013 | >::value)) | |
| 1014 | { | |
| 1015 | _VSTD::get<0>(*this) = __pair.first; | |
| 1016 | _VSTD::get<1>(*this) = __pair.second; | |
| 1017 | return *this; | |
| 1018 | } | |
| 921 | 1019 | |
| 922 | _LIBCPP_INLINE_VISIBILITY | |
| 923 | tuple& operator=(typename conditional<_CanCopyAssign::value, tuple, __nat>::type const& __t) | |
| 924 | _NOEXCEPT_((__all<is_nothrow_copy_assignable<_Tp>::value...>::value)) | |
| 1020 | template<class _Up1, class _Up2, class _Dep = true_type, _EnableIf< | |
| 1021 | _And<_Dep, | |
| 1022 | _BoolConstant<sizeof...(_Tp) == 2>, | |
| 1023 | is_assignable<_FirstType<_Tp..., _Dep>&, _Up1>, | |
| 1024 | is_assignable<_SecondType<_Tp..., _Dep>&, _Up2> | |
| 1025 | >::value | |
| 1026 | ,int> = 0> | |
| 1027 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1028 | tuple& operator=(pair<_Up1, _Up2>&& __pair) | |
| 1029 | _NOEXCEPT_((_And< | |
| 1030 | is_nothrow_assignable<_FirstType<_Tp...>&, _Up1>, | |
| 1031 | is_nothrow_assignable<_SecondType<_Tp...>&, _Up2> | |
| 1032 | >::value)) | |
| 925 | 1033 | { |
| 926 | __base_.operator=(__t.__base_); | |
| 1034 | _VSTD::get<0>(*this) = _VSTD::forward<_Up1>(__pair.first); | |
| 1035 | _VSTD::get<1>(*this) = _VSTD::forward<_Up2>(__pair.second); | |
| 927 | 1036 | return *this; |
| 928 | 1037 | } |
| 929 | 1038 | |
| 930 | _LIBCPP_INLINE_VISIBILITY | |
| 931 | tuple& operator=(typename conditional<_CanMoveAssign::value, tuple, __nat>::type&& __t) | |
| 932 | _NOEXCEPT_((__all<is_nothrow_move_assignable<_Tp>::value...>::value)) | |
| 1039 | // EXTENSION | |
| 1040 | template<class _Up, size_t _Np, class = _EnableIf< | |
| 1041 | _And< | |
| 1042 | _BoolConstant<_Np == sizeof...(_Tp)>, | |
| 1043 | is_assignable<_Tp&, _Up const&>... | |
| 1044 | >::value | |
| 1045 | > > | |
| 1046 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1047 | tuple& operator=(array<_Up, _Np> const& __array) | |
| 1048 | _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up const&>...>::value)) | |
| 933 | 1049 | { |
| 934 | __base_.operator=(static_cast<_BaseT&&>(__t.__base_)); | |
| 1050 | _VSTD::__memberwise_copy_assign(*this, __array, | |
| 1051 | typename __make_tuple_indices<sizeof...(_Tp)>::type()); | |
| 935 | 1052 | return *this; |
| 936 | 1053 | } |
| 937 | 1054 | |
| 938 | template <class _Tuple, | |
| 939 | class = typename enable_if | |
| 940 | < | |
| 941 | __tuple_assignable<_Tuple, tuple>::value | |
| 942 | >::type | |
| 943 | > | |
| 944 | _LIBCPP_INLINE_VISIBILITY | |
| 945 | tuple& | |
| 946 | operator=(_Tuple&& __t) _NOEXCEPT_((is_nothrow_assignable<_BaseT&, _Tuple>::value)) | |
| 947 | { | |
| 948 | __base_.operator=(_VSTD::forward<_Tuple>(__t)); | |
| 949 | return *this; | |
| 950 | } | |
| 1055 | // EXTENSION | |
| 1056 | template<class _Up, size_t _Np, class = void, class = _EnableIf< | |
| 1057 | _And< | |
| 1058 | _BoolConstant<_Np == sizeof...(_Tp)>, | |
| 1059 | is_assignable<_Tp&, _Up>... | |
| 1060 | >::value | |
| 1061 | > > | |
| 1062 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 1063 | tuple& operator=(array<_Up, _Np>&& __array) | |
| 1064 | _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up>...>::value)) | |
| 1065 | { | |
| 1066 | _VSTD::__memberwise_forward_assign(*this, _VSTD::move(__array), | |
| 1067 | __tuple_types<_If<true, _Up, _Tp>...>(), | |
| 1068 | typename __make_tuple_indices<sizeof...(_Tp)>::type()); | |
| 1069 | return *this; | |
| 1070 | } | |
| 951 | 1071 | |
| 952 | _LIBCPP_INLINE_VISIBILITY | |
| 1072 | // [tuple.swap] | |
| 1073 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 953 | 1074 | void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value) |
| 954 | 1075 | {__base_.swap(__t.__base_);} |
| 955 | 1076 | }; |
| ... | ... | @@ -958,21 +1079,21 @@ template <> |
| 958 | 1079 | class _LIBCPP_TEMPLATE_VIS tuple<> |
| 959 | 1080 | { |
| 960 | 1081 | public: |
| 961 | _LIBCPP_INLINE_VISIBILITY | |
| 962 | _LIBCPP_CONSTEXPR tuple() _NOEXCEPT = default; | |
| 1082 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 1083 | tuple() _NOEXCEPT = default; | |
| 963 | 1084 | template <class _Alloc> |
| 964 | _LIBCPP_INLINE_VISIBILITY | |
| 1085 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 965 | 1086 | tuple(allocator_arg_t, const _Alloc&) _NOEXCEPT {} |
| 966 | 1087 | template <class _Alloc> |
| 967 | _LIBCPP_INLINE_VISIBILITY | |
| 1088 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 968 | 1089 | tuple(allocator_arg_t, const _Alloc&, const tuple&) _NOEXCEPT {} |
| 969 | 1090 | template <class _Up> |
| 970 | _LIBCPP_INLINE_VISIBILITY | |
| 1091 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 971 | 1092 | tuple(array<_Up, 0>) _NOEXCEPT {} |
| 972 | 1093 | template <class _Alloc, class _Up> |
| 973 | _LIBCPP_INLINE_VISIBILITY | |
| 1094 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 974 | 1095 | tuple(allocator_arg_t, const _Alloc&, array<_Up, 0>) _NOEXCEPT {} |
| 975 | _LIBCPP_INLINE_VISIBILITY | |
| 1096 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 976 | 1097 | void swap(tuple&) _NOEXCEPT {} |
| 977 | 1098 | }; |
| 978 | 1099 | |
| ... | ... | @@ -990,7 +1111,7 @@ tuple(allocator_arg_t, _Alloc, tuple<_Tp...>) -> tuple<_Tp...>; |
| 990 | 1111 | #endif |
| 991 | 1112 | |
| 992 | 1113 | template <class ..._Tp> |
| 993 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1114 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 994 | 1115 | typename enable_if |
| 995 | 1116 | < |
| 996 | 1117 | __all<__is_swappable<_Tp>::value...>::value, |
| ... | ... | @@ -1044,7 +1165,7 @@ get(const tuple<_Tp...>&& __t) _NOEXCEPT |
| 1044 | 1165 | |
| 1045 | 1166 | namespace __find_detail { |
| 1046 | 1167 | |
| 1047 | static constexpr size_t __not_found = -1; | |
| 1168 | static constexpr size_t __not_found = static_cast<size_t>(-1); | |
| 1048 | 1169 | static constexpr size_t __ambiguous = __not_found - 1; |
| 1049 | 1170 | |
| 1050 | 1171 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1450,4 +1571,4 @@ _LIBCPP_NOEXCEPT_RETURN( |
| 1450 | 1571 | |
| 1451 | 1572 | _LIBCPP_END_NAMESPACE_STD |
| 1452 | 1573 | |
| 1453 | #endif // _LIBCPP_TUPLE | |
| 1574 | #endif // _LIBCPP_TUPLE |
lib/libcxx/include/type_traits+372-176| ... | ... | @@ -99,7 +99,7 @@ namespace std |
| 99 | 99 | template <class T> struct is_trivial; |
| 100 | 100 | template <class T> struct is_trivially_copyable; |
| 101 | 101 | template <class T> struct is_standard_layout; |
| 102 | template <class T> struct is_literal_type; | |
| 102 | template <class T> struct is_literal_type; // Deprecated in C++17; removed in C++20 | |
| 103 | 103 | template <class T> struct is_empty; |
| 104 | 104 | template <class T> struct is_polymorphic; |
| 105 | 105 | template <class T> struct is_abstract; |
| ... | ... | @@ -165,8 +165,8 @@ namespace std |
| 165 | 165 | template <class T> struct decay; |
| 166 | 166 | template <class... T> struct common_type; |
| 167 | 167 | template <class T> struct underlying_type; |
| 168 | template <class> class result_of; // undefined | |
| 169 | template <class Fn, class... ArgTypes> class result_of<Fn(ArgTypes...)>; | |
| 168 | template <class> class result_of; // undefined; deprecated in C++17; removed in C++20 | |
| 169 | template <class Fn, class... ArgTypes> class result_of<Fn(ArgTypes...)>; // deprecated in C++17; removed in C++20 | |
| 170 | 170 | template <class Fn, class... ArgTypes> struct invoke_result; // C++17 |
| 171 | 171 | |
| 172 | 172 | // const-volatile modifications: |
| ... | ... | @@ -216,9 +216,9 @@ namespace std |
| 216 | 216 | using add_pointer_t = typename add_pointer<T>::type; // C++14 |
| 217 | 217 | |
| 218 | 218 | // other transformations: |
| 219 | template <size_t Len, std::size_t Align=default-alignment> | |
| 219 | template <size_t Len, size_t Align=default-alignment> | |
| 220 | 220 | using aligned_storage_t = typename aligned_storage<Len,Align>::type; // C++14 |
| 221 | template <std::size_t Len, class... Types> | |
| 221 | template <size_t Len, class... Types> | |
| 222 | 222 | using aligned_union_t = typename aligned_union<Len,Types...>::type; // C++14 |
| 223 | 223 | template <class T> |
| 224 | 224 | using remove_cvref_t = typename remove_cvref<T>::type; // C++20 |
| ... | ... | @@ -233,7 +233,7 @@ namespace std |
| 233 | 233 | template <class T> |
| 234 | 234 | using underlying_type_t = typename underlying_type<T>::type; // C++14 |
| 235 | 235 | template <class T> |
| 236 | using result_of_t = typename result_of<T>::type; // C++14 | |
| 236 | using result_of_t = typename result_of<T>::type; // C++14; deprecated in C++17; removed in C++20 | |
| 237 | 237 | template <class Fn, class... ArgTypes> |
| 238 | 238 | using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type; // C++17 |
| 239 | 239 | |
| ... | ... | @@ -302,7 +302,7 @@ namespace std |
| 302 | 302 | template <class T> inline constexpr bool is_pod_v |
| 303 | 303 | = is_pod<T>::value; // C++17 |
| 304 | 304 | template <class T> inline constexpr bool is_literal_type_v |
| 305 | = is_literal_type<T>::value; // C++17 | |
| 305 | = is_literal_type<T>::value; // C++17; deprecated in C++17; removed in C++20 | |
| 306 | 306 | template <class T> inline constexpr bool is_empty_v |
| 307 | 307 | = is_empty<T>::value; // C++17 |
| 308 | 308 | template <class T> inline constexpr bool is_polymorphic_v |
| ... | ... | @@ -476,8 +476,6 @@ struct _MetaBase<true> { |
| 476 | 476 | using _EnableIfImpl _LIBCPP_NODEBUG_TYPE = _Tp; |
| 477 | 477 | template <class _Result, class _First, class ..._Rest> |
| 478 | 478 | using _OrImpl _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_First::value != true && sizeof...(_Rest) != 0>::template _OrImpl<_First, _Rest...>; |
| 479 | template <class _Result, class _First, class ..._Rest> | |
| 480 | using _AndImpl _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_First::value == true && sizeof...(_Rest) != 0>::template _AndImpl<_First, _Rest...>; | |
| 481 | 479 | }; |
| 482 | 480 | |
| 483 | 481 | template <> |
| ... | ... | @@ -488,8 +486,6 @@ struct _MetaBase<false> { |
| 488 | 486 | using _SelectApplyImpl _LIBCPP_NODEBUG_TYPE = _SecondFn<_Args...>; |
| 489 | 487 | template <class _Result, class ...> |
| 490 | 488 | using _OrImpl _LIBCPP_NODEBUG_TYPE = _Result; |
| 491 | template <class _Result, class ...> | |
| 492 | using _AndImpl _LIBCPP_NODEBUG_TYPE = _Result; | |
| 493 | 489 | }; |
| 494 | 490 | template <bool _Cond, class _Ret = void> |
| 495 | 491 | using _EnableIf _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_Cond>::template _EnableIfImpl<_Ret>; |
| ... | ... | @@ -497,8 +493,6 @@ template <bool _Cond, class _IfRes, class _ElseRes> |
| 497 | 493 | using _If _LIBCPP_NODEBUG_TYPE = typename _MetaBase<_Cond>::template _SelectImpl<_IfRes, _ElseRes>; |
| 498 | 494 | template <class ..._Rest> |
| 499 | 495 | using _Or _LIBCPP_NODEBUG_TYPE = typename _MetaBase< sizeof...(_Rest) != 0 >::template _OrImpl<false_type, _Rest...>; |
| 500 | template <class ..._Rest> | |
| 501 | using _And _LIBCPP_NODEBUG_TYPE = typename _MetaBase< sizeof...(_Rest) != 0 >::template _AndImpl<true_type, _Rest...>; | |
| 502 | 496 | template <class _Pred> |
| 503 | 497 | struct _Not : _BoolConstant<!_Pred::value> {}; |
| 504 | 498 | template <class ..._Args> |
| ... | ... | @@ -506,6 +500,14 @@ using _FirstType _LIBCPP_NODEBUG_TYPE = typename _MetaBase<(sizeof...(_Args) >= |
| 506 | 500 | template <class ..._Args> |
| 507 | 501 | using _SecondType _LIBCPP_NODEBUG_TYPE = typename _MetaBase<(sizeof...(_Args) >= 2)>::template _SecondImpl<_Args...>; |
| 508 | 502 | |
| 503 | template <class ...> using __expand_to_true = true_type; | |
| 504 | template <class ..._Pred> | |
| 505 | __expand_to_true<_EnableIf<_Pred::value>...> __and_helper(int); | |
| 506 | template <class ...> | |
| 507 | false_type __and_helper(...); | |
| 508 | template <class ..._Pred> | |
| 509 | using _And _LIBCPP_NODEBUG_TYPE = decltype(__and_helper<_Pred...>(0)); | |
| 510 | ||
| 509 | 511 | template <template <class...> class _Func, class ..._Args> |
| 510 | 512 | struct _Lazy : _Func<_Args...> {}; |
| 511 | 513 | |
| ... | ... | @@ -525,6 +527,9 @@ struct __void_t { typedef void type; }; |
| 525 | 527 | template <class _Tp> |
| 526 | 528 | struct __identity { typedef _Tp type; }; |
| 527 | 529 | |
| 530 | template <class _Tp> | |
| 531 | using __identity_t _LIBCPP_NODEBUG_TYPE = typename __identity<_Tp>::type; | |
| 532 | ||
| 528 | 533 | template <class _Tp, bool> |
| 529 | 534 | struct _LIBCPP_TEMPLATE_VIS __dependent_type : public _Tp {}; |
| 530 | 535 | |
| ... | ... | @@ -575,7 +580,7 @@ using _IsSame = _BoolConstant< |
| 575 | 580 | #ifdef __clang__ |
| 576 | 581 | __is_same(_Tp, _Up) |
| 577 | 582 | #else |
| 578 | _VSTD::is_same<_Tp, _Up>::value | |
| 583 | is_same<_Tp, _Up>::value | |
| 579 | 584 | #endif |
| 580 | 585 | >; |
| 581 | 586 | |
| ... | ... | @@ -584,7 +589,7 @@ using _IsNotSame = _BoolConstant< |
| 584 | 589 | #ifdef __clang__ |
| 585 | 590 | !__is_same(_Tp, _Up) |
| 586 | 591 | #else |
| 587 | !_VSTD::is_same<_Tp, _Up>::value | |
| 592 | !is_same<_Tp, _Up>::value | |
| 588 | 593 | #endif |
| 589 | 594 | >; |
| 590 | 595 | |
| ... | ... | @@ -784,6 +789,33 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_integral_v |
| 784 | 789 | |
| 785 | 790 | #endif // __has_keyword(__is_integral) |
| 786 | 791 | |
| 792 | // __libcpp_is_signed_integer, __libcpp_is_unsigned_integer | |
| 793 | ||
| 794 | // [basic.fundamental] defines five standard signed integer types; | |
| 795 | // __int128_t is an extended signed integer type. | |
| 796 | // The signed and unsigned integer types, plus bool and the | |
| 797 | // five types with "char" in their name, compose the "integral" types. | |
| 798 | ||
| 799 | template <class _Tp> struct __libcpp_is_signed_integer : public false_type {}; | |
| 800 | template <> struct __libcpp_is_signed_integer<signed char> : public true_type {}; | |
| 801 | template <> struct __libcpp_is_signed_integer<signed short> : public true_type {}; | |
| 802 | template <> struct __libcpp_is_signed_integer<signed int> : public true_type {}; | |
| 803 | template <> struct __libcpp_is_signed_integer<signed long> : public true_type {}; | |
| 804 | template <> struct __libcpp_is_signed_integer<signed long long> : public true_type {}; | |
| 805 | #ifndef _LIBCPP_HAS_NO_INT128 | |
| 806 | template <> struct __libcpp_is_signed_integer<__int128_t> : public true_type {}; | |
| 807 | #endif | |
| 808 | ||
| 809 | template <class _Tp> struct __libcpp_is_unsigned_integer : public false_type {}; | |
| 810 | template <> struct __libcpp_is_unsigned_integer<unsigned char> : public true_type {}; | |
| 811 | template <> struct __libcpp_is_unsigned_integer<unsigned short> : public true_type {}; | |
| 812 | template <> struct __libcpp_is_unsigned_integer<unsigned int> : public true_type {}; | |
| 813 | template <> struct __libcpp_is_unsigned_integer<unsigned long> : public true_type {}; | |
| 814 | template <> struct __libcpp_is_unsigned_integer<unsigned long long> : public true_type {}; | |
| 815 | #ifndef _LIBCPP_HAS_NO_INT128 | |
| 816 | template <> struct __libcpp_is_unsigned_integer<__uint128_t> : public true_type {}; | |
| 817 | #endif | |
| 818 | ||
| 787 | 819 | // is_floating_point |
| 788 | 820 | |
| 789 | 821 | template <class _Tp> struct __libcpp_is_floating_point : public false_type {}; |
| ... | ... | @@ -831,8 +863,10 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_array_v |
| 831 | 863 | |
| 832 | 864 | // is_pointer |
| 833 | 865 | |
| 834 | // In clang 10.0.0 and earlier __is_pointer didn't work with Objective-C types. | |
| 835 | #if __has_keyword(__is_pointer) && _LIBCPP_CLANG_VER > 1000 | |
| 866 | // Before Clang 11 / AppleClang 12.0.5, __is_pointer didn't work for Objective-C types. | |
| 867 | #if __has_keyword(__is_pointer) && \ | |
| 868 | !(defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1100) && \ | |
| 869 | !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1205) | |
| 836 | 870 | |
| 837 | 871 | template<class _Tp> |
| 838 | 872 | struct _LIBCPP_TEMPLATE_VIS is_pointer : _BoolConstant<__is_pointer(_Tp)> { }; |
| ... | ... | @@ -1126,9 +1160,11 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_arithmetic_v |
| 1126 | 1160 | |
| 1127 | 1161 | // is_fundamental |
| 1128 | 1162 | |
| 1129 | // In clang 9 and lower, this builtin did not work for nullptr_t. Additionally, in C++03 mode, | |
| 1130 | // nullptr isn't defined by the compiler so, this builtin won't work. | |
| 1131 | #if __has_keyword(__is_fundamental) && _LIBCPP_CLANG_VER > 900 && !defined(_LIBCPP_CXX03_LANG) | |
| 1163 | // Before Clang 10, __is_fundamental didn't work for nullptr_t. | |
| 1164 | // In C++03 nullptr_t is library-provided but must still count as "fundamental." | |
| 1165 | #if __has_keyword(__is_fundamental) && \ | |
| 1166 | !(defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1000) && \ | |
| 1167 | !defined(_LIBCPP_CXX03_LANG) | |
| 1132 | 1168 | |
| 1133 | 1169 | template<class _Tp> |
| 1134 | 1170 | struct _LIBCPP_TEMPLATE_VIS is_fundamental : _BoolConstant<__is_fundamental(_Tp)> { }; |
| ... | ... | @@ -1155,7 +1191,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_fundamental_v |
| 1155 | 1191 | |
| 1156 | 1192 | // is_scalar |
| 1157 | 1193 | |
| 1158 | // >= 11 because in C++03 nullptr isn't actually nullptr | |
| 1194 | // In C++03 nullptr_t is library-provided but must still count as "scalar." | |
| 1159 | 1195 | #if __has_keyword(__is_scalar) && !defined(_LIBCPP_CXX03_LANG) |
| 1160 | 1196 | |
| 1161 | 1197 | template<class _Tp> |
| ... | ... | @@ -1335,7 +1371,7 @@ template <class _Tp> _Tp __declval(long); |
| 1335 | 1371 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 1336 | 1372 | |
| 1337 | 1373 | template <class _Tp> |
| 1338 | decltype(_VSTD::__declval<_Tp>(0)) | |
| 1374 | decltype(__declval<_Tp>(0)) | |
| 1339 | 1375 | declval() _NOEXCEPT; |
| 1340 | 1376 | |
| 1341 | 1377 | // __uncvref |
| ... | ... | @@ -1412,8 +1448,9 @@ template<class _Tp> using type_identity_t = typename type_identity<_Tp>::type; |
| 1412 | 1448 | |
| 1413 | 1449 | // is_signed |
| 1414 | 1450 | |
| 1415 | // In clang 9 and earlier, this builtin did not work for floating points or enums | |
| 1416 | #if __has_keyword(__is_signed) && _LIBCPP_CLANG_VER > 900 | |
| 1451 | // Before Clang 10, __is_signed didn't work for floating-point types or enums. | |
| 1452 | #if __has_keyword(__is_signed) && \ | |
| 1453 | !(defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1000) | |
| 1417 | 1454 | |
| 1418 | 1455 | template<class _Tp> |
| 1419 | 1456 | struct _LIBCPP_TEMPLATE_VIS is_signed : _BoolConstant<__is_signed(_Tp)> { }; |
| ... | ... | @@ -1448,7 +1485,11 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_signed_v |
| 1448 | 1485 | |
| 1449 | 1486 | // is_unsigned |
| 1450 | 1487 | |
| 1451 | #if __has_keyword(__is_unsigned) | |
| 1488 | // Before Clang 13, __is_unsigned returned true for enums with signed underlying type. | |
| 1489 | // No currently-released version of AppleClang contains the fixed intrinsic. | |
| 1490 | #if __has_keyword(__is_unsigned) && \ | |
| 1491 | !(defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1300) && \ | |
| 1492 | !defined(_LIBCPP_APPLE_CLANG_VER) | |
| 1452 | 1493 | |
| 1453 | 1494 | template<class _Tp> |
| 1454 | 1495 | struct _LIBCPP_TEMPLATE_VIS is_unsigned : _BoolConstant<__is_unsigned(_Tp)> { }; |
| ... | ... | @@ -1698,7 +1739,7 @@ struct __is_convertible_test : public false_type {}; |
| 1698 | 1739 | |
| 1699 | 1740 | template <class _From, class _To> |
| 1700 | 1741 | struct __is_convertible_test<_From, _To, |
| 1701 | decltype(_VSTD::__is_convertible_imp::__test_convert<_To>(_VSTD::declval<_From>()))> : public true_type | |
| 1742 | decltype(__is_convertible_imp::__test_convert<_To>(declval<_From>()))> : public true_type | |
| 1702 | 1743 | {}; |
| 1703 | 1744 | |
| 1704 | 1745 | template <class _Tp, bool _IsArray = is_array<_Tp>::value, |
| ... | ... | @@ -1754,7 +1795,7 @@ template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS is_convertible |
| 1754 | 1795 | static const size_t __complete_check2 = __is_convertible_check<_T2>::__v; |
| 1755 | 1796 | }; |
| 1756 | 1797 | |
| 1757 | #endif // __has_feature(is_convertible_to) | |
| 1798 | #endif // __has_feature(is_convertible_to) | |
| 1758 | 1799 | |
| 1759 | 1800 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| 1760 | 1801 | template <class _From, class _To> |
| ... | ... | @@ -1817,7 +1858,7 @@ template <class _Tp> struct __libcpp_empty<_Tp, false> : public false_type {}; |
| 1817 | 1858 | |
| 1818 | 1859 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_empty : public __libcpp_empty<_Tp> {}; |
| 1819 | 1860 | |
| 1820 | #endif // __has_feature(is_empty) | |
| 1861 | #endif // __has_feature(is_empty) | |
| 1821 | 1862 | |
| 1822 | 1863 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| 1823 | 1864 | template <class _Tp> |
| ... | ... | @@ -2297,6 +2338,14 @@ struct _LIBCPP_TEMPLATE_VIS make_unsigned |
| 2297 | 2338 | template <class _Tp> using make_unsigned_t = typename make_unsigned<_Tp>::type; |
| 2298 | 2339 | #endif |
| 2299 | 2340 | |
| 2341 | #ifndef _LIBCPP_CXX03_LANG | |
| 2342 | template <class _Tp> | |
| 2343 | _LIBCPP_NODISCARD_ATTRIBUTE _LIBCPP_INLINE_VISIBILITY constexpr | |
| 2344 | typename make_unsigned<_Tp>::type __to_unsigned_like(_Tp __x) noexcept { | |
| 2345 | return static_cast<typename make_unsigned<_Tp>::type>(__x); | |
| 2346 | } | |
| 2347 | #endif | |
| 2348 | ||
| 2300 | 2349 | #if _LIBCPP_STD_VER > 14 |
| 2301 | 2350 | template <class...> using void_t = void; |
| 2302 | 2351 | #endif |
| ... | ... | @@ -2304,7 +2353,7 @@ template <class...> using void_t = void; |
| 2304 | 2353 | #if _LIBCPP_STD_VER > 17 |
| 2305 | 2354 | // Let COND_RES(X, Y) be: |
| 2306 | 2355 | template <class _Tp, class _Up> |
| 2307 | using __cond_type = decltype(false ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()); | |
| 2356 | using __cond_type = decltype(false ? declval<_Tp>() : declval<_Up>()); | |
| 2308 | 2357 | |
| 2309 | 2358 | template <class _Tp, class _Up, class = void> |
| 2310 | 2359 | struct __common_type3 {}; |
| ... | ... | @@ -2327,11 +2376,11 @@ struct __common_type2_imp {}; |
| 2327 | 2376 | template <class _Tp, class _Up> |
| 2328 | 2377 | struct __common_type2_imp<_Tp, _Up, |
| 2329 | 2378 | typename __void_t<decltype( |
| 2330 | true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>() | |
| 2379 | true ? declval<_Tp>() : declval<_Up>() | |
| 2331 | 2380 | )>::type> |
| 2332 | 2381 | { |
| 2333 | 2382 | typedef _LIBCPP_NODEBUG_TYPE typename decay<decltype( |
| 2334 | true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>() | |
| 2383 | true ? declval<_Tp>() : declval<_Up>() | |
| 2335 | 2384 | )>::type type; |
| 2336 | 2385 | }; |
| 2337 | 2386 | |
| ... | ... | @@ -2411,6 +2460,216 @@ struct _LIBCPP_TEMPLATE_VIS |
| 2411 | 2460 | template <class ..._Tp> using common_type_t = typename common_type<_Tp...>::type; |
| 2412 | 2461 | #endif |
| 2413 | 2462 | |
| 2463 | #if _LIBCPP_STD_VER > 11 | |
| 2464 | // Let COPYCV(FROM, TO) be an alias for type TO with the addition of FROM's | |
| 2465 | // top-level cv-qualifiers. | |
| 2466 | template <class _From, class _To> | |
| 2467 | struct __copy_cv | |
| 2468 | { | |
| 2469 | using type = _To; | |
| 2470 | }; | |
| 2471 | ||
| 2472 | template <class _From, class _To> | |
| 2473 | struct __copy_cv<const _From, _To> | |
| 2474 | { | |
| 2475 | using type = add_const_t<_To>; | |
| 2476 | }; | |
| 2477 | ||
| 2478 | template <class _From, class _To> | |
| 2479 | struct __copy_cv<volatile _From, _To> | |
| 2480 | { | |
| 2481 | using type = add_volatile_t<_To>; | |
| 2482 | }; | |
| 2483 | ||
| 2484 | template <class _From, class _To> | |
| 2485 | struct __copy_cv<const volatile _From, _To> | |
| 2486 | { | |
| 2487 | using type = add_cv_t<_To>; | |
| 2488 | }; | |
| 2489 | ||
| 2490 | template <class _From, class _To> | |
| 2491 | using __copy_cv_t = typename __copy_cv<_From, _To>::type; | |
| 2492 | ||
| 2493 | template <class _From, class _To> | |
| 2494 | struct __copy_cvref | |
| 2495 | { | |
| 2496 | using type = __copy_cv_t<_From, _To>; | |
| 2497 | }; | |
| 2498 | ||
| 2499 | template <class _From, class _To> | |
| 2500 | struct __copy_cvref<_From&, _To> | |
| 2501 | { | |
| 2502 | using type = add_lvalue_reference_t<__copy_cv_t<_From, _To>>; | |
| 2503 | }; | |
| 2504 | ||
| 2505 | template <class _From, class _To> | |
| 2506 | struct __copy_cvref<_From&&, _To> | |
| 2507 | { | |
| 2508 | using type = add_rvalue_reference_t<__copy_cv_t<_From, _To>>; | |
| 2509 | }; | |
| 2510 | ||
| 2511 | template <class _From, class _To> | |
| 2512 | using __copy_cvref_t = typename __copy_cvref<_From, _To>::type; | |
| 2513 | ||
| 2514 | #endif // _LIBCPP_STD_VER > 11 | |
| 2515 | ||
| 2516 | // common_reference | |
| 2517 | #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 2518 | // Let COND_RES(X, Y) be: | |
| 2519 | template <class _Xp, class _Yp> | |
| 2520 | using __cond_res = | |
| 2521 | decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()()); | |
| 2522 | ||
| 2523 | // Let `XREF(A)` denote a unary alias template `T` such that `T<U>` denotes the same type as `U` | |
| 2524 | // with the addition of `A`'s cv and reference qualifiers, for a non-reference cv-unqualified type | |
| 2525 | // `U`. | |
| 2526 | // [Note: `XREF(A)` is `__xref<A>::template __apply`] | |
| 2527 | template <class _Tp> | |
| 2528 | struct __xref { | |
| 2529 | template<class _Up> | |
| 2530 | using __apply = __copy_cvref_t<_Tp, _Up>; | |
| 2531 | }; | |
| 2532 | ||
| 2533 | // Given types A and B, let X be remove_reference_t<A>, let Y be remove_reference_t<B>, | |
| 2534 | // and let COMMON-REF(A, B) be: | |
| 2535 | template<class _Ap, class _Bp, class _Xp = remove_reference_t<_Ap>, class _Yp = remove_reference_t<_Bp>> | |
| 2536 | struct __common_ref; | |
| 2537 | ||
| 2538 | template<class _Xp, class _Yp> | |
| 2539 | using __common_ref_t = typename __common_ref<_Xp, _Yp>::__type; | |
| 2540 | ||
| 2541 | template<class _Xp, class _Yp> | |
| 2542 | using __cv_cond_res = __cond_res<__copy_cv_t<_Xp, _Yp>&, __copy_cv_t<_Yp, _Xp>&>; | |
| 2543 | ||
| 2544 | ||
| 2545 | // If A and B are both lvalue reference types, COMMON-REF(A, B) is | |
| 2546 | // COND-RES(COPYCV(X, Y)&, COPYCV(Y, X)&) if that type exists and is a reference type. | |
| 2547 | template<class _Ap, class _Bp, class _Xp, class _Yp> | |
| 2548 | requires requires { typename __cv_cond_res<_Xp, _Yp>; } && is_reference_v<__cv_cond_res<_Xp, _Yp>> | |
| 2549 | struct __common_ref<_Ap&, _Bp&, _Xp, _Yp> | |
| 2550 | { | |
| 2551 | using __type = __cv_cond_res<_Xp, _Yp>; | |
| 2552 | }; | |
| 2553 | ||
| 2554 | // Otherwise, let C be remove_reference_t<COMMON-REF(X&, Y&)>&&. ... | |
| 2555 | template <class _Xp, class _Yp> | |
| 2556 | using __common_ref_C = remove_reference_t<__common_ref_t<_Xp&, _Yp&>>&&; | |
| 2557 | ||
| 2558 | ||
| 2559 | // .... If A and B are both rvalue reference types, C is well-formed, and | |
| 2560 | // is_convertible_v<A, C> && is_convertible_v<B, C> is true, then COMMON-REF(A, B) is C. | |
| 2561 | template<class _Ap, class _Bp, class _Xp, class _Yp> | |
| 2562 | requires | |
| 2563 | requires { typename __common_ref_C<_Xp, _Yp>; } && | |
| 2564 | is_convertible_v<_Ap&&, __common_ref_C<_Xp, _Yp>> && | |
| 2565 | is_convertible_v<_Bp&&, __common_ref_C<_Xp, _Yp>> | |
| 2566 | struct __common_ref<_Ap&&, _Bp&&, _Xp, _Yp> | |
| 2567 | { | |
| 2568 | using __type = __common_ref_C<_Xp, _Yp>; | |
| 2569 | }; | |
| 2570 | ||
| 2571 | // Otherwise, let D be COMMON-REF(const X&, Y&). ... | |
| 2572 | template <class _Tp, class _Up> | |
| 2573 | using __common_ref_D = __common_ref_t<const _Tp&, _Up&>; | |
| 2574 | ||
| 2575 | // ... If A is an rvalue reference and B is an lvalue reference and D is well-formed and | |
| 2576 | // is_convertible_v<A, D> is true, then COMMON-REF(A, B) is D. | |
| 2577 | template<class _Ap, class _Bp, class _Xp, class _Yp> | |
| 2578 | requires requires { typename __common_ref_D<_Xp, _Yp>; } && | |
| 2579 | is_convertible_v<_Ap&&, __common_ref_D<_Xp, _Yp>> | |
| 2580 | struct __common_ref<_Ap&&, _Bp&, _Xp, _Yp> | |
| 2581 | { | |
| 2582 | using __type = __common_ref_D<_Xp, _Yp>; | |
| 2583 | }; | |
| 2584 | ||
| 2585 | // Otherwise, if A is an lvalue reference and B is an rvalue reference, then | |
| 2586 | // COMMON-REF(A, B) is COMMON-REF(B, A). | |
| 2587 | template<class _Ap, class _Bp, class _Xp, class _Yp> | |
| 2588 | struct __common_ref<_Ap&, _Bp&&, _Xp, _Yp> : __common_ref<_Bp&&, _Ap&> {}; | |
| 2589 | ||
| 2590 | // Otherwise, COMMON-REF(A, B) is ill-formed. | |
| 2591 | template<class _Ap, class _Bp, class _Xp, class _Yp> | |
| 2592 | struct __common_ref {}; | |
| 2593 | ||
| 2594 | // Note C: For the common_reference trait applied to a parameter pack [...] | |
| 2595 | ||
| 2596 | template <class...> | |
| 2597 | struct common_reference; | |
| 2598 | ||
| 2599 | template <class... _Types> | |
| 2600 | using common_reference_t = typename common_reference<_Types...>::type; | |
| 2601 | ||
| 2602 | // bullet 1 - sizeof...(T) == 0 | |
| 2603 | template<> | |
| 2604 | struct common_reference<> {}; | |
| 2605 | ||
| 2606 | // bullet 2 - sizeof...(T) == 1 | |
| 2607 | template <class _Tp> | |
| 2608 | struct common_reference<_Tp> | |
| 2609 | { | |
| 2610 | using type = _Tp; | |
| 2611 | }; | |
| 2612 | ||
| 2613 | // bullet 3 - sizeof...(T) == 2 | |
| 2614 | template <class _Tp, class _Up> struct __common_reference_sub_bullet3; | |
| 2615 | template <class _Tp, class _Up> struct __common_reference_sub_bullet2 : __common_reference_sub_bullet3<_Tp, _Up> {}; | |
| 2616 | template <class _Tp, class _Up> struct __common_reference_sub_bullet1 : __common_reference_sub_bullet2<_Tp, _Up> {}; | |
| 2617 | ||
| 2618 | // sub-bullet 1 - If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, then | |
| 2619 | // the member typedef `type` denotes that type. | |
| 2620 | template <class _Tp, class _Up> struct common_reference<_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {}; | |
| 2621 | ||
| 2622 | template <class _Tp, class _Up> | |
| 2623 | requires is_reference_v<_Tp> && is_reference_v<_Up> && requires { typename __common_ref_t<_Tp, _Up>; } | |
| 2624 | struct __common_reference_sub_bullet1<_Tp, _Up> | |
| 2625 | { | |
| 2626 | using type = __common_ref_t<_Tp, _Up>; | |
| 2627 | }; | |
| 2628 | ||
| 2629 | // sub-bullet 2 - Otherwise, if basic_common_reference<remove_cvref_t<T1>, remove_cvref_t<T2>, XREF(T1), XREF(T2)>::type | |
| 2630 | // is well-formed, then the member typedef `type` denotes that type. | |
| 2631 | template <class, class, template <class> class, template <class> class> struct basic_common_reference {}; | |
| 2632 | ||
| 2633 | template <class _Tp, class _Up> | |
| 2634 | using __basic_common_reference_t = typename basic_common_reference< | |
| 2635 | remove_cvref_t<_Tp>, remove_cvref_t<_Up>, | |
| 2636 | __xref<_Tp>::template __apply, __xref<_Up>::template __apply>::type; | |
| 2637 | ||
| 2638 | template <class _Tp, class _Up> | |
| 2639 | requires requires { typename __basic_common_reference_t<_Tp, _Up>; } | |
| 2640 | struct __common_reference_sub_bullet2<_Tp, _Up> | |
| 2641 | { | |
| 2642 | using type = __basic_common_reference_t<_Tp, _Up>; | |
| 2643 | }; | |
| 2644 | ||
| 2645 | // sub-bullet 3 - Otherwise, if COND-RES(T1, T2) is well-formed, | |
| 2646 | // then the member typedef `type` denotes that type. | |
| 2647 | template <class _Tp, class _Up> | |
| 2648 | requires requires { typename __cond_res<_Tp, _Up>; } | |
| 2649 | struct __common_reference_sub_bullet3<_Tp, _Up> | |
| 2650 | { | |
| 2651 | using type = __cond_res<_Tp, _Up>; | |
| 2652 | }; | |
| 2653 | ||
| 2654 | ||
| 2655 | // sub-bullet 4 & 5 - Otherwise, if common_type_t<T1, T2> is well-formed, | |
| 2656 | // then the member typedef `type` denotes that type. | |
| 2657 | // - Otherwise, there shall be no member `type`. | |
| 2658 | template <class _Tp, class _Up> struct __common_reference_sub_bullet3 : common_type<_Tp, _Up> {}; | |
| 2659 | ||
| 2660 | // bullet 4 - If there is such a type `C`, the member typedef type shall denote the same type, if | |
| 2661 | // any, as `common_reference_t<C, Rest...>`. | |
| 2662 | template <class _Tp, class _Up, class _Vp, class... _Rest> | |
| 2663 | requires requires { typename common_reference_t<_Tp, _Up>; } | |
| 2664 | struct common_reference<_Tp, _Up, _Vp, _Rest...> | |
| 2665 | : common_reference<common_reference_t<_Tp, _Up>, _Vp, _Rest...> | |
| 2666 | {}; | |
| 2667 | ||
| 2668 | // bullet 5 - Otherwise, there shall be no member `type`. | |
| 2669 | template <class...> struct common_reference {}; | |
| 2670 | ||
| 2671 | #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 2672 | ||
| 2414 | 2673 | // is_assignable |
| 2415 | 2674 | |
| 2416 | 2675 | template<typename, typename _Tp> struct __select_2nd { typedef _LIBCPP_NODEBUG_TYPE _Tp type; }; |
| ... | ... | @@ -2428,7 +2687,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_assignable_v = __is_assignable(_Tp, |
| 2428 | 2687 | #else // __has_keyword(__is_assignable) |
| 2429 | 2688 | |
| 2430 | 2689 | template <class _Tp, class _Arg> |
| 2431 | typename __select_2nd<decltype((_VSTD::declval<_Tp>() = _VSTD::declval<_Arg>())), true_type>::type | |
| 2690 | typename __select_2nd<decltype((declval<_Tp>() = declval<_Arg>())), true_type>::type | |
| 2432 | 2691 | __is_assignable_test(int); |
| 2433 | 2692 | |
| 2434 | 2693 | template <class, class> |
| ... | ... | @@ -2455,7 +2714,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_assignable_v |
| 2455 | 2714 | = is_assignable<_Tp, _Arg>::value; |
| 2456 | 2715 | #endif |
| 2457 | 2716 | |
| 2458 | #endif // __has_keyword(__is_assignable) | |
| 2717 | #endif // __has_keyword(__is_assignable) | |
| 2459 | 2718 | |
| 2460 | 2719 | // is_copy_assignable |
| 2461 | 2720 | |
| ... | ... | @@ -2509,7 +2768,7 @@ template <typename _Tp> |
| 2509 | 2768 | struct __is_destructor_wellformed { |
| 2510 | 2769 | template <typename _Tp1> |
| 2511 | 2770 | static char __test ( |
| 2512 | typename __is_destructible_apply<decltype(_VSTD::declval<_Tp1&>().~_Tp1())>::type | |
| 2771 | typename __is_destructible_apply<decltype(declval<_Tp1&>().~_Tp1())>::type | |
| 2513 | 2772 | ); |
| 2514 | 2773 | |
| 2515 | 2774 | template <typename _Tp1> |
| ... | ... | @@ -2523,33 +2782,33 @@ struct __destructible_imp; |
| 2523 | 2782 | |
| 2524 | 2783 | template <class _Tp> |
| 2525 | 2784 | struct __destructible_imp<_Tp, false> |
| 2526 | : public _VSTD::integral_constant<bool, | |
| 2527 | __is_destructor_wellformed<typename _VSTD::remove_all_extents<_Tp>::type>::value> {}; | |
| 2785 | : public integral_constant<bool, | |
| 2786 | __is_destructor_wellformed<typename remove_all_extents<_Tp>::type>::value> {}; | |
| 2528 | 2787 | |
| 2529 | 2788 | template <class _Tp> |
| 2530 | 2789 | struct __destructible_imp<_Tp, true> |
| 2531 | : public _VSTD::true_type {}; | |
| 2790 | : public true_type {}; | |
| 2532 | 2791 | |
| 2533 | 2792 | template <class _Tp, bool> |
| 2534 | 2793 | struct __destructible_false; |
| 2535 | 2794 | |
| 2536 | 2795 | template <class _Tp> |
| 2537 | struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, _VSTD::is_reference<_Tp>::value> {}; | |
| 2796 | struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, is_reference<_Tp>::value> {}; | |
| 2538 | 2797 | |
| 2539 | 2798 | template <class _Tp> |
| 2540 | struct __destructible_false<_Tp, true> : public _VSTD::false_type {}; | |
| 2799 | struct __destructible_false<_Tp, true> : public false_type {}; | |
| 2541 | 2800 | |
| 2542 | 2801 | template <class _Tp> |
| 2543 | 2802 | struct is_destructible |
| 2544 | : public __destructible_false<_Tp, _VSTD::is_function<_Tp>::value> {}; | |
| 2803 | : public __destructible_false<_Tp, is_function<_Tp>::value> {}; | |
| 2545 | 2804 | |
| 2546 | 2805 | template <class _Tp> |
| 2547 | 2806 | struct is_destructible<_Tp[]> |
| 2548 | : public _VSTD::false_type {}; | |
| 2807 | : public false_type {}; | |
| 2549 | 2808 | |
| 2550 | 2809 | template <> |
| 2551 | 2810 | struct is_destructible<void> |
| 2552 | : public _VSTD::false_type {}; | |
| 2811 | : public false_type {}; | |
| 2553 | 2812 | |
| 2554 | 2813 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| 2555 | 2814 | template <class _Tp> |
| ... | ... | @@ -2559,43 +2818,6 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_destructible_v |
| 2559 | 2818 | |
| 2560 | 2819 | #endif // __has_keyword(__is_destructible) |
| 2561 | 2820 | |
| 2562 | // move | |
| 2563 | ||
| 2564 | template <class _Tp> | |
| 2565 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 2566 | typename remove_reference<_Tp>::type&& | |
| 2567 | move(_Tp&& __t) _NOEXCEPT | |
| 2568 | { | |
| 2569 | typedef _LIBCPP_NODEBUG_TYPE typename remove_reference<_Tp>::type _Up; | |
| 2570 | return static_cast<_Up&&>(__t); | |
| 2571 | } | |
| 2572 | ||
| 2573 | template <class _Tp> | |
| 2574 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 2575 | _Tp&& | |
| 2576 | forward(typename remove_reference<_Tp>::type& __t) _NOEXCEPT | |
| 2577 | { | |
| 2578 | return static_cast<_Tp&&>(__t); | |
| 2579 | } | |
| 2580 | ||
| 2581 | template <class _Tp> | |
| 2582 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 2583 | _Tp&& | |
| 2584 | forward(typename remove_reference<_Tp>::type&& __t) _NOEXCEPT | |
| 2585 | { | |
| 2586 | static_assert(!is_lvalue_reference<_Tp>::value, | |
| 2587 | "can not forward an rvalue as an lvalue"); | |
| 2588 | return static_cast<_Tp&&>(__t); | |
| 2589 | } | |
| 2590 | ||
| 2591 | template <class _Tp> | |
| 2592 | inline _LIBCPP_INLINE_VISIBILITY | |
| 2593 | typename decay<_Tp>::type | |
| 2594 | __decay_copy(_Tp&& __t) | |
| 2595 | { | |
| 2596 | return _VSTD::forward<_Tp>(__t); | |
| 2597 | } | |
| 2598 | ||
| 2599 | 2821 | template <class _MP, bool _IsMemberFunctionPtr, bool _IsMemberObjectPtr> |
| 2600 | 2822 | struct __member_pointer_traits_imp |
| 2601 | 2823 | { |
| ... | ... | @@ -2795,7 +3017,7 @@ struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatil |
| 2795 | 3017 | typedef _Rp (_FnType) (_Param..., ...); |
| 2796 | 3018 | }; |
| 2797 | 3019 | |
| 2798 | #endif // __has_feature(cxx_reference_qualified_functions) || defined(_LIBCPP_COMPILER_GCC) | |
| 3020 | #endif // __has_feature(cxx_reference_qualified_functions) || defined(_LIBCPP_COMPILER_GCC) | |
| 2799 | 3021 | |
| 2800 | 3022 | |
| 2801 | 3023 | template <class _Rp, class _Class> |
| ... | ... | @@ -2876,11 +3098,11 @@ struct __is_constructible_helper |
| 2876 | 3098 | // NOTE: The static_cast implementation below is required to support |
| 2877 | 3099 | // classes with explicit conversion operators. |
| 2878 | 3100 | template <class _To, class _From, |
| 2879 | class = decltype(__eat<_To>(_VSTD::declval<_From>()))> | |
| 3101 | class = decltype(__eat<_To>(declval<_From>()))> | |
| 2880 | 3102 | static true_type __test_cast(int); |
| 2881 | 3103 | |
| 2882 | 3104 | template <class _To, class _From, |
| 2883 | class = decltype(static_cast<_To>(_VSTD::declval<_From>()))> | |
| 3105 | class = decltype(static_cast<_To>(declval<_From>()))> | |
| 2884 | 3106 | static integral_constant<bool, |
| 2885 | 3107 | !__is_invalid_base_to_derived_cast<_To, _From>::value && |
| 2886 | 3108 | !__is_invalid_lvalue_to_rvalue_cast<_To, _From>::value |
| ... | ... | @@ -2890,12 +3112,12 @@ struct __is_constructible_helper |
| 2890 | 3112 | static false_type __test_cast(...); |
| 2891 | 3113 | |
| 2892 | 3114 | template <class _Tp, class ..._Args, |
| 2893 | class = decltype(_Tp(_VSTD::declval<_Args>()...))> | |
| 3115 | class = decltype(_Tp(declval<_Args>()...))> | |
| 2894 | 3116 | static true_type __test_nary(int); |
| 2895 | 3117 | template <class _Tp, class...> |
| 2896 | 3118 | static false_type __test_nary(...); |
| 2897 | 3119 | |
| 2898 | template <class _Tp, class _A0, class = decltype(::new _Tp(_VSTD::declval<_A0>()))> | |
| 3120 | template <class _Tp, class _A0, class = decltype(::new _Tp(declval<_A0>()))> | |
| 2899 | 3121 | static is_destructible<_Tp> __test_unary(int); |
| 2900 | 3122 | template <class, class> |
| 2901 | 3123 | static false_type __test_unary(...); |
| ... | ... | @@ -2984,18 +3206,18 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_default_constructible_v |
| 2984 | 3206 | template <class _Tp> |
| 2985 | 3207 | void __test_implicit_default_constructible(_Tp); |
| 2986 | 3208 | |
| 2987 | template <class _Tp, class = void, bool = is_default_constructible<_Tp>::value> | |
| 3209 | template <class _Tp, class = void, class = typename is_default_constructible<_Tp>::type> | |
| 2988 | 3210 | struct __is_implicitly_default_constructible |
| 2989 | 3211 | : false_type |
| 2990 | 3212 | { }; |
| 2991 | 3213 | |
| 2992 | 3214 | template <class _Tp> |
| 2993 | struct __is_implicitly_default_constructible<_Tp, decltype(__test_implicit_default_constructible<_Tp const&>({})), true> | |
| 3215 | struct __is_implicitly_default_constructible<_Tp, decltype(__test_implicit_default_constructible<_Tp const&>({})), true_type> | |
| 2994 | 3216 | : true_type |
| 2995 | 3217 | { }; |
| 2996 | 3218 | |
| 2997 | 3219 | template <class _Tp> |
| 2998 | struct __is_implicitly_default_constructible<_Tp, decltype(__test_implicit_default_constructible<_Tp const&>({})), false> | |
| 3220 | struct __is_implicitly_default_constructible<_Tp, decltype(__test_implicit_default_constructible<_Tp const&>({})), false_type> | |
| 2999 | 3221 | : false_type |
| 3000 | 3222 | { }; |
| 3001 | 3223 | #endif // !C++03 |
| ... | ... | @@ -3072,7 +3294,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_constructible<_Tp, _Tp&> |
| 3072 | 3294 | { |
| 3073 | 3295 | }; |
| 3074 | 3296 | |
| 3075 | #endif // !__has_feature(is_trivially_constructible) | |
| 3297 | #endif // !__has_feature(is_trivially_constructible) | |
| 3076 | 3298 | |
| 3077 | 3299 | |
| 3078 | 3300 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| ... | ... | @@ -3149,7 +3371,7 @@ template <class _Tp> |
| 3149 | 3371 | struct is_trivially_assignable<_Tp&, _Tp&&> |
| 3150 | 3372 | : integral_constant<bool, is_scalar<_Tp>::value> {}; |
| 3151 | 3373 | |
| 3152 | #endif // !__has_feature(is_trivially_assignable) | |
| 3374 | #endif // !__has_feature(is_trivially_assignable) | |
| 3153 | 3375 | |
| 3154 | 3376 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| 3155 | 3377 | template <class _Tp, class _Arg> |
| ... | ... | @@ -3259,7 +3481,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_constructible<_Tp[_Ns]> |
| 3259 | 3481 | { |
| 3260 | 3482 | }; |
| 3261 | 3483 | |
| 3262 | #endif // _LIBCPP_HAS_NO_NOEXCEPT | |
| 3484 | #endif // _LIBCPP_HAS_NO_NOEXCEPT | |
| 3263 | 3485 | |
| 3264 | 3486 | |
| 3265 | 3487 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| ... | ... | @@ -3324,7 +3546,7 @@ struct __libcpp_is_nothrow_assignable<false, _Tp, _Arg> |
| 3324 | 3546 | |
| 3325 | 3547 | template <class _Tp, class _Arg> |
| 3326 | 3548 | struct __libcpp_is_nothrow_assignable<true, _Tp, _Arg> |
| 3327 | : public integral_constant<bool, noexcept(_VSTD::declval<_Tp>() = _VSTD::declval<_Arg>()) > | |
| 3549 | : public integral_constant<bool, noexcept(declval<_Tp>() = declval<_Arg>()) > | |
| 3328 | 3550 | { |
| 3329 | 3551 | }; |
| 3330 | 3552 | |
| ... | ... | @@ -3334,7 +3556,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_assignable |
| 3334 | 3556 | { |
| 3335 | 3557 | }; |
| 3336 | 3558 | |
| 3337 | #endif // _LIBCPP_HAS_NO_NOEXCEPT | |
| 3559 | #endif // _LIBCPP_HAS_NO_NOEXCEPT | |
| 3338 | 3560 | |
| 3339 | 3561 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| 3340 | 3562 | template <class _Tp, class _Arg> |
| ... | ... | @@ -3381,7 +3603,7 @@ struct __libcpp_is_nothrow_destructible<false, _Tp> |
| 3381 | 3603 | |
| 3382 | 3604 | template <class _Tp> |
| 3383 | 3605 | struct __libcpp_is_nothrow_destructible<true, _Tp> |
| 3384 | : public integral_constant<bool, noexcept(_VSTD::declval<_Tp>().~_Tp()) > | |
| 3606 | : public integral_constant<bool, noexcept(declval<_Tp>().~_Tp()) > | |
| 3385 | 3607 | { |
| 3386 | 3608 | }; |
| 3387 | 3609 | |
| ... | ... | @@ -3455,15 +3677,17 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_pod_v |
| 3455 | 3677 | |
| 3456 | 3678 | // is_literal_type; |
| 3457 | 3679 | |
| 3458 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_literal_type | |
| 3680 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) | |
| 3681 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 is_literal_type | |
| 3459 | 3682 | : public integral_constant<bool, __is_literal_type(_Tp)> |
| 3460 | 3683 | {}; |
| 3461 | 3684 | |
| 3462 | 3685 | #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) |
| 3463 | 3686 | template <class _Tp> |
| 3464 | _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_literal_type_v | |
| 3687 | _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_literal_type_v | |
| 3465 | 3688 | = is_literal_type<_Tp>::value; |
| 3466 | #endif | |
| 3689 | #endif // _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) | |
| 3690 | #endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) | |
| 3467 | 3691 | |
| 3468 | 3692 | // is_standard_layout; |
| 3469 | 3693 | |
| ... | ... | @@ -3604,42 +3828,42 @@ template <class _Fp, class _A0, class ..._Args, |
| 3604 | 3828 | inline _LIBCPP_INLINE_VISIBILITY |
| 3605 | 3829 | _LIBCPP_CONSTEXPR_AFTER_CXX17 auto |
| 3606 | 3830 | __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) |
| 3607 | _LIBCPP_INVOKE_RETURN((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3831 | _LIBCPP_INVOKE_RETURN((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...)) | |
| 3608 | 3832 | |
| 3609 | 3833 | template <class _Fp, class _A0, class ..._Args, |
| 3610 | 3834 | class = __enable_if_bullet1<_Fp, _A0>> |
| 3611 | 3835 | inline _LIBCPP_INLINE_VISIBILITY |
| 3612 | 3836 | _LIBCPP_CONSTEXPR auto |
| 3613 | 3837 | __invoke_constexpr(_Fp&& __f, _A0&& __a0, _Args&& ...__args) |
| 3614 | _LIBCPP_INVOKE_RETURN((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3838 | _LIBCPP_INVOKE_RETURN((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...)) | |
| 3615 | 3839 | |
| 3616 | 3840 | template <class _Fp, class _A0, class ..._Args, |
| 3617 | 3841 | class = __enable_if_bullet2<_Fp, _A0>> |
| 3618 | 3842 | inline _LIBCPP_INLINE_VISIBILITY |
| 3619 | 3843 | _LIBCPP_CONSTEXPR_AFTER_CXX17 auto |
| 3620 | 3844 | __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) |
| 3621 | _LIBCPP_INVOKE_RETURN((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3845 | _LIBCPP_INVOKE_RETURN((__a0.get().*__f)(static_cast<_Args&&>(__args)...)) | |
| 3622 | 3846 | |
| 3623 | 3847 | template <class _Fp, class _A0, class ..._Args, |
| 3624 | 3848 | class = __enable_if_bullet2<_Fp, _A0>> |
| 3625 | 3849 | inline _LIBCPP_INLINE_VISIBILITY |
| 3626 | 3850 | _LIBCPP_CONSTEXPR auto |
| 3627 | 3851 | __invoke_constexpr(_Fp&& __f, _A0&& __a0, _Args&& ...__args) |
| 3628 | _LIBCPP_INVOKE_RETURN((__a0.get().*__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3852 | _LIBCPP_INVOKE_RETURN((__a0.get().*__f)(static_cast<_Args&&>(__args)...)) | |
| 3629 | 3853 | |
| 3630 | 3854 | template <class _Fp, class _A0, class ..._Args, |
| 3631 | 3855 | class = __enable_if_bullet3<_Fp, _A0>> |
| 3632 | 3856 | inline _LIBCPP_INLINE_VISIBILITY |
| 3633 | 3857 | _LIBCPP_CONSTEXPR_AFTER_CXX17 auto |
| 3634 | 3858 | __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) |
| 3635 | _LIBCPP_INVOKE_RETURN(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3859 | _LIBCPP_INVOKE_RETURN(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...)) | |
| 3636 | 3860 | |
| 3637 | 3861 | template <class _Fp, class _A0, class ..._Args, |
| 3638 | 3862 | class = __enable_if_bullet3<_Fp, _A0>> |
| 3639 | 3863 | inline _LIBCPP_INLINE_VISIBILITY |
| 3640 | 3864 | _LIBCPP_CONSTEXPR auto |
| 3641 | 3865 | __invoke_constexpr(_Fp&& __f, _A0&& __a0, _Args&& ...__args) |
| 3642 | _LIBCPP_INVOKE_RETURN(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3866 | _LIBCPP_INVOKE_RETURN(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...)) | |
| 3643 | 3867 | |
| 3644 | 3868 | // bullets 4, 5 and 6 |
| 3645 | 3869 | |
| ... | ... | @@ -3648,14 +3872,14 @@ template <class _Fp, class _A0, |
| 3648 | 3872 | inline _LIBCPP_INLINE_VISIBILITY |
| 3649 | 3873 | _LIBCPP_CONSTEXPR_AFTER_CXX17 auto |
| 3650 | 3874 | __invoke(_Fp&& __f, _A0&& __a0) |
| 3651 | _LIBCPP_INVOKE_RETURN(_VSTD::forward<_A0>(__a0).*__f) | |
| 3875 | _LIBCPP_INVOKE_RETURN(static_cast<_A0&&>(__a0).*__f) | |
| 3652 | 3876 | |
| 3653 | 3877 | template <class _Fp, class _A0, |
| 3654 | 3878 | class = __enable_if_bullet4<_Fp, _A0>> |
| 3655 | 3879 | inline _LIBCPP_INLINE_VISIBILITY |
| 3656 | 3880 | _LIBCPP_CONSTEXPR auto |
| 3657 | 3881 | __invoke_constexpr(_Fp&& __f, _A0&& __a0) |
| 3658 | _LIBCPP_INVOKE_RETURN(_VSTD::forward<_A0>(__a0).*__f) | |
| 3882 | _LIBCPP_INVOKE_RETURN(static_cast<_A0&&>(__a0).*__f) | |
| 3659 | 3883 | |
| 3660 | 3884 | template <class _Fp, class _A0, |
| 3661 | 3885 | class = __enable_if_bullet5<_Fp, _A0>> |
| ... | ... | @@ -3676,14 +3900,14 @@ template <class _Fp, class _A0, |
| 3676 | 3900 | inline _LIBCPP_INLINE_VISIBILITY |
| 3677 | 3901 | _LIBCPP_CONSTEXPR_AFTER_CXX17 auto |
| 3678 | 3902 | __invoke(_Fp&& __f, _A0&& __a0) |
| 3679 | _LIBCPP_INVOKE_RETURN((*_VSTD::forward<_A0>(__a0)).*__f) | |
| 3903 | _LIBCPP_INVOKE_RETURN((*static_cast<_A0&&>(__a0)).*__f) | |
| 3680 | 3904 | |
| 3681 | 3905 | template <class _Fp, class _A0, |
| 3682 | 3906 | class = __enable_if_bullet6<_Fp, _A0>> |
| 3683 | 3907 | inline _LIBCPP_INLINE_VISIBILITY |
| 3684 | 3908 | _LIBCPP_CONSTEXPR auto |
| 3685 | 3909 | __invoke_constexpr(_Fp&& __f, _A0&& __a0) |
| 3686 | _LIBCPP_INVOKE_RETURN((*_VSTD::forward<_A0>(__a0)).*__f) | |
| 3910 | _LIBCPP_INVOKE_RETURN((*static_cast<_A0&&>(__a0)).*__f) | |
| 3687 | 3911 | |
| 3688 | 3912 | // bullet 7 |
| 3689 | 3913 | |
| ... | ... | @@ -3691,13 +3915,13 @@ template <class _Fp, class ..._Args> |
| 3691 | 3915 | inline _LIBCPP_INLINE_VISIBILITY |
| 3692 | 3916 | _LIBCPP_CONSTEXPR_AFTER_CXX17 auto |
| 3693 | 3917 | __invoke(_Fp&& __f, _Args&& ...__args) |
| 3694 | _LIBCPP_INVOKE_RETURN(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3918 | _LIBCPP_INVOKE_RETURN(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...)) | |
| 3695 | 3919 | |
| 3696 | 3920 | template <class _Fp, class ..._Args> |
| 3697 | 3921 | inline _LIBCPP_INLINE_VISIBILITY |
| 3698 | 3922 | _LIBCPP_CONSTEXPR auto |
| 3699 | 3923 | __invoke_constexpr(_Fp&& __f, _Args&& ...__args) |
| 3700 | _LIBCPP_INVOKE_RETURN(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)) | |
| 3924 | _LIBCPP_INVOKE_RETURN(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...)) | |
| 3701 | 3925 | |
| 3702 | 3926 | #undef _LIBCPP_INVOKE_RETURN |
| 3703 | 3927 | |
| ... | ... | @@ -3707,7 +3931,7 @@ struct __invokable_r |
| 3707 | 3931 | { |
| 3708 | 3932 | template <class _XFp, class ..._XArgs> |
| 3709 | 3933 | static auto __try_call(int) -> decltype( |
| 3710 | _VSTD::__invoke(_VSTD::declval<_XFp>(), _VSTD::declval<_XArgs>()...)); | |
| 3934 | _VSTD::__invoke(declval<_XFp>(), declval<_XArgs>()...)); | |
| 3711 | 3935 | template <class _XFp, class ..._XArgs> |
| 3712 | 3936 | static __nat __try_call(...); |
| 3713 | 3937 | |
| ... | ... | @@ -3744,14 +3968,14 @@ struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...> |
| 3744 | 3968 | static void __test_noexcept(_Tp) noexcept; |
| 3745 | 3969 | |
| 3746 | 3970 | static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>( |
| 3747 | _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...))); | |
| 3971 | _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...))); | |
| 3748 | 3972 | }; |
| 3749 | 3973 | |
| 3750 | 3974 | template <class _Ret, class _Fp, class ..._Args> |
| 3751 | 3975 | struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...> |
| 3752 | 3976 | { |
| 3753 | 3977 | static const bool value = noexcept( |
| 3754 | _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...)); | |
| 3978 | _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...)); | |
| 3755 | 3979 | }; |
| 3756 | 3980 | |
| 3757 | 3981 | template <class _Ret, class _Fp, class ..._Args> |
| ... | ... | @@ -3781,7 +4005,8 @@ struct __invoke_of |
| 3781 | 4005 | |
| 3782 | 4006 | // result_of |
| 3783 | 4007 | |
| 3784 | template <class _Callable> class result_of; | |
| 4008 | #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) | |
| 4009 | template <class _Callable> class _LIBCPP_DEPRECATED_IN_CXX17 result_of; | |
| 3785 | 4010 | |
| 3786 | 4011 | #ifndef _LIBCPP_CXX03_LANG |
| 3787 | 4012 | |
| ... | ... | @@ -3812,8 +4037,8 @@ struct __result_of_mp; |
| 3812 | 4037 | |
| 3813 | 4038 | template <class _MP, class _Tp> |
| 3814 | 4039 | struct __result_of_mp<_MP, _Tp, true> |
| 3815 | : public __identity<typename __member_pointer_traits<_MP>::_ReturnType> | |
| 3816 | 4040 | { |
| 4041 | using type = typename __member_pointer_traits<_MP>::_ReturnType; | |
| 3817 | 4042 | }; |
| 3818 | 4043 | |
| 3819 | 4044 | // member data pointer |
| ... | ... | @@ -3824,13 +4049,13 @@ struct __result_of_mdp; |
| 3824 | 4049 | template <class _Rp, class _Class, class _Tp> |
| 3825 | 4050 | struct __result_of_mdp<_Rp _Class::*, _Tp, false> |
| 3826 | 4051 | { |
| 3827 | typedef typename __apply_cv<decltype(*_VSTD::declval<_Tp>()), _Rp>::type& type; | |
| 4052 | using type = typename __apply_cv<decltype(*declval<_Tp>()), _Rp>::type&; | |
| 3828 | 4053 | }; |
| 3829 | 4054 | |
| 3830 | 4055 | template <class _Rp, class _Class, class _Tp> |
| 3831 | 4056 | struct __result_of_mdp<_Rp _Class::*, _Tp, true> |
| 3832 | 4057 | { |
| 3833 | typedef typename __apply_cv<_Tp, _Rp>::type& type; | |
| 4058 | using type = typename __apply_cv<_Tp, _Rp>::type&; | |
| 3834 | 4059 | }; |
| 3835 | 4060 | |
| 3836 | 4061 | template <class _Rp, class _Class, class _Tp> |
| ... | ... | @@ -3866,11 +4091,12 @@ class _LIBCPP_TEMPLATE_VIS result_of<_Fn(_Args...)> |
| 3866 | 4091 | { |
| 3867 | 4092 | }; |
| 3868 | 4093 | |
| 3869 | #endif // C++03 | |
| 4094 | #endif // C++03 | |
| 3870 | 4095 | |
| 3871 | 4096 | #if _LIBCPP_STD_VER > 11 |
| 3872 | template <class _Tp> using result_of_t = typename result_of<_Tp>::type; | |
| 3873 | #endif | |
| 4097 | template <class _Tp> using result_of_t _LIBCPP_DEPRECATED_IN_CXX17 = typename result_of<_Tp>::type; | |
| 4098 | #endif // _LIBCPP_STD_VER > 11 | |
| 4099 | #endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) | |
| 3874 | 4100 | |
| 3875 | 4101 | #if _LIBCPP_STD_VER > 14 |
| 3876 | 4102 | |
| ... | ... | @@ -3923,70 +4149,32 @@ _LIBCPP_INLINE_VAR constexpr bool is_nothrow_invocable_r_v |
| 3923 | 4149 | |
| 3924 | 4150 | #endif // _LIBCPP_STD_VER > 14 |
| 3925 | 4151 | |
| 4152 | // __swappable | |
| 4153 | ||
| 3926 | 4154 | template <class _Tp> struct __is_swappable; |
| 3927 | 4155 | template <class _Tp> struct __is_nothrow_swappable; |
| 3928 | 4156 | |
| 3929 | // swap, swap_ranges | |
| 3930 | 4157 | |
| 3931 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 3932 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3933 | _ForwardIterator2 | |
| 3934 | swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2); | |
| 3935 | ||
| 3936 | template <class _Tp> | |
| 3937 | inline _LIBCPP_INLINE_VISIBILITY | |
| 3938 | 4158 | #ifndef _LIBCPP_CXX03_LANG |
| 3939 | typename enable_if | |
| 3940 | < | |
| 3941 | is_move_constructible<_Tp>::value && | |
| 3942 | is_move_assignable<_Tp>::value | |
| 3943 | >::type | |
| 4159 | template <class _Tp> | |
| 4160 | using __swap_result_t = typename enable_if<is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value>::type; | |
| 3944 | 4161 | #else |
| 3945 | void | |
| 4162 | template <class> | |
| 4163 | using __swap_result_t = void; | |
| 3946 | 4164 | #endif |
| 3947 | _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 4165 | ||
| 4166 | template <class _Tp> | |
| 4167 | inline _LIBCPP_INLINE_VISIBILITY | |
| 4168 | _LIBCPP_CONSTEXPR_AFTER_CXX17 __swap_result_t<_Tp> | |
| 3948 | 4169 | swap(_Tp& __x, _Tp& __y) _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value && |
| 3949 | is_nothrow_move_assignable<_Tp>::value) | |
| 3950 | { | |
| 3951 | _Tp __t(_VSTD::move(__x)); | |
| 3952 | __x = _VSTD::move(__y); | |
| 3953 | __y = _VSTD::move(__t); | |
| 3954 | } | |
| 4170 | is_nothrow_move_assignable<_Tp>::value); | |
| 3955 | 4171 | |
| 3956 | 4172 | template<class _Tp, size_t _Np> |
| 3957 | 4173 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 |
| 3958 | 4174 | typename enable_if< |
| 3959 | 4175 | __is_swappable<_Tp>::value |
| 3960 | 4176 | >::type |
| 3961 | swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) | |
| 3962 | { | |
| 3963 | _VSTD::swap_ranges(__a, __a + _Np, __b); | |
| 3964 | } | |
| 3965 | ||
| 3966 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 3967 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3968 | _ForwardIterator2 | |
| 3969 | swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) | |
| 3970 | { | |
| 3971 | for(; __first1 != __last1; ++__first1, (void) ++__first2) | |
| 3972 | swap(*__first1, *__first2); | |
| 3973 | return __first2; | |
| 3974 | } | |
| 3975 | ||
| 3976 | // iter_swap | |
| 3977 | ||
| 3978 | template <class _ForwardIterator1, class _ForwardIterator2> | |
| 3979 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 3980 | void | |
| 3981 | iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) | |
| 3982 | // _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b))) | |
| 3983 | _NOEXCEPT_(_NOEXCEPT_(swap(*_VSTD::declval<_ForwardIterator1>(), | |
| 3984 | *_VSTD::declval<_ForwardIterator2>()))) | |
| 3985 | { | |
| 3986 | swap(*__a, *__b); | |
| 3987 | } | |
| 3988 | ||
| 3989 | // __swappable | |
| 4177 | swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value); | |
| 3990 | 4178 | |
| 3991 | 4179 | namespace __detail |
| 3992 | 4180 | { |
| ... | ... | @@ -3997,7 +4185,7 @@ template <class _Tp, class _Up = _Tp, |
| 3997 | 4185 | struct __swappable_with |
| 3998 | 4186 | { |
| 3999 | 4187 | template <class _LHS, class _RHS> |
| 4000 | static decltype(swap(_VSTD::declval<_LHS>(), _VSTD::declval<_RHS>())) | |
| 4188 | static decltype(swap(declval<_LHS>(), declval<_RHS>())) | |
| 4001 | 4189 | __test_swap(int); |
| 4002 | 4190 | template <class, class> |
| 4003 | 4191 | static __nat __test_swap(long); |
| ... | ... | @@ -4017,8 +4205,8 @@ template <class _Tp, class _Up = _Tp, bool _Swappable = __swappable_with<_Tp, _U |
| 4017 | 4205 | struct __nothrow_swappable_with { |
| 4018 | 4206 | static const bool value = |
| 4019 | 4207 | #ifndef _LIBCPP_HAS_NO_NOEXCEPT |
| 4020 | noexcept(swap(_VSTD::declval<_Tp>(), _VSTD::declval<_Up>())) | |
| 4021 | && noexcept(swap(_VSTD::declval<_Up>(), _VSTD::declval<_Tp>())); | |
| 4208 | noexcept(swap(declval<_Tp>(), declval<_Up>())) | |
| 4209 | && noexcept(swap(declval<_Up>(), declval<_Tp>())); | |
| 4022 | 4210 | #else |
| 4023 | 4211 | false; |
| 4024 | 4212 | #endif |
| ... | ... | @@ -4168,7 +4356,7 @@ struct __has_operator_addressof_member_imp |
| 4168 | 4356 | { |
| 4169 | 4357 | template <class _Up> |
| 4170 | 4358 | static auto __test(int) |
| 4171 | -> typename __select_2nd<decltype(_VSTD::declval<_Up>().operator&()), true_type>::type; | |
| 4359 | -> typename __select_2nd<decltype(declval<_Up>().operator&()), true_type>::type; | |
| 4172 | 4360 | template <class> |
| 4173 | 4361 | static auto __test(long) -> false_type; |
| 4174 | 4362 | |
| ... | ... | @@ -4180,7 +4368,7 @@ struct __has_operator_addressof_free_imp |
| 4180 | 4368 | { |
| 4181 | 4369 | template <class _Up> |
| 4182 | 4370 | static auto __test(int) |
| 4183 | -> typename __select_2nd<decltype(operator&(_VSTD::declval<_Up>())), true_type>::type; | |
| 4371 | -> typename __select_2nd<decltype(operator&(declval<_Up>())), true_type>::type; | |
| 4184 | 4372 | template <class> |
| 4185 | 4373 | static auto __test(long) -> false_type; |
| 4186 | 4374 | |
| ... | ... | @@ -4193,7 +4381,7 @@ struct __has_operator_addressof |
| 4193 | 4381 | || __has_operator_addressof_free_imp<_Tp>::value> |
| 4194 | 4382 | {}; |
| 4195 | 4383 | |
| 4196 | #endif // _LIBCPP_CXX03_LANG | |
| 4384 | #endif // _LIBCPP_CXX03_LANG | |
| 4197 | 4385 | |
| 4198 | 4386 | // is_scoped_enum [meta.unary.prop] |
| 4199 | 4387 | |
| ... | ... | @@ -4233,7 +4421,7 @@ struct negation : _Not<_Tp> {}; |
| 4233 | 4421 | template<class _Tp> |
| 4234 | 4422 | _LIBCPP_INLINE_VAR constexpr bool negation_v |
| 4235 | 4423 | = negation<_Tp>::value; |
| 4236 | #endif // _LIBCPP_STD_VER > 14 | |
| 4424 | #endif // _LIBCPP_STD_VER > 14 | |
| 4237 | 4425 | |
| 4238 | 4426 | // These traits are used in __tree and __hash_table |
| 4239 | 4427 | struct __extract_key_fail_tag {}; |
| ... | ... | @@ -4283,6 +4471,14 @@ bool __libcpp_is_constant_evaluated() _NOEXCEPT { return false; } |
| 4283 | 4471 | template <class _CharT> |
| 4284 | 4472 | using _IsCharLikeType = _And<is_standard_layout<_CharT>, is_trivial<_CharT> >; |
| 4285 | 4473 | |
| 4474 | template<class _Tp> | |
| 4475 | using __make_const_lvalue_ref = const typename remove_reference<_Tp>::type&; | |
| 4476 | ||
| 4477 | #if _LIBCPP_STD_VER > 17 | |
| 4478 | template<bool _Const, class _Tp> | |
| 4479 | using __maybe_const = conditional_t<_Const, const _Tp, _Tp>; | |
| 4480 | #endif // _LIBCPP_STD_VER > 17 | |
| 4481 | ||
| 4286 | 4482 | _LIBCPP_END_NAMESPACE_STD |
| 4287 | 4483 | |
| 4288 | 4484 | #if _LIBCPP_STD_VER > 14 |
| ... | ... | @@ -4294,4 +4490,4 @@ namespace std // purposefully not versioned |
| 4294 | 4490 | } |
| 4295 | 4491 | #endif |
| 4296 | 4492 | |
| 4297 | #endif // _LIBCPP_TYPE_TRAITS | |
| 4493 | #endif // _LIBCPP_TYPE_TRAITS |
lib/libcxx/include/typeindex+4-2| ... | ... | @@ -45,8 +45,10 @@ struct hash<type_index> |
| 45 | 45 | */ |
| 46 | 46 | |
| 47 | 47 | #include <__config> |
| 48 | #include <typeinfo> | |
| 48 | #include <__functional/unary_function.h> | |
| 49 | 49 | #include <__functional_base> |
| 50 | #include <compare> | |
| 51 | #include <typeinfo> | |
| 50 | 52 | |
| 51 | 53 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 52 | 54 | #pragma GCC system_header |
| ... | ... | @@ -99,4 +101,4 @@ struct _LIBCPP_TEMPLATE_VIS hash<type_index> |
| 99 | 101 | |
| 100 | 102 | _LIBCPP_END_NAMESPACE_STD |
| 101 | 103 | |
| 102 | #endif // _LIBCPP_TYPEINDEX | |
| 104 | #endif // _LIBCPP_TYPEINDEX |
lib/libcxx/include/typeinfo+30-24| ... | ... | @@ -56,12 +56,13 @@ public: |
| 56 | 56 | |
| 57 | 57 | */ |
| 58 | 58 | |
| 59 | #include <__config> | |
| 60 | 59 | #include <__availability> |
| 61 | #include <exception> | |
| 60 | #include <__config> | |
| 62 | 61 | #include <cstddef> |
| 63 | 62 | #include <cstdint> |
| 63 | #include <exception> | |
| 64 | 64 | #include <type_traits> |
| 65 | ||
| 65 | 66 | #ifdef _LIBCPP_NO_EXCEPTIONS |
| 66 | 67 | #include <cstdlib> |
| 67 | 68 | #endif |
| ... | ... | @@ -125,7 +126,7 @@ public: |
| 125 | 126 | // (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 1) |
| 126 | 127 | // ------------------------------------------------------------------------- // |
| 127 | 128 | // This implementation of type_info assumes a unique copy of the RTTI for a |
| 128 | // given type inside a program. This is a valid assumption when abiding to | |
| 129 | // given type inside a program. This is a valid assumption when abiding to the | |
| 129 | 130 | // Itanium ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-components). |
| 130 | 131 | // Under this assumption, we can always compare the addresses of the type names |
| 131 | 132 | // to implement equality-comparison of type_infos instead of having to perform |
| ... | ... | @@ -144,22 +145,29 @@ public: |
| 144 | 145 | // NonUniqueARMRTTIBit |
| 145 | 146 | // (_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 3) |
| 146 | 147 | // -------------------------------------------------------------------------- // |
| 148 | // This implementation is specific to ARM64 on Apple platforms. | |
| 149 | // | |
| 147 | 150 | // This implementation of type_info does not assume always a unique copy of |
| 148 | // the RTTI for a given type inside a program. It packs the pointer to the | |
| 149 | // type name into a uintptr_t and reserves the high bit of that pointer (which | |
| 150 | // is assumed to be free for use under the ABI in use) to represent whether | |
| 151 | // that specific copy of the RTTI can be assumed unique inside the program. | |
| 152 | // To implement equality-comparison of type_infos, we check whether BOTH | |
| 153 | // type_infos are guaranteed unique, and if so, we simply compare the addresses | |
| 154 | // of their type names instead of doing a deep string comparison, which is | |
| 155 | // faster. If at least one of the type_infos can't guarantee uniqueness, we | |
| 156 | // have no choice but to fall back to a deep string comparison. | |
| 151 | // the RTTI for a given type inside a program. When constructing the type_info, | |
| 152 | // the compiler packs the pointer to the type name into a uintptr_t and reserves | |
| 153 | // the high bit of that pointer, which is assumed to be free for use under that | |
| 154 | // ABI. If that high bit is set, that specific copy of the RTTI can't be assumed | |
| 155 | // to be unique within the program. If the high bit is unset, then the RTTI can | |
| 156 | // be assumed to be unique within the program. | |
| 157 | 157 | // |
| 158 | // This implementation is specific to ARM64 on Apple platforms. | |
| 158 | // When comparing type_infos, if both RTTIs can be assumed to be unique, it | |
| 159 | // suffices to compare their addresses. If both the RTTIs can't be assumed to | |
| 160 | // be unique, we must perform a deep string comparison of the type names. | |
| 161 | // However, if one of the RTTIs is guaranteed unique and the other one isn't, | |
| 162 | // then both RTTIs are necessarily not to be considered equal. | |
| 159 | 163 | // |
| 160 | // Note that the compiler is the one setting (or unsetting) the high bit of | |
| 161 | // the pointer when it constructs the type_info, depending on whether it can | |
| 162 | // guarantee uniqueness for that specific type_info. | |
| 164 | // The intent of this design is to remove the need for weak symbols. Specifically, | |
| 165 | // if a type would normally have a default-visibility RTTI emitted as a weak | |
| 166 | // symbol, it is given hidden visibility instead and the non-unique bit is set. | |
| 167 | // Otherwise, types declared with hidden visibility are always considered to have | |
| 168 | // a unique RTTI: the RTTI is emitted with linkonce_odr linkage and is assumed | |
| 169 | // to be deduplicated by the linker within the linked image. Across linked image | |
| 170 | // boundaries, such types are thus considered different types. | |
| 163 | 171 | |
| 164 | 172 | // This value can be overriden in the __config_site. When it's not overriden, |
| 165 | 173 | // we pick a default implementation based on the platform here. |
| ... | ... | @@ -241,20 +249,22 @@ struct __type_info_implementations { |
| 241 | 249 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE |
| 242 | 250 | static size_t __hash(__type_name_t __v) _NOEXCEPT { |
| 243 | 251 | if (__is_type_name_unique(__v)) |
| 244 | return reinterpret_cast<size_t>(__v); | |
| 252 | return __v; | |
| 245 | 253 | return __non_unique_impl::__hash(__type_name_to_string(__v)); |
| 246 | 254 | } |
| 247 | 255 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE |
| 248 | 256 | static bool __eq(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { |
| 249 | 257 | if (__lhs == __rhs) |
| 250 | 258 | return true; |
| 251 | if (__is_type_name_unique(__lhs, __rhs)) | |
| 259 | if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs)) | |
| 260 | // Either both are unique and have a different address, or one of them | |
| 261 | // is unique and the other one isn't. In both cases they are unequal. | |
| 252 | 262 | return false; |
| 253 | 263 | return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) == 0; |
| 254 | 264 | } |
| 255 | 265 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE |
| 256 | 266 | static bool __lt(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { |
| 257 | if (__is_type_name_unique(__lhs, __rhs)) | |
| 267 | if (__is_type_name_unique(__lhs) || __is_type_name_unique(__rhs)) | |
| 258 | 268 | return __lhs < __rhs; |
| 259 | 269 | return __builtin_strcmp(__type_name_to_string(__lhs), __type_name_to_string(__rhs)) < 0; |
| 260 | 270 | } |
| ... | ... | @@ -269,10 +279,6 @@ struct __type_info_implementations { |
| 269 | 279 | static bool __is_type_name_unique(__type_name_t __lhs) _NOEXCEPT { |
| 270 | 280 | return !(__lhs & __non_unique_rtti_bit::value); |
| 271 | 281 | } |
| 272 | _LIBCPP_INLINE_VISIBILITY | |
| 273 | static bool __is_type_name_unique(__type_name_t __lhs, __type_name_t __rhs) _NOEXCEPT { | |
| 274 | return !((__lhs & __rhs) & __non_unique_rtti_bit::value); | |
| 275 | } | |
| 276 | 282 | }; |
| 277 | 283 | |
| 278 | 284 | typedef |
| ... | ... | @@ -371,4 +377,4 @@ void __throw_bad_cast() |
| 371 | 377 | } |
| 372 | 378 | _LIBCPP_END_NAMESPACE_STD |
| 373 | 379 | |
| 374 | #endif // __LIBCPP_TYPEINFO | |
| 380 | #endif // __LIBCPP_TYPEINFO |
lib/libcxx/include/unordered_map+27-24| ... | ... | @@ -432,15 +432,18 @@ template <class Key, class T, class Hash, class Pred, class Alloc> |
| 432 | 432 | */ |
| 433 | 433 | |
| 434 | 434 | #include <__config> |
| 435 | #include <__debug> | |
| 436 | #include <__functional/is_transparent.h> | |
| 435 | 437 | #include <__hash_table> |
| 436 | 438 | #include <__node_handle> |
| 439 | #include <__utility/forward.h> | |
| 440 | #include <compare> | |
| 437 | 441 | #include <functional> |
| 442 | #include <iterator> // __libcpp_erase_if_container | |
| 438 | 443 | #include <stdexcept> |
| 439 | 444 | #include <tuple> |
| 440 | 445 | #include <version> |
| 441 | 446 | |
| 442 | #include <__debug> | |
| 443 | ||
| 444 | 447 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 445 | 448 | #pragma GCC system_header |
| 446 | 449 | #endif |
| ... | ... | @@ -684,7 +687,7 @@ public: |
| 684 | 687 | { |
| 685 | 688 | const_cast<bool&>(__x.__value_constructed) = false; |
| 686 | 689 | } |
| 687 | #endif // _LIBCPP_CXX03_LANG | |
| 690 | #endif // _LIBCPP_CXX03_LANG | |
| 688 | 691 | |
| 689 | 692 | _LIBCPP_INLINE_VISIBILITY |
| 690 | 693 | void operator()(pointer __p) _NOEXCEPT |
| ... | ... | @@ -700,7 +703,7 @@ public: |
| 700 | 703 | |
| 701 | 704 | #ifndef _LIBCPP_CXX03_LANG |
| 702 | 705 | template <class _Key, class _Tp> |
| 703 | struct __hash_value_type | |
| 706 | struct _LIBCPP_STANDALONE_DEBUG __hash_value_type | |
| 704 | 707 | { |
| 705 | 708 | typedef _Key key_type; |
| 706 | 709 | typedef _Tp mapped_type; |
| ... | ... | @@ -920,9 +923,9 @@ public: |
| 920 | 923 | // types |
| 921 | 924 | typedef _Key key_type; |
| 922 | 925 | typedef _Tp mapped_type; |
| 923 | typedef typename __identity<_Hash>::type hasher; | |
| 924 | typedef typename __identity<_Pred>::type key_equal; | |
| 925 | typedef typename __identity<_Alloc>::type allocator_type; | |
| 926 | typedef __identity_t<_Hash> hasher; | |
| 927 | typedef __identity_t<_Pred> key_equal; | |
| 928 | typedef __identity_t<_Alloc> allocator_type; | |
| 926 | 929 | typedef pair<const key_type, mapped_type> value_type; |
| 927 | 930 | typedef value_type& reference; |
| 928 | 931 | typedef const value_type& const_reference; |
| ... | ... | @@ -1013,7 +1016,7 @@ public: |
| 1013 | 1016 | unordered_map(initializer_list<value_type> __il, size_type __n, |
| 1014 | 1017 | const hasher& __hf, const key_equal& __eql, |
| 1015 | 1018 | const allocator_type& __a); |
| 1016 | #endif // _LIBCPP_CXX03_LANG | |
| 1019 | #endif // _LIBCPP_CXX03_LANG | |
| 1017 | 1020 | #if _LIBCPP_STD_VER > 11 |
| 1018 | 1021 | _LIBCPP_INLINE_VISIBILITY |
| 1019 | 1022 | unordered_map(size_type __n, const allocator_type& __a) |
| ... | ... | @@ -1066,7 +1069,7 @@ public: |
| 1066 | 1069 | _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); |
| 1067 | 1070 | _LIBCPP_INLINE_VISIBILITY |
| 1068 | 1071 | unordered_map& operator=(initializer_list<value_type> __il); |
| 1069 | #endif // _LIBCPP_CXX03_LANG | |
| 1072 | #endif // _LIBCPP_CXX03_LANG | |
| 1070 | 1073 | |
| 1071 | 1074 | _LIBCPP_INLINE_VISIBILITY |
| 1072 | 1075 | allocator_type get_allocator() const _NOEXCEPT |
| ... | ... | @@ -1171,7 +1174,7 @@ public: |
| 1171 | 1174 | return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...).first; |
| 1172 | 1175 | } |
| 1173 | 1176 | |
| 1174 | #endif // _LIBCPP_CXX03_LANG | |
| 1177 | #endif // _LIBCPP_CXX03_LANG | |
| 1175 | 1178 | |
| 1176 | 1179 | #if _LIBCPP_STD_VER > 14 |
| 1177 | 1180 | template <class... _Args> |
| ... | ... | @@ -1452,7 +1455,7 @@ public: |
| 1452 | 1455 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const |
| 1453 | 1456 | {return __table_.__addable(&__i->__i_, __n);} |
| 1454 | 1457 | |
| 1455 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1458 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1456 | 1459 | |
| 1457 | 1460 | private: |
| 1458 | 1461 | |
| ... | ... | @@ -1718,7 +1721,7 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=( |
| 1718 | 1721 | return *this; |
| 1719 | 1722 | } |
| 1720 | 1723 | |
| 1721 | #endif // _LIBCPP_CXX03_LANG | |
| 1724 | #endif // _LIBCPP_CXX03_LANG | |
| 1722 | 1725 | |
| 1723 | 1726 | template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> |
| 1724 | 1727 | template <class _InputIterator> |
| ... | ... | @@ -1778,7 +1781,7 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) |
| 1778 | 1781 | return __r.first->second; |
| 1779 | 1782 | } |
| 1780 | 1783 | |
| 1781 | #endif // _LIBCPP_CXX03_MODE | |
| 1784 | #endif // _LIBCPP_CXX03_LANG | |
| 1782 | 1785 | |
| 1783 | 1786 | template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> |
| 1784 | 1787 | _Tp& |
| ... | ... | @@ -1817,7 +1820,7 @@ inline _LIBCPP_INLINE_VISIBILITY |
| 1817 | 1820 | typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type |
| 1818 | 1821 | erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, |
| 1819 | 1822 | _Predicate __pred) { |
| 1820 | return __libcpp_erase_if_container(__c, __pred); | |
| 1823 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 1821 | 1824 | } |
| 1822 | 1825 | #endif |
| 1823 | 1826 | |
| ... | ... | @@ -1857,9 +1860,9 @@ public: |
| 1857 | 1860 | // types |
| 1858 | 1861 | typedef _Key key_type; |
| 1859 | 1862 | typedef _Tp mapped_type; |
| 1860 | typedef typename __identity<_Hash>::type hasher; | |
| 1861 | typedef typename __identity<_Pred>::type key_equal; | |
| 1862 | typedef typename __identity<_Alloc>::type allocator_type; | |
| 1863 | typedef __identity_t<_Hash> hasher; | |
| 1864 | typedef __identity_t<_Pred> key_equal; | |
| 1865 | typedef __identity_t<_Alloc> allocator_type; | |
| 1863 | 1866 | typedef pair<const key_type, mapped_type> value_type; |
| 1864 | 1867 | typedef value_type& reference; |
| 1865 | 1868 | typedef const value_type& const_reference; |
| ... | ... | @@ -1948,7 +1951,7 @@ public: |
| 1948 | 1951 | unordered_multimap(initializer_list<value_type> __il, size_type __n, |
| 1949 | 1952 | const hasher& __hf, const key_equal& __eql, |
| 1950 | 1953 | const allocator_type& __a); |
| 1951 | #endif // _LIBCPP_CXX03_LANG | |
| 1954 | #endif // _LIBCPP_CXX03_LANG | |
| 1952 | 1955 | #if _LIBCPP_STD_VER > 11 |
| 1953 | 1956 | _LIBCPP_INLINE_VISIBILITY |
| 1954 | 1957 | unordered_multimap(size_type __n, const allocator_type& __a) |
| ... | ... | @@ -2001,7 +2004,7 @@ public: |
| 2001 | 2004 | _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); |
| 2002 | 2005 | _LIBCPP_INLINE_VISIBILITY |
| 2003 | 2006 | unordered_multimap& operator=(initializer_list<value_type> __il); |
| 2004 | #endif // _LIBCPP_CXX03_LANG | |
| 2007 | #endif // _LIBCPP_CXX03_LANG | |
| 2005 | 2008 | |
| 2006 | 2009 | _LIBCPP_INLINE_VISIBILITY |
| 2007 | 2010 | allocator_type get_allocator() const _NOEXCEPT |
| ... | ... | @@ -2070,7 +2073,7 @@ public: |
| 2070 | 2073 | iterator emplace_hint(const_iterator __p, _Args&&... __args) { |
| 2071 | 2074 | return __table_.__emplace_hint_multi(__p.__i_, _VSTD::forward<_Args>(__args)...); |
| 2072 | 2075 | } |
| 2073 | #endif // _LIBCPP_CXX03_LANG | |
| 2076 | #endif // _LIBCPP_CXX03_LANG | |
| 2074 | 2077 | |
| 2075 | 2078 | |
| 2076 | 2079 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -2255,7 +2258,7 @@ public: |
| 2255 | 2258 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const |
| 2256 | 2259 | {return __table_.__addable(&__i->__i_, __n);} |
| 2257 | 2260 | |
| 2258 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2261 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2259 | 2262 | |
| 2260 | 2263 | |
| 2261 | 2264 | }; |
| ... | ... | @@ -2518,7 +2521,7 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=( |
| 2518 | 2521 | return *this; |
| 2519 | 2522 | } |
| 2520 | 2523 | |
| 2521 | #endif // _LIBCPP_CXX03_LANG | |
| 2524 | #endif // _LIBCPP_CXX03_LANG | |
| 2522 | 2525 | |
| 2523 | 2526 | |
| 2524 | 2527 | |
| ... | ... | @@ -2550,7 +2553,7 @@ inline _LIBCPP_INLINE_VISIBILITY |
| 2550 | 2553 | typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type |
| 2551 | 2554 | erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, |
| 2552 | 2555 | _Predicate __pred) { |
| 2553 | return __libcpp_erase_if_container(__c, __pred); | |
| 2556 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 2554 | 2557 | } |
| 2555 | 2558 | #endif |
| 2556 | 2559 | |
| ... | ... | @@ -2588,4 +2591,4 @@ operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, |
| 2588 | 2591 | |
| 2589 | 2592 | _LIBCPP_END_NAMESPACE_STD |
| 2590 | 2593 | |
| 2591 | #endif // _LIBCPP_UNORDERED_MAP | |
| 2594 | #endif // _LIBCPP_UNORDERED_MAP |
lib/libcxx/include/unordered_set+24-21| ... | ... | @@ -387,13 +387,16 @@ template <class Value, class Hash, class Pred, class Alloc> |
| 387 | 387 | */ |
| 388 | 388 | |
| 389 | 389 | #include <__config> |
| 390 | #include <__debug> | |
| 391 | #include <__functional/is_transparent.h> | |
| 390 | 392 | #include <__hash_table> |
| 391 | 393 | #include <__node_handle> |
| 394 | #include <__utility/forward.h> | |
| 395 | #include <compare> | |
| 392 | 396 | #include <functional> |
| 397 | #include <iterator> // __libcpp_erase_if_container | |
| 393 | 398 | #include <version> |
| 394 | 399 | |
| 395 | #include <__debug> | |
| 396 | ||
| 397 | 400 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 398 | 401 | #pragma GCC system_header |
| 399 | 402 | #endif |
| ... | ... | @@ -411,9 +414,9 @@ public: |
| 411 | 414 | // types |
| 412 | 415 | typedef _Value key_type; |
| 413 | 416 | typedef key_type value_type; |
| 414 | typedef typename __identity<_Hash>::type hasher; | |
| 415 | typedef typename __identity<_Pred>::type key_equal; | |
| 416 | typedef typename __identity<_Alloc>::type allocator_type; | |
| 417 | typedef __identity_t<_Hash> hasher; | |
| 418 | typedef __identity_t<_Pred> key_equal; | |
| 419 | typedef __identity_t<_Alloc> allocator_type; | |
| 417 | 420 | typedef value_type& reference; |
| 418 | 421 | typedef const value_type& const_reference; |
| 419 | 422 | static_assert((is_same<value_type, typename allocator_type::value_type>::value), |
| ... | ... | @@ -512,7 +515,7 @@ public: |
| 512 | 515 | const hasher& __hf, const allocator_type& __a) |
| 513 | 516 | : unordered_set(__il, __n, __hf, key_equal(), __a) {} |
| 514 | 517 | #endif |
| 515 | #endif // _LIBCPP_CXX03_LANG | |
| 518 | #endif // _LIBCPP_CXX03_LANG | |
| 516 | 519 | _LIBCPP_INLINE_VISIBILITY |
| 517 | 520 | ~unordered_set() { |
| 518 | 521 | static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); |
| ... | ... | @@ -530,7 +533,7 @@ public: |
| 530 | 533 | _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); |
| 531 | 534 | _LIBCPP_INLINE_VISIBILITY |
| 532 | 535 | unordered_set& operator=(initializer_list<value_type> __il); |
| 533 | #endif // _LIBCPP_CXX03_LANG | |
| 536 | #endif // _LIBCPP_CXX03_LANG | |
| 534 | 537 | |
| 535 | 538 | _LIBCPP_INLINE_VISIBILITY |
| 536 | 539 | allocator_type get_allocator() const _NOEXCEPT |
| ... | ... | @@ -595,7 +598,7 @@ public: |
| 595 | 598 | _LIBCPP_INLINE_VISIBILITY |
| 596 | 599 | void insert(initializer_list<value_type> __il) |
| 597 | 600 | {insert(__il.begin(), __il.end());} |
| 598 | #endif // _LIBCPP_CXX03_LANG | |
| 601 | #endif // _LIBCPP_CXX03_LANG | |
| 599 | 602 | _LIBCPP_INLINE_VISIBILITY |
| 600 | 603 | pair<iterator, bool> insert(const value_type& __x) |
| 601 | 604 | {return __table_.__insert_unique(__x);} |
| ... | ... | @@ -792,7 +795,7 @@ public: |
| 792 | 795 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const |
| 793 | 796 | {return __table_.__addable(__i, __n);} |
| 794 | 797 | |
| 795 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 798 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 796 | 799 | |
| 797 | 800 | }; |
| 798 | 801 | |
| ... | ... | @@ -1039,7 +1042,7 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::operator=( |
| 1039 | 1042 | return *this; |
| 1040 | 1043 | } |
| 1041 | 1044 | |
| 1042 | #endif // _LIBCPP_CXX03_LANG | |
| 1045 | #endif // _LIBCPP_CXX03_LANG | |
| 1043 | 1046 | |
| 1044 | 1047 | template <class _Value, class _Hash, class _Pred, class _Alloc> |
| 1045 | 1048 | template <class _InputIterator> |
| ... | ... | @@ -1069,7 +1072,7 @@ inline _LIBCPP_INLINE_VISIBILITY |
| 1069 | 1072 | typename unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type |
| 1070 | 1073 | erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, |
| 1071 | 1074 | _Predicate __pred) { |
| 1072 | return __libcpp_erase_if_container(__c, __pred); | |
| 1075 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 1073 | 1076 | } |
| 1074 | 1077 | #endif |
| 1075 | 1078 | |
| ... | ... | @@ -1109,9 +1112,9 @@ public: |
| 1109 | 1112 | // types |
| 1110 | 1113 | typedef _Value key_type; |
| 1111 | 1114 | typedef key_type value_type; |
| 1112 | typedef typename __identity<_Hash>::type hasher; | |
| 1113 | typedef typename __identity<_Pred>::type key_equal; | |
| 1114 | typedef typename __identity<_Alloc>::type allocator_type; | |
| 1115 | typedef __identity_t<_Hash> hasher; | |
| 1116 | typedef __identity_t<_Pred> key_equal; | |
| 1117 | typedef __identity_t<_Alloc> allocator_type; | |
| 1115 | 1118 | typedef value_type& reference; |
| 1116 | 1119 | typedef const value_type& const_reference; |
| 1117 | 1120 | static_assert((is_same<value_type, typename allocator_type::value_type>::value), |
| ... | ... | @@ -1208,7 +1211,7 @@ public: |
| 1208 | 1211 | unordered_multiset(initializer_list<value_type> __il, size_type __n, const hasher& __hf, const allocator_type& __a) |
| 1209 | 1212 | : unordered_multiset(__il, __n, __hf, key_equal(), __a) {} |
| 1210 | 1213 | #endif |
| 1211 | #endif // _LIBCPP_CXX03_LANG | |
| 1214 | #endif // _LIBCPP_CXX03_LANG | |
| 1212 | 1215 | _LIBCPP_INLINE_VISIBILITY |
| 1213 | 1216 | ~unordered_multiset() { |
| 1214 | 1217 | static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); |
| ... | ... | @@ -1225,7 +1228,7 @@ public: |
| 1225 | 1228 | unordered_multiset& operator=(unordered_multiset&& __u) |
| 1226 | 1229 | _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); |
| 1227 | 1230 | unordered_multiset& operator=(initializer_list<value_type> __il); |
| 1228 | #endif // _LIBCPP_CXX03_LANG | |
| 1231 | #endif // _LIBCPP_CXX03_LANG | |
| 1229 | 1232 | |
| 1230 | 1233 | _LIBCPP_INLINE_VISIBILITY |
| 1231 | 1234 | allocator_type get_allocator() const _NOEXCEPT |
| ... | ... | @@ -1269,7 +1272,7 @@ public: |
| 1269 | 1272 | _LIBCPP_INLINE_VISIBILITY |
| 1270 | 1273 | void insert(initializer_list<value_type> __il) |
| 1271 | 1274 | {insert(__il.begin(), __il.end());} |
| 1272 | #endif // _LIBCPP_CXX03_LANG | |
| 1275 | #endif // _LIBCPP_CXX03_LANG | |
| 1273 | 1276 | |
| 1274 | 1277 | _LIBCPP_INLINE_VISIBILITY |
| 1275 | 1278 | iterator insert(const value_type& __x) {return __table_.__insert_multi(__x);} |
| ... | ... | @@ -1458,7 +1461,7 @@ public: |
| 1458 | 1461 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const |
| 1459 | 1462 | {return __table_.__addable(__i, __n);} |
| 1460 | 1463 | |
| 1461 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1464 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 1462 | 1465 | |
| 1463 | 1466 | }; |
| 1464 | 1467 | |
| ... | ... | @@ -1705,7 +1708,7 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::operator=( |
| 1705 | 1708 | return *this; |
| 1706 | 1709 | } |
| 1707 | 1710 | |
| 1708 | #endif // _LIBCPP_CXX03_LANG | |
| 1711 | #endif // _LIBCPP_CXX03_LANG | |
| 1709 | 1712 | |
| 1710 | 1713 | template <class _Value, class _Hash, class _Pred, class _Alloc> |
| 1711 | 1714 | template <class _InputIterator> |
| ... | ... | @@ -1735,7 +1738,7 @@ inline _LIBCPP_INLINE_VISIBILITY |
| 1735 | 1738 | typename unordered_multiset<_Value, _Hash, _Pred, _Alloc>::size_type |
| 1736 | 1739 | erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, |
| 1737 | 1740 | _Predicate __pred) { |
| 1738 | return __libcpp_erase_if_container(__c, __pred); | |
| 1741 | return _VSTD::__libcpp_erase_if_container(__c, __pred); | |
| 1739 | 1742 | } |
| 1740 | 1743 | #endif |
| 1741 | 1744 | |
| ... | ... | @@ -1773,4 +1776,4 @@ operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, |
| 1773 | 1776 | |
| 1774 | 1777 | _LIBCPP_END_NAMESPACE_STD |
| 1775 | 1778 | |
| 1776 | #endif // _LIBCPP_UNORDERED_SET | |
| 1779 | #endif // _LIBCPP_UNORDERED_SET |
lib/libcxx/include/utility+35-1434| ... | ... | @@ -58,6 +58,14 @@ template <class T> void as_const(const T&&) = delete; // C+ |
| 58 | 58 | |
| 59 | 59 | template <class T> typename add_rvalue_reference<T>::type declval() noexcept; |
| 60 | 60 | |
| 61 | template<class T, class U> constexpr bool cmp_equal(T t, U u) noexcept; // C++20 | |
| 62 | template<class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept; // C++20 | |
| 63 | template<class T, class U> constexpr bool cmp_less(T t, U u) noexcept; // C++20 | |
| 64 | template<class T, class U> constexpr bool cmp_greater(T t, U u) noexcept; // C++20 | |
| 65 | template<class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept; // C++20 | |
| 66 | template<class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept; // C++20 | |
| 67 | template<class R, class T> constexpr bool in_range(T t) noexcept; // C++20 | |
| 68 | ||
| 61 | 69 | template <class T1, class T2> |
| 62 | 70 | struct pair |
| 63 | 71 | { |
| ... | ... | @@ -76,15 +84,15 @@ struct pair |
| 76 | 84 | template <class U, class V> explicit(see-below) pair(pair<U, V>&& p); // constexpr in C++14 |
| 77 | 85 | template <class... Args1, class... Args2> |
| 78 | 86 | pair(piecewise_construct_t, tuple<Args1...> first_args, |
| 79 | tuple<Args2...> second_args); | |
| 87 | tuple<Args2...> second_args); // constexpr in C++20 | |
| 80 | 88 | |
| 81 | template <class U, class V> pair& operator=(const pair<U, V>& p); | |
| 89 | template <class U, class V> pair& operator=(const pair<U, V>& p); // constexpr in C++20 | |
| 82 | 90 | pair& operator=(pair&& p) noexcept(is_nothrow_move_assignable<T1>::value && |
| 83 | is_nothrow_move_assignable<T2>::value); | |
| 84 | template <class U, class V> pair& operator=(pair<U, V>&& p); | |
| 91 | is_nothrow_move_assignable<T2>::value); // constexpr in C++20 | |
| 92 | template <class U, class V> pair& operator=(pair<U, V>&& p); // constexpr in C++20 | |
| 85 | 93 | |
| 86 | 94 | void swap(pair& p) noexcept(is_nothrow_swappable_v<T1> && |
| 87 | is_nothrow_swappable_v<T2>); | |
| 95 | is_nothrow_swappable_v<T2>); // constexpr in C++20 | |
| 88 | 96 | }; |
| 89 | 97 | |
| 90 | 98 | template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14 |
| ... | ... | @@ -94,10 +102,10 @@ template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1, |
| 94 | 102 | template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14 |
| 95 | 103 | template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14 |
| 96 | 104 | |
| 97 | template <class T1, class T2> pair<V1, V2> make_pair(T1&&, T2&&); // constexpr in C++14 | |
| 105 | template <class T1, class T2> pair<V1, V2> make_pair(T1&&, T2&&); // constexpr in C++14 | |
| 98 | 106 | template <class T1, class T2> |
| 99 | 107 | void |
| 100 | swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); | |
| 108 | swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20 | |
| 101 | 109 | |
| 102 | 110 | struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; |
| 103 | 111 | inline constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); |
| ... | ... | @@ -191,1439 +199,32 @@ template <size_t I> |
| 191 | 199 | template <size_t I> |
| 192 | 200 | inline constexpr in_place_index_t<I> in_place_index{}; |
| 193 | 201 | |
| 202 | // [utility.underlying], to_underlying | |
| 203 | template <class T> | |
| 204 | constexpr underlying_type_t<T> to_underlying( T value ) noexcept; // C++2b | |
| 205 | ||
| 194 | 206 | } // std |
| 195 | 207 | |
| 196 | 208 | */ |
| 197 | 209 | |
| 198 | 210 | #include <__config> |
| 211 | #include <__debug> | |
| 199 | 212 | #include <__tuple> |
| 200 | #include <type_traits> | |
| 213 | #include <__utility/as_const.h> | |
| 214 | #include <__utility/cmp.h> | |
| 215 | #include <__utility/declval.h> | |
| 216 | #include <__utility/exchange.h> | |
| 217 | #include <__utility/forward.h> | |
| 218 | #include <__utility/in_place.h> | |
| 219 | #include <__utility/integer_sequence.h> | |
| 220 | #include <__utility/move.h> | |
| 221 | #include <__utility/pair.h> | |
| 222 | #include <__utility/piecewise_construct.h> | |
| 223 | #include <__utility/rel_ops.h> | |
| 224 | #include <__utility/swap.h> | |
| 225 | #include <__utility/to_underlying.h> | |
| 226 | #include <compare> | |
| 201 | 227 | #include <initializer_list> |
| 202 | #include <cstddef> | |
| 203 | #include <cstring> | |
| 204 | #include <cstdint> | |
| 205 | 228 | #include <version> |
| 206 | #include <__debug> | |
| 207 | ||
| 208 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 209 | #pragma GCC system_header | |
| 210 | #endif | |
| 211 | ||
| 212 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 213 | ||
| 214 | namespace rel_ops | |
| 215 | { | |
| 216 | ||
| 217 | template<class _Tp> | |
| 218 | inline _LIBCPP_INLINE_VISIBILITY | |
| 219 | bool | |
| 220 | operator!=(const _Tp& __x, const _Tp& __y) | |
| 221 | { | |
| 222 | return !(__x == __y); | |
| 223 | } | |
| 224 | ||
| 225 | template<class _Tp> | |
| 226 | inline _LIBCPP_INLINE_VISIBILITY | |
| 227 | bool | |
| 228 | operator> (const _Tp& __x, const _Tp& __y) | |
| 229 | { | |
| 230 | return __y < __x; | |
| 231 | } | |
| 232 | ||
| 233 | template<class _Tp> | |
| 234 | inline _LIBCPP_INLINE_VISIBILITY | |
| 235 | bool | |
| 236 | operator<=(const _Tp& __x, const _Tp& __y) | |
| 237 | { | |
| 238 | return !(__y < __x); | |
| 239 | } | |
| 240 | ||
| 241 | template<class _Tp> | |
| 242 | inline _LIBCPP_INLINE_VISIBILITY | |
| 243 | bool | |
| 244 | operator>=(const _Tp& __x, const _Tp& __y) | |
| 245 | { | |
| 246 | return !(__x < __y); | |
| 247 | } | |
| 248 | ||
| 249 | } // rel_ops | |
| 250 | ||
| 251 | // swap_ranges is defined in <type_traits>` | |
| 252 | ||
| 253 | // swap is defined in <type_traits> | |
| 254 | ||
| 255 | // move_if_noexcept | |
| 256 | ||
| 257 | template <class _Tp> | |
| 258 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 259 | #ifndef _LIBCPP_CXX03_LANG | |
| 260 | typename conditional | |
| 261 | < | |
| 262 | !is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value, | |
| 263 | const _Tp&, | |
| 264 | _Tp&& | |
| 265 | >::type | |
| 266 | #else // _LIBCPP_CXX03_LANG | |
| 267 | const _Tp& | |
| 268 | #endif | |
| 269 | move_if_noexcept(_Tp& __x) _NOEXCEPT | |
| 270 | { | |
| 271 | return _VSTD::move(__x); | |
| 272 | } | |
| 273 | ||
| 274 | #if _LIBCPP_STD_VER > 14 | |
| 275 | template <class _Tp> constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } | |
| 276 | template <class _Tp> void as_const(const _Tp&&) = delete; | |
| 277 | #endif | |
| 278 | ||
| 279 | struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { explicit piecewise_construct_t() = default; }; | |
| 280 | #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) | |
| 281 | extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;// = piecewise_construct_t(); | |
| 282 | #else | |
| 283 | /* _LIBCPP_INLINE_VAR */ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); | |
| 284 | #endif | |
| 285 | ||
| 286 | #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) | |
| 287 | template <class, class> | |
| 288 | struct __non_trivially_copyable_base { | |
| 289 | _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY | |
| 290 | __non_trivially_copyable_base() _NOEXCEPT {} | |
| 291 | _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY | |
| 292 | __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {} | |
| 293 | }; | |
| 294 | #endif | |
| 295 | ||
| 296 | template <class _T1, class _T2> | |
| 297 | struct _LIBCPP_TEMPLATE_VIS pair | |
| 298 | #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) | |
| 299 | : private __non_trivially_copyable_base<_T1, _T2> | |
| 300 | #endif | |
| 301 | { | |
| 302 | typedef _T1 first_type; | |
| 303 | typedef _T2 second_type; | |
| 304 | ||
| 305 | _T1 first; | |
| 306 | _T2 second; | |
| 307 | ||
| 308 | #if !defined(_LIBCPP_CXX03_LANG) | |
| 309 | pair(pair const&) = default; | |
| 310 | pair(pair&&) = default; | |
| 311 | #else | |
| 312 | // Use the implicitly declared copy constructor in C++03 | |
| 313 | #endif | |
| 314 | ||
| 315 | #ifdef _LIBCPP_CXX03_LANG | |
| 316 | _LIBCPP_INLINE_VISIBILITY | |
| 317 | pair() : first(), second() {} | |
| 318 | ||
| 319 | _LIBCPP_INLINE_VISIBILITY | |
| 320 | pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {} | |
| 321 | ||
| 322 | template <class _U1, class _U2> | |
| 323 | _LIBCPP_INLINE_VISIBILITY | |
| 324 | pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {} | |
| 325 | ||
| 326 | _LIBCPP_INLINE_VISIBILITY | |
| 327 | pair& operator=(pair const& __p) { | |
| 328 | first = __p.first; | |
| 329 | second = __p.second; | |
| 330 | return *this; | |
| 331 | } | |
| 332 | #else | |
| 333 | template <bool _Val> | |
| 334 | using _EnableB _LIBCPP_NODEBUG_TYPE = typename enable_if<_Val, bool>::type; | |
| 335 | ||
| 336 | struct _CheckArgs { | |
| 337 | template <int&...> | |
| 338 | static constexpr bool __enable_explicit_default() { | |
| 339 | return is_default_constructible<_T1>::value | |
| 340 | && is_default_constructible<_T2>::value | |
| 341 | && !__enable_implicit_default<>(); | |
| 342 | } | |
| 343 | ||
| 344 | template <int&...> | |
| 345 | static constexpr bool __enable_implicit_default() { | |
| 346 | return __is_implicitly_default_constructible<_T1>::value | |
| 347 | && __is_implicitly_default_constructible<_T2>::value; | |
| 348 | } | |
| 349 | ||
| 350 | template <class _U1, class _U2> | |
| 351 | static constexpr bool __enable_explicit() { | |
| 352 | return is_constructible<first_type, _U1>::value | |
| 353 | && is_constructible<second_type, _U2>::value | |
| 354 | && (!is_convertible<_U1, first_type>::value | |
| 355 | || !is_convertible<_U2, second_type>::value); | |
| 356 | } | |
| 357 | ||
| 358 | template <class _U1, class _U2> | |
| 359 | static constexpr bool __enable_implicit() { | |
| 360 | return is_constructible<first_type, _U1>::value | |
| 361 | && is_constructible<second_type, _U2>::value | |
| 362 | && is_convertible<_U1, first_type>::value | |
| 363 | && is_convertible<_U2, second_type>::value; | |
| 364 | } | |
| 365 | }; | |
| 366 | ||
| 367 | template <bool _MaybeEnable> | |
| 368 | using _CheckArgsDep _LIBCPP_NODEBUG_TYPE = typename conditional< | |
| 369 | _MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type; | |
| 370 | ||
| 371 | struct _CheckTupleLikeConstructor { | |
| 372 | template <class _Tuple> | |
| 373 | static constexpr bool __enable_implicit() { | |
| 374 | return __tuple_convertible<_Tuple, pair>::value; | |
| 375 | } | |
| 376 | ||
| 377 | template <class _Tuple> | |
| 378 | static constexpr bool __enable_explicit() { | |
| 379 | return __tuple_constructible<_Tuple, pair>::value | |
| 380 | && !__tuple_convertible<_Tuple, pair>::value; | |
| 381 | } | |
| 382 | ||
| 383 | template <class _Tuple> | |
| 384 | static constexpr bool __enable_assign() { | |
| 385 | return __tuple_assignable<_Tuple, pair>::value; | |
| 386 | } | |
| 387 | }; | |
| 388 | ||
| 389 | template <class _Tuple> | |
| 390 | using _CheckTLC _LIBCPP_NODEBUG_TYPE = typename conditional< | |
| 391 | __tuple_like_with_size<_Tuple, 2>::value | |
| 392 | && !is_same<typename decay<_Tuple>::type, pair>::value, | |
| 393 | _CheckTupleLikeConstructor, | |
| 394 | __check_tuple_constructor_fail | |
| 395 | >::type; | |
| 396 | ||
| 397 | template<bool _Dummy = true, _EnableB< | |
| 398 | _CheckArgsDep<_Dummy>::__enable_explicit_default() | |
| 399 | > = false> | |
| 400 | explicit _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 401 | pair() _NOEXCEPT_(is_nothrow_default_constructible<first_type>::value && | |
| 402 | is_nothrow_default_constructible<second_type>::value) | |
| 403 | : first(), second() {} | |
| 404 | ||
| 405 | template<bool _Dummy = true, _EnableB< | |
| 406 | _CheckArgsDep<_Dummy>::__enable_implicit_default() | |
| 407 | > = false> | |
| 408 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR | |
| 409 | pair() _NOEXCEPT_(is_nothrow_default_constructible<first_type>::value && | |
| 410 | is_nothrow_default_constructible<second_type>::value) | |
| 411 | : first(), second() {} | |
| 412 | ||
| 413 | template <bool _Dummy = true, _EnableB< | |
| 414 | _CheckArgsDep<_Dummy>::template __enable_explicit<_T1 const&, _T2 const&>() | |
| 415 | > = false> | |
| 416 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 417 | explicit pair(_T1 const& __t1, _T2 const& __t2) | |
| 418 | _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && | |
| 419 | is_nothrow_copy_constructible<second_type>::value) | |
| 420 | : first(__t1), second(__t2) {} | |
| 421 | ||
| 422 | template<bool _Dummy = true, _EnableB< | |
| 423 | _CheckArgsDep<_Dummy>::template __enable_implicit<_T1 const&, _T2 const&>() | |
| 424 | > = false> | |
| 425 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 426 | pair(_T1 const& __t1, _T2 const& __t2) | |
| 427 | _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && | |
| 428 | is_nothrow_copy_constructible<second_type>::value) | |
| 429 | : first(__t1), second(__t2) {} | |
| 430 | ||
| 431 | template<class _U1, class _U2, _EnableB< | |
| 432 | _CheckArgs::template __enable_explicit<_U1, _U2>() | |
| 433 | > = false> | |
| 434 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 435 | explicit pair(_U1&& __u1, _U2&& __u2) | |
| 436 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && | |
| 437 | is_nothrow_constructible<second_type, _U2>::value)) | |
| 438 | : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} | |
| 439 | ||
| 440 | template<class _U1, class _U2, _EnableB< | |
| 441 | _CheckArgs::template __enable_implicit<_U1, _U2>() | |
| 442 | > = false> | |
| 443 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 444 | pair(_U1&& __u1, _U2&& __u2) | |
| 445 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && | |
| 446 | is_nothrow_constructible<second_type, _U2>::value)) | |
| 447 | : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} | |
| 448 | ||
| 449 | template<class _U1, class _U2, _EnableB< | |
| 450 | _CheckArgs::template __enable_explicit<_U1 const&, _U2 const&>() | |
| 451 | > = false> | |
| 452 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 453 | explicit pair(pair<_U1, _U2> const& __p) | |
| 454 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && | |
| 455 | is_nothrow_constructible<second_type, _U2 const&>::value)) | |
| 456 | : first(__p.first), second(__p.second) {} | |
| 457 | ||
| 458 | template<class _U1, class _U2, _EnableB< | |
| 459 | _CheckArgs::template __enable_implicit<_U1 const&, _U2 const&>() | |
| 460 | > = false> | |
| 461 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 462 | pair(pair<_U1, _U2> const& __p) | |
| 463 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && | |
| 464 | is_nothrow_constructible<second_type, _U2 const&>::value)) | |
| 465 | : first(__p.first), second(__p.second) {} | |
| 466 | ||
| 467 | template<class _U1, class _U2, _EnableB< | |
| 468 | _CheckArgs::template __enable_explicit<_U1, _U2>() | |
| 469 | > = false> | |
| 470 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 471 | explicit pair(pair<_U1, _U2>&&__p) | |
| 472 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && | |
| 473 | is_nothrow_constructible<second_type, _U2&&>::value)) | |
| 474 | : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} | |
| 475 | ||
| 476 | template<class _U1, class _U2, _EnableB< | |
| 477 | _CheckArgs::template __enable_implicit<_U1, _U2>() | |
| 478 | > = false> | |
| 479 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 480 | pair(pair<_U1, _U2>&& __p) | |
| 481 | _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && | |
| 482 | is_nothrow_constructible<second_type, _U2&&>::value)) | |
| 483 | : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} | |
| 484 | ||
| 485 | template<class _Tuple, _EnableB< | |
| 486 | _CheckTLC<_Tuple>::template __enable_explicit<_Tuple>() | |
| 487 | > = false> | |
| 488 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 489 | explicit pair(_Tuple&& __p) | |
| 490 | : first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))), | |
| 491 | second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} | |
| 492 | ||
| 493 | template<class _Tuple, _EnableB< | |
| 494 | _CheckTLC<_Tuple>::template __enable_implicit<_Tuple>() | |
| 495 | > = false> | |
| 496 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 497 | pair(_Tuple&& __p) | |
| 498 | : first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))), | |
| 499 | second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} | |
| 500 | ||
| 501 | template <class... _Args1, class... _Args2> | |
| 502 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 503 | pair(piecewise_construct_t __pc, | |
| 504 | tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) | |
| 505 | _NOEXCEPT_((is_nothrow_constructible<first_type, _Args1...>::value && | |
| 506 | is_nothrow_constructible<second_type, _Args2...>::value)) | |
| 507 | : pair(__pc, __first_args, __second_args, | |
| 508 | typename __make_tuple_indices<sizeof...(_Args1)>::type(), | |
| 509 | typename __make_tuple_indices<sizeof...(_Args2) >::type()) {} | |
| 510 | ||
| 511 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 512 | pair& operator=(typename conditional< | |
| 513 | is_copy_assignable<first_type>::value && | |
| 514 | is_copy_assignable<second_type>::value, | |
| 515 | pair, __nat>::type const& __p) | |
| 516 | _NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value && | |
| 517 | is_nothrow_copy_assignable<second_type>::value) | |
| 518 | { | |
| 519 | first = __p.first; | |
| 520 | second = __p.second; | |
| 521 | return *this; | |
| 522 | } | |
| 523 | ||
| 524 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 525 | pair& operator=(typename conditional< | |
| 526 | is_move_assignable<first_type>::value && | |
| 527 | is_move_assignable<second_type>::value, | |
| 528 | pair, __nat>::type&& __p) | |
| 529 | _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value && | |
| 530 | is_nothrow_move_assignable<second_type>::value) | |
| 531 | { | |
| 532 | first = _VSTD::forward<first_type>(__p.first); | |
| 533 | second = _VSTD::forward<second_type>(__p.second); | |
| 534 | return *this; | |
| 535 | } | |
| 536 | ||
| 537 | template <class _Tuple, _EnableB< | |
| 538 | _CheckTLC<_Tuple>::template __enable_assign<_Tuple>() | |
| 539 | > = false> | |
| 540 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 541 | pair& operator=(_Tuple&& __p) { | |
| 542 | first = _VSTD::get<0>(_VSTD::forward<_Tuple>(__p)); | |
| 543 | second = _VSTD::get<1>(_VSTD::forward<_Tuple>(__p)); | |
| 544 | return *this; | |
| 545 | } | |
| 546 | #endif | |
| 547 | ||
| 548 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 549 | void | |
| 550 | swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable<first_type>::value && | |
| 551 | __is_nothrow_swappable<second_type>::value) | |
| 552 | { | |
| 553 | using _VSTD::swap; | |
| 554 | swap(first, __p.first); | |
| 555 | swap(second, __p.second); | |
| 556 | } | |
| 557 | private: | |
| 558 | ||
| 559 | #ifndef _LIBCPP_CXX03_LANG | |
| 560 | template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2> | |
| 561 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 562 | pair(piecewise_construct_t, | |
| 563 | tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, | |
| 564 | __tuple_indices<_I1...>, __tuple_indices<_I2...>); | |
| 565 | #endif | |
| 566 | }; | |
| 567 | ||
| 568 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 569 | template<class _T1, class _T2> | |
| 570 | pair(_T1, _T2) -> pair<_T1, _T2>; | |
| 571 | #endif // _LIBCPP_HAS_NO_DEDUCTION_GUIDES | |
| 572 | ||
| 573 | template <class _T1, class _T2> | |
| 574 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 575 | bool | |
| 576 | operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 577 | { | |
| 578 | return __x.first == __y.first && __x.second == __y.second; | |
| 579 | } | |
| 580 | ||
| 581 | template <class _T1, class _T2> | |
| 582 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 583 | bool | |
| 584 | operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 585 | { | |
| 586 | return !(__x == __y); | |
| 587 | } | |
| 588 | ||
| 589 | template <class _T1, class _T2> | |
| 590 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 591 | bool | |
| 592 | operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 593 | { | |
| 594 | return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second); | |
| 595 | } | |
| 596 | ||
| 597 | template <class _T1, class _T2> | |
| 598 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 599 | bool | |
| 600 | operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 601 | { | |
| 602 | return __y < __x; | |
| 603 | } | |
| 604 | ||
| 605 | template <class _T1, class _T2> | |
| 606 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 607 | bool | |
| 608 | operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 609 | { | |
| 610 | return !(__x < __y); | |
| 611 | } | |
| 612 | ||
| 613 | template <class _T1, class _T2> | |
| 614 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 615 | bool | |
| 616 | operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) | |
| 617 | { | |
| 618 | return !(__y < __x); | |
| 619 | } | |
| 620 | ||
| 621 | template <class _T1, class _T2> | |
| 622 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 623 | typename enable_if | |
| 624 | < | |
| 625 | __is_swappable<_T1>::value && | |
| 626 | __is_swappable<_T2>::value, | |
| 627 | void | |
| 628 | >::type | |
| 629 | swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) | |
| 630 | _NOEXCEPT_((__is_nothrow_swappable<_T1>::value && | |
| 631 | __is_nothrow_swappable<_T2>::value)) | |
| 632 | { | |
| 633 | __x.swap(__y); | |
| 634 | } | |
| 635 | ||
| 636 | template <class _Tp> | |
| 637 | struct __unwrap_reference { typedef _LIBCPP_NODEBUG_TYPE _Tp type; }; | |
| 638 | ||
| 639 | template <class _Tp> | |
| 640 | struct __unwrap_reference<reference_wrapper<_Tp> > { typedef _LIBCPP_NODEBUG_TYPE _Tp& type; }; | |
| 641 | ||
| 642 | #if _LIBCPP_STD_VER > 17 | |
| 643 | template <class _Tp> | |
| 644 | struct unwrap_reference : __unwrap_reference<_Tp> { }; | |
| 645 | ||
| 646 | template <class _Tp> | |
| 647 | struct unwrap_ref_decay : unwrap_reference<typename decay<_Tp>::type> { }; | |
| 648 | #endif // > C++17 | |
| 649 | ||
| 650 | template <class _Tp> | |
| 651 | struct __unwrap_ref_decay | |
| 652 | #if _LIBCPP_STD_VER > 17 | |
| 653 | : unwrap_ref_decay<_Tp> | |
| 654 | #else | |
| 655 | : __unwrap_reference<typename decay<_Tp>::type> | |
| 656 | #endif | |
| 657 | { }; | |
| 658 | ||
| 659 | #ifndef _LIBCPP_CXX03_LANG | |
| 660 | ||
| 661 | template <class _T1, class _T2> | |
| 662 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 663 | pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> | |
| 664 | make_pair(_T1&& __t1, _T2&& __t2) | |
| 665 | { | |
| 666 | return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> | |
| 667 | (_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2)); | |
| 668 | } | |
| 669 | ||
| 670 | #else // _LIBCPP_CXX03_LANG | |
| 671 | ||
| 672 | template <class _T1, class _T2> | |
| 673 | inline _LIBCPP_INLINE_VISIBILITY | |
| 674 | pair<_T1,_T2> | |
| 675 | make_pair(_T1 __x, _T2 __y) | |
| 676 | { | |
| 677 | return pair<_T1, _T2>(__x, __y); | |
| 678 | } | |
| 679 | ||
| 680 | #endif // _LIBCPP_CXX03_LANG | |
| 681 | ||
| 682 | template <class _T1, class _T2> | |
| 683 | struct _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > | |
| 684 | : public integral_constant<size_t, 2> {}; | |
| 685 | ||
| 686 | template <size_t _Ip, class _T1, class _T2> | |
| 687 | struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, pair<_T1, _T2> > | |
| 688 | { | |
| 689 | static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::pair<T1, T2>>"); | |
| 690 | }; | |
| 691 | ||
| 692 | template <class _T1, class _T2> | |
| 693 | struct _LIBCPP_TEMPLATE_VIS tuple_element<0, pair<_T1, _T2> > | |
| 694 | { | |
| 695 | typedef _LIBCPP_NODEBUG_TYPE _T1 type; | |
| 696 | }; | |
| 697 | ||
| 698 | template <class _T1, class _T2> | |
| 699 | struct _LIBCPP_TEMPLATE_VIS tuple_element<1, pair<_T1, _T2> > | |
| 700 | { | |
| 701 | typedef _LIBCPP_NODEBUG_TYPE _T2 type; | |
| 702 | }; | |
| 703 | ||
| 704 | template <size_t _Ip> struct __get_pair; | |
| 705 | ||
| 706 | template <> | |
| 707 | struct __get_pair<0> | |
| 708 | { | |
| 709 | template <class _T1, class _T2> | |
| 710 | static | |
| 711 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 712 | _T1& | |
| 713 | get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;} | |
| 714 | ||
| 715 | template <class _T1, class _T2> | |
| 716 | static | |
| 717 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 718 | const _T1& | |
| 719 | get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;} | |
| 720 | ||
| 721 | #ifndef _LIBCPP_CXX03_LANG | |
| 722 | template <class _T1, class _T2> | |
| 723 | static | |
| 724 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 725 | _T1&& | |
| 726 | get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T1>(__p.first);} | |
| 727 | ||
| 728 | template <class _T1, class _T2> | |
| 729 | static | |
| 730 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 731 | const _T1&& | |
| 732 | get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<const _T1>(__p.first);} | |
| 733 | #endif // _LIBCPP_CXX03_LANG | |
| 734 | }; | |
| 735 | ||
| 736 | template <> | |
| 737 | struct __get_pair<1> | |
| 738 | { | |
| 739 | template <class _T1, class _T2> | |
| 740 | static | |
| 741 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 742 | _T2& | |
| 743 | get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;} | |
| 744 | ||
| 745 | template <class _T1, class _T2> | |
| 746 | static | |
| 747 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 748 | const _T2& | |
| 749 | get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;} | |
| 750 | ||
| 751 | #ifndef _LIBCPP_CXX03_LANG | |
| 752 | template <class _T1, class _T2> | |
| 753 | static | |
| 754 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 755 | _T2&& | |
| 756 | get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T2>(__p.second);} | |
| 757 | ||
| 758 | template <class _T1, class _T2> | |
| 759 | static | |
| 760 | _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 761 | const _T2&& | |
| 762 | get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<const _T2>(__p.second);} | |
| 763 | #endif // _LIBCPP_CXX03_LANG | |
| 764 | }; | |
| 765 | ||
| 766 | template <size_t _Ip, class _T1, class _T2> | |
| 767 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 768 | typename tuple_element<_Ip, pair<_T1, _T2> >::type& | |
| 769 | get(pair<_T1, _T2>& __p) _NOEXCEPT | |
| 770 | { | |
| 771 | return __get_pair<_Ip>::get(__p); | |
| 772 | } | |
| 773 | ||
| 774 | template <size_t _Ip, class _T1, class _T2> | |
| 775 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 776 | const typename tuple_element<_Ip, pair<_T1, _T2> >::type& | |
| 777 | get(const pair<_T1, _T2>& __p) _NOEXCEPT | |
| 778 | { | |
| 779 | return __get_pair<_Ip>::get(__p); | |
| 780 | } | |
| 781 | ||
| 782 | #ifndef _LIBCPP_CXX03_LANG | |
| 783 | template <size_t _Ip, class _T1, class _T2> | |
| 784 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 785 | typename tuple_element<_Ip, pair<_T1, _T2> >::type&& | |
| 786 | get(pair<_T1, _T2>&& __p) _NOEXCEPT | |
| 787 | { | |
| 788 | return __get_pair<_Ip>::get(_VSTD::move(__p)); | |
| 789 | } | |
| 790 | ||
| 791 | template <size_t _Ip, class _T1, class _T2> | |
| 792 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 | |
| 793 | const typename tuple_element<_Ip, pair<_T1, _T2> >::type&& | |
| 794 | get(const pair<_T1, _T2>&& __p) _NOEXCEPT | |
| 795 | { | |
| 796 | return __get_pair<_Ip>::get(_VSTD::move(__p)); | |
| 797 | } | |
| 798 | #endif // _LIBCPP_CXX03_LANG | |
| 799 | ||
| 800 | #if _LIBCPP_STD_VER > 11 | |
| 801 | template <class _T1, class _T2> | |
| 802 | inline _LIBCPP_INLINE_VISIBILITY | |
| 803 | constexpr _T1 & get(pair<_T1, _T2>& __p) _NOEXCEPT | |
| 804 | { | |
| 805 | return __get_pair<0>::get(__p); | |
| 806 | } | |
| 807 | ||
| 808 | template <class _T1, class _T2> | |
| 809 | inline _LIBCPP_INLINE_VISIBILITY | |
| 810 | constexpr _T1 const & get(pair<_T1, _T2> const& __p) _NOEXCEPT | |
| 811 | { | |
| 812 | return __get_pair<0>::get(__p); | |
| 813 | } | |
| 814 | ||
| 815 | template <class _T1, class _T2> | |
| 816 | inline _LIBCPP_INLINE_VISIBILITY | |
| 817 | constexpr _T1 && get(pair<_T1, _T2>&& __p) _NOEXCEPT | |
| 818 | { | |
| 819 | return __get_pair<0>::get(_VSTD::move(__p)); | |
| 820 | } | |
| 821 | ||
| 822 | template <class _T1, class _T2> | |
| 823 | inline _LIBCPP_INLINE_VISIBILITY | |
| 824 | constexpr _T1 const && get(pair<_T1, _T2> const&& __p) _NOEXCEPT | |
| 825 | { | |
| 826 | return __get_pair<0>::get(_VSTD::move(__p)); | |
| 827 | } | |
| 828 | ||
| 829 | template <class _T1, class _T2> | |
| 830 | inline _LIBCPP_INLINE_VISIBILITY | |
| 831 | constexpr _T1 & get(pair<_T2, _T1>& __p) _NOEXCEPT | |
| 832 | { | |
| 833 | return __get_pair<1>::get(__p); | |
| 834 | } | |
| 835 | ||
| 836 | template <class _T1, class _T2> | |
| 837 | inline _LIBCPP_INLINE_VISIBILITY | |
| 838 | constexpr _T1 const & get(pair<_T2, _T1> const& __p) _NOEXCEPT | |
| 839 | { | |
| 840 | return __get_pair<1>::get(__p); | |
| 841 | } | |
| 842 | ||
| 843 | template <class _T1, class _T2> | |
| 844 | inline _LIBCPP_INLINE_VISIBILITY | |
| 845 | constexpr _T1 && get(pair<_T2, _T1>&& __p) _NOEXCEPT | |
| 846 | { | |
| 847 | return __get_pair<1>::get(_VSTD::move(__p)); | |
| 848 | } | |
| 849 | ||
| 850 | template <class _T1, class _T2> | |
| 851 | inline _LIBCPP_INLINE_VISIBILITY | |
| 852 | constexpr _T1 const && get(pair<_T2, _T1> const&& __p) _NOEXCEPT | |
| 853 | { | |
| 854 | return __get_pair<1>::get(_VSTD::move(__p)); | |
| 855 | } | |
| 856 | ||
| 857 | #endif | |
| 858 | ||
| 859 | #if _LIBCPP_STD_VER > 11 | |
| 860 | ||
| 861 | template<class _Tp, _Tp... _Ip> | |
| 862 | struct _LIBCPP_TEMPLATE_VIS integer_sequence | |
| 863 | { | |
| 864 | typedef _Tp value_type; | |
| 865 | static_assert( is_integral<_Tp>::value, | |
| 866 | "std::integer_sequence can only be instantiated with an integral type" ); | |
| 867 | static | |
| 868 | _LIBCPP_INLINE_VISIBILITY | |
| 869 | constexpr | |
| 870 | size_t | |
| 871 | size() noexcept { return sizeof...(_Ip); } | |
| 872 | }; | |
| 873 | ||
| 874 | template<size_t... _Ip> | |
| 875 | using index_sequence = integer_sequence<size_t, _Ip...>; | |
| 876 | ||
| 877 | #if __has_builtin(__make_integer_seq) && !defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE) | |
| 878 | ||
| 879 | template <class _Tp, _Tp _Ep> | |
| 880 | using __make_integer_sequence _LIBCPP_NODEBUG_TYPE = __make_integer_seq<integer_sequence, _Tp, _Ep>; | |
| 881 | ||
| 882 | #else | |
| 883 | ||
| 884 | template<typename _Tp, _Tp _Np> using __make_integer_sequence_unchecked _LIBCPP_NODEBUG_TYPE = | |
| 885 | typename __detail::__make<_Np>::type::template __convert<integer_sequence, _Tp>; | |
| 886 | ||
| 887 | template <class _Tp, _Tp _Ep> | |
| 888 | struct __make_integer_sequence_checked | |
| 889 | { | |
| 890 | static_assert(is_integral<_Tp>::value, | |
| 891 | "std::make_integer_sequence can only be instantiated with an integral type" ); | |
| 892 | static_assert(0 <= _Ep, "std::make_integer_sequence must have a non-negative sequence length"); | |
| 893 | // Workaround GCC bug by preventing bad installations when 0 <= _Ep | |
| 894 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68929 | |
| 895 | typedef _LIBCPP_NODEBUG_TYPE __make_integer_sequence_unchecked<_Tp, 0 <= _Ep ? _Ep : 0> type; | |
| 896 | }; | |
| 897 | ||
| 898 | template <class _Tp, _Tp _Ep> | |
| 899 | using __make_integer_sequence _LIBCPP_NODEBUG_TYPE = typename __make_integer_sequence_checked<_Tp, _Ep>::type; | |
| 900 | ||
| 901 | #endif | |
| 902 | ||
| 903 | template<class _Tp, _Tp _Np> | |
| 904 | using make_integer_sequence = __make_integer_sequence<_Tp, _Np>; | |
| 905 | ||
| 906 | template<size_t _Np> | |
| 907 | using make_index_sequence = make_integer_sequence<size_t, _Np>; | |
| 908 | ||
| 909 | template<class... _Tp> | |
| 910 | using index_sequence_for = make_index_sequence<sizeof...(_Tp)>; | |
| 911 | ||
| 912 | #endif // _LIBCPP_STD_VER > 11 | |
| 913 | ||
| 914 | #if _LIBCPP_STD_VER > 11 | |
| 915 | template<class _T1, class _T2 = _T1> | |
| 916 | inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 | |
| 917 | _T1 exchange(_T1& __obj, _T2 && __new_value) | |
| 918 | { | |
| 919 | _T1 __old_value = _VSTD::move(__obj); | |
| 920 | __obj = _VSTD::forward<_T2>(__new_value); | |
| 921 | return __old_value; | |
| 922 | } | |
| 923 | #endif // _LIBCPP_STD_VER > 11 | |
| 924 | ||
| 925 | #if _LIBCPP_STD_VER > 14 | |
| 926 | ||
| 927 | struct _LIBCPP_TYPE_VIS in_place_t { | |
| 928 | explicit in_place_t() = default; | |
| 929 | }; | |
| 930 | _LIBCPP_INLINE_VAR constexpr in_place_t in_place{}; | |
| 931 | ||
| 932 | template <class _Tp> | |
| 933 | struct _LIBCPP_TEMPLATE_VIS in_place_type_t { | |
| 934 | explicit in_place_type_t() = default; | |
| 935 | }; | |
| 936 | template <class _Tp> | |
| 937 | _LIBCPP_INLINE_VAR constexpr in_place_type_t<_Tp> in_place_type{}; | |
| 938 | ||
| 939 | template <size_t _Idx> | |
| 940 | struct _LIBCPP_TYPE_VIS in_place_index_t { | |
| 941 | explicit in_place_index_t() = default; | |
| 942 | }; | |
| 943 | template <size_t _Idx> | |
| 944 | _LIBCPP_INLINE_VAR constexpr in_place_index_t<_Idx> in_place_index{}; | |
| 945 | ||
| 946 | template <class _Tp> struct __is_inplace_type_imp : false_type {}; | |
| 947 | template <class _Tp> struct __is_inplace_type_imp<in_place_type_t<_Tp>> : true_type {}; | |
| 948 | ||
| 949 | template <class _Tp> | |
| 950 | using __is_inplace_type = __is_inplace_type_imp<__uncvref_t<_Tp>>; | |
| 951 | ||
| 952 | template <class _Tp> struct __is_inplace_index_imp : false_type {}; | |
| 953 | template <size_t _Idx> struct __is_inplace_index_imp<in_place_index_t<_Idx>> : true_type {}; | |
| 954 | ||
| 955 | template <class _Tp> | |
| 956 | using __is_inplace_index = __is_inplace_index_imp<__uncvref_t<_Tp>>; | |
| 957 | ||
| 958 | #endif // _LIBCPP_STD_VER > 14 | |
| 959 | ||
| 960 | template <class _Arg, class _Result> | |
| 961 | struct _LIBCPP_TEMPLATE_VIS unary_function | |
| 962 | { | |
| 963 | typedef _Arg argument_type; | |
| 964 | typedef _Result result_type; | |
| 965 | }; | |
| 966 | ||
| 967 | template <class _Size> | |
| 968 | inline _LIBCPP_INLINE_VISIBILITY | |
| 969 | _Size | |
| 970 | __loadword(const void* __p) | |
| 971 | { | |
| 972 | _Size __r; | |
| 973 | _VSTD::memcpy(&__r, __p, sizeof(__r)); | |
| 974 | return __r; | |
| 975 | } | |
| 976 | ||
| 977 | // We use murmur2 when size_t is 32 bits, and cityhash64 when size_t | |
| 978 | // is 64 bits. This is because cityhash64 uses 64bit x 64bit | |
| 979 | // multiplication, which can be very slow on 32-bit systems. | |
| 980 | template <class _Size, size_t = sizeof(_Size)*__CHAR_BIT__> | |
| 981 | struct __murmur2_or_cityhash; | |
| 982 | ||
| 983 | template <class _Size> | |
| 984 | struct __murmur2_or_cityhash<_Size, 32> | |
| 985 | { | |
| 986 | inline _Size operator()(const void* __key, _Size __len) | |
| 987 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; | |
| 988 | }; | |
| 989 | ||
| 990 | // murmur2 | |
| 991 | template <class _Size> | |
| 992 | _Size | |
| 993 | __murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) | |
| 994 | { | |
| 995 | const _Size __m = 0x5bd1e995; | |
| 996 | const _Size __r = 24; | |
| 997 | _Size __h = __len; | |
| 998 | const unsigned char* __data = static_cast<const unsigned char*>(__key); | |
| 999 | for (; __len >= 4; __data += 4, __len -= 4) | |
| 1000 | { | |
| 1001 | _Size __k = __loadword<_Size>(__data); | |
| 1002 | __k *= __m; | |
| 1003 | __k ^= __k >> __r; | |
| 1004 | __k *= __m; | |
| 1005 | __h *= __m; | |
| 1006 | __h ^= __k; | |
| 1007 | } | |
| 1008 | switch (__len) | |
| 1009 | { | |
| 1010 | case 3: | |
| 1011 | __h ^= __data[2] << 16; | |
| 1012 | _LIBCPP_FALLTHROUGH(); | |
| 1013 | case 2: | |
| 1014 | __h ^= __data[1] << 8; | |
| 1015 | _LIBCPP_FALLTHROUGH(); | |
| 1016 | case 1: | |
| 1017 | __h ^= __data[0]; | |
| 1018 | __h *= __m; | |
| 1019 | } | |
| 1020 | __h ^= __h >> 13; | |
| 1021 | __h *= __m; | |
| 1022 | __h ^= __h >> 15; | |
| 1023 | return __h; | |
| 1024 | } | |
| 1025 | ||
| 1026 | template <class _Size> | |
| 1027 | struct __murmur2_or_cityhash<_Size, 64> | |
| 1028 | { | |
| 1029 | inline _Size operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; | |
| 1030 | ||
| 1031 | private: | |
| 1032 | // Some primes between 2^63 and 2^64. | |
| 1033 | static const _Size __k0 = 0xc3a5c85c97cb3127ULL; | |
| 1034 | static const _Size __k1 = 0xb492b66fbe98f273ULL; | |
| 1035 | static const _Size __k2 = 0x9ae16a3b2f90404fULL; | |
| 1036 | static const _Size __k3 = 0xc949d7c7509e6557ULL; | |
| 1037 | ||
| 1038 | static _Size __rotate(_Size __val, int __shift) { | |
| 1039 | return __shift == 0 ? __val : ((__val >> __shift) | (__val << (64 - __shift))); | |
| 1040 | } | |
| 1041 | ||
| 1042 | static _Size __rotate_by_at_least_1(_Size __val, int __shift) { | |
| 1043 | return (__val >> __shift) | (__val << (64 - __shift)); | |
| 1044 | } | |
| 1045 | ||
| 1046 | static _Size __shift_mix(_Size __val) { | |
| 1047 | return __val ^ (__val >> 47); | |
| 1048 | } | |
| 1049 | ||
| 1050 | static _Size __hash_len_16(_Size __u, _Size __v) | |
| 1051 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 1052 | { | |
| 1053 | const _Size __mul = 0x9ddfea08eb382d69ULL; | |
| 1054 | _Size __a = (__u ^ __v) * __mul; | |
| 1055 | __a ^= (__a >> 47); | |
| 1056 | _Size __b = (__v ^ __a) * __mul; | |
| 1057 | __b ^= (__b >> 47); | |
| 1058 | __b *= __mul; | |
| 1059 | return __b; | |
| 1060 | } | |
| 1061 | ||
| 1062 | static _Size __hash_len_0_to_16(const char* __s, _Size __len) | |
| 1063 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 1064 | { | |
| 1065 | if (__len > 8) { | |
| 1066 | const _Size __a = __loadword<_Size>(__s); | |
| 1067 | const _Size __b = __loadword<_Size>(__s + __len - 8); | |
| 1068 | return __hash_len_16(__a, __rotate_by_at_least_1(__b + __len, __len)) ^ __b; | |
| 1069 | } | |
| 1070 | if (__len >= 4) { | |
| 1071 | const uint32_t __a = __loadword<uint32_t>(__s); | |
| 1072 | const uint32_t __b = __loadword<uint32_t>(__s + __len - 4); | |
| 1073 | return __hash_len_16(__len + (__a << 3), __b); | |
| 1074 | } | |
| 1075 | if (__len > 0) { | |
| 1076 | const unsigned char __a = __s[0]; | |
| 1077 | const unsigned char __b = __s[__len >> 1]; | |
| 1078 | const unsigned char __c = __s[__len - 1]; | |
| 1079 | const uint32_t __y = static_cast<uint32_t>(__a) + | |
| 1080 | (static_cast<uint32_t>(__b) << 8); | |
| 1081 | const uint32_t __z = __len + (static_cast<uint32_t>(__c) << 2); | |
| 1082 | return __shift_mix(__y * __k2 ^ __z * __k3) * __k2; | |
| 1083 | } | |
| 1084 | return __k2; | |
| 1085 | } | |
| 1086 | ||
| 1087 | static _Size __hash_len_17_to_32(const char *__s, _Size __len) | |
| 1088 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 1089 | { | |
| 1090 | const _Size __a = __loadword<_Size>(__s) * __k1; | |
| 1091 | const _Size __b = __loadword<_Size>(__s + 8); | |
| 1092 | const _Size __c = __loadword<_Size>(__s + __len - 8) * __k2; | |
| 1093 | const _Size __d = __loadword<_Size>(__s + __len - 16) * __k0; | |
| 1094 | return __hash_len_16(__rotate(__a - __b, 43) + __rotate(__c, 30) + __d, | |
| 1095 | __a + __rotate(__b ^ __k3, 20) - __c + __len); | |
| 1096 | } | |
| 1097 | ||
| 1098 | // Return a 16-byte hash for 48 bytes. Quick and dirty. | |
| 1099 | // Callers do best to use "random-looking" values for a and b. | |
| 1100 | static pair<_Size, _Size> __weak_hash_len_32_with_seeds( | |
| 1101 | _Size __w, _Size __x, _Size __y, _Size __z, _Size __a, _Size __b) | |
| 1102 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 1103 | { | |
| 1104 | __a += __w; | |
| 1105 | __b = __rotate(__b + __a + __z, 21); | |
| 1106 | const _Size __c = __a; | |
| 1107 | __a += __x; | |
| 1108 | __a += __y; | |
| 1109 | __b += __rotate(__a, 44); | |
| 1110 | return pair<_Size, _Size>(__a + __z, __b + __c); | |
| 1111 | } | |
| 1112 | ||
| 1113 | // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. | |
| 1114 | static pair<_Size, _Size> __weak_hash_len_32_with_seeds( | |
| 1115 | const char* __s, _Size __a, _Size __b) | |
| 1116 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 1117 | { | |
| 1118 | return __weak_hash_len_32_with_seeds(__loadword<_Size>(__s), | |
| 1119 | __loadword<_Size>(__s + 8), | |
| 1120 | __loadword<_Size>(__s + 16), | |
| 1121 | __loadword<_Size>(__s + 24), | |
| 1122 | __a, | |
| 1123 | __b); | |
| 1124 | } | |
| 1125 | ||
| 1126 | // Return an 8-byte hash for 33 to 64 bytes. | |
| 1127 | static _Size __hash_len_33_to_64(const char *__s, size_t __len) | |
| 1128 | _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK | |
| 1129 | { | |
| 1130 | _Size __z = __loadword<_Size>(__s + 24); | |
| 1131 | _Size __a = __loadword<_Size>(__s) + | |
| 1132 | (__len + __loadword<_Size>(__s + __len - 16)) * __k0; | |
| 1133 | _Size __b = __rotate(__a + __z, 52); | |
| 1134 | _Size __c = __rotate(__a, 37); | |
| 1135 | __a += __loadword<_Size>(__s + 8); | |
| 1136 | __c += __rotate(__a, 7); | |
| 1137 | __a += __loadword<_Size>(__s + 16); | |
| 1138 | _Size __vf = __a + __z; | |
| 1139 | _Size __vs = __b + __rotate(__a, 31) + __c; | |
| 1140 | __a = __loadword<_Size>(__s + 16) + __loadword<_Size>(__s + __len - 32); | |
| 1141 | __z += __loadword<_Size>(__s + __len - 8); | |
| 1142 | __b = __rotate(__a + __z, 52); | |
| 1143 | __c = __rotate(__a, 37); | |
| 1144 | __a += __loadword<_Size>(__s + __len - 24); | |
| 1145 | __c += __rotate(__a, 7); | |
| 1146 | __a += __loadword<_Size>(__s + __len - 16); | |
| 1147 | _Size __wf = __a + __z; | |
| 1148 | _Size __ws = __b + __rotate(__a, 31) + __c; | |
| 1149 | _Size __r = __shift_mix((__vf + __ws) * __k2 + (__wf + __vs) * __k0); | |
| 1150 | return __shift_mix(__r * __k0 + __vs) * __k2; | |
| 1151 | } | |
| 1152 | }; | |
| 1153 | ||
| 1154 | // cityhash64 | |
| 1155 | template <class _Size> | |
| 1156 | _Size | |
| 1157 | __murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len) | |
| 1158 | { | |
| 1159 | const char* __s = static_cast<const char*>(__key); | |
| 1160 | if (__len <= 32) { | |
| 1161 | if (__len <= 16) { | |
| 1162 | return __hash_len_0_to_16(__s, __len); | |
| 1163 | } else { | |
| 1164 | return __hash_len_17_to_32(__s, __len); | |
| 1165 | } | |
| 1166 | } else if (__len <= 64) { | |
| 1167 | return __hash_len_33_to_64(__s, __len); | |
| 1168 | } | |
| 1169 | ||
| 1170 | // For strings over 64 bytes we hash the end first, and then as we | |
| 1171 | // loop we keep 56 bytes of state: v, w, x, y, and z. | |
| 1172 | _Size __x = __loadword<_Size>(__s + __len - 40); | |
| 1173 | _Size __y = __loadword<_Size>(__s + __len - 16) + | |
| 1174 | __loadword<_Size>(__s + __len - 56); | |
| 1175 | _Size __z = __hash_len_16(__loadword<_Size>(__s + __len - 48) + __len, | |
| 1176 | __loadword<_Size>(__s + __len - 24)); | |
| 1177 | pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); | |
| 1178 | pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); | |
| 1179 | __x = __x * __k1 + __loadword<_Size>(__s); | |
| 1180 | ||
| 1181 | // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. | |
| 1182 | __len = (__len - 1) & ~static_cast<_Size>(63); | |
| 1183 | do { | |
| 1184 | __x = __rotate(__x + __y + __v.first + __loadword<_Size>(__s + 8), 37) * __k1; | |
| 1185 | __y = __rotate(__y + __v.second + __loadword<_Size>(__s + 48), 42) * __k1; | |
| 1186 | __x ^= __w.second; | |
| 1187 | __y += __v.first + __loadword<_Size>(__s + 40); | |
| 1188 | __z = __rotate(__z + __w.first, 33) * __k1; | |
| 1189 | __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); | |
| 1190 | __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, | |
| 1191 | __y + __loadword<_Size>(__s + 16)); | |
| 1192 | _VSTD::swap(__z, __x); | |
| 1193 | __s += 64; | |
| 1194 | __len -= 64; | |
| 1195 | } while (__len != 0); | |
| 1196 | return __hash_len_16( | |
| 1197 | __hash_len_16(__v.first, __w.first) + __shift_mix(__y) * __k1 + __z, | |
| 1198 | __hash_len_16(__v.second, __w.second) + __x); | |
| 1199 | } | |
| 1200 | ||
| 1201 | template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)> | |
| 1202 | struct __scalar_hash; | |
| 1203 | ||
| 1204 | template <class _Tp> | |
| 1205 | struct __scalar_hash<_Tp, 0> | |
| 1206 | : public unary_function<_Tp, size_t> | |
| 1207 | { | |
| 1208 | _LIBCPP_INLINE_VISIBILITY | |
| 1209 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 1210 | { | |
| 1211 | union | |
| 1212 | { | |
| 1213 | _Tp __t; | |
| 1214 | size_t __a; | |
| 1215 | } __u; | |
| 1216 | __u.__a = 0; | |
| 1217 | __u.__t = __v; | |
| 1218 | return __u.__a; | |
| 1219 | } | |
| 1220 | }; | |
| 1221 | ||
| 1222 | template <class _Tp> | |
| 1223 | struct __scalar_hash<_Tp, 1> | |
| 1224 | : public unary_function<_Tp, size_t> | |
| 1225 | { | |
| 1226 | _LIBCPP_INLINE_VISIBILITY | |
| 1227 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 1228 | { | |
| 1229 | union | |
| 1230 | { | |
| 1231 | _Tp __t; | |
| 1232 | size_t __a; | |
| 1233 | } __u; | |
| 1234 | __u.__t = __v; | |
| 1235 | return __u.__a; | |
| 1236 | } | |
| 1237 | }; | |
| 1238 | ||
| 1239 | template <class _Tp> | |
| 1240 | struct __scalar_hash<_Tp, 2> | |
| 1241 | : public unary_function<_Tp, size_t> | |
| 1242 | { | |
| 1243 | _LIBCPP_INLINE_VISIBILITY | |
| 1244 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 1245 | { | |
| 1246 | union | |
| 1247 | { | |
| 1248 | _Tp __t; | |
| 1249 | struct | |
| 1250 | { | |
| 1251 | size_t __a; | |
| 1252 | size_t __b; | |
| 1253 | } __s; | |
| 1254 | } __u; | |
| 1255 | __u.__t = __v; | |
| 1256 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 1257 | } | |
| 1258 | }; | |
| 1259 | ||
| 1260 | template <class _Tp> | |
| 1261 | struct __scalar_hash<_Tp, 3> | |
| 1262 | : public unary_function<_Tp, size_t> | |
| 1263 | { | |
| 1264 | _LIBCPP_INLINE_VISIBILITY | |
| 1265 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 1266 | { | |
| 1267 | union | |
| 1268 | { | |
| 1269 | _Tp __t; | |
| 1270 | struct | |
| 1271 | { | |
| 1272 | size_t __a; | |
| 1273 | size_t __b; | |
| 1274 | size_t __c; | |
| 1275 | } __s; | |
| 1276 | } __u; | |
| 1277 | __u.__t = __v; | |
| 1278 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 1279 | } | |
| 1280 | }; | |
| 1281 | ||
| 1282 | template <class _Tp> | |
| 1283 | struct __scalar_hash<_Tp, 4> | |
| 1284 | : public unary_function<_Tp, size_t> | |
| 1285 | { | |
| 1286 | _LIBCPP_INLINE_VISIBILITY | |
| 1287 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 1288 | { | |
| 1289 | union | |
| 1290 | { | |
| 1291 | _Tp __t; | |
| 1292 | struct | |
| 1293 | { | |
| 1294 | size_t __a; | |
| 1295 | size_t __b; | |
| 1296 | size_t __c; | |
| 1297 | size_t __d; | |
| 1298 | } __s; | |
| 1299 | } __u; | |
| 1300 | __u.__t = __v; | |
| 1301 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 1302 | } | |
| 1303 | }; | |
| 1304 | ||
| 1305 | struct _PairT { | |
| 1306 | size_t first; | |
| 1307 | size_t second; | |
| 1308 | }; | |
| 1309 | ||
| 1310 | _LIBCPP_INLINE_VISIBILITY | |
| 1311 | inline size_t __hash_combine(size_t __lhs, size_t __rhs) _NOEXCEPT { | |
| 1312 | typedef __scalar_hash<_PairT> _HashT; | |
| 1313 | const _PairT __p = {__lhs, __rhs}; | |
| 1314 | return _HashT()(__p); | |
| 1315 | } | |
| 1316 | ||
| 1317 | template<class _Tp> | |
| 1318 | struct _LIBCPP_TEMPLATE_VIS hash<_Tp*> | |
| 1319 | : public unary_function<_Tp*, size_t> | |
| 1320 | { | |
| 1321 | _LIBCPP_INLINE_VISIBILITY | |
| 1322 | size_t operator()(_Tp* __v) const _NOEXCEPT | |
| 1323 | { | |
| 1324 | union | |
| 1325 | { | |
| 1326 | _Tp* __t; | |
| 1327 | size_t __a; | |
| 1328 | } __u; | |
| 1329 | __u.__t = __v; | |
| 1330 | return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u)); | |
| 1331 | } | |
| 1332 | }; | |
| 1333 | ||
| 1334 | ||
| 1335 | template <> | |
| 1336 | struct _LIBCPP_TEMPLATE_VIS hash<bool> | |
| 1337 | : public unary_function<bool, size_t> | |
| 1338 | { | |
| 1339 | _LIBCPP_INLINE_VISIBILITY | |
| 1340 | size_t operator()(bool __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1341 | }; | |
| 1342 | ||
| 1343 | template <> | |
| 1344 | struct _LIBCPP_TEMPLATE_VIS hash<char> | |
| 1345 | : public unary_function<char, size_t> | |
| 1346 | { | |
| 1347 | _LIBCPP_INLINE_VISIBILITY | |
| 1348 | size_t operator()(char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1349 | }; | |
| 1350 | ||
| 1351 | template <> | |
| 1352 | struct _LIBCPP_TEMPLATE_VIS hash<signed char> | |
| 1353 | : public unary_function<signed char, size_t> | |
| 1354 | { | |
| 1355 | _LIBCPP_INLINE_VISIBILITY | |
| 1356 | size_t operator()(signed char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1357 | }; | |
| 1358 | ||
| 1359 | template <> | |
| 1360 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned char> | |
| 1361 | : public unary_function<unsigned char, size_t> | |
| 1362 | { | |
| 1363 | _LIBCPP_INLINE_VISIBILITY | |
| 1364 | size_t operator()(unsigned char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1365 | }; | |
| 1366 | ||
| 1367 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 1368 | template <> | |
| 1369 | struct _LIBCPP_TEMPLATE_VIS hash<char8_t> | |
| 1370 | : public unary_function<char8_t, size_t> | |
| 1371 | { | |
| 1372 | _LIBCPP_INLINE_VISIBILITY | |
| 1373 | size_t operator()(char8_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1374 | }; | |
| 1375 | #endif // !_LIBCPP_NO_HAS_CHAR8_T | |
| 1376 | ||
| 1377 | #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 1378 | ||
| 1379 | template <> | |
| 1380 | struct _LIBCPP_TEMPLATE_VIS hash<char16_t> | |
| 1381 | : public unary_function<char16_t, size_t> | |
| 1382 | { | |
| 1383 | _LIBCPP_INLINE_VISIBILITY | |
| 1384 | size_t operator()(char16_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1385 | }; | |
| 1386 | ||
| 1387 | template <> | |
| 1388 | struct _LIBCPP_TEMPLATE_VIS hash<char32_t> | |
| 1389 | : public unary_function<char32_t, size_t> | |
| 1390 | { | |
| 1391 | _LIBCPP_INLINE_VISIBILITY | |
| 1392 | size_t operator()(char32_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1393 | }; | |
| 1394 | ||
| 1395 | #endif // _LIBCPP_HAS_NO_UNICODE_CHARS | |
| 1396 | ||
| 1397 | template <> | |
| 1398 | struct _LIBCPP_TEMPLATE_VIS hash<wchar_t> | |
| 1399 | : public unary_function<wchar_t, size_t> | |
| 1400 | { | |
| 1401 | _LIBCPP_INLINE_VISIBILITY | |
| 1402 | size_t operator()(wchar_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1403 | }; | |
| 1404 | ||
| 1405 | template <> | |
| 1406 | struct _LIBCPP_TEMPLATE_VIS hash<short> | |
| 1407 | : public unary_function<short, size_t> | |
| 1408 | { | |
| 1409 | _LIBCPP_INLINE_VISIBILITY | |
| 1410 | size_t operator()(short __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1411 | }; | |
| 1412 | ||
| 1413 | template <> | |
| 1414 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned short> | |
| 1415 | : public unary_function<unsigned short, size_t> | |
| 1416 | { | |
| 1417 | _LIBCPP_INLINE_VISIBILITY | |
| 1418 | size_t operator()(unsigned short __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1419 | }; | |
| 1420 | ||
| 1421 | template <> | |
| 1422 | struct _LIBCPP_TEMPLATE_VIS hash<int> | |
| 1423 | : public unary_function<int, size_t> | |
| 1424 | { | |
| 1425 | _LIBCPP_INLINE_VISIBILITY | |
| 1426 | size_t operator()(int __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1427 | }; | |
| 1428 | ||
| 1429 | template <> | |
| 1430 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned int> | |
| 1431 | : public unary_function<unsigned int, size_t> | |
| 1432 | { | |
| 1433 | _LIBCPP_INLINE_VISIBILITY | |
| 1434 | size_t operator()(unsigned int __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1435 | }; | |
| 1436 | ||
| 1437 | template <> | |
| 1438 | struct _LIBCPP_TEMPLATE_VIS hash<long> | |
| 1439 | : public unary_function<long, size_t> | |
| 1440 | { | |
| 1441 | _LIBCPP_INLINE_VISIBILITY | |
| 1442 | size_t operator()(long __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1443 | }; | |
| 1444 | ||
| 1445 | template <> | |
| 1446 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned long> | |
| 1447 | : public unary_function<unsigned long, size_t> | |
| 1448 | { | |
| 1449 | _LIBCPP_INLINE_VISIBILITY | |
| 1450 | size_t operator()(unsigned long __v) const _NOEXCEPT {return static_cast<size_t>(__v);} | |
| 1451 | }; | |
| 1452 | ||
| 1453 | template <> | |
| 1454 | struct _LIBCPP_TEMPLATE_VIS hash<long long> | |
| 1455 | : public __scalar_hash<long long> | |
| 1456 | { | |
| 1457 | }; | |
| 1458 | ||
| 1459 | template <> | |
| 1460 | struct _LIBCPP_TEMPLATE_VIS hash<unsigned long long> | |
| 1461 | : public __scalar_hash<unsigned long long> | |
| 1462 | { | |
| 1463 | }; | |
| 1464 | ||
| 1465 | #ifndef _LIBCPP_HAS_NO_INT128 | |
| 1466 | ||
| 1467 | template <> | |
| 1468 | struct _LIBCPP_TEMPLATE_VIS hash<__int128_t> | |
| 1469 | : public __scalar_hash<__int128_t> | |
| 1470 | { | |
| 1471 | }; | |
| 1472 | ||
| 1473 | template <> | |
| 1474 | struct _LIBCPP_TEMPLATE_VIS hash<__uint128_t> | |
| 1475 | : public __scalar_hash<__uint128_t> | |
| 1476 | { | |
| 1477 | }; | |
| 1478 | ||
| 1479 | #endif | |
| 1480 | ||
| 1481 | template <> | |
| 1482 | struct _LIBCPP_TEMPLATE_VIS hash<float> | |
| 1483 | : public __scalar_hash<float> | |
| 1484 | { | |
| 1485 | _LIBCPP_INLINE_VISIBILITY | |
| 1486 | size_t operator()(float __v) const _NOEXCEPT | |
| 1487 | { | |
| 1488 | // -0.0 and 0.0 should return same hash | |
| 1489 | if (__v == 0.0f) | |
| 1490 | return 0; | |
| 1491 | return __scalar_hash<float>::operator()(__v); | |
| 1492 | } | |
| 1493 | }; | |
| 1494 | ||
| 1495 | template <> | |
| 1496 | struct _LIBCPP_TEMPLATE_VIS hash<double> | |
| 1497 | : public __scalar_hash<double> | |
| 1498 | { | |
| 1499 | _LIBCPP_INLINE_VISIBILITY | |
| 1500 | size_t operator()(double __v) const _NOEXCEPT | |
| 1501 | { | |
| 1502 | // -0.0 and 0.0 should return same hash | |
| 1503 | if (__v == 0.0) | |
| 1504 | return 0; | |
| 1505 | return __scalar_hash<double>::operator()(__v); | |
| 1506 | } | |
| 1507 | }; | |
| 1508 | ||
| 1509 | template <> | |
| 1510 | struct _LIBCPP_TEMPLATE_VIS hash<long double> | |
| 1511 | : public __scalar_hash<long double> | |
| 1512 | { | |
| 1513 | _LIBCPP_INLINE_VISIBILITY | |
| 1514 | size_t operator()(long double __v) const _NOEXCEPT | |
| 1515 | { | |
| 1516 | // -0.0 and 0.0 should return same hash | |
| 1517 | if (__v == 0.0L) | |
| 1518 | return 0; | |
| 1519 | #if defined(__i386__) || (defined(__x86_64__) && defined(__ILP32__)) | |
| 1520 | // Zero out padding bits | |
| 1521 | union | |
| 1522 | { | |
| 1523 | long double __t; | |
| 1524 | struct | |
| 1525 | { | |
| 1526 | size_t __a; | |
| 1527 | size_t __b; | |
| 1528 | size_t __c; | |
| 1529 | size_t __d; | |
| 1530 | } __s; | |
| 1531 | } __u; | |
| 1532 | __u.__s.__a = 0; | |
| 1533 | __u.__s.__b = 0; | |
| 1534 | __u.__s.__c = 0; | |
| 1535 | __u.__s.__d = 0; | |
| 1536 | __u.__t = __v; | |
| 1537 | return __u.__s.__a ^ __u.__s.__b ^ __u.__s.__c ^ __u.__s.__d; | |
| 1538 | #elif defined(__x86_64__) | |
| 1539 | // Zero out padding bits | |
| 1540 | union | |
| 1541 | { | |
| 1542 | long double __t; | |
| 1543 | struct | |
| 1544 | { | |
| 1545 | size_t __a; | |
| 1546 | size_t __b; | |
| 1547 | } __s; | |
| 1548 | } __u; | |
| 1549 | __u.__s.__a = 0; | |
| 1550 | __u.__s.__b = 0; | |
| 1551 | __u.__t = __v; | |
| 1552 | return __u.__s.__a ^ __u.__s.__b; | |
| 1553 | #else | |
| 1554 | return __scalar_hash<long double>::operator()(__v); | |
| 1555 | #endif | |
| 1556 | } | |
| 1557 | }; | |
| 1558 | ||
| 1559 | #if _LIBCPP_STD_VER > 11 | |
| 1560 | ||
| 1561 | template <class _Tp, bool = is_enum<_Tp>::value> | |
| 1562 | struct _LIBCPP_TEMPLATE_VIS __enum_hash | |
| 1563 | : public unary_function<_Tp, size_t> | |
| 1564 | { | |
| 1565 | _LIBCPP_INLINE_VISIBILITY | |
| 1566 | size_t operator()(_Tp __v) const _NOEXCEPT | |
| 1567 | { | |
| 1568 | typedef typename underlying_type<_Tp>::type type; | |
| 1569 | return hash<type>{}(static_cast<type>(__v)); | |
| 1570 | } | |
| 1571 | }; | |
| 1572 | template <class _Tp> | |
| 1573 | struct _LIBCPP_TEMPLATE_VIS __enum_hash<_Tp, false> { | |
| 1574 | __enum_hash() = delete; | |
| 1575 | __enum_hash(__enum_hash const&) = delete; | |
| 1576 | __enum_hash& operator=(__enum_hash const&) = delete; | |
| 1577 | }; | |
| 1578 | ||
| 1579 | template <class _Tp> | |
| 1580 | struct _LIBCPP_TEMPLATE_VIS hash : public __enum_hash<_Tp> | |
| 1581 | { | |
| 1582 | }; | |
| 1583 | #endif | |
| 1584 | ||
| 1585 | #if _LIBCPP_STD_VER > 14 | |
| 1586 | ||
| 1587 | template <> | |
| 1588 | struct _LIBCPP_TEMPLATE_VIS hash<nullptr_t> | |
| 1589 | : public unary_function<nullptr_t, size_t> | |
| 1590 | { | |
| 1591 | _LIBCPP_INLINE_VISIBILITY | |
| 1592 | size_t operator()(nullptr_t) const _NOEXCEPT { | |
| 1593 | return 662607004ull; | |
| 1594 | } | |
| 1595 | }; | |
| 1596 | #endif | |
| 1597 | ||
| 1598 | #ifndef _LIBCPP_CXX03_LANG | |
| 1599 | template <class _Key, class _Hash> | |
| 1600 | using __check_hash_requirements _LIBCPP_NODEBUG_TYPE = integral_constant<bool, | |
| 1601 | is_copy_constructible<_Hash>::value && | |
| 1602 | is_move_constructible<_Hash>::value && | |
| 1603 | __invokable_r<size_t, _Hash, _Key const&>::value | |
| 1604 | >; | |
| 1605 | ||
| 1606 | template <class _Key, class _Hash = hash<_Key> > | |
| 1607 | using __has_enabled_hash _LIBCPP_NODEBUG_TYPE = integral_constant<bool, | |
| 1608 | __check_hash_requirements<_Key, _Hash>::value && | |
| 1609 | is_default_constructible<_Hash>::value | |
| 1610 | >; | |
| 1611 | ||
| 1612 | #if _LIBCPP_STD_VER > 14 | |
| 1613 | template <class _Type, class> | |
| 1614 | using __enable_hash_helper_imp _LIBCPP_NODEBUG_TYPE = _Type; | |
| 1615 | ||
| 1616 | template <class _Type, class ..._Keys> | |
| 1617 | using __enable_hash_helper _LIBCPP_NODEBUG_TYPE = __enable_hash_helper_imp<_Type, | |
| 1618 | typename enable_if<__all<__has_enabled_hash<_Keys>::value...>::value>::type | |
| 1619 | >; | |
| 1620 | #else | |
| 1621 | template <class _Type, class ...> | |
| 1622 | using __enable_hash_helper _LIBCPP_NODEBUG_TYPE = _Type; | |
| 1623 | #endif | |
| 1624 | ||
| 1625 | #endif // !_LIBCPP_CXX03_LANG | |
| 1626 | ||
| 1627 | _LIBCPP_END_NAMESPACE_STD | |
| 1628 | 229 | |
| 1629 | #endif // _LIBCPP_UTILITY | |
| 230 | #endif // _LIBCPP_UTILITY |
lib/libcxx/include/valarray+126-105| ... | ... | @@ -340,11 +340,11 @@ template <class T> unspecified2 end(const valarray<T>& v); |
| 340 | 340 | */ |
| 341 | 341 | |
| 342 | 342 | #include <__config> |
| 343 | #include <cstddef> | |
| 344 | #include <cmath> | |
| 345 | #include <initializer_list> | |
| 346 | 343 | #include <algorithm> |
| 344 | #include <cmath> | |
| 345 | #include <cstddef> | |
| 347 | 346 | #include <functional> |
| 347 | #include <initializer_list> | |
| 348 | 348 | #include <new> |
| 349 | 349 | |
| 350 | 350 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -354,7 +354,6 @@ template <class T> unspecified2 end(const valarray<T>& v); |
| 354 | 354 | _LIBCPP_PUSH_MACROS |
| 355 | 355 | #include <__undef_macros> |
| 356 | 356 | |
| 357 | ||
| 358 | 357 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 359 | 358 | |
| 360 | 359 | template<class _Tp> class _LIBCPP_TEMPLATE_VIS valarray; |
| ... | ... | @@ -413,8 +412,8 @@ end(const valarray<_Tp>& __v); |
| 413 | 412 | template <class _Op, class _A0> |
| 414 | 413 | struct _UnaryOp |
| 415 | 414 | { |
| 416 | typedef typename _Op::result_type result_type; | |
| 417 | typedef typename _A0::value_type value_type; | |
| 415 | typedef typename _Op::__result_type __result_type; | |
| 416 | typedef typename decay<__result_type>::type value_type; | |
| 418 | 417 | |
| 419 | 418 | _Op __op_; |
| 420 | 419 | _A0 __a0_; |
| ... | ... | @@ -423,7 +422,7 @@ struct _UnaryOp |
| 423 | 422 | _UnaryOp(const _Op& __op, const _A0& __a0) : __op_(__op), __a0_(__a0) {} |
| 424 | 423 | |
| 425 | 424 | _LIBCPP_INLINE_VISIBILITY |
| 426 | result_type operator[](size_t __i) const {return __op_(__a0_[__i]);} | |
| 425 | __result_type operator[](size_t __i) const {return __op_(__a0_[__i]);} | |
| 427 | 426 | |
| 428 | 427 | _LIBCPP_INLINE_VISIBILITY |
| 429 | 428 | size_t size() const {return __a0_.size();} |
| ... | ... | @@ -432,8 +431,8 @@ struct _UnaryOp |
| 432 | 431 | template <class _Op, class _A0, class _A1> |
| 433 | 432 | struct _BinaryOp |
| 434 | 433 | { |
| 435 | typedef typename _Op::result_type result_type; | |
| 436 | typedef typename _A0::value_type value_type; | |
| 434 | typedef typename _Op::__result_type __result_type; | |
| 435 | typedef typename decay<__result_type>::type value_type; | |
| 437 | 436 | |
| 438 | 437 | _Op __op_; |
| 439 | 438 | _A0 __a0_; |
| ... | ... | @@ -444,7 +443,7 @@ struct _BinaryOp |
| 444 | 443 | : __op_(__op), __a0_(__a0), __a1_(__a1) {} |
| 445 | 444 | |
| 446 | 445 | _LIBCPP_INLINE_VISIBILITY |
| 447 | value_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 446 | __result_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 448 | 447 | |
| 449 | 448 | _LIBCPP_INLINE_VISIBILITY |
| 450 | 449 | size_t size() const {return __a0_.size();} |
| ... | ... | @@ -455,7 +454,7 @@ class __scalar_expr |
| 455 | 454 | { |
| 456 | 455 | public: |
| 457 | 456 | typedef _Tp value_type; |
| 458 | typedef const _Tp& result_type; | |
| 457 | typedef const _Tp& __result_type; | |
| 459 | 458 | private: |
| 460 | 459 | const value_type& __t_; |
| 461 | 460 | size_t __s_; |
| ... | ... | @@ -464,50 +463,56 @@ public: |
| 464 | 463 | explicit __scalar_expr(const value_type& __t, size_t __s) : __t_(__t), __s_(__s) {} |
| 465 | 464 | |
| 466 | 465 | _LIBCPP_INLINE_VISIBILITY |
| 467 | result_type operator[](size_t) const {return __t_;} | |
| 466 | __result_type operator[](size_t) const {return __t_;} | |
| 468 | 467 | |
| 469 | 468 | _LIBCPP_INLINE_VISIBILITY |
| 470 | 469 | size_t size() const {return __s_;} |
| 471 | 470 | }; |
| 472 | 471 | |
| 473 | 472 | template <class _Tp> |
| 474 | struct __unary_plus : unary_function<_Tp, _Tp> | |
| 473 | struct __unary_plus | |
| 475 | 474 | { |
| 475 | typedef _Tp __result_type; | |
| 476 | 476 | _LIBCPP_INLINE_VISIBILITY |
| 477 | 477 | _Tp operator()(const _Tp& __x) const |
| 478 | 478 | {return +__x;} |
| 479 | 479 | }; |
| 480 | 480 | |
| 481 | 481 | template <class _Tp> |
| 482 | struct __bit_not : unary_function<_Tp, _Tp> | |
| 482 | struct __bit_not | |
| 483 | 483 | { |
| 484 | typedef _Tp __result_type; | |
| 484 | 485 | _LIBCPP_INLINE_VISIBILITY |
| 485 | 486 | _Tp operator()(const _Tp& __x) const |
| 486 | 487 | {return ~__x;} |
| 487 | 488 | }; |
| 488 | 489 | |
| 489 | 490 | template <class _Tp> |
| 490 | struct __bit_shift_left : binary_function<_Tp, _Tp, _Tp> | |
| 491 | struct __bit_shift_left | |
| 491 | 492 | { |
| 493 | typedef _Tp __result_type; | |
| 492 | 494 | _LIBCPP_INLINE_VISIBILITY |
| 493 | 495 | _Tp operator()(const _Tp& __x, const _Tp& __y) const |
| 494 | 496 | {return __x << __y;} |
| 495 | 497 | }; |
| 496 | 498 | |
| 497 | 499 | template <class _Tp> |
| 498 | struct __bit_shift_right : binary_function<_Tp, _Tp, _Tp> | |
| 500 | struct __bit_shift_right | |
| 499 | 501 | { |
| 502 | typedef _Tp __result_type; | |
| 500 | 503 | _LIBCPP_INLINE_VISIBILITY |
| 501 | 504 | _Tp operator()(const _Tp& __x, const _Tp& __y) const |
| 502 | 505 | {return __x >> __y;} |
| 503 | 506 | }; |
| 504 | 507 | |
| 505 | 508 | template <class _Tp, class _Fp> |
| 506 | struct __apply_expr : unary_function<_Tp, _Tp> | |
| 509 | struct __apply_expr | |
| 507 | 510 | { |
| 508 | 511 | private: |
| 509 | 512 | _Fp __f_; |
| 510 | 513 | public: |
| 514 | typedef _Tp __result_type; | |
| 515 | ||
| 511 | 516 | _LIBCPP_INLINE_VISIBILITY |
| 512 | 517 | explicit __apply_expr(_Fp __f) : __f_(__f) {} |
| 513 | 518 | |
| ... | ... | @@ -517,128 +522,144 @@ public: |
| 517 | 522 | }; |
| 518 | 523 | |
| 519 | 524 | template <class _Tp> |
| 520 | struct __abs_expr : unary_function<_Tp, _Tp> | |
| 525 | struct __abs_expr | |
| 521 | 526 | { |
| 527 | typedef _Tp __result_type; | |
| 522 | 528 | _LIBCPP_INLINE_VISIBILITY |
| 523 | 529 | _Tp operator()(const _Tp& __x) const |
| 524 | 530 | {return abs(__x);} |
| 525 | 531 | }; |
| 526 | 532 | |
| 527 | 533 | template <class _Tp> |
| 528 | struct __acos_expr : unary_function<_Tp, _Tp> | |
| 534 | struct __acos_expr | |
| 529 | 535 | { |
| 536 | typedef _Tp __result_type; | |
| 530 | 537 | _LIBCPP_INLINE_VISIBILITY |
| 531 | 538 | _Tp operator()(const _Tp& __x) const |
| 532 | 539 | {return acos(__x);} |
| 533 | 540 | }; |
| 534 | 541 | |
| 535 | 542 | template <class _Tp> |
| 536 | struct __asin_expr : unary_function<_Tp, _Tp> | |
| 543 | struct __asin_expr | |
| 537 | 544 | { |
| 545 | typedef _Tp __result_type; | |
| 538 | 546 | _LIBCPP_INLINE_VISIBILITY |
| 539 | 547 | _Tp operator()(const _Tp& __x) const |
| 540 | 548 | {return asin(__x);} |
| 541 | 549 | }; |
| 542 | 550 | |
| 543 | 551 | template <class _Tp> |
| 544 | struct __atan_expr : unary_function<_Tp, _Tp> | |
| 552 | struct __atan_expr | |
| 545 | 553 | { |
| 554 | typedef _Tp __result_type; | |
| 546 | 555 | _LIBCPP_INLINE_VISIBILITY |
| 547 | 556 | _Tp operator()(const _Tp& __x) const |
| 548 | 557 | {return atan(__x);} |
| 549 | 558 | }; |
| 550 | 559 | |
| 551 | 560 | template <class _Tp> |
| 552 | struct __atan2_expr : binary_function<_Tp, _Tp, _Tp> | |
| 561 | struct __atan2_expr | |
| 553 | 562 | { |
| 563 | typedef _Tp __result_type; | |
| 554 | 564 | _LIBCPP_INLINE_VISIBILITY |
| 555 | 565 | _Tp operator()(const _Tp& __x, const _Tp& __y) const |
| 556 | 566 | {return atan2(__x, __y);} |
| 557 | 567 | }; |
| 558 | 568 | |
| 559 | 569 | template <class _Tp> |
| 560 | struct __cos_expr : unary_function<_Tp, _Tp> | |
| 570 | struct __cos_expr | |
| 561 | 571 | { |
| 572 | typedef _Tp __result_type; | |
| 562 | 573 | _LIBCPP_INLINE_VISIBILITY |
| 563 | 574 | _Tp operator()(const _Tp& __x) const |
| 564 | 575 | {return cos(__x);} |
| 565 | 576 | }; |
| 566 | 577 | |
| 567 | 578 | template <class _Tp> |
| 568 | struct __cosh_expr : unary_function<_Tp, _Tp> | |
| 579 | struct __cosh_expr | |
| 569 | 580 | { |
| 581 | typedef _Tp __result_type; | |
| 570 | 582 | _LIBCPP_INLINE_VISIBILITY |
| 571 | 583 | _Tp operator()(const _Tp& __x) const |
| 572 | 584 | {return cosh(__x);} |
| 573 | 585 | }; |
| 574 | 586 | |
| 575 | 587 | template <class _Tp> |
| 576 | struct __exp_expr : unary_function<_Tp, _Tp> | |
| 588 | struct __exp_expr | |
| 577 | 589 | { |
| 590 | typedef _Tp __result_type; | |
| 578 | 591 | _LIBCPP_INLINE_VISIBILITY |
| 579 | 592 | _Tp operator()(const _Tp& __x) const |
| 580 | 593 | {return exp(__x);} |
| 581 | 594 | }; |
| 582 | 595 | |
| 583 | 596 | template <class _Tp> |
| 584 | struct __log_expr : unary_function<_Tp, _Tp> | |
| 597 | struct __log_expr | |
| 585 | 598 | { |
| 599 | typedef _Tp __result_type; | |
| 586 | 600 | _LIBCPP_INLINE_VISIBILITY |
| 587 | 601 | _Tp operator()(const _Tp& __x) const |
| 588 | 602 | {return log(__x);} |
| 589 | 603 | }; |
| 590 | 604 | |
| 591 | 605 | template <class _Tp> |
| 592 | struct __log10_expr : unary_function<_Tp, _Tp> | |
| 606 | struct __log10_expr | |
| 593 | 607 | { |
| 608 | typedef _Tp __result_type; | |
| 594 | 609 | _LIBCPP_INLINE_VISIBILITY |
| 595 | 610 | _Tp operator()(const _Tp& __x) const |
| 596 | 611 | {return log10(__x);} |
| 597 | 612 | }; |
| 598 | 613 | |
| 599 | 614 | template <class _Tp> |
| 600 | struct __pow_expr : binary_function<_Tp, _Tp, _Tp> | |
| 615 | struct __pow_expr | |
| 601 | 616 | { |
| 617 | typedef _Tp __result_type; | |
| 602 | 618 | _LIBCPP_INLINE_VISIBILITY |
| 603 | 619 | _Tp operator()(const _Tp& __x, const _Tp& __y) const |
| 604 | 620 | {return pow(__x, __y);} |
| 605 | 621 | }; |
| 606 | 622 | |
| 607 | 623 | template <class _Tp> |
| 608 | struct __sin_expr : unary_function<_Tp, _Tp> | |
| 624 | struct __sin_expr | |
| 609 | 625 | { |
| 626 | typedef _Tp __result_type; | |
| 610 | 627 | _LIBCPP_INLINE_VISIBILITY |
| 611 | 628 | _Tp operator()(const _Tp& __x) const |
| 612 | 629 | {return sin(__x);} |
| 613 | 630 | }; |
| 614 | 631 | |
| 615 | 632 | template <class _Tp> |
| 616 | struct __sinh_expr : unary_function<_Tp, _Tp> | |
| 633 | struct __sinh_expr | |
| 617 | 634 | { |
| 635 | typedef _Tp __result_type; | |
| 618 | 636 | _LIBCPP_INLINE_VISIBILITY |
| 619 | 637 | _Tp operator()(const _Tp& __x) const |
| 620 | 638 | {return sinh(__x);} |
| 621 | 639 | }; |
| 622 | 640 | |
| 623 | 641 | template <class _Tp> |
| 624 | struct __sqrt_expr : unary_function<_Tp, _Tp> | |
| 642 | struct __sqrt_expr | |
| 625 | 643 | { |
| 644 | typedef _Tp __result_type; | |
| 626 | 645 | _LIBCPP_INLINE_VISIBILITY |
| 627 | 646 | _Tp operator()(const _Tp& __x) const |
| 628 | 647 | {return sqrt(__x);} |
| 629 | 648 | }; |
| 630 | 649 | |
| 631 | 650 | template <class _Tp> |
| 632 | struct __tan_expr : unary_function<_Tp, _Tp> | |
| 651 | struct __tan_expr | |
| 633 | 652 | { |
| 653 | typedef _Tp __result_type; | |
| 634 | 654 | _LIBCPP_INLINE_VISIBILITY |
| 635 | 655 | _Tp operator()(const _Tp& __x) const |
| 636 | 656 | {return tan(__x);} |
| 637 | 657 | }; |
| 638 | 658 | |
| 639 | 659 | template <class _Tp> |
| 640 | struct __tanh_expr : unary_function<_Tp, _Tp> | |
| 660 | struct __tanh_expr | |
| 641 | 661 | { |
| 662 | typedef _Tp __result_type; | |
| 642 | 663 | _LIBCPP_INLINE_VISIBILITY |
| 643 | 664 | _Tp operator()(const _Tp& __x) const |
| 644 | 665 | {return tanh(__x);} |
| ... | ... | @@ -650,7 +671,7 @@ class __slice_expr |
| 650 | 671 | typedef typename remove_reference<_ValExpr>::type _RmExpr; |
| 651 | 672 | public: |
| 652 | 673 | typedef typename _RmExpr::value_type value_type; |
| 653 | typedef value_type result_type; | |
| 674 | typedef value_type __result_type; | |
| 654 | 675 | |
| 655 | 676 | private: |
| 656 | 677 | _ValExpr __expr_; |
| ... | ... | @@ -668,7 +689,7 @@ private: |
| 668 | 689 | public: |
| 669 | 690 | |
| 670 | 691 | _LIBCPP_INLINE_VISIBILITY |
| 671 | result_type operator[](size_t __i) const | |
| 692 | __result_type operator[](size_t __i) const | |
| 672 | 693 | {return __expr_[__start_ + __i * __stride_];} |
| 673 | 694 | |
| 674 | 695 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -690,7 +711,7 @@ class __shift_expr |
| 690 | 711 | typedef typename remove_reference<_ValExpr>::type _RmExpr; |
| 691 | 712 | public: |
| 692 | 713 | typedef typename _RmExpr::value_type value_type; |
| 693 | typedef value_type result_type; | |
| 714 | typedef value_type __result_type; | |
| 694 | 715 | |
| 695 | 716 | private: |
| 696 | 717 | _ValExpr __expr_; |
| ... | ... | @@ -714,7 +735,7 @@ private: |
| 714 | 735 | public: |
| 715 | 736 | |
| 716 | 737 | _LIBCPP_INLINE_VISIBILITY |
| 717 | result_type operator[](size_t __j) const | |
| 738 | __result_type operator[](size_t __j) const | |
| 718 | 739 | { |
| 719 | 740 | ptrdiff_t __i = static_cast<ptrdiff_t>(__j); |
| 720 | 741 | ptrdiff_t __m = (__sn_ * __i - __ul_) >> _Np; |
| ... | ... | @@ -733,7 +754,7 @@ class __cshift_expr |
| 733 | 754 | typedef typename remove_reference<_ValExpr>::type _RmExpr; |
| 734 | 755 | public: |
| 735 | 756 | typedef typename _RmExpr::value_type value_type; |
| 736 | typedef value_type result_type; | |
| 757 | typedef value_type __result_type; | |
| 737 | 758 | |
| 738 | 759 | private: |
| 739 | 760 | _ValExpr __expr_; |
| ... | ... | @@ -764,7 +785,7 @@ private: |
| 764 | 785 | public: |
| 765 | 786 | |
| 766 | 787 | _LIBCPP_INLINE_VISIBILITY |
| 767 | result_type operator[](size_t __i) const | |
| 788 | __result_type operator[](size_t __i) const | |
| 768 | 789 | { |
| 769 | 790 | if (__i < __m_) |
| 770 | 791 | return __expr_[__i + __o1_]; |
| ... | ... | @@ -794,7 +815,7 @@ class _LIBCPP_TEMPLATE_VIS valarray |
| 794 | 815 | { |
| 795 | 816 | public: |
| 796 | 817 | typedef _Tp value_type; |
| 797 | typedef _Tp result_type; | |
| 818 | typedef _Tp __result_type; | |
| 798 | 819 | |
| 799 | 820 | private: |
| 800 | 821 | value_type* __begin_; |
| ... | ... | @@ -814,7 +835,7 @@ public: |
| 814 | 835 | _LIBCPP_INLINE_VISIBILITY |
| 815 | 836 | valarray(valarray&& __v) _NOEXCEPT; |
| 816 | 837 | valarray(initializer_list<value_type> __il); |
| 817 | #endif // _LIBCPP_CXX03_LANG | |
| 838 | #endif // _LIBCPP_CXX03_LANG | |
| 818 | 839 | valarray(const slice_array<value_type>& __sa); |
| 819 | 840 | valarray(const gslice_array<value_type>& __ga); |
| 820 | 841 | valarray(const mask_array<value_type>& __ma); |
| ... | ... | @@ -829,7 +850,7 @@ public: |
| 829 | 850 | valarray& operator=(valarray&& __v) _NOEXCEPT; |
| 830 | 851 | _LIBCPP_INLINE_VISIBILITY |
| 831 | 852 | valarray& operator=(initializer_list<value_type>); |
| 832 | #endif // _LIBCPP_CXX03_LANG | |
| 853 | #endif // _LIBCPP_CXX03_LANG | |
| 833 | 854 | _LIBCPP_INLINE_VISIBILITY |
| 834 | 855 | valarray& operator=(const value_type& __x); |
| 835 | 856 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -865,7 +886,7 @@ public: |
| 865 | 886 | __val_expr<__indirect_expr<const valarray&> > operator[](gslice&& __gs) const; |
| 866 | 887 | _LIBCPP_INLINE_VISIBILITY |
| 867 | 888 | gslice_array<value_type> operator[](gslice&& __gs); |
| 868 | #endif // _LIBCPP_CXX03_LANG | |
| 889 | #endif // _LIBCPP_CXX03_LANG | |
| 869 | 890 | _LIBCPP_INLINE_VISIBILITY |
| 870 | 891 | __val_expr<__mask_expr<const valarray&> > operator[](const valarray<bool>& __vb) const; |
| 871 | 892 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -875,7 +896,7 @@ public: |
| 875 | 896 | __val_expr<__mask_expr<const valarray&> > operator[](valarray<bool>&& __vb) const; |
| 876 | 897 | _LIBCPP_INLINE_VISIBILITY |
| 877 | 898 | mask_array<value_type> operator[](valarray<bool>&& __vb); |
| 878 | #endif // _LIBCPP_CXX03_LANG | |
| 899 | #endif // _LIBCPP_CXX03_LANG | |
| 879 | 900 | _LIBCPP_INLINE_VISIBILITY |
| 880 | 901 | __val_expr<__indirect_expr<const valarray&> > operator[](const valarray<size_t>& __vs) const; |
| 881 | 902 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -885,7 +906,7 @@ public: |
| 885 | 906 | __val_expr<__indirect_expr<const valarray&> > operator[](valarray<size_t>&& __vs) const; |
| 886 | 907 | _LIBCPP_INLINE_VISIBILITY |
| 887 | 908 | indirect_array<value_type> operator[](valarray<size_t>&& __vs); |
| 888 | #endif // _LIBCPP_CXX03_LANG | |
| 909 | #endif // _LIBCPP_CXX03_LANG | |
| 889 | 910 | |
| 890 | 911 | // unary operators: |
| 891 | 912 | valarray operator+() const; |
| ... | ... | @@ -1065,8 +1086,8 @@ _LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS void valarray<size_t>::resize(size_t, s |
| 1065 | 1086 | template <class _Op, class _Tp> |
| 1066 | 1087 | struct _UnaryOp<_Op, valarray<_Tp> > |
| 1067 | 1088 | { |
| 1068 | typedef typename _Op::result_type result_type; | |
| 1069 | typedef _Tp value_type; | |
| 1089 | typedef typename _Op::__result_type __result_type; | |
| 1090 | typedef typename decay<__result_type>::type value_type; | |
| 1070 | 1091 | |
| 1071 | 1092 | _Op __op_; |
| 1072 | 1093 | const valarray<_Tp>& __a0_; |
| ... | ... | @@ -1075,7 +1096,7 @@ struct _UnaryOp<_Op, valarray<_Tp> > |
| 1075 | 1096 | _UnaryOp(const _Op& __op, const valarray<_Tp>& __a0) : __op_(__op), __a0_(__a0) {} |
| 1076 | 1097 | |
| 1077 | 1098 | _LIBCPP_INLINE_VISIBILITY |
| 1078 | result_type operator[](size_t __i) const {return __op_(__a0_[__i]);} | |
| 1099 | __result_type operator[](size_t __i) const {return __op_(__a0_[__i]);} | |
| 1079 | 1100 | |
| 1080 | 1101 | _LIBCPP_INLINE_VISIBILITY |
| 1081 | 1102 | size_t size() const {return __a0_.size();} |
| ... | ... | @@ -1084,8 +1105,8 @@ struct _UnaryOp<_Op, valarray<_Tp> > |
| 1084 | 1105 | template <class _Op, class _Tp, class _A1> |
| 1085 | 1106 | struct _BinaryOp<_Op, valarray<_Tp>, _A1> |
| 1086 | 1107 | { |
| 1087 | typedef typename _Op::result_type result_type; | |
| 1088 | typedef _Tp value_type; | |
| 1108 | typedef typename _Op::__result_type __result_type; | |
| 1109 | typedef typename decay<__result_type>::type value_type; | |
| 1089 | 1110 | |
| 1090 | 1111 | _Op __op_; |
| 1091 | 1112 | const valarray<_Tp>& __a0_; |
| ... | ... | @@ -1096,7 +1117,7 @@ struct _BinaryOp<_Op, valarray<_Tp>, _A1> |
| 1096 | 1117 | : __op_(__op), __a0_(__a0), __a1_(__a1) {} |
| 1097 | 1118 | |
| 1098 | 1119 | _LIBCPP_INLINE_VISIBILITY |
| 1099 | value_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 1120 | __result_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 1100 | 1121 | |
| 1101 | 1122 | _LIBCPP_INLINE_VISIBILITY |
| 1102 | 1123 | size_t size() const {return __a0_.size();} |
| ... | ... | @@ -1105,8 +1126,8 @@ struct _BinaryOp<_Op, valarray<_Tp>, _A1> |
| 1105 | 1126 | template <class _Op, class _A0, class _Tp> |
| 1106 | 1127 | struct _BinaryOp<_Op, _A0, valarray<_Tp> > |
| 1107 | 1128 | { |
| 1108 | typedef typename _Op::result_type result_type; | |
| 1109 | typedef _Tp value_type; | |
| 1129 | typedef typename _Op::__result_type __result_type; | |
| 1130 | typedef typename decay<__result_type>::type value_type; | |
| 1110 | 1131 | |
| 1111 | 1132 | _Op __op_; |
| 1112 | 1133 | _A0 __a0_; |
| ... | ... | @@ -1117,7 +1138,7 @@ struct _BinaryOp<_Op, _A0, valarray<_Tp> > |
| 1117 | 1138 | : __op_(__op), __a0_(__a0), __a1_(__a1) {} |
| 1118 | 1139 | |
| 1119 | 1140 | _LIBCPP_INLINE_VISIBILITY |
| 1120 | value_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 1141 | __result_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 1121 | 1142 | |
| 1122 | 1143 | _LIBCPP_INLINE_VISIBILITY |
| 1123 | 1144 | size_t size() const {return __a0_.size();} |
| ... | ... | @@ -1126,8 +1147,8 @@ struct _BinaryOp<_Op, _A0, valarray<_Tp> > |
| 1126 | 1147 | template <class _Op, class _Tp> |
| 1127 | 1148 | struct _BinaryOp<_Op, valarray<_Tp>, valarray<_Tp> > |
| 1128 | 1149 | { |
| 1129 | typedef typename _Op::result_type result_type; | |
| 1130 | typedef _Tp value_type; | |
| 1150 | typedef typename _Op::__result_type __result_type; | |
| 1151 | typedef typename decay<__result_type>::type value_type; | |
| 1131 | 1152 | |
| 1132 | 1153 | _Op __op_; |
| 1133 | 1154 | const valarray<_Tp>& __a0_; |
| ... | ... | @@ -1138,7 +1159,7 @@ struct _BinaryOp<_Op, valarray<_Tp>, valarray<_Tp> > |
| 1138 | 1159 | : __op_(__op), __a0_(__a0), __a1_(__a1) {} |
| 1139 | 1160 | |
| 1140 | 1161 | _LIBCPP_INLINE_VISIBILITY |
| 1141 | value_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 1162 | __result_type operator[](size_t __i) const {return __op_(__a0_[__i], __a1_[__i]);} | |
| 1142 | 1163 | |
| 1143 | 1164 | _LIBCPP_INLINE_VISIBILITY |
| 1144 | 1165 | size_t size() const {return __a0_.size();} |
| ... | ... | @@ -1518,7 +1539,7 @@ public: |
| 1518 | 1539 | __stride_(move(__stride)) |
| 1519 | 1540 | {__init(__start);} |
| 1520 | 1541 | |
| 1521 | #endif // _LIBCPP_CXX03_LANG | |
| 1542 | #endif // _LIBCPP_CXX03_LANG | |
| 1522 | 1543 | |
| 1523 | 1544 | _LIBCPP_INLINE_VISIBILITY |
| 1524 | 1545 | size_t start() const {return __1d_.size() ? __1d_[0] : 0;} |
| ... | ... | @@ -1668,7 +1689,7 @@ private: |
| 1668 | 1689 | : __vp_(const_cast<value_type*>(__v.__begin_)), |
| 1669 | 1690 | __1d_(move(__gs.__1d_)) |
| 1670 | 1691 | {} |
| 1671 | #endif // _LIBCPP_CXX03_LANG | |
| 1692 | #endif // _LIBCPP_CXX03_LANG | |
| 1672 | 1693 | |
| 1673 | 1694 | template <class> friend class valarray; |
| 1674 | 1695 | }; |
| ... | ... | @@ -2199,7 +2220,7 @@ class __mask_expr |
| 2199 | 2220 | typedef typename remove_reference<_ValExpr>::type _RmExpr; |
| 2200 | 2221 | public: |
| 2201 | 2222 | typedef typename _RmExpr::value_type value_type; |
| 2202 | typedef value_type result_type; | |
| 2223 | typedef value_type __result_type; | |
| 2203 | 2224 | |
| 2204 | 2225 | private: |
| 2205 | 2226 | _ValExpr __expr_; |
| ... | ... | @@ -2218,7 +2239,7 @@ private: |
| 2218 | 2239 | |
| 2219 | 2240 | public: |
| 2220 | 2241 | _LIBCPP_INLINE_VISIBILITY |
| 2221 | result_type operator[](size_t __i) const | |
| 2242 | __result_type operator[](size_t __i) const | |
| 2222 | 2243 | {return __expr_[__1d_[__i]];} |
| 2223 | 2244 | |
| 2224 | 2245 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -2363,7 +2384,7 @@ private: |
| 2363 | 2384 | __1d_(move(__ia)) |
| 2364 | 2385 | {} |
| 2365 | 2386 | |
| 2366 | #endif // _LIBCPP_CXX03_LANG | |
| 2387 | #endif // _LIBCPP_CXX03_LANG | |
| 2367 | 2388 | |
| 2368 | 2389 | template <class> friend class valarray; |
| 2369 | 2390 | }; |
| ... | ... | @@ -2562,7 +2583,7 @@ class __indirect_expr |
| 2562 | 2583 | typedef typename remove_reference<_ValExpr>::type _RmExpr; |
| 2563 | 2584 | public: |
| 2564 | 2585 | typedef typename _RmExpr::value_type value_type; |
| 2565 | typedef value_type result_type; | |
| 2586 | typedef value_type __result_type; | |
| 2566 | 2587 | |
| 2567 | 2588 | private: |
| 2568 | 2589 | _ValExpr __expr_; |
| ... | ... | @@ -2582,11 +2603,11 @@ private: |
| 2582 | 2603 | __1d_(move(__ia)) |
| 2583 | 2604 | {} |
| 2584 | 2605 | |
| 2585 | #endif // _LIBCPP_CXX03_LANG | |
| 2606 | #endif // _LIBCPP_CXX03_LANG | |
| 2586 | 2607 | |
| 2587 | 2608 | public: |
| 2588 | 2609 | _LIBCPP_INLINE_VISIBILITY |
| 2589 | result_type operator[](size_t __i) const | |
| 2610 | __result_type operator[](size_t __i) const | |
| 2590 | 2611 | {return __expr_[__1d_[__i]];} |
| 2591 | 2612 | |
| 2592 | 2613 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -2604,13 +2625,13 @@ class __val_expr |
| 2604 | 2625 | _ValExpr __expr_; |
| 2605 | 2626 | public: |
| 2606 | 2627 | typedef typename _RmExpr::value_type value_type; |
| 2607 | typedef typename _RmExpr::result_type result_type; | |
| 2628 | typedef typename _RmExpr::__result_type __result_type; | |
| 2608 | 2629 | |
| 2609 | 2630 | _LIBCPP_INLINE_VISIBILITY |
| 2610 | 2631 | explicit __val_expr(const _RmExpr& __e) : __expr_(__e) {} |
| 2611 | 2632 | |
| 2612 | 2633 | _LIBCPP_INLINE_VISIBILITY |
| 2613 | result_type operator[](size_t __i) const | |
| 2634 | __result_type operator[](size_t __i) const | |
| 2614 | 2635 | {return __expr_[__i];} |
| 2615 | 2636 | |
| 2616 | 2637 | _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -2673,29 +2694,29 @@ public: |
| 2673 | 2694 | return __val_expr<_NewExpr>(_NewExpr(logical_not<value_type>(), __expr_)); |
| 2674 | 2695 | } |
| 2675 | 2696 | |
| 2676 | operator valarray<result_type>() const; | |
| 2697 | operator valarray<__result_type>() const; | |
| 2677 | 2698 | |
| 2678 | 2699 | _LIBCPP_INLINE_VISIBILITY |
| 2679 | 2700 | size_t size() const {return __expr_.size();} |
| 2680 | 2701 | |
| 2681 | 2702 | _LIBCPP_INLINE_VISIBILITY |
| 2682 | result_type sum() const | |
| 2703 | __result_type sum() const | |
| 2683 | 2704 | { |
| 2684 | 2705 | size_t __n = __expr_.size(); |
| 2685 | result_type __r = __n ? __expr_[0] : result_type(); | |
| 2706 | __result_type __r = __n ? __expr_[0] : __result_type(); | |
| 2686 | 2707 | for (size_t __i = 1; __i < __n; ++__i) |
| 2687 | 2708 | __r += __expr_[__i]; |
| 2688 | 2709 | return __r; |
| 2689 | 2710 | } |
| 2690 | 2711 | |
| 2691 | 2712 | _LIBCPP_INLINE_VISIBILITY |
| 2692 | result_type min() const | |
| 2713 | __result_type min() const | |
| 2693 | 2714 | { |
| 2694 | 2715 | size_t __n = size(); |
| 2695 | result_type __r = __n ? (*this)[0] : result_type(); | |
| 2716 | __result_type __r = __n ? (*this)[0] : __result_type(); | |
| 2696 | 2717 | for (size_t __i = 1; __i < __n; ++__i) |
| 2697 | 2718 | { |
| 2698 | result_type __x = __expr_[__i]; | |
| 2719 | __result_type __x = __expr_[__i]; | |
| 2699 | 2720 | if (__x < __r) |
| 2700 | 2721 | __r = __x; |
| 2701 | 2722 | } |
| ... | ... | @@ -2703,13 +2724,13 @@ public: |
| 2703 | 2724 | } |
| 2704 | 2725 | |
| 2705 | 2726 | _LIBCPP_INLINE_VISIBILITY |
| 2706 | result_type max() const | |
| 2727 | __result_type max() const | |
| 2707 | 2728 | { |
| 2708 | 2729 | size_t __n = size(); |
| 2709 | result_type __r = __n ? (*this)[0] : result_type(); | |
| 2730 | __result_type __r = __n ? (*this)[0] : __result_type(); | |
| 2710 | 2731 | for (size_t __i = 1; __i < __n; ++__i) |
| 2711 | 2732 | { |
| 2712 | result_type __x = __expr_[__i]; | |
| 2733 | __result_type __x = __expr_[__i]; | |
| 2713 | 2734 | if (__r < __x) |
| 2714 | 2735 | __r = __x; |
| 2715 | 2736 | } |
| ... | ... | @@ -2744,16 +2765,16 @@ public: |
| 2744 | 2765 | }; |
| 2745 | 2766 | |
| 2746 | 2767 | template<class _ValExpr> |
| 2747 | __val_expr<_ValExpr>::operator valarray<__val_expr::result_type>() const | |
| 2768 | __val_expr<_ValExpr>::operator valarray<__val_expr::__result_type>() const | |
| 2748 | 2769 | { |
| 2749 | valarray<result_type> __r; | |
| 2770 | valarray<__result_type> __r; | |
| 2750 | 2771 | size_t __n = __expr_.size(); |
| 2751 | 2772 | if (__n) |
| 2752 | 2773 | { |
| 2753 | 2774 | __r.__begin_ = |
| 2754 | __r.__end_ = allocator<result_type>().allocate(__n); | |
| 2775 | __r.__end_ = allocator<__result_type>().allocate(__n); | |
| 2755 | 2776 | for (size_t __i = 0; __i != __n; ++__r.__end_, ++__i) |
| 2756 | ::new ((void*)__r.__end_) result_type(__expr_[__i]); | |
| 2777 | ::new ((void*)__r.__end_) __result_type(__expr_[__i]); | |
| 2757 | 2778 | } |
| 2758 | 2779 | return __r; |
| 2759 | 2780 | } |
| ... | ... | @@ -2772,7 +2793,7 @@ valarray<_Tp>::valarray(size_t __n) |
| 2772 | 2793 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2773 | 2794 | try |
| 2774 | 2795 | { |
| 2775 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2796 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2776 | 2797 | for (size_t __n_left = __n; __n_left; --__n_left, ++__end_) |
| 2777 | 2798 | ::new ((void*)__end_) value_type(); |
| 2778 | 2799 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2782,7 +2803,7 @@ valarray<_Tp>::valarray(size_t __n) |
| 2782 | 2803 | __clear(__n); |
| 2783 | 2804 | throw; |
| 2784 | 2805 | } |
| 2785 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2806 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2786 | 2807 | } |
| 2787 | 2808 | } |
| 2788 | 2809 | |
| ... | ... | @@ -2806,7 +2827,7 @@ valarray<_Tp>::valarray(const value_type* __p, size_t __n) |
| 2806 | 2827 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2807 | 2828 | try |
| 2808 | 2829 | { |
| 2809 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2830 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2810 | 2831 | for (size_t __n_left = __n; __n_left; ++__end_, ++__p, --__n_left) |
| 2811 | 2832 | ::new ((void*)__end_) value_type(*__p); |
| 2812 | 2833 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2816,7 +2837,7 @@ valarray<_Tp>::valarray(const value_type* __p, size_t __n) |
| 2816 | 2837 | __clear(__n); |
| 2817 | 2838 | throw; |
| 2818 | 2839 | } |
| 2819 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2840 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2820 | 2841 | } |
| 2821 | 2842 | } |
| 2822 | 2843 | |
| ... | ... | @@ -2831,7 +2852,7 @@ valarray<_Tp>::valarray(const valarray& __v) |
| 2831 | 2852 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2832 | 2853 | try |
| 2833 | 2854 | { |
| 2834 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2855 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2835 | 2856 | for (value_type* __p = __v.__begin_; __p != __v.__end_; ++__end_, ++__p) |
| 2836 | 2857 | ::new ((void*)__end_) value_type(*__p); |
| 2837 | 2858 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2841,7 +2862,7 @@ valarray<_Tp>::valarray(const valarray& __v) |
| 2841 | 2862 | __clear(__v.size()); |
| 2842 | 2863 | throw; |
| 2843 | 2864 | } |
| 2844 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2865 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2845 | 2866 | } |
| 2846 | 2867 | } |
| 2847 | 2868 | |
| ... | ... | @@ -2868,7 +2889,7 @@ valarray<_Tp>::valarray(initializer_list<value_type> __il) |
| 2868 | 2889 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2869 | 2890 | try |
| 2870 | 2891 | { |
| 2871 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2892 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2872 | 2893 | size_t __n_left = __n; |
| 2873 | 2894 | for (const value_type* __p = __il.begin(); __n_left; ++__end_, ++__p, --__n_left) |
| 2874 | 2895 | ::new ((void*)__end_) value_type(*__p); |
| ... | ... | @@ -2879,11 +2900,11 @@ valarray<_Tp>::valarray(initializer_list<value_type> __il) |
| 2879 | 2900 | __clear(__n); |
| 2880 | 2901 | throw; |
| 2881 | 2902 | } |
| 2882 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2903 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2883 | 2904 | } |
| 2884 | 2905 | } |
| 2885 | 2906 | |
| 2886 | #endif // _LIBCPP_CXX03_LANG | |
| 2907 | #endif // _LIBCPP_CXX03_LANG | |
| 2887 | 2908 | |
| 2888 | 2909 | template <class _Tp> |
| 2889 | 2910 | valarray<_Tp>::valarray(const slice_array<value_type>& __sa) |
| ... | ... | @@ -2897,7 +2918,7 @@ valarray<_Tp>::valarray(const slice_array<value_type>& __sa) |
| 2897 | 2918 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2898 | 2919 | try |
| 2899 | 2920 | { |
| 2900 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2921 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2901 | 2922 | size_t __n_left = __n; |
| 2902 | 2923 | for (const value_type* __p = __sa.__vp_; __n_left; ++__end_, __p += __sa.__stride_, --__n_left) |
| 2903 | 2924 | ::new ((void*)__end_) value_type(*__p); |
| ... | ... | @@ -2908,7 +2929,7 @@ valarray<_Tp>::valarray(const slice_array<value_type>& __sa) |
| 2908 | 2929 | __clear(__n); |
| 2909 | 2930 | throw; |
| 2910 | 2931 | } |
| 2911 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2932 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2912 | 2933 | } |
| 2913 | 2934 | } |
| 2914 | 2935 | |
| ... | ... | @@ -2924,7 +2945,7 @@ valarray<_Tp>::valarray(const gslice_array<value_type>& __ga) |
| 2924 | 2945 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2925 | 2946 | try |
| 2926 | 2947 | { |
| 2927 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2948 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2928 | 2949 | typedef const size_t* _Ip; |
| 2929 | 2950 | const value_type* __s = __ga.__vp_; |
| 2930 | 2951 | for (_Ip __i = __ga.__1d_.__begin_, __e = __ga.__1d_.__end_; |
| ... | ... | @@ -2937,7 +2958,7 @@ valarray<_Tp>::valarray(const gslice_array<value_type>& __ga) |
| 2937 | 2958 | __clear(__n); |
| 2938 | 2959 | throw; |
| 2939 | 2960 | } |
| 2940 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2961 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2941 | 2962 | } |
| 2942 | 2963 | } |
| 2943 | 2964 | |
| ... | ... | @@ -2953,7 +2974,7 @@ valarray<_Tp>::valarray(const mask_array<value_type>& __ma) |
| 2953 | 2974 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2954 | 2975 | try |
| 2955 | 2976 | { |
| 2956 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2977 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2957 | 2978 | typedef const size_t* _Ip; |
| 2958 | 2979 | const value_type* __s = __ma.__vp_; |
| 2959 | 2980 | for (_Ip __i = __ma.__1d_.__begin_, __e = __ma.__1d_.__end_; |
| ... | ... | @@ -2966,7 +2987,7 @@ valarray<_Tp>::valarray(const mask_array<value_type>& __ma) |
| 2966 | 2987 | __clear(__n); |
| 2967 | 2988 | throw; |
| 2968 | 2989 | } |
| 2969 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2990 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2970 | 2991 | } |
| 2971 | 2992 | } |
| 2972 | 2993 | |
| ... | ... | @@ -2982,7 +3003,7 @@ valarray<_Tp>::valarray(const indirect_array<value_type>& __ia) |
| 2982 | 3003 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2983 | 3004 | try |
| 2984 | 3005 | { |
| 2985 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3006 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2986 | 3007 | typedef const size_t* _Ip; |
| 2987 | 3008 | const value_type* __s = __ia.__vp_; |
| 2988 | 3009 | for (_Ip __i = __ia.__1d_.__begin_, __e = __ia.__1d_.__end_; |
| ... | ... | @@ -2995,7 +3016,7 @@ valarray<_Tp>::valarray(const indirect_array<value_type>& __ia) |
| 2995 | 3016 | __clear(__n); |
| 2996 | 3017 | throw; |
| 2997 | 3018 | } |
| 2998 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3019 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2999 | 3020 | } |
| 3000 | 3021 | } |
| 3001 | 3022 | |
| ... | ... | @@ -3055,7 +3076,7 @@ valarray<_Tp>::operator=(initializer_list<value_type> __il) |
| 3055 | 3076 | return __assign_range(__il.begin(), __il.end()); |
| 3056 | 3077 | } |
| 3057 | 3078 | |
| 3058 | #endif // _LIBCPP_CXX03_LANG | |
| 3079 | #endif // _LIBCPP_CXX03_LANG | |
| 3059 | 3080 | |
| 3060 | 3081 | template <class _Tp> |
| 3061 | 3082 | inline |
| ... | ... | @@ -3131,7 +3152,7 @@ valarray<_Tp>::operator=(const __val_expr<_ValExpr>& __v) |
| 3131 | 3152 | resize(__n); |
| 3132 | 3153 | value_type* __t = __begin_; |
| 3133 | 3154 | for (size_t __i = 0; __i != __n; ++__t, ++__i) |
| 3134 | *__t = result_type(__v[__i]); | |
| 3155 | *__t = __result_type(__v[__i]); | |
| 3135 | 3156 | return *this; |
| 3136 | 3157 | } |
| 3137 | 3158 | |
| ... | ... | @@ -3185,7 +3206,7 @@ valarray<_Tp>::operator[](gslice&& __gs) |
| 3185 | 3206 | return gslice_array<value_type>(move(__gs), *this); |
| 3186 | 3207 | } |
| 3187 | 3208 | |
| 3188 | #endif // _LIBCPP_CXX03_LANG | |
| 3209 | #endif // _LIBCPP_CXX03_LANG | |
| 3189 | 3210 | |
| 3190 | 3211 | template <class _Tp> |
| 3191 | 3212 | inline |
| ... | ... | @@ -3221,7 +3242,7 @@ valarray<_Tp>::operator[](valarray<bool>&& __vb) |
| 3221 | 3242 | return mask_array<value_type>(move(__vb), *this); |
| 3222 | 3243 | } |
| 3223 | 3244 | |
| 3224 | #endif // _LIBCPP_CXX03_LANG | |
| 3245 | #endif // _LIBCPP_CXX03_LANG | |
| 3225 | 3246 | |
| 3226 | 3247 | template <class _Tp> |
| 3227 | 3248 | inline |
| ... | ... | @@ -3257,7 +3278,7 @@ valarray<_Tp>::operator[](valarray<size_t>&& __vs) |
| 3257 | 3278 | return indirect_array<value_type>(move(__vs), *this); |
| 3258 | 3279 | } |
| 3259 | 3280 | |
| 3260 | #endif // _LIBCPP_CXX03_LANG | |
| 3281 | #endif // _LIBCPP_CXX03_LANG | |
| 3261 | 3282 | |
| 3262 | 3283 | template <class _Tp> |
| 3263 | 3284 | valarray<_Tp> |
| ... | ... | @@ -3731,7 +3752,7 @@ valarray<_Tp>::resize(size_t __n, value_type __x) |
| 3731 | 3752 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 3732 | 3753 | try |
| 3733 | 3754 | { |
| 3734 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3755 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3735 | 3756 | for (size_t __n_left = __n; __n_left; --__n_left, ++__end_) |
| 3736 | 3757 | ::new ((void*)__end_) value_type(__x); |
| 3737 | 3758 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -3741,7 +3762,7 @@ valarray<_Tp>::resize(size_t __n, value_type __x) |
| 3741 | 3762 | __clear(__n); |
| 3742 | 3763 | throw; |
| 3743 | 3764 | } |
| 3744 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3765 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3745 | 3766 | } |
| 3746 | 3767 | } |
| 3747 | 3768 | |
| ... | ... | @@ -4905,4 +4926,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 4905 | 4926 | |
| 4906 | 4927 | _LIBCPP_POP_MACROS |
| 4907 | 4928 | |
| 4908 | #endif // _LIBCPP_VALARRAY | |
| 4929 | #endif // _LIBCPP_VALARRAY |
lib/libcxx/include/variant+90-50| ... | ... | @@ -199,18 +199,20 @@ namespace std { |
| 199 | 199 | |
| 200 | 200 | */ |
| 201 | 201 | |
| 202 | #include <__config> | |
| 203 | 202 | #include <__availability> |
| 203 | #include <__config> | |
| 204 | #include <__functional/hash.h> | |
| 204 | 205 | #include <__tuple> |
| 205 | #include <array> | |
| 206 | #include <__utility/forward.h> | |
| 207 | #include <__variant/monostate.h> | |
| 208 | #include <compare> | |
| 206 | 209 | #include <exception> |
| 207 | #include <functional> | |
| 208 | 210 | #include <initializer_list> |
| 211 | #include <limits> | |
| 209 | 212 | #include <new> |
| 210 | 213 | #include <tuple> |
| 211 | 214 | #include <type_traits> |
| 212 | 215 | #include <utility> |
| 213 | #include <limits> | |
| 214 | 216 | #include <version> |
| 215 | 217 | |
| 216 | 218 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| ... | ... | @@ -236,6 +238,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD |
| 236 | 238 | // Remove this once we drop support for GCC 5. |
| 237 | 239 | #if _LIBCPP_STD_VER > 14 && !(defined(_LIBCPP_COMPILER_GCC) && _GNUC_VER_NEW < 6000) |
| 238 | 240 | |
| 241 | // Light N-dimensional array of function pointers. Used in place of std::array to avoid | |
| 242 | // adding a dependency. | |
| 243 | template<class _Tp, size_t _Size> | |
| 244 | struct __farray { | |
| 245 | static_assert(_Size > 0, "N-dimensional array should never be empty in std::visit"); | |
| 246 | _Tp __buf_[_Size] = {}; | |
| 247 | ||
| 248 | _LIBCPP_INLINE_VISIBILITY constexpr | |
| 249 | const _Tp &operator[](size_t __n) const noexcept { | |
| 250 | return __buf_[__n]; | |
| 251 | } | |
| 252 | }; | |
| 253 | ||
| 239 | 254 | _LIBCPP_NORETURN |
| 240 | 255 | inline _LIBCPP_INLINE_VISIBILITY |
| 241 | 256 | _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS |
| ... | ... | @@ -318,6 +333,33 @@ using __variant_index_t = |
| 318 | 333 | template <class _IndexType> |
| 319 | 334 | constexpr _IndexType __variant_npos = static_cast<_IndexType>(-1); |
| 320 | 335 | |
| 336 | template <class... _Types> | |
| 337 | class _LIBCPP_TEMPLATE_VIS variant; | |
| 338 | ||
| 339 | template <class... _Types> | |
| 340 | _LIBCPP_INLINE_VISIBILITY constexpr variant<_Types...>& | |
| 341 | __as_variant(variant<_Types...>& __vs) noexcept { | |
| 342 | return __vs; | |
| 343 | } | |
| 344 | ||
| 345 | template <class... _Types> | |
| 346 | _LIBCPP_INLINE_VISIBILITY constexpr const variant<_Types...>& | |
| 347 | __as_variant(const variant<_Types...>& __vs) noexcept { | |
| 348 | return __vs; | |
| 349 | } | |
| 350 | ||
| 351 | template <class... _Types> | |
| 352 | _LIBCPP_INLINE_VISIBILITY constexpr variant<_Types...>&& | |
| 353 | __as_variant(variant<_Types...>&& __vs) noexcept { | |
| 354 | return _VSTD::move(__vs); | |
| 355 | } | |
| 356 | ||
| 357 | template <class... _Types> | |
| 358 | _LIBCPP_INLINE_VISIBILITY constexpr const variant<_Types...>&& | |
| 359 | __as_variant(const variant<_Types...>&& __vs) noexcept { | |
| 360 | return _VSTD::move(__vs); | |
| 361 | } | |
| 362 | ||
| 321 | 363 | namespace __find_detail { |
| 322 | 364 | |
| 323 | 365 | template <class _Tp, class... _Types> |
| ... | ... | @@ -469,7 +511,7 @@ private: |
| 469 | 511 | |
| 470 | 512 | template <class _Tp, size_t _Np, typename... _Indices> |
| 471 | 513 | inline _LIBCPP_INLINE_VISIBILITY |
| 472 | static constexpr auto&& __at(const array<_Tp, _Np>& __elems, | |
| 514 | static constexpr auto&& __at(const __farray<_Tp, _Np>& __elems, | |
| 473 | 515 | size_t __index, _Indices... __indices) { |
| 474 | 516 | return __at(__elems[__index], __indices...); |
| 475 | 517 | } |
| ... | ... | @@ -485,7 +527,7 @@ private: |
| 485 | 527 | inline _LIBCPP_INLINE_VISIBILITY |
| 486 | 528 | static constexpr auto __make_farray(_Fs&&... __fs) { |
| 487 | 529 | __std_visit_visitor_return_type_check<__uncvref_t<_Fs>...>(); |
| 488 | using __result = array<common_type_t<__uncvref_t<_Fs>...>, sizeof...(_Fs)>; | |
| 530 | using __result = __farray<common_type_t<__uncvref_t<_Fs>...>, sizeof...(_Fs)>; | |
| 489 | 531 | return __result{{_VSTD::forward<_Fs>(__fs)...}}; |
| 490 | 532 | } |
| 491 | 533 | |
| ... | ... | @@ -564,8 +606,9 @@ struct __variant { |
| 564 | 606 | inline _LIBCPP_INLINE_VISIBILITY |
| 565 | 607 | static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor, |
| 566 | 608 | _Vs&&... __vs) { |
| 567 | return __base::__visit_alt(_VSTD::forward<_Visitor>(__visitor), | |
| 568 | _VSTD::forward<_Vs>(__vs).__impl...); | |
| 609 | return __base::__visit_alt( | |
| 610 | _VSTD::forward<_Visitor>(__visitor), | |
| 611 | _VSTD::__as_variant(_VSTD::forward<_Vs>(__vs)).__impl...); | |
| 569 | 612 | } |
| 570 | 613 | |
| 571 | 614 | template <class _Visitor, class... _Vs> |
| ... | ... | @@ -586,6 +629,7 @@ struct __variant { |
| 586 | 629 | __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)), |
| 587 | 630 | _VSTD::forward<_Vs>(__vs)...); |
| 588 | 631 | } |
| 632 | ||
| 589 | 633 | #if _LIBCPP_STD_VER > 17 |
| 590 | 634 | template <class _Rp, class _Visitor, class... _Vs> |
| 591 | 635 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1152,7 +1196,7 @@ struct __narrowing_check { |
| 1152 | 1196 | template <class _Dest> |
| 1153 | 1197 | static auto __test_impl(_Dest (&&)[1]) -> __identity<_Dest>; |
| 1154 | 1198 | template <class _Dest, class _Source> |
| 1155 | using _Apply _LIBCPP_NODEBUG_TYPE = decltype(__test_impl<_Dest>({_VSTD::declval<_Source>()})); | |
| 1199 | using _Apply _LIBCPP_NODEBUG_TYPE = decltype(__test_impl<_Dest>({declval<_Source>()})); | |
| 1156 | 1200 | }; |
| 1157 | 1201 | |
| 1158 | 1202 | template <class _Dest, class _Source> |
| ... | ... | @@ -1637,18 +1681,21 @@ constexpr bool operator>=(const variant<_Types...>& __lhs, |
| 1637 | 1681 | |
| 1638 | 1682 | template <class... _Vs> |
| 1639 | 1683 | inline _LIBCPP_INLINE_VISIBILITY |
| 1640 | _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS | |
| 1641 | constexpr void __throw_if_valueless(_Vs&&... __vs) { | |
| 1642 | const bool __valueless = (... || __vs.valueless_by_exception()); | |
| 1684 | _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr void | |
| 1685 | __throw_if_valueless(_Vs&&... __vs) { | |
| 1686 | const bool __valueless = | |
| 1687 | (... || _VSTD::__as_variant(__vs).valueless_by_exception()); | |
| 1643 | 1688 | if (__valueless) { |
| 1644 | __throw_bad_variant_access(); | |
| 1689 | __throw_bad_variant_access(); | |
| 1645 | 1690 | } |
| 1646 | 1691 | } |
| 1647 | 1692 | |
| 1648 | template <class _Visitor, class... _Vs> | |
| 1693 | template < | |
| 1694 | class _Visitor, class... _Vs, | |
| 1695 | typename = void_t<decltype(_VSTD::__as_variant(declval<_Vs>()))...> > | |
| 1649 | 1696 | inline _LIBCPP_INLINE_VISIBILITY |
| 1650 | _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS | |
| 1651 | constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { | |
| 1697 | _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr | |
| 1698 | decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { | |
| 1652 | 1699 | using __variant_detail::__visitation::__variant; |
| 1653 | 1700 | _VSTD::__throw_if_valueless(_VSTD::forward<_Vs>(__vs)...); |
| 1654 | 1701 | return __variant::__visit_value(_VSTD::forward<_Visitor>(__visitor), |
| ... | ... | @@ -1656,10 +1703,12 @@ constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { |
| 1656 | 1703 | } |
| 1657 | 1704 | |
| 1658 | 1705 | #if _LIBCPP_STD_VER > 17 |
| 1659 | template <class _Rp, class _Visitor, class... _Vs> | |
| 1706 | template < | |
| 1707 | class _Rp, class _Visitor, class... _Vs, | |
| 1708 | typename = void_t<decltype(_VSTD::__as_variant(declval<_Vs>()))...> > | |
| 1660 | 1709 | inline _LIBCPP_INLINE_VISIBILITY |
| 1661 | _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS | |
| 1662 | constexpr _Rp visit(_Visitor&& __visitor, _Vs&&... __vs) { | |
| 1710 | _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Rp | |
| 1711 | visit(_Visitor&& __visitor, _Vs&&... __vs) { | |
| 1663 | 1712 | using __variant_detail::__visitation::__variant; |
| 1664 | 1713 | _VSTD::__throw_if_valueless(_VSTD::forward<_Vs>(__vs)...); |
| 1665 | 1714 | return __variant::__visit_value<_Rp>(_VSTD::forward<_Visitor>(__visitor), |
| ... | ... | @@ -1667,26 +1716,6 @@ constexpr _Rp visit(_Visitor&& __visitor, _Vs&&... __vs) { |
| 1667 | 1716 | } |
| 1668 | 1717 | #endif |
| 1669 | 1718 | |
| 1670 | struct _LIBCPP_TEMPLATE_VIS monostate {}; | |
| 1671 | ||
| 1672 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1673 | constexpr bool operator<(monostate, monostate) noexcept { return false; } | |
| 1674 | ||
| 1675 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1676 | constexpr bool operator>(monostate, monostate) noexcept { return false; } | |
| 1677 | ||
| 1678 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1679 | constexpr bool operator<=(monostate, monostate) noexcept { return true; } | |
| 1680 | ||
| 1681 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1682 | constexpr bool operator>=(monostate, monostate) noexcept { return true; } | |
| 1683 | ||
| 1684 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1685 | constexpr bool operator==(monostate, monostate) noexcept { return true; } | |
| 1686 | ||
| 1687 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1688 | constexpr bool operator!=(monostate, monostate) noexcept { return false; } | |
| 1689 | ||
| 1690 | 1719 | template <class... _Types> |
| 1691 | 1720 | inline _LIBCPP_INLINE_VISIBILITY |
| 1692 | 1721 | auto swap(variant<_Types...>& __lhs, |
| ... | ... | @@ -1719,21 +1748,32 @@ struct _LIBCPP_TEMPLATE_VIS hash< |
| 1719 | 1748 | } |
| 1720 | 1749 | }; |
| 1721 | 1750 | |
| 1722 | template <> | |
| 1723 | struct _LIBCPP_TEMPLATE_VIS hash<monostate> { | |
| 1724 | using argument_type = monostate; | |
| 1725 | using result_type = size_t; | |
| 1751 | // __unchecked_get is the same as std::get, except, it is UB to use it with the wrong | |
| 1752 | // type whereas std::get will throw or returning nullptr. This makes it faster than | |
| 1753 | // std::get. | |
| 1754 | template <size_t _Ip, class _Vp> | |
| 1755 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1756 | constexpr auto&& __unchecked_get(_Vp&& __v) noexcept { | |
| 1757 | using __variant_detail::__access::__variant; | |
| 1758 | return __variant::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)).__value; | |
| 1759 | } | |
| 1726 | 1760 | |
| 1727 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1728 | result_type operator()(const argument_type&) const _NOEXCEPT { | |
| 1729 | return 66740831; // return a fundamentally attractive random value. | |
| 1730 | } | |
| 1731 | }; | |
| 1761 | template <class _Tp, class... _Types> | |
| 1762 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1763 | constexpr auto&& __unchecked_get(const variant<_Types...>& __v) noexcept { | |
| 1764 | return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); | |
| 1765 | } | |
| 1766 | ||
| 1767 | template <class _Tp, class... _Types> | |
| 1768 | inline _LIBCPP_INLINE_VISIBILITY | |
| 1769 | constexpr auto&& __unchecked_get(variant<_Types...>& __v) noexcept { | |
| 1770 | return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); | |
| 1771 | } | |
| 1732 | 1772 | |
| 1733 | #endif // _LIBCPP_STD_VER > 14 | |
| 1773 | #endif // _LIBCPP_STD_VER > 14 | |
| 1734 | 1774 | |
| 1735 | 1775 | _LIBCPP_END_NAMESPACE_STD |
| 1736 | 1776 | |
| 1737 | 1777 | _LIBCPP_POP_MACROS |
| 1738 | 1778 | |
| 1739 | #endif // _LIBCPP_VARIANT | |
| 1779 | #endif // _LIBCPP_VARIANT |
lib/libcxx/include/vector+53-51| ... | ... | @@ -144,7 +144,7 @@ public: |
| 144 | 144 | public: |
| 145 | 145 | reference(const reference&) noexcept; |
| 146 | 146 | operator bool() const noexcept; |
| 147 | reference& operator=(const bool x) noexcept; | |
| 147 | reference& operator=(bool x) noexcept; | |
| 148 | 148 | reference& operator=(const reference& x) noexcept; |
| 149 | 149 | iterator operator&() const noexcept; |
| 150 | 150 | void flip() noexcept; |
| ... | ... | @@ -272,21 +272,23 @@ erase_if(vector<T, Allocator>& c, Predicate pred); // C++20 |
| 272 | 272 | */ |
| 273 | 273 | |
| 274 | 274 | #include <__config> |
| 275 | #include <iosfwd> // for forward declaration of vector | |
| 276 | 275 | #include <__bit_reference> |
| 277 | #include <type_traits> | |
| 276 | #include <__debug> | |
| 277 | #include <__functional_base> | |
| 278 | #include <__iterator/wrap_iter.h> | |
| 279 | #include <__split_buffer> | |
| 280 | #include <__utility/forward.h> | |
| 281 | #include <algorithm> | |
| 278 | 282 | #include <climits> |
| 279 | #include <limits> | |
| 283 | #include <compare> | |
| 284 | #include <cstring> | |
| 280 | 285 | #include <initializer_list> |
| 286 | #include <iosfwd> // for forward declaration of vector | |
| 287 | #include <limits> | |
| 281 | 288 | #include <memory> |
| 282 | 289 | #include <stdexcept> |
| 283 | #include <algorithm> | |
| 284 | #include <cstring> | |
| 290 | #include <type_traits> | |
| 285 | 291 | #include <version> |
| 286 | #include <__split_buffer> | |
| 287 | #include <__functional_base> | |
| 288 | ||
| 289 | #include <__debug> | |
| 290 | 292 | |
| 291 | 293 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 292 | 294 | #pragma GCC system_header |
| ... | ... | @@ -557,7 +559,7 @@ public: |
| 557 | 559 | } |
| 558 | 560 | |
| 559 | 561 | vector(const vector& __x); |
| 560 | vector(const vector& __x, const allocator_type& __a); | |
| 562 | vector(const vector& __x, const __identity_t<allocator_type>& __a); | |
| 561 | 563 | _LIBCPP_INLINE_VISIBILITY |
| 562 | 564 | vector& operator=(const vector& __x); |
| 563 | 565 | |
| ... | ... | @@ -577,7 +579,7 @@ public: |
| 577 | 579 | #endif |
| 578 | 580 | |
| 579 | 581 | _LIBCPP_INLINE_VISIBILITY |
| 580 | vector(vector&& __x, const allocator_type& __a); | |
| 582 | vector(vector&& __x, const __identity_t<allocator_type>& __a); | |
| 581 | 583 | _LIBCPP_INLINE_VISIBILITY |
| 582 | 584 | vector& operator=(vector&& __x) |
| 583 | 585 | _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); |
| ... | ... | @@ -586,7 +588,7 @@ public: |
| 586 | 588 | vector& operator=(initializer_list<value_type> __il) |
| 587 | 589 | {assign(__il.begin(), __il.end()); return *this;} |
| 588 | 590 | |
| 589 | #endif // !_LIBCPP_CXX03_LANG | |
| 591 | #endif // !_LIBCPP_CXX03_LANG | |
| 590 | 592 | |
| 591 | 593 | template <class _InputIterator> |
| 592 | 594 | typename enable_if |
| ... | ... | @@ -673,22 +675,22 @@ public: |
| 673 | 675 | |
| 674 | 676 | _LIBCPP_INLINE_VISIBILITY reference front() _NOEXCEPT |
| 675 | 677 | { |
| 676 | _LIBCPP_ASSERT(!empty(), "front() called for empty vector"); | |
| 678 | _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); | |
| 677 | 679 | return *this->__begin_; |
| 678 | 680 | } |
| 679 | 681 | _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT |
| 680 | 682 | { |
| 681 | _LIBCPP_ASSERT(!empty(), "front() called for empty vector"); | |
| 683 | _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); | |
| 682 | 684 | return *this->__begin_; |
| 683 | 685 | } |
| 684 | 686 | _LIBCPP_INLINE_VISIBILITY reference back() _NOEXCEPT |
| 685 | 687 | { |
| 686 | _LIBCPP_ASSERT(!empty(), "back() called for empty vector"); | |
| 688 | _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); | |
| 687 | 689 | return *(this->__end_ - 1); |
| 688 | 690 | } |
| 689 | 691 | _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT |
| 690 | 692 | { |
| 691 | _LIBCPP_ASSERT(!empty(), "back() called for empty vector"); | |
| 693 | _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); | |
| 692 | 694 | return *(this->__end_ - 1); |
| 693 | 695 | } |
| 694 | 696 | |
| ... | ... | @@ -733,7 +735,7 @@ public: |
| 733 | 735 | iterator insert(const_iterator __position, value_type&& __x); |
| 734 | 736 | template <class... _Args> |
| 735 | 737 | iterator emplace(const_iterator __position, _Args&&... __args); |
| 736 | #endif // !_LIBCPP_CXX03_LANG | |
| 738 | #endif // !_LIBCPP_CXX03_LANG | |
| 737 | 739 | |
| 738 | 740 | iterator insert(const_iterator __position, size_type __n, const_reference __x); |
| 739 | 741 | template <class _InputIterator> |
| ... | ... | @@ -796,7 +798,7 @@ public: |
| 796 | 798 | bool __addable(const const_iterator* __i, ptrdiff_t __n) const; |
| 797 | 799 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; |
| 798 | 800 | |
| 799 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 801 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 800 | 802 | |
| 801 | 803 | private: |
| 802 | 804 | _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators(); |
| ... | ... | @@ -931,18 +933,18 @@ private: |
| 931 | 933 | |
| 932 | 934 | #ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES |
| 933 | 935 | template<class _InputIterator, |
| 934 | class _Alloc = allocator<typename iterator_traits<_InputIterator>::value_type>, | |
| 935 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 936 | class _Alloc = allocator<__iter_value_type<_InputIterator>>, | |
| 937 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 936 | 938 | > |
| 937 | 939 | vector(_InputIterator, _InputIterator) |
| 938 | -> vector<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 940 | -> vector<__iter_value_type<_InputIterator>, _Alloc>; | |
| 939 | 941 | |
| 940 | 942 | template<class _InputIterator, |
| 941 | 943 | class _Alloc, |
| 942 | class = typename enable_if<__is_allocator<_Alloc>::value, void>::type | |
| 944 | class = _EnableIf<__is_allocator<_Alloc>::value> | |
| 943 | 945 | > |
| 944 | 946 | vector(_InputIterator, _InputIterator, _Alloc) |
| 945 | -> vector<typename iterator_traits<_InputIterator>::value_type, _Alloc>; | |
| 947 | -> vector<__iter_value_type<_InputIterator>, _Alloc>; | |
| 946 | 948 | #endif |
| 947 | 949 | |
| 948 | 950 | template <class _Tp, class _Allocator> |
| ... | ... | @@ -1027,7 +1029,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const |
| 1027 | 1029 | const size_type __cap = capacity(); |
| 1028 | 1030 | if (__cap >= __ms / 2) |
| 1029 | 1031 | return __ms; |
| 1030 | return _VSTD::max<size_type>(2*__cap, __new_size); | |
| 1032 | return _VSTD::max<size_type>(2 * __cap, __new_size); | |
| 1031 | 1033 | } |
| 1032 | 1034 | |
| 1033 | 1035 | // Default constructs __n objects starting at __end_ |
| ... | ... | @@ -1261,7 +1263,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x) |
| 1261 | 1263 | } |
| 1262 | 1264 | |
| 1263 | 1265 | template <class _Tp, class _Allocator> |
| 1264 | vector<_Tp, _Allocator>::vector(const vector& __x, const allocator_type& __a) | |
| 1266 | vector<_Tp, _Allocator>::vector(const vector& __x, const __identity_t<allocator_type>& __a) | |
| 1265 | 1267 | : __base(__a) |
| 1266 | 1268 | { |
| 1267 | 1269 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| ... | ... | @@ -1299,7 +1301,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x) |
| 1299 | 1301 | |
| 1300 | 1302 | template <class _Tp, class _Allocator> |
| 1301 | 1303 | inline _LIBCPP_INLINE_VISIBILITY |
| 1302 | vector<_Tp, _Allocator>::vector(vector&& __x, const allocator_type& __a) | |
| 1304 | vector<_Tp, _Allocator>::vector(vector&& __x, const __identity_t<allocator_type>& __a) | |
| 1303 | 1305 | : __base(__a) |
| 1304 | 1306 | { |
| 1305 | 1307 | #if _LIBCPP_DEBUG_LEVEL == 2 |
| ... | ... | @@ -1392,7 +1394,7 @@ vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type) |
| 1392 | 1394 | #endif |
| 1393 | 1395 | } |
| 1394 | 1396 | |
| 1395 | #endif // !_LIBCPP_CXX03_LANG | |
| 1397 | #endif // !_LIBCPP_CXX03_LANG | |
| 1396 | 1398 | |
| 1397 | 1399 | template <class _Tp, class _Allocator> |
| 1398 | 1400 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -1598,7 +1600,7 @@ vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT |
| 1598 | 1600 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1599 | 1601 | try |
| 1600 | 1602 | { |
| 1601 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1603 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1602 | 1604 | allocator_type& __a = this->__alloc(); |
| 1603 | 1605 | __split_buffer<value_type, allocator_type&> __v(size(), size(), __a); |
| 1604 | 1606 | __swap_out_circular_buffer(__v); |
| ... | ... | @@ -1607,7 +1609,7 @@ vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT |
| 1607 | 1609 | catch (...) |
| 1608 | 1610 | { |
| 1609 | 1611 | } |
| 1610 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1612 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1611 | 1613 | } |
| 1612 | 1614 | } |
| 1613 | 1615 | |
| ... | ... | @@ -1690,14 +1692,14 @@ vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) |
| 1690 | 1692 | #endif |
| 1691 | 1693 | } |
| 1692 | 1694 | |
| 1693 | #endif // !_LIBCPP_CXX03_LANG | |
| 1695 | #endif // !_LIBCPP_CXX03_LANG | |
| 1694 | 1696 | |
| 1695 | 1697 | template <class _Tp, class _Allocator> |
| 1696 | 1698 | inline |
| 1697 | 1699 | void |
| 1698 | 1700 | vector<_Tp, _Allocator>::pop_back() |
| 1699 | 1701 | { |
| 1700 | _LIBCPP_ASSERT(!empty(), "vector::pop_back called for empty vector"); | |
| 1702 | _LIBCPP_ASSERT(!empty(), "vector::pop_back called on an empty vector"); | |
| 1701 | 1703 | this->__destruct_at_end(this->__end_ - 1); |
| 1702 | 1704 | } |
| 1703 | 1705 | |
| ... | ... | @@ -1865,7 +1867,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) |
| 1865 | 1867 | return __make_iter(__p); |
| 1866 | 1868 | } |
| 1867 | 1869 | |
| 1868 | #endif // !_LIBCPP_CXX03_LANG | |
| 1870 | #endif // !_LIBCPP_CXX03_LANG | |
| 1869 | 1871 | |
| 1870 | 1872 | template <class _Tp, class _Allocator> |
| 1871 | 1873 | typename vector<_Tp, _Allocator>::iterator |
| ... | ... | @@ -1941,7 +1943,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __firs |
| 1941 | 1943 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 1942 | 1944 | try |
| 1943 | 1945 | { |
| 1944 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1946 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1945 | 1947 | __v.__construct_at_end(__first, __last); |
| 1946 | 1948 | difference_type __old_size = __old_last - this->__begin_; |
| 1947 | 1949 | difference_type __old_p = __p - this->__begin_; |
| ... | ... | @@ -1955,7 +1957,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __firs |
| 1955 | 1957 | erase(__make_iter(__old_last), end()); |
| 1956 | 1958 | throw; |
| 1957 | 1959 | } |
| 1958 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1960 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 1959 | 1961 | } |
| 1960 | 1962 | __p = _VSTD::rotate(__p, __old_last, this->__end_); |
| 1961 | 1963 | insert(__make_iter(__p), _VSTD::make_move_iterator(__v.begin()), |
| ... | ... | @@ -2114,7 +2116,7 @@ vector<_Tp, _Allocator>::__subscriptable(const const_iterator* __i, ptrdiff_t __ |
| 2114 | 2116 | return this->__begin_ <= __p && __p < this->__end_; |
| 2115 | 2117 | } |
| 2116 | 2118 | |
| 2117 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2119 | #endif // _LIBCPP_DEBUG_LEVEL == 2 | |
| 2118 | 2120 | |
| 2119 | 2121 | template <class _Tp, class _Allocator> |
| 2120 | 2122 | inline _LIBCPP_INLINE_VISIBILITY |
| ... | ... | @@ -2261,7 +2263,7 @@ public: |
| 2261 | 2263 | #else |
| 2262 | 2264 | _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); |
| 2263 | 2265 | #endif |
| 2264 | vector(vector&& __v, const allocator_type& __a); | |
| 2266 | vector(vector&& __v, const __identity_t<allocator_type>& __a); | |
| 2265 | 2267 | _LIBCPP_INLINE_VISIBILITY |
| 2266 | 2268 | vector& operator=(vector&& __v) |
| 2267 | 2269 | _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); |
| ... | ... | @@ -2270,7 +2272,7 @@ public: |
| 2270 | 2272 | vector& operator=(initializer_list<value_type> __il) |
| 2271 | 2273 | {assign(__il.begin(), __il.end()); return *this;} |
| 2272 | 2274 | |
| 2273 | #endif // !_LIBCPP_CXX03_LANG | |
| 2275 | #endif // !_LIBCPP_CXX03_LANG | |
| 2274 | 2276 | |
| 2275 | 2277 | template <class _InputIterator> |
| 2276 | 2278 | typename enable_if |
| ... | ... | @@ -2573,7 +2575,7 @@ vector<bool, _Allocator>::__recommend(size_type __new_size) const |
| 2573 | 2575 | const size_type __cap = capacity(); |
| 2574 | 2576 | if (__cap >= __ms / 2) |
| 2575 | 2577 | return __ms; |
| 2576 | return _VSTD::max(2*__cap, __align_it(__new_size)); | |
| 2578 | return _VSTD::max(2 * __cap, __align_it(__new_size)); | |
| 2577 | 2579 | } |
| 2578 | 2580 | |
| 2579 | 2581 | // Default constructs __n objects starting at __end_ |
| ... | ... | @@ -2708,7 +2710,7 @@ vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, |
| 2708 | 2710 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2709 | 2711 | try |
| 2710 | 2712 | { |
| 2711 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2713 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2712 | 2714 | for (; __first != __last; ++__first) |
| 2713 | 2715 | push_back(*__first); |
| 2714 | 2716 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2720,7 +2722,7 @@ vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, |
| 2720 | 2722 | __invalidate_all_iterators(); |
| 2721 | 2723 | throw; |
| 2722 | 2724 | } |
| 2723 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2725 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2724 | 2726 | } |
| 2725 | 2727 | |
| 2726 | 2728 | template <class _Allocator> |
| ... | ... | @@ -2735,7 +2737,7 @@ vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, |
| 2735 | 2737 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 2736 | 2738 | try |
| 2737 | 2739 | { |
| 2738 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2740 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2739 | 2741 | for (; __first != __last; ++__first) |
| 2740 | 2742 | push_back(*__first); |
| 2741 | 2743 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| ... | ... | @@ -2747,7 +2749,7 @@ vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, |
| 2747 | 2749 | __invalidate_all_iterators(); |
| 2748 | 2750 | throw; |
| 2749 | 2751 | } |
| 2750 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2752 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 2751 | 2753 | } |
| 2752 | 2754 | |
| 2753 | 2755 | template <class _Allocator> |
| ... | ... | @@ -2812,7 +2814,7 @@ vector<bool, _Allocator>::vector(initializer_list<value_type> __il, const alloca |
| 2812 | 2814 | } |
| 2813 | 2815 | } |
| 2814 | 2816 | |
| 2815 | #endif // _LIBCPP_CXX03_LANG | |
| 2817 | #endif // _LIBCPP_CXX03_LANG | |
| 2816 | 2818 | |
| 2817 | 2819 | template <class _Allocator> |
| 2818 | 2820 | vector<bool, _Allocator>::~vector() |
| ... | ... | @@ -2887,7 +2889,7 @@ inline _LIBCPP_INLINE_VISIBILITY vector<bool, _Allocator>::vector(vector&& __v) |
| 2887 | 2889 | } |
| 2888 | 2890 | |
| 2889 | 2891 | template <class _Allocator> |
| 2890 | vector<bool, _Allocator>::vector(vector&& __v, const allocator_type& __a) | |
| 2892 | vector<bool, _Allocator>::vector(vector&& __v, const __identity_t<allocator_type>& __a) | |
| 2891 | 2893 | : __begin_(nullptr), |
| 2892 | 2894 | __size_(0), |
| 2893 | 2895 | __cap_alloc_(0, __a) |
| ... | ... | @@ -2942,7 +2944,7 @@ vector<bool, _Allocator>::__move_assign(vector& __c, true_type) |
| 2942 | 2944 | __c.__cap() = __c.__size_ = 0; |
| 2943 | 2945 | } |
| 2944 | 2946 | |
| 2945 | #endif // !_LIBCPP_CXX03_LANG | |
| 2947 | #endif // !_LIBCPP_CXX03_LANG | |
| 2946 | 2948 | |
| 2947 | 2949 | template <class _Allocator> |
| 2948 | 2950 | void |
| ... | ... | @@ -3028,14 +3030,14 @@ vector<bool, _Allocator>::shrink_to_fit() _NOEXCEPT |
| 3028 | 3030 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 3029 | 3031 | try |
| 3030 | 3032 | { |
| 3031 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3033 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3032 | 3034 | vector(*this, allocator_type(__alloc())).swap(*this); |
| 3033 | 3035 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 3034 | 3036 | } |
| 3035 | 3037 | catch (...) |
| 3036 | 3038 | { |
| 3037 | 3039 | } |
| 3038 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3040 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3039 | 3041 | } |
| 3040 | 3042 | } |
| 3041 | 3043 | |
| ... | ... | @@ -3142,7 +3144,7 @@ vector<bool, _Allocator>::insert(const_iterator __position, _InputIterator __fir |
| 3142 | 3144 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 3143 | 3145 | try |
| 3144 | 3146 | { |
| 3145 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3147 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3146 | 3148 | __v.assign(__first, __last); |
| 3147 | 3149 | difference_type __old_size = static_cast<difference_type>(__old_end - begin()); |
| 3148 | 3150 | difference_type __old_p = __p - begin(); |
| ... | ... | @@ -3156,7 +3158,7 @@ vector<bool, _Allocator>::insert(const_iterator __position, _InputIterator __fir |
| 3156 | 3158 | erase(__old_end, end()); |
| 3157 | 3159 | throw; |
| 3158 | 3160 | } |
| 3159 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3161 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 3160 | 3162 | } |
| 3161 | 3163 | __p = _VSTD::rotate(__p, __old_end, end()); |
| 3162 | 3164 | insert(__p, __v.begin(), __v.end()); |
| ... | ... | @@ -3411,4 +3413,4 @@ _LIBCPP_END_NAMESPACE_STD |
| 3411 | 3413 | |
| 3412 | 3414 | _LIBCPP_POP_MACROS |
| 3413 | 3415 | |
| 3414 | #endif // _LIBCPP_VECTOR | |
| 3416 | #endif // _LIBCPP_VECTOR |
lib/libcxx/include/version+36-22| ... | ... | @@ -56,7 +56,7 @@ __cpp_lib_constexpr_functional 201907L <functional> |
| 56 | 56 | __cpp_lib_constexpr_iterator 201811L <iterator> |
| 57 | 57 | __cpp_lib_constexpr_memory 201811L <memory> |
| 58 | 58 | __cpp_lib_constexpr_numeric 201911L <numeric> |
| 59 | __cpp_lib_constexpr_string 201907L <string> | |
| 59 | __cpp_lib_constexpr_string 201811L <string> | |
| 60 | 60 | __cpp_lib_constexpr_string_view 201811L <string_view> |
| 61 | 61 | __cpp_lib_constexpr_tuple 201811L <tuple> |
| 62 | 62 | __cpp_lib_constexpr_utility 201811L <utility> |
| ... | ... | @@ -72,6 +72,7 @@ __cpp_lib_exchange_function 201304L <utility> |
| 72 | 72 | __cpp_lib_execution 201902L <execution> |
| 73 | 73 | 201603L // C++17 |
| 74 | 74 | __cpp_lib_filesystem 201703L <filesystem> |
| 75 | __cpp_lib_format 201907L <format> | |
| 75 | 76 | __cpp_lib_gcd_lcm 201606L <numeric> |
| 76 | 77 | __cpp_lib_generic_associative_lookup 201304L <map> <set> |
| 77 | 78 | __cpp_lib_generic_unordered_lookup 201811L <unordered_map> <unordered_set> |
| ... | ... | @@ -149,6 +150,7 @@ __cpp_lib_three_way_comparison 201907L <compare> |
| 149 | 150 | __cpp_lib_to_address 201711L <memory> |
| 150 | 151 | __cpp_lib_to_array 201907L <array> |
| 151 | 152 | __cpp_lib_to_chars 201611L <utility> |
| 153 | __cpp_lib_to_underlying 202102L <utility> | |
| 152 | 154 | __cpp_lib_transformation_trait_aliases 201304L <type_traits> |
| 153 | 155 | __cpp_lib_transparent_operators 201510L <functional> <memory> |
| 154 | 156 | 201210L // C++14 |
| ... | ... | @@ -158,7 +160,7 @@ __cpp_lib_type_trait_variable_templates 201510L <type_traits> |
| 158 | 160 | __cpp_lib_uncaught_exceptions 201411L <exception> |
| 159 | 161 | __cpp_lib_unordered_map_try_emplace 201411L <unordered_map> |
| 160 | 162 | __cpp_lib_unwrap_ref 201811L <functional> |
| 161 | __cpp_lib_variant 201606L <variant> | |
| 163 | __cpp_lib_variant 202102L <variant> | |
| 162 | 164 | __cpp_lib_void_t 201411L <type_traits> |
| 163 | 165 | |
| 164 | 166 | */ |
| ... | ... | @@ -169,6 +171,8 @@ __cpp_lib_void_t 201411L <type_traits> |
| 169 | 171 | #pragma GCC system_header |
| 170 | 172 | #endif |
| 171 | 173 | |
| 174 | // clang-format off | |
| 175 | ||
| 172 | 176 | #if _LIBCPP_STD_VER > 11 |
| 173 | 177 | # define __cpp_lib_chrono_udls 201304L |
| 174 | 178 | # define __cpp_lib_complex_udls 201309L |
| ... | ... | @@ -184,7 +188,7 @@ __cpp_lib_void_t 201411L <type_traits> |
| 184 | 188 | # define __cpp_lib_quoted_string_io 201304L |
| 185 | 189 | # define __cpp_lib_result_of_sfinae 201210L |
| 186 | 190 | # define __cpp_lib_robust_nonmodifying_seq_ops 201304L |
| 187 | # if !defined(_LIBCPP_HAS_NO_THREADS) | |
| 191 | # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) | |
| 188 | 192 | # define __cpp_lib_shared_timed_mutex 201402L |
| 189 | 193 | # endif |
| 190 | 194 | # define __cpp_lib_string_udls 201304L |
| ... | ... | @@ -213,7 +217,9 @@ __cpp_lib_void_t 201411L <type_traits> |
| 213 | 217 | # define __cpp_lib_clamp 201603L |
| 214 | 218 | # define __cpp_lib_enable_shared_from_this 201603L |
| 215 | 219 | // # define __cpp_lib_execution 201603L |
| 216 | # define __cpp_lib_filesystem 201703L | |
| 220 | # if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) | |
| 221 | # define __cpp_lib_filesystem 201703L | |
| 222 | # endif | |
| 217 | 223 | # define __cpp_lib_gcd_lcm 201606L |
| 218 | 224 | // # define __cpp_lib_hardware_interference_size 201703L |
| 219 | 225 | # if defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS) |
| ... | ... | @@ -241,7 +247,7 @@ __cpp_lib_void_t 201411L <type_traits> |
| 241 | 247 | # define __cpp_lib_raw_memory_algorithms 201606L |
| 242 | 248 | # define __cpp_lib_sample 201603L |
| 243 | 249 | # define __cpp_lib_scoped_lock 201703L |
| 244 | # if !defined(_LIBCPP_HAS_NO_THREADS) | |
| 250 | # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) | |
| 245 | 251 | # define __cpp_lib_shared_mutex 201505L |
| 246 | 252 | # endif |
| 247 | 253 | # define __cpp_lib_shared_ptr_arrays 201611L |
| ... | ... | @@ -253,7 +259,7 @@ __cpp_lib_void_t 201411L <type_traits> |
| 253 | 259 | # define __cpp_lib_type_trait_variable_templates 201510L |
| 254 | 260 | # define __cpp_lib_uncaught_exceptions 201411L |
| 255 | 261 | # define __cpp_lib_unordered_map_try_emplace 201411L |
| 256 | # define __cpp_lib_variant 201606L | |
| 262 | # define __cpp_lib_variant 202102L | |
| 257 | 263 | # define __cpp_lib_void_t 201411L |
| 258 | 264 | #endif |
| 259 | 265 | |
| ... | ... | @@ -277,32 +283,32 @@ __cpp_lib_void_t 201411L <type_traits> |
| 277 | 283 | // # define __cpp_lib_atomic_shared_ptr 201711L |
| 278 | 284 | # endif |
| 279 | 285 | # if !defined(_LIBCPP_HAS_NO_THREADS) |
| 280 | // # define __cpp_lib_atomic_value_initialization 201911L | |
| 286 | # define __cpp_lib_atomic_value_initialization 201911L | |
| 281 | 287 | # endif |
| 282 | # if !defined(_LIBCPP_HAS_NO_THREADS) | |
| 288 | # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) | |
| 283 | 289 | # define __cpp_lib_atomic_wait 201907L |
| 284 | 290 | # endif |
| 285 | # if !defined(_LIBCPP_HAS_NO_THREADS) | |
| 291 | # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) | |
| 286 | 292 | # define __cpp_lib_barrier 201907L |
| 287 | 293 | # endif |
| 288 | // # define __cpp_lib_bind_front 201907L | |
| 294 | # define __cpp_lib_bind_front 201907L | |
| 289 | 295 | // # define __cpp_lib_bit_cast 201806L |
| 290 | 296 | // # define __cpp_lib_bitops 201907L |
| 291 | 297 | # define __cpp_lib_bounded_array_traits 201902L |
| 292 | # if !defined(_LIBCPP_NO_HAS_CHAR8_T) | |
| 298 | # if !defined(_LIBCPP_HAS_NO_CHAR8_T) | |
| 293 | 299 | # define __cpp_lib_char8_t 201811L |
| 294 | 300 | # endif |
| 295 | // # define __cpp_lib_concepts 202002L | |
| 296 | // # define __cpp_lib_constexpr_algorithms 201806L | |
| 301 | # define __cpp_lib_concepts 202002L | |
| 302 | # define __cpp_lib_constexpr_algorithms 201806L | |
| 297 | 303 | // # define __cpp_lib_constexpr_complex 201711L |
| 298 | 304 | # define __cpp_lib_constexpr_dynamic_alloc 201907L |
| 299 | 305 | # define __cpp_lib_constexpr_functional 201907L |
| 300 | // # define __cpp_lib_constexpr_iterator 201811L | |
| 301 | // # define __cpp_lib_constexpr_memory 201811L | |
| 306 | # define __cpp_lib_constexpr_iterator 201811L | |
| 307 | # define __cpp_lib_constexpr_memory 201811L | |
| 302 | 308 | # define __cpp_lib_constexpr_numeric 201911L |
| 303 | // # define __cpp_lib_constexpr_string 201907L | |
| 304 | // # define __cpp_lib_constexpr_string_view 201811L | |
| 305 | // # define __cpp_lib_constexpr_tuple 201811L | |
| 309 | # define __cpp_lib_constexpr_string 201811L | |
| 310 | # define __cpp_lib_constexpr_string_view 201811L | |
| 311 | # define __cpp_lib_constexpr_tuple 201811L | |
| 306 | 312 | # define __cpp_lib_constexpr_utility 201811L |
| 307 | 313 | // # define __cpp_lib_constexpr_vector 201907L |
| 308 | 314 | // # define __cpp_lib_coroutine 201902L |
| ... | ... | @@ -313,9 +319,14 @@ __cpp_lib_void_t 201411L <type_traits> |
| 313 | 319 | # define __cpp_lib_erase_if 202002L |
| 314 | 320 | # undef __cpp_lib_execution |
| 315 | 321 | // # define __cpp_lib_execution 201902L |
| 322 | # if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) | |
| 323 | // # define __cpp_lib_format 201907L | |
| 324 | # endif | |
| 316 | 325 | # define __cpp_lib_generic_unordered_lookup 201811L |
| 317 | 326 | # define __cpp_lib_int_pow2 202002L |
| 318 | // # define __cpp_lib_integer_comparison_functions 202002L | |
| 327 | # if !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 328 | # define __cpp_lib_integer_comparison_functions 202002L | |
| 329 | # endif | |
| 319 | 330 | # define __cpp_lib_interpolate 201902L |
| 320 | 331 | # if !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) |
| 321 | 332 | # define __cpp_lib_is_constant_evaluated 201811L |
| ... | ... | @@ -326,17 +337,17 @@ __cpp_lib_void_t 201411L <type_traits> |
| 326 | 337 | # if !defined(_LIBCPP_HAS_NO_THREADS) |
| 327 | 338 | // # define __cpp_lib_jthread 201911L |
| 328 | 339 | # endif |
| 329 | # if !defined(_LIBCPP_HAS_NO_THREADS) | |
| 340 | # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) | |
| 330 | 341 | # define __cpp_lib_latch 201907L |
| 331 | 342 | # endif |
| 332 | 343 | # define __cpp_lib_list_remove_return_type 201806L |
| 333 | # if defined(__cpp_concepts) && __cpp_concepts >= 201811L | |
| 344 | # if !defined(_LIBCPP_HAS_NO_CONCEPTS) | |
| 334 | 345 | # define __cpp_lib_math_constants 201907L |
| 335 | 346 | # endif |
| 336 | 347 | // # define __cpp_lib_polymorphic_allocator 201902L |
| 337 | 348 | // # define __cpp_lib_ranges 201811L |
| 338 | 349 | # define __cpp_lib_remove_cvref 201711L |
| 339 | # if !defined(_LIBCPP_HAS_NO_THREADS) | |
| 350 | # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) | |
| 340 | 351 | # define __cpp_lib_semaphore 201907L |
| 341 | 352 | # endif |
| 342 | 353 | # define __cpp_lib_shift 201806L |
| ... | ... | @@ -359,6 +370,9 @@ __cpp_lib_void_t 201411L <type_traits> |
| 359 | 370 | // # define __cpp_lib_stacktrace 202011L |
| 360 | 371 | // # define __cpp_lib_stdatomic_h 202011L |
| 361 | 372 | # define __cpp_lib_string_contains 202011L |
| 373 | # define __cpp_lib_to_underlying 202102L | |
| 362 | 374 | #endif |
| 363 | 375 | |
| 376 | // clang-format on | |
| 377 | ||
| 364 | 378 | #endif // _LIBCPP_VERSIONH |
lib/libcxx/include/wchar.h+2-2| ... | ... | @@ -177,6 +177,6 @@ size_t mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src, |
| 177 | 177 | size_t wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src, |
| 178 | 178 | size_t nwc, size_t len, mbstate_t *__restrict ps); |
| 179 | 179 | } // extern "C++" |
| 180 | #endif // __cplusplus && _LIBCPP_MSVCRT | |
| 180 | #endif // __cplusplus && _LIBCPP_MSVCRT | |
| 181 | 181 | |
| 182 | #endif // _LIBCPP_WCHAR_H | |
| 182 | #endif // _LIBCPP_WCHAR_H |
lib/libcxx/include/wctype.h+2-2| ... | ... | @@ -75,6 +75,6 @@ wctrans_t wctrans(const char* property); |
| 75 | 75 | #undef towctrans |
| 76 | 76 | #undef wctrans |
| 77 | 77 | |
| 78 | #endif // __cplusplus | |
| 78 | #endif // __cplusplus | |
| 79 | 79 | |
| 80 | #endif // _LIBCPP_WCTYPE_H | |
| 80 | #endif // _LIBCPP_WCTYPE_H |
lib/libcxx/src/any.cpp+3-3| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | #include "any" |
| 10 | 10 | |
| 11 | 11 | namespace std { |
| 12 | const char* bad_any_cast::what() const _NOEXCEPT { | |
| 12 | const char* bad_any_cast::what() const noexcept { | |
| 13 | 13 | return "bad any cast"; |
| 14 | 14 | } |
| 15 | 15 | } |
| ... | ... | @@ -24,10 +24,10 @@ _LIBCPP_BEGIN_NAMESPACE_LFTS |
| 24 | 24 | class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast |
| 25 | 25 | { |
| 26 | 26 | public: |
| 27 | virtual const char* what() const _NOEXCEPT; | |
| 27 | virtual const char* what() const noexcept; | |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | const char* bad_any_cast::what() const _NOEXCEPT { | |
| 30 | const char* bad_any_cast::what() const noexcept { | |
| 31 | 31 | return "bad any cast"; |
| 32 | 32 | } |
| 33 | 33 |
lib/libcxx/src/charconv.cpp+2-2| ... | ... | @@ -99,7 +99,7 @@ append8_no_zeros(char* buffer, T v) noexcept |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | 101 | char* |
| 102 | __u32toa(uint32_t value, char* buffer) _NOEXCEPT | |
| 102 | __u32toa(uint32_t value, char* buffer) noexcept | |
| 103 | 103 | { |
| 104 | 104 | if (value < 100000000) |
| 105 | 105 | { |
| ... | ... | @@ -120,7 +120,7 @@ __u32toa(uint32_t value, char* buffer) _NOEXCEPT |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | char* |
| 123 | __u64toa(uint64_t value, char* buffer) _NOEXCEPT | |
| 123 | __u64toa(uint64_t value, char* buffer) noexcept | |
| 124 | 124 | { |
| 125 | 125 | if (value < 100000000) |
| 126 | 126 | { |
lib/libcxx/src/chrono.cpp+26-5| ... | ... | @@ -6,9 +6,20 @@ |
| 6 | 6 | // |
| 7 | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | |
| 9 | #if defined(__MVS__) | |
| 10 | // As part of monotonic clock support on z/OS we need macro _LARGE_TIME_API | |
| 11 | // to be defined before any system header to include definition of struct timespec64. | |
| 12 | #define _LARGE_TIME_API | |
| 13 | #endif | |
| 14 | ||
| 9 | 15 | #include "chrono" |
| 10 | 16 | #include "cerrno" // errno |
| 11 | 17 | #include "system_error" // __throw_system_error |
| 18 | ||
| 19 | #if defined(__MVS__) | |
| 20 | #include <__support/ibm/gettod_zos.h> // gettimeofdayMonotonic | |
| 21 | #endif | |
| 22 | ||
| 12 | 23 | #include <time.h> // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW} |
| 13 | 24 | #include "include/apple_availability.h" |
| 14 | 25 | |
| ... | ... | @@ -20,7 +31,7 @@ |
| 20 | 31 | # include <sys/time.h> // for gettimeofday and timeval |
| 21 | 32 | #endif |
| 22 | 33 | |
| 23 | #if !defined(__APPLE__) && _POSIX_TIMERS > 0 | |
| 34 | #if !defined(__APPLE__) && defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 | |
| 24 | 35 | # define _LIBCPP_USE_CLOCK_GETTIME |
| 25 | 36 | #endif |
| 26 | 37 | |
| ... | ... | @@ -96,19 +107,19 @@ static system_clock::time_point __libcpp_system_clock_now() { |
| 96 | 107 | const bool system_clock::is_steady; |
| 97 | 108 | |
| 98 | 109 | system_clock::time_point |
| 99 | system_clock::now() _NOEXCEPT | |
| 110 | system_clock::now() noexcept | |
| 100 | 111 | { |
| 101 | 112 | return __libcpp_system_clock_now(); |
| 102 | 113 | } |
| 103 | 114 | |
| 104 | 115 | time_t |
| 105 | system_clock::to_time_t(const time_point& t) _NOEXCEPT | |
| 116 | system_clock::to_time_t(const time_point& t) noexcept | |
| 106 | 117 | { |
| 107 | 118 | return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); |
| 108 | 119 | } |
| 109 | 120 | |
| 110 | 121 | system_clock::time_point |
| 111 | system_clock::from_time_t(time_t t) _NOEXCEPT | |
| 122 | system_clock::from_time_t(time_t t) noexcept | |
| 112 | 123 | { |
| 113 | 124 | return system_clock::time_point(seconds(t)); |
| 114 | 125 | } |
| ... | ... | @@ -218,6 +229,16 @@ static steady_clock::time_point __libcpp_steady_clock_now() { |
| 218 | 229 | return steady_clock::time_point(steady_clock::duration(dur)); |
| 219 | 230 | } |
| 220 | 231 | |
| 232 | #elif defined(__MVS__) | |
| 233 | ||
| 234 | static steady_clock::time_point __libcpp_steady_clock_now() { | |
| 235 | struct timespec64 ts; | |
| 236 | if (0 != gettimeofdayMonotonic(&ts)) | |
| 237 | __throw_system_error(errno, "failed to obtain time of day"); | |
| 238 | ||
| 239 | return steady_clock::time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec)); | |
| 240 | } | |
| 241 | ||
| 221 | 242 | #elif defined(CLOCK_MONOTONIC) |
| 222 | 243 | |
| 223 | 244 | static steady_clock::time_point __libcpp_steady_clock_now() { |
| ... | ... | @@ -234,7 +255,7 @@ static steady_clock::time_point __libcpp_steady_clock_now() { |
| 234 | 255 | const bool steady_clock::is_steady; |
| 235 | 256 | |
| 236 | 257 | steady_clock::time_point |
| 237 | steady_clock::now() _NOEXCEPT | |
| 258 | steady_clock::now() noexcept | |
| 238 | 259 | { |
| 239 | 260 | return __libcpp_steady_clock_now(); |
| 240 | 261 | } |
lib/libcxx/src/condition_variable.cpp+4-4| ... | ... | @@ -24,19 +24,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD |
| 24 | 24 | // ~condition_variable is defined elsewhere. |
| 25 | 25 | |
| 26 | 26 | void |
| 27 | condition_variable::notify_one() _NOEXCEPT | |
| 27 | condition_variable::notify_one() noexcept | |
| 28 | 28 | { |
| 29 | 29 | __libcpp_condvar_signal(&__cv_); |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | void |
| 33 | condition_variable::notify_all() _NOEXCEPT | |
| 33 | condition_variable::notify_all() noexcept | |
| 34 | 34 | { |
| 35 | 35 | __libcpp_condvar_broadcast(&__cv_); |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | 38 | void |
| 39 | condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT | |
| 39 | condition_variable::wait(unique_lock<mutex>& lk) noexcept | |
| 40 | 40 | { |
| 41 | 41 | if (!lk.owns_lock()) |
| 42 | 42 | __throw_system_error(EPERM, |
| ... | ... | @@ -48,7 +48,7 @@ condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT |
| 48 | 48 | |
| 49 | 49 | void |
| 50 | 50 | condition_variable::__do_timed_wait(unique_lock<mutex>& lk, |
| 51 | chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) _NOEXCEPT | |
| 51 | chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) noexcept | |
| 52 | 52 | { |
| 53 | 53 | using namespace chrono; |
| 54 | 54 | if (!lk.owns_lock()) |
lib/libcxx/src/debug.cpp+1-1| ... | ... | @@ -438,7 +438,7 @@ __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const |
| 438 | 438 | __i_node* j = __find_iterator(__j); |
| 439 | 439 | __c_node* ci = i != nullptr ? i->__c_ : nullptr; |
| 440 | 440 | __c_node* cj = j != nullptr ? j->__c_ : nullptr; |
| 441 | return ci != nullptr && ci == cj; | |
| 441 | return ci == cj; | |
| 442 | 442 | } |
| 443 | 443 | |
| 444 | 444 | void |
lib/libcxx/src/experimental/memory_resource.cpp+8-13| ... | ... | @@ -40,7 +40,7 @@ class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp |
| 40 | 40 | _VSTD::__libcpp_deallocate(p, n, align); |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | bool do_is_equal(memory_resource const & other) const _NOEXCEPT override | |
| 43 | bool do_is_equal(memory_resource const & other) const noexcept override | |
| 44 | 44 | { return &other == this; } |
| 45 | 45 | |
| 46 | 46 | public: |
| ... | ... | @@ -60,7 +60,7 @@ protected: |
| 60 | 60 | __throw_bad_alloc(); |
| 61 | 61 | } |
| 62 | 62 | virtual void do_deallocate(void *, size_t, size_t) {} |
| 63 | virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT | |
| 63 | virtual bool do_is_equal(memory_resource const & __other) const noexcept | |
| 64 | 64 | { return &__other == this; } |
| 65 | 65 | }; |
| 66 | 66 | |
| ... | ... | @@ -76,28 +76,23 @@ union ResourceInitHelper { |
| 76 | 76 | ~ResourceInitHelper() {} |
| 77 | 77 | }; |
| 78 | 78 | |
| 79 | // When compiled in C++14 this initialization should be a constant expression. | |
| 80 | // Only in C++11 is "init_priority" needed to ensure initialization order. | |
| 81 | #if _LIBCPP_STD_VER > 11 | |
| 82 | _LIBCPP_SAFE_STATIC | |
| 83 | #endif | |
| 84 | ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; | |
| 79 | _LIBCPP_SAFE_STATIC ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; | |
| 85 | 80 | |
| 86 | 81 | } // end namespace |
| 87 | 82 | |
| 88 | 83 | |
| 89 | memory_resource * new_delete_resource() _NOEXCEPT { | |
| 84 | memory_resource * new_delete_resource() noexcept { | |
| 90 | 85 | return &res_init.resources.new_delete_res; |
| 91 | 86 | } |
| 92 | 87 | |
| 93 | memory_resource * null_memory_resource() _NOEXCEPT { | |
| 88 | memory_resource * null_memory_resource() noexcept { | |
| 94 | 89 | return &res_init.resources.null_res; |
| 95 | 90 | } |
| 96 | 91 | |
| 97 | 92 | // default_memory_resource() |
| 98 | 93 | |
| 99 | 94 | static memory_resource * |
| 100 | __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT | |
| 95 | __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept | |
| 101 | 96 | { |
| 102 | 97 | #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER |
| 103 | 98 | _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = |
| ... | ... | @@ -138,12 +133,12 @@ __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) |
| 138 | 133 | #endif |
| 139 | 134 | } |
| 140 | 135 | |
| 141 | memory_resource * get_default_resource() _NOEXCEPT | |
| 136 | memory_resource * get_default_resource() noexcept | |
| 142 | 137 | { |
| 143 | 138 | return __default_memory_resource(); |
| 144 | 139 | } |
| 145 | 140 | |
| 146 | memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT | |
| 141 | memory_resource * set_default_resource(memory_resource * __new_res) noexcept | |
| 147 | 142 | { |
| 148 | 143 | return __default_memory_resource(true, __new_res); |
| 149 | 144 | } |
lib/libcxx/src/filesystem/directory_iterator.cpp+6-4| ... | ... | @@ -124,7 +124,8 @@ public: |
| 124 | 124 | ec = detail::make_windows_error(GetLastError()); |
| 125 | 125 | const bool ignore_permission_denied = |
| 126 | 126 | bool(opts & directory_options::skip_permission_denied); |
| 127 | if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED) | |
| 127 | if (ignore_permission_denied && | |
| 128 | ec.value() == static_cast<int>(errc::permission_denied)) | |
| 128 | 129 | ec.clear(); |
| 129 | 130 | return; |
| 130 | 131 | } |
| ... | ... | @@ -272,7 +273,7 @@ directory_iterator& directory_iterator::__increment(error_code* ec) { |
| 272 | 273 | path root = move(__imp_->__root_); |
| 273 | 274 | __imp_.reset(); |
| 274 | 275 | if (m_ec) |
| 275 | err.report(m_ec, "at root \"%s\"", root); | |
| 276 | err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); | |
| 276 | 277 | } |
| 277 | 278 | return *this; |
| 278 | 279 | } |
| ... | ... | @@ -359,7 +360,7 @@ void recursive_directory_iterator::__advance(error_code* ec) { |
| 359 | 360 | if (m_ec) { |
| 360 | 361 | path root = move(stack.top().__root_); |
| 361 | 362 | __imp_.reset(); |
| 362 | err.report(m_ec, "at root \"%s\"", root); | |
| 363 | err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); | |
| 363 | 364 | } else { |
| 364 | 365 | __imp_.reset(); |
| 365 | 366 | } |
| ... | ... | @@ -404,7 +405,8 @@ bool recursive_directory_iterator::__try_recursion(error_code* ec) { |
| 404 | 405 | } else { |
| 405 | 406 | path at_ent = move(curr_it.__entry_.__p_); |
| 406 | 407 | __imp_.reset(); |
| 407 | err.report(m_ec, "attempting recursion into \"%s\"", at_ent); | |
| 408 | err.report(m_ec, "attempting recursion into " PATH_CSTR_FMT, | |
| 409 | at_ent.c_str()); | |
| 408 | 410 | } |
| 409 | 411 | } |
| 410 | 412 | return false; |
lib/libcxx/src/filesystem/filesystem_common.h+130-71| ... | ... | @@ -35,15 +35,17 @@ |
| 35 | 35 | #endif |
| 36 | 36 | #endif |
| 37 | 37 | |
| 38 | #if defined(__GNUC__) | |
| 38 | #if defined(__GNUC__) || defined(__clang__) | |
| 39 | 39 | #pragma GCC diagnostic push |
| 40 | 40 | #pragma GCC diagnostic ignored "-Wunused-function" |
| 41 | 41 | #endif |
| 42 | 42 | |
| 43 | 43 | #if defined(_LIBCPP_WIN32API) |
| 44 | 44 | #define PS(x) (L##x) |
| 45 | #define PATH_CSTR_FMT "\"%ls\"" | |
| 45 | 46 | #else |
| 46 | 47 | #define PS(x) (x) |
| 48 | #define PATH_CSTR_FMT "\"%s\"" | |
| 47 | 49 | #endif |
| 48 | 50 | |
| 49 | 51 | _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM |
| ... | ... | @@ -57,68 +59,47 @@ errc __win_err_to_errc(int err); |
| 57 | 59 | |
| 58 | 60 | namespace { |
| 59 | 61 | |
| 60 | static string format_string_imp(const char* msg, ...) { | |
| 61 | // we might need a second shot at this, so pre-emptivly make a copy | |
| 62 | struct GuardVAList { | |
| 63 | va_list& target; | |
| 64 | bool active = true; | |
| 65 | GuardVAList(va_list& tgt) : target(tgt), active(true) {} | |
| 66 | void clear() { | |
| 67 | if (active) | |
| 68 | va_end(target); | |
| 69 | active = false; | |
| 70 | } | |
| 71 | ~GuardVAList() { | |
| 72 | if (active) | |
| 73 | va_end(target); | |
| 74 | } | |
| 75 | }; | |
| 76 | va_list args; | |
| 77 | va_start(args, msg); | |
| 78 | GuardVAList args_guard(args); | |
| 79 | ||
| 80 | va_list args_cp; | |
| 81 | va_copy(args_cp, args); | |
| 82 | GuardVAList args_copy_guard(args_cp); | |
| 83 | ||
| 84 | std::string result; | |
| 85 | ||
| 86 | array<char, 256> local_buff; | |
| 87 | size_t size_with_null = local_buff.size(); | |
| 88 | auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp); | |
| 89 | ||
| 90 | args_copy_guard.clear(); | |
| 91 | ||
| 92 | // handle empty expansion | |
| 93 | if (ret == 0) | |
| 94 | return result; | |
| 95 | if (static_cast<size_t>(ret) < size_with_null) { | |
| 96 | result.assign(local_buff.data(), static_cast<size_t>(ret)); | |
| 97 | return result; | |
| 62 | static _LIBCPP_FORMAT_PRINTF(1, 0) string | |
| 63 | format_string_impl(const char* msg, va_list ap) { | |
| 64 | array<char, 256> buf; | |
| 65 | ||
| 66 | va_list apcopy; | |
| 67 | va_copy(apcopy, ap); | |
| 68 | int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); | |
| 69 | va_end(apcopy); | |
| 70 | ||
| 71 | string result; | |
| 72 | if (static_cast<size_t>(ret) < buf.size()) { | |
| 73 | result.assign(buf.data(), static_cast<size_t>(ret)); | |
| 74 | } else { | |
| 75 | // we did not provide a long enough buffer on our first attempt. The | |
| 76 | // return value is the number of bytes (excluding the null byte) that are | |
| 77 | // needed for formatting. | |
| 78 | size_t size_with_null = static_cast<size_t>(ret) + 1; | |
| 79 | result.__resize_default_init(size_with_null - 1); | |
| 80 | ret = ::vsnprintf(&result[0], size_with_null, msg, ap); | |
| 81 | _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); | |
| 98 | 82 | } |
| 99 | ||
| 100 | // we did not provide a long enough buffer on our first attempt. The | |
| 101 | // return value is the number of bytes (excluding the null byte) that are | |
| 102 | // needed for formatting. | |
| 103 | size_with_null = static_cast<size_t>(ret) + 1; | |
| 104 | result.__resize_default_init(size_with_null - 1); | |
| 105 | ret = ::vsnprintf(&result[0], size_with_null, msg, args); | |
| 106 | _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); | |
| 107 | ||
| 108 | 83 | return result; |
| 109 | 84 | } |
| 110 | 85 | |
| 111 | const path::value_type* unwrap(path::string_type const& s) { return s.c_str(); } | |
| 112 | const path::value_type* unwrap(path const& p) { return p.native().c_str(); } | |
| 113 | template <class Arg> | |
| 114 | Arg const& unwrap(Arg const& a) { | |
| 115 | static_assert(!is_class<Arg>::value, "cannot pass class here"); | |
| 116 | return a; | |
| 117 | } | |
| 118 | ||
| 119 | template <class... Args> | |
| 120 | string format_string(const char* fmt, Args const&... args) { | |
| 121 | return format_string_imp(fmt, unwrap(args)...); | |
| 86 | static _LIBCPP_FORMAT_PRINTF(1, 2) string | |
| 87 | format_string(const char* msg, ...) { | |
| 88 | string ret; | |
| 89 | va_list ap; | |
| 90 | va_start(ap, msg); | |
| 91 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 92 | try { | |
| 93 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 94 | ret = format_string_impl(msg, ap); | |
| 95 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 96 | } catch (...) { | |
| 97 | va_end(ap); | |
| 98 | throw; | |
| 99 | } | |
| 100 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 101 | va_end(ap); | |
| 102 | return ret; | |
| 122 | 103 | } |
| 123 | 104 | |
| 124 | 105 | error_code capture_errno() { |
| ... | ... | @@ -190,14 +171,14 @@ struct ErrorHandler { |
| 190 | 171 | _LIBCPP_UNREACHABLE(); |
| 191 | 172 | } |
| 192 | 173 | |
| 193 | template <class... Args> | |
| 194 | T report(const error_code& ec, const char* msg, Args const&... args) const { | |
| 174 | _LIBCPP_FORMAT_PRINTF(3, 0) | |
| 175 | void report_impl(const error_code& ec, const char* msg, va_list ap) const { | |
| 195 | 176 | if (ec_) { |
| 196 | 177 | *ec_ = ec; |
| 197 | return error_value<T>(); | |
| 178 | return; | |
| 198 | 179 | } |
| 199 | 180 | string what = |
| 200 | string("in ") + func_name_ + ": " + format_string(msg, args...); | |
| 181 | string("in ") + func_name_ + ": " + format_string_impl(msg, ap); | |
| 201 | 182 | switch (bool(p1_) + bool(p2_)) { |
| 202 | 183 | case 0: |
| 203 | 184 | __throw_filesystem_error(what, ec); |
| ... | ... | @@ -209,11 +190,44 @@ struct ErrorHandler { |
| 209 | 190 | _LIBCPP_UNREACHABLE(); |
| 210 | 191 | } |
| 211 | 192 | |
| 212 | T report(errc const& err) const { return report(make_error_code(err)); } | |
| 193 | _LIBCPP_FORMAT_PRINTF(3, 4) | |
| 194 | T report(const error_code& ec, const char* msg, ...) const { | |
| 195 | va_list ap; | |
| 196 | va_start(ap, msg); | |
| 197 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 198 | try { | |
| 199 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 200 | report_impl(ec, msg, ap); | |
| 201 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 202 | } catch (...) { | |
| 203 | va_end(ap); | |
| 204 | throw; | |
| 205 | } | |
| 206 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 207 | va_end(ap); | |
| 208 | return error_value<T>(); | |
| 209 | } | |
| 210 | ||
| 211 | T report(errc const& err) const { | |
| 212 | return report(make_error_code(err)); | |
| 213 | } | |
| 213 | 214 | |
| 214 | template <class... Args> | |
| 215 | T report(errc const& err, const char* msg, Args const&... args) const { | |
| 216 | return report(make_error_code(err), msg, args...); | |
| 215 | _LIBCPP_FORMAT_PRINTF(3, 4) | |
| 216 | T report(errc const& err, const char* msg, ...) const { | |
| 217 | va_list ap; | |
| 218 | va_start(ap, msg); | |
| 219 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 220 | try { | |
| 221 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 222 | report_impl(make_error_code(err), msg, ap); | |
| 223 | #ifndef _LIBCPP_NO_EXCEPTIONS | |
| 224 | } catch (...) { | |
| 225 | va_end(ap); | |
| 226 | throw; | |
| 227 | } | |
| 228 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 229 | va_end(ap); | |
| 230 | return error_value<T>(); | |
| 217 | 231 | } |
| 218 | 232 | |
| 219 | 233 | private: |
| ... | ... | @@ -224,9 +238,41 @@ private: |
| 224 | 238 | using chrono::duration; |
| 225 | 239 | using chrono::duration_cast; |
| 226 | 240 | |
| 241 | #if defined(_LIBCPP_WIN32API) | |
| 242 | // Various C runtime versions (UCRT, or the legacy msvcrt.dll used by | |
| 243 | // some mingw toolchains) provide different stat function implementations, | |
| 244 | // with a number of limitations with respect to what we want from the | |
| 245 | // stat function. Instead provide our own (in the anonymous detail namespace | |
| 246 | // in posix_compat.h) which does exactly what we want, along with our own | |
| 247 | // stat structure and flag macros. | |
| 248 | ||
| 249 | struct TimeSpec { | |
| 250 | int64_t tv_sec; | |
| 251 | int64_t tv_nsec; | |
| 252 | }; | |
| 253 | struct StatT { | |
| 254 | unsigned st_mode; | |
| 255 | TimeSpec st_atim; | |
| 256 | TimeSpec st_mtim; | |
| 257 | uint64_t st_dev; // FILE_ID_INFO::VolumeSerialNumber | |
| 258 | struct FileIdStruct { | |
| 259 | unsigned char id[16]; // FILE_ID_INFO::FileId | |
| 260 | bool operator==(const FileIdStruct &other) const { | |
| 261 | for (int i = 0; i < 16; i++) | |
| 262 | if (id[i] != other.id[i]) | |
| 263 | return false; | |
| 264 | return true; | |
| 265 | } | |
| 266 | } st_ino; | |
| 267 | uint32_t st_nlink; | |
| 268 | uintmax_t st_size; | |
| 269 | }; | |
| 270 | ||
| 271 | #else | |
| 227 | 272 | using TimeSpec = struct timespec; |
| 228 | 273 | using TimeVal = struct timeval; |
| 229 | 274 | using StatT = struct stat; |
| 275 | #endif | |
| 230 | 276 | |
| 231 | 277 | template <class FileTimeT, class TimeT, |
| 232 | 278 | bool IsFloat = is_floating_point<typename FileTimeT::rep>::value> |
| ... | ... | @@ -255,8 +301,7 @@ struct time_util_base { |
| 255 | 301 | .count(); |
| 256 | 302 | |
| 257 | 303 | private: |
| 258 | #if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) | |
| 259 | static constexpr fs_duration get_min_nsecs() { | |
| 304 | static _LIBCPP_CONSTEXPR_AFTER_CXX11 fs_duration get_min_nsecs() { | |
| 260 | 305 | return duration_cast<fs_duration>( |
| 261 | 306 | fs_nanoseconds(min_nsec_timespec) - |
| 262 | 307 | duration_cast<fs_nanoseconds>(fs_seconds(1))); |
| ... | ... | @@ -266,7 +311,7 @@ private: |
| 266 | 311 | FileTimeT::duration::min(), |
| 267 | 312 | "value doesn't roundtrip"); |
| 268 | 313 | |
| 269 | static constexpr bool check_range() { | |
| 314 | static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool check_range() { | |
| 270 | 315 | // This kinda sucks, but it's what happens when we don't have __int128_t. |
| 271 | 316 | if (sizeof(TimeT) == sizeof(rep)) { |
| 272 | 317 | typedef duration<long long, ratio<3600 * 24 * 365> > Years; |
| ... | ... | @@ -277,7 +322,6 @@ private: |
| 277 | 322 | min_seconds <= numeric_limits<TimeT>::min(); |
| 278 | 323 | } |
| 279 | 324 | static_assert(check_range(), "the representable range is unacceptable small"); |
| 280 | #endif | |
| 281 | 325 | }; |
| 282 | 326 | |
| 283 | 327 | template <class FileTimeT, class TimeT> |
| ... | ... | @@ -405,7 +449,11 @@ public: |
| 405 | 449 | } |
| 406 | 450 | }; |
| 407 | 451 | |
| 452 | #if defined(_LIBCPP_WIN32API) | |
| 453 | using fs_time = time_util<file_time_type, int64_t, TimeSpec>; | |
| 454 | #else | |
| 408 | 455 | using fs_time = time_util<file_time_type, time_t, TimeSpec>; |
| 456 | #endif | |
| 409 | 457 | |
| 410 | 458 | #if defined(__APPLE__) |
| 411 | 459 | inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } |
| ... | ... | @@ -419,11 +467,21 @@ inline TimeSpec extract_atime(StatT const& st) { |
| 419 | 467 | TimeSpec TS = {st.st_atime, 0}; |
| 420 | 468 | return TS; |
| 421 | 469 | } |
| 470 | #elif defined(_AIX) | |
| 471 | inline TimeSpec extract_mtime(StatT const& st) { | |
| 472 | TimeSpec TS = {st.st_mtime, st.st_mtime_n}; | |
| 473 | return TS; | |
| 474 | } | |
| 475 | inline TimeSpec extract_atime(StatT const& st) { | |
| 476 | TimeSpec TS = {st.st_atime, st.st_atime_n}; | |
| 477 | return TS; | |
| 478 | } | |
| 422 | 479 | #else |
| 423 | 480 | inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } |
| 424 | 481 | inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; } |
| 425 | 482 | #endif |
| 426 | 483 | |
| 484 | #if !defined(_LIBCPP_WIN32API) | |
| 427 | 485 | inline TimeVal make_timeval(TimeSpec const& ts) { |
| 428 | 486 | using namespace chrono; |
| 429 | 487 | auto Convert = [](long nsec) { |
| ... | ... | @@ -466,6 +524,7 @@ bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, |
| 466 | 524 | return posix_utimensat(p, TS, ec); |
| 467 | 525 | #endif |
| 468 | 526 | } |
| 527 | #endif /* !_LIBCPP_WIN32API */ | |
| 469 | 528 | |
| 470 | 529 | } // namespace |
| 471 | 530 | } // end namespace detail |
lib/libcxx/src/filesystem/operations.cpp+232-145| ... | ... | @@ -17,6 +17,8 @@ |
| 17 | 17 | |
| 18 | 18 | #include "filesystem_common.h" |
| 19 | 19 | |
| 20 | #include "posix_compat.h" | |
| 21 | ||
| 20 | 22 | #if defined(_LIBCPP_WIN32API) |
| 21 | 23 | # define WIN32_LEAN_AND_MEAN |
| 22 | 24 | # define NOMINMAX |
| ... | ... | @@ -40,7 +42,7 @@ |
| 40 | 42 | # define _LIBCPP_FILESYSTEM_USE_FSTREAM |
| 41 | 43 | #endif |
| 42 | 44 | |
| 43 | #if !defined(CLOCK_REALTIME) | |
| 45 | #if !defined(CLOCK_REALTIME) && !defined(_LIBCPP_WIN32API) | |
| 44 | 46 | # include <sys/time.h> // for gettimeofday and timeval |
| 45 | 47 | #endif |
| 46 | 48 | |
| ... | ... | @@ -62,6 +64,10 @@ bool isSeparator(path::value_type C) { |
| 62 | 64 | return false; |
| 63 | 65 | } |
| 64 | 66 | |
| 67 | bool isDriveLetter(path::value_type C) { | |
| 68 | return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z'); | |
| 69 | } | |
| 70 | ||
| 65 | 71 | namespace parser { |
| 66 | 72 | |
| 67 | 73 | using string_view_t = path::__string_view; |
| ... | ... | @@ -118,7 +124,13 @@ public: |
| 118 | 124 | |
| 119 | 125 | switch (State) { |
| 120 | 126 | case PS_BeforeBegin: { |
| 121 | PosPtr TkEnd = consumeSeparator(Start, End); | |
| 127 | PosPtr TkEnd = consumeRootName(Start, End); | |
| 128 | if (TkEnd) | |
| 129 | return makeState(PS_InRootName, Start, TkEnd); | |
| 130 | } | |
| 131 | _LIBCPP_FALLTHROUGH(); | |
| 132 | case PS_InRootName: { | |
| 133 | PosPtr TkEnd = consumeAllSeparators(Start, End); | |
| 122 | 134 | if (TkEnd) |
| 123 | 135 | return makeState(PS_InRootDir, Start, TkEnd); |
| 124 | 136 | else |
| ... | ... | @@ -128,7 +140,7 @@ public: |
| 128 | 140 | return makeState(PS_InFilenames, Start, consumeName(Start, End)); |
| 129 | 141 | |
| 130 | 142 | case PS_InFilenames: { |
| 131 | PosPtr SepEnd = consumeSeparator(Start, End); | |
| 143 | PosPtr SepEnd = consumeAllSeparators(Start, End); | |
| 132 | 144 | if (SepEnd != End) { |
| 133 | 145 | PosPtr TkEnd = consumeName(SepEnd, End); |
| 134 | 146 | if (TkEnd) |
| ... | ... | @@ -140,7 +152,6 @@ public: |
| 140 | 152 | case PS_InTrailingSep: |
| 141 | 153 | return makeState(PS_AtEnd); |
| 142 | 154 | |
| 143 | case PS_InRootName: | |
| 144 | 155 | case PS_AtEnd: |
| 145 | 156 | _LIBCPP_UNREACHABLE(); |
| 146 | 157 | } |
| ... | ... | @@ -155,12 +166,18 @@ public: |
| 155 | 166 | switch (State) { |
| 156 | 167 | case PS_AtEnd: { |
| 157 | 168 | // Try to consume a trailing separator or root directory first. |
| 158 | if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) { | |
| 169 | if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) { | |
| 159 | 170 | if (SepEnd == REnd) |
| 160 | 171 | return makeState(PS_InRootDir, Path.data(), RStart + 1); |
| 172 | PosPtr TkStart = consumeRootName(SepEnd, REnd); | |
| 173 | if (TkStart == REnd) | |
| 174 | return makeState(PS_InRootDir, RStart, RStart + 1); | |
| 161 | 175 | return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1); |
| 162 | 176 | } else { |
| 163 | PosPtr TkStart = consumeName(RStart, REnd); | |
| 177 | PosPtr TkStart = consumeRootName(RStart, REnd); | |
| 178 | if (TkStart == REnd) | |
| 179 | return makeState(PS_InRootName, TkStart + 1, RStart + 1); | |
| 180 | TkStart = consumeName(RStart, REnd); | |
| 164 | 181 | return makeState(PS_InFilenames, TkStart + 1, RStart + 1); |
| 165 | 182 | } |
| 166 | 183 | } |
| ... | ... | @@ -168,14 +185,20 @@ public: |
| 168 | 185 | return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, |
| 169 | 186 | RStart + 1); |
| 170 | 187 | case PS_InFilenames: { |
| 171 | PosPtr SepEnd = consumeSeparator(RStart, REnd); | |
| 188 | PosPtr SepEnd = consumeAllSeparators(RStart, REnd); | |
| 172 | 189 | if (SepEnd == REnd) |
| 173 | 190 | return makeState(PS_InRootDir, Path.data(), RStart + 1); |
| 174 | PosPtr TkEnd = consumeName(SepEnd, REnd); | |
| 175 | return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1); | |
| 191 | PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd); | |
| 192 | if (TkStart == REnd) { | |
| 193 | if (SepEnd) | |
| 194 | return makeState(PS_InRootDir, SepEnd + 1, RStart + 1); | |
| 195 | return makeState(PS_InRootName, TkStart + 1, RStart + 1); | |
| 196 | } | |
| 197 | TkStart = consumeName(SepEnd, REnd); | |
| 198 | return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1); | |
| 176 | 199 | } |
| 177 | 200 | case PS_InRootDir: |
| 178 | // return makeState(PS_InRootName, Path.data(), RStart + 1); | |
| 201 | return makeState(PS_InRootName, Path.data(), RStart + 1); | |
| 179 | 202 | case PS_InRootName: |
| 180 | 203 | case PS_BeforeBegin: |
| 181 | 204 | _LIBCPP_UNREACHABLE(); |
| ... | ... | @@ -281,8 +304,9 @@ private: |
| 281 | 304 | _LIBCPP_UNREACHABLE(); |
| 282 | 305 | } |
| 283 | 306 | |
| 284 | PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept { | |
| 285 | if (P == End || !isSeparator(*P)) | |
| 307 | // Consume all consecutive separators. | |
| 308 | PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept { | |
| 309 | if (P == nullptr || P == End || !isSeparator(*P)) | |
| 286 | 310 | return nullptr; |
| 287 | 311 | const int Inc = P < End ? 1 : -1; |
| 288 | 312 | P += Inc; |
| ... | ... | @@ -291,15 +315,72 @@ private: |
| 291 | 315 | return P; |
| 292 | 316 | } |
| 293 | 317 | |
| 318 | // Consume exactly N separators, or return nullptr. | |
| 319 | PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept { | |
| 320 | PosPtr Ret = consumeAllSeparators(P, End); | |
| 321 | if (Ret == nullptr) | |
| 322 | return nullptr; | |
| 323 | if (P < End) { | |
| 324 | if (Ret == P + N) | |
| 325 | return Ret; | |
| 326 | } else { | |
| 327 | if (Ret == P - N) | |
| 328 | return Ret; | |
| 329 | } | |
| 330 | return nullptr; | |
| 331 | } | |
| 332 | ||
| 294 | 333 | PosPtr consumeName(PosPtr P, PosPtr End) const noexcept { |
| 295 | if (P == End || isSeparator(*P)) | |
| 334 | PosPtr Start = P; | |
| 335 | if (P == nullptr || P == End || isSeparator(*P)) | |
| 296 | 336 | return nullptr; |
| 297 | 337 | const int Inc = P < End ? 1 : -1; |
| 298 | 338 | P += Inc; |
| 299 | 339 | while (P != End && !isSeparator(*P)) |
| 300 | 340 | P += Inc; |
| 341 | if (P == End && Inc < 0) { | |
| 342 | // Iterating backwards and consumed all the rest of the input. | |
| 343 | // Check if the start of the string would have been considered | |
| 344 | // a root name. | |
| 345 | PosPtr RootEnd = consumeRootName(End + 1, Start); | |
| 346 | if (RootEnd) | |
| 347 | return RootEnd - 1; | |
| 348 | } | |
| 301 | 349 | return P; |
| 302 | 350 | } |
| 351 | ||
| 352 | PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept { | |
| 353 | if (P == End) | |
| 354 | return nullptr; | |
| 355 | if (P < End) { | |
| 356 | if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':') | |
| 357 | return nullptr; | |
| 358 | return P + 2; | |
| 359 | } else { | |
| 360 | if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':') | |
| 361 | return nullptr; | |
| 362 | return P - 2; | |
| 363 | } | |
| 364 | } | |
| 365 | ||
| 366 | PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept { | |
| 367 | if (P == End) | |
| 368 | return nullptr; | |
| 369 | if (P < End) | |
| 370 | return consumeName(consumeNSeparators(P, End, 2), End); | |
| 371 | else | |
| 372 | return consumeNSeparators(consumeName(P, End), End, 2); | |
| 373 | } | |
| 374 | ||
| 375 | PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept { | |
| 376 | #if defined(_LIBCPP_WIN32API) | |
| 377 | if (PosPtr Ret = consumeDriveLetter(P, End)) | |
| 378 | return Ret; | |
| 379 | if (PosPtr Ret = consumeNetworkRoot(P, End)) | |
| 380 | return Ret; | |
| 381 | #endif | |
| 382 | return nullptr; | |
| 383 | } | |
| 303 | 384 | }; |
| 304 | 385 | |
| 305 | 386 | string_view_pair separate_filename(string_view_t const& s) { |
| ... | ... | @@ -331,6 +412,7 @@ errc __win_err_to_errc(int err) { |
| 331 | 412 | {ERROR_ACCESS_DENIED, errc::permission_denied}, |
| 332 | 413 | {ERROR_ALREADY_EXISTS, errc::file_exists}, |
| 333 | 414 | {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, |
| 415 | {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, | |
| 334 | 416 | {ERROR_BAD_UNIT, errc::no_such_device}, |
| 335 | 417 | {ERROR_BROKEN_PIPE, errc::broken_pipe}, |
| 336 | 418 | {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, |
| ... | ... | @@ -403,7 +485,7 @@ struct FileDescriptor { |
| 403 | 485 | static FileDescriptor create(const path* p, error_code& ec, Args... args) { |
| 404 | 486 | ec.clear(); |
| 405 | 487 | int fd; |
| 406 | if ((fd = ::open(p->c_str(), args...)) == -1) { | |
| 488 | if ((fd = detail::open(p->c_str(), args...)) == -1) { | |
| 407 | 489 | ec = capture_errno(); |
| 408 | 490 | return FileDescriptor{p}; |
| 409 | 491 | } |
| ... | ... | @@ -429,7 +511,7 @@ struct FileDescriptor { |
| 429 | 511 | |
| 430 | 512 | void close() noexcept { |
| 431 | 513 | if (fd != -1) |
| 432 | ::close(fd); | |
| 514 | detail::close(fd); | |
| 433 | 515 | fd = -1; |
| 434 | 516 | } |
| 435 | 517 | |
| ... | ... | @@ -453,10 +535,6 @@ perms posix_get_perms(const StatT& st) noexcept { |
| 453 | 535 | return static_cast<perms>(st.st_mode) & perms::mask; |
| 454 | 536 | } |
| 455 | 537 | |
| 456 | ::mode_t posix_convert_perms(perms prms) { | |
| 457 | return static_cast< ::mode_t>(prms & perms::mask); | |
| 458 | } | |
| 459 | ||
| 460 | 538 | file_status create_file_status(error_code& m_ec, path const& p, |
| 461 | 539 | const StatT& path_stat, error_code* ec) { |
| 462 | 540 | if (ec) |
| ... | ... | @@ -495,7 +573,7 @@ file_status create_file_status(error_code& m_ec, path const& p, |
| 495 | 573 | |
| 496 | 574 | file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { |
| 497 | 575 | error_code m_ec; |
| 498 | if (::stat(p.c_str(), &path_stat) == -1) | |
| 576 | if (detail::stat(p.c_str(), &path_stat) == -1) | |
| 499 | 577 | m_ec = detail::capture_errno(); |
| 500 | 578 | return create_file_status(m_ec, p, path_stat, ec); |
| 501 | 579 | } |
| ... | ... | @@ -507,7 +585,7 @@ file_status posix_stat(path const& p, error_code* ec) { |
| 507 | 585 | |
| 508 | 586 | file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { |
| 509 | 587 | error_code m_ec; |
| 510 | if (::lstat(p.c_str(), &path_stat) == -1) | |
| 588 | if (detail::lstat(p.c_str(), &path_stat) == -1) | |
| 511 | 589 | m_ec = detail::capture_errno(); |
| 512 | 590 | return create_file_status(m_ec, p, path_stat, ec); |
| 513 | 591 | } |
| ... | ... | @@ -519,7 +597,7 @@ file_status posix_lstat(path const& p, error_code* ec) { |
| 519 | 597 | |
| 520 | 598 | // http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html |
| 521 | 599 | bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { |
| 522 | if (::ftruncate(fd.fd, to_size) == -1) { | |
| 600 | if (detail::ftruncate(fd.fd, to_size) == -1) { | |
| 523 | 601 | ec = capture_errno(); |
| 524 | 602 | return true; |
| 525 | 603 | } |
| ... | ... | @@ -528,7 +606,7 @@ bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { |
| 528 | 606 | } |
| 529 | 607 | |
| 530 | 608 | bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { |
| 531 | if (::fchmod(fd.fd, st.st_mode) == -1) { | |
| 609 | if (detail::fchmod(fd.fd, st.st_mode) == -1) { | |
| 532 | 610 | ec = capture_errno(); |
| 533 | 611 | return true; |
| 534 | 612 | } |
| ... | ... | @@ -545,7 +623,7 @@ file_status FileDescriptor::refresh_status(error_code& ec) { |
| 545 | 623 | m_status = file_status{}; |
| 546 | 624 | m_stat = {}; |
| 547 | 625 | error_code m_ec; |
| 548 | if (::fstat(fd, &m_stat) == -1) | |
| 626 | if (detail::fstat(fd, &m_stat) == -1) | |
| 549 | 627 | m_ec = capture_errno(); |
| 550 | 628 | m_status = create_file_status(m_ec, name, m_stat, &ec); |
| 551 | 629 | return m_status; |
| ... | ... | @@ -565,7 +643,14 @@ const bool _FilesystemClock::is_steady; |
| 565 | 643 | |
| 566 | 644 | _FilesystemClock::time_point _FilesystemClock::now() noexcept { |
| 567 | 645 | typedef chrono::duration<rep> __secs; |
| 568 | #if defined(CLOCK_REALTIME) | |
| 646 | #if defined(_LIBCPP_WIN32API) | |
| 647 | typedef chrono::duration<rep, nano> __nsecs; | |
| 648 | FILETIME time; | |
| 649 | GetSystemTimeAsFileTime(&time); | |
| 650 | TimeSpec tp = detail::filetime_to_timespec(time); | |
| 651 | return time_point(__secs(tp.tv_sec) + | |
| 652 | chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); | |
| 653 | #elif defined(CLOCK_REALTIME) | |
| 569 | 654 | typedef chrono::duration<rep, nano> __nsecs; |
| 570 | 655 | struct timespec tp; |
| 571 | 656 | if (0 != clock_gettime(CLOCK_REALTIME, &tp)) |
| ... | ... | @@ -582,27 +667,20 @@ _FilesystemClock::time_point _FilesystemClock::now() noexcept { |
| 582 | 667 | |
| 583 | 668 | filesystem_error::~filesystem_error() {} |
| 584 | 669 | |
| 585 | #if defined(_LIBCPP_WIN32API) | |
| 586 | #define PS_FMT "%ls" | |
| 587 | #else | |
| 588 | #define PS_FMT "%s" | |
| 589 | #endif | |
| 590 | ||
| 591 | 670 | void filesystem_error::__create_what(int __num_paths) { |
| 592 | 671 | const char* derived_what = system_error::what(); |
| 593 | 672 | __storage_->__what_ = [&]() -> string { |
| 594 | const path::value_type* p1 = path1().native().empty() ? PS("\"\"") : path1().c_str(); | |
| 595 | const path::value_type* p2 = path2().native().empty() ? PS("\"\"") : path2().c_str(); | |
| 596 | 673 | switch (__num_paths) { |
| 597 | default: | |
| 674 | case 0: | |
| 598 | 675 | return detail::format_string("filesystem error: %s", derived_what); |
| 599 | 676 | case 1: |
| 600 | return detail::format_string("filesystem error: %s [" PS_FMT "]", derived_what, | |
| 601 | p1); | |
| 677 | return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "]", | |
| 678 | derived_what, path1().c_str()); | |
| 602 | 679 | case 2: |
| 603 | return detail::format_string("filesystem error: %s [" PS_FMT "] [" PS_FMT "]", | |
| 604 | derived_what, p1, p2); | |
| 680 | return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "] [" PATH_CSTR_FMT "]", | |
| 681 | derived_what, path1().c_str(), path2().c_str()); | |
| 605 | 682 | } |
| 683 | _LIBCPP_UNREACHABLE(); | |
| 606 | 684 | }(); |
| 607 | 685 | } |
| 608 | 686 | |
| ... | ... | @@ -627,20 +705,20 @@ path __canonical(path const& orig_p, error_code* ec) { |
| 627 | 705 | ErrorHandler<path> err("canonical", ec, &orig_p, &cwd); |
| 628 | 706 | |
| 629 | 707 | path p = __do_absolute(orig_p, &cwd, ec); |
| 630 | #if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112 | |
| 631 | std::unique_ptr<char, decltype(&::free)> | |
| 632 | hold(::realpath(p.c_str(), nullptr), &::free); | |
| 708 | #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API) | |
| 709 | std::unique_ptr<path::value_type, decltype(&::free)> | |
| 710 | hold(detail::realpath(p.c_str(), nullptr), &::free); | |
| 633 | 711 | if (hold.get() == nullptr) |
| 634 | 712 | return err.report(capture_errno()); |
| 635 | 713 | return {hold.get()}; |
| 636 | 714 | #else |
| 637 | 715 | #if defined(__MVS__) && !defined(PATH_MAX) |
| 638 | char buff[ _XOPEN_PATH_MAX + 1 ]; | |
| 716 | path::value_type buff[ _XOPEN_PATH_MAX + 1 ]; | |
| 639 | 717 | #else |
| 640 | char buff[PATH_MAX + 1]; | |
| 718 | path::value_type buff[PATH_MAX + 1]; | |
| 641 | 719 | #endif |
| 642 | char* ret; | |
| 643 | if ((ret = ::realpath(p.c_str(), buff)) == nullptr) | |
| 720 | path::value_type* ret; | |
| 721 | if ((ret = detail::realpath(p.c_str(), buff)) == nullptr) | |
| 644 | 722 | return err.report(capture_errno()); |
| 645 | 723 | return {ret}; |
| 646 | 724 | #endif |
| ... | ... | @@ -819,8 +897,8 @@ bool __copy_file(const path& from, const path& to, copy_options options, |
| 819 | 897 | ErrorHandler<bool> err("copy_file", ec, &to, &from); |
| 820 | 898 | |
| 821 | 899 | error_code m_ec; |
| 822 | FileDescriptor from_fd = | |
| 823 | FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK); | |
| 900 | FileDescriptor from_fd = FileDescriptor::create_with_status( | |
| 901 | &from, m_ec, O_RDONLY | O_NONBLOCK | O_BINARY); | |
| 824 | 902 | if (m_ec) |
| 825 | 903 | return err.report(m_ec); |
| 826 | 904 | |
| ... | ... | @@ -872,7 +950,7 @@ bool __copy_file(const path& from, const path& to, copy_options options, |
| 872 | 950 | |
| 873 | 951 | // Don't truncate right away. We may not be opening the file we originally |
| 874 | 952 | // looked at; we'll check this later. |
| 875 | int to_open_flags = O_WRONLY; | |
| 953 | int to_open_flags = O_WRONLY | O_BINARY; | |
| 876 | 954 | if (!to_exists) |
| 877 | 955 | to_open_flags |= O_CREAT; |
| 878 | 956 | FileDescriptor to_fd = FileDescriptor::create_with_status( |
| ... | ... | @@ -908,10 +986,13 @@ void __copy_symlink(const path& existing_symlink, const path& new_symlink, |
| 908 | 986 | if (ec && *ec) { |
| 909 | 987 | return; |
| 910 | 988 | } |
| 911 | // NOTE: proposal says you should detect if you should call | |
| 912 | // create_symlink or create_directory_symlink. I don't think this | |
| 913 | // is needed with POSIX | |
| 914 | __create_symlink(real_path, new_symlink, ec); | |
| 989 | #if defined(_LIBCPP_WIN32API) | |
| 990 | error_code local_ec; | |
| 991 | if (is_directory(real_path, local_ec)) | |
| 992 | __create_directory_symlink(real_path, new_symlink, ec); | |
| 993 | else | |
| 994 | #endif | |
| 995 | __create_symlink(real_path, new_symlink, ec); | |
| 915 | 996 | } |
| 916 | 997 | |
| 917 | 998 | bool __create_directories(const path& p, error_code* ec) { |
| ... | ... | @@ -932,31 +1013,34 @@ bool __create_directories(const path& p, error_code* ec) { |
| 932 | 1013 | if (not status_known(parent_st)) |
| 933 | 1014 | return err.report(m_ec); |
| 934 | 1015 | if (not exists(parent_st)) { |
| 1016 | if (parent == p) | |
| 1017 | return err.report(errc::invalid_argument); | |
| 935 | 1018 | __create_directories(parent, ec); |
| 936 | 1019 | if (ec && *ec) { |
| 937 | 1020 | return false; |
| 938 | 1021 | } |
| 939 | } | |
| 1022 | } else if (not is_directory(parent_st)) | |
| 1023 | return err.report(errc::not_a_directory); | |
| 940 | 1024 | } |
| 941 | return __create_directory(p, ec); | |
| 1025 | bool ret = __create_directory(p, &m_ec); | |
| 1026 | if (m_ec) | |
| 1027 | return err.report(m_ec); | |
| 1028 | return ret; | |
| 942 | 1029 | } |
| 943 | 1030 | |
| 944 | 1031 | bool __create_directory(const path& p, error_code* ec) { |
| 945 | 1032 | ErrorHandler<bool> err("create_directory", ec, &p); |
| 946 | 1033 | |
| 947 | if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) | |
| 1034 | if (detail::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) | |
| 948 | 1035 | return true; |
| 949 | 1036 | |
| 950 | if (errno == EEXIST) { | |
| 951 | error_code mec = capture_errno(); | |
| 952 | error_code ignored_ec; | |
| 953 | const file_status st = status(p, ignored_ec); | |
| 954 | if (!is_directory(st)) { | |
| 955 | err.report(mec); | |
| 956 | } | |
| 957 | } else { | |
| 958 | err.report(capture_errno()); | |
| 959 | } | |
| 1037 | if (errno != EEXIST) | |
| 1038 | return err.report(capture_errno()); | |
| 1039 | error_code mec = capture_errno(); | |
| 1040 | error_code ignored_ec; | |
| 1041 | const file_status st = status(p, ignored_ec); | |
| 1042 | if (!is_directory(st)) | |
| 1043 | return err.report(mec); | |
| 960 | 1044 | return false; |
| 961 | 1045 | } |
| 962 | 1046 | |
| ... | ... | @@ -965,65 +1049,80 @@ bool __create_directory(path const& p, path const& attributes, error_code* ec) { |
| 965 | 1049 | |
| 966 | 1050 | StatT attr_stat; |
| 967 | 1051 | error_code mec; |
| 968 | auto st = detail::posix_stat(attributes, attr_stat, &mec); | |
| 1052 | file_status st = detail::posix_stat(attributes, attr_stat, &mec); | |
| 969 | 1053 | if (!status_known(st)) |
| 970 | 1054 | return err.report(mec); |
| 971 | 1055 | if (!is_directory(st)) |
| 972 | 1056 | return err.report(errc::not_a_directory, |
| 973 | 1057 | "the specified attribute path is invalid"); |
| 974 | 1058 | |
| 975 | if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) | |
| 1059 | if (detail::mkdir(p.c_str(), attr_stat.st_mode) == 0) | |
| 976 | 1060 | return true; |
| 977 | 1061 | |
| 978 | if (errno == EEXIST) { | |
| 979 | error_code mec = capture_errno(); | |
| 980 | error_code ignored_ec; | |
| 981 | const file_status st = status(p, ignored_ec); | |
| 982 | if (!is_directory(st)) { | |
| 983 | err.report(mec); | |
| 984 | } | |
| 985 | } else { | |
| 986 | err.report(capture_errno()); | |
| 987 | } | |
| 1062 | if (errno != EEXIST) | |
| 1063 | return err.report(capture_errno()); | |
| 1064 | ||
| 1065 | mec = capture_errno(); | |
| 1066 | error_code ignored_ec; | |
| 1067 | st = status(p, ignored_ec); | |
| 1068 | if (!is_directory(st)) | |
| 1069 | return err.report(mec); | |
| 988 | 1070 | return false; |
| 989 | 1071 | } |
| 990 | 1072 | |
| 991 | 1073 | void __create_directory_symlink(path const& from, path const& to, |
| 992 | 1074 | error_code* ec) { |
| 993 | 1075 | ErrorHandler<void> err("create_directory_symlink", ec, &from, &to); |
| 994 | if (::symlink(from.c_str(), to.c_str()) != 0) | |
| 1076 | if (detail::symlink_dir(from.c_str(), to.c_str()) == -1) | |
| 995 | 1077 | return err.report(capture_errno()); |
| 996 | 1078 | } |
| 997 | 1079 | |
| 998 | 1080 | void __create_hard_link(const path& from, const path& to, error_code* ec) { |
| 999 | 1081 | ErrorHandler<void> err("create_hard_link", ec, &from, &to); |
| 1000 | if (::link(from.c_str(), to.c_str()) == -1) | |
| 1082 | if (detail::link(from.c_str(), to.c_str()) == -1) | |
| 1001 | 1083 | return err.report(capture_errno()); |
| 1002 | 1084 | } |
| 1003 | 1085 | |
| 1004 | 1086 | void __create_symlink(path const& from, path const& to, error_code* ec) { |
| 1005 | 1087 | ErrorHandler<void> err("create_symlink", ec, &from, &to); |
| 1006 | if (::symlink(from.c_str(), to.c_str()) == -1) | |
| 1088 | if (detail::symlink_file(from.c_str(), to.c_str()) == -1) | |
| 1007 | 1089 | return err.report(capture_errno()); |
| 1008 | 1090 | } |
| 1009 | 1091 | |
| 1010 | 1092 | path __current_path(error_code* ec) { |
| 1011 | 1093 | ErrorHandler<path> err("current_path", ec); |
| 1012 | 1094 | |
| 1095 | #if defined(_LIBCPP_WIN32API) || defined(__GLIBC__) || defined(__APPLE__) | |
| 1096 | // Common extension outside of POSIX getcwd() spec, without needing to | |
| 1097 | // preallocate a buffer. Also supported by a number of other POSIX libcs. | |
| 1098 | int size = 0; | |
| 1099 | path::value_type* ptr = nullptr; | |
| 1100 | typedef decltype(&::free) Deleter; | |
| 1101 | Deleter deleter = &::free; | |
| 1102 | #else | |
| 1013 | 1103 | auto size = ::pathconf(".", _PC_PATH_MAX); |
| 1014 | 1104 | _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); |
| 1015 | 1105 | |
| 1016 | auto buff = unique_ptr<char[]>(new char[size + 1]); | |
| 1017 | char* ret; | |
| 1018 | if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr) | |
| 1106 | auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]); | |
| 1107 | path::value_type* ptr = buff.get(); | |
| 1108 | ||
| 1109 | // Preallocated buffer, don't free the buffer in the second unique_ptr | |
| 1110 | // below. | |
| 1111 | struct Deleter { void operator()(void*) const {} }; | |
| 1112 | Deleter deleter; | |
| 1113 | #endif | |
| 1114 | ||
| 1115 | unique_ptr<path::value_type, Deleter> hold(detail::getcwd(ptr, size), | |
| 1116 | deleter); | |
| 1117 | if (hold.get() == nullptr) | |
| 1019 | 1118 | return err.report(capture_errno(), "call to getcwd failed"); |
| 1020 | 1119 | |
| 1021 | return {buff.get()}; | |
| 1120 | return {hold.get()}; | |
| 1022 | 1121 | } |
| 1023 | 1122 | |
| 1024 | 1123 | void __current_path(const path& p, error_code* ec) { |
| 1025 | 1124 | ErrorHandler<void> err("current_path", ec, &p); |
| 1026 | if (::chdir(p.c_str()) == -1) | |
| 1125 | if (detail::chdir(p.c_str()) == -1) | |
| 1027 | 1126 | err.report(capture_errno()); |
| 1028 | 1127 | } |
| 1029 | 1128 | |
| ... | ... | @@ -1119,6 +1218,17 @@ void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { |
| 1119 | 1218 | using detail::fs_time; |
| 1120 | 1219 | ErrorHandler<void> err("last_write_time", ec, &p); |
| 1121 | 1220 | |
| 1221 | #if defined(_LIBCPP_WIN32API) | |
| 1222 | TimeSpec ts; | |
| 1223 | if (!fs_time::convert_to_timespec(ts, new_time)) | |
| 1224 | return err.report(errc::value_too_large); | |
| 1225 | detail::WinHandle h(p.c_str(), FILE_WRITE_ATTRIBUTES, 0); | |
| 1226 | if (!h) | |
| 1227 | return err.report(detail::make_windows_error(GetLastError())); | |
| 1228 | FILETIME last_write = timespec_to_filetime(ts); | |
| 1229 | if (!SetFileTime(h, nullptr, nullptr, &last_write)) | |
| 1230 | return err.report(detail::make_windows_error(GetLastError())); | |
| 1231 | #else | |
| 1122 | 1232 | error_code m_ec; |
| 1123 | 1233 | array<TimeSpec, 2> tbuf; |
| 1124 | 1234 | #if !defined(_LIBCPP_USE_UTIMENSAT) |
| ... | ... | @@ -1140,6 +1250,7 @@ void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { |
| 1140 | 1250 | detail::set_file_times(p, tbuf, m_ec); |
| 1141 | 1251 | if (m_ec) |
| 1142 | 1252 | return err.report(m_ec); |
| 1253 | #endif | |
| 1143 | 1254 | } |
| 1144 | 1255 | |
| 1145 | 1256 | void __permissions(const path& p, perms prms, perm_options opts, |
| ... | ... | @@ -1171,11 +1282,11 @@ void __permissions(const path& p, perms prms, perm_options opts, |
| 1171 | 1282 | else if (remove_perms) |
| 1172 | 1283 | prms = st.permissions() & ~prms; |
| 1173 | 1284 | } |
| 1174 | const auto real_perms = detail::posix_convert_perms(prms); | |
| 1285 | const auto real_perms = static_cast<detail::ModeT>(prms & perms::mask); | |
| 1175 | 1286 | |
| 1176 | 1287 | #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) |
| 1177 | 1288 | const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; |
| 1178 | if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { | |
| 1289 | if (detail::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { | |
| 1179 | 1290 | return err.report(capture_errno()); |
| 1180 | 1291 | } |
| 1181 | 1292 | #else |
| ... | ... | @@ -1190,21 +1301,25 @@ void __permissions(const path& p, perms prms, perm_options opts, |
| 1190 | 1301 | path __read_symlink(const path& p, error_code* ec) { |
| 1191 | 1302 | ErrorHandler<path> err("read_symlink", ec, &p); |
| 1192 | 1303 | |
| 1193 | #ifdef PATH_MAX | |
| 1304 | #if defined(PATH_MAX) || defined(MAX_SYMLINK_SIZE) | |
| 1194 | 1305 | struct NullDeleter { void operator()(void*) const {} }; |
| 1306 | #ifdef MAX_SYMLINK_SIZE | |
| 1307 | const size_t size = MAX_SYMLINK_SIZE + 1; | |
| 1308 | #else | |
| 1195 | 1309 | const size_t size = PATH_MAX + 1; |
| 1196 | char stack_buff[size]; | |
| 1197 | auto buff = std::unique_ptr<char[], NullDeleter>(stack_buff); | |
| 1310 | #endif | |
| 1311 | path::value_type stack_buff[size]; | |
| 1312 | auto buff = std::unique_ptr<path::value_type[], NullDeleter>(stack_buff); | |
| 1198 | 1313 | #else |
| 1199 | 1314 | StatT sb; |
| 1200 | if (::lstat(p.c_str(), &sb) == -1) { | |
| 1315 | if (detail::lstat(p.c_str(), &sb) == -1) { | |
| 1201 | 1316 | return err.report(capture_errno()); |
| 1202 | 1317 | } |
| 1203 | 1318 | const size_t size = sb.st_size + 1; |
| 1204 | auto buff = unique_ptr<char[]>(new char[size]); | |
| 1319 | auto buff = unique_ptr<path::value_type[]>(new path::value_type[size]); | |
| 1205 | 1320 | #endif |
| 1206 | ::ssize_t ret; | |
| 1207 | if ((ret = ::readlink(p.c_str(), buff.get(), size)) == -1) | |
| 1321 | detail::SSizeT ret; | |
| 1322 | if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1) | |
| 1208 | 1323 | return err.report(capture_errno()); |
| 1209 | 1324 | _LIBCPP_ASSERT(ret > 0, "TODO"); |
| 1210 | 1325 | if (static_cast<size_t>(ret) >= size) |
| ... | ... | @@ -1215,7 +1330,7 @@ path __read_symlink(const path& p, error_code* ec) { |
| 1215 | 1330 | |
| 1216 | 1331 | bool __remove(const path& p, error_code* ec) { |
| 1217 | 1332 | ErrorHandler<bool> err("remove", ec, &p); |
| 1218 | if (::remove(p.c_str()) == -1) { | |
| 1333 | if (detail::remove(p.c_str()) == -1) { | |
| 1219 | 1334 | if (errno != ENOENT) |
| 1220 | 1335 | err.report(capture_errno()); |
| 1221 | 1336 | return false; |
| ... | ... | @@ -1264,21 +1379,21 @@ uintmax_t __remove_all(const path& p, error_code* ec) { |
| 1264 | 1379 | |
| 1265 | 1380 | void __rename(const path& from, const path& to, error_code* ec) { |
| 1266 | 1381 | ErrorHandler<void> err("rename", ec, &from, &to); |
| 1267 | if (::rename(from.c_str(), to.c_str()) == -1) | |
| 1382 | if (detail::rename(from.c_str(), to.c_str()) == -1) | |
| 1268 | 1383 | err.report(capture_errno()); |
| 1269 | 1384 | } |
| 1270 | 1385 | |
| 1271 | 1386 | void __resize_file(const path& p, uintmax_t size, error_code* ec) { |
| 1272 | 1387 | ErrorHandler<void> err("resize_file", ec, &p); |
| 1273 | if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) | |
| 1388 | if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) | |
| 1274 | 1389 | return err.report(capture_errno()); |
| 1275 | 1390 | } |
| 1276 | 1391 | |
| 1277 | 1392 | space_info __space(const path& p, error_code* ec) { |
| 1278 | 1393 | ErrorHandler<void> err("space", ec, &p); |
| 1279 | 1394 | space_info si; |
| 1280 | struct statvfs m_svfs = {}; | |
| 1281 | if (::statvfs(p.c_str(), &m_svfs) == -1) { | |
| 1395 | detail::StatVFS m_svfs = {}; | |
| 1396 | if (detail::statvfs(p.c_str(), &m_svfs) == -1) { | |
| 1282 | 1397 | err.report(capture_errno()); |
| 1283 | 1398 | si.capacity = si.free = si.available = static_cast<uintmax_t>(-1); |
| 1284 | 1399 | return si; |
| ... | ... | @@ -1306,6 +1421,19 @@ file_status __symlink_status(const path& p, error_code* ec) { |
| 1306 | 1421 | path __temp_directory_path(error_code* ec) { |
| 1307 | 1422 | ErrorHandler<path> err("temp_directory_path", ec); |
| 1308 | 1423 | |
| 1424 | #if defined(_LIBCPP_WIN32API) | |
| 1425 | wchar_t buf[MAX_PATH]; | |
| 1426 | DWORD retval = GetTempPathW(MAX_PATH, buf); | |
| 1427 | if (!retval) | |
| 1428 | return err.report(detail::make_windows_error(GetLastError())); | |
| 1429 | if (retval > MAX_PATH) | |
| 1430 | return err.report(errc::filename_too_long); | |
| 1431 | // GetTempPathW returns a path with a trailing slash, which we | |
| 1432 | // shouldn't include for consistency. | |
| 1433 | if (buf[retval-1] == L'\\') | |
| 1434 | buf[retval-1] = L'\0'; | |
| 1435 | path p(buf); | |
| 1436 | #else | |
| 1309 | 1437 | const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; |
| 1310 | 1438 | const char* ret = nullptr; |
| 1311 | 1439 | |
| ... | ... | @@ -1316,14 +1444,15 @@ path __temp_directory_path(error_code* ec) { |
| 1316 | 1444 | ret = "/tmp"; |
| 1317 | 1445 | |
| 1318 | 1446 | path p(ret); |
| 1447 | #endif | |
| 1319 | 1448 | error_code m_ec; |
| 1320 | 1449 | file_status st = detail::posix_stat(p, &m_ec); |
| 1321 | 1450 | if (!status_known(st)) |
| 1322 | return err.report(m_ec, "cannot access path \"" PS_FMT "\"", p); | |
| 1451 | return err.report(m_ec, "cannot access path " PATH_CSTR_FMT, p.c_str()); | |
| 1323 | 1452 | |
| 1324 | 1453 | if (!exists(st) || !is_directory(st)) |
| 1325 | return err.report(errc::not_a_directory, "path \"" PS_FMT "\" is not a directory", | |
| 1326 | p); | |
| 1454 | return err.report(errc::not_a_directory, | |
| 1455 | "path " PATH_CSTR_FMT " is not a directory", p.c_str()); | |
| 1327 | 1456 | |
| 1328 | 1457 | return p; |
| 1329 | 1458 | } |
| ... | ... | @@ -1586,6 +1715,7 @@ path path::lexically_normal() const { |
| 1586 | 1715 | if (NeedTrailingSep) |
| 1587 | 1716 | Result /= PS(""); |
| 1588 | 1717 | |
| 1718 | Result.make_preferred(); | |
| 1589 | 1719 | return Result; |
| 1590 | 1720 | } |
| 1591 | 1721 | |
| ... | ... | @@ -1806,7 +1936,6 @@ size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) { |
| 1806 | 1936 | // directory entry definitions |
| 1807 | 1937 | /////////////////////////////////////////////////////////////////////////////// |
| 1808 | 1938 | |
| 1809 | #ifndef _LIBCPP_WIN32API | |
| 1810 | 1939 | error_code directory_entry::__do_refresh() noexcept { |
| 1811 | 1940 | __data_.__reset(); |
| 1812 | 1941 | error_code failure_ec; |
| ... | ... | @@ -1860,47 +1989,5 @@ error_code directory_entry::__do_refresh() noexcept { |
| 1860 | 1989 | |
| 1861 | 1990 | return failure_ec; |
| 1862 | 1991 | } |
| 1863 | #else | |
| 1864 | error_code directory_entry::__do_refresh() noexcept { | |
| 1865 | __data_.__reset(); | |
| 1866 | error_code failure_ec; | |
| 1867 | ||
| 1868 | file_status st = _VSTD_FS::symlink_status(__p_, failure_ec); | |
| 1869 | if (!status_known(st)) { | |
| 1870 | __data_.__reset(); | |
| 1871 | return failure_ec; | |
| 1872 | } | |
| 1873 | ||
| 1874 | if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { | |
| 1875 | __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; | |
| 1876 | __data_.__type_ = st.type(); | |
| 1877 | __data_.__non_sym_perms_ = st.permissions(); | |
| 1878 | } else { // we have a symlink | |
| 1879 | __data_.__sym_perms_ = st.permissions(); | |
| 1880 | // Get the information about the linked entity. | |
| 1881 | // Ignore errors from stat, since we don't want errors regarding symlink | |
| 1882 | // resolution to be reported to the user. | |
| 1883 | error_code ignored_ec; | |
| 1884 | st = _VSTD_FS::status(__p_, ignored_ec); | |
| 1885 | ||
| 1886 | __data_.__type_ = st.type(); | |
| 1887 | __data_.__non_sym_perms_ = st.permissions(); | |
| 1888 | ||
| 1889 | // If we failed to resolve the link, then only partially populate the | |
| 1890 | // cache. | |
| 1891 | if (!status_known(st)) { | |
| 1892 | __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; | |
| 1893 | return error_code{}; | |
| 1894 | } | |
| 1895 | __data_.__cache_type_ = directory_entry::_RefreshSymlink; | |
| 1896 | } | |
| 1897 | ||
| 1898 | // FIXME: This is currently broken, and the implementation only a placeholder. | |
| 1899 | // We need to cache last_write_time, file_size, and hard_link_count here before | |
| 1900 | // the implementation actually works. | |
| 1901 | ||
| 1902 | return failure_ec; | |
| 1903 | } | |
| 1904 | #endif | |
| 1905 | 1992 | |
| 1906 | 1993 | _LIBCPP_END_NAMESPACE_FILESYSTEM |
lib/libcxx/src/filesystem/posix_compat.h created+521| ... | ... | @@ -0,0 +1,521 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | // | |
| 10 | // POSIX-like portability helper functions. | |
| 11 | // | |
| 12 | // These generally behave like the proper posix functions, with these | |
| 13 | // exceptions: | |
| 14 | // On Windows, they take paths in wchar_t* form, instead of char* form. | |
| 15 | // The symlink() function is split into two frontends, symlink_file() | |
| 16 | // and symlink_dir(). | |
| 17 | // | |
| 18 | // These are provided within an anonymous namespace within the detail | |
| 19 | // namespace - callers need to include this header and call them as | |
| 20 | // detail::function(), regardless of platform. | |
| 21 | // | |
| 22 | ||
| 23 | #ifndef POSIX_COMPAT_H | |
| 24 | #define POSIX_COMPAT_H | |
| 25 | ||
| 26 | #include "filesystem" | |
| 27 | ||
| 28 | #include "filesystem_common.h" | |
| 29 | ||
| 30 | #if defined(_LIBCPP_WIN32API) | |
| 31 | # define WIN32_LEAN_AND_MEAN | |
| 32 | # define NOMINMAX | |
| 33 | # include <windows.h> | |
| 34 | # include <io.h> | |
| 35 | # include <winioctl.h> | |
| 36 | #else | |
| 37 | # include <unistd.h> | |
| 38 | # include <sys/stat.h> | |
| 39 | # include <sys/statvfs.h> | |
| 40 | #endif | |
| 41 | #include <time.h> | |
| 42 | ||
| 43 | #if defined(_LIBCPP_WIN32API) | |
| 44 | // This struct isn't defined in the normal Windows SDK, but only in the | |
| 45 | // Windows Driver Kit. | |
| 46 | struct LIBCPP_REPARSE_DATA_BUFFER { | |
| 47 | unsigned long ReparseTag; | |
| 48 | unsigned short ReparseDataLength; | |
| 49 | unsigned short Reserved; | |
| 50 | union { | |
| 51 | struct { | |
| 52 | unsigned short SubstituteNameOffset; | |
| 53 | unsigned short SubstituteNameLength; | |
| 54 | unsigned short PrintNameOffset; | |
| 55 | unsigned short PrintNameLength; | |
| 56 | unsigned long Flags; | |
| 57 | wchar_t PathBuffer[1]; | |
| 58 | } SymbolicLinkReparseBuffer; | |
| 59 | struct { | |
| 60 | unsigned short SubstituteNameOffset; | |
| 61 | unsigned short SubstituteNameLength; | |
| 62 | unsigned short PrintNameOffset; | |
| 63 | unsigned short PrintNameLength; | |
| 64 | wchar_t PathBuffer[1]; | |
| 65 | } MountPointReparseBuffer; | |
| 66 | struct { | |
| 67 | unsigned char DataBuffer[1]; | |
| 68 | } GenericReparseBuffer; | |
| 69 | }; | |
| 70 | }; | |
| 71 | #endif | |
| 72 | ||
| 73 | _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM | |
| 74 | ||
| 75 | namespace detail { | |
| 76 | namespace { | |
| 77 | ||
| 78 | #if defined(_LIBCPP_WIN32API) | |
| 79 | ||
| 80 | // Various C runtime header sets provide more or less of these. As we | |
| 81 | // provide our own implementation, undef all potential defines from the | |
| 82 | // C runtime headers and provide a complete set of macros of our own. | |
| 83 | ||
| 84 | #undef _S_IFMT | |
| 85 | #undef _S_IFDIR | |
| 86 | #undef _S_IFCHR | |
| 87 | #undef _S_IFIFO | |
| 88 | #undef _S_IFREG | |
| 89 | #undef _S_IFBLK | |
| 90 | #undef _S_IFLNK | |
| 91 | #undef _S_IFSOCK | |
| 92 | ||
| 93 | #define _S_IFMT 0xF000 | |
| 94 | #define _S_IFDIR 0x4000 | |
| 95 | #define _S_IFCHR 0x2000 | |
| 96 | #define _S_IFIFO 0x1000 | |
| 97 | #define _S_IFREG 0x8000 | |
| 98 | #define _S_IFBLK 0x6000 | |
| 99 | #define _S_IFLNK 0xA000 | |
| 100 | #define _S_IFSOCK 0xC000 | |
| 101 | ||
| 102 | #undef S_ISDIR | |
| 103 | #undef S_ISFIFO | |
| 104 | #undef S_ISCHR | |
| 105 | #undef S_ISREG | |
| 106 | #undef S_ISLNK | |
| 107 | #undef S_ISBLK | |
| 108 | #undef S_ISSOCK | |
| 109 | ||
| 110 | #define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) | |
| 111 | #define S_ISCHR(m) (((m) & _S_IFMT) == _S_IFCHR) | |
| 112 | #define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) | |
| 113 | #define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) | |
| 114 | #define S_ISBLK(m) (((m) & _S_IFMT) == _S_IFBLK) | |
| 115 | #define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK) | |
| 116 | #define S_ISSOCK(m) (((m) & _S_IFMT) == _S_IFSOCK) | |
| 117 | ||
| 118 | #define O_NONBLOCK 0 | |
| 119 | ||
| 120 | ||
| 121 | // There were 369 years and 89 leap days from the Windows epoch | |
| 122 | // (1601) to the Unix epoch (1970). | |
| 123 | #define FILE_TIME_OFFSET_SECS (uint64_t(369 * 365 + 89) * (24 * 60 * 60)) | |
| 124 | ||
| 125 | TimeSpec filetime_to_timespec(LARGE_INTEGER li) { | |
| 126 | TimeSpec ret; | |
| 127 | ret.tv_sec = li.QuadPart / 10000000 - FILE_TIME_OFFSET_SECS; | |
| 128 | ret.tv_nsec = (li.QuadPart % 10000000) * 100; | |
| 129 | return ret; | |
| 130 | } | |
| 131 | ||
| 132 | TimeSpec filetime_to_timespec(FILETIME ft) { | |
| 133 | LARGE_INTEGER li; | |
| 134 | li.LowPart = ft.dwLowDateTime; | |
| 135 | li.HighPart = ft.dwHighDateTime; | |
| 136 | return filetime_to_timespec(li); | |
| 137 | } | |
| 138 | ||
| 139 | FILETIME timespec_to_filetime(TimeSpec ts) { | |
| 140 | LARGE_INTEGER li; | |
| 141 | li.QuadPart = | |
| 142 | ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000; | |
| 143 | FILETIME ft; | |
| 144 | ft.dwLowDateTime = li.LowPart; | |
| 145 | ft.dwHighDateTime = li.HighPart; | |
| 146 | return ft; | |
| 147 | } | |
| 148 | ||
| 149 | int set_errno(int e = GetLastError()) { | |
| 150 | errno = static_cast<int>(__win_err_to_errc(e)); | |
| 151 | return -1; | |
| 152 | } | |
| 153 | ||
| 154 | class WinHandle { | |
| 155 | public: | |
| 156 | WinHandle(const wchar_t *p, DWORD access, DWORD flags) { | |
| 157 | h = CreateFileW( | |
| 158 | p, access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | |
| 159 | nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | flags, nullptr); | |
| 160 | } | |
| 161 | ~WinHandle() { | |
| 162 | if (h != INVALID_HANDLE_VALUE) | |
| 163 | CloseHandle(h); | |
| 164 | } | |
| 165 | operator HANDLE() const { return h; } | |
| 166 | operator bool() const { return h != INVALID_HANDLE_VALUE; } | |
| 167 | ||
| 168 | private: | |
| 169 | HANDLE h; | |
| 170 | }; | |
| 171 | ||
| 172 | int stat_handle(HANDLE h, StatT *buf) { | |
| 173 | FILE_BASIC_INFO basic; | |
| 174 | if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) | |
| 175 | return set_errno(); | |
| 176 | memset(buf, 0, sizeof(*buf)); | |
| 177 | buf->st_mtim = filetime_to_timespec(basic.LastWriteTime); | |
| 178 | buf->st_atim = filetime_to_timespec(basic.LastAccessTime); | |
| 179 | buf->st_mode = 0555; // Read-only | |
| 180 | if (!(basic.FileAttributes & FILE_ATTRIBUTE_READONLY)) | |
| 181 | buf->st_mode |= 0222; // Write | |
| 182 | if (basic.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | |
| 183 | buf->st_mode |= _S_IFDIR; | |
| 184 | } else { | |
| 185 | buf->st_mode |= _S_IFREG; | |
| 186 | } | |
| 187 | if (basic.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { | |
| 188 | FILE_ATTRIBUTE_TAG_INFO tag; | |
| 189 | if (!GetFileInformationByHandleEx(h, FileAttributeTagInfo, &tag, | |
| 190 | sizeof(tag))) | |
| 191 | return set_errno(); | |
| 192 | if (tag.ReparseTag == IO_REPARSE_TAG_SYMLINK) | |
| 193 | buf->st_mode = (buf->st_mode & ~_S_IFMT) | _S_IFLNK; | |
| 194 | } | |
| 195 | FILE_STANDARD_INFO standard; | |
| 196 | if (!GetFileInformationByHandleEx(h, FileStandardInfo, &standard, | |
| 197 | sizeof(standard))) | |
| 198 | return set_errno(); | |
| 199 | buf->st_nlink = standard.NumberOfLinks; | |
| 200 | buf->st_size = standard.EndOfFile.QuadPart; | |
| 201 | BY_HANDLE_FILE_INFORMATION info; | |
| 202 | if (!GetFileInformationByHandle(h, &info)) | |
| 203 | return set_errno(); | |
| 204 | buf->st_dev = info.dwVolumeSerialNumber; | |
| 205 | memcpy(&buf->st_ino.id[0], &info.nFileIndexHigh, 4); | |
| 206 | memcpy(&buf->st_ino.id[4], &info.nFileIndexLow, 4); | |
| 207 | return 0; | |
| 208 | } | |
| 209 | ||
| 210 | int stat_file(const wchar_t *path, StatT *buf, DWORD flags) { | |
| 211 | WinHandle h(path, FILE_READ_ATTRIBUTES, flags); | |
| 212 | if (!h) | |
| 213 | return set_errno(); | |
| 214 | int ret = stat_handle(h, buf); | |
| 215 | return ret; | |
| 216 | } | |
| 217 | ||
| 218 | int stat(const wchar_t *path, StatT *buf) { return stat_file(path, buf, 0); } | |
| 219 | ||
| 220 | int lstat(const wchar_t *path, StatT *buf) { | |
| 221 | return stat_file(path, buf, FILE_FLAG_OPEN_REPARSE_POINT); | |
| 222 | } | |
| 223 | ||
| 224 | int fstat(int fd, StatT *buf) { | |
| 225 | HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); | |
| 226 | return stat_handle(h, buf); | |
| 227 | } | |
| 228 | ||
| 229 | int mkdir(const wchar_t *path, int permissions) { | |
| 230 | (void)permissions; | |
| 231 | return _wmkdir(path); | |
| 232 | } | |
| 233 | ||
| 234 | int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, | |
| 235 | bool is_dir) { | |
| 236 | path dest(oldname); | |
| 237 | dest.make_preferred(); | |
| 238 | oldname = dest.c_str(); | |
| 239 | DWORD flags = is_dir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; | |
| 240 | if (CreateSymbolicLinkW(newname, oldname, | |
| 241 | flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) | |
| 242 | return 0; | |
| 243 | int e = GetLastError(); | |
| 244 | if (e != ERROR_INVALID_PARAMETER) | |
| 245 | return set_errno(e); | |
| 246 | if (CreateSymbolicLinkW(newname, oldname, flags)) | |
| 247 | return 0; | |
| 248 | return set_errno(); | |
| 249 | } | |
| 250 | ||
| 251 | int symlink_file(const wchar_t *oldname, const wchar_t *newname) { | |
| 252 | return symlink_file_dir(oldname, newname, false); | |
| 253 | } | |
| 254 | ||
| 255 | int symlink_dir(const wchar_t *oldname, const wchar_t *newname) { | |
| 256 | return symlink_file_dir(oldname, newname, true); | |
| 257 | } | |
| 258 | ||
| 259 | int link(const wchar_t *oldname, const wchar_t *newname) { | |
| 260 | if (CreateHardLinkW(newname, oldname, nullptr)) | |
| 261 | return 0; | |
| 262 | return set_errno(); | |
| 263 | } | |
| 264 | ||
| 265 | int remove(const wchar_t *path) { | |
| 266 | detail::WinHandle h(path, DELETE, FILE_FLAG_OPEN_REPARSE_POINT); | |
| 267 | if (!h) | |
| 268 | return set_errno(); | |
| 269 | FILE_DISPOSITION_INFO info; | |
| 270 | info.DeleteFile = TRUE; | |
| 271 | if (!SetFileInformationByHandle(h, FileDispositionInfo, &info, sizeof(info))) | |
| 272 | return set_errno(); | |
| 273 | return 0; | |
| 274 | } | |
| 275 | ||
| 276 | int truncate_handle(HANDLE h, off_t length) { | |
| 277 | LARGE_INTEGER size_param; | |
| 278 | size_param.QuadPart = length; | |
| 279 | if (!SetFilePointerEx(h, size_param, 0, FILE_BEGIN)) | |
| 280 | return set_errno(); | |
| 281 | if (!SetEndOfFile(h)) | |
| 282 | return set_errno(); | |
| 283 | return 0; | |
| 284 | } | |
| 285 | ||
| 286 | int ftruncate(int fd, off_t length) { | |
| 287 | HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); | |
| 288 | return truncate_handle(h, length); | |
| 289 | } | |
| 290 | ||
| 291 | int truncate(const wchar_t *path, off_t length) { | |
| 292 | detail::WinHandle h(path, GENERIC_WRITE, 0); | |
| 293 | if (!h) | |
| 294 | return set_errno(); | |
| 295 | return truncate_handle(h, length); | |
| 296 | } | |
| 297 | ||
| 298 | int rename(const wchar_t *from, const wchar_t *to) { | |
| 299 | if (!(MoveFileExW(from, to, | |
| 300 | MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | | |
| 301 | MOVEFILE_WRITE_THROUGH))) | |
| 302 | return set_errno(); | |
| 303 | return 0; | |
| 304 | } | |
| 305 | ||
| 306 | template <class... Args> int open(const wchar_t *filename, Args... args) { | |
| 307 | return _wopen(filename, args...); | |
| 308 | } | |
| 309 | int close(int fd) { return _close(fd); } | |
| 310 | int chdir(const wchar_t *path) { return _wchdir(path); } | |
| 311 | ||
| 312 | struct StatVFS { | |
| 313 | uint64_t f_frsize; | |
| 314 | uint64_t f_blocks; | |
| 315 | uint64_t f_bfree; | |
| 316 | uint64_t f_bavail; | |
| 317 | }; | |
| 318 | ||
| 319 | int statvfs(const wchar_t *p, StatVFS *buf) { | |
| 320 | path dir = p; | |
| 321 | while (true) { | |
| 322 | error_code local_ec; | |
| 323 | const file_status st = status(dir, local_ec); | |
| 324 | if (!exists(st) || is_directory(st)) | |
| 325 | break; | |
| 326 | path parent = dir.parent_path(); | |
| 327 | if (parent == dir) { | |
| 328 | errno = ENOENT; | |
| 329 | return -1; | |
| 330 | } | |
| 331 | dir = parent; | |
| 332 | } | |
| 333 | ULARGE_INTEGER free_bytes_available_to_caller, total_number_of_bytes, | |
| 334 | total_number_of_free_bytes; | |
| 335 | if (!GetDiskFreeSpaceExW(dir.c_str(), &free_bytes_available_to_caller, | |
| 336 | &total_number_of_bytes, &total_number_of_free_bytes)) | |
| 337 | return set_errno(); | |
| 338 | buf->f_frsize = 1; | |
| 339 | buf->f_blocks = total_number_of_bytes.QuadPart; | |
| 340 | buf->f_bfree = total_number_of_free_bytes.QuadPart; | |
| 341 | buf->f_bavail = free_bytes_available_to_caller.QuadPart; | |
| 342 | return 0; | |
| 343 | } | |
| 344 | ||
| 345 | wchar_t *getcwd(wchar_t *buff, size_t size) { return _wgetcwd(buff, size); } | |
| 346 | ||
| 347 | wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) { | |
| 348 | // Only expected to be used with us allocating the buffer. | |
| 349 | _LIBCPP_ASSERT(resolved_name == nullptr, | |
| 350 | "Windows realpath() assumes a null resolved_name"); | |
| 351 | ||
| 352 | WinHandle h(path, FILE_READ_ATTRIBUTES, 0); | |
| 353 | if (!h) { | |
| 354 | set_errno(); | |
| 355 | return nullptr; | |
| 356 | } | |
| 357 | size_t buff_size = MAX_PATH + 10; | |
| 358 | std::unique_ptr<wchar_t, decltype(&::free)> buff( | |
| 359 | static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t))), &::free); | |
| 360 | DWORD retval = GetFinalPathNameByHandleW( | |
| 361 | h, buff.get(), buff_size, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); | |
| 362 | if (retval > buff_size) { | |
| 363 | buff_size = retval; | |
| 364 | buff.reset(static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t)))); | |
| 365 | retval = GetFinalPathNameByHandleW(h, buff.get(), buff_size, | |
| 366 | FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); | |
| 367 | } | |
| 368 | if (!retval) { | |
| 369 | set_errno(); | |
| 370 | return nullptr; | |
| 371 | } | |
| 372 | wchar_t *ptr = buff.get(); | |
| 373 | if (!wcsncmp(ptr, L"\\\\?\\", 4)) { | |
| 374 | if (ptr[5] == ':') { // \\?\X: -> X: | |
| 375 | memmove(&ptr[0], &ptr[4], (wcslen(&ptr[4]) + 1) * sizeof(wchar_t)); | |
| 376 | } else if (!wcsncmp(&ptr[4], L"UNC\\", 4)) { // \\?\UNC\server -> \\server | |
| 377 | wcscpy(&ptr[0], L"\\\\"); | |
| 378 | memmove(&ptr[2], &ptr[8], (wcslen(&ptr[8]) + 1) * sizeof(wchar_t)); | |
| 379 | } | |
| 380 | } | |
| 381 | return buff.release(); | |
| 382 | } | |
| 383 | ||
| 384 | #define AT_FDCWD -1 | |
| 385 | #define AT_SYMLINK_NOFOLLOW 1 | |
| 386 | using ModeT = int; | |
| 387 | ||
| 388 | int fchmod_handle(HANDLE h, int perms) { | |
| 389 | FILE_BASIC_INFO basic; | |
| 390 | if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) | |
| 391 | return set_errno(); | |
| 392 | DWORD orig_attributes = basic.FileAttributes; | |
| 393 | basic.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; | |
| 394 | if ((perms & 0222) == 0) | |
| 395 | basic.FileAttributes |= FILE_ATTRIBUTE_READONLY; | |
| 396 | if (basic.FileAttributes != orig_attributes && | |
| 397 | !SetFileInformationByHandle(h, FileBasicInfo, &basic, sizeof(basic))) | |
| 398 | return set_errno(); | |
| 399 | return 0; | |
| 400 | } | |
| 401 | ||
| 402 | int fchmodat(int fd, const wchar_t *path, int perms, int flag) { | |
| 403 | DWORD attributes = GetFileAttributesW(path); | |
| 404 | if (attributes == INVALID_FILE_ATTRIBUTES) | |
| 405 | return set_errno(); | |
| 406 | if (attributes & FILE_ATTRIBUTE_REPARSE_POINT && | |
| 407 | !(flag & AT_SYMLINK_NOFOLLOW)) { | |
| 408 | // If the file is a symlink, and we are supposed to operate on the target | |
| 409 | // of the symlink, we need to open a handle to it, without the | |
| 410 | // FILE_FLAG_OPEN_REPARSE_POINT flag, to open the destination of the | |
| 411 | // symlink, and operate on it via the handle. | |
| 412 | detail::WinHandle h(path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0); | |
| 413 | if (!h) | |
| 414 | return set_errno(); | |
| 415 | return fchmod_handle(h, perms); | |
| 416 | } else { | |
| 417 | // For a non-symlink, or if operating on the symlink itself instead of | |
| 418 | // its target, we can use SetFileAttributesW, saving a few calls. | |
| 419 | DWORD orig_attributes = attributes; | |
| 420 | attributes &= ~FILE_ATTRIBUTE_READONLY; | |
| 421 | if ((perms & 0222) == 0) | |
| 422 | attributes |= FILE_ATTRIBUTE_READONLY; | |
| 423 | if (attributes != orig_attributes && !SetFileAttributesW(path, attributes)) | |
| 424 | return set_errno(); | |
| 425 | } | |
| 426 | return 0; | |
| 427 | } | |
| 428 | ||
| 429 | int fchmod(int fd, int perms) { | |
| 430 | HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); | |
| 431 | return fchmod_handle(h, perms); | |
| 432 | } | |
| 433 | ||
| 434 | #define MAX_SYMLINK_SIZE MAXIMUM_REPARSE_DATA_BUFFER_SIZE | |
| 435 | using SSizeT = ::int64_t; | |
| 436 | ||
| 437 | SSizeT readlink(const wchar_t *path, wchar_t *ret_buf, size_t bufsize) { | |
| 438 | uint8_t buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; | |
| 439 | detail::WinHandle h(path, FILE_READ_ATTRIBUTES, FILE_FLAG_OPEN_REPARSE_POINT); | |
| 440 | if (!h) | |
| 441 | return set_errno(); | |
| 442 | DWORD out; | |
| 443 | if (!DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, nullptr, 0, buf, sizeof(buf), | |
| 444 | &out, 0)) | |
| 445 | return set_errno(); | |
| 446 | const auto *reparse = reinterpret_cast<LIBCPP_REPARSE_DATA_BUFFER *>(buf); | |
| 447 | size_t path_buf_offset = offsetof(LIBCPP_REPARSE_DATA_BUFFER, | |
| 448 | SymbolicLinkReparseBuffer.PathBuffer[0]); | |
| 449 | if (out < path_buf_offset) { | |
| 450 | errno = EINVAL; | |
| 451 | return -1; | |
| 452 | } | |
| 453 | if (reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) { | |
| 454 | errno = EINVAL; | |
| 455 | return -1; | |
| 456 | } | |
| 457 | const auto &symlink = reparse->SymbolicLinkReparseBuffer; | |
| 458 | unsigned short name_offset, name_length; | |
| 459 | if (symlink.PrintNameLength == 0) { | |
| 460 | name_offset = symlink.SubstituteNameOffset; | |
| 461 | name_length = symlink.SubstituteNameLength; | |
| 462 | } else { | |
| 463 | name_offset = symlink.PrintNameOffset; | |
| 464 | name_length = symlink.PrintNameLength; | |
| 465 | } | |
| 466 | // name_offset/length are expressed in bytes, not in wchar_t | |
| 467 | if (path_buf_offset + name_offset + name_length > out) { | |
| 468 | errno = EINVAL; | |
| 469 | return -1; | |
| 470 | } | |
| 471 | if (name_length / sizeof(wchar_t) > bufsize) { | |
| 472 | errno = ENOMEM; | |
| 473 | return -1; | |
| 474 | } | |
| 475 | memcpy(ret_buf, &symlink.PathBuffer[name_offset / sizeof(wchar_t)], | |
| 476 | name_length); | |
| 477 | return name_length / sizeof(wchar_t); | |
| 478 | } | |
| 479 | ||
| 480 | #else | |
| 481 | int symlink_file(const char *oldname, const char *newname) { | |
| 482 | return ::symlink(oldname, newname); | |
| 483 | } | |
| 484 | int symlink_dir(const char *oldname, const char *newname) { | |
| 485 | return ::symlink(oldname, newname); | |
| 486 | } | |
| 487 | using ::chdir; | |
| 488 | using ::close; | |
| 489 | using ::fchmod; | |
| 490 | #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) | |
| 491 | using ::fchmodat; | |
| 492 | #endif | |
| 493 | using ::fstat; | |
| 494 | using ::ftruncate; | |
| 495 | using ::getcwd; | |
| 496 | using ::link; | |
| 497 | using ::lstat; | |
| 498 | using ::mkdir; | |
| 499 | using ::open; | |
| 500 | using ::readlink; | |
| 501 | using ::realpath; | |
| 502 | using ::remove; | |
| 503 | using ::rename; | |
| 504 | using ::stat; | |
| 505 | using ::statvfs; | |
| 506 | using ::truncate; | |
| 507 | ||
| 508 | #define O_BINARY 0 | |
| 509 | ||
| 510 | using StatVFS = struct statvfs; | |
| 511 | using ModeT = ::mode_t; | |
| 512 | using SSizeT = ::ssize_t; | |
| 513 | ||
| 514 | #endif | |
| 515 | ||
| 516 | } // namespace | |
| 517 | } // end namespace detail | |
| 518 | ||
| 519 | _LIBCPP_END_NAMESPACE_FILESYSTEM | |
| 520 | ||
| 521 | #endif // POSIX_COMPAT_H |
lib/libcxx/src/format.cpp created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | //===------------------------- format.cpp ---------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #include "format" | |
| 10 | ||
| 11 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 12 | ||
| 13 | #if _LIBCPP_STD_VER > 17 | |
| 14 | ||
| 15 | format_error::~format_error() noexcept = default; | |
| 16 | ||
| 17 | #endif //_LIBCPP_STD_VER > 17 | |
| 18 | ||
| 19 | _LIBCPP_END_NAMESPACE_STD |
lib/libcxx/src/functional.cpp+2-2| ... | ... | @@ -11,12 +11,12 @@ |
| 11 | 11 | _LIBCPP_BEGIN_NAMESPACE_STD |
| 12 | 12 | |
| 13 | 13 | #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION |
| 14 | bad_function_call::~bad_function_call() _NOEXCEPT | |
| 14 | bad_function_call::~bad_function_call() noexcept | |
| 15 | 15 | { |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | const char* |
| 19 | bad_function_call::what() const _NOEXCEPT | |
| 19 | bad_function_call::what() const noexcept | |
| 20 | 20 | { |
| 21 | 21 | return "std::bad_function_call"; |
| 22 | 22 | } |
lib/libcxx/src/future.cpp+5-5| ... | ... | @@ -19,12 +19,12 @@ class _LIBCPP_HIDDEN __future_error_category |
| 19 | 19 | : public __do_message |
| 20 | 20 | { |
| 21 | 21 | public: |
| 22 | virtual const char* name() const _NOEXCEPT; | |
| 22 | virtual const char* name() const noexcept; | |
| 23 | 23 | virtual string message(int ev) const; |
| 24 | 24 | }; |
| 25 | 25 | |
| 26 | 26 | const char* |
| 27 | __future_error_category::name() const _NOEXCEPT | |
| 27 | __future_error_category::name() const noexcept | |
| 28 | 28 | { |
| 29 | 29 | return "future"; |
| 30 | 30 | } |
| ... | ... | @@ -65,7 +65,7 @@ __future_error_category::message(int ev) const |
| 65 | 65 | #endif |
| 66 | 66 | |
| 67 | 67 | const error_category& |
| 68 | future_category() _NOEXCEPT | |
| 68 | future_category() noexcept | |
| 69 | 69 | { |
| 70 | 70 | static __future_error_category __f; |
| 71 | 71 | return __f; |
| ... | ... | @@ -77,12 +77,12 @@ future_error::future_error(error_code __ec) |
| 77 | 77 | { |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | future_error::~future_error() _NOEXCEPT | |
| 80 | future_error::~future_error() noexcept | |
| 81 | 81 | { |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | void |
| 85 | __assoc_sub_state::__on_zero_shared() _NOEXCEPT | |
| 85 | __assoc_sub_state::__on_zero_shared() noexcept | |
| 86 | 86 | { |
| 87 | 87 | delete this; |
| 88 | 88 | } |
lib/libcxx/src/include/config_elast.h+4| ... | ... | @@ -35,8 +35,12 @@ |
| 35 | 35 | // No _LIBCPP_ELAST needed on Apple |
| 36 | 36 | #elif defined(__sun__) |
| 37 | 37 | #define _LIBCPP_ELAST ESTALE |
| 38 | #elif defined(__MVS__) | |
| 39 | #define _LIBCPP_ELAST 1160 | |
| 38 | 40 | #elif defined(_LIBCPP_MSVCRT_LIKE) |
| 39 | 41 | #define _LIBCPP_ELAST (_sys_nerr - 1) |
| 42 | #elif defined(_AIX) | |
| 43 | #define _LIBCPP_ELAST 127 | |
| 40 | 44 | #else |
| 41 | 45 | // Warn here so that the person doing the libcxx port has an easier time: |
| 42 | 46 | #warning ELAST for this platform not yet implemented |
lib/libcxx/src/include/refstring.h+4-4| ... | ... | @@ -55,7 +55,7 @@ inline char * data_from_rep(_Rep_base *rep) noexcept { |
| 55 | 55 | |
| 56 | 56 | #if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) |
| 57 | 57 | inline |
| 58 | const char* compute_gcc_empty_string_storage() _NOEXCEPT | |
| 58 | const char* compute_gcc_empty_string_storage() noexcept | |
| 59 | 59 | { |
| 60 | 60 | void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); |
| 61 | 61 | if (handle == nullptr) |
| ... | ... | @@ -68,7 +68,7 @@ const char* compute_gcc_empty_string_storage() _NOEXCEPT |
| 68 | 68 | |
| 69 | 69 | inline |
| 70 | 70 | const char* |
| 71 | get_gcc_empty_string_storage() _NOEXCEPT | |
| 71 | get_gcc_empty_string_storage() noexcept | |
| 72 | 72 | { |
| 73 | 73 | static const char* p = compute_gcc_empty_string_storage(); |
| 74 | 74 | return p; |
| ... | ... | @@ -92,7 +92,7 @@ __libcpp_refstring::__libcpp_refstring(const char* msg) { |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | inline |
| 95 | __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT | |
| 95 | __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) noexcept | |
| 96 | 96 | : __imp_(s.__imp_) |
| 97 | 97 | { |
| 98 | 98 | if (__uses_refcount()) |
| ... | ... | @@ -100,7 +100,7 @@ __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | inline |
| 103 | __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { | |
| 103 | __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) noexcept { | |
| 104 | 104 | bool adjust_old_count = __uses_refcount(); |
| 105 | 105 | struct _Rep_base *old_rep = rep_from_data(__imp_); |
| 106 | 106 | __imp_ = s.__imp_; |
lib/libcxx/src/include/sso_allocator.h created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | // -*- C++ -*- | |
| 2 | //===----------------------------------------------------------------------===// | |
| 3 | // | |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 5 | // See https://llvm.org/LICENSE.txt for license information. | |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef _LIBCPP_SSO_ALLOCATOR_H | |
| 11 | #define _LIBCPP_SSO_ALLOCATOR_H | |
| 12 | ||
| 13 | #include <__config> | |
| 14 | #include <memory> | |
| 15 | #include <new> | |
| 16 | #include <type_traits> | |
| 17 | ||
| 18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| 19 | #pragma GCC system_header | |
| 20 | #endif | |
| 21 | ||
| 22 | _LIBCPP_BEGIN_NAMESPACE_STD | |
| 23 | ||
| 24 | template <class _Tp, size_t _Np> class _LIBCPP_HIDDEN __sso_allocator; | |
| 25 | ||
| 26 | template <size_t _Np> | |
| 27 | class _LIBCPP_HIDDEN __sso_allocator<void, _Np> | |
| 28 | { | |
| 29 | public: | |
| 30 | typedef const void* const_pointer; | |
| 31 | typedef void value_type; | |
| 32 | }; | |
| 33 | ||
| 34 | template <class _Tp, size_t _Np> | |
| 35 | class _LIBCPP_HIDDEN __sso_allocator | |
| 36 | { | |
| 37 | typename aligned_storage<sizeof(_Tp) * _Np>::type buf_; | |
| 38 | bool __allocated_; | |
| 39 | public: | |
| 40 | typedef size_t size_type; | |
| 41 | typedef _Tp* pointer; | |
| 42 | typedef _Tp value_type; | |
| 43 | ||
| 44 | _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} | |
| 45 | _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} | |
| 46 | template <class _Up> _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() | |
| 47 | : __allocated_(false) {} | |
| 48 | private: | |
| 49 | __sso_allocator& operator=(const __sso_allocator&); | |
| 50 | public: | |
| 51 | _LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, typename __sso_allocator<void, _Np>::const_pointer = nullptr) | |
| 52 | { | |
| 53 | if (!__allocated_ && __n <= _Np) | |
| 54 | { | |
| 55 | __allocated_ = true; | |
| 56 | return (pointer)&buf_; | |
| 57 | } | |
| 58 | return allocator<_Tp>().allocate(__n); | |
| 59 | } | |
| 60 | _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) | |
| 61 | { | |
| 62 | if (__p == (pointer)&buf_) | |
| 63 | __allocated_ = false; | |
| 64 | else | |
| 65 | allocator<_Tp>().deallocate(__p, __n); | |
| 66 | } | |
| 67 | _LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);} | |
| 68 | ||
| 69 | _LIBCPP_INLINE_VISIBILITY | |
| 70 | bool operator==(const __sso_allocator& __a) const {return &buf_ == &__a.buf_;} | |
| 71 | _LIBCPP_INLINE_VISIBILITY | |
| 72 | bool operator!=(const __sso_allocator& __a) const {return &buf_ != &__a.buf_;} | |
| 73 | }; | |
| 74 | ||
| 75 | _LIBCPP_END_NAMESPACE_STD | |
| 76 | ||
| 77 | #endif // _LIBCPP_SSO_ALLOCATOR_H |
lib/libcxx/src/ios.cpp+7-7| ... | ... | @@ -27,12 +27,12 @@ class _LIBCPP_HIDDEN __iostream_category |
| 27 | 27 | : public __do_message |
| 28 | 28 | { |
| 29 | 29 | public: |
| 30 | virtual const char* name() const _NOEXCEPT; | |
| 30 | virtual const char* name() const noexcept; | |
| 31 | 31 | virtual string message(int ev) const; |
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | 34 | const char* |
| 35 | __iostream_category::name() const _NOEXCEPT | |
| 35 | __iostream_category::name() const noexcept | |
| 36 | 36 | { |
| 37 | 37 | return "iostream"; |
| 38 | 38 | } |
| ... | ... | @@ -43,14 +43,14 @@ __iostream_category::message(int ev) const |
| 43 | 43 | if (ev != static_cast<int>(io_errc::stream) |
| 44 | 44 | #ifdef _LIBCPP_ELAST |
| 45 | 45 | && ev <= _LIBCPP_ELAST |
| 46 | #endif // _LIBCPP_ELAST | |
| 46 | #endif // _LIBCPP_ELAST | |
| 47 | 47 | ) |
| 48 | 48 | return __do_message::message(ev); |
| 49 | 49 | return string("unspecified iostream_category error"); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | const error_category& |
| 53 | iostream_category() _NOEXCEPT | |
| 53 | iostream_category() noexcept | |
| 54 | 54 | { |
| 55 | 55 | static __iostream_category s; |
| 56 | 56 | return s; |
| ... | ... | @@ -387,7 +387,7 @@ ios_base::move(ios_base& rhs) |
| 387 | 387 | } |
| 388 | 388 | |
| 389 | 389 | void |
| 390 | ios_base::swap(ios_base& rhs) _NOEXCEPT | |
| 390 | ios_base::swap(ios_base& rhs) noexcept | |
| 391 | 391 | { |
| 392 | 392 | _VSTD::swap(__fmtflags_, rhs.__fmtflags_); |
| 393 | 393 | _VSTD::swap(__precision_, rhs.__precision_); |
| ... | ... | @@ -416,7 +416,7 @@ ios_base::__set_badbit_and_consider_rethrow() |
| 416 | 416 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 417 | 417 | if (__exceptions_ & badbit) |
| 418 | 418 | throw; |
| 419 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 419 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 420 | 420 | } |
| 421 | 421 | |
| 422 | 422 | void |
| ... | ... | @@ -426,7 +426,7 @@ ios_base::__set_failbit_and_consider_rethrow() |
| 426 | 426 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 427 | 427 | if (__exceptions_ & failbit) |
| 428 | 428 | throw; |
| 429 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 429 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 430 | 430 | } |
| 431 | 431 | |
| 432 | 432 | bool |
lib/libcxx/src/locale.cpp+85-82| ... | ... | @@ -27,7 +27,6 @@ |
| 27 | 27 | #define _CTYPE_DISABLE_MACROS |
| 28 | 28 | #endif |
| 29 | 29 | #include "cwctype" |
| 30 | #include "__sso_allocator" | |
| 31 | 30 | #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
| 32 | 31 | #include "__support/win32/locale_win32.h" |
| 33 | 32 | #elif !defined(__BIONIC__) && !defined(__NuttX__) |
| ... | ... | @@ -36,6 +35,7 @@ |
| 36 | 35 | #include <stdlib.h> |
| 37 | 36 | #include <stdio.h> |
| 38 | 37 | #include "include/atomic_support.h" |
| 38 | #include "include/sso_allocator.h" | |
| 39 | 39 | #include "__undef_macros" |
| 40 | 40 | |
| 41 | 41 | // On Linux, wint_t and wchar_t have different signed-ness, and this causes |
| ... | ... | @@ -206,7 +206,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 206 | 206 | install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); |
| 207 | 207 | install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); |
| 208 | 208 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 209 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 209 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 210 | 210 | install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u)); |
| 211 | 211 | install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u)); |
| 212 | 212 | #endif |
| ... | ... | @@ -240,7 +240,7 @@ locale::__imp::__imp(const string& name, size_t refs) |
| 240 | 240 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 241 | 241 | try |
| 242 | 242 | { |
| 243 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 243 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 244 | 244 | facets_ = locale::classic().__locale_->facets_; |
| 245 | 245 | for (unsigned i = 0; i < facets_.size(); ++i) |
| 246 | 246 | if (facets_[i]) |
| ... | ... | @@ -255,7 +255,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 255 | 255 | install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); |
| 256 | 256 | install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); |
| 257 | 257 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 258 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 258 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 259 | 259 | install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_)); |
| 260 | 260 | install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_)); |
| 261 | 261 | #endif |
| ... | ... | @@ -280,7 +280,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 280 | 280 | facets_[i]->__release_shared(); |
| 281 | 281 | throw; |
| 282 | 282 | } |
| 283 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 283 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 284 | 284 | } |
| 285 | 285 | |
| 286 | 286 | // NOTE avoid the `base class should be explicitly initialized in the |
| ... | ... | @@ -315,7 +315,7 @@ locale::__imp::__imp(const __imp& other, const string& name, locale::category c) |
| 315 | 315 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 316 | 316 | try |
| 317 | 317 | { |
| 318 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 318 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 319 | 319 | if (c & locale::collate) |
| 320 | 320 | { |
| 321 | 321 | install(new collate_byname<char>(name)); |
| ... | ... | @@ -331,7 +331,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 331 | 331 | install(new codecvt_byname<char16_t, char, mbstate_t>(name)); |
| 332 | 332 | install(new codecvt_byname<char32_t, char, mbstate_t>(name)); |
| 333 | 333 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 334 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 334 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 335 | 335 | install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name)); |
| 336 | 336 | install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name)); |
| 337 | 337 | #endif |
| ... | ... | @@ -369,7 +369,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 369 | 369 | facets_[i]->__release_shared(); |
| 370 | 370 | throw; |
| 371 | 371 | } |
| 372 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 372 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 373 | 373 | } |
| 374 | 374 | |
| 375 | 375 | template<class F> |
| ... | ... | @@ -392,7 +392,7 @@ locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) |
| 392 | 392 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 393 | 393 | try |
| 394 | 394 | { |
| 395 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 395 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 396 | 396 | if (c & locale::collate) |
| 397 | 397 | { |
| 398 | 398 | install_from<_VSTD::collate<char> >(one); |
| ... | ... | @@ -407,7 +407,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_PUSH |
| 407 | 407 | install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one); |
| 408 | 408 | install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one); |
| 409 | 409 | _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 410 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 410 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 411 | 411 | install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one); |
| 412 | 412 | install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one); |
| 413 | 413 | #endif |
| ... | ... | @@ -454,7 +454,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP |
| 454 | 454 | facets_[i]->__release_shared(); |
| 455 | 455 | throw; |
| 456 | 456 | } |
| 457 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 457 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | 460 | locale::__imp::__imp(const __imp& other, facet* f, long id) |
| ... | ... | @@ -532,13 +532,13 @@ locale::__global() |
| 532 | 532 | return g; |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | locale::locale() _NOEXCEPT | |
| 535 | locale::locale() noexcept | |
| 536 | 536 | : __locale_(__global().__locale_) |
| 537 | 537 | { |
| 538 | 538 | __locale_->__add_shared(); |
| 539 | 539 | } |
| 540 | 540 | |
| 541 | locale::locale(const locale& l) _NOEXCEPT | |
| 541 | locale::locale(const locale& l) noexcept | |
| 542 | 542 | : __locale_(l.__locale_) |
| 543 | 543 | { |
| 544 | 544 | __locale_->__add_shared(); |
| ... | ... | @@ -550,7 +550,7 @@ locale::~locale() |
| 550 | 550 | } |
| 551 | 551 | |
| 552 | 552 | const locale& |
| 553 | locale::operator=(const locale& other) _NOEXCEPT | |
| 553 | locale::operator=(const locale& other) noexcept | |
| 554 | 554 | { |
| 555 | 555 | other.__locale_->__add_shared(); |
| 556 | 556 | __locale_->__release_shared(); |
| ... | ... | @@ -643,7 +643,7 @@ locale::facet::~facet() |
| 643 | 643 | } |
| 644 | 644 | |
| 645 | 645 | void |
| 646 | locale::facet::__on_zero_shared() _NOEXCEPT | |
| 646 | locale::facet::__on_zero_shared() noexcept | |
| 647 | 647 | { |
| 648 | 648 | delete this; |
| 649 | 649 | } |
| ... | ... | @@ -1051,7 +1051,7 @@ extern "C" const int ** __ctype_toupper_loc(); |
| 1051 | 1051 | |
| 1052 | 1052 | #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE |
| 1053 | 1053 | const ctype<char>::mask* |
| 1054 | ctype<char>::classic_table() _NOEXCEPT | |
| 1054 | ctype<char>::classic_table() noexcept | |
| 1055 | 1055 | { |
| 1056 | 1056 | static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = { |
| 1057 | 1057 | cntrl, cntrl, |
| ... | ... | @@ -1131,7 +1131,7 @@ ctype<char>::classic_table() _NOEXCEPT |
| 1131 | 1131 | } |
| 1132 | 1132 | #else |
| 1133 | 1133 | const ctype<char>::mask* |
| 1134 | ctype<char>::classic_table() _NOEXCEPT | |
| 1134 | ctype<char>::classic_table() noexcept | |
| 1135 | 1135 | { |
| 1136 | 1136 | #if defined(__APPLE__) || defined(__FreeBSD__) |
| 1137 | 1137 | return _DefaultRuneLocale.__runetype; |
| ... | ... | @@ -1139,7 +1139,7 @@ ctype<char>::classic_table() _NOEXCEPT |
| 1139 | 1139 | return _C_ctype_tab_ + 1; |
| 1140 | 1140 | #elif defined(__GLIBC__) |
| 1141 | 1141 | return _LIBCPP_GET_C_LOCALE->__ctype_b; |
| 1142 | #elif __sun__ | |
| 1142 | #elif defined(__sun__) | |
| 1143 | 1143 | return __ctype_mask; |
| 1144 | 1144 | #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) |
| 1145 | 1145 | return __pctype_func(); |
| ... | ... | @@ -1163,38 +1163,38 @@ ctype<char>::classic_table() _NOEXCEPT |
| 1163 | 1163 | |
| 1164 | 1164 | #if defined(__GLIBC__) |
| 1165 | 1165 | const int* |
| 1166 | ctype<char>::__classic_lower_table() _NOEXCEPT | |
| 1166 | ctype<char>::__classic_lower_table() noexcept | |
| 1167 | 1167 | { |
| 1168 | 1168 | return _LIBCPP_GET_C_LOCALE->__ctype_tolower; |
| 1169 | 1169 | } |
| 1170 | 1170 | |
| 1171 | 1171 | const int* |
| 1172 | ctype<char>::__classic_upper_table() _NOEXCEPT | |
| 1172 | ctype<char>::__classic_upper_table() noexcept | |
| 1173 | 1173 | { |
| 1174 | 1174 | return _LIBCPP_GET_C_LOCALE->__ctype_toupper; |
| 1175 | 1175 | } |
| 1176 | 1176 | #elif defined(__NetBSD__) |
| 1177 | 1177 | const short* |
| 1178 | ctype<char>::__classic_lower_table() _NOEXCEPT | |
| 1178 | ctype<char>::__classic_lower_table() noexcept | |
| 1179 | 1179 | { |
| 1180 | 1180 | return _C_tolower_tab_ + 1; |
| 1181 | 1181 | } |
| 1182 | 1182 | |
| 1183 | 1183 | const short* |
| 1184 | ctype<char>::__classic_upper_table() _NOEXCEPT | |
| 1184 | ctype<char>::__classic_upper_table() noexcept | |
| 1185 | 1185 | { |
| 1186 | 1186 | return _C_toupper_tab_ + 1; |
| 1187 | 1187 | } |
| 1188 | 1188 | |
| 1189 | 1189 | #elif defined(__EMSCRIPTEN__) |
| 1190 | 1190 | const int* |
| 1191 | ctype<char>::__classic_lower_table() _NOEXCEPT | |
| 1191 | ctype<char>::__classic_lower_table() noexcept | |
| 1192 | 1192 | { |
| 1193 | 1193 | return *__ctype_tolower_loc(); |
| 1194 | 1194 | } |
| 1195 | 1195 | |
| 1196 | 1196 | const int* |
| 1197 | ctype<char>::__classic_upper_table() _NOEXCEPT | |
| 1197 | ctype<char>::__classic_upper_table() noexcept | |
| 1198 | 1198 | { |
| 1199 | 1199 | return *__ctype_toupper_loc(); |
| 1200 | 1200 | } |
| ... | ... | @@ -1492,13 +1492,13 @@ codecvt<char, char, mbstate_t>::do_unshift(state_type&, |
| 1492 | 1492 | } |
| 1493 | 1493 | |
| 1494 | 1494 | int |
| 1495 | codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT | |
| 1495 | codecvt<char, char, mbstate_t>::do_encoding() const noexcept | |
| 1496 | 1496 | { |
| 1497 | 1497 | return 1; |
| 1498 | 1498 | } |
| 1499 | 1499 | |
| 1500 | 1500 | bool |
| 1501 | codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT | |
| 1501 | codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept | |
| 1502 | 1502 | { |
| 1503 | 1503 | return true; |
| 1504 | 1504 | } |
| ... | ... | @@ -1511,7 +1511,7 @@ codecvt<char, char, mbstate_t>::do_length(state_type&, |
| 1511 | 1511 | } |
| 1512 | 1512 | |
| 1513 | 1513 | int |
| 1514 | codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT | |
| 1514 | codecvt<char, char, mbstate_t>::do_max_length() const noexcept | |
| 1515 | 1515 | { |
| 1516 | 1516 | return 1; |
| 1517 | 1517 | } |
| ... | ... | @@ -1682,7 +1682,7 @@ codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, |
| 1682 | 1682 | } |
| 1683 | 1683 | |
| 1684 | 1684 | int |
| 1685 | codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT | |
| 1685 | codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept | |
| 1686 | 1686 | { |
| 1687 | 1687 | if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) |
| 1688 | 1688 | return -1; |
| ... | ... | @@ -1694,7 +1694,7 @@ codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT |
| 1694 | 1694 | } |
| 1695 | 1695 | |
| 1696 | 1696 | bool |
| 1697 | codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT | |
| 1697 | codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept | |
| 1698 | 1698 | { |
| 1699 | 1699 | return false; |
| 1700 | 1700 | } |
| ... | ... | @@ -1726,7 +1726,7 @@ codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, |
| 1726 | 1726 | } |
| 1727 | 1727 | |
| 1728 | 1728 | int |
| 1729 | codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT | |
| 1729 | codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept | |
| 1730 | 1730 | { |
| 1731 | 1731 | return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l)); |
| 1732 | 1732 | } |
| ... | ... | @@ -3169,13 +3169,13 @@ codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, |
| 3169 | 3169 | } |
| 3170 | 3170 | |
| 3171 | 3171 | int |
| 3172 | codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT | |
| 3172 | codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept | |
| 3173 | 3173 | { |
| 3174 | 3174 | return 0; |
| 3175 | 3175 | } |
| 3176 | 3176 | |
| 3177 | 3177 | bool |
| 3178 | codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT | |
| 3178 | codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept | |
| 3179 | 3179 | { |
| 3180 | 3180 | return false; |
| 3181 | 3181 | } |
| ... | ... | @@ -3190,12 +3190,12 @@ codecvt<char16_t, char, mbstate_t>::do_length(state_type&, |
| 3190 | 3190 | } |
| 3191 | 3191 | |
| 3192 | 3192 | int |
| 3193 | codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT | |
| 3193 | codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept | |
| 3194 | 3194 | { |
| 3195 | 3195 | return 4; |
| 3196 | 3196 | } |
| 3197 | 3197 | |
| 3198 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 3198 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 3199 | 3199 | |
| 3200 | 3200 | // template <> class codecvt<char16_t, char8_t, mbstate_t> |
| 3201 | 3201 | |
| ... | ... | @@ -3248,13 +3248,13 @@ codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&, |
| 3248 | 3248 | } |
| 3249 | 3249 | |
| 3250 | 3250 | int |
| 3251 | codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const _NOEXCEPT | |
| 3251 | codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept | |
| 3252 | 3252 | { |
| 3253 | 3253 | return 0; |
| 3254 | 3254 | } |
| 3255 | 3255 | |
| 3256 | 3256 | bool |
| 3257 | codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const _NOEXCEPT | |
| 3257 | codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept | |
| 3258 | 3258 | { |
| 3259 | 3259 | return false; |
| 3260 | 3260 | } |
| ... | ... | @@ -3269,7 +3269,7 @@ codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&, |
| 3269 | 3269 | } |
| 3270 | 3270 | |
| 3271 | 3271 | int |
| 3272 | codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const _NOEXCEPT | |
| 3272 | codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept | |
| 3273 | 3273 | { |
| 3274 | 3274 | return 4; |
| 3275 | 3275 | } |
| ... | ... | @@ -3327,13 +3327,13 @@ codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, |
| 3327 | 3327 | } |
| 3328 | 3328 | |
| 3329 | 3329 | int |
| 3330 | codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT | |
| 3330 | codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept | |
| 3331 | 3331 | { |
| 3332 | 3332 | return 0; |
| 3333 | 3333 | } |
| 3334 | 3334 | |
| 3335 | 3335 | bool |
| 3336 | codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT | |
| 3336 | codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept | |
| 3337 | 3337 | { |
| 3338 | 3338 | return false; |
| 3339 | 3339 | } |
| ... | ... | @@ -3348,12 +3348,12 @@ codecvt<char32_t, char, mbstate_t>::do_length(state_type&, |
| 3348 | 3348 | } |
| 3349 | 3349 | |
| 3350 | 3350 | int |
| 3351 | codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT | |
| 3351 | codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept | |
| 3352 | 3352 | { |
| 3353 | 3353 | return 4; |
| 3354 | 3354 | } |
| 3355 | 3355 | |
| 3356 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 3356 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 3357 | 3357 | |
| 3358 | 3358 | // template <> class codecvt<char32_t, char8_t, mbstate_t> |
| 3359 | 3359 | |
| ... | ... | @@ -3406,13 +3406,13 @@ codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&, |
| 3406 | 3406 | } |
| 3407 | 3407 | |
| 3408 | 3408 | int |
| 3409 | codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const _NOEXCEPT | |
| 3409 | codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept | |
| 3410 | 3410 | { |
| 3411 | 3411 | return 0; |
| 3412 | 3412 | } |
| 3413 | 3413 | |
| 3414 | 3414 | bool |
| 3415 | codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const _NOEXCEPT | |
| 3415 | codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept | |
| 3416 | 3416 | { |
| 3417 | 3417 | return false; |
| 3418 | 3418 | } |
| ... | ... | @@ -3427,7 +3427,7 @@ codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&, |
| 3427 | 3427 | } |
| 3428 | 3428 | |
| 3429 | 3429 | int |
| 3430 | codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const _NOEXCEPT | |
| 3430 | codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept | |
| 3431 | 3431 | { |
| 3432 | 3432 | return 4; |
| 3433 | 3433 | } |
| ... | ... | @@ -3500,13 +3500,13 @@ __codecvt_utf8<wchar_t>::do_unshift(state_type&, |
| 3500 | 3500 | } |
| 3501 | 3501 | |
| 3502 | 3502 | int |
| 3503 | __codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT | |
| 3503 | __codecvt_utf8<wchar_t>::do_encoding() const noexcept | |
| 3504 | 3504 | { |
| 3505 | 3505 | return 0; |
| 3506 | 3506 | } |
| 3507 | 3507 | |
| 3508 | 3508 | bool |
| 3509 | __codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT | |
| 3509 | __codecvt_utf8<wchar_t>::do_always_noconv() const noexcept | |
| 3510 | 3510 | { |
| 3511 | 3511 | return false; |
| 3512 | 3512 | } |
| ... | ... | @@ -3521,7 +3521,7 @@ __codecvt_utf8<wchar_t>::do_length(state_type&, |
| 3521 | 3521 | } |
| 3522 | 3522 | |
| 3523 | 3523 | int |
| 3524 | __codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT | |
| 3524 | __codecvt_utf8<wchar_t>::do_max_length() const noexcept | |
| 3525 | 3525 | { |
| 3526 | 3526 | if (_Mode_ & consume_header) |
| 3527 | 3527 | return 7; |
| ... | ... | @@ -3575,13 +3575,13 @@ __codecvt_utf8<char16_t>::do_unshift(state_type&, |
| 3575 | 3575 | } |
| 3576 | 3576 | |
| 3577 | 3577 | int |
| 3578 | __codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT | |
| 3578 | __codecvt_utf8<char16_t>::do_encoding() const noexcept | |
| 3579 | 3579 | { |
| 3580 | 3580 | return 0; |
| 3581 | 3581 | } |
| 3582 | 3582 | |
| 3583 | 3583 | bool |
| 3584 | __codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT | |
| 3584 | __codecvt_utf8<char16_t>::do_always_noconv() const noexcept | |
| 3585 | 3585 | { |
| 3586 | 3586 | return false; |
| 3587 | 3587 | } |
| ... | ... | @@ -3596,7 +3596,7 @@ __codecvt_utf8<char16_t>::do_length(state_type&, |
| 3596 | 3596 | } |
| 3597 | 3597 | |
| 3598 | 3598 | int |
| 3599 | __codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT | |
| 3599 | __codecvt_utf8<char16_t>::do_max_length() const noexcept | |
| 3600 | 3600 | { |
| 3601 | 3601 | if (_Mode_ & consume_header) |
| 3602 | 3602 | return 6; |
| ... | ... | @@ -3650,13 +3650,13 @@ __codecvt_utf8<char32_t>::do_unshift(state_type&, |
| 3650 | 3650 | } |
| 3651 | 3651 | |
| 3652 | 3652 | int |
| 3653 | __codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT | |
| 3653 | __codecvt_utf8<char32_t>::do_encoding() const noexcept | |
| 3654 | 3654 | { |
| 3655 | 3655 | return 0; |
| 3656 | 3656 | } |
| 3657 | 3657 | |
| 3658 | 3658 | bool |
| 3659 | __codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT | |
| 3659 | __codecvt_utf8<char32_t>::do_always_noconv() const noexcept | |
| 3660 | 3660 | { |
| 3661 | 3661 | return false; |
| 3662 | 3662 | } |
| ... | ... | @@ -3671,7 +3671,7 @@ __codecvt_utf8<char32_t>::do_length(state_type&, |
| 3671 | 3671 | } |
| 3672 | 3672 | |
| 3673 | 3673 | int |
| 3674 | __codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT | |
| 3674 | __codecvt_utf8<char32_t>::do_max_length() const noexcept | |
| 3675 | 3675 | { |
| 3676 | 3676 | if (_Mode_ & consume_header) |
| 3677 | 3677 | return 7; |
| ... | ... | @@ -3725,13 +3725,13 @@ __codecvt_utf16<wchar_t, false>::do_unshift(state_type&, |
| 3725 | 3725 | } |
| 3726 | 3726 | |
| 3727 | 3727 | int |
| 3728 | __codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT | |
| 3728 | __codecvt_utf16<wchar_t, false>::do_encoding() const noexcept | |
| 3729 | 3729 | { |
| 3730 | 3730 | return 0; |
| 3731 | 3731 | } |
| 3732 | 3732 | |
| 3733 | 3733 | bool |
| 3734 | __codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT | |
| 3734 | __codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept | |
| 3735 | 3735 | { |
| 3736 | 3736 | return false; |
| 3737 | 3737 | } |
| ... | ... | @@ -3746,7 +3746,7 @@ __codecvt_utf16<wchar_t, false>::do_length(state_type&, |
| 3746 | 3746 | } |
| 3747 | 3747 | |
| 3748 | 3748 | int |
| 3749 | __codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT | |
| 3749 | __codecvt_utf16<wchar_t, false>::do_max_length() const noexcept | |
| 3750 | 3750 | { |
| 3751 | 3751 | if (_Mode_ & consume_header) |
| 3752 | 3752 | return 6; |
| ... | ... | @@ -3800,13 +3800,13 @@ __codecvt_utf16<wchar_t, true>::do_unshift(state_type&, |
| 3800 | 3800 | } |
| 3801 | 3801 | |
| 3802 | 3802 | int |
| 3803 | __codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT | |
| 3803 | __codecvt_utf16<wchar_t, true>::do_encoding() const noexcept | |
| 3804 | 3804 | { |
| 3805 | 3805 | return 0; |
| 3806 | 3806 | } |
| 3807 | 3807 | |
| 3808 | 3808 | bool |
| 3809 | __codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT | |
| 3809 | __codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept | |
| 3810 | 3810 | { |
| 3811 | 3811 | return false; |
| 3812 | 3812 | } |
| ... | ... | @@ -3821,7 +3821,7 @@ __codecvt_utf16<wchar_t, true>::do_length(state_type&, |
| 3821 | 3821 | } |
| 3822 | 3822 | |
| 3823 | 3823 | int |
| 3824 | __codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT | |
| 3824 | __codecvt_utf16<wchar_t, true>::do_max_length() const noexcept | |
| 3825 | 3825 | { |
| 3826 | 3826 | if (_Mode_ & consume_header) |
| 3827 | 3827 | return 6; |
| ... | ... | @@ -3875,13 +3875,13 @@ __codecvt_utf16<char16_t, false>::do_unshift(state_type&, |
| 3875 | 3875 | } |
| 3876 | 3876 | |
| 3877 | 3877 | int |
| 3878 | __codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT | |
| 3878 | __codecvt_utf16<char16_t, false>::do_encoding() const noexcept | |
| 3879 | 3879 | { |
| 3880 | 3880 | return 0; |
| 3881 | 3881 | } |
| 3882 | 3882 | |
| 3883 | 3883 | bool |
| 3884 | __codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT | |
| 3884 | __codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept | |
| 3885 | 3885 | { |
| 3886 | 3886 | return false; |
| 3887 | 3887 | } |
| ... | ... | @@ -3896,7 +3896,7 @@ __codecvt_utf16<char16_t, false>::do_length(state_type&, |
| 3896 | 3896 | } |
| 3897 | 3897 | |
| 3898 | 3898 | int |
| 3899 | __codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT | |
| 3899 | __codecvt_utf16<char16_t, false>::do_max_length() const noexcept | |
| 3900 | 3900 | { |
| 3901 | 3901 | if (_Mode_ & consume_header) |
| 3902 | 3902 | return 4; |
| ... | ... | @@ -3950,13 +3950,13 @@ __codecvt_utf16<char16_t, true>::do_unshift(state_type&, |
| 3950 | 3950 | } |
| 3951 | 3951 | |
| 3952 | 3952 | int |
| 3953 | __codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT | |
| 3953 | __codecvt_utf16<char16_t, true>::do_encoding() const noexcept | |
| 3954 | 3954 | { |
| 3955 | 3955 | return 0; |
| 3956 | 3956 | } |
| 3957 | 3957 | |
| 3958 | 3958 | bool |
| 3959 | __codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT | |
| 3959 | __codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept | |
| 3960 | 3960 | { |
| 3961 | 3961 | return false; |
| 3962 | 3962 | } |
| ... | ... | @@ -3971,7 +3971,7 @@ __codecvt_utf16<char16_t, true>::do_length(state_type&, |
| 3971 | 3971 | } |
| 3972 | 3972 | |
| 3973 | 3973 | int |
| 3974 | __codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT | |
| 3974 | __codecvt_utf16<char16_t, true>::do_max_length() const noexcept | |
| 3975 | 3975 | { |
| 3976 | 3976 | if (_Mode_ & consume_header) |
| 3977 | 3977 | return 4; |
| ... | ... | @@ -4025,13 +4025,13 @@ __codecvt_utf16<char32_t, false>::do_unshift(state_type&, |
| 4025 | 4025 | } |
| 4026 | 4026 | |
| 4027 | 4027 | int |
| 4028 | __codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT | |
| 4028 | __codecvt_utf16<char32_t, false>::do_encoding() const noexcept | |
| 4029 | 4029 | { |
| 4030 | 4030 | return 0; |
| 4031 | 4031 | } |
| 4032 | 4032 | |
| 4033 | 4033 | bool |
| 4034 | __codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT | |
| 4034 | __codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept | |
| 4035 | 4035 | { |
| 4036 | 4036 | return false; |
| 4037 | 4037 | } |
| ... | ... | @@ -4046,7 +4046,7 @@ __codecvt_utf16<char32_t, false>::do_length(state_type&, |
| 4046 | 4046 | } |
| 4047 | 4047 | |
| 4048 | 4048 | int |
| 4049 | __codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT | |
| 4049 | __codecvt_utf16<char32_t, false>::do_max_length() const noexcept | |
| 4050 | 4050 | { |
| 4051 | 4051 | if (_Mode_ & consume_header) |
| 4052 | 4052 | return 6; |
| ... | ... | @@ -4100,13 +4100,13 @@ __codecvt_utf16<char32_t, true>::do_unshift(state_type&, |
| 4100 | 4100 | } |
| 4101 | 4101 | |
| 4102 | 4102 | int |
| 4103 | __codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT | |
| 4103 | __codecvt_utf16<char32_t, true>::do_encoding() const noexcept | |
| 4104 | 4104 | { |
| 4105 | 4105 | return 0; |
| 4106 | 4106 | } |
| 4107 | 4107 | |
| 4108 | 4108 | bool |
| 4109 | __codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT | |
| 4109 | __codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept | |
| 4110 | 4110 | { |
| 4111 | 4111 | return false; |
| 4112 | 4112 | } |
| ... | ... | @@ -4121,7 +4121,7 @@ __codecvt_utf16<char32_t, true>::do_length(state_type&, |
| 4121 | 4121 | } |
| 4122 | 4122 | |
| 4123 | 4123 | int |
| 4124 | __codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT | |
| 4124 | __codecvt_utf16<char32_t, true>::do_max_length() const noexcept | |
| 4125 | 4125 | { |
| 4126 | 4126 | if (_Mode_ & consume_header) |
| 4127 | 4127 | return 6; |
| ... | ... | @@ -4175,13 +4175,13 @@ __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, |
| 4175 | 4175 | } |
| 4176 | 4176 | |
| 4177 | 4177 | int |
| 4178 | __codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT | |
| 4178 | __codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept | |
| 4179 | 4179 | { |
| 4180 | 4180 | return 0; |
| 4181 | 4181 | } |
| 4182 | 4182 | |
| 4183 | 4183 | bool |
| 4184 | __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT | |
| 4184 | __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept | |
| 4185 | 4185 | { |
| 4186 | 4186 | return false; |
| 4187 | 4187 | } |
| ... | ... | @@ -4196,7 +4196,7 @@ __codecvt_utf8_utf16<wchar_t>::do_length(state_type&, |
| 4196 | 4196 | } |
| 4197 | 4197 | |
| 4198 | 4198 | int |
| 4199 | __codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT | |
| 4199 | __codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept | |
| 4200 | 4200 | { |
| 4201 | 4201 | if (_Mode_ & consume_header) |
| 4202 | 4202 | return 7; |
| ... | ... | @@ -4250,13 +4250,13 @@ __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, |
| 4250 | 4250 | } |
| 4251 | 4251 | |
| 4252 | 4252 | int |
| 4253 | __codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT | |
| 4253 | __codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept | |
| 4254 | 4254 | { |
| 4255 | 4255 | return 0; |
| 4256 | 4256 | } |
| 4257 | 4257 | |
| 4258 | 4258 | bool |
| 4259 | __codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT | |
| 4259 | __codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept | |
| 4260 | 4260 | { |
| 4261 | 4261 | return false; |
| 4262 | 4262 | } |
| ... | ... | @@ -4271,7 +4271,7 @@ __codecvt_utf8_utf16<char16_t>::do_length(state_type&, |
| 4271 | 4271 | } |
| 4272 | 4272 | |
| 4273 | 4273 | int |
| 4274 | __codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT | |
| 4274 | __codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept | |
| 4275 | 4275 | { |
| 4276 | 4276 | if (_Mode_ & consume_header) |
| 4277 | 4277 | return 7; |
| ... | ... | @@ -4325,13 +4325,13 @@ __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, |
| 4325 | 4325 | } |
| 4326 | 4326 | |
| 4327 | 4327 | int |
| 4328 | __codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT | |
| 4328 | __codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept | |
| 4329 | 4329 | { |
| 4330 | 4330 | return 0; |
| 4331 | 4331 | } |
| 4332 | 4332 | |
| 4333 | 4333 | bool |
| 4334 | __codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT | |
| 4334 | __codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept | |
| 4335 | 4335 | { |
| 4336 | 4336 | return false; |
| 4337 | 4337 | } |
| ... | ... | @@ -4346,7 +4346,7 @@ __codecvt_utf8_utf16<char32_t>::do_length(state_type&, |
| 4346 | 4346 | } |
| 4347 | 4347 | |
| 4348 | 4348 | int |
| 4349 | __codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT | |
| 4349 | __codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept | |
| 4350 | 4350 | { |
| 4351 | 4351 | if (_Mode_ & consume_header) |
| 4352 | 4352 | return 7; |
| ... | ... | @@ -4597,7 +4597,10 @@ void |
| 4597 | 4597 | __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, |
| 4598 | 4598 | ios_base::fmtflags __flags) |
| 4599 | 4599 | { |
| 4600 | if (__flags & ios_base::showpos) | |
| 4600 | if ((__flags & ios_base::showpos) && | |
| 4601 | (__flags & ios_base::basefield) != ios_base::oct && | |
| 4602 | (__flags & ios_base::basefield) != ios_base::hex && | |
| 4603 | 	__signd) | |
| 4601 | 4604 | *__fmtp++ = '+'; |
| 4602 | 4605 | if (__flags & ios_base::showbase) |
| 4603 | 4606 | *__fmtp++ = '#'; |
| ... | ... | @@ -6336,7 +6339,7 @@ template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, cha |
| 6336 | 6339 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>; |
| 6337 | 6340 | template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>; |
| 6338 | 6341 | template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>; |
| 6339 | #ifndef _LIBCPP_NO_HAS_CHAR8_T | |
| 6342 | #ifndef _LIBCPP_HAS_NO_CHAR8_T | |
| 6340 | 6343 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>; |
| 6341 | 6344 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>; |
| 6342 | 6345 | #endif |
lib/libcxx/src/memory.cpp+13-20| ... | ... | @@ -20,10 +20,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD |
| 20 | 20 | |
| 21 | 21 | const allocator_arg_t allocator_arg = allocator_arg_t(); |
| 22 | 22 | |
| 23 | bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {} | |
| 23 | bad_weak_ptr::~bad_weak_ptr() noexcept {} | |
| 24 | 24 | |
| 25 | 25 | const char* |
| 26 | bad_weak_ptr::what() const _NOEXCEPT | |
| 26 | bad_weak_ptr::what() const noexcept | |
| 27 | 27 | { |
| 28 | 28 | return "bad_weak_ptr"; |
| 29 | 29 | } |
| ... | ... | @@ -38,13 +38,13 @@ __shared_weak_count::~__shared_weak_count() |
| 38 | 38 | |
| 39 | 39 | #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) |
| 40 | 40 | void |
| 41 | __shared_count::__add_shared() _NOEXCEPT | |
| 41 | __shared_count::__add_shared() noexcept | |
| 42 | 42 | { |
| 43 | 43 | __libcpp_atomic_refcount_increment(__shared_owners_); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | bool |
| 47 | __shared_count::__release_shared() _NOEXCEPT | |
| 47 | __shared_count::__release_shared() noexcept | |
| 48 | 48 | { |
| 49 | 49 | if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) |
| 50 | 50 | { |
| ... | ... | @@ -55,19 +55,19 @@ __shared_count::__release_shared() _NOEXCEPT |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | void |
| 58 | __shared_weak_count::__add_shared() _NOEXCEPT | |
| 58 | __shared_weak_count::__add_shared() noexcept | |
| 59 | 59 | { |
| 60 | 60 | __shared_count::__add_shared(); |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | void |
| 64 | __shared_weak_count::__add_weak() _NOEXCEPT | |
| 64 | __shared_weak_count::__add_weak() noexcept | |
| 65 | 65 | { |
| 66 | 66 | __libcpp_atomic_refcount_increment(__shared_weak_owners_); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | 69 | void |
| 70 | __shared_weak_count::__release_shared() _NOEXCEPT | |
| 70 | __shared_weak_count::__release_shared() noexcept | |
| 71 | 71 | { |
| 72 | 72 | if (__shared_count::__release_shared()) |
| 73 | 73 | __release_weak(); |
| ... | ... | @@ -76,7 +76,7 @@ __shared_weak_count::__release_shared() _NOEXCEPT |
| 76 | 76 | #endif // _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS |
| 77 | 77 | |
| 78 | 78 | void |
| 79 | __shared_weak_count::__release_weak() _NOEXCEPT | |
| 79 | __shared_weak_count::__release_weak() noexcept | |
| 80 | 80 | { |
| 81 | 81 | // NOTE: The acquire load here is an optimization of the very |
| 82 | 82 | // common case where a shared pointer is being destructed while |
| ... | ... | @@ -111,7 +111,7 @@ __shared_weak_count::__release_weak() _NOEXCEPT |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | __shared_weak_count* |
| 114 | __shared_weak_count::lock() _NOEXCEPT | |
| 114 | __shared_weak_count::lock() noexcept | |
| 115 | 115 | { |
| 116 | 116 | long object_owners = __libcpp_atomic_load(&__shared_owners_); |
| 117 | 117 | while (object_owners != -1) |
| ... | ... | @@ -125,7 +125,7 @@ __shared_weak_count::lock() _NOEXCEPT |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | const void* |
| 128 | __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT | |
| 128 | __shared_weak_count::__get_deleter(const type_info&) const noexcept | |
| 129 | 129 | { |
| 130 | 130 | return nullptr; |
| 131 | 131 | } |
| ... | ... | @@ -141,13 +141,13 @@ _LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] = |
| 141 | 141 | _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER |
| 142 | 142 | }; |
| 143 | 143 | |
| 144 | _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT | |
| 144 | _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) noexcept | |
| 145 | 145 | : __lx(p) |
| 146 | 146 | { |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | void |
| 150 | __sp_mut::lock() _NOEXCEPT | |
| 150 | __sp_mut::lock() noexcept | |
| 151 | 151 | { |
| 152 | 152 | auto m = static_cast<__libcpp_mutex_t*>(__lx); |
| 153 | 153 | unsigned count = 0; |
| ... | ... | @@ -163,7 +163,7 @@ __sp_mut::lock() _NOEXCEPT |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | 165 | void |
| 166 | __sp_mut::unlock() _NOEXCEPT | |
| 166 | __sp_mut::unlock() noexcept | |
| 167 | 167 | { |
| 168 | 168 | __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx)); |
| 169 | 169 | } |
| ... | ... | @@ -198,13 +198,6 @@ undeclare_no_pointers(char*, size_t) |
| 198 | 198 | { |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | #if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) | |
| 202 | pointer_safety get_pointer_safety() _NOEXCEPT | |
| 203 | { | |
| 204 | return pointer_safety::relaxed; | |
| 205 | } | |
| 206 | #endif | |
| 207 | ||
| 208 | 201 | void* |
| 209 | 202 | __undeclare_reachable(void* p) |
| 210 | 203 | { |
lib/libcxx/src/mutex.cpp+12-12| ... | ... | @@ -36,13 +36,13 @@ mutex::lock() |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | 38 | bool |
| 39 | mutex::try_lock() _NOEXCEPT | |
| 39 | mutex::try_lock() noexcept | |
| 40 | 40 | { |
| 41 | 41 | return __libcpp_mutex_trylock(&__m_); |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | void |
| 45 | mutex::unlock() _NOEXCEPT | |
| 45 | mutex::unlock() noexcept | |
| 46 | 46 | { |
| 47 | 47 | int ec = __libcpp_mutex_unlock(&__m_); |
| 48 | 48 | (void)ec; |
| ... | ... | @@ -74,7 +74,7 @@ recursive_mutex::lock() |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | 76 | void |
| 77 | recursive_mutex::unlock() _NOEXCEPT | |
| 77 | recursive_mutex::unlock() noexcept | |
| 78 | 78 | { |
| 79 | 79 | int e = __libcpp_recursive_mutex_unlock(&__m_); |
| 80 | 80 | (void)e; |
| ... | ... | @@ -82,7 +82,7 @@ recursive_mutex::unlock() _NOEXCEPT |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | bool |
| 85 | recursive_mutex::try_lock() _NOEXCEPT | |
| 85 | recursive_mutex::try_lock() noexcept | |
| 86 | 86 | { |
| 87 | 87 | return __libcpp_recursive_mutex_trylock(&__m_); |
| 88 | 88 | } |
| ... | ... | @@ -109,7 +109,7 @@ timed_mutex::lock() |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 111 | bool |
| 112 | timed_mutex::try_lock() _NOEXCEPT | |
| 112 | timed_mutex::try_lock() noexcept | |
| 113 | 113 | { |
| 114 | 114 | unique_lock<mutex> lk(__m_, try_to_lock); |
| 115 | 115 | if (lk.owns_lock() && !__locked_) |
| ... | ... | @@ -121,7 +121,7 @@ timed_mutex::try_lock() _NOEXCEPT |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | void |
| 124 | timed_mutex::unlock() _NOEXCEPT | |
| 124 | timed_mutex::unlock() noexcept | |
| 125 | 125 | { |
| 126 | 126 | lock_guard<mutex> _(__m_); |
| 127 | 127 | __locked_ = false; |
| ... | ... | @@ -160,7 +160,7 @@ recursive_timed_mutex::lock() |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | 162 | bool |
| 163 | recursive_timed_mutex::try_lock() _NOEXCEPT | |
| 163 | recursive_timed_mutex::try_lock() noexcept | |
| 164 | 164 | { |
| 165 | 165 | __thread_id id = this_thread::get_id(); |
| 166 | 166 | unique_lock<mutex> lk(__m_, try_to_lock); |
| ... | ... | @@ -176,7 +176,7 @@ recursive_timed_mutex::try_lock() _NOEXCEPT |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | 178 | void |
| 179 | recursive_timed_mutex::unlock() _NOEXCEPT | |
| 179 | recursive_timed_mutex::unlock() noexcept | |
| 180 | 180 | { |
| 181 | 181 | unique_lock<mutex> lk(__m_); |
| 182 | 182 | if (--__count_ == 0) |
| ... | ... | @@ -209,7 +209,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, |
| 209 | 209 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 210 | 210 | try |
| 211 | 211 | { |
| 212 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 212 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 213 | 213 | flag = 1; |
| 214 | 214 | func(arg); |
| 215 | 215 | flag = ~once_flag::_State_type(0); |
| ... | ... | @@ -220,7 +220,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, |
| 220 | 220 | flag = 0; |
| 221 | 221 | throw; |
| 222 | 222 | } |
| 223 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 223 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 224 | 224 | } |
| 225 | 225 | #else // !_LIBCPP_HAS_NO_THREADS |
| 226 | 226 | __libcpp_mutex_lock(&mut); |
| ... | ... | @@ -231,7 +231,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, |
| 231 | 231 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 232 | 232 | try |
| 233 | 233 | { |
| 234 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 234 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 235 | 235 | __libcpp_relaxed_store(&flag, once_flag::_State_type(1)); |
| 236 | 236 | __libcpp_mutex_unlock(&mut); |
| 237 | 237 | func(arg); |
| ... | ... | @@ -250,7 +250,7 @@ void __call_once(volatile once_flag::_State_type& flag, void* arg, |
| 250 | 250 | __libcpp_condvar_broadcast(&cv); |
| 251 | 251 | throw; |
| 252 | 252 | } |
| 253 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 253 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 254 | 254 | } |
| 255 | 255 | else |
| 256 | 256 | __libcpp_mutex_unlock(&mut); |
lib/libcxx/src/mutex_destructor.cpp+1-1| ... | ... | @@ -41,7 +41,7 @@ public: |
| 41 | 41 | }; |
| 42 | 42 | |
| 43 | 43 | |
| 44 | mutex::~mutex() _NOEXCEPT | |
| 44 | mutex::~mutex() noexcept | |
| 45 | 45 | { |
| 46 | 46 | __libcpp_mutex_destroy(&__m_); |
| 47 | 47 | } |
lib/libcxx/src/new.cpp+24-24| ... | ... | @@ -83,20 +83,20 @@ operator new(std::size_t size) _THROW_BAD_ALLOC |
| 83 | 83 | |
| 84 | 84 | _LIBCPP_WEAK |
| 85 | 85 | void* |
| 86 | operator new(size_t size, const std::nothrow_t&) _NOEXCEPT | |
| 86 | operator new(size_t size, const std::nothrow_t&) noexcept | |
| 87 | 87 | { |
| 88 | 88 | void* p = nullptr; |
| 89 | 89 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 90 | 90 | try |
| 91 | 91 | { |
| 92 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 92 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 93 | 93 | p = ::operator new(size); |
| 94 | 94 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 95 | 95 | } |
| 96 | 96 | catch (...) |
| 97 | 97 | { |
| 98 | 98 | } |
| 99 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 99 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 100 | 100 | return p; |
| 101 | 101 | } |
| 102 | 102 | |
| ... | ... | @@ -109,61 +109,61 @@ operator new[](size_t size) _THROW_BAD_ALLOC |
| 109 | 109 | |
| 110 | 110 | _LIBCPP_WEAK |
| 111 | 111 | void* |
| 112 | operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT | |
| 112 | operator new[](size_t size, const std::nothrow_t&) noexcept | |
| 113 | 113 | { |
| 114 | 114 | void* p = nullptr; |
| 115 | 115 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 116 | 116 | try |
| 117 | 117 | { |
| 118 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 118 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 119 | 119 | p = ::operator new[](size); |
| 120 | 120 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 121 | 121 | } |
| 122 | 122 | catch (...) |
| 123 | 123 | { |
| 124 | 124 | } |
| 125 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 125 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 126 | 126 | return p; |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | _LIBCPP_WEAK |
| 130 | 130 | void |
| 131 | operator delete(void* ptr) _NOEXCEPT | |
| 131 | operator delete(void* ptr) noexcept | |
| 132 | 132 | { |
| 133 | 133 | ::free(ptr); |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | 136 | _LIBCPP_WEAK |
| 137 | 137 | void |
| 138 | operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT | |
| 138 | operator delete(void* ptr, const std::nothrow_t&) noexcept | |
| 139 | 139 | { |
| 140 | 140 | ::operator delete(ptr); |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | _LIBCPP_WEAK |
| 144 | 144 | void |
| 145 | operator delete(void* ptr, size_t) _NOEXCEPT | |
| 145 | operator delete(void* ptr, size_t) noexcept | |
| 146 | 146 | { |
| 147 | 147 | ::operator delete(ptr); |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | _LIBCPP_WEAK |
| 151 | 151 | void |
| 152 | operator delete[] (void* ptr) _NOEXCEPT | |
| 152 | operator delete[] (void* ptr) noexcept | |
| 153 | 153 | { |
| 154 | 154 | ::operator delete(ptr); |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | _LIBCPP_WEAK |
| 158 | 158 | void |
| 159 | operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT | |
| 159 | operator delete[] (void* ptr, const std::nothrow_t&) noexcept | |
| 160 | 160 | { |
| 161 | 161 | ::operator delete[](ptr); |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | 164 | _LIBCPP_WEAK |
| 165 | 165 | void |
| 166 | operator delete[] (void* ptr, size_t) _NOEXCEPT | |
| 166 | operator delete[] (void* ptr, size_t) noexcept | |
| 167 | 167 | { |
| 168 | 168 | ::operator delete[](ptr); |
| 169 | 169 | } |
| ... | ... | @@ -204,20 +204,20 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC |
| 204 | 204 | |
| 205 | 205 | _LIBCPP_WEAK |
| 206 | 206 | void* |
| 207 | operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 207 | operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 208 | 208 | { |
| 209 | 209 | void* p = nullptr; |
| 210 | 210 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 211 | 211 | try |
| 212 | 212 | { |
| 213 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 213 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 214 | 214 | p = ::operator new(size, alignment); |
| 215 | 215 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 216 | 216 | } |
| 217 | 217 | catch (...) |
| 218 | 218 | { |
| 219 | 219 | } |
| 220 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 220 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 221 | 221 | return p; |
| 222 | 222 | } |
| 223 | 223 | |
| ... | ... | @@ -230,61 +230,61 @@ operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC |
| 230 | 230 | |
| 231 | 231 | _LIBCPP_WEAK |
| 232 | 232 | void* |
| 233 | operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 233 | operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 234 | 234 | { |
| 235 | 235 | void* p = nullptr; |
| 236 | 236 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 237 | 237 | try |
| 238 | 238 | { |
| 239 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 239 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 240 | 240 | p = ::operator new[](size, alignment); |
| 241 | 241 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 242 | 242 | } |
| 243 | 243 | catch (...) |
| 244 | 244 | { |
| 245 | 245 | } |
| 246 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 246 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 247 | 247 | return p; |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | 250 | _LIBCPP_WEAK |
| 251 | 251 | void |
| 252 | operator delete(void* ptr, std::align_val_t) _NOEXCEPT | |
| 252 | operator delete(void* ptr, std::align_val_t) noexcept | |
| 253 | 253 | { |
| 254 | 254 | std::__libcpp_aligned_free(ptr); |
| 255 | 255 | } |
| 256 | 256 | |
| 257 | 257 | _LIBCPP_WEAK |
| 258 | 258 | void |
| 259 | operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 259 | operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 260 | 260 | { |
| 261 | 261 | ::operator delete(ptr, alignment); |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | 264 | _LIBCPP_WEAK |
| 265 | 265 | void |
| 266 | operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT | |
| 266 | operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept | |
| 267 | 267 | { |
| 268 | 268 | ::operator delete(ptr, alignment); |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | 271 | _LIBCPP_WEAK |
| 272 | 272 | void |
| 273 | operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT | |
| 273 | operator delete[] (void* ptr, std::align_val_t alignment) noexcept | |
| 274 | 274 | { |
| 275 | 275 | ::operator delete(ptr, alignment); |
| 276 | 276 | } |
| 277 | 277 | |
| 278 | 278 | _LIBCPP_WEAK |
| 279 | 279 | void |
| 280 | operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 280 | operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 281 | 281 | { |
| 282 | 282 | ::operator delete[](ptr, alignment); |
| 283 | 283 | } |
| 284 | 284 | |
| 285 | 285 | _LIBCPP_WEAK |
| 286 | 286 | void |
| 287 | operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT | |
| 287 | operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept | |
| 288 | 288 | { |
| 289 | 289 | ::operator delete[](ptr, alignment); |
| 290 | 290 | } |
lib/libcxx/src/optional.cpp+4-4| ... | ... | @@ -12,9 +12,9 @@ |
| 12 | 12 | namespace std |
| 13 | 13 | { |
| 14 | 14 | |
| 15 | bad_optional_access::~bad_optional_access() _NOEXCEPT = default; | |
| 15 | bad_optional_access::~bad_optional_access() noexcept = default; | |
| 16 | 16 | |
| 17 | const char* bad_optional_access::what() const _NOEXCEPT { | |
| 17 | const char* bad_optional_access::what() const noexcept { | |
| 18 | 18 | return "bad_optional_access"; |
| 19 | 19 | } |
| 20 | 20 | |
| ... | ... | @@ -34,9 +34,9 @@ public: |
| 34 | 34 | 	bad_optional_access() : std::logic_error("Bad optional Access") {} |
| 35 | 35 | |
| 36 | 36 | //	Get the key function ~bad_optional_access() into the dylib |
| 37 | virtual ~bad_optional_access() _NOEXCEPT; | |
| 37 | virtual ~bad_optional_access() noexcept; | |
| 38 | 38 | }; |
| 39 | 39 | |
| 40 | bad_optional_access::~bad_optional_access() _NOEXCEPT = default; | |
| 40 | bad_optional_access::~bad_optional_access() noexcept = default; | |
| 41 | 41 | |
| 42 | 42 | _LIBCPP_END_NAMESPACE_EXPERIMENTAL |
lib/libcxx/src/random.cpp+1-1| ... | ... | @@ -175,7 +175,7 @@ random_device::operator()() |
| 175 | 175 | #endif |
| 176 | 176 | |
| 177 | 177 | double |
| 178 | random_device::entropy() const _NOEXCEPT | |
| 178 | random_device::entropy() const noexcept | |
| 179 | 179 | { |
| 180 | 180 | #if defined(_LIBCPP_USING_DEV_RANDOM) && defined(RNDGETENTCNT) |
| 181 | 181 | int ent; |
lib/libcxx/src/string.cpp+4-4| ... | ... | @@ -20,6 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD |
| 20 | 20 | |
| 21 | 21 | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; |
| 22 | 22 | |
| 23 | #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; | |
| 23 | 24 | #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION |
| 24 | 25 | _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) |
| 25 | 26 | _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) |
| ... | ... | @@ -27,10 +28,9 @@ _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wch |
| 27 | 28 | _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) |
| 28 | 29 | _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) |
| 29 | 30 | #endif |
| 31 | #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE | |
| 30 | 32 | |
| 31 | template | |
| 32 | string | |
| 33 | operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); | |
| 33 | template string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); | |
| 34 | 34 | |
| 35 | 35 | namespace |
| 36 | 36 | { |
| ... | ... | @@ -423,7 +423,7 @@ get_swprintf() |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | 425 | template <typename S, typename V> |
| 426 | S i_to_string(const V v) | |
| 426 | S i_to_string(V v) | |
| 427 | 427 | { |
| 428 | 428 | // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. |
| 429 | 429 | // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), |
lib/libcxx/src/support/ibm/xlocale_zos.cpp created+137| ... | ... | @@ -0,0 +1,137 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #include <__support/ibm/xlocale.h> | |
| 10 | #include <sstream> | |
| 11 | #include <vector> | |
| 12 | ||
| 13 | #ifdef __cplusplus | |
| 14 | extern "C" { | |
| 15 | #endif // __cplusplus | |
| 16 | ||
| 17 | locale_t newlocale(int category_mask, const char* locale, locale_t base) { | |
| 18 | // Maintain current locale name(s) to restore later. | |
| 19 | std::string current_loc_name(setlocale(LC_ALL, 0)); | |
| 20 | ||
| 21 | // Check for errors. | |
| 22 | if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) { | |
| 23 | errno = EINVAL; | |
| 24 | return (locale_t)0; | |
| 25 | } else { | |
| 26 | for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) { | |
| 27 | if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == NULL) { | |
| 28 | setlocale(LC_ALL, current_loc_name.c_str()); | |
| 29 | errno = EINVAL; | |
| 30 | return (locale_t)0; | |
| 31 | } | |
| 32 | } | |
| 33 | } | |
| 34 | ||
| 35 | // Create new locale. | |
| 36 | locale_t newloc = new locale_struct(); | |
| 37 | ||
| 38 | if (base) { | |
| 39 | if (category_mask != LC_ALL_MASK) { | |
| 40 | // Copy base when it will not be overwritten. | |
| 41 | memcpy(newloc, base, sizeof (locale_struct)); | |
| 42 | newloc->category_mask = category_mask | base->category_mask; | |
| 43 | } | |
| 44 | delete base; | |
| 45 | } else { | |
| 46 | newloc->category_mask = category_mask; | |
| 47 | } | |
| 48 | ||
| 49 | if (category_mask & LC_COLLATE_MASK) | |
| 50 | newloc->lc_collate = locale; | |
| 51 | if (category_mask & LC_CTYPE_MASK) | |
| 52 | newloc->lc_ctype = locale; | |
| 53 | if (category_mask & LC_MONETARY_MASK) | |
| 54 | newloc->lc_monetary = locale; | |
| 55 | if (category_mask & LC_NUMERIC_MASK) | |
| 56 | newloc->lc_numeric = locale; | |
| 57 | if (category_mask & LC_TIME_MASK) | |
| 58 | newloc->lc_time = locale; | |
| 59 | if (category_mask & LC_MESSAGES_MASK) | |
| 60 | newloc->lc_messages = locale; | |
| 61 | ||
| 62 | // Restore current locale. | |
| 63 | setlocale(LC_ALL, current_loc_name.c_str()); | |
| 64 | return (locale_t)newloc; | |
| 65 | } | |
| 66 | ||
| 67 | void freelocale(locale_t locobj) { | |
| 68 | delete locobj; | |
| 69 | } | |
| 70 | ||
| 71 | locale_t uselocale(locale_t newloc) { | |
| 72 | // Maintain current locale name(s). | |
| 73 | std::string current_loc_name(setlocale(LC_ALL, 0)); | |
| 74 | ||
| 75 | if (newloc) { | |
| 76 | // Set locales and check for errors. | |
| 77 | bool is_error = | |
| 78 | (newloc->category_mask & LC_COLLATE_MASK && | |
| 79 | setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == NULL) || | |
| 80 | (newloc->category_mask & LC_CTYPE_MASK && | |
| 81 | setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) || | |
| 82 | (newloc->category_mask & LC_MONETARY_MASK && | |
| 83 | setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) || | |
| 84 | (newloc->category_mask & LC_NUMERIC_MASK && | |
| 85 | setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) || | |
| 86 | (newloc->category_mask & LC_TIME_MASK && | |
| 87 | setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) || | |
| 88 | (newloc->category_mask & LC_MESSAGES_MASK && | |
| 89 | setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL); | |
| 90 | ||
| 91 | if (is_error) { | |
| 92 | setlocale(LC_ALL, current_loc_name.c_str()); | |
| 93 | errno = EINVAL; | |
| 94 | return (locale_t)0; | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 98 | // Construct and return previous locale. | |
| 99 | locale_t previous_loc = new locale_struct(); | |
| 100 | ||
| 101 | // current_loc_name might be a comma-separated locale name list. | |
| 102 | if (current_loc_name.find(',') != std::string::npos) { | |
| 103 | // Tokenize locale name list. | |
| 104 | const char delimiter = ','; | |
| 105 | std::vector<std::string> tokenized; | |
| 106 | std::stringstream ss(current_loc_name); | |
| 107 | std::string s; | |
| 108 | ||
| 109 | while (std::getline(ss, s, delimiter)) { | |
| 110 | tokenized.push_back(s); | |
| 111 | } | |
| 112 | ||
| 113 | _LIBCPP_ASSERT(tokenized.size() >= _NCAT, "locale-name list is too short"); | |
| 114 | ||
| 115 | previous_loc->lc_collate = tokenized[LC_COLLATE]; | |
| 116 | previous_loc->lc_ctype = tokenized[LC_CTYPE]; | |
| 117 | previous_loc->lc_monetary = tokenized[LC_MONETARY]; | |
| 118 | previous_loc->lc_numeric = tokenized[LC_NUMERIC]; | |
| 119 | previous_loc->lc_time = tokenized[LC_TIME]; | |
| 120 | // Skip LC_TOD. | |
| 121 | previous_loc->lc_messages = tokenized[LC_MESSAGES]; | |
| 122 | } else { | |
| 123 | previous_loc->lc_collate = current_loc_name; | |
| 124 | previous_loc->lc_ctype = current_loc_name; | |
| 125 | previous_loc->lc_monetary = current_loc_name; | |
| 126 | previous_loc->lc_numeric = current_loc_name; | |
| 127 | previous_loc->lc_time = current_loc_name; | |
| 128 | previous_loc->lc_messages = current_loc_name; | |
| 129 | } | |
| 130 | ||
| 131 | previous_loc->category_mask = LC_ALL_MASK; | |
| 132 | return previous_loc; | |
| 133 | } | |
| 134 | ||
| 135 | #ifdef __cplusplus | |
| 136 | } | |
| 137 | #endif // __cplusplus |
lib/libcxx/src/support/runtime/exception_fallback.ipp+25-25| ... | ... | @@ -17,13 +17,13 @@ _LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler; |
| 17 | 17 | |
| 18 | 18 | // libcxxrt provides implementations of these functions itself. |
| 19 | 19 | unexpected_handler |
| 20 | set_unexpected(unexpected_handler func) _NOEXCEPT | |
| 20 | set_unexpected(unexpected_handler func) noexcept | |
| 21 | 21 | { |
| 22 | 22 | return __libcpp_atomic_exchange(&__unexpected_handler, func); |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | 25 | unexpected_handler |
| 26 | get_unexpected() _NOEXCEPT | |
| 26 | get_unexpected() noexcept | |
| 27 | 27 | { |
| 28 | 28 | return __libcpp_atomic_load(&__unexpected_handler); |
| 29 | 29 | |
| ... | ... | @@ -38,25 +38,25 @@ void unexpected() |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | terminate_handler |
| 41 | set_terminate(terminate_handler func) _NOEXCEPT | |
| 41 | set_terminate(terminate_handler func) noexcept | |
| 42 | 42 | { |
| 43 | 43 | return __libcpp_atomic_exchange(&__terminate_handler, func); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | terminate_handler |
| 47 | get_terminate() _NOEXCEPT | |
| 47 | get_terminate() noexcept | |
| 48 | 48 | { |
| 49 | 49 | return __libcpp_atomic_load(&__terminate_handler); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | _LIBCPP_NORETURN |
| 53 | 53 | void |
| 54 | terminate() _NOEXCEPT | |
| 54 | terminate() noexcept | |
| 55 | 55 | { |
| 56 | 56 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 57 | 57 | try |
| 58 | 58 | { |
| 59 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 59 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 60 | 60 | (*get_terminate())(); |
| 61 | 61 | // handler should not return |
| 62 | 62 | fprintf(stderr, "terminate_handler unexpectedly returned\n"); |
| ... | ... | @@ -69,12 +69,12 @@ terminate() _NOEXCEPT |
| 69 | 69 | fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); |
| 70 | 70 | ::abort(); |
| 71 | 71 | } |
| 72 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 72 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } | |
| 75 | bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } | |
| 76 | 76 | |
| 77 | int uncaught_exceptions() _NOEXCEPT | |
| 77 | int uncaught_exceptions() noexcept | |
| 78 | 78 | { |
| 79 | 79 | #warning uncaught_exception not yet implemented |
| 80 | 80 | fprintf(stderr, "uncaught_exceptions not yet implemented\n"); |
| ... | ... | @@ -82,77 +82,77 @@ int uncaught_exceptions() _NOEXCEPT |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | |
| 85 | exception::~exception() _NOEXCEPT | |
| 85 | exception::~exception() noexcept | |
| 86 | 86 | { |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | const char* exception::what() const _NOEXCEPT | |
| 89 | const char* exception::what() const noexcept | |
| 90 | 90 | { |
| 91 | 91 | return "std::exception"; |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | bad_exception::~bad_exception() _NOEXCEPT | |
| 94 | bad_exception::~bad_exception() noexcept | |
| 95 | 95 | { |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | const char* bad_exception::what() const _NOEXCEPT | |
| 98 | const char* bad_exception::what() const noexcept | |
| 99 | 99 | { |
| 100 | 100 | return "std::bad_exception"; |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | |
| 104 | bad_alloc::bad_alloc() _NOEXCEPT | |
| 104 | bad_alloc::bad_alloc() noexcept | |
| 105 | 105 | { |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | bad_alloc::~bad_alloc() _NOEXCEPT | |
| 108 | bad_alloc::~bad_alloc() noexcept | |
| 109 | 109 | { |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | const char* |
| 113 | bad_alloc::what() const _NOEXCEPT | |
| 113 | bad_alloc::what() const noexcept | |
| 114 | 114 | { |
| 115 | 115 | return "std::bad_alloc"; |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | bad_array_new_length::bad_array_new_length() _NOEXCEPT | |
| 118 | bad_array_new_length::bad_array_new_length() noexcept | |
| 119 | 119 | { |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | bad_array_new_length::~bad_array_new_length() _NOEXCEPT | |
| 122 | bad_array_new_length::~bad_array_new_length() noexcept | |
| 123 | 123 | { |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | 126 | const char* |
| 127 | bad_array_new_length::what() const _NOEXCEPT | |
| 127 | bad_array_new_length::what() const noexcept | |
| 128 | 128 | { |
| 129 | 129 | return "bad_array_new_length"; |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | bad_cast::bad_cast() _NOEXCEPT | |
| 132 | bad_cast::bad_cast() noexcept | |
| 133 | 133 | { |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | bad_typeid::bad_typeid() _NOEXCEPT | |
| 136 | bad_typeid::bad_typeid() noexcept | |
| 137 | 137 | { |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | bad_cast::~bad_cast() _NOEXCEPT | |
| 140 | bad_cast::~bad_cast() noexcept | |
| 141 | 141 | { |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | const char* |
| 145 | bad_cast::what() const _NOEXCEPT | |
| 145 | bad_cast::what() const noexcept | |
| 146 | 146 | { |
| 147 | 147 | return "std::bad_cast"; |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | bad_typeid::~bad_typeid() _NOEXCEPT | |
| 150 | bad_typeid::~bad_typeid() noexcept | |
| 151 | 151 | { |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | const char* |
| 155 | bad_typeid::what() const _NOEXCEPT | |
| 155 | bad_typeid::what() const noexcept | |
| 156 | 156 | { |
| 157 | 157 | return "std::bad_typeid"; |
| 158 | 158 | } |
lib/libcxx/src/support/runtime/exception_glibcxx.ipp+4-4| ... | ... | @@ -13,19 +13,19 @@ |
| 13 | 13 | |
| 14 | 14 | namespace std { |
| 15 | 15 | |
| 16 | bad_alloc::bad_alloc() _NOEXCEPT | |
| 16 | bad_alloc::bad_alloc() noexcept | |
| 17 | 17 | { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | bad_array_new_length::bad_array_new_length() _NOEXCEPT | |
| 20 | bad_array_new_length::bad_array_new_length() noexcept | |
| 21 | 21 | { |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | bad_cast::bad_cast() _NOEXCEPT | |
| 24 | bad_cast::bad_cast() noexcept | |
| 25 | 25 | { |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | bad_typeid::bad_typeid() _NOEXCEPT | |
| 28 | bad_typeid::bad_typeid() noexcept | |
| 29 | 29 | { |
| 30 | 30 | } |
| 31 | 31 |
lib/libcxx/src/support/runtime/exception_libcxxabi.ipp+2-2| ... | ... | @@ -13,9 +13,9 @@ |
| 13 | 13 | |
| 14 | 14 | namespace std { |
| 15 | 15 | |
| 16 | bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } | |
| 16 | bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } | |
| 17 | 17 | |
| 18 | int uncaught_exceptions() _NOEXCEPT | |
| 18 | int uncaught_exceptions() noexcept | |
| 19 | 19 | { |
| 20 | 20 | # if _LIBCPPABI_VERSION > 1001 |
| 21 | 21 | return __cxa_uncaught_exceptions(); |
lib/libcxx/src/support/runtime/exception_libcxxrt.ipp+2-2| ... | ... | @@ -13,11 +13,11 @@ |
| 13 | 13 | |
| 14 | 14 | namespace std { |
| 15 | 15 | |
| 16 | bad_exception::~bad_exception() _NOEXCEPT | |
| 16 | bad_exception::~bad_exception() noexcept | |
| 17 | 17 | { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | const char* bad_exception::what() const _NOEXCEPT | |
| 20 | const char* bad_exception::what() const noexcept | |
| 21 | 21 | { |
| 22 | 22 | return "std::bad_exception"; |
| 23 | 23 | } |
lib/libcxx/src/support/runtime/exception_msvc.ipp+25-25| ... | ... | @@ -31,11 +31,11 @@ int __cdecl __uncaught_exceptions(); |
| 31 | 31 | namespace std { |
| 32 | 32 | |
| 33 | 33 | unexpected_handler |
| 34 | set_unexpected(unexpected_handler func) _NOEXCEPT { | |
| 34 | set_unexpected(unexpected_handler func) noexcept { | |
| 35 | 35 | return ::set_unexpected(func); |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | unexpected_handler get_unexpected() _NOEXCEPT { | |
| 38 | unexpected_handler get_unexpected() noexcept { | |
| 39 | 39 | return ::_get_unexpected(); |
| 40 | 40 | } |
| 41 | 41 | |
| ... | ... | @@ -46,21 +46,21 @@ void unexpected() { |
| 46 | 46 | terminate(); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | terminate_handler set_terminate(terminate_handler func) _NOEXCEPT { | |
| 49 | terminate_handler set_terminate(terminate_handler func) noexcept { | |
| 50 | 50 | return ::set_terminate(func); |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | terminate_handler get_terminate() _NOEXCEPT { | |
| 53 | terminate_handler get_terminate() noexcept { | |
| 54 | 54 | return ::_get_terminate(); |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | _LIBCPP_NORETURN |
| 58 | void terminate() _NOEXCEPT | |
| 58 | void terminate() noexcept | |
| 59 | 59 | { |
| 60 | 60 | #ifndef _LIBCPP_NO_EXCEPTIONS |
| 61 | 61 | try |
| 62 | 62 | { |
| 63 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 63 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 64 | 64 | (*get_terminate())(); |
| 65 | 65 | // handler should not return |
| 66 | 66 | fprintf(stderr, "terminate_handler unexpectedly returned\n"); |
| ... | ... | @@ -73,88 +73,88 @@ void terminate() _NOEXCEPT |
| 73 | 73 | fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); |
| 74 | 74 | ::abort(); |
| 75 | 75 | } |
| 76 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 76 | #endif // _LIBCPP_NO_EXCEPTIONS | |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } | |
| 79 | bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } | |
| 80 | 80 | |
| 81 | int uncaught_exceptions() _NOEXCEPT { | |
| 81 | int uncaught_exceptions() noexcept { | |
| 82 | 82 | return __uncaught_exceptions(); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | 85 | #if !defined(_LIBCPP_ABI_VCRUNTIME) |
| 86 | bad_cast::bad_cast() _NOEXCEPT | |
| 86 | bad_cast::bad_cast() noexcept | |
| 87 | 87 | { |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | bad_cast::~bad_cast() _NOEXCEPT | |
| 90 | bad_cast::~bad_cast() noexcept | |
| 91 | 91 | { |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | const char * |
| 95 | bad_cast::what() const _NOEXCEPT | |
| 95 | bad_cast::what() const noexcept | |
| 96 | 96 | { |
| 97 | 97 | return "std::bad_cast"; |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | bad_typeid::bad_typeid() _NOEXCEPT | |
| 100 | bad_typeid::bad_typeid() noexcept | |
| 101 | 101 | { |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | bad_typeid::~bad_typeid() _NOEXCEPT | |
| 104 | bad_typeid::~bad_typeid() noexcept | |
| 105 | 105 | { |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | 108 | const char * |
| 109 | bad_typeid::what() const _NOEXCEPT | |
| 109 | bad_typeid::what() const noexcept | |
| 110 | 110 | { |
| 111 | 111 | return "std::bad_typeid"; |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | exception::~exception() _NOEXCEPT | |
| 114 | exception::~exception() noexcept | |
| 115 | 115 | { |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | const char* exception::what() const _NOEXCEPT | |
| 118 | const char* exception::what() const noexcept | |
| 119 | 119 | { |
| 120 | 120 | return "std::exception"; |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | |
| 124 | bad_exception::~bad_exception() _NOEXCEPT | |
| 124 | bad_exception::~bad_exception() noexcept | |
| 125 | 125 | { |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | const char* bad_exception::what() const _NOEXCEPT | |
| 128 | const char* bad_exception::what() const noexcept | |
| 129 | 129 | { |
| 130 | 130 | return "std::bad_exception"; |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | |
| 134 | bad_alloc::bad_alloc() _NOEXCEPT | |
| 134 | bad_alloc::bad_alloc() noexcept | |
| 135 | 135 | { |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | bad_alloc::~bad_alloc() _NOEXCEPT | |
| 138 | bad_alloc::~bad_alloc() noexcept | |
| 139 | 139 | { |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | const char* |
| 143 | bad_alloc::what() const _NOEXCEPT | |
| 143 | bad_alloc::what() const noexcept | |
| 144 | 144 | { |
| 145 | 145 | return "std::bad_alloc"; |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | bad_array_new_length::bad_array_new_length() _NOEXCEPT | |
| 148 | bad_array_new_length::bad_array_new_length() noexcept | |
| 149 | 149 | { |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | bad_array_new_length::~bad_array_new_length() _NOEXCEPT | |
| 152 | bad_array_new_length::~bad_array_new_length() noexcept | |
| 153 | 153 | { |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | const char* |
| 157 | bad_array_new_length::what() const _NOEXCEPT | |
| 157 | bad_array_new_length::what() const noexcept | |
| 158 | 158 | { |
| 159 | 159 | return "bad_array_new_length"; |
| 160 | 160 | } |
lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp+6-6| ... | ... | @@ -13,17 +13,17 @@ |
| 13 | 13 | |
| 14 | 14 | namespace std { |
| 15 | 15 | |
| 16 | exception_ptr::~exception_ptr() _NOEXCEPT { | |
| 16 | exception_ptr::~exception_ptr() noexcept { | |
| 17 | 17 | __cxa_decrement_exception_refcount(__ptr_); |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT | |
| 20 | exception_ptr::exception_ptr(const exception_ptr& other) noexcept | |
| 21 | 21 | : __ptr_(other.__ptr_) |
| 22 | 22 | { |
| 23 | 23 | __cxa_increment_exception_refcount(__ptr_); |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT | |
| 26 | exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept | |
| 27 | 27 | { |
| 28 | 28 | if (__ptr_ != other.__ptr_) |
| 29 | 29 | { |
| ... | ... | @@ -34,12 +34,12 @@ exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT |
| 34 | 34 | return *this; |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | nested_exception::nested_exception() _NOEXCEPT | |
| 37 | nested_exception::nested_exception() noexcept | |
| 38 | 38 | : __ptr_(current_exception()) |
| 39 | 39 | { |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | nested_exception::~nested_exception() _NOEXCEPT | |
| 42 | nested_exception::~nested_exception() noexcept | |
| 43 | 43 | { |
| 44 | 44 | } |
| 45 | 45 | |
| ... | ... | @@ -52,7 +52,7 @@ nested_exception::rethrow_nested() const |
| 52 | 52 | rethrow_exception(__ptr_); |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | exception_ptr current_exception() _NOEXCEPT | |
| 55 | exception_ptr current_exception() noexcept | |
| 56 | 56 | { |
| 57 | 57 | // be nicer if there was a constructor that took a ptr, then |
| 58 | 58 | // this whole function would be just: |
lib/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp+7-7| ... | ... | @@ -25,35 +25,35 @@ struct exception_ptr |
| 25 | 25 | { |
| 26 | 26 | void* __ptr_; |
| 27 | 27 | |
| 28 | exception_ptr(const exception_ptr&) _NOEXCEPT; | |
| 29 | exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; | |
| 30 | ~exception_ptr() _NOEXCEPT; | |
| 28 | exception_ptr(const exception_ptr&) noexcept; | |
| 29 | exception_ptr& operator=(const exception_ptr&) noexcept; | |
| 30 | ~exception_ptr() noexcept; | |
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | _LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); |
| 36 | 36 | |
| 37 | exception_ptr::~exception_ptr() _NOEXCEPT | |
| 37 | exception_ptr::~exception_ptr() noexcept | |
| 38 | 38 | { |
| 39 | 39 | reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT | |
| 42 | exception_ptr::exception_ptr(const exception_ptr& other) noexcept | |
| 43 | 43 | : __ptr_(other.__ptr_) |
| 44 | 44 | { |
| 45 | 45 | new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( |
| 46 | 46 | reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT | |
| 49 | exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept | |
| 50 | 50 | { |
| 51 | 51 | *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = |
| 52 | 52 | reinterpret_cast<const __exception_ptr::exception_ptr&>(other); |
| 53 | 53 | return *this; |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | nested_exception::nested_exception() _NOEXCEPT | |
| 56 | nested_exception::nested_exception() noexcept | |
| 57 | 57 | : __ptr_(current_exception()) |
| 58 | 58 | { |
| 59 | 59 | } |
lib/libcxx/src/support/runtime/exception_pointer_msvc.ipp+12-12| ... | ... | @@ -24,35 +24,35 @@ __ExceptionPtrCopyException(void*, const void*, const void*); |
| 24 | 24 | |
| 25 | 25 | namespace std { |
| 26 | 26 | |
| 27 | exception_ptr::exception_ptr() _NOEXCEPT { __ExceptionPtrCreate(this); } | |
| 28 | exception_ptr::exception_ptr(nullptr_t) _NOEXCEPT { __ExceptionPtrCreate(this); } | |
| 27 | exception_ptr::exception_ptr() noexcept { __ExceptionPtrCreate(this); } | |
| 28 | exception_ptr::exception_ptr(nullptr_t) noexcept { __ExceptionPtrCreate(this); } | |
| 29 | 29 | |
| 30 | exception_ptr::exception_ptr(const exception_ptr& __other) _NOEXCEPT { | |
| 30 | exception_ptr::exception_ptr(const exception_ptr& __other) noexcept { | |
| 31 | 31 | __ExceptionPtrCopy(this, &__other); |
| 32 | 32 | } |
| 33 | exception_ptr& exception_ptr::operator=(const exception_ptr& __other) _NOEXCEPT { | |
| 33 | exception_ptr& exception_ptr::operator=(const exception_ptr& __other) noexcept { | |
| 34 | 34 | __ExceptionPtrAssign(this, &__other); |
| 35 | 35 | return *this; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | exception_ptr& exception_ptr::operator=(nullptr_t) _NOEXCEPT { | |
| 38 | exception_ptr& exception_ptr::operator=(nullptr_t) noexcept { | |
| 39 | 39 | exception_ptr dummy; |
| 40 | 40 | __ExceptionPtrAssign(this, &dummy); |
| 41 | 41 | return *this; |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | exception_ptr::~exception_ptr() _NOEXCEPT { __ExceptionPtrDestroy(this); } | |
| 44 | exception_ptr::~exception_ptr() noexcept { __ExceptionPtrDestroy(this); } | |
| 45 | 45 | |
| 46 | exception_ptr::operator bool() const _NOEXCEPT { | |
| 46 | exception_ptr::operator bool() const noexcept { | |
| 47 | 47 | return __ExceptionPtrToBool(this); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { | |
| 50 | bool operator==(const exception_ptr& __x, const exception_ptr& __y) noexcept { | |
| 51 | 51 | return __ExceptionPtrCompare(&__x, &__y); |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | |
| 55 | void swap(exception_ptr& lhs, exception_ptr& rhs) _NOEXCEPT { | |
| 55 | void swap(exception_ptr& lhs, exception_ptr& rhs) noexcept { | |
| 56 | 56 | __ExceptionPtrSwap(&rhs, &lhs); |
| 57 | 57 | } |
| 58 | 58 | |
| ... | ... | @@ -63,7 +63,7 @@ exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) { |
| 63 | 63 | return __ret; |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | exception_ptr current_exception() _NOEXCEPT { | |
| 66 | exception_ptr current_exception() noexcept { | |
| 67 | 67 | exception_ptr __ret; |
| 68 | 68 | __ExceptionPtrCurrentException(&__ret); |
| 69 | 69 | return __ret; |
| ... | ... | @@ -72,9 +72,9 @@ exception_ptr current_exception() _NOEXCEPT { |
| 72 | 72 | _LIBCPP_NORETURN |
| 73 | 73 | void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); } |
| 74 | 74 | |
| 75 | nested_exception::nested_exception() _NOEXCEPT : __ptr_(current_exception()) {} | |
| 75 | nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {} | |
| 76 | 76 | |
| 77 | nested_exception::~nested_exception() _NOEXCEPT {} | |
| 77 | nested_exception::~nested_exception() noexcept {} | |
| 78 | 78 | |
| 79 | 79 | _LIBCPP_NORETURN |
| 80 | 80 | void nested_exception::rethrow_nested() const { |
lib/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp+6-6| ... | ... | @@ -12,14 +12,14 @@ |
| 12 | 12 | |
| 13 | 13 | namespace std { |
| 14 | 14 | |
| 15 | exception_ptr::~exception_ptr() _NOEXCEPT | |
| 15 | exception_ptr::~exception_ptr() noexcept | |
| 16 | 16 | { |
| 17 | 17 | # warning exception_ptr not yet implemented |
| 18 | 18 | fprintf(stderr, "exception_ptr not yet implemented\n"); |
| 19 | 19 | ::abort(); |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT | |
| 22 | exception_ptr::exception_ptr(const exception_ptr& other) noexcept | |
| 23 | 23 | : __ptr_(other.__ptr_) |
| 24 | 24 | { |
| 25 | 25 | # warning exception_ptr not yet implemented |
| ... | ... | @@ -27,21 +27,21 @@ exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT |
| 27 | 27 | ::abort(); |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT | |
| 30 | exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept | |
| 31 | 31 | { |
| 32 | 32 | # warning exception_ptr not yet implemented |
| 33 | 33 | fprintf(stderr, "exception_ptr not yet implemented\n"); |
| 34 | 34 | ::abort(); |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | nested_exception::nested_exception() _NOEXCEPT | |
| 37 | nested_exception::nested_exception() noexcept | |
| 38 | 38 | : __ptr_(current_exception()) |
| 39 | 39 | { |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | 42 | #if !defined(__GLIBCXX__) |
| 43 | 43 | |
| 44 | nested_exception::~nested_exception() _NOEXCEPT | |
| 44 | nested_exception::~nested_exception() noexcept | |
| 45 | 45 | { |
| 46 | 46 | } |
| 47 | 47 | |
| ... | ... | @@ -61,7 +61,7 @@ nested_exception::rethrow_nested() const |
| 61 | 61 | #endif // FIXME |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | exception_ptr current_exception() _NOEXCEPT | |
| 64 | exception_ptr current_exception() noexcept | |
| 65 | 65 | { |
| 66 | 66 | # warning exception_ptr not yet implemented |
| 67 | 67 | fprintf(stderr, "exception_ptr not yet implemented\n"); |
lib/libcxx/src/support/runtime/new_handler_fallback.ipp+2-2| ... | ... | @@ -12,13 +12,13 @@ namespace std { |
| 12 | 12 | _LIBCPP_SAFE_STATIC static std::new_handler __new_handler; |
| 13 | 13 | |
| 14 | 14 | new_handler |
| 15 | set_new_handler(new_handler handler) _NOEXCEPT | |
| 15 | set_new_handler(new_handler handler) noexcept | |
| 16 | 16 | { |
| 17 | 17 | return __libcpp_atomic_exchange(&__new_handler, handler); |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | new_handler |
| 21 | get_new_handler() _NOEXCEPT | |
| 21 | get_new_handler() noexcept | |
| 22 | 22 | { |
| 23 | 23 | return __libcpp_atomic_load(&__new_handler); |
| 24 | 24 | } |
lib/libcxx/src/support/runtime/stdexcept_default.ipp+15-15| ... | ... | @@ -23,9 +23,9 @@ logic_error::logic_error(const string& msg) : __imp_(msg.c_str()) {} |
| 23 | 23 | |
| 24 | 24 | logic_error::logic_error(const char* msg) : __imp_(msg) {} |
| 25 | 25 | |
| 26 | logic_error::logic_error(const logic_error& le) _NOEXCEPT : __imp_(le.__imp_) {} | |
| 26 | logic_error::logic_error(const logic_error& le) noexcept : __imp_(le.__imp_) {} | |
| 27 | 27 | |
| 28 | logic_error& logic_error::operator=(const logic_error& le) _NOEXCEPT { | |
| 28 | logic_error& logic_error::operator=(const logic_error& le) noexcept { | |
| 29 | 29 | __imp_ = le.__imp_; |
| 30 | 30 | return *this; |
| 31 | 31 | } |
| ... | ... | @@ -34,30 +34,30 @@ runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str()) {} |
| 34 | 34 | |
| 35 | 35 | runtime_error::runtime_error(const char* msg) : __imp_(msg) {} |
| 36 | 36 | |
| 37 | runtime_error::runtime_error(const runtime_error& re) _NOEXCEPT | |
| 37 | runtime_error::runtime_error(const runtime_error& re) noexcept | |
| 38 | 38 | : __imp_(re.__imp_) {} |
| 39 | 39 | |
| 40 | runtime_error& runtime_error::operator=(const runtime_error& re) _NOEXCEPT { | |
| 40 | runtime_error& runtime_error::operator=(const runtime_error& re) noexcept { | |
| 41 | 41 | __imp_ = re.__imp_; |
| 42 | 42 | return *this; |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | #if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) |
| 46 | 46 | |
| 47 | const char* logic_error::what() const _NOEXCEPT { return __imp_.c_str(); } | |
| 47 | const char* logic_error::what() const noexcept { return __imp_.c_str(); } | |
| 48 | 48 | |
| 49 | const char* runtime_error::what() const _NOEXCEPT { return __imp_.c_str(); } | |
| 49 | const char* runtime_error::what() const noexcept { return __imp_.c_str(); } | |
| 50 | 50 | |
| 51 | logic_error::~logic_error() _NOEXCEPT {} | |
| 52 | domain_error::~domain_error() _NOEXCEPT {} | |
| 53 | invalid_argument::~invalid_argument() _NOEXCEPT {} | |
| 54 | length_error::~length_error() _NOEXCEPT {} | |
| 55 | out_of_range::~out_of_range() _NOEXCEPT {} | |
| 51 | logic_error::~logic_error() noexcept {} | |
| 52 | domain_error::~domain_error() noexcept {} | |
| 53 | invalid_argument::~invalid_argument() noexcept {} | |
| 54 | length_error::~length_error() noexcept {} | |
| 55 | out_of_range::~out_of_range() noexcept {} | |
| 56 | 56 | |
| 57 | runtime_error::~runtime_error() _NOEXCEPT {} | |
| 58 | range_error::~range_error() _NOEXCEPT {} | |
| 59 | overflow_error::~overflow_error() _NOEXCEPT {} | |
| 60 | underflow_error::~underflow_error() _NOEXCEPT {} | |
| 57 | runtime_error::~runtime_error() noexcept {} | |
| 58 | range_error::~range_error() noexcept {} | |
| 59 | overflow_error::~overflow_error() noexcept {} | |
| 60 | underflow_error::~underflow_error() noexcept {} | |
| 61 | 61 | |
| 62 | 62 | #endif |
| 63 | 63 |
lib/libcxx/src/support/win32/support.cpp+4-1| ... | ... | @@ -22,7 +22,10 @@ int __libcpp_vasprintf( char **sptr, const char *__restrict format, va_list ap ) |
| 22 | 22 | { |
| 23 | 23 | *sptr = NULL; |
| 24 | 24 | // Query the count required. |
| 25 | int count = _vsnprintf( NULL, 0, format, ap ); | |
| 25 | va_list ap_copy; | |
| 26 | va_copy(ap_copy, ap); | |
| 27 | int count = _vsnprintf( NULL, 0, format, ap_copy ); | |
| 28 | va_end(ap_copy); | |
| 26 | 29 | if (count < 0) |
| 27 | 30 | return count; |
| 28 | 31 | size_t buffer_size = static_cast<size_t>(count) + 1; |
lib/libcxx/src/support/win32/thread_win32.cpp+40-4| ... | ... | @@ -8,6 +8,8 @@ |
| 8 | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | |
| 10 | 10 | #include <__threading_support> |
| 11 | #define NOMINMAX | |
| 12 | #define WIN32_LEAN_AND_MEAN | |
| 11 | 13 | #include <windows.h> |
| 12 | 14 | #include <process.h> |
| 13 | 15 | #include <fibersapi.h> |
| ... | ... | @@ -37,6 +39,9 @@ static_assert(alignof(__libcpp_thread_t) == alignof(HANDLE), ""); |
| 37 | 39 | static_assert(sizeof(__libcpp_tls_key) == sizeof(DWORD), ""); |
| 38 | 40 | static_assert(alignof(__libcpp_tls_key) == alignof(DWORD), ""); |
| 39 | 41 | |
| 42 | static_assert(sizeof(__libcpp_semaphore_t) == sizeof(HANDLE), ""); | |
| 43 | static_assert(alignof(__libcpp_semaphore_t) == alignof(HANDLE), ""); | |
| 44 | ||
| 40 | 45 | // Mutex |
| 41 | 46 | int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) |
| 42 | 47 | { |
| ... | ... | @@ -241,10 +246,8 @@ void __libcpp_thread_yield() |
| 241 | 246 | |
| 242 | 247 | void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) |
| 243 | 248 | { |
| 244 | using namespace chrono; | |
| 245 | // round-up to the nearest milisecond | |
| 246 | milliseconds __ms = | |
| 247 | duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999)); | |
| 249 | // round-up to the nearest millisecond | |
| 250 | chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); | |
| 248 | 251 | // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx) |
| 249 | 252 | Sleep(__ms.count()); |
| 250 | 253 | } |
| ... | ... | @@ -272,4 +275,37 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) |
| 272 | 275 | return 0; |
| 273 | 276 | } |
| 274 | 277 | |
| 278 | // Semaphores | |
| 279 | bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) | |
| 280 | { | |
| 281 | *(PHANDLE)__sem = CreateSemaphoreEx(nullptr, __init, _LIBCPP_SEMAPHORE_MAX, | |
| 282 | nullptr, 0, SEMAPHORE_ALL_ACCESS); | |
| 283 | return *__sem != nullptr; | |
| 284 | } | |
| 285 | ||
| 286 | bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) | |
| 287 | { | |
| 288 | CloseHandle(*(PHANDLE)__sem); | |
| 289 | return true; | |
| 290 | } | |
| 291 | ||
| 292 | bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) | |
| 293 | { | |
| 294 | return ReleaseSemaphore(*(PHANDLE)__sem, 1, nullptr); | |
| 295 | } | |
| 296 | ||
| 297 | bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) | |
| 298 | { | |
| 299 | return WaitForSingleObjectEx(*(PHANDLE)__sem, INFINITE, false) == | |
| 300 | WAIT_OBJECT_0; | |
| 301 | } | |
| 302 | ||
| 303 | bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, | |
| 304 | chrono::nanoseconds const& __ns) | |
| 305 | { | |
| 306 | chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); | |
| 307 | return WaitForSingleObjectEx(*(PHANDLE)__sem, __ms.count(), false) == | |
| 308 | WAIT_OBJECT_0; | |
| 309 | } | |
| 310 | ||
| 275 | 311 | _LIBCPP_END_NAMESPACE_STD |
lib/libcxx/src/system_error.cpp+17-17| ... | ... | @@ -28,29 +28,29 @@ _LIBCPP_BEGIN_NAMESPACE_STD |
| 28 | 28 | // class error_category |
| 29 | 29 | |
| 30 | 30 | #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) |
| 31 | error_category::error_category() _NOEXCEPT | |
| 31 | error_category::error_category() noexcept | |
| 32 | 32 | { |
| 33 | 33 | } |
| 34 | 34 | #endif |
| 35 | 35 | |
| 36 | error_category::~error_category() _NOEXCEPT | |
| 36 | error_category::~error_category() noexcept | |
| 37 | 37 | { |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | error_condition |
| 41 | error_category::default_error_condition(int ev) const _NOEXCEPT | |
| 41 | error_category::default_error_condition(int ev) const noexcept | |
| 42 | 42 | { |
| 43 | 43 | return error_condition(ev, *this); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | bool |
| 47 | error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT | |
| 47 | error_category::equivalent(int code, const error_condition& condition) const noexcept | |
| 48 | 48 | { |
| 49 | 49 | return default_error_condition(code) == condition; |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | bool |
| 53 | error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT | |
| 53 | error_category::equivalent(const error_code& code, int condition) const noexcept | |
| 54 | 54 | { |
| 55 | 55 | return *this == code.category() && code.value() == condition; |
| 56 | 56 | } |
| ... | ... | @@ -141,12 +141,12 @@ class _LIBCPP_HIDDEN __generic_error_category |
| 141 | 141 | : public __do_message |
| 142 | 142 | { |
| 143 | 143 | public: |
| 144 | virtual const char* name() const _NOEXCEPT; | |
| 144 | virtual const char* name() const noexcept; | |
| 145 | 145 | virtual string message(int ev) const; |
| 146 | 146 | }; |
| 147 | 147 | |
| 148 | 148 | const char* |
| 149 | __generic_error_category::name() const _NOEXCEPT | |
| 149 | __generic_error_category::name() const noexcept | |
| 150 | 150 | { |
| 151 | 151 | return "generic"; |
| 152 | 152 | } |
| ... | ... | @@ -157,12 +157,12 @@ __generic_error_category::message(int ev) const |
| 157 | 157 | #ifdef _LIBCPP_ELAST |
| 158 | 158 | if (ev > _LIBCPP_ELAST) |
| 159 | 159 | return string("unspecified generic_category error"); |
| 160 | #endif // _LIBCPP_ELAST | |
| 160 | #endif // _LIBCPP_ELAST | |
| 161 | 161 | return __do_message::message(ev); |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | 164 | const error_category& |
| 165 | generic_category() _NOEXCEPT | |
| 165 | generic_category() noexcept | |
| 166 | 166 | { |
| 167 | 167 | static __generic_error_category s; |
| 168 | 168 | return s; |
| ... | ... | @@ -172,13 +172,13 @@ class _LIBCPP_HIDDEN __system_error_category |
| 172 | 172 | : public __do_message |
| 173 | 173 | { |
| 174 | 174 | public: |
| 175 | virtual const char* name() const _NOEXCEPT; | |
| 175 | virtual const char* name() const noexcept; | |
| 176 | 176 | virtual string message(int ev) const; |
| 177 | virtual error_condition default_error_condition(int ev) const _NOEXCEPT; | |
| 177 | virtual error_condition default_error_condition(int ev) const noexcept; | |
| 178 | 178 | }; |
| 179 | 179 | |
| 180 | 180 | const char* |
| 181 | __system_error_category::name() const _NOEXCEPT | |
| 181 | __system_error_category::name() const noexcept | |
| 182 | 182 | { |
| 183 | 183 | return "system"; |
| 184 | 184 | } |
| ... | ... | @@ -189,22 +189,22 @@ __system_error_category::message(int ev) const |
| 189 | 189 | #ifdef _LIBCPP_ELAST |
| 190 | 190 | if (ev > _LIBCPP_ELAST) |
| 191 | 191 | return string("unspecified system_category error"); |
| 192 | #endif // _LIBCPP_ELAST | |
| 192 | #endif // _LIBCPP_ELAST | |
| 193 | 193 | return __do_message::message(ev); |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | 196 | error_condition |
| 197 | __system_error_category::default_error_condition(int ev) const _NOEXCEPT | |
| 197 | __system_error_category::default_error_condition(int ev) const noexcept | |
| 198 | 198 | { |
| 199 | 199 | #ifdef _LIBCPP_ELAST |
| 200 | 200 | if (ev > _LIBCPP_ELAST) |
| 201 | 201 | return error_condition(ev, system_category()); |
| 202 | #endif // _LIBCPP_ELAST | |
| 202 | #endif // _LIBCPP_ELAST | |
| 203 | 203 | return error_condition(ev, generic_category()); |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | 206 | const error_category& |
| 207 | system_category() _NOEXCEPT | |
| 207 | system_category() noexcept | |
| 208 | 208 | { |
| 209 | 209 | static __system_error_category s; |
| 210 | 210 | return s; |
| ... | ... | @@ -276,7 +276,7 @@ system_error::system_error(int ev, const error_category& ecat) |
| 276 | 276 | { |
| 277 | 277 | } |
| 278 | 278 | |
| 279 | system_error::~system_error() _NOEXCEPT | |
| 279 | system_error::~system_error() noexcept | |
| 280 | 280 | { |
| 281 | 281 | } |
| 282 | 282 |
lib/libcxx/src/thread.cpp+2-2| ... | ... | @@ -70,7 +70,7 @@ thread::detach() |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | unsigned |
| 73 | thread::hardware_concurrency() _NOEXCEPT | |
| 73 | thread::hardware_concurrency() noexcept | |
| 74 | 74 | { |
| 75 | 75 | #if defined(_SC_NPROCESSORS_ONLN) |
| 76 | 76 | long result = sysconf(_SC_NPROCESSORS_ONLN); |
| ... | ... | @@ -94,7 +94,7 @@ thread::hardware_concurrency() _NOEXCEPT |
| 94 | 94 | # warning hardware_concurrency not yet implemented |
| 95 | 95 | # endif |
| 96 | 96 | return 0; // Means not computable [thread.thread.static] |
| 97 | #endif // defined(CTL_HW) && defined(HW_NCPU) | |
| 97 | #endif // defined(CTL_HW) && defined(HW_NCPU) | |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | namespace this_thread |
lib/libcxx/src/typeinfo.cpp+3-3| ... | ... | @@ -11,18 +11,18 @@ |
| 11 | 11 | #if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_VCRUNTIME) |
| 12 | 12 | #include <string.h> |
| 13 | 13 | |
| 14 | int std::type_info::__compare(const type_info &__rhs) const _NOEXCEPT { | |
| 14 | int std::type_info::__compare(const type_info &__rhs) const noexcept { | |
| 15 | 15 | if (&__data == &__rhs.__data) |
| 16 | 16 | return 0; |
| 17 | 17 | return strcmp(&__data.__decorated_name[1], &__rhs.__data.__decorated_name[1]); |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | const char *std::type_info::name() const _NOEXCEPT { | |
| 20 | const char *std::type_info::name() const noexcept { | |
| 21 | 21 | // TODO(compnerd) cache demangled &__data.__decorated_name[1] |
| 22 | 22 | return &__data.__decorated_name[1]; |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | size_t std::type_info::hash_code() const _NOEXCEPT { | |
| 25 | size_t std::type_info::hash_code() const noexcept { | |
| 26 | 26 | #if defined(_WIN64) |
| 27 | 27 | constexpr size_t fnv_offset_basis = 14695981039346656037ull; |
| 28 | 28 | constexpr size_t fnv_prime = 10995116282110ull; |
lib/libcxxabi/src/cxa_default_handlers.cpp+2-2| ... | ... | @@ -108,7 +108,7 @@ namespace std |
| 108 | 108 | { |
| 109 | 109 | |
| 110 | 110 | unexpected_handler |
| 111 | set_unexpected(unexpected_handler func) _NOEXCEPT | |
| 111 | set_unexpected(unexpected_handler func) noexcept | |
| 112 | 112 | { |
| 113 | 113 | if (func == 0) |
| 114 | 114 | func = default_unexpected_handler; |
| ... | ... | @@ -117,7 +117,7 @@ set_unexpected(unexpected_handler func) _NOEXCEPT |
| 117 | 117 | } |
| 118 | 118 | |
| 119 | 119 | terminate_handler |
| 120 | set_terminate(terminate_handler func) _NOEXCEPT | |
| 120 | set_terminate(terminate_handler func) noexcept | |
| 121 | 121 | { |
| 122 | 122 | if (func == 0) |
| 123 | 123 | func = default_terminate_handler; |
lib/libcxxabi/src/cxa_exception.cpp+2-2| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | #include "include/atomic_support.h" |
| 21 | 21 | |
| 22 | 22 | #if __has_feature(address_sanitizer) |
| 23 | extern "C" void __asan_handle_no_return(void); | |
| 23 | #include <sanitizer/asan_interface.h> | |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | 26 | // +---------------------------+-----------------------------+---------------+ |
| ... | ... | @@ -384,7 +384,7 @@ asm ( |
| 384 | 384 | "	bl	abort\n" |
| 385 | 385 | "	.popsection" |
| 386 | 386 | ); |
| 387 | #endif // defined(_LIBCXXABI_ARM_EHABI) | |
| 387 | #endif // defined(_LIBCXXABI_ARM_EHABI) | |
| 388 | 388 | |
| 389 | 389 | /* |
| 390 | 390 | This routine can catch foreign or native exceptions. If native, the exception |
lib/libcxxabi/src/cxa_exception.h+1-1| ... | ... | @@ -161,4 +161,4 @@ extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * depen |
| 161 | 161 | |
| 162 | 162 | } // namespace __cxxabiv1 |
| 163 | 163 | |
| 164 | #endif // _CXA_EXCEPTION_H | |
| 164 | #endif // _CXA_EXCEPTION_H |
lib/libcxxabi/src/cxa_handlers.cpp+8-8| ... | ... | @@ -23,7 +23,7 @@ namespace std |
| 23 | 23 | { |
| 24 | 24 | |
| 25 | 25 | unexpected_handler |
| 26 | get_unexpected() _NOEXCEPT | |
| 26 | get_unexpected() noexcept | |
| 27 | 27 | { |
| 28 | 28 | return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire); |
| 29 | 29 | } |
| ... | ... | @@ -44,18 +44,18 @@ unexpected() |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | terminate_handler |
| 47 | get_terminate() _NOEXCEPT | |
| 47 | get_terminate() noexcept | |
| 48 | 48 | { |
| 49 | 49 | return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | void |
| 53 | __terminate(terminate_handler func) _NOEXCEPT | |
| 53 | __terminate(terminate_handler func) noexcept | |
| 54 | 54 | { |
| 55 | 55 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 56 | 56 | try |
| 57 | 57 | { |
| 58 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 58 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 59 | 59 | func(); |
| 60 | 60 | // handler should not return |
| 61 | 61 | abort_message("terminate_handler unexpectedly returned"); |
| ... | ... | @@ -66,12 +66,12 @@ __terminate(terminate_handler func) _NOEXCEPT |
| 66 | 66 | // handler should not throw exception |
| 67 | 67 | abort_message("terminate_handler unexpectedly threw an exception"); |
| 68 | 68 | } |
| 69 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 69 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | __attribute__((noreturn)) |
| 73 | 73 | void |
| 74 | terminate() _NOEXCEPT | |
| 74 | terminate() noexcept | |
| 75 | 75 | { |
| 76 | 76 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 77 | 77 | // If there might be an uncaught exception |
| ... | ... | @@ -97,13 +97,13 @@ new_handler __cxa_new_handler = 0; |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | new_handler |
| 100 | set_new_handler(new_handler handler) _NOEXCEPT | |
| 100 | set_new_handler(new_handler handler) noexcept | |
| 101 | 101 | { |
| 102 | 102 | return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel); |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | 105 | new_handler |
| 106 | get_new_handler() _NOEXCEPT | |
| 106 | get_new_handler() noexcept | |
| 107 | 107 | { |
| 108 | 108 | return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire); |
| 109 | 109 | } |
lib/libcxxabi/src/cxa_handlers.h+2-2| ... | ... | @@ -25,7 +25,7 @@ __unexpected(unexpected_handler func); |
| 25 | 25 | |
| 26 | 26 | _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN |
| 27 | 27 | void |
| 28 | __terminate(terminate_handler func) _NOEXCEPT; | |
| 28 | __terminate(terminate_handler func) noexcept; | |
| 29 | 29 | |
| 30 | 30 | } // std |
| 31 | 31 | |
| ... | ... | @@ -52,4 +52,4 @@ _LIBCXXABI_DATA_VIS extern void (*__cxa_new_handler)(); |
| 52 | 52 | |
| 53 | 53 | } // extern "C" |
| 54 | 54 | |
| 55 | #endif // _CXA_HANDLERS_H | |
| 55 | #endif // _CXA_HANDLERS_H |
lib/libcxxabi/src/cxa_personality.cpp+74-19| ... | ... | @@ -88,7 +88,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, |
| 88 | 88 | | +-------------+---------------------------------+------------------------------+ | |
| 89 | 89 | | ... | |
| 90 | 90 | +----------------------------------------------------------------------------------+ |
| 91 | #endif // __USING_SJLJ_EXCEPTIONS__ | |
| 91 | #endif // __USING_SJLJ_EXCEPTIONS__ | |
| 92 | 92 | +---------------------------------------------------------------------+ |
| 93 | 93 | | Beginning of Action Table ttypeIndex == 0 : cleanup | |
| 94 | 94 | | ... ttypeIndex > 0 : catch | |
| ... | ... | @@ -241,10 +241,11 @@ readSLEB128(const uint8_t** data) |
| 241 | 241 | /// @link http://dwarfstd.org/Dwarf3.pdf @unlink |
| 242 | 242 | /// @param data reference variable holding memory pointer to decode from |
| 243 | 243 | /// @param encoding dwarf encoding type |
| 244 | /// @param base for adding relative offset, default to 0 | |
| 244 | 245 | /// @returns decoded value |
| 245 | 246 | static |
| 246 | 247 | uintptr_t |
| 247 | readEncodedPointer(const uint8_t** data, uint8_t encoding) | |
| 248 | readEncodedPointer(const uint8_t** data, uint8_t encoding, uintptr_t base = 0) | |
| 248 | 249 | { |
| 249 | 250 | uintptr_t result = 0; |
| 250 | 251 | if (encoding == DW_EH_PE_omit) |
| ... | ... | @@ -295,8 +296,12 @@ readEncodedPointer(const uint8_t** data, uint8_t encoding) |
| 295 | 296 | if (result) |
| 296 | 297 | result += (uintptr_t)(*data); |
| 297 | 298 | break; |
| 298 | case DW_EH_PE_textrel: | |
| 299 | 299 | case DW_EH_PE_datarel: |
| 300 | assert((base != 0) && "DW_EH_PE_datarel is invalid with a base of 0"); | |
| 301 | if (result) | |
| 302 | result += base; | |
| 303 | break; | |
| 304 | case DW_EH_PE_textrel: | |
| 300 | 305 | case DW_EH_PE_funcrel: |
| 301 | 306 | case DW_EH_PE_aligned: |
| 302 | 307 | default: |
| ... | ... | @@ -348,7 +353,7 @@ static const void* read_target2_value(const void* ptr) |
| 348 | 353 | static const __shim_type_info* |
| 349 | 354 | get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, |
| 350 | 355 | uint8_t ttypeEncoding, bool native_exception, |
| 351 | _Unwind_Exception* unwind_exception) | |
| 356 | _Unwind_Exception* unwind_exception, uintptr_t /*base*/ = 0) | |
| 352 | 357 | { |
| 353 | 358 | if (classInfo == 0) |
| 354 | 359 | { |
| ... | ... | @@ -371,7 +376,7 @@ static |
| 371 | 376 | const __shim_type_info* |
| 372 | 377 | get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, |
| 373 | 378 | uint8_t ttypeEncoding, bool native_exception, |
| 374 | _Unwind_Exception* unwind_exception) | |
| 379 | _Unwind_Exception* unwind_exception, uintptr_t base = 0) | |
| 375 | 380 | { |
| 376 | 381 | if (classInfo == 0) |
| 377 | 382 | { |
| ... | ... | @@ -400,7 +405,8 @@ get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo, |
| 400 | 405 | call_terminate(native_exception, unwind_exception); |
| 401 | 406 | } |
| 402 | 407 | classInfo -= ttypeIndex; |
| 403 | return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding); | |
| 408 | return (const __shim_type_info*)readEncodedPointer(&classInfo, | |
| 409 | ttypeEncoding, base); | |
| 404 | 410 | } |
| 405 | 411 | #endif // !defined(_LIBCXXABI_ARM_EHABI) |
| 406 | 412 | |
| ... | ... | @@ -418,7 +424,8 @@ static |
| 418 | 424 | bool |
| 419 | 425 | exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, |
| 420 | 426 | uint8_t ttypeEncoding, const __shim_type_info* excpType, |
| 421 | void* adjustedPtr, _Unwind_Exception* unwind_exception) | |
| 427 | void* adjustedPtr, _Unwind_Exception* unwind_exception, | |
| 428 | uintptr_t /*base*/ = 0) | |
| 422 | 429 | { |
| 423 | 430 | if (classInfo == 0) |
| 424 | 431 | { |
| ... | ... | @@ -463,7 +470,8 @@ static |
| 463 | 470 | bool |
| 464 | 471 | exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, |
| 465 | 472 | uint8_t ttypeEncoding, const __shim_type_info* excpType, |
| 466 | void* adjustedPtr, _Unwind_Exception* unwind_exception) | |
| 473 | void* adjustedPtr, _Unwind_Exception* unwind_exception, | |
| 474 | uintptr_t base = 0) | |
| 467 | 475 | { |
| 468 | 476 | if (classInfo == 0) |
| 469 | 477 | { |
| ... | ... | @@ -485,7 +493,8 @@ exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, |
| 485 | 493 | classInfo, |
| 486 | 494 | ttypeEncoding, |
| 487 | 495 | true, |
| 488 | unwind_exception); | |
| 496 | unwind_exception, | |
| 497 | base); | |
| 489 | 498 | void* tempPtr = adjustedPtr; |
| 490 | 499 | if (catchType->can_catch(excpType, tempPtr)) |
| 491 | 500 | return false; |
| ... | ... | @@ -531,6 +540,9 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, |
| 531 | 540 | { |
| 532 | 541 | #if defined(__USING_SJLJ_EXCEPTIONS__) |
| 533 | 542 | #define __builtin_eh_return_data_regno(regno) regno |
| 543 | #elif defined(__ibmxl__) | |
| 544 | // IBM xlclang++ compiler does not support __builtin_eh_return_data_regno. | |
| 545 | #define __builtin_eh_return_data_regno(regno) regno + 3 | |
| 534 | 546 | #endif |
| 535 | 547 | _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), |
| 536 | 548 | reinterpret_cast<uintptr_t>(unwind_exception)); |
| ... | ... | @@ -610,6 +622,11 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| 610 | 622 | return; |
| 611 | 623 | } |
| 612 | 624 | results.languageSpecificData = lsda; |
| 625 | #if defined(_AIX) | |
| 626 | uintptr_t base = _Unwind_GetDataRelBase(context); | |
| 627 | #else | |
| 628 | uintptr_t base = 0; | |
| 629 | #endif | |
| 613 | 630 | // Get the current instruction pointer and offset it before next |
| 614 | 631 | // instruction in the current frame which threw the exception. |
| 615 | 632 | uintptr_t ip = _Unwind_GetIP(context) - 1; |
| ... | ... | @@ -628,13 +645,14 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| 628 | 645 | // ip is 1-based index into call site table |
| 629 | 646 | #else // !__USING_SJLJ_EXCEPTIONS__ |
| 630 | 647 | uintptr_t ipOffset = ip - funcStart; |
| 631 | #endif // !defined(_USING_SLJL_EXCEPTIONS__) | |
| 648 | #endif // !defined(_USING_SLJL_EXCEPTIONS__) | |
| 632 | 649 | const uint8_t* classInfo = NULL; |
| 633 | 650 | // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding |
| 634 | 651 | // dwarf emission |
| 635 | 652 | // Parse LSDA header. |
| 636 | 653 | uint8_t lpStartEncoding = *lsda++; |
| 637 | const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); | |
| 654 | const uint8_t* lpStart = | |
| 655 | (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base); | |
| 638 | 656 | if (lpStart == 0) |
| 639 | 657 | lpStart = (const uint8_t*)funcStart; |
| 640 | 658 | uint8_t ttypeEncoding = *lsda++; |
| ... | ... | @@ -673,7 +691,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| 673 | 691 | uintptr_t landingPad = readULEB128(&callSitePtr); |
| 674 | 692 | uintptr_t actionEntry = readULEB128(&callSitePtr); |
| 675 | 693 | if (--ip == 0) |
| 676 | #endif // __USING_SJLJ_EXCEPTIONS__ | |
| 694 | #endif // __USING_SJLJ_EXCEPTIONS__ | |
| 677 | 695 | { |
| 678 | 696 | // Found the call site containing ip. |
| 679 | 697 | #ifndef __USING_SJLJ_EXCEPTIONS__ |
| ... | ... | @@ -687,7 +705,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| 687 | 705 | results.landingPad = landingPad; |
| 688 | 706 | #else // __USING_SJLJ_EXCEPTIONS__ |
| 689 | 707 | ++landingPad; |
| 690 | #endif // __USING_SJLJ_EXCEPTIONS__ | |
| 708 | #endif // __USING_SJLJ_EXCEPTIONS__ | |
| 691 | 709 | if (actionEntry == 0) |
| 692 | 710 | { |
| 693 | 711 | // Found a cleanup |
| ... | ... | @@ -711,7 +729,8 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| 711 | 729 | const __shim_type_info* catchType = |
| 712 | 730 | get_shim_type_info(static_cast<uint64_t>(ttypeIndex), |
| 713 | 731 | classInfo, ttypeEncoding, |
| 714 | native_exception, unwind_exception); | |
| 732 | native_exception, unwind_exception, | |
| 733 | base); | |
| 715 | 734 | if (catchType == 0) |
| 716 | 735 | { |
| 717 | 736 | // Found catch (...) catches everything, including |
| ... | ... | @@ -772,7 +791,8 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| 772 | 791 | } |
| 773 | 792 | if (exception_spec_can_catch(ttypeIndex, classInfo, |
| 774 | 793 | ttypeEncoding, excpType, |
| 775 | adjustedPtr, unwind_exception)) | |
| 794 | adjustedPtr, | |
| 795 | unwind_exception, base)) | |
| 776 | 796 | { |
| 777 | 797 | // Native exception caught by exception |
| 778 | 798 | // specification. |
| ... | ... | @@ -820,7 +840,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, |
| 820 | 840 | // Possible stack corruption. |
| 821 | 841 | call_terminate(native_exception, unwind_exception); |
| 822 | 842 | } |
| 823 | #endif // !__USING_SJLJ_EXCEPTIONS__ | |
| 843 | #endif // !__USING_SJLJ_EXCEPTIONS__ | |
| 824 | 844 | } // there might be some tricky cases which break out of this loop |
| 825 | 845 | |
| 826 | 846 | // It is possible that no eh table entry specify how to handle |
| ... | ... | @@ -911,6 +931,15 @@ __gxx_personality_v0 |
| 911 | 931 | |
| 912 | 932 | // Jump to the handler. |
| 913 | 933 | set_registers(unwind_exception, context, results); |
| 934 | // Cache base for calculating the address of ttype in | |
| 935 | // __cxa_call_unexpected. | |
| 936 | if (results.ttypeIndex < 0) { | |
| 937 | #if defined(_AIX) | |
| 938 | exception_header->catchTemp = (void *)_Unwind_GetDataRelBase(context); | |
| 939 | #else | |
| 940 | exception_header->catchTemp = 0; | |
| 941 | #endif | |
| 942 | } | |
| 914 | 943 | return _URC_INSTALL_CONTEXT; |
| 915 | 944 | } |
| 916 | 945 | |
| ... | ... | @@ -940,6 +969,16 @@ __gxx_personality_v0 |
| 940 | 969 | assert(actions & _UA_CLEANUP_PHASE); |
| 941 | 970 | assert(results.reason == _URC_HANDLER_FOUND); |
| 942 | 971 | set_registers(unwind_exception, context, results); |
| 972 | // Cache base for calculating the address of ttype in __cxa_call_unexpected. | |
| 973 | if (results.ttypeIndex < 0) { | |
| 974 | __cxa_exception* exception_header = | |
| 975 | (__cxa_exception*)(unwind_exception + 1) - 1; | |
| 976 | #if defined(_AIX) | |
| 977 | exception_header->catchTemp = (void *)_Unwind_GetDataRelBase(context); | |
| 978 | #else | |
| 979 | exception_header->catchTemp = 0; | |
| 980 | #endif | |
| 981 | } | |
| 943 | 982 | return _URC_INSTALL_CONTEXT; |
| 944 | 983 | } |
| 945 | 984 | |
| ... | ... | @@ -1114,6 +1153,8 @@ __cxa_call_unexpected(void* arg) |
| 1114 | 1153 | __cxa_exception* old_exception_header = 0; |
| 1115 | 1154 | int64_t ttypeIndex; |
| 1116 | 1155 | const uint8_t* lsda; |
| 1156 | uintptr_t base = 0; | |
| 1157 | ||
| 1117 | 1158 | if (native_old_exception) |
| 1118 | 1159 | { |
| 1119 | 1160 | old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1; |
| ... | ... | @@ -1127,6 +1168,7 @@ __cxa_call_unexpected(void* arg) |
| 1127 | 1168 | #else |
| 1128 | 1169 | ttypeIndex = old_exception_header->handlerSwitchValue; |
| 1129 | 1170 | lsda = old_exception_header->languageSpecificData; |
| 1171 | base = (uintptr_t)old_exception_header->catchTemp; | |
| 1130 | 1172 | #endif |
| 1131 | 1173 | } |
| 1132 | 1174 | else |
| ... | ... | @@ -1150,11 +1192,13 @@ __cxa_call_unexpected(void* arg) |
| 1150 | 1192 | // Have: |
| 1151 | 1193 | // old_exception_header->languageSpecificData |
| 1152 | 1194 | // old_exception_header->actionRecord |
| 1195 | // old_exception_header->catchTemp, base for calculating ttype | |
| 1153 | 1196 | // Need |
| 1154 | 1197 | // const uint8_t* classInfo |
| 1155 | 1198 | // uint8_t ttypeEncoding |
| 1156 | 1199 | uint8_t lpStartEncoding = *lsda++; |
| 1157 | const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); | |
| 1200 | const uint8_t* lpStart = | |
| 1201 | (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base); | |
| 1158 | 1202 | (void)lpStart; // purposefully unused. Just needed to increment lsda. |
| 1159 | 1203 | uint8_t ttypeEncoding = *lsda++; |
| 1160 | 1204 | if (ttypeEncoding == DW_EH_PE_omit) |
| ... | ... | @@ -1181,7 +1225,8 @@ __cxa_call_unexpected(void* arg) |
| 1181 | 1225 | ((__cxa_dependent_exception*)new_exception_header)->primaryException : |
| 1182 | 1226 | new_exception_header + 1; |
| 1183 | 1227 | if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, |
| 1184 | excpType, adjustedPtr, unwind_exception)) | |
| 1228 | excpType, adjustedPtr, | |
| 1229 | unwind_exception, base)) | |
| 1185 | 1230 | { |
| 1186 | 1231 | // We need to __cxa_end_catch, but for the old exception, |
| 1187 | 1232 | // not the new one. This is a little tricky ... |
| ... | ... | @@ -1210,7 +1255,8 @@ __cxa_call_unexpected(void* arg) |
| 1210 | 1255 | std::bad_exception be; |
| 1211 | 1256 | adjustedPtr = &be; |
| 1212 | 1257 | if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, |
| 1213 | excpType, adjustedPtr, unwind_exception)) | |
| 1258 | excpType, adjustedPtr, | |
| 1259 | unwind_exception, base)) | |
| 1214 | 1260 | { |
| 1215 | 1261 | // We need to __cxa_end_catch for both the old exception and the |
| 1216 | 1262 | // new exception. Technically we should do it in that order. |
| ... | ... | @@ -1226,6 +1272,15 @@ __cxa_call_unexpected(void* arg) |
| 1226 | 1272 | std::__terminate(t_handler); |
| 1227 | 1273 | } |
| 1228 | 1274 | |
| 1275 | #if defined(_AIX) | |
| 1276 | // Personality routine for EH using the range table. Make it an alias of | |
| 1277 | // __gxx_personality_v0(). | |
| 1278 | _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1( | |
| 1279 | int version, _Unwind_Action actions, uint64_t exceptionClass, | |
| 1280 | _Unwind_Exception* unwind_exception, _Unwind_Context* context) | |
| 1281 | __attribute__((__alias__("__gxx_personality_v0"))); | |
| 1282 | #endif | |
| 1283 | ||
| 1229 | 1284 | } // extern "C" |
| 1230 | 1285 | |
| 1231 | 1286 | } // __cxxabiv1 |
lib/libcxxabi/src/demangle/ItaniumDemangle.h+19-7| ... | ... | @@ -280,17 +280,20 @@ public: |
| 280 | 280 | class VendorExtQualType final : public Node { |
| 281 | 281 | const Node *Ty; |
| 282 | 282 | StringView Ext; |
| 283 | const Node *TA; | |
| 283 | 284 | |
| 284 | 285 | public: |
| 285 | VendorExtQualType(const Node *Ty_, StringView Ext_) | |
| 286 | : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {} | |
| 286 | VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_) | |
| 287 | : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {} | |
| 287 | 288 | |
| 288 | template<typename Fn> void match(Fn F) const { F(Ty, Ext); } | |
| 289 | template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); } | |
| 289 | 290 | |
| 290 | 291 | void printLeft(OutputStream &S) const override { |
| 291 | 292 | Ty->print(S); |
| 292 | 293 | S += " "; |
| 293 | 294 | S += Ext; |
| 295 | if (TA != nullptr) | |
| 296 | TA->print(S); | |
| 294 | 297 | } |
| 295 | 298 | }; |
| 296 | 299 | |
| ... | ... | @@ -3680,8 +3683,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() { |
| 3680 | 3683 | if (Qual.empty()) |
| 3681 | 3684 | return nullptr; |
| 3682 | 3685 | |
| 3683 | // FIXME parse the optional <template-args> here! | |
| 3684 | ||
| 3685 | 3686 | // extension ::= U <objc-name> <objc-type> # objc-type<identifier> |
| 3686 | 3687 | if (Qual.startsWith("objcproto")) { |
| 3687 | 3688 | StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto")); |
| ... | ... | @@ -3699,10 +3700,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() { |
| 3699 | 3700 | return make<ObjCProtoName>(Child, Proto); |
| 3700 | 3701 | } |
| 3701 | 3702 | |
| 3703 | Node *TA = nullptr; | |
| 3704 | if (look() == 'I') { | |
| 3705 | TA = getDerived().parseTemplateArgs(); | |
| 3706 | if (TA == nullptr) | |
| 3707 | return nullptr; | |
| 3708 | } | |
| 3709 | ||
| 3702 | 3710 | Node *Child = getDerived().parseQualifiedType(); |
| 3703 | 3711 | if (Child == nullptr) |
| 3704 | 3712 | return nullptr; |
| 3705 | return make<VendorExtQualType>(Child, Qual); | |
| 3713 | return make<VendorExtQualType>(Child, Qual, TA); | |
| 3706 | 3714 | } |
| 3707 | 3715 | |
| 3708 | 3716 | Qualifiers Quals = parseCVQualifiers(); |
| ... | ... | @@ -3875,7 +3883,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { |
| 3875 | 3883 | // ::= Dh # IEEE 754r half-precision floating point (16 bits) |
| 3876 | 3884 | case 'h': |
| 3877 | 3885 | First += 2; |
| 3878 | return make<NameType>("decimal16"); | |
| 3886 | return make<NameType>("half"); | |
| 3879 | 3887 | // ::= Di # char32_t |
| 3880 | 3888 | case 'i': |
| 3881 | 3889 | First += 2; |
| ... | ... | @@ -5227,14 +5235,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() { |
| 5227 | 5235 | class SaveTemplateParams { |
| 5228 | 5236 | AbstractManglingParser *Parser; |
| 5229 | 5237 | decltype(TemplateParams) OldParams; |
| 5238 | decltype(OuterTemplateParams) OldOuterParams; | |
| 5230 | 5239 | |
| 5231 | 5240 | public: |
| 5232 | 5241 | SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) { |
| 5233 | 5242 | OldParams = std::move(Parser->TemplateParams); |
| 5243 | OldOuterParams = std::move(Parser->OuterTemplateParams); | |
| 5234 | 5244 | Parser->TemplateParams.clear(); |
| 5245 | Parser->OuterTemplateParams.clear(); | |
| 5235 | 5246 | } |
| 5236 | 5247 | ~SaveTemplateParams() { |
| 5237 | 5248 | Parser->TemplateParams = std::move(OldParams); |
| 5249 | Parser->OuterTemplateParams = std::move(OldOuterParams); | |
| 5238 | 5250 | } |
| 5239 | 5251 | } SaveTemplateParams(this); |
| 5240 | 5252 |
lib/libcxxabi/src/demangle/StringView.h+3-10| ... | ... | @@ -36,8 +36,9 @@ public: |
| 36 | 36 | StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {} |
| 37 | 37 | StringView() : First(nullptr), Last(nullptr) {} |
| 38 | 38 | |
| 39 | StringView substr(size_t From) const { | |
| 40 | return StringView(begin() + From, size() - From); | |
| 39 | StringView substr(size_t Pos, size_t Len = npos) const { | |
| 40 | assert(Pos <= size()); | |
| 41 | return StringView(begin() + Pos, std::min(Len, size() - Pos)); | |
| 41 | 42 | } |
| 42 | 43 | |
| 43 | 44 | size_t find(char C, size_t From = 0) const { |
| ... | ... | @@ -51,14 +52,6 @@ public: |
| 51 | 52 | return npos; |
| 52 | 53 | } |
| 53 | 54 | |
| 54 | StringView substr(size_t From, size_t To) const { | |
| 55 | if (To >= size()) | |
| 56 | To = size() - 1; | |
| 57 | if (From >= size()) | |
| 58 | From = size() - 1; | |
| 59 | return StringView(First + From, First + To); | |
| 60 | } | |
| 61 | ||
| 62 | 55 | StringView dropFront(size_t N = 1) const { |
| 63 | 56 | if (N >= size()) |
| 64 | 57 | N = size(); |
lib/libcxxabi/src/private_typeinfo.cpp+2-2| ... | ... | @@ -679,7 +679,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, |
| 679 | 679 | info.number_of_dst_type = 1; |
| 680 | 680 | dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true); |
| 681 | 681 | } |
| 682 | #endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST | |
| 682 | #endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST | |
| 683 | 683 | // Query the search. |
| 684 | 684 | if (info.path_dst_ptr_to_static_ptr == public_path) |
| 685 | 685 | dst_ptr = dynamic_ptr; |
| ... | ... | @@ -707,7 +707,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, |
| 707 | 707 | info = {dst_type, static_ptr, static_type, src2dst_offset, 0}; |
| 708 | 708 | dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true); |
| 709 | 709 | } |
| 710 | #endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST | |
| 710 | #endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST | |
| 711 | 711 | // Query the search. |
| 712 | 712 | switch (info.number_to_static_ptr) |
| 713 | 713 | { |
lib/libcxxabi/src/private_typeinfo.h+1-1| ... | ... | @@ -248,4 +248,4 @@ public: |
| 248 | 248 | |
| 249 | 249 | } // __cxxabiv1 |
| 250 | 250 | |
| 251 | #endif // __PRIVATE_TYPEINFO_H_ | |
| 251 | #endif // __PRIVATE_TYPEINFO_H_ |
lib/libcxxabi/src/stdlib_exception.cpp+10-10| ... | ... | @@ -14,22 +14,22 @@ namespace std |
| 14 | 14 | |
| 15 | 15 | // exception |
| 16 | 16 | |
| 17 | exception::~exception() _NOEXCEPT | |
| 17 | exception::~exception() noexcept | |
| 18 | 18 | { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | const char* exception::what() const _NOEXCEPT | |
| 21 | const char* exception::what() const noexcept | |
| 22 | 22 | { |
| 23 | 23 | return "std::exception"; |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | // bad_exception |
| 27 | 27 | |
| 28 | bad_exception::~bad_exception() _NOEXCEPT | |
| 28 | bad_exception::~bad_exception() noexcept | |
| 29 | 29 | { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | const char* bad_exception::what() const _NOEXCEPT | |
| 32 | const char* bad_exception::what() const noexcept | |
| 33 | 33 | { |
| 34 | 34 | return "std::bad_exception"; |
| 35 | 35 | } |
| ... | ... | @@ -37,32 +37,32 @@ const char* bad_exception::what() const _NOEXCEPT |
| 37 | 37 | |
| 38 | 38 | // bad_alloc |
| 39 | 39 | |
| 40 | bad_alloc::bad_alloc() _NOEXCEPT | |
| 40 | bad_alloc::bad_alloc() noexcept | |
| 41 | 41 | { |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | bad_alloc::~bad_alloc() _NOEXCEPT | |
| 44 | bad_alloc::~bad_alloc() noexcept | |
| 45 | 45 | { |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | const char* |
| 49 | bad_alloc::what() const _NOEXCEPT | |
| 49 | bad_alloc::what() const noexcept | |
| 50 | 50 | { |
| 51 | 51 | return "std::bad_alloc"; |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | // bad_array_new_length |
| 55 | 55 | |
| 56 | bad_array_new_length::bad_array_new_length() _NOEXCEPT | |
| 56 | bad_array_new_length::bad_array_new_length() noexcept | |
| 57 | 57 | { |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | bad_array_new_length::~bad_array_new_length() _NOEXCEPT | |
| 60 | bad_array_new_length::~bad_array_new_length() noexcept | |
| 61 | 61 | { |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | const char* |
| 65 | bad_array_new_length::what() const _NOEXCEPT | |
| 65 | bad_array_new_length::what() const noexcept | |
| 66 | 66 | { |
| 67 | 67 | return "bad_array_new_length"; |
| 68 | 68 | } |
lib/libcxxabi/src/stdlib_new_delete.cpp+26-26| ... | ... | @@ -12,8 +12,8 @@ |
| 12 | 12 | #include <new> |
| 13 | 13 | #include <cstdlib> |
| 14 | 14 | |
| 15 | #if !defined(_THROW_BAD_ALLOC) || !defined(_NOEXCEPT) || !defined(_LIBCXXABI_WEAK) | |
| 16 | #error The _THROW_BAD_ALLOC, _NOEXCEPT, and _LIBCXXABI_WEAK libc++ macros must \ | |
| 15 | #if !defined(_THROW_BAD_ALLOC) || !defined(_LIBCXXABI_WEAK) | |
| 16 | #error The _THROW_BAD_ALLOC and _LIBCXXABI_WEAK libc++ macros must \ | |
| 17 | 17 | already be defined by libc++. |
| 18 | 18 | #endif |
| 19 | 19 | // Implement all new and delete operators as weak definitions |
| ... | ... | @@ -46,20 +46,20 @@ operator new(std::size_t size) _THROW_BAD_ALLOC |
| 46 | 46 | |
| 47 | 47 | _LIBCXXABI_WEAK |
| 48 | 48 | void* |
| 49 | operator new(size_t size, const std::nothrow_t&) _NOEXCEPT | |
| 49 | operator new(size_t size, const std::nothrow_t&) noexcept | |
| 50 | 50 | { |
| 51 | 51 | void* p = nullptr; |
| 52 | 52 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 53 | 53 | try |
| 54 | 54 | { |
| 55 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 55 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 56 | 56 | p = ::operator new(size); |
| 57 | 57 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 58 | 58 | } |
| 59 | 59 | catch (...) |
| 60 | 60 | { |
| 61 | 61 | } |
| 62 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 62 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 63 | 63 | return p; |
| 64 | 64 | } |
| 65 | 65 | |
| ... | ... | @@ -72,61 +72,61 @@ operator new[](size_t size) _THROW_BAD_ALLOC |
| 72 | 72 | |
| 73 | 73 | _LIBCXXABI_WEAK |
| 74 | 74 | void* |
| 75 | operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT | |
| 75 | operator new[](size_t size, const std::nothrow_t&) noexcept | |
| 76 | 76 | { |
| 77 | 77 | void* p = nullptr; |
| 78 | 78 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 79 | 79 | try |
| 80 | 80 | { |
| 81 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 81 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 82 | 82 | p = ::operator new[](size); |
| 83 | 83 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 84 | 84 | } |
| 85 | 85 | catch (...) |
| 86 | 86 | { |
| 87 | 87 | } |
| 88 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 88 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 89 | 89 | return p; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | 92 | _LIBCXXABI_WEAK |
| 93 | 93 | void |
| 94 | operator delete(void* ptr) _NOEXCEPT | |
| 94 | operator delete(void* ptr) noexcept | |
| 95 | 95 | { |
| 96 | 96 | ::free(ptr); |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | _LIBCXXABI_WEAK |
| 100 | 100 | void |
| 101 | operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT | |
| 101 | operator delete(void* ptr, const std::nothrow_t&) noexcept | |
| 102 | 102 | { |
| 103 | 103 | ::operator delete(ptr); |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 | _LIBCXXABI_WEAK |
| 107 | 107 | void |
| 108 | operator delete(void* ptr, size_t) _NOEXCEPT | |
| 108 | operator delete(void* ptr, size_t) noexcept | |
| 109 | 109 | { |
| 110 | 110 | ::operator delete(ptr); |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | _LIBCXXABI_WEAK |
| 114 | 114 | void |
| 115 | operator delete[] (void* ptr) _NOEXCEPT | |
| 115 | operator delete[] (void* ptr) noexcept | |
| 116 | 116 | { |
| 117 | 117 | ::operator delete(ptr); |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | 120 | _LIBCXXABI_WEAK |
| 121 | 121 | void |
| 122 | operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT | |
| 122 | operator delete[] (void* ptr, const std::nothrow_t&) noexcept | |
| 123 | 123 | { |
| 124 | 124 | ::operator delete[](ptr); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | _LIBCXXABI_WEAK |
| 128 | 128 | void |
| 129 | operator delete[] (void* ptr, size_t) _NOEXCEPT | |
| 129 | operator delete[] (void* ptr, size_t) noexcept | |
| 130 | 130 | { |
| 131 | 131 | ::operator delete[](ptr); |
| 132 | 132 | } |
| ... | ... | @@ -167,20 +167,20 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC |
| 167 | 167 | |
| 168 | 168 | _LIBCXXABI_WEAK |
| 169 | 169 | void* |
| 170 | operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 170 | operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 171 | 171 | { |
| 172 | 172 | void* p = nullptr; |
| 173 | 173 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 174 | 174 | try |
| 175 | 175 | { |
| 176 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 176 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 177 | 177 | p = ::operator new(size, alignment); |
| 178 | 178 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 179 | 179 | } |
| 180 | 180 | catch (...) |
| 181 | 181 | { |
| 182 | 182 | } |
| 183 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 183 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 184 | 184 | return p; |
| 185 | 185 | } |
| 186 | 186 | |
| ... | ... | @@ -193,61 +193,61 @@ operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC |
| 193 | 193 | |
| 194 | 194 | _LIBCXXABI_WEAK |
| 195 | 195 | void* |
| 196 | operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 196 | operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 197 | 197 | { |
| 198 | 198 | void* p = nullptr; |
| 199 | 199 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 200 | 200 | try |
| 201 | 201 | { |
| 202 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 202 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 203 | 203 | p = ::operator new[](size, alignment); |
| 204 | 204 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 205 | 205 | } |
| 206 | 206 | catch (...) |
| 207 | 207 | { |
| 208 | 208 | } |
| 209 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 209 | #endif // _LIBCXXABI_NO_EXCEPTIONS | |
| 210 | 210 | return p; |
| 211 | 211 | } |
| 212 | 212 | |
| 213 | 213 | _LIBCXXABI_WEAK |
| 214 | 214 | void |
| 215 | operator delete(void* ptr, std::align_val_t) _NOEXCEPT | |
| 215 | operator delete(void* ptr, std::align_val_t) noexcept | |
| 216 | 216 | { |
| 217 | 217 | std::__libcpp_aligned_free(ptr); |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | 220 | _LIBCXXABI_WEAK |
| 221 | 221 | void |
| 222 | operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 222 | operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 223 | 223 | { |
| 224 | 224 | ::operator delete(ptr, alignment); |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | 227 | _LIBCXXABI_WEAK |
| 228 | 228 | void |
| 229 | operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT | |
| 229 | operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept | |
| 230 | 230 | { |
| 231 | 231 | ::operator delete(ptr, alignment); |
| 232 | 232 | } |
| 233 | 233 | |
| 234 | 234 | _LIBCXXABI_WEAK |
| 235 | 235 | void |
| 236 | operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT | |
| 236 | operator delete[] (void* ptr, std::align_val_t alignment) noexcept | |
| 237 | 237 | { |
| 238 | 238 | ::operator delete(ptr, alignment); |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | 241 | _LIBCXXABI_WEAK |
| 242 | 242 | void |
| 243 | operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | |
| 243 | operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept | |
| 244 | 244 | { |
| 245 | 245 | ::operator delete[](ptr, alignment); |
| 246 | 246 | } |
| 247 | 247 | |
| 248 | 248 | _LIBCXXABI_WEAK |
| 249 | 249 | void |
| 250 | operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT | |
| 250 | operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept | |
| 251 | 251 | { |
| 252 | 252 | ::operator delete[](ptr, alignment); |
| 253 | 253 | } |
lib/libcxxabi/src/stdlib_stdexcept.cpp+14-12| ... | ... | @@ -6,7 +6,6 @@ |
| 6 | 6 | // |
| 7 | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | |
| 9 | #include "../../libcxx/src/include/refstring.h" | |
| 10 | 9 | #include "stdexcept" |
| 11 | 10 | #include "new" |
| 12 | 11 | #include <cstdlib> |
| ... | ... | @@ -14,34 +13,37 @@ |
| 14 | 13 | #include <cstdint> |
| 15 | 14 | #include <cstddef> |
| 16 | 15 | |
| 16 | // This includes an implementation file from libc++. | |
| 17 | #include "../../libcxx/src/include/refstring.h" | |
| 18 | ||
| 17 | 19 | static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), ""); |
| 18 | 20 | |
| 19 | 21 | namespace std // purposefully not using versioning namespace |
| 20 | 22 | { |
| 21 | 23 | |
| 22 | logic_error::~logic_error() _NOEXCEPT {} | |
| 24 | logic_error::~logic_error() noexcept {} | |
| 23 | 25 | |
| 24 | 26 | const char* |
| 25 | logic_error::what() const _NOEXCEPT | |
| 27 | logic_error::what() const noexcept | |
| 26 | 28 | { |
| 27 | 29 | return __imp_.c_str(); |
| 28 | 30 | } |
| 29 | 31 | |
| 30 | runtime_error::~runtime_error() _NOEXCEPT {} | |
| 32 | runtime_error::~runtime_error() noexcept {} | |
| 31 | 33 | |
| 32 | 34 | const char* |
| 33 | runtime_error::what() const _NOEXCEPT | |
| 35 | runtime_error::what() const noexcept | |
| 34 | 36 | { |
| 35 | 37 | return __imp_.c_str(); |
| 36 | 38 | } |
| 37 | 39 | |
| 38 | domain_error::~domain_error() _NOEXCEPT {} | |
| 39 | invalid_argument::~invalid_argument() _NOEXCEPT {} | |
| 40 | length_error::~length_error() _NOEXCEPT {} | |
| 41 | out_of_range::~out_of_range() _NOEXCEPT {} | |
| 40 | domain_error::~domain_error() noexcept {} | |
| 41 | invalid_argument::~invalid_argument() noexcept {} | |
| 42 | length_error::~length_error() noexcept {} | |
| 43 | out_of_range::~out_of_range() noexcept {} | |
| 42 | 44 | |
| 43 | range_error::~range_error() _NOEXCEPT {} | |
| 44 | overflow_error::~overflow_error() _NOEXCEPT {} | |
| 45 | underflow_error::~underflow_error() _NOEXCEPT {} | |
| 45 | range_error::~range_error() noexcept {} | |
| 46 | overflow_error::~overflow_error() noexcept {} | |
| 47 | underflow_error::~underflow_error() noexcept {} | |
| 46 | 48 | |
| 47 | 49 | } // std |
lib/libcxxabi/src/stdlib_typeinfo.cpp+6-6| ... | ... | @@ -19,32 +19,32 @@ type_info::~type_info() |
| 19 | 19 | |
| 20 | 20 | // bad_cast |
| 21 | 21 | |
| 22 | bad_cast::bad_cast() _NOEXCEPT | |
| 22 | bad_cast::bad_cast() noexcept | |
| 23 | 23 | { |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | bad_cast::~bad_cast() _NOEXCEPT | |
| 26 | bad_cast::~bad_cast() noexcept | |
| 27 | 27 | { |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | 30 | const char* |
| 31 | bad_cast::what() const _NOEXCEPT | |
| 31 | bad_cast::what() const noexcept | |
| 32 | 32 | { |
| 33 | 33 | return "std::bad_cast"; |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | // bad_typeid |
| 37 | 37 | |
| 38 | bad_typeid::bad_typeid() _NOEXCEPT | |
| 38 | bad_typeid::bad_typeid() noexcept | |
| 39 | 39 | { |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | bad_typeid::~bad_typeid() _NOEXCEPT | |
| 42 | bad_typeid::~bad_typeid() noexcept | |
| 43 | 43 | { |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | const char* |
| 47 | bad_typeid::what() const _NOEXCEPT | |
| 47 | bad_typeid::what() const noexcept | |
| 48 | 48 | { |
| 49 | 49 | return "std::bad_typeid"; |
| 50 | 50 | } |
lib/libunwind/include/__libunwind_config.h+12-5| ... | ... | @@ -131,12 +131,19 @@ |
| 131 | 131 | #define _LIBUNWIND_CONTEXT_SIZE 16 |
| 132 | 132 | #define _LIBUNWIND_CURSOR_SIZE 23 |
| 133 | 133 | # elif defined(__riscv) |
| 134 | # if __riscv_xlen == 64 | |
| 135 | # define _LIBUNWIND_TARGET_RISCV 1 | |
| 136 | # define _LIBUNWIND_CONTEXT_SIZE 64 | |
| 137 | # define _LIBUNWIND_CURSOR_SIZE 76 | |
| 134 | # define _LIBUNWIND_TARGET_RISCV 1 | |
| 135 | # if defined(__riscv_flen) | |
| 136 | # define RISCV_FLEN __riscv_flen | |
| 138 | 137 | # else |
| 139 | # error "Unsupported RISC-V ABI" | |
| 138 | # define RISCV_FLEN 0 | |
| 139 | # endif | |
| 140 | # define _LIBUNWIND_CONTEXT_SIZE (32 * (__riscv_xlen + RISCV_FLEN) / 64) | |
| 141 | # if __riscv_xlen == 32 | |
| 142 | # define _LIBUNWIND_CURSOR_SIZE (_LIBUNWIND_CONTEXT_SIZE + 7) | |
| 143 | # elif __riscv_xlen == 64 | |
| 144 | # define _LIBUNWIND_CURSOR_SIZE (_LIBUNWIND_CONTEXT_SIZE + 12) | |
| 145 | # else | |
| 146 | # error "Unsupported RISC-V ABI" | |
| 140 | 147 | # endif |
| 141 | 148 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV |
| 142 | 149 | # elif defined(__ve__) |
lib/libunwind/include/libunwind.h+24-23| ... | ... | @@ -493,16 +493,16 @@ enum { |
| 493 | 493 | |
| 494 | 494 | // 64-bit ARM64 registers |
| 495 | 495 | enum { |
| 496 | UNW_ARM64_X0 = 0, | |
| 497 | UNW_ARM64_X1 = 1, | |
| 498 | UNW_ARM64_X2 = 2, | |
| 499 | UNW_ARM64_X3 = 3, | |
| 500 | UNW_ARM64_X4 = 4, | |
| 501 | UNW_ARM64_X5 = 5, | |
| 502 | UNW_ARM64_X6 = 6, | |
| 503 | UNW_ARM64_X7 = 7, | |
| 504 | UNW_ARM64_X8 = 8, | |
| 505 | UNW_ARM64_X9 = 9, | |
| 496 | UNW_ARM64_X0 = 0, | |
| 497 | UNW_ARM64_X1 = 1, | |
| 498 | UNW_ARM64_X2 = 2, | |
| 499 | UNW_ARM64_X3 = 3, | |
| 500 | UNW_ARM64_X4 = 4, | |
| 501 | UNW_ARM64_X5 = 5, | |
| 502 | UNW_ARM64_X6 = 6, | |
| 503 | UNW_ARM64_X7 = 7, | |
| 504 | UNW_ARM64_X8 = 8, | |
| 505 | UNW_ARM64_X9 = 9, | |
| 506 | 506 | UNW_ARM64_X10 = 10, |
| 507 | 507 | UNW_ARM64_X11 = 11, |
| 508 | 508 | UNW_ARM64_X12 = 12, |
| ... | ... | @@ -523,24 +523,25 @@ enum { |
| 523 | 523 | UNW_ARM64_X27 = 27, |
| 524 | 524 | UNW_ARM64_X28 = 28, |
| 525 | 525 | UNW_ARM64_X29 = 29, |
| 526 | UNW_ARM64_FP = 29, | |
| 526 | UNW_ARM64_FP = 29, | |
| 527 | 527 | UNW_ARM64_X30 = 30, |
| 528 | UNW_ARM64_LR = 30, | |
| 528 | UNW_ARM64_LR = 30, | |
| 529 | 529 | UNW_ARM64_X31 = 31, |
| 530 | UNW_ARM64_SP = 31, | |
| 530 | UNW_ARM64_SP = 31, | |
| 531 | UNW_ARM64_PC = 32, | |
| 531 | 532 | // reserved block |
| 532 | 533 | UNW_ARM64_RA_SIGN_STATE = 34, |
| 533 | 534 | // reserved block |
| 534 | UNW_ARM64_D0 = 64, | |
| 535 | UNW_ARM64_D1 = 65, | |
| 536 | UNW_ARM64_D2 = 66, | |
| 537 | UNW_ARM64_D3 = 67, | |
| 538 | UNW_ARM64_D4 = 68, | |
| 539 | UNW_ARM64_D5 = 69, | |
| 540 | UNW_ARM64_D6 = 70, | |
| 541 | UNW_ARM64_D7 = 71, | |
| 542 | UNW_ARM64_D8 = 72, | |
| 543 | UNW_ARM64_D9 = 73, | |
| 535 | UNW_ARM64_D0 = 64, | |
| 536 | UNW_ARM64_D1 = 65, | |
| 537 | UNW_ARM64_D2 = 66, | |
| 538 | UNW_ARM64_D3 = 67, | |
| 539 | UNW_ARM64_D4 = 68, | |
| 540 | UNW_ARM64_D5 = 69, | |
| 541 | UNW_ARM64_D6 = 70, | |
| 542 | UNW_ARM64_D7 = 71, | |
| 543 | UNW_ARM64_D8 = 72, | |
| 544 | UNW_ARM64_D9 = 73, | |
| 544 | 545 | UNW_ARM64_D10 = 74, |
| 545 | 546 | UNW_ARM64_D11 = 75, |
| 546 | 547 | UNW_ARM64_D12 = 76, |
lib/libunwind/src/DwarfInstructions.hpp+12-5| ... | ... | @@ -167,6 +167,16 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 167 | 167 | |
| 168 | 168 | // restore registers that DWARF says were saved |
| 169 | 169 | R newRegisters = registers; |
| 170 | ||
| 171 | // Typically, the CFA is the stack pointer at the call site in | |
| 172 | // the previous frame. However, there are scenarios in which this is not | |
| 173 | // true. For example, if we switched to a new stack. In that case, the | |
| 174 | // value of the previous SP might be indicated by a CFI directive. | |
| 175 | // | |
| 176 | // We set the SP here to the CFA, allowing for it to be overridden | |
| 177 | // by a CFI directive later on. | |
| 178 | newRegisters.setSP(cfa); | |
| 179 | ||
| 170 | 180 | pint_t returnAddress = 0; |
| 171 | 181 | const int lastReg = R::lastDwarfRegNum(); |
| 172 | 182 | assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg && |
| ... | ... | @@ -200,10 +210,6 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 200 | 210 | } |
| 201 | 211 | } |
| 202 | 212 | |
| 203 | // By definition, the CFA is the stack pointer at the call site, so | |
| 204 | // restoring SP means setting it to CFA. | |
| 205 | newRegisters.setSP(cfa); | |
| 206 | ||
| 207 | 213 | isSignalFrame = cieInfo.isSignalFrame; |
| 208 | 214 | |
| 209 | 215 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| ... | ... | @@ -213,7 +219,8 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 213 | 219 | // restored. autia1716 is used instead of autia as autia1716 assembles |
| 214 | 220 | // to a NOP on pre-v8.3a architectures. |
| 215 | 221 | if ((R::getArch() == REGISTERS_ARM64) && |
| 216 | prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) { | |
| 222 | prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value && | |
| 223 | returnAddress != 0) { | |
| 217 | 224 | #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) |
| 218 | 225 | return UNW_ECROSSRASIGNING; |
| 219 | 226 | #else |
lib/libunwind/src/Registers.hpp+92-31| ... | ... | @@ -1849,31 +1849,39 @@ inline bool Registers_arm64::validRegister(int regNum) const { |
| 1849 | 1849 | return false; |
| 1850 | 1850 | if (regNum == UNW_ARM64_RA_SIGN_STATE) |
| 1851 | 1851 | return true; |
| 1852 | if ((regNum > 31) && (regNum < 64)) | |
| 1852 | if ((regNum > 32) && (regNum < 64)) | |
| 1853 | 1853 | return false; |
| 1854 | 1854 | return true; |
| 1855 | 1855 | } |
| 1856 | 1856 | |
| 1857 | 1857 | inline uint64_t Registers_arm64::getRegister(int regNum) const { |
| 1858 | if (regNum == UNW_REG_IP) | |
| 1858 | if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC) | |
| 1859 | 1859 | return _registers.__pc; |
| 1860 | if (regNum == UNW_REG_SP) | |
| 1860 | if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP) | |
| 1861 | 1861 | return _registers.__sp; |
| 1862 | 1862 | if (regNum == UNW_ARM64_RA_SIGN_STATE) |
| 1863 | 1863 | return _registers.__ra_sign_state; |
| 1864 | if ((regNum >= 0) && (regNum < 32)) | |
| 1864 | if (regNum == UNW_ARM64_FP) | |
| 1865 | return _registers.__fp; | |
| 1866 | if (regNum == UNW_ARM64_LR) | |
| 1867 | return _registers.__lr; | |
| 1868 | if ((regNum >= 0) && (regNum < 29)) | |
| 1865 | 1869 | return _registers.__x[regNum]; |
| 1866 | 1870 | _LIBUNWIND_ABORT("unsupported arm64 register"); |
| 1867 | 1871 | } |
| 1868 | 1872 | |
| 1869 | 1873 | inline void Registers_arm64::setRegister(int regNum, uint64_t value) { |
| 1870 | if (regNum == UNW_REG_IP) | |
| 1874 | if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC) | |
| 1871 | 1875 | _registers.__pc = value; |
| 1872 | else if (regNum == UNW_REG_SP) | |
| 1876 | else if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP) | |
| 1873 | 1877 | _registers.__sp = value; |
| 1874 | 1878 | else if (regNum == UNW_ARM64_RA_SIGN_STATE) |
| 1875 | 1879 | _registers.__ra_sign_state = value; |
| 1876 | else if ((regNum >= 0) && (regNum < 32)) | |
| 1880 | else if (regNum == UNW_ARM64_FP) | |
| 1881 | _registers.__fp = value; | |
| 1882 | else if (regNum == UNW_ARM64_LR) | |
| 1883 | _registers.__lr = value; | |
| 1884 | else if ((regNum >= 0) && (regNum < 29)) | |
| 1877 | 1885 | _registers.__x[regNum] = value; |
| 1878 | 1886 | else |
| 1879 | 1887 | _LIBUNWIND_ABORT("unsupported arm64 register"); |
| ... | ... | @@ -1943,12 +1951,14 @@ inline const char *Registers_arm64::getRegisterName(int regNum) { |
| 1943 | 1951 | return "x27"; |
| 1944 | 1952 | case UNW_ARM64_X28: |
| 1945 | 1953 | return "x28"; |
| 1946 | case UNW_ARM64_X29: | |
| 1954 | case UNW_ARM64_FP: | |
| 1947 | 1955 | return "fp"; |
| 1948 | case UNW_ARM64_X30: | |
| 1956 | case UNW_ARM64_LR: | |
| 1949 | 1957 | return "lr"; |
| 1950 | case UNW_ARM64_X31: | |
| 1958 | case UNW_ARM64_SP: | |
| 1951 | 1959 | return "sp"; |
| 1960 | case UNW_ARM64_PC: | |
| 1961 | return "pc"; | |
| 1952 | 1962 | case UNW_ARM64_D0: |
| 1953 | 1963 | return "d0"; |
| 1954 | 1964 | case UNW_ARM64_D1: |
| ... | ... | @@ -3718,19 +3728,51 @@ inline const char *Registers_hexagon::getRegisterName(int regNum) { |
| 3718 | 3728 | |
| 3719 | 3729 | |
| 3720 | 3730 | #if defined(_LIBUNWIND_TARGET_RISCV) |
| 3721 | /// Registers_riscv holds the register state of a thread in a 64-bit RISC-V | |
| 3731 | /// Registers_riscv holds the register state of a thread in a RISC-V | |
| 3722 | 3732 | /// process. |
| 3733 | ||
| 3734 | // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled. | |
| 3735 | # ifdef __riscv | |
| 3736 | # if __riscv_xlen == 32 | |
| 3737 | typedef uint32_t reg_t; | |
| 3738 | # elif __riscv_xlen == 64 | |
| 3739 | typedef uint64_t reg_t; | |
| 3740 | # else | |
| 3741 | # error "Unsupported __riscv_xlen" | |
| 3742 | # endif | |
| 3743 | ||
| 3744 | # if defined(__riscv_flen) | |
| 3745 | # if __riscv_flen == 64 | |
| 3746 | typedef double fp_t; | |
| 3747 | # elif __riscv_flen == 32 | |
| 3748 | typedef float fp_t; | |
| 3749 | # else | |
| 3750 | # error "Unsupported __riscv_flen" | |
| 3751 | # endif | |
| 3752 | # else | |
| 3753 | // This is just for supressing undeclared error of fp_t. | |
| 3754 | typedef double fp_t; | |
| 3755 | # endif | |
| 3756 | # else | |
| 3757 | // Use Max possible width when cross unwinding | |
| 3758 | typedef uint64_t reg_t; | |
| 3759 | typedef double fp_t; | |
| 3760 | # define __riscv_xlen 64 | |
| 3761 | # define __riscv_flen 64 | |
| 3762 | #endif | |
| 3763 | ||
| 3764 | /// Registers_riscv holds the register state of a thread. | |
| 3723 | 3765 | class _LIBUNWIND_HIDDEN Registers_riscv { |
| 3724 | 3766 | public: |
| 3725 | 3767 | Registers_riscv(); |
| 3726 | 3768 | Registers_riscv(const void *registers); |
| 3727 | 3769 | |
| 3728 | 3770 | bool validRegister(int num) const; |
| 3729 | uint64_t getRegister(int num) const; | |
| 3730 | void setRegister(int num, uint64_t value); | |
| 3771 | reg_t getRegister(int num) const; | |
| 3772 | void setRegister(int num, reg_t value); | |
| 3731 | 3773 | bool validFloatRegister(int num) const; |
| 3732 | double getFloatRegister(int num) const; | |
| 3733 | void setFloatRegister(int num, double value); | |
| 3774 | fp_t getFloatRegister(int num) const; | |
| 3775 | void setFloatRegister(int num, fp_t value); | |
| 3734 | 3776 | bool validVectorRegister(int num) const; |
| 3735 | 3777 | v128 getVectorRegister(int num) const; |
| 3736 | 3778 | void setVectorRegister(int num, v128 value); |
| ... | ... | @@ -3739,31 +3781,45 @@ public: |
| 3739 | 3781 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } |
| 3740 | 3782 | static int getArch() { return REGISTERS_RISCV; } |
| 3741 | 3783 | |
| 3742 | uint64_t getSP() const { return _registers[2]; } | |
| 3743 | void setSP(uint64_t value) { _registers[2] = value; } | |
| 3744 | uint64_t getIP() const { return _registers[0]; } | |
| 3745 | void setIP(uint64_t value) { _registers[0] = value; } | |
| 3784 | reg_t getSP() const { return _registers[2]; } | |
| 3785 | void setSP(reg_t value) { _registers[2] = value; } | |
| 3786 | reg_t getIP() const { return _registers[0]; } | |
| 3787 | void setIP(reg_t value) { _registers[0] = value; } | |
| 3746 | 3788 | |
| 3747 | 3789 | private: |
| 3748 | 3790 | // _registers[0] holds the pc |
| 3749 | uint64_t _registers[32]; | |
| 3750 | double _floats[32]; | |
| 3791 | reg_t _registers[32]; | |
| 3792 | # if defined(__riscv_flen) | |
| 3793 | fp_t _floats[32]; | |
| 3794 | # endif | |
| 3751 | 3795 | }; |
| 3752 | 3796 | |
| 3753 | 3797 | inline Registers_riscv::Registers_riscv(const void *registers) { |
| 3754 | 3798 | static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit), |
| 3755 | 3799 | "riscv registers do not fit into unw_context_t"); |
| 3756 | 3800 | memcpy(&_registers, registers, sizeof(_registers)); |
| 3801 | # if __riscv_xlen == 32 | |
| 3802 | static_assert(sizeof(_registers) == 0x80, | |
| 3803 | "expected float registers to be at offset 128"); | |
| 3804 | # elif __riscv_xlen == 64 | |
| 3757 | 3805 | static_assert(sizeof(_registers) == 0x100, |
| 3758 | 3806 | "expected float registers to be at offset 256"); |
| 3807 | # else | |
| 3808 | # error "Unexpected float registers." | |
| 3809 | # endif | |
| 3810 | ||
| 3811 | # if defined(__riscv_flen) | |
| 3759 | 3812 | memcpy(_floats, |
| 3760 | 3813 | static_cast<const uint8_t *>(registers) + sizeof(_registers), |
| 3761 | 3814 | sizeof(_floats)); |
| 3815 | # endif | |
| 3762 | 3816 | } |
| 3763 | 3817 | |
| 3764 | 3818 | inline Registers_riscv::Registers_riscv() { |
| 3765 | 3819 | memset(&_registers, 0, sizeof(_registers)); |
| 3820 | # if defined(__riscv_flen) | |
| 3766 | 3821 | memset(&_floats, 0, sizeof(_floats)); |
| 3822 | # endif | |
| 3767 | 3823 | } |
| 3768 | 3824 | |
| 3769 | 3825 | inline bool Registers_riscv::validRegister(int regNum) const { |
| ... | ... | @@ -3778,7 +3834,7 @@ inline bool Registers_riscv::validRegister(int regNum) const { |
| 3778 | 3834 | return true; |
| 3779 | 3835 | } |
| 3780 | 3836 | |
| 3781 | inline uint64_t Registers_riscv::getRegister(int regNum) const { | |
| 3837 | inline reg_t Registers_riscv::getRegister(int regNum) const { | |
| 3782 | 3838 | if (regNum == UNW_REG_IP) |
| 3783 | 3839 | return _registers[0]; |
| 3784 | 3840 | if (regNum == UNW_REG_SP) |
| ... | ... | @@ -3790,7 +3846,7 @@ inline uint64_t Registers_riscv::getRegister(int regNum) const { |
| 3790 | 3846 | _LIBUNWIND_ABORT("unsupported riscv register"); |
| 3791 | 3847 | } |
| 3792 | 3848 | |
| 3793 | inline void Registers_riscv::setRegister(int regNum, uint64_t value) { | |
| 3849 | inline void Registers_riscv::setRegister(int regNum, reg_t value) { | |
| 3794 | 3850 | if (regNum == UNW_REG_IP) |
| 3795 | 3851 | _registers[0] = value; |
| 3796 | 3852 | else if (regNum == UNW_REG_SP) |
| ... | ... | @@ -3944,32 +4000,37 @@ inline const char *Registers_riscv::getRegisterName(int regNum) { |
| 3944 | 4000 | } |
| 3945 | 4001 | |
| 3946 | 4002 | inline bool Registers_riscv::validFloatRegister(int regNum) const { |
| 4003 | # if defined(__riscv_flen) | |
| 3947 | 4004 | if (regNum < UNW_RISCV_F0) |
| 3948 | 4005 | return false; |
| 3949 | 4006 | if (regNum > UNW_RISCV_F31) |
| 3950 | 4007 | return false; |
| 3951 | 4008 | return true; |
| 4009 | # else | |
| 4010 | (void)regNum; | |
| 4011 | return false; | |
| 4012 | # endif | |
| 3952 | 4013 | } |
| 3953 | 4014 | |
| 3954 | inline double Registers_riscv::getFloatRegister(int regNum) const { | |
| 3955 | #if defined(__riscv_flen) && __riscv_flen == 64 | |
| 4015 | inline fp_t Registers_riscv::getFloatRegister(int regNum) const { | |
| 4016 | # if defined(__riscv_flen) | |
| 3956 | 4017 | assert(validFloatRegister(regNum)); |
| 3957 | 4018 | return _floats[regNum - UNW_RISCV_F0]; |
| 3958 | #else | |
| 4019 | # else | |
| 3959 | 4020 | (void)regNum; |
| 3960 | 4021 | _LIBUNWIND_ABORT("libunwind not built with float support"); |
| 3961 | #endif | |
| 4022 | # endif | |
| 3962 | 4023 | } |
| 3963 | 4024 | |
| 3964 | inline void Registers_riscv::setFloatRegister(int regNum, double value) { | |
| 3965 | #if defined(__riscv_flen) && __riscv_flen == 64 | |
| 4025 | inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) { | |
| 4026 | # if defined(__riscv_flen) | |
| 3966 | 4027 | assert(validFloatRegister(regNum)); |
| 3967 | 4028 | _floats[regNum - UNW_RISCV_F0] = value; |
| 3968 | #else | |
| 4029 | # else | |
| 3969 | 4030 | (void)regNum; |
| 3970 | 4031 | (void)value; |
| 3971 | 4032 | _LIBUNWIND_ABORT("libunwind not built with float support"); |
| 3972 | #endif | |
| 4033 | # endif | |
| 3973 | 4034 | } |
| 3974 | 4035 | |
| 3975 | 4036 | inline bool Registers_riscv::validVectorRegister(int) const { |
lib/libunwind/src/UnwindCursor.hpp+9-7| ... | ... | @@ -1737,14 +1737,16 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, |
| 1737 | 1737 | else |
| 1738 | 1738 | funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; |
| 1739 | 1739 | if (pc < funcStart) { |
| 1740 | _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " | |
| 1741 | "level compressed unwind table. funcStart=0x%llX", | |
| 1740 | _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX " | |
| 1741 | "not in second level compressed unwind table. " | |
| 1742 | "funcStart=0x%llX", | |
| 1742 | 1743 | (uint64_t) pc, (uint64_t) funcStart); |
| 1743 | 1744 | return false; |
| 1744 | 1745 | } |
| 1745 | 1746 | if (pc > funcEnd) { |
| 1746 | _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " | |
| 1747 | "level compressed unwind table. funcEnd=0x%llX", | |
| 1747 | _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX " | |
| 1748 | "not in second level compressed unwind table. " | |
| 1749 | "funcEnd=0x%llX", | |
| 1748 | 1750 | (uint64_t) pc, (uint64_t) funcEnd); |
| 1749 | 1751 | return false; |
| 1750 | 1752 | } |
| ... | ... | @@ -1764,9 +1766,9 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, |
| 1764 | 1766 | pageEncodingIndex * sizeof(uint32_t)); |
| 1765 | 1767 | } |
| 1766 | 1768 | } else { |
| 1767 | _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second " | |
| 1768 | "level page", | |
| 1769 | (uint64_t) sects.compact_unwind_section); | |
| 1769 | _LIBUNWIND_DEBUG_LOG( | |
| 1770 | "malformed __unwind_info at 0x%0llX bad second level page", | |
| 1771 | (uint64_t)sects.compact_unwind_section); | |
| 1770 | 1772 | return false; |
| 1771 | 1773 | } |
| 1772 | 1774 |
lib/libunwind/src/UnwindRegistersRestore.S+192-192| ... | ... | @@ -134,7 +134,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) |
| 134 | 134 | |
| 135 | 135 | // load register (GPR) |
| 136 | 136 | #define PPC64_LR(n) \ |
| 137 | ld %r##n, (8 * (n + 2))(%r3) | |
| 137 | ld n, (8 * (n + 2))(3) | |
| 138 | 138 | |
| 139 | 139 | // restore integral registers |
| 140 | 140 | // skip r0 for now |
| ... | ... | @@ -176,12 +176,12 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) |
| 176 | 176 | // (note that this also restores floating point registers and V registers, |
| 177 | 177 | // because part of VS is mapped to these registers) |
| 178 | 178 | |
| 179 | addi %r4, %r3, PPC64_OFFS_FP | |
| 179 | addi 4, 3, PPC64_OFFS_FP | |
| 180 | 180 | |
| 181 | 181 | // load VS register |
| 182 | 182 | #define PPC64_LVS(n) \ |
| 183 | lxvd2x %vs##n, 0, %r4 ;\ | |
| 184 | addi %r4, %r4, 16 | |
| 183 | lxvd2x n, 0, 4 ;\ | |
| 184 | addi 4, 4, 16 | |
| 185 | 185 | |
| 186 | 186 | // restore the first 32 VS regs (and also all floating point regs) |
| 187 | 187 | PPC64_LVS(0) |
| ... | ... | @@ -220,23 +220,23 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) |
| 220 | 220 | // use VRSAVE to conditionally restore the remaining VS regs, |
| 221 | 221 | // that are where the V regs are mapped |
| 222 | 222 | |
| 223 | ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave | |
| 224 | cmpwi %r5, 0 | |
| 223 | ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave | |
| 224 | cmpwi 5, 0 | |
| 225 | 225 | beq Lnovec |
| 226 | 226 | |
| 227 | 227 | // conditionally load VS |
| 228 | 228 | #define PPC64_CLVS_BOTTOM(n) \ |
| 229 | 229 | beq Ldone##n ;\ |
| 230 | addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\ | |
| 231 | lxvd2x %vs##n, 0, %r4 ;\ | |
| 230 | addi 4, 3, PPC64_OFFS_FP + n * 16 ;\ | |
| 231 | lxvd2x n, 0, 4 ;\ | |
| 232 | 232 | Ldone##n: |
| 233 | 233 | |
| 234 | #define PPC64_CLVSl(n) \ | |
| 235 | andis. %r0, %r5, (1<<(47-n)) ;\ | |
| 234 | #define PPC64_CLVSl(n) \ | |
| 235 | andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\ | |
| 236 | 236 | PPC64_CLVS_BOTTOM(n) |
| 237 | 237 | |
| 238 | #define PPC64_CLVSh(n) \ | |
| 239 | andi. %r0, %r5, (1<<(63-n)) ;\ | |
| 238 | #define PPC64_CLVSh(n) \ | |
| 239 | andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\ | |
| 240 | 240 | PPC64_CLVS_BOTTOM(n) |
| 241 | 241 | |
| 242 | 242 | PPC64_CLVSl(32) |
| ... | ... | @@ -276,7 +276,7 @@ PPC64_CLVS_BOTTOM(n) |
| 276 | 276 | |
| 277 | 277 | // load FP register |
| 278 | 278 | #define PPC64_LF(n) \ |
| 279 | lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) | |
| 279 | lfd n, (PPC64_OFFS_FP + n * 16)(3) | |
| 280 | 280 | |
| 281 | 281 | // restore float registers |
| 282 | 282 | PPC64_LF(0) |
| ... | ... | @@ -314,30 +314,30 @@ PPC64_CLVS_BOTTOM(n) |
| 314 | 314 | |
| 315 | 315 | #if defined(__ALTIVEC__) |
| 316 | 316 | // restore vector registers if any are in use |
| 317 | ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave | |
| 318 | cmpwi %r5, 0 | |
| 317 | ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave | |
| 318 | cmpwi 5, 0 | |
| 319 | 319 | beq Lnovec |
| 320 | 320 | |
| 321 | subi %r4, %r1, 16 | |
| 321 | subi 4, 1, 16 | |
| 322 | 322 | // r4 is now a 16-byte aligned pointer into the red zone |
| 323 | 323 | // the _vectorScalarRegisters may not be 16-byte aligned |
| 324 | 324 | // so copy via red zone temp buffer |
| 325 | 325 | |
| 326 | 326 | #define PPC64_CLV_UNALIGNED_BOTTOM(n) \ |
| 327 | 327 | beq Ldone##n ;\ |
| 328 | ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\ | |
| 329 | std %r0, 0(%r4) ;\ | |
| 330 | ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\ | |
| 331 | std %r0, 8(%r4) ;\ | |
| 332 | lvx %v##n, 0, %r4 ;\ | |
| 328 | ld 0, (PPC64_OFFS_V + n * 16)(3) ;\ | |
| 329 | std 0, 0(4) ;\ | |
| 330 | ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\ | |
| 331 | std 0, 8(4) ;\ | |
| 332 | lvx n, 0, 4 ;\ | |
| 333 | 333 | Ldone ## n: |
| 334 | 334 | |
| 335 | #define PPC64_CLV_UNALIGNEDl(n) \ | |
| 336 | andis. %r0, %r5, (1<<(15-n)) ;\ | |
| 335 | #define PPC64_CLV_UNALIGNEDl(n) \ | |
| 336 | andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\ | |
| 337 | 337 | PPC64_CLV_UNALIGNED_BOTTOM(n) |
| 338 | 338 | |
| 339 | #define PPC64_CLV_UNALIGNEDh(n) \ | |
| 340 | andi. %r0, %r5, (1<<(31-n)) ;\ | |
| 339 | #define PPC64_CLV_UNALIGNEDh(n) \ | |
| 340 | andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\ | |
| 341 | 341 | PPC64_CLV_UNALIGNED_BOTTOM(n) |
| 342 | 342 | |
| 343 | 343 | PPC64_CLV_UNALIGNEDl(0) |
| ... | ... | @@ -377,10 +377,10 @@ PPC64_CLV_UNALIGNED_BOTTOM(n) |
| 377 | 377 | #endif |
| 378 | 378 | |
| 379 | 379 | Lnovec: |
| 380 | ld %r0, PPC64_OFFS_CR(%r3) | |
| 381 | mtcr %r0 | |
| 382 | ld %r0, PPC64_OFFS_SRR0(%r3) | |
| 383 | mtctr %r0 | |
| 380 | ld 0, PPC64_OFFS_CR(3) | |
| 381 | mtcr 0 | |
| 382 | ld 0, PPC64_OFFS_SRR0(3) | |
| 383 | mtctr 0 | |
| 384 | 384 | |
| 385 | 385 | PPC64_LR(0) |
| 386 | 386 | PPC64_LR(5) |
| ... | ... | @@ -402,111 +402,111 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 402 | 402 | // restore integral registerrs |
| 403 | 403 | // skip r0 for now |
| 404 | 404 | // skip r1 for now |
| 405 | lwz %r2, 16(%r3) | |
| 405 | lwz 2, 16(3) | |
| 406 | 406 | // skip r3 for now |
| 407 | 407 | // skip r4 for now |
| 408 | 408 | // skip r5 for now |
| 409 | lwz %r6, 32(%r3) | |
| 410 | lwz %r7, 36(%r3) | |
| 411 | lwz %r8, 40(%r3) | |
| 412 | lwz %r9, 44(%r3) | |
| 413 | lwz %r10, 48(%r3) | |
| 414 | lwz %r11, 52(%r3) | |
| 415 | lwz %r12, 56(%r3) | |
| 416 | lwz %r13, 60(%r3) | |
| 417 | lwz %r14, 64(%r3) | |
| 418 | lwz %r15, 68(%r3) | |
| 419 | lwz %r16, 72(%r3) | |
| 420 | lwz %r17, 76(%r3) | |
| 421 | lwz %r18, 80(%r3) | |
| 422 | lwz %r19, 84(%r3) | |
| 423 | lwz %r20, 88(%r3) | |
| 424 | lwz %r21, 92(%r3) | |
| 425 | lwz %r22, 96(%r3) | |
| 426 | lwz %r23,100(%r3) | |
| 427 | lwz %r24,104(%r3) | |
| 428 | lwz %r25,108(%r3) | |
| 429 | lwz %r26,112(%r3) | |
| 430 | lwz %r27,116(%r3) | |
| 431 | lwz %r28,120(%r3) | |
| 432 | lwz %r29,124(%r3) | |
| 433 | lwz %r30,128(%r3) | |
| 434 | lwz %r31,132(%r3) | |
| 409 | lwz 6, 32(3) | |
| 410 | lwz 7, 36(3) | |
| 411 | lwz 8, 40(3) | |
| 412 | lwz 9, 44(3) | |
| 413 | lwz 10, 48(3) | |
| 414 | lwz 11, 52(3) | |
| 415 | lwz 12, 56(3) | |
| 416 | lwz 13, 60(3) | |
| 417 | lwz 14, 64(3) | |
| 418 | lwz 15, 68(3) | |
| 419 | lwz 16, 72(3) | |
| 420 | lwz 17, 76(3) | |
| 421 | lwz 18, 80(3) | |
| 422 | lwz 19, 84(3) | |
| 423 | lwz 20, 88(3) | |
| 424 | lwz 21, 92(3) | |
| 425 | lwz 22, 96(3) | |
| 426 | lwz 23,100(3) | |
| 427 | lwz 24,104(3) | |
| 428 | lwz 25,108(3) | |
| 429 | lwz 26,112(3) | |
| 430 | lwz 27,116(3) | |
| 431 | lwz 28,120(3) | |
| 432 | lwz 29,124(3) | |
| 433 | lwz 30,128(3) | |
| 434 | lwz 31,132(3) | |
| 435 | 435 | |
| 436 | 436 | #ifndef __NO_FPRS__ |
| 437 | 437 | // restore float registers |
| 438 | lfd %f0, 160(%r3) | |
| 439 | lfd %f1, 168(%r3) | |
| 440 | lfd %f2, 176(%r3) | |
| 441 | lfd %f3, 184(%r3) | |
| 442 | lfd %f4, 192(%r3) | |
| 443 | lfd %f5, 200(%r3) | |
| 444 | lfd %f6, 208(%r3) | |
| 445 | lfd %f7, 216(%r3) | |
| 446 | lfd %f8, 224(%r3) | |
| 447 | lfd %f9, 232(%r3) | |
| 448 | lfd %f10,240(%r3) | |
| 449 | lfd %f11,248(%r3) | |
| 450 | lfd %f12,256(%r3) | |
| 451 | lfd %f13,264(%r3) | |
| 452 | lfd %f14,272(%r3) | |
| 453 | lfd %f15,280(%r3) | |
| 454 | lfd %f16,288(%r3) | |
| 455 | lfd %f17,296(%r3) | |
| 456 | lfd %f18,304(%r3) | |
| 457 | lfd %f19,312(%r3) | |
| 458 | lfd %f20,320(%r3) | |
| 459 | lfd %f21,328(%r3) | |
| 460 | lfd %f22,336(%r3) | |
| 461 | lfd %f23,344(%r3) | |
| 462 | lfd %f24,352(%r3) | |
| 463 | lfd %f25,360(%r3) | |
| 464 | lfd %f26,368(%r3) | |
| 465 | lfd %f27,376(%r3) | |
| 466 | lfd %f28,384(%r3) | |
| 467 | lfd %f29,392(%r3) | |
| 468 | lfd %f30,400(%r3) | |
| 469 | lfd %f31,408(%r3) | |
| 438 | lfd 0, 160(3) | |
| 439 | lfd 1, 168(3) | |
| 440 | lfd 2, 176(3) | |
| 441 | lfd 3, 184(3) | |
| 442 | lfd 4, 192(3) | |
| 443 | lfd 5, 200(3) | |
| 444 | lfd 6, 208(3) | |
| 445 | lfd 7, 216(3) | |
| 446 | lfd 8, 224(3) | |
| 447 | lfd 9, 232(3) | |
| 448 | lfd 10,240(3) | |
| 449 | lfd 11,248(3) | |
| 450 | lfd 12,256(3) | |
| 451 | lfd 13,264(3) | |
| 452 | lfd 14,272(3) | |
| 453 | lfd 15,280(3) | |
| 454 | lfd 16,288(3) | |
| 455 | lfd 17,296(3) | |
| 456 | lfd 18,304(3) | |
| 457 | lfd 19,312(3) | |
| 458 | lfd 20,320(3) | |
| 459 | lfd 21,328(3) | |
| 460 | lfd 22,336(3) | |
| 461 | lfd 23,344(3) | |
| 462 | lfd 24,352(3) | |
| 463 | lfd 25,360(3) | |
| 464 | lfd 26,368(3) | |
| 465 | lfd 27,376(3) | |
| 466 | lfd 28,384(3) | |
| 467 | lfd 29,392(3) | |
| 468 | lfd 30,400(3) | |
| 469 | lfd 31,408(3) | |
| 470 | 470 | #endif |
| 471 | 471 | |
| 472 | 472 | #if defined(__ALTIVEC__) |
| 473 | 473 | // restore vector registers if any are in use |
| 474 | lwz %r5, 156(%r3) // test VRsave | |
| 475 | cmpwi %r5, 0 | |
| 474 | lwz 5, 156(3) // test VRsave | |
| 475 | cmpwi 5, 0 | |
| 476 | 476 | beq Lnovec |
| 477 | 477 | |
| 478 | subi %r4, %r1, 16 | |
| 479 | rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits | |
| 478 | subi 4, 1, 16 | |
| 479 | rlwinm 4, 4, 0, 0, 27 // mask low 4-bits | |
| 480 | 480 | // r4 is now a 16-byte aligned pointer into the red zone |
| 481 | 481 | // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer |
| 482 | ||
| 483 | 482 | |
| 484 | #define LOAD_VECTOR_UNALIGNEDl(_index) \ | |
| 485 | andis. %r0, %r5, (1<<(15-_index)) SEPARATOR \ | |
| 483 | ||
| 484 | #define LOAD_VECTOR_UNALIGNEDl(_index) \ | |
| 485 | andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \ | |
| 486 | 486 | beq Ldone ## _index SEPARATOR \ |
| 487 | lwz %r0, 424+_index*16(%r3) SEPARATOR \ | |
| 488 | stw %r0, 0(%r4) SEPARATOR \ | |
| 489 | lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ | |
| 490 | stw %r0, 4(%r4) SEPARATOR \ | |
| 491 | lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ | |
| 492 | stw %r0, 8(%r4) SEPARATOR \ | |
| 493 | lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ | |
| 494 | stw %r0, 12(%r4) SEPARATOR \ | |
| 495 | lvx %v ## _index, 0, %r4 SEPARATOR \ | |
| 487 | lwz 0, 424+_index*16(3) SEPARATOR \ | |
| 488 | stw 0, 0(%r4) SEPARATOR \ | |
| 489 | lwz 0, 424+_index*16+4(%r3) SEPARATOR \ | |
| 490 | stw 0, 4(%r4) SEPARATOR \ | |
| 491 | lwz 0, 424+_index*16+8(%r3) SEPARATOR \ | |
| 492 | stw 0, 8(%r4) SEPARATOR \ | |
| 493 | lwz 0, 424+_index*16+12(%r3) SEPARATOR \ | |
| 494 | stw 0, 12(%r4) SEPARATOR \ | |
| 495 | lvx _index, 0, 4 SEPARATOR \ | |
| 496 | 496 | Ldone ## _index: |
| 497 | 497 | |
| 498 | #define LOAD_VECTOR_UNALIGNEDh(_index) \ | |
| 499 | andi. %r0, %r5, (1<<(31-_index)) SEPARATOR \ | |
| 498 | #define LOAD_VECTOR_UNALIGNEDh(_index) \ | |
| 499 | andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \ | |
| 500 | 500 | beq Ldone ## _index SEPARATOR \ |
| 501 | lwz %r0, 424+_index*16(%r3) SEPARATOR \ | |
| 502 | stw %r0, 0(%r4) SEPARATOR \ | |
| 503 | lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ | |
| 504 | stw %r0, 4(%r4) SEPARATOR \ | |
| 505 | lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ | |
| 506 | stw %r0, 8(%r4) SEPARATOR \ | |
| 507 | lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ | |
| 508 | stw %r0, 12(%r4) SEPARATOR \ | |
| 509 | lvx %v ## _index, 0, %r4 SEPARATOR \ | |
| 501 | lwz 0, 424+_index*16(3) SEPARATOR \ | |
| 502 | stw 0, 0(4) SEPARATOR \ | |
| 503 | lwz 0, 424+_index*16+4(3) SEPARATOR \ | |
| 504 | stw 0, 4(4) SEPARATOR \ | |
| 505 | lwz 0, 424+_index*16+8(3) SEPARATOR \ | |
| 506 | stw 0, 8(%r4) SEPARATOR \ | |
| 507 | lwz 0, 424+_index*16+12(3) SEPARATOR \ | |
| 508 | stw 0, 12(4) SEPARATOR \ | |
| 509 | lvx _index, 0, 4 SEPARATOR \ | |
| 510 | 510 | Ldone ## _index: |
| 511 | 511 | |
| 512 | 512 | |
| ... | ... | @@ -545,17 +545,17 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 545 | 545 | #endif |
| 546 | 546 | |
| 547 | 547 | Lnovec: |
| 548 | lwz %r0, 136(%r3) // __cr | |
| 549 | mtcr %r0 | |
| 550 | lwz %r0, 148(%r3) // __ctr | |
| 551 | mtctr %r0 | |
| 552 | lwz %r0, 0(%r3) // __ssr0 | |
| 553 | mtctr %r0 | |
| 554 | lwz %r0, 8(%r3) // do r0 now | |
| 555 | lwz %r5, 28(%r3) // do r5 now | |
| 556 | lwz %r4, 24(%r3) // do r4 now | |
| 557 | lwz %r1, 12(%r3) // do sp now | |
| 558 | lwz %r3, 20(%r3) // do r3 last | |
| 548 | lwz 0, 136(3) // __cr | |
| 549 | mtcr 0 | |
| 550 | lwz 0, 148(3) // __ctr | |
| 551 | mtctr 0 | |
| 552 | lwz 0, 0(3) // __ssr0 | |
| 553 | mtctr 0 | |
| 554 | lwz 0, 8(3) // do r0 now | |
| 555 | lwz 5, 28(3) // do r5 now | |
| 556 | lwz 4, 24(3) // do r4 now | |
| 557 | lwz 1, 12(3) // do sp now | |
| 558 | lwz 3, 20(3) // do r3 last | |
| 559 | 559 | bctr |
| 560 | 560 | |
| 561 | 561 | #elif defined(__aarch64__) |
| ... | ... | @@ -1072,7 +1072,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) |
| 1072 | 1072 | jmp %o7 |
| 1073 | 1073 | nop |
| 1074 | 1074 | |
| 1075 | #elif defined(__riscv) && __riscv_xlen == 64 | |
| 1075 | #elif defined(__riscv) | |
| 1076 | 1076 | |
| 1077 | 1077 | // |
| 1078 | 1078 | // void libunwind::Registers_riscv::jumpto() |
| ... | ... | @@ -1082,74 +1082,74 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) |
| 1082 | 1082 | // |
| 1083 | 1083 | .p2align 2 |
| 1084 | 1084 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) |
| 1085 | #if defined(__riscv_flen) && __riscv_flen == 64 | |
| 1086 | fld f0, (8 * 32 + 8 * 0)(a0) | |
| 1087 | fld f1, (8 * 32 + 8 * 1)(a0) | |
| 1088 | fld f2, (8 * 32 + 8 * 2)(a0) | |
| 1089 | fld f3, (8 * 32 + 8 * 3)(a0) | |
| 1090 | fld f4, (8 * 32 + 8 * 4)(a0) | |
| 1091 | fld f5, (8 * 32 + 8 * 5)(a0) | |
| 1092 | fld f6, (8 * 32 + 8 * 6)(a0) | |
| 1093 | fld f7, (8 * 32 + 8 * 7)(a0) | |
| 1094 | fld f8, (8 * 32 + 8 * 8)(a0) | |
| 1095 | fld f9, (8 * 32 + 8 * 9)(a0) | |
| 1096 | fld f10, (8 * 32 + 8 * 10)(a0) | |
| 1097 | fld f11, (8 * 32 + 8 * 11)(a0) | |
| 1098 | fld f12, (8 * 32 + 8 * 12)(a0) | |
| 1099 | fld f13, (8 * 32 + 8 * 13)(a0) | |
| 1100 | fld f14, (8 * 32 + 8 * 14)(a0) | |
| 1101 | fld f15, (8 * 32 + 8 * 15)(a0) | |
| 1102 | fld f16, (8 * 32 + 8 * 16)(a0) | |
| 1103 | fld f17, (8 * 32 + 8 * 17)(a0) | |
| 1104 | fld f18, (8 * 32 + 8 * 18)(a0) | |
| 1105 | fld f19, (8 * 32 + 8 * 19)(a0) | |
| 1106 | fld f20, (8 * 32 + 8 * 20)(a0) | |
| 1107 | fld f21, (8 * 32 + 8 * 21)(a0) | |
| 1108 | fld f22, (8 * 32 + 8 * 22)(a0) | |
| 1109 | fld f23, (8 * 32 + 8 * 23)(a0) | |
| 1110 | fld f24, (8 * 32 + 8 * 24)(a0) | |
| 1111 | fld f25, (8 * 32 + 8 * 25)(a0) | |
| 1112 | fld f26, (8 * 32 + 8 * 26)(a0) | |
| 1113 | fld f27, (8 * 32 + 8 * 27)(a0) | |
| 1114 | fld f28, (8 * 32 + 8 * 28)(a0) | |
| 1115 | fld f29, (8 * 32 + 8 * 29)(a0) | |
| 1116 | fld f30, (8 * 32 + 8 * 30)(a0) | |
| 1117 | fld f31, (8 * 32 + 8 * 31)(a0) | |
| 1118 | #endif | |
| 1085 | # if defined(__riscv_flen) | |
| 1086 | FLOAD f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0) | |
| 1087 | FLOAD f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0) | |
| 1088 | FLOAD f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0) | |
| 1089 | FLOAD f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0) | |
| 1090 | FLOAD f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0) | |
| 1091 | FLOAD f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0) | |
| 1092 | FLOAD f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0) | |
| 1093 | FLOAD f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0) | |
| 1094 | FLOAD f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0) | |
| 1095 | FLOAD f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0) | |
| 1096 | FLOAD f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0) | |
| 1097 | FLOAD f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0) | |
| 1098 | FLOAD f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0) | |
| 1099 | FLOAD f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0) | |
| 1100 | FLOAD f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0) | |
| 1101 | FLOAD f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0) | |
| 1102 | FLOAD f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0) | |
| 1103 | FLOAD f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0) | |
| 1104 | FLOAD f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0) | |
| 1105 | FLOAD f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0) | |
| 1106 | FLOAD f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0) | |
| 1107 | FLOAD f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0) | |
| 1108 | FLOAD f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0) | |
| 1109 | FLOAD f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0) | |
| 1110 | FLOAD f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0) | |
| 1111 | FLOAD f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0) | |
| 1112 | FLOAD f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0) | |
| 1113 | FLOAD f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0) | |
| 1114 | FLOAD f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0) | |
| 1115 | FLOAD f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0) | |
| 1116 | FLOAD f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0) | |
| 1117 | FLOAD f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0) | |
| 1118 | # endif | |
| 1119 | 1119 | |
| 1120 | 1120 | // x0 is zero |
| 1121 | ld x1, (8 * 0)(a0) // restore pc into ra | |
| 1122 | ld x2, (8 * 2)(a0) | |
| 1123 | ld x3, (8 * 3)(a0) | |
| 1124 | ld x4, (8 * 4)(a0) | |
| 1125 | ld x5, (8 * 5)(a0) | |
| 1126 | ld x6, (8 * 6)(a0) | |
| 1127 | ld x7, (8 * 7)(a0) | |
| 1128 | ld x8, (8 * 8)(a0) | |
| 1129 | ld x9, (8 * 9)(a0) | |
| 1121 | ILOAD x1, (RISCV_ISIZE * 0)(a0) // restore pc into ra | |
| 1122 | ILOAD x2, (RISCV_ISIZE * 2)(a0) | |
| 1123 | ILOAD x3, (RISCV_ISIZE * 3)(a0) | |
| 1124 | ILOAD x4, (RISCV_ISIZE * 4)(a0) | |
| 1125 | ILOAD x5, (RISCV_ISIZE * 5)(a0) | |
| 1126 | ILOAD x6, (RISCV_ISIZE * 6)(a0) | |
| 1127 | ILOAD x7, (RISCV_ISIZE * 7)(a0) | |
| 1128 | ILOAD x8, (RISCV_ISIZE * 8)(a0) | |
| 1129 | ILOAD x9, (RISCV_ISIZE * 9)(a0) | |
| 1130 | 1130 | // skip a0 for now |
| 1131 | ld x11, (8 * 11)(a0) | |
| 1132 | ld x12, (8 * 12)(a0) | |
| 1133 | ld x13, (8 * 13)(a0) | |
| 1134 | ld x14, (8 * 14)(a0) | |
| 1135 | ld x15, (8 * 15)(a0) | |
| 1136 | ld x16, (8 * 16)(a0) | |
| 1137 | ld x17, (8 * 17)(a0) | |
| 1138 | ld x18, (8 * 18)(a0) | |
| 1139 | ld x19, (8 * 19)(a0) | |
| 1140 | ld x20, (8 * 20)(a0) | |
| 1141 | ld x21, (8 * 21)(a0) | |
| 1142 | ld x22, (8 * 22)(a0) | |
| 1143 | ld x23, (8 * 23)(a0) | |
| 1144 | ld x24, (8 * 24)(a0) | |
| 1145 | ld x25, (8 * 25)(a0) | |
| 1146 | ld x26, (8 * 26)(a0) | |
| 1147 | ld x27, (8 * 27)(a0) | |
| 1148 | ld x28, (8 * 28)(a0) | |
| 1149 | ld x29, (8 * 29)(a0) | |
| 1150 | ld x30, (8 * 30)(a0) | |
| 1151 | ld x31, (8 * 31)(a0) | |
| 1152 | ld x10, (8 * 10)(a0) // restore a0 | |
| 1131 | ILOAD x11, (RISCV_ISIZE * 11)(a0) | |
| 1132 | ILOAD x12, (RISCV_ISIZE * 12)(a0) | |
| 1133 | ILOAD x13, (RISCV_ISIZE * 13)(a0) | |
| 1134 | ILOAD x14, (RISCV_ISIZE * 14)(a0) | |
| 1135 | ILOAD x15, (RISCV_ISIZE * 15)(a0) | |
| 1136 | ILOAD x16, (RISCV_ISIZE * 16)(a0) | |
| 1137 | ILOAD x17, (RISCV_ISIZE * 17)(a0) | |
| 1138 | ILOAD x18, (RISCV_ISIZE * 18)(a0) | |
| 1139 | ILOAD x19, (RISCV_ISIZE * 19)(a0) | |
| 1140 | ILOAD x20, (RISCV_ISIZE * 20)(a0) | |
| 1141 | ILOAD x21, (RISCV_ISIZE * 21)(a0) | |
| 1142 | ILOAD x22, (RISCV_ISIZE * 22)(a0) | |
| 1143 | ILOAD x23, (RISCV_ISIZE * 23)(a0) | |
| 1144 | ILOAD x24, (RISCV_ISIZE * 24)(a0) | |
| 1145 | ILOAD x25, (RISCV_ISIZE * 25)(a0) | |
| 1146 | ILOAD x26, (RISCV_ISIZE * 26)(a0) | |
| 1147 | ILOAD x27, (RISCV_ISIZE * 27)(a0) | |
| 1148 | ILOAD x28, (RISCV_ISIZE * 28)(a0) | |
| 1149 | ILOAD x29, (RISCV_ISIZE * 29)(a0) | |
| 1150 | ILOAD x30, (RISCV_ISIZE * 30)(a0) | |
| 1151 | ILOAD x31, (RISCV_ISIZE * 31)(a0) | |
| 1152 | ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0 | |
| 1153 | 1153 | |
| 1154 | 1154 | ret // jump to ra |
| 1155 | 1155 |
lib/libunwind/src/UnwindRegistersSave.S+210-210| ... | ... | @@ -335,12 +335,12 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 335 | 335 | |
| 336 | 336 | // store register (GPR) |
| 337 | 337 | #define PPC64_STR(n) \ |
| 338 | std %r##n, (8 * (n + 2))(%r3) | |
| 338 | std n, (8 * (n + 2))(3) | |
| 339 | 339 | |
| 340 | 340 | // save GPRs |
| 341 | 341 | PPC64_STR(0) |
| 342 | mflr %r0 | |
| 343 | std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0 | |
| 342 | mflr 0 | |
| 343 | std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0 | |
| 344 | 344 | PPC64_STR(1) |
| 345 | 345 | PPC64_STR(2) |
| 346 | 346 | PPC64_STR(3) |
| ... | ... | @@ -373,28 +373,28 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 373 | 373 | PPC64_STR(30) |
| 374 | 374 | PPC64_STR(31) |
| 375 | 375 | |
| 376 | mfcr %r0 | |
| 377 | std %r0, PPC64_OFFS_CR(%r3) | |
| 378 | mfxer %r0 | |
| 379 | std %r0, PPC64_OFFS_XER(%r3) | |
| 380 | mflr %r0 | |
| 381 | std %r0, PPC64_OFFS_LR(%r3) | |
| 382 | mfctr %r0 | |
| 383 | std %r0, PPC64_OFFS_CTR(%r3) | |
| 384 | mfvrsave %r0 | |
| 385 | std %r0, PPC64_OFFS_VRSAVE(%r3) | |
| 376 | mfcr 0 | |
| 377 | std 0, PPC64_OFFS_CR(3) | |
| 378 | mfxer 0 | |
| 379 | std 0, PPC64_OFFS_XER(3) | |
| 380 | mflr 0 | |
| 381 | std 0, PPC64_OFFS_LR(3) | |
| 382 | mfctr 0 | |
| 383 | std 0, PPC64_OFFS_CTR(3) | |
| 384 | mfvrsave 0 | |
| 385 | std 0, PPC64_OFFS_VRSAVE(3) | |
| 386 | 386 | |
| 387 | 387 | #if defined(__VSX__) |
| 388 | 388 | // save VS registers |
| 389 | 389 | // (note that this also saves floating point registers and V registers, |
| 390 | 390 | // because part of VS is mapped to these registers) |
| 391 | 391 | |
| 392 | addi %r4, %r3, PPC64_OFFS_FP | |
| 392 | addi 4, 3, PPC64_OFFS_FP | |
| 393 | 393 | |
| 394 | 394 | // store VS register |
| 395 | 395 | #define PPC64_STVS(n) \ |
| 396 | stxvd2x %vs##n, 0, %r4 ;\ | |
| 397 | addi %r4, %r4, 16 | |
| 396 | stxvd2x n, 0, 4 ;\ | |
| 397 | addi 4, 4, 16 | |
| 398 | 398 | |
| 399 | 399 | PPC64_STVS(0) |
| 400 | 400 | PPC64_STVS(1) |
| ... | ... | @@ -465,7 +465,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 465 | 465 | |
| 466 | 466 | // store FP register |
| 467 | 467 | #define PPC64_STF(n) \ |
| 468 | stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) | |
| 468 | stfd n, (PPC64_OFFS_FP + n * 16)(3) | |
| 469 | 469 | |
| 470 | 470 | // save float registers |
| 471 | 471 | PPC64_STF(0) |
| ... | ... | @@ -507,14 +507,14 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 507 | 507 | // Use 16-bytes below the stack pointer as an |
| 508 | 508 | // aligned buffer to save each vector register. |
| 509 | 509 | // Note that the stack pointer is always 16-byte aligned. |
| 510 | subi %r4, %r1, 16 | |
| 510 | subi 4, 1, 16 | |
| 511 | 511 | |
| 512 | #define PPC64_STV_UNALIGNED(n) \ | |
| 513 | stvx %v##n, 0, %r4 ;\ | |
| 514 | ld %r5, 0(%r4) ;\ | |
| 515 | std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\ | |
| 516 | ld %r5, 8(%r4) ;\ | |
| 517 | std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3) | |
| 512 | #define PPC64_STV_UNALIGNED(n) \ | |
| 513 | stvx n, 0, 4 ;\ | |
| 514 | ld 5, 0(4) ;\ | |
| 515 | std 5, (PPC64_OFFS_V + n * 16)(3) ;\ | |
| 516 | ld 5, 8(4) ;\ | |
| 517 | std 5, (PPC64_OFFS_V + n * 16 + 8)(3) | |
| 518 | 518 | |
| 519 | 519 | PPC64_STV_UNALIGNED(0) |
| 520 | 520 | PPC64_STV_UNALIGNED(1) |
| ... | ... | @@ -552,7 +552,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 552 | 552 | #endif |
| 553 | 553 | #endif |
| 554 | 554 | |
| 555 | li %r3, 0 // return UNW_ESUCCESS | |
| 555 | li 3, 0 // return UNW_ESUCCESS | |
| 556 | 556 | blr |
| 557 | 557 | |
| 558 | 558 | |
| ... | ... | @@ -565,140 +565,140 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 565 | 565 | // thread_state pointer is in r3 |
| 566 | 566 | // |
| 567 | 567 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 568 | stw %r0, 8(%r3) | |
| 569 | mflr %r0 | |
| 570 | stw %r0, 0(%r3) // store lr as ssr0 | |
| 571 | stw %r1, 12(%r3) | |
| 572 | stw %r2, 16(%r3) | |
| 573 | stw %r3, 20(%r3) | |
| 574 | stw %r4, 24(%r3) | |
| 575 | stw %r5, 28(%r3) | |
| 576 | stw %r6, 32(%r3) | |
| 577 | stw %r7, 36(%r3) | |
| 578 | stw %r8, 40(%r3) | |
| 579 | stw %r9, 44(%r3) | |
| 580 | stw %r10, 48(%r3) | |
| 581 | stw %r11, 52(%r3) | |
| 582 | stw %r12, 56(%r3) | |
| 583 | stw %r13, 60(%r3) | |
| 584 | stw %r14, 64(%r3) | |
| 585 | stw %r15, 68(%r3) | |
| 586 | stw %r16, 72(%r3) | |
| 587 | stw %r17, 76(%r3) | |
| 588 | stw %r18, 80(%r3) | |
| 589 | stw %r19, 84(%r3) | |
| 590 | stw %r20, 88(%r3) | |
| 591 | stw %r21, 92(%r3) | |
| 592 | stw %r22, 96(%r3) | |
| 593 | stw %r23,100(%r3) | |
| 594 | stw %r24,104(%r3) | |
| 595 | stw %r25,108(%r3) | |
| 596 | stw %r26,112(%r3) | |
| 597 | stw %r27,116(%r3) | |
| 598 | stw %r28,120(%r3) | |
| 599 | stw %r29,124(%r3) | |
| 600 | stw %r30,128(%r3) | |
| 601 | stw %r31,132(%r3) | |
| 568 | stw 0, 8(3) | |
| 569 | mflr 0 | |
| 570 | stw 0, 0(3) // store lr as ssr0 | |
| 571 | stw 1, 12(3) | |
| 572 | stw 2, 16(3) | |
| 573 | stw 3, 20(3) | |
| 574 | stw 4, 24(3) | |
| 575 | stw 5, 28(3) | |
| 576 | stw 6, 32(3) | |
| 577 | stw 7, 36(3) | |
| 578 | stw 8, 40(3) | |
| 579 | stw 9, 44(3) | |
| 580 | stw 10, 48(3) | |
| 581 | stw 11, 52(3) | |
| 582 | stw 12, 56(3) | |
| 583 | stw 13, 60(3) | |
| 584 | stw 14, 64(3) | |
| 585 | stw 15, 68(3) | |
| 586 | stw 16, 72(3) | |
| 587 | stw 17, 76(3) | |
| 588 | stw 18, 80(3) | |
| 589 | stw 19, 84(3) | |
| 590 | stw 20, 88(3) | |
| 591 | stw 21, 92(3) | |
| 592 | stw 22, 96(3) | |
| 593 | stw 23,100(3) | |
| 594 | stw 24,104(3) | |
| 595 | stw 25,108(3) | |
| 596 | stw 26,112(3) | |
| 597 | stw 27,116(3) | |
| 598 | stw 28,120(3) | |
| 599 | stw 29,124(3) | |
| 600 | stw 30,128(3) | |
| 601 | stw 31,132(3) | |
| 602 | 602 | |
| 603 | 603 | // save VRSave register |
| 604 | mfspr %r0, 256 | |
| 605 | stw %r0, 156(%r3) | |
| 604 | mfspr 0, 256 | |
| 605 | stw 0, 156(3) | |
| 606 | 606 | // save CR registers |
| 607 | mfcr %r0 | |
| 608 | stw %r0, 136(%r3) | |
| 607 | mfcr 0 | |
| 608 | stw 0, 136(3) | |
| 609 | 609 | // save CTR register |
| 610 | mfctr %r0 | |
| 611 | stw %r0, 148(%r3) | |
| 610 | mfctr 0 | |
| 611 | stw 0, 148(3) | |
| 612 | 612 | |
| 613 | 613 | #if !defined(__NO_FPRS__) |
| 614 | 614 | // save float registers |
| 615 | stfd %f0, 160(%r3) | |
| 616 | stfd %f1, 168(%r3) | |
| 617 | stfd %f2, 176(%r3) | |
| 618 | stfd %f3, 184(%r3) | |
| 619 | stfd %f4, 192(%r3) | |
| 620 | stfd %f5, 200(%r3) | |
| 621 | stfd %f6, 208(%r3) | |
| 622 | stfd %f7, 216(%r3) | |
| 623 | stfd %f8, 224(%r3) | |
| 624 | stfd %f9, 232(%r3) | |
| 625 | stfd %f10,240(%r3) | |
| 626 | stfd %f11,248(%r3) | |
| 627 | stfd %f12,256(%r3) | |
| 628 | stfd %f13,264(%r3) | |
| 629 | stfd %f14,272(%r3) | |
| 630 | stfd %f15,280(%r3) | |
| 631 | stfd %f16,288(%r3) | |
| 632 | stfd %f17,296(%r3) | |
| 633 | stfd %f18,304(%r3) | |
| 634 | stfd %f19,312(%r3) | |
| 635 | stfd %f20,320(%r3) | |
| 636 | stfd %f21,328(%r3) | |
| 637 | stfd %f22,336(%r3) | |
| 638 | stfd %f23,344(%r3) | |
| 639 | stfd %f24,352(%r3) | |
| 640 | stfd %f25,360(%r3) | |
| 641 | stfd %f26,368(%r3) | |
| 642 | stfd %f27,376(%r3) | |
| 643 | stfd %f28,384(%r3) | |
| 644 | stfd %f29,392(%r3) | |
| 645 | stfd %f30,400(%r3) | |
| 646 | stfd %f31,408(%r3) | |
| 615 | stfd 0, 160(3) | |
| 616 | stfd 1, 168(3) | |
| 617 | stfd 2, 176(3) | |
| 618 | stfd 3, 184(3) | |
| 619 | stfd 4, 192(3) | |
| 620 | stfd 5, 200(3) | |
| 621 | stfd 6, 208(3) | |
| 622 | stfd 7, 216(3) | |
| 623 | stfd 8, 224(3) | |
| 624 | stfd 9, 232(3) | |
| 625 | stfd 10,240(3) | |
| 626 | stfd 11,248(3) | |
| 627 | stfd 12,256(3) | |
| 628 | stfd 13,264(3) | |
| 629 | stfd 14,272(3) | |
| 630 | stfd 15,280(3) | |
| 631 | stfd 16,288(3) | |
| 632 | stfd 17,296(3) | |
| 633 | stfd 18,304(3) | |
| 634 | stfd 19,312(3) | |
| 635 | stfd 20,320(3) | |
| 636 | stfd 21,328(3) | |
| 637 | stfd 22,336(3) | |
| 638 | stfd 23,344(3) | |
| 639 | stfd 24,352(3) | |
| 640 | stfd 25,360(3) | |
| 641 | stfd 26,368(3) | |
| 642 | stfd 27,376(3) | |
| 643 | stfd 28,384(3) | |
| 644 | stfd 29,392(3) | |
| 645 | stfd 30,400(3) | |
| 646 | stfd 31,408(3) | |
| 647 | 647 | #endif |
| 648 | 648 | |
| 649 | 649 | #if defined(__ALTIVEC__) |
| 650 | 650 | // save vector registers |
| 651 | 651 | |
| 652 | subi %r4, %r1, 16 | |
| 653 | rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits | |
| 652 | subi 4, 1, 16 | |
| 653 | rlwinm 4, 4, 0, 0, 27 // mask low 4-bits | |
| 654 | 654 | // r4 is now a 16-byte aligned pointer into the red zone |
| 655 | 655 | |
| 656 | 656 | #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ |
| 657 | stvx _vec, 0, %r4 SEPARATOR \ | |
| 658 | lwz %r5, 0(%r4) SEPARATOR \ | |
| 659 | stw %r5, _offset(%r3) SEPARATOR \ | |
| 660 | lwz %r5, 4(%r4) SEPARATOR \ | |
| 661 | stw %r5, _offset+4(%r3) SEPARATOR \ | |
| 662 | lwz %r5, 8(%r4) SEPARATOR \ | |
| 663 | stw %r5, _offset+8(%r3) SEPARATOR \ | |
| 664 | lwz %r5, 12(%r4) SEPARATOR \ | |
| 665 | stw %r5, _offset+12(%r3) | |
| 666 | ||
| 667 | SAVE_VECTOR_UNALIGNED( %v0, 424+0x000) | |
| 668 | SAVE_VECTOR_UNALIGNED( %v1, 424+0x010) | |
| 669 | SAVE_VECTOR_UNALIGNED( %v2, 424+0x020) | |
| 670 | SAVE_VECTOR_UNALIGNED( %v3, 424+0x030) | |
| 671 | SAVE_VECTOR_UNALIGNED( %v4, 424+0x040) | |
| 672 | SAVE_VECTOR_UNALIGNED( %v5, 424+0x050) | |
| 673 | SAVE_VECTOR_UNALIGNED( %v6, 424+0x060) | |
| 674 | SAVE_VECTOR_UNALIGNED( %v7, 424+0x070) | |
| 675 | SAVE_VECTOR_UNALIGNED( %v8, 424+0x080) | |
| 676 | SAVE_VECTOR_UNALIGNED( %v9, 424+0x090) | |
| 677 | SAVE_VECTOR_UNALIGNED(%v10, 424+0x0A0) | |
| 678 | SAVE_VECTOR_UNALIGNED(%v11, 424+0x0B0) | |
| 679 | SAVE_VECTOR_UNALIGNED(%v12, 424+0x0C0) | |
| 680 | SAVE_VECTOR_UNALIGNED(%v13, 424+0x0D0) | |
| 681 | SAVE_VECTOR_UNALIGNED(%v14, 424+0x0E0) | |
| 682 | SAVE_VECTOR_UNALIGNED(%v15, 424+0x0F0) | |
| 683 | SAVE_VECTOR_UNALIGNED(%v16, 424+0x100) | |
| 684 | SAVE_VECTOR_UNALIGNED(%v17, 424+0x110) | |
| 685 | SAVE_VECTOR_UNALIGNED(%v18, 424+0x120) | |
| 686 | SAVE_VECTOR_UNALIGNED(%v19, 424+0x130) | |
| 687 | SAVE_VECTOR_UNALIGNED(%v20, 424+0x140) | |
| 688 | SAVE_VECTOR_UNALIGNED(%v21, 424+0x150) | |
| 689 | SAVE_VECTOR_UNALIGNED(%v22, 424+0x160) | |
| 690 | SAVE_VECTOR_UNALIGNED(%v23, 424+0x170) | |
| 691 | SAVE_VECTOR_UNALIGNED(%v24, 424+0x180) | |
| 692 | SAVE_VECTOR_UNALIGNED(%v25, 424+0x190) | |
| 693 | SAVE_VECTOR_UNALIGNED(%v26, 424+0x1A0) | |
| 694 | SAVE_VECTOR_UNALIGNED(%v27, 424+0x1B0) | |
| 695 | SAVE_VECTOR_UNALIGNED(%v28, 424+0x1C0) | |
| 696 | SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0) | |
| 697 | SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) | |
| 698 | SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) | |
| 657 | stvx _vec, 0, 4 SEPARATOR \ | |
| 658 | lwz 5, 0(4) SEPARATOR \ | |
| 659 | stw 5, _offset(3) SEPARATOR \ | |
| 660 | lwz 5, 4(4) SEPARATOR \ | |
| 661 | stw 5, _offset+4(3) SEPARATOR \ | |
| 662 | lwz 5, 8(4) SEPARATOR \ | |
| 663 | stw 5, _offset+8(3) SEPARATOR \ | |
| 664 | lwz 5, 12(4) SEPARATOR \ | |
| 665 | stw 5, _offset+12(3) | |
| 666 | ||
| 667 | SAVE_VECTOR_UNALIGNED( 0, 424+0x000) | |
| 668 | SAVE_VECTOR_UNALIGNED( 1, 424+0x010) | |
| 669 | SAVE_VECTOR_UNALIGNED( 2, 424+0x020) | |
| 670 | SAVE_VECTOR_UNALIGNED( 3, 424+0x030) | |
| 671 | SAVE_VECTOR_UNALIGNED( 4, 424+0x040) | |
| 672 | SAVE_VECTOR_UNALIGNED( 5, 424+0x050) | |
| 673 | SAVE_VECTOR_UNALIGNED( 6, 424+0x060) | |
| 674 | SAVE_VECTOR_UNALIGNED( 7, 424+0x070) | |
| 675 | SAVE_VECTOR_UNALIGNED( 8, 424+0x080) | |
| 676 | SAVE_VECTOR_UNALIGNED( 9, 424+0x090) | |
| 677 | SAVE_VECTOR_UNALIGNED(10, 424+0x0A0) | |
| 678 | SAVE_VECTOR_UNALIGNED(11, 424+0x0B0) | |
| 679 | SAVE_VECTOR_UNALIGNED(12, 424+0x0C0) | |
| 680 | SAVE_VECTOR_UNALIGNED(13, 424+0x0D0) | |
| 681 | SAVE_VECTOR_UNALIGNED(14, 424+0x0E0) | |
| 682 | SAVE_VECTOR_UNALIGNED(15, 424+0x0F0) | |
| 683 | SAVE_VECTOR_UNALIGNED(16, 424+0x100) | |
| 684 | SAVE_VECTOR_UNALIGNED(17, 424+0x110) | |
| 685 | SAVE_VECTOR_UNALIGNED(18, 424+0x120) | |
| 686 | SAVE_VECTOR_UNALIGNED(19, 424+0x130) | |
| 687 | SAVE_VECTOR_UNALIGNED(20, 424+0x140) | |
| 688 | SAVE_VECTOR_UNALIGNED(21, 424+0x150) | |
| 689 | SAVE_VECTOR_UNALIGNED(22, 424+0x160) | |
| 690 | SAVE_VECTOR_UNALIGNED(23, 424+0x170) | |
| 691 | SAVE_VECTOR_UNALIGNED(24, 424+0x180) | |
| 692 | SAVE_VECTOR_UNALIGNED(25, 424+0x190) | |
| 693 | SAVE_VECTOR_UNALIGNED(26, 424+0x1A0) | |
| 694 | SAVE_VECTOR_UNALIGNED(27, 424+0x1B0) | |
| 695 | SAVE_VECTOR_UNALIGNED(28, 424+0x1C0) | |
| 696 | SAVE_VECTOR_UNALIGNED(29, 424+0x1D0) | |
| 697 | SAVE_VECTOR_UNALIGNED(30, 424+0x1E0) | |
| 698 | SAVE_VECTOR_UNALIGNED(31, 424+0x1F0) | |
| 699 | 699 | #endif |
| 700 | 700 | |
| 701 | li %r3, 0 // return UNW_ESUCCESS | |
| 701 | li 3, 0 // return UNW_ESUCCESS | |
| 702 | 702 | blr |
| 703 | 703 | |
| 704 | 704 | |
| ... | ... | @@ -1026,7 +1026,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1026 | 1026 | jmp %o7 |
| 1027 | 1027 | clr %o0 // return UNW_ESUCCESS |
| 1028 | 1028 | |
| 1029 | #elif defined(__riscv) && __riscv_xlen == 64 | |
| 1029 | #elif defined(__riscv) | |
| 1030 | 1030 | |
| 1031 | 1031 | # |
| 1032 | 1032 | # extern int __unw_getcontext(unw_context_t* thread_state) |
| ... | ... | @@ -1035,73 +1035,73 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1035 | 1035 | # thread_state pointer is in a0 |
| 1036 | 1036 | # |
| 1037 | 1037 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1038 | sd x1, (8 * 0)(a0) // store ra as pc | |
| 1039 | sd x1, (8 * 1)(a0) | |
| 1040 | sd x2, (8 * 2)(a0) | |
| 1041 | sd x3, (8 * 3)(a0) | |
| 1042 | sd x4, (8 * 4)(a0) | |
| 1043 | sd x5, (8 * 5)(a0) | |
| 1044 | sd x6, (8 * 6)(a0) | |
| 1045 | sd x7, (8 * 7)(a0) | |
| 1046 | sd x8, (8 * 8)(a0) | |
| 1047 | sd x9, (8 * 9)(a0) | |
| 1048 | sd x10, (8 * 10)(a0) | |
| 1049 | sd x11, (8 * 11)(a0) | |
| 1050 | sd x12, (8 * 12)(a0) | |
| 1051 | sd x13, (8 * 13)(a0) | |
| 1052 | sd x14, (8 * 14)(a0) | |
| 1053 | sd x15, (8 * 15)(a0) | |
| 1054 | sd x16, (8 * 16)(a0) | |
| 1055 | sd x17, (8 * 17)(a0) | |
| 1056 | sd x18, (8 * 18)(a0) | |
| 1057 | sd x19, (8 * 19)(a0) | |
| 1058 | sd x20, (8 * 20)(a0) | |
| 1059 | sd x21, (8 * 21)(a0) | |
| 1060 | sd x22, (8 * 22)(a0) | |
| 1061 | sd x23, (8 * 23)(a0) | |
| 1062 | sd x24, (8 * 24)(a0) | |
| 1063 | sd x25, (8 * 25)(a0) | |
| 1064 | sd x26, (8 * 26)(a0) | |
| 1065 | sd x27, (8 * 27)(a0) | |
| 1066 | sd x28, (8 * 28)(a0) | |
| 1067 | sd x29, (8 * 29)(a0) | |
| 1068 | sd x30, (8 * 30)(a0) | |
| 1069 | sd x31, (8 * 31)(a0) | |
| 1070 | ||
| 1071 | #if defined(__riscv_flen) && __riscv_flen == 64 | |
| 1072 | fsd f0, (8 * 32 + 8 * 0)(a0) | |
| 1073 | fsd f1, (8 * 32 + 8 * 1)(a0) | |
| 1074 | fsd f2, (8 * 32 + 8 * 2)(a0) | |
| 1075 | fsd f3, (8 * 32 + 8 * 3)(a0) | |
| 1076 | fsd f4, (8 * 32 + 8 * 4)(a0) | |
| 1077 | fsd f5, (8 * 32 + 8 * 5)(a0) | |
| 1078 | fsd f6, (8 * 32 + 8 * 6)(a0) | |
| 1079 | fsd f7, (8 * 32 + 8 * 7)(a0) | |
| 1080 | fsd f8, (8 * 32 + 8 * 8)(a0) | |
| 1081 | fsd f9, (8 * 32 + 8 * 9)(a0) | |
| 1082 | fsd f10, (8 * 32 + 8 * 10)(a0) | |
| 1083 | fsd f11, (8 * 32 + 8 * 11)(a0) | |
| 1084 | fsd f12, (8 * 32 + 8 * 12)(a0) | |
| 1085 | fsd f13, (8 * 32 + 8 * 13)(a0) | |
| 1086 | fsd f14, (8 * 32 + 8 * 14)(a0) | |
| 1087 | fsd f15, (8 * 32 + 8 * 15)(a0) | |
| 1088 | fsd f16, (8 * 32 + 8 * 16)(a0) | |
| 1089 | fsd f17, (8 * 32 + 8 * 17)(a0) | |
| 1090 | fsd f18, (8 * 32 + 8 * 18)(a0) | |
| 1091 | fsd f19, (8 * 32 + 8 * 19)(a0) | |
| 1092 | fsd f20, (8 * 32 + 8 * 20)(a0) | |
| 1093 | fsd f21, (8 * 32 + 8 * 21)(a0) | |
| 1094 | fsd f22, (8 * 32 + 8 * 22)(a0) | |
| 1095 | fsd f23, (8 * 32 + 8 * 23)(a0) | |
| 1096 | fsd f24, (8 * 32 + 8 * 24)(a0) | |
| 1097 | fsd f25, (8 * 32 + 8 * 25)(a0) | |
| 1098 | fsd f26, (8 * 32 + 8 * 26)(a0) | |
| 1099 | fsd f27, (8 * 32 + 8 * 27)(a0) | |
| 1100 | fsd f28, (8 * 32 + 8 * 28)(a0) | |
| 1101 | fsd f29, (8 * 32 + 8 * 29)(a0) | |
| 1102 | fsd f30, (8 * 32 + 8 * 30)(a0) | |
| 1103 | fsd f31, (8 * 32 + 8 * 31)(a0) | |
| 1104 | #endif | |
| 1038 | ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc | |
| 1039 | ISTORE x1, (RISCV_ISIZE * 1)(a0) | |
| 1040 | ISTORE x2, (RISCV_ISIZE * 2)(a0) | |
| 1041 | ISTORE x3, (RISCV_ISIZE * 3)(a0) | |
| 1042 | ISTORE x4, (RISCV_ISIZE * 4)(a0) | |
| 1043 | ISTORE x5, (RISCV_ISIZE * 5)(a0) | |
| 1044 | ISTORE x6, (RISCV_ISIZE * 6)(a0) | |
| 1045 | ISTORE x7, (RISCV_ISIZE * 7)(a0) | |
| 1046 | ISTORE x8, (RISCV_ISIZE * 8)(a0) | |
| 1047 | ISTORE x9, (RISCV_ISIZE * 9)(a0) | |
| 1048 | ISTORE x10, (RISCV_ISIZE * 10)(a0) | |
| 1049 | ISTORE x11, (RISCV_ISIZE * 11)(a0) | |
| 1050 | ISTORE x12, (RISCV_ISIZE * 12)(a0) | |
| 1051 | ISTORE x13, (RISCV_ISIZE * 13)(a0) | |
| 1052 | ISTORE x14, (RISCV_ISIZE * 14)(a0) | |
| 1053 | ISTORE x15, (RISCV_ISIZE * 15)(a0) | |
| 1054 | ISTORE x16, (RISCV_ISIZE * 16)(a0) | |
| 1055 | ISTORE x17, (RISCV_ISIZE * 17)(a0) | |
| 1056 | ISTORE x18, (RISCV_ISIZE * 18)(a0) | |
| 1057 | ISTORE x19, (RISCV_ISIZE * 19)(a0) | |
| 1058 | ISTORE x20, (RISCV_ISIZE * 20)(a0) | |
| 1059 | ISTORE x21, (RISCV_ISIZE * 21)(a0) | |
| 1060 | ISTORE x22, (RISCV_ISIZE * 22)(a0) | |
| 1061 | ISTORE x23, (RISCV_ISIZE * 23)(a0) | |
| 1062 | ISTORE x24, (RISCV_ISIZE * 24)(a0) | |
| 1063 | ISTORE x25, (RISCV_ISIZE * 25)(a0) | |
| 1064 | ISTORE x26, (RISCV_ISIZE * 26)(a0) | |
| 1065 | ISTORE x27, (RISCV_ISIZE * 27)(a0) | |
| 1066 | ISTORE x28, (RISCV_ISIZE * 28)(a0) | |
| 1067 | ISTORE x29, (RISCV_ISIZE * 29)(a0) | |
| 1068 | ISTORE x30, (RISCV_ISIZE * 30)(a0) | |
| 1069 | ISTORE x31, (RISCV_ISIZE * 31)(a0) | |
| 1070 | ||
| 1071 | # if defined(__riscv_flen) | |
| 1072 | FSTORE f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0) | |
| 1073 | FSTORE f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0) | |
| 1074 | FSTORE f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0) | |
| 1075 | FSTORE f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0) | |
| 1076 | FSTORE f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0) | |
| 1077 | FSTORE f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0) | |
| 1078 | FSTORE f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0) | |
| 1079 | FSTORE f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0) | |
| 1080 | FSTORE f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0) | |
| 1081 | FSTORE f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0) | |
| 1082 | FSTORE f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0) | |
| 1083 | FSTORE f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0) | |
| 1084 | FSTORE f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0) | |
| 1085 | FSTORE f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0) | |
| 1086 | FSTORE f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0) | |
| 1087 | FSTORE f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0) | |
| 1088 | FSTORE f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0) | |
| 1089 | FSTORE f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0) | |
| 1090 | FSTORE f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0) | |
| 1091 | FSTORE f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0) | |
| 1092 | FSTORE f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0) | |
| 1093 | FSTORE f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0) | |
| 1094 | FSTORE f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0) | |
| 1095 | FSTORE f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0) | |
| 1096 | FSTORE f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0) | |
| 1097 | FSTORE f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0) | |
| 1098 | FSTORE f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0) | |
| 1099 | FSTORE f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0) | |
| 1100 | FSTORE f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0) | |
| 1101 | FSTORE f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0) | |
| 1102 | FSTORE f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0) | |
| 1103 | FSTORE f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0) | |
| 1104 | # endif | |
| 1105 | 1105 | |
| 1106 | 1106 | li a0, 0 // return UNW_ESUCCESS |
| 1107 | 1107 | ret // jump to ra |
lib/libunwind/src/assembly.h+50-8| ... | ... | @@ -27,6 +27,35 @@ |
| 27 | 27 | #define PPC64_OFFS_V 824 |
| 28 | 28 | #elif defined(__APPLE__) && defined(__aarch64__) |
| 29 | 29 | #define SEPARATOR %% |
| 30 | #elif defined(__riscv) | |
| 31 | # define RISCV_ISIZE (__riscv_xlen / 8) | |
| 32 | # define RISCV_FOFFSET (RISCV_ISIZE * 32) | |
| 33 | # if defined(__riscv_flen) | |
| 34 | # define RISCV_FSIZE (__riscv_flen / 8) | |
| 35 | # endif | |
| 36 | ||
| 37 | # if __riscv_xlen == 64 | |
| 38 | # define ILOAD ld | |
| 39 | # define ISTORE sd | |
| 40 | # elif __riscv_xlen == 32 | |
| 41 | # define ILOAD lw | |
| 42 | # define ISTORE sw | |
| 43 | # else | |
| 44 | # error "Unsupported __riscv_xlen" | |
| 45 | # endif | |
| 46 | ||
| 47 | # if defined(__riscv_flen) | |
| 48 | # if __riscv_flen == 64 | |
| 49 | # define FLOAD fld | |
| 50 | # define FSTORE fsd | |
| 51 | # elif __riscv_flen == 32 | |
| 52 | # define FLOAD flw | |
| 53 | # define FSTORE fsw | |
| 54 | # else | |
| 55 | # error "Unsupported __riscv_flen" | |
| 56 | # endif | |
| 57 | # endif | |
| 58 | # define SEPARATOR ; | |
| 30 | 59 | #else |
| 31 | 60 | #define SEPARATOR ; |
| 32 | 61 | #endif |
| ... | ... | @@ -70,12 +99,15 @@ |
| 70 | 99 | #if defined(__APPLE__) |
| 71 | 100 | |
| 72 | 101 | #define SYMBOL_IS_FUNC(name) |
| 73 | #define EXPORT_SYMBOL(name) | |
| 74 | 102 | #define HIDDEN_SYMBOL(name) .private_extern name |
| 75 | #define WEAK_SYMBOL(name) .weak_reference name | |
| 103 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) | |
| 104 | #define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name) | |
| 105 | #else | |
| 106 | #define EXPORT_SYMBOL(name) | |
| 107 | #endif | |
| 76 | 108 | #define WEAK_ALIAS(name, aliasname) \ |
| 77 | 109 | .globl SYMBOL_NAME(aliasname) SEPARATOR \ |
| 78 | WEAK_SYMBOL(aliasname) SEPARATOR \ | |
| 110 | EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \ | |
| 79 | 111 | SYMBOL_NAME(aliasname) = SYMBOL_NAME(name) |
| 80 | 112 | |
| 81 | 113 | #define NO_EXEC_STACK_DIRECTIVE |
| ... | ... | @@ -87,17 +119,23 @@ |
| 87 | 119 | #else |
| 88 | 120 | #define SYMBOL_IS_FUNC(name) .type name,@function |
| 89 | 121 | #endif |
| 90 | #define EXPORT_SYMBOL(name) | |
| 91 | 122 | #define HIDDEN_SYMBOL(name) .hidden name |
| 123 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) | |
| 124 | #define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name) | |
| 125 | #else | |
| 126 | #define EXPORT_SYMBOL(name) | |
| 127 | #endif | |
| 92 | 128 | #define WEAK_SYMBOL(name) .weak name |
| 93 | 129 | |
| 94 | 130 | #if defined(__hexagon__) |
| 95 | #define WEAK_ALIAS(name, aliasname) \ | |
| 96 | WEAK_SYMBOL(aliasname) SEPARATOR \ | |
| 131 | #define WEAK_ALIAS(name, aliasname) \ | |
| 132 | EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \ | |
| 133 | WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \ | |
| 97 | 134 | .equiv SYMBOL_NAME(aliasname), SYMBOL_NAME(name) |
| 98 | 135 | #else |
| 99 | 136 | #define WEAK_ALIAS(name, aliasname) \ |
| 100 | WEAK_SYMBOL(aliasname) SEPARATOR \ | |
| 137 | EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \ | |
| 138 | WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \ | |
| 101 | 139 | SYMBOL_NAME(aliasname) = SYMBOL_NAME(name) |
| 102 | 140 | #endif |
| 103 | 141 | |
| ... | ... | @@ -119,7 +157,7 @@ |
| 119 | 157 | .section .drectve,"yn" SEPARATOR \ |
| 120 | 158 | .ascii "-export:", #name, "\0" SEPARATOR \ |
| 121 | 159 | .text |
| 122 | #if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS) | |
| 160 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) | |
| 123 | 161 | #define EXPORT_SYMBOL(name) |
| 124 | 162 | #else |
| 125 | 163 | #define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name) |
| ... | ... | @@ -178,4 +216,8 @@ |
| 178 | 216 | #endif |
| 179 | 217 | #endif /* __arm__ */ |
| 180 | 218 | |
| 219 | #if defined(__ppc__) || defined(__powerpc64__) | |
| 220 | #define PPC_LEFT_SHIFT(index) << (index) | |
| 221 | #endif | |
| 222 | ||
| 181 | 223 | #endif /* UNWIND_ASSEMBLY_H */ |
lib/libunwind/src/config.h+8-3| ... | ... | @@ -52,7 +52,8 @@ |
| 52 | 52 | #endif |
| 53 | 53 | #endif |
| 54 | 54 | |
| 55 | #if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS) | |
| 55 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) | |
| 56 | // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility. | |
| 56 | 57 | #define _LIBUNWIND_EXPORT |
| 57 | 58 | #define _LIBUNWIND_HIDDEN |
| 58 | 59 | #else |
| ... | ... | @@ -70,11 +71,15 @@ |
| 70 | 71 | #define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name |
| 71 | 72 | |
| 72 | 73 | #if defined(__APPLE__) |
| 74 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) | |
| 75 | #define _LIBUNWIND_ALIAS_VISIBILITY(name) __asm__(".private_extern " name); | |
| 76 | #else | |
| 77 | #define _LIBUNWIND_ALIAS_VISIBILITY(name) | |
| 78 | #endif | |
| 73 | 79 | #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ |
| 74 | 80 | __asm__(".globl " SYMBOL_NAME(aliasname)); \ |
| 75 | 81 | __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \ |
| 76 | extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ | |
| 77 | __attribute__((weak_import)); | |
| 82 | _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname)) | |
| 78 | 83 | #elif defined(__ELF__) |
| 79 | 84 | #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ |
| 80 | 85 | extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ |
lib/libunwind/src/libunwind.cpp+14-1| ... | ... | @@ -16,6 +16,15 @@ |
| 16 | 16 | |
| 17 | 17 | #include <stdlib.h> |
| 18 | 18 | |
| 19 | // Define the __has_feature extension for compilers that do not support it so | |
| 20 | // that we can later check for the presence of ASan in a compiler-neutral way. | |
| 21 | #if !defined(__has_feature) | |
| 22 | #define __has_feature(feature) 0 | |
| 23 | #endif | |
| 24 | ||
| 25 | #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) | |
| 26 | #include <sanitizer/asan_interface.h> | |
| 27 | #endif | |
| 19 | 28 | |
| 20 | 29 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
| 21 | 30 | #include "AddressSpace.hpp" |
| ... | ... | @@ -60,7 +69,7 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, |
| 60 | 69 | # warning The MIPS architecture is not supported with this ABI and environment! |
| 61 | 70 | #elif defined(__sparc__) |
| 62 | 71 | # define REGISTER_KIND Registers_sparc |
| 63 | #elif defined(__riscv) && __riscv_xlen == 64 | |
| 72 | #elif defined(__riscv) | |
| 64 | 73 | # define REGISTER_KIND Registers_riscv |
| 65 | 74 | #elif defined(__ve__) |
| 66 | 75 | # define REGISTER_KIND Registers_ve |
| ... | ... | @@ -184,6 +193,10 @@ _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info) |
| 184 | 193 | /// Resume execution at cursor position (aka longjump). |
| 185 | 194 | _LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) { |
| 186 | 195 | _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor)); |
| 196 | #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) | |
| 197 | // Inform the ASan runtime that now might be a good time to clean stuff up. | |
| 198 | __asan_handle_no_return(); | |
| 199 | #endif | |
| 187 | 200 | AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; |
| 188 | 201 | co->jumpto(); |
| 189 | 202 | return UNW_EUNSPEC; |
lib/tsan/interception/interception.h+13-22| ... | ... | @@ -16,10 +16,10 @@ |
| 16 | 16 | |
| 17 | 17 | #include "sanitizer_common/sanitizer_internal_defs.h" |
| 18 | 18 | |
| 19 | #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC && \ | |
| 20 | !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_WINDOWS && \ | |
| 21 | !SANITIZER_FUCHSIA && !SANITIZER_RTEMS && !SANITIZER_SOLARIS | |
| 22 | # error "Interception doesn't work on this operating system." | |
| 19 | #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC && \ | |
| 20 | !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \ | |
| 21 | !SANITIZER_SOLARIS | |
| 22 | # error "Interception doesn't work on this operating system." | |
| 23 | 23 | #endif |
| 24 | 24 | |
| 25 | 25 | // These typedefs should be used only in the interceptor definitions to replace |
| ... | ... | @@ -130,11 +130,6 @@ const interpose_substitution substitution_##func_name[] \ |
| 130 | 130 | extern "C" ret_type func(__VA_ARGS__); |
| 131 | 131 | # define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \ |
| 132 | 132 | extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__); |
| 133 | #elif SANITIZER_RTEMS | |
| 134 | # define WRAP(x) x | |
| 135 | # define WRAPPER_NAME(x) #x | |
| 136 | # define INTERCEPTOR_ATTRIBUTE | |
| 137 | # define DECLARE_WRAPPER(ret_type, func, ...) | |
| 138 | 133 | #elif SANITIZER_FREEBSD || SANITIZER_NETBSD |
| 139 | 134 | # define WRAP(x) __interceptor_ ## x |
| 140 | 135 | # define WRAPPER_NAME(x) "__interceptor_" #x |
| ... | ... | @@ -162,10 +157,6 @@ const interpose_substitution substitution_##func_name[] \ |
| 162 | 157 | # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) |
| 163 | 158 | # define REAL(x) __unsanitized_##x |
| 164 | 159 | # define DECLARE_REAL(ret_type, func, ...) |
| 165 | #elif SANITIZER_RTEMS | |
| 166 | # define REAL(x) __real_ ## x | |
| 167 | # define DECLARE_REAL(ret_type, func, ...) \ | |
| 168 | extern "C" ret_type REAL(func)(__VA_ARGS__); | |
| 169 | 160 | #elif !SANITIZER_MAC |
| 170 | 161 | # define PTR_TO_REAL(x) real_##x |
| 171 | 162 | # define REAL(x) __interception::PTR_TO_REAL(x) |
| ... | ... | @@ -184,10 +175,10 @@ const interpose_substitution substitution_##func_name[] \ |
| 184 | 175 | # define ASSIGN_REAL(x, y) |
| 185 | 176 | #endif // SANITIZER_MAC |
| 186 | 177 | |
| 187 | #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS | |
| 188 | # define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \ | |
| 189 | DECLARE_REAL(ret_type, func, __VA_ARGS__) \ | |
| 190 | extern "C" ret_type WRAP(func)(__VA_ARGS__); | |
| 178 | #if !SANITIZER_FUCHSIA | |
| 179 | # define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \ | |
| 180 | DECLARE_REAL(ret_type, func, __VA_ARGS__) \ | |
| 181 | extern "C" ret_type WRAP(func)(__VA_ARGS__); | |
| 191 | 182 | // Declare an interceptor and its wrapper defined in a different translation |
| 192 | 183 | // unit (ex. asm). |
| 193 | 184 | # define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \ |
| ... | ... | @@ -202,11 +193,11 @@ const interpose_substitution substitution_##func_name[] \ |
| 202 | 193 | // macros does its job. In exceptional cases you may need to call REAL(foo) |
| 203 | 194 | // without defining INTERCEPTOR(..., foo, ...). For example, if you override |
| 204 | 195 | // foo with an interceptor for other function. |
| 205 | #if !SANITIZER_MAC && !SANITIZER_FUCHSIA && !SANITIZER_RTEMS | |
| 206 | # define DEFINE_REAL(ret_type, func, ...) \ | |
| 196 | #if !SANITIZER_MAC && !SANITIZER_FUCHSIA | |
| 197 | # define DEFINE_REAL(ret_type, func, ...) \ | |
| 207 | 198 | typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \ |
| 208 | namespace __interception { \ | |
| 209 | FUNC_TYPE(func) PTR_TO_REAL(func); \ | |
| 199 | namespace __interception { \ | |
| 200 | FUNC_TYPE(func) PTR_TO_REAL(func); \ | |
| 210 | 201 | } |
| 211 | 202 | #else |
| 212 | 203 | # define DEFINE_REAL(ret_type, func, ...) |
| ... | ... | @@ -281,7 +272,7 @@ typedef unsigned long uptr; |
| 281 | 272 | #define INCLUDED_FROM_INTERCEPTION_LIB |
| 282 | 273 | |
| 283 | 274 | #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ |
| 284 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 275 | SANITIZER_SOLARIS | |
| 285 | 276 | |
| 286 | 277 | # include "interception_linux.h" |
| 287 | 278 | # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) |
lib/tsan/interception/interception_linux.cpp+5-5| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | #include "interception.h" |
| 15 | 15 | |
| 16 | 16 | #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ |
| 17 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 17 | SANITIZER_SOLARIS | |
| 18 | 18 | |
| 19 | 19 | #include <dlfcn.h> // for dlsym() and dlvsym() |
| 20 | 20 | |
| ... | ... | @@ -63,8 +63,8 @@ bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, |
| 63 | 63 | return addr && (func == wrapper); |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | // Android and Solaris do not have dlvsym | |
| 67 | #if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD | |
| 66 | // dlvsym is a GNU extension supported by some other platforms. | |
| 67 | #if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 68 | 68 | static void *GetFuncAddr(const char *name, const char *ver) { |
| 69 | 69 | return dlvsym(RTLD_NEXT, name, ver); |
| 70 | 70 | } |
| ... | ... | @@ -75,9 +75,9 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, |
| 75 | 75 | *ptr_to_real = (uptr)addr; |
| 76 | 76 | return addr && (func == wrapper); |
| 77 | 77 | } |
| 78 | #endif // !SANITIZER_ANDROID | |
| 78 | #endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 79 | 79 | |
| 80 | 80 | } // namespace __interception |
| 81 | 81 | |
| 82 | 82 | #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || |
| 83 | // SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 83 | // SANITIZER_SOLARIS |
lib/tsan/interception/interception_linux.h+5-5| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | //===----------------------------------------------------------------------===// |
| 13 | 13 | |
| 14 | 14 | #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ |
| 15 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 15 | SANITIZER_SOLARIS | |
| 16 | 16 | |
| 17 | 17 | #if !defined(INCLUDED_FROM_INTERCEPTION_LIB) |
| 18 | 18 | # error "interception_linux.h should be included from interception library only" |
| ... | ... | @@ -35,8 +35,8 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, |
| 35 | 35 | (::__interception::uptr) & (func), \ |
| 36 | 36 | (::__interception::uptr) & WRAP(func)) |
| 37 | 37 | |
| 38 | // Android, Solaris and OpenBSD do not have dlvsym | |
| 39 | #if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD | |
| 38 | // dlvsym is a GNU extension supported by some other platforms. | |
| 39 | #if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 40 | 40 | #define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \ |
| 41 | 41 | ::__interception::InterceptFunction( \ |
| 42 | 42 | #func, symver, \ |
| ... | ... | @@ -46,8 +46,8 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, |
| 46 | 46 | #else |
| 47 | 47 | #define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \ |
| 48 | 48 | INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) |
| 49 | #endif // !SANITIZER_ANDROID && !SANITIZER_SOLARIS | |
| 49 | #endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 50 | 50 | |
| 51 | 51 | #endif // INTERCEPTION_LINUX_H |
| 52 | 52 | #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || |
| 53 | // SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 53 | // SANITIZER_SOLARIS |
lib/tsan/interception/interception_win.cpp+3-3| ... | ... | @@ -136,7 +136,7 @@ namespace __interception { |
| 136 | 136 | static const int kAddressLength = FIRST_32_SECOND_64(4, 8); |
| 137 | 137 | static const int kJumpInstructionLength = 5; |
| 138 | 138 | static const int kShortJumpInstructionLength = 2; |
| 139 | static const int kIndirectJumpInstructionLength = 6; | |
| 139 | UNUSED static const int kIndirectJumpInstructionLength = 6; | |
| 140 | 140 | static const int kBranchLength = |
| 141 | 141 | FIRST_32_SECOND_64(kJumpInstructionLength, kIndirectJumpInstructionLength); |
| 142 | 142 | static const int kDirectBranchLength = kBranchLength + kAddressLength; |
| ... | ... | @@ -165,7 +165,7 @@ static uptr GetMmapGranularity() { |
| 165 | 165 | return si.dwAllocationGranularity; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | static uptr RoundUpTo(uptr size, uptr boundary) { | |
| 168 | UNUSED static uptr RoundUpTo(uptr size, uptr boundary) { | |
| 169 | 169 | return (size + boundary - 1) & ~(boundary - 1); |
| 170 | 170 | } |
| 171 | 171 | |
| ... | ... | @@ -309,7 +309,7 @@ struct TrampolineMemoryRegion { |
| 309 | 309 | uptr max_size; |
| 310 | 310 | }; |
| 311 | 311 | |
| 312 | static const uptr kTrampolineScanLimitRange = 1 << 31; // 2 gig | |
| 312 | UNUSED static const uptr kTrampolineScanLimitRange = 1 << 31; // 2 gig | |
| 313 | 313 | static const int kMaxTrampolineRegion = 1024; |
| 314 | 314 | static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion]; |
| 315 | 315 |
lib/tsan/sanitizer_common/sanitizer_addrhashmap.h+53-53| ... | ... | @@ -162,8 +162,8 @@ AddrHashMap<T, kSize>::AddrHashMap() { |
| 162 | 162 | table_ = (Bucket*)MmapOrDie(kSize * sizeof(table_[0]), "AddrHashMap"); |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | template<typename T, uptr kSize> | |
| 166 | void AddrHashMap<T, kSize>::acquire(Handle *h) { | |
| 165 | template <typename T, uptr kSize> | |
| 166 | void AddrHashMap<T, kSize>::acquire(Handle *h) NO_THREAD_SAFETY_ANALYSIS { | |
| 167 | 167 | uptr addr = h->addr_; |
| 168 | 168 | uptr hash = calcHash(addr); |
| 169 | 169 | Bucket *b = &table_[hash]; |
| ... | ... | @@ -289,57 +289,57 @@ void AddrHashMap<T, kSize>::acquire(Handle *h) { |
| 289 | 289 | CHECK_EQ(atomic_load(&c->addr, memory_order_relaxed), 0); |
| 290 | 290 | h->addidx_ = i; |
| 291 | 291 | h->cell_ = c; |
| 292 | } | |
| 293 | ||
| 294 | template<typename T, uptr kSize> | |
| 295 | void AddrHashMap<T, kSize>::release(Handle *h) { | |
| 296 | if (!h->cell_) | |
| 297 | return; | |
| 298 | Bucket *b = h->bucket_; | |
| 299 | Cell *c = h->cell_; | |
| 300 | uptr addr1 = atomic_load(&c->addr, memory_order_relaxed); | |
| 301 | if (h->created_) { | |
| 302 | // Denote completion of insertion. | |
| 303 | CHECK_EQ(addr1, 0); | |
| 304 | // After the following store, the element becomes available | |
| 305 | // for lock-free reads. | |
| 306 | atomic_store(&c->addr, h->addr_, memory_order_release); | |
| 307 | b->mtx.Unlock(); | |
| 308 | } else if (h->remove_) { | |
| 309 | // Denote that the cell is empty now. | |
| 310 | CHECK_EQ(addr1, h->addr_); | |
| 311 | atomic_store(&c->addr, 0, memory_order_release); | |
| 312 | // See if we need to compact the bucket. | |
| 313 | AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed); | |
| 314 | if (h->addidx_ == -1U) { | |
| 315 | // Removed from embed array, move an add element into the freed cell. | |
| 316 | if (add && add->size != 0) { | |
| 317 | uptr last = --add->size; | |
| 318 | Cell *c1 = &add->cells[last]; | |
| 319 | c->val = c1->val; | |
| 320 | uptr addr1 = atomic_load(&c1->addr, memory_order_relaxed); | |
| 321 | atomic_store(&c->addr, addr1, memory_order_release); | |
| 322 | atomic_store(&c1->addr, 0, memory_order_release); | |
| 323 | } | |
| 324 | } else { | |
| 325 | // Removed from add array, compact it. | |
| 326 | uptr last = --add->size; | |
| 327 | Cell *c1 = &add->cells[last]; | |
| 328 | if (c != c1) { | |
| 329 | *c = *c1; | |
| 330 | atomic_store(&c1->addr, 0, memory_order_relaxed); | |
| 331 | } | |
| 332 | } | |
| 333 | if (add && add->size == 0) { | |
| 334 | // FIXME(dvyukov): free add? | |
| 335 | } | |
| 336 | b->mtx.Unlock(); | |
| 337 | } else { | |
| 338 | CHECK_EQ(addr1, h->addr_); | |
| 339 | if (h->addidx_ != -1U) | |
| 340 | b->mtx.ReadUnlock(); | |
| 341 | } | |
| 342 | } | |
| 292 | } | |
| 293 | ||
| 294 | template <typename T, uptr kSize> | |
| 295 | void AddrHashMap<T, kSize>::release(Handle *h) NO_THREAD_SAFETY_ANALYSIS { | |
| 296 | if (!h->cell_) | |
| 297 | return; | |
| 298 | Bucket *b = h->bucket_; | |
| 299 | Cell *c = h->cell_; | |
| 300 | uptr addr1 = atomic_load(&c->addr, memory_order_relaxed); | |
| 301 | if (h->created_) { | |
| 302 | // Denote completion of insertion. | |
| 303 | CHECK_EQ(addr1, 0); | |
| 304 | // After the following store, the element becomes available | |
| 305 | // for lock-free reads. | |
| 306 | atomic_store(&c->addr, h->addr_, memory_order_release); | |
| 307 | b->mtx.Unlock(); | |
| 308 | } else if (h->remove_) { | |
| 309 | // Denote that the cell is empty now. | |
| 310 | CHECK_EQ(addr1, h->addr_); | |
| 311 | atomic_store(&c->addr, 0, memory_order_release); | |
| 312 | // See if we need to compact the bucket. | |
| 313 | AddBucket *add = (AddBucket *)atomic_load(&b->add, memory_order_relaxed); | |
| 314 | if (h->addidx_ == -1U) { | |
| 315 | // Removed from embed array, move an add element into the freed cell. | |
| 316 | if (add && add->size != 0) { | |
| 317 | uptr last = --add->size; | |
| 318 | Cell *c1 = &add->cells[last]; | |
| 319 | c->val = c1->val; | |
| 320 | uptr addr1 = atomic_load(&c1->addr, memory_order_relaxed); | |
| 321 | atomic_store(&c->addr, addr1, memory_order_release); | |
| 322 | atomic_store(&c1->addr, 0, memory_order_release); | |
| 323 | } | |
| 324 | } else { | |
| 325 | // Removed from add array, compact it. | |
| 326 | uptr last = --add->size; | |
| 327 | Cell *c1 = &add->cells[last]; | |
| 328 | if (c != c1) { | |
| 329 | *c = *c1; | |
| 330 | atomic_store(&c1->addr, 0, memory_order_relaxed); | |
| 331 | } | |
| 332 | } | |
| 333 | if (add && add->size == 0) { | |
| 334 | // FIXME(dvyukov): free add? | |
| 335 | } | |
| 336 | b->mtx.Unlock(); | |
| 337 | } else { | |
| 338 | CHECK_EQ(addr1, h->addr_); | |
| 339 | if (h->addidx_ != -1U) | |
| 340 | b->mtx.ReadUnlock(); | |
| 341 | } | |
| 342 | } | |
| 343 | 343 | |
| 344 | 344 | template<typename T, uptr kSize> |
| 345 | 345 | uptr AddrHashMap<T, kSize>::calcHash(uptr addr) { |
lib/tsan/sanitizer_common/sanitizer_allocator.cpp+4-21| ... | ... | @@ -137,8 +137,6 @@ static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) { |
| 137 | 137 | |
| 138 | 138 | #endif // SANITIZER_GO || defined(SANITIZER_USE_MALLOC) |
| 139 | 139 | |
| 140 | const u64 kBlockMagic = 0x6A6CB03ABCEBC041ull; | |
| 141 | ||
| 142 | 140 | static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) { |
| 143 | 141 | SetAllocatorOutOfMemory(); |
| 144 | 142 | Report("FATAL: %s: internal allocator is out of memory trying to allocate " |
| ... | ... | @@ -147,27 +145,17 @@ static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) { |
| 147 | 145 | } |
| 148 | 146 | |
| 149 | 147 | void *InternalAlloc(uptr size, InternalAllocatorCache *cache, uptr alignment) { |
| 150 | if (size + sizeof(u64) < size) | |
| 151 | return nullptr; | |
| 152 | void *p = RawInternalAlloc(size + sizeof(u64), cache, alignment); | |
| 148 | void *p = RawInternalAlloc(size, cache, alignment); | |
| 153 | 149 | if (UNLIKELY(!p)) |
| 154 | ReportInternalAllocatorOutOfMemory(size + sizeof(u64)); | |
| 155 | ((u64*)p)[0] = kBlockMagic; | |
| 156 | return (char*)p + sizeof(u64); | |
| 150 | ReportInternalAllocatorOutOfMemory(size); | |
| 151 | return p; | |
| 157 | 152 | } |
| 158 | 153 | |
| 159 | 154 | void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) { |
| 160 | if (!addr) | |
| 161 | return InternalAlloc(size, cache); | |
| 162 | if (size + sizeof(u64) < size) | |
| 163 | return nullptr; | |
| 164 | addr = (char*)addr - sizeof(u64); | |
| 165 | size = size + sizeof(u64); | |
| 166 | CHECK_EQ(kBlockMagic, ((u64*)addr)[0]); | |
| 167 | 155 | void *p = RawInternalRealloc(addr, size, cache); |
| 168 | 156 | if (UNLIKELY(!p)) |
| 169 | 157 | ReportInternalAllocatorOutOfMemory(size); |
| 170 | return (char*)p + sizeof(u64); | |
| 158 | return p; | |
| 171 | 159 | } |
| 172 | 160 | |
| 173 | 161 | void *InternalReallocArray(void *addr, uptr count, uptr size, |
| ... | ... | @@ -196,11 +184,6 @@ void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) { |
| 196 | 184 | } |
| 197 | 185 | |
| 198 | 186 | void InternalFree(void *addr, InternalAllocatorCache *cache) { |
| 199 | if (!addr) | |
| 200 | return; | |
| 201 | addr = (char*)addr - sizeof(u64); | |
| 202 | CHECK_EQ(kBlockMagic, ((u64*)addr)[0]); | |
| 203 | ((u64*)addr)[0] = 0; | |
| 204 | 187 | RawInternalFree(addr, cache); |
| 205 | 188 | } |
| 206 | 189 |
lib/tsan/sanitizer_common/sanitizer_allocator.h+3-3| ... | ... | @@ -52,14 +52,14 @@ struct NoOpMapUnmapCallback { |
| 52 | 52 | // Callback type for iterating over chunks. |
| 53 | 53 | typedef void (*ForEachChunkCallback)(uptr chunk, void *arg); |
| 54 | 54 | |
| 55 | INLINE u32 Rand(u32 *state) { // ANSI C linear congruential PRNG. | |
| 55 | inline u32 Rand(u32 *state) { // ANSI C linear congruential PRNG. | |
| 56 | 56 | return (*state = *state * 1103515245 + 12345) >> 16; |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | INLINE u32 RandN(u32 *state, u32 n) { return Rand(state) % n; } // [0, n) | |
| 59 | inline u32 RandN(u32 *state, u32 n) { return Rand(state) % n; } // [0, n) | |
| 60 | 60 | |
| 61 | 61 | template<typename T> |
| 62 | INLINE void RandomShuffle(T *a, u32 n, u32 *rand_state) { | |
| 62 | inline void RandomShuffle(T *a, u32 n, u32 *rand_state) { | |
| 63 | 63 | if (n <= 1) return; |
| 64 | 64 | u32 state = *rand_state; |
| 65 | 65 | for (u32 i = n - 1; i > 0; i--) |
lib/tsan/sanitizer_common/sanitizer_allocator_checks.h+5-5| ... | ... | @@ -27,7 +27,7 @@ namespace __sanitizer { |
| 27 | 27 | void SetErrnoToENOMEM(); |
| 28 | 28 | |
| 29 | 29 | // A common errno setting logic shared by almost all sanitizer allocator APIs. |
| 30 | INLINE void *SetErrnoOnNull(void *ptr) { | |
| 30 | inline void *SetErrnoOnNull(void *ptr) { | |
| 31 | 31 | if (UNLIKELY(!ptr)) |
| 32 | 32 | SetErrnoToENOMEM(); |
| 33 | 33 | return ptr; |
| ... | ... | @@ -41,7 +41,7 @@ INLINE void *SetErrnoOnNull(void *ptr) { |
| 41 | 41 | // two and that the size is a multiple of alignment for POSIX implementation, |
| 42 | 42 | // and a bit relaxed requirement for non-POSIX ones, that the size is a multiple |
| 43 | 43 | // of alignment. |
| 44 | INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) { | |
| 44 | inline bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) { | |
| 45 | 45 | #if SANITIZER_POSIX |
| 46 | 46 | return alignment != 0 && IsPowerOfTwo(alignment) && |
| 47 | 47 | (size & (alignment - 1)) == 0; |
| ... | ... | @@ -52,13 +52,13 @@ INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) { |
| 52 | 52 | |
| 53 | 53 | // Checks posix_memalign() parameters, verifies that alignment is a power of two |
| 54 | 54 | // and a multiple of sizeof(void *). |
| 55 | INLINE bool CheckPosixMemalignAlignment(uptr alignment) { | |
| 55 | inline bool CheckPosixMemalignAlignment(uptr alignment) { | |
| 56 | 56 | return alignment != 0 && IsPowerOfTwo(alignment) && |
| 57 | 57 | (alignment % sizeof(void *)) == 0; |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | // Returns true if calloc(size, n) call overflows on size*n calculation. |
| 61 | INLINE bool CheckForCallocOverflow(uptr size, uptr n) { | |
| 61 | inline bool CheckForCallocOverflow(uptr size, uptr n) { | |
| 62 | 62 | if (!size) |
| 63 | 63 | return false; |
| 64 | 64 | uptr max = (uptr)-1L; |
| ... | ... | @@ -67,7 +67,7 @@ INLINE bool CheckForCallocOverflow(uptr size, uptr n) { |
| 67 | 67 | |
| 68 | 68 | // Returns true if the size passed to pvalloc overflows when rounded to the next |
| 69 | 69 | // multiple of page_size. |
| 70 | INLINE bool CheckForPvallocOverflow(uptr size, uptr page_size) { | |
| 70 | inline bool CheckForPvallocOverflow(uptr size, uptr page_size) { | |
| 71 | 71 | return RoundUpTo(size, page_size) < size; |
| 72 | 72 | } |
| 73 | 73 |
lib/tsan/sanitizer_common/sanitizer_allocator_combined.h+4-4| ... | ... | @@ -35,9 +35,9 @@ class CombinedAllocator { |
| 35 | 35 | secondary_.InitLinkerInitialized(); |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | void Init(s32 release_to_os_interval_ms) { | |
| 38 | void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) { | |
| 39 | 39 | stats_.Init(); |
| 40 | primary_.Init(release_to_os_interval_ms); | |
| 40 | primary_.Init(release_to_os_interval_ms, heap_start); | |
| 41 | 41 | secondary_.Init(); |
| 42 | 42 | } |
| 43 | 43 | |
| ... | ... | @@ -177,12 +177,12 @@ class CombinedAllocator { |
| 177 | 177 | |
| 178 | 178 | // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone |
| 179 | 179 | // introspection API. |
| 180 | void ForceLock() { | |
| 180 | void ForceLock() NO_THREAD_SAFETY_ANALYSIS { | |
| 181 | 181 | primary_.ForceLock(); |
| 182 | 182 | secondary_.ForceLock(); |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | void ForceUnlock() { | |
| 185 | void ForceUnlock() NO_THREAD_SAFETY_ANALYSIS { | |
| 186 | 186 | secondary_.ForceUnlock(); |
| 187 | 187 | primary_.ForceUnlock(); |
| 188 | 188 | } |
lib/tsan/sanitizer_common/sanitizer_allocator_local_cache.h+13-6| ... | ... | @@ -17,6 +17,7 @@ |
| 17 | 17 | template <class SizeClassAllocator> |
| 18 | 18 | struct SizeClassAllocator64LocalCache { |
| 19 | 19 | typedef SizeClassAllocator Allocator; |
| 20 | typedef MemoryMapper<Allocator> MemoryMapperT; | |
| 20 | 21 | |
| 21 | 22 | void Init(AllocatorGlobalStats *s) { |
| 22 | 23 | stats_.Init(); |
| ... | ... | @@ -53,7 +54,7 @@ struct SizeClassAllocator64LocalCache { |
| 53 | 54 | PerClass *c = &per_class_[class_id]; |
| 54 | 55 | InitCache(c); |
| 55 | 56 | if (UNLIKELY(c->count == c->max_count)) |
| 56 | Drain(c, allocator, class_id, c->max_count / 2); | |
| 57 | DrainHalfMax(c, allocator, class_id); | |
| 57 | 58 | CompactPtrT chunk = allocator->PointerToCompactPtr( |
| 58 | 59 | allocator->GetRegionBeginBySizeClass(class_id), |
| 59 | 60 | reinterpret_cast<uptr>(p)); |
| ... | ... | @@ -62,10 +63,10 @@ struct SizeClassAllocator64LocalCache { |
| 62 | 63 | } |
| 63 | 64 | |
| 64 | 65 | void Drain(SizeClassAllocator *allocator) { |
| 66 | MemoryMapperT memory_mapper(*allocator); | |
| 65 | 67 | for (uptr i = 1; i < kNumClasses; i++) { |
| 66 | 68 | PerClass *c = &per_class_[i]; |
| 67 | while (c->count > 0) | |
| 68 | Drain(c, allocator, i, c->count); | |
| 69 | while (c->count > 0) Drain(&memory_mapper, c, allocator, i, c->count); | |
| 69 | 70 | } |
| 70 | 71 | } |
| 71 | 72 | |
| ... | ... | @@ -106,12 +107,18 @@ struct SizeClassAllocator64LocalCache { |
| 106 | 107 | return true; |
| 107 | 108 | } |
| 108 | 109 | |
| 109 | NOINLINE void Drain(PerClass *c, SizeClassAllocator *allocator, uptr class_id, | |
| 110 | uptr count) { | |
| 110 | NOINLINE void DrainHalfMax(PerClass *c, SizeClassAllocator *allocator, | |
| 111 | uptr class_id) { | |
| 112 | MemoryMapperT memory_mapper(*allocator); | |
| 113 | Drain(&memory_mapper, c, allocator, class_id, c->max_count / 2); | |
| 114 | } | |
| 115 | ||
| 116 | void Drain(MemoryMapperT *memory_mapper, PerClass *c, | |
| 117 | SizeClassAllocator *allocator, uptr class_id, uptr count) { | |
| 111 | 118 | CHECK_GE(c->count, count); |
| 112 | 119 | const uptr first_idx_to_drain = c->count - count; |
| 113 | 120 | c->count -= count; |
| 114 | allocator->ReturnToAllocator(&stats_, class_id, | |
| 121 | allocator->ReturnToAllocator(memory_mapper, &stats_, class_id, | |
| 115 | 122 | &c->chunks[first_idx_to_drain], count); |
| 116 | 123 | } |
| 117 | 124 | }; |
lib/tsan/sanitizer_common/sanitizer_allocator_primary32.h+5-3| ... | ... | @@ -119,7 +119,8 @@ class SizeClassAllocator32 { |
| 119 | 119 | typedef SizeClassAllocator32<Params> ThisT; |
| 120 | 120 | typedef SizeClassAllocator32LocalCache<ThisT> AllocatorCache; |
| 121 | 121 | |
| 122 | void Init(s32 release_to_os_interval_ms) { | |
| 122 | void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) { | |
| 123 | CHECK(!heap_start); | |
| 123 | 124 | possible_regions.Init(); |
| 124 | 125 | internal_memset(size_class_info_array, 0, sizeof(size_class_info_array)); |
| 125 | 126 | } |
| ... | ... | @@ -153,6 +154,7 @@ class SizeClassAllocator32 { |
| 153 | 154 | } |
| 154 | 155 | |
| 155 | 156 | void *GetMetaData(const void *p) { |
| 157 | CHECK(kMetadataSize); | |
| 156 | 158 | CHECK(PointerIsMine(p)); |
| 157 | 159 | uptr mem = reinterpret_cast<uptr>(p); |
| 158 | 160 | uptr beg = ComputeRegionBeg(mem); |
| ... | ... | @@ -235,13 +237,13 @@ class SizeClassAllocator32 { |
| 235 | 237 | |
| 236 | 238 | // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone |
| 237 | 239 | // introspection API. |
| 238 | void ForceLock() { | |
| 240 | void ForceLock() NO_THREAD_SAFETY_ANALYSIS { | |
| 239 | 241 | for (uptr i = 0; i < kNumClasses; i++) { |
| 240 | 242 | GetSizeClassInfo(i)->mutex.Lock(); |
| 241 | 243 | } |
| 242 | 244 | } |
| 243 | 245 | |
| 244 | void ForceUnlock() { | |
| 246 | void ForceUnlock() NO_THREAD_SAFETY_ANALYSIS { | |
| 245 | 247 | for (int i = kNumClasses - 1; i >= 0; i--) { |
| 246 | 248 | GetSizeClassInfo(i)->mutex.Unlock(); |
| 247 | 249 | } |
lib/tsan/sanitizer_common/sanitizer_allocator_primary64.h+145-111| ... | ... | @@ -19,7 +19,7 @@ template<class SizeClassAllocator> struct SizeClassAllocator64LocalCache; |
| 19 | 19 | // The template parameter Params is a class containing the actual parameters. |
| 20 | 20 | // |
| 21 | 21 | // Space: a portion of address space of kSpaceSize bytes starting at SpaceBeg. |
| 22 | // If kSpaceBeg is ~0 then SpaceBeg is chosen dynamically my mmap. | |
| 22 | // If kSpaceBeg is ~0 then SpaceBeg is chosen dynamically by mmap. | |
| 23 | 23 | // Otherwise SpaceBeg=kSpaceBeg (fixed address). |
| 24 | 24 | // kSpaceSize is a power of two. |
| 25 | 25 | // At the beginning the entire space is mprotect-ed, then small parts of it |
| ... | ... | @@ -42,6 +42,44 @@ struct SizeClassAllocator64FlagMasks { // Bit masks. |
| 42 | 42 | }; |
| 43 | 43 | }; |
| 44 | 44 | |
| 45 | template <typename Allocator> | |
| 46 | class MemoryMapper { | |
| 47 | public: | |
| 48 | typedef typename Allocator::CompactPtrT CompactPtrT; | |
| 49 | ||
| 50 | explicit MemoryMapper(const Allocator &allocator) : allocator_(allocator) {} | |
| 51 | ||
| 52 | bool GetAndResetStats(uptr &ranges, uptr &bytes) { | |
| 53 | ranges = released_ranges_count_; | |
| 54 | released_ranges_count_ = 0; | |
| 55 | bytes = released_bytes_; | |
| 56 | released_bytes_ = 0; | |
| 57 | return ranges != 0; | |
| 58 | } | |
| 59 | ||
| 60 | u64 *MapPackedCounterArrayBuffer(uptr count) { | |
| 61 | buffer_.clear(); | |
| 62 | buffer_.resize(count); | |
| 63 | return buffer_.data(); | |
| 64 | } | |
| 65 | ||
| 66 | // Releases [from, to) range of pages back to OS. | |
| 67 | void ReleasePageRangeToOS(uptr class_id, CompactPtrT from, CompactPtrT to) { | |
| 68 | const uptr region_base = allocator_.GetRegionBeginBySizeClass(class_id); | |
| 69 | const uptr from_page = allocator_.CompactPtrToPointer(region_base, from); | |
| 70 | const uptr to_page = allocator_.CompactPtrToPointer(region_base, to); | |
| 71 | ReleaseMemoryPagesToOS(from_page, to_page); | |
| 72 | released_ranges_count_++; | |
| 73 | released_bytes_ += to_page - from_page; | |
| 74 | } | |
| 75 | ||
| 76 | private: | |
| 77 | const Allocator &allocator_; | |
| 78 | uptr released_ranges_count_ = 0; | |
| 79 | uptr released_bytes_ = 0; | |
| 80 | InternalMmapVector<u64> buffer_; | |
| 81 | }; | |
| 82 | ||
| 45 | 83 | template <class Params> |
| 46 | 84 | class SizeClassAllocator64 { |
| 47 | 85 | public: |
| ... | ... | @@ -57,6 +95,7 @@ class SizeClassAllocator64 { |
| 57 | 95 | |
| 58 | 96 | typedef SizeClassAllocator64<Params> ThisT; |
| 59 | 97 | typedef SizeClassAllocator64LocalCache<ThisT> AllocatorCache; |
| 98 | typedef MemoryMapper<ThisT> MemoryMapperT; | |
| 60 | 99 | |
| 61 | 100 | // When we know the size class (the region base) we can represent a pointer |
| 62 | 101 | // as a 4-byte integer (offset from the region start shifted right by 4). |
| ... | ... | @@ -69,25 +108,45 @@ class SizeClassAllocator64 { |
| 69 | 108 | return base + (static_cast<uptr>(ptr32) << kCompactPtrScale); |
| 70 | 109 | } |
| 71 | 110 | |
| 72 | void Init(s32 release_to_os_interval_ms) { | |
| 111 | // If heap_start is nonzero, assumes kSpaceSize bytes are already mapped R/W | |
| 112 | // at heap_start and places the heap there. This mode requires kSpaceBeg == | |
| 113 | // ~(uptr)0. | |
| 114 | void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) { | |
| 73 | 115 | uptr TotalSpaceSize = kSpaceSize + AdditionalSize(); |
| 74 | if (kUsingConstantSpaceBeg) { | |
| 75 | CHECK(IsAligned(kSpaceBeg, SizeClassMap::kMaxSize)); | |
| 76 | CHECK_EQ(kSpaceBeg, address_range.Init(TotalSpaceSize, | |
| 77 | PrimaryAllocatorName, kSpaceBeg)); | |
| 116 | PremappedHeap = heap_start != 0; | |
| 117 | if (PremappedHeap) { | |
| 118 | CHECK(!kUsingConstantSpaceBeg); | |
| 119 | NonConstSpaceBeg = heap_start; | |
| 120 | uptr RegionInfoSize = AdditionalSize(); | |
| 121 | RegionInfoSpace = | |
| 122 | address_range.Init(RegionInfoSize, PrimaryAllocatorName); | |
| 123 | CHECK_NE(RegionInfoSpace, ~(uptr)0); | |
| 124 | CHECK_EQ(RegionInfoSpace, | |
| 125 | address_range.MapOrDie(RegionInfoSpace, RegionInfoSize, | |
| 126 | "SizeClassAllocator: region info")); | |
| 127 | MapUnmapCallback().OnMap(RegionInfoSpace, RegionInfoSize); | |
| 78 | 128 | } else { |
| 79 | // Combined allocator expects that an 2^N allocation is always aligned to | |
| 80 | // 2^N. For this to work, the start of the space needs to be aligned as | |
| 81 | // high as the largest size class (which also needs to be a power of 2). | |
| 82 | NonConstSpaceBeg = address_range.InitAligned( | |
| 83 | TotalSpaceSize, SizeClassMap::kMaxSize, PrimaryAllocatorName); | |
| 84 | CHECK_NE(NonConstSpaceBeg, ~(uptr)0); | |
| 129 | if (kUsingConstantSpaceBeg) { | |
| 130 | CHECK(IsAligned(kSpaceBeg, SizeClassMap::kMaxSize)); | |
| 131 | CHECK_EQ(kSpaceBeg, | |
| 132 | address_range.Init(TotalSpaceSize, PrimaryAllocatorName, | |
| 133 | kSpaceBeg)); | |
| 134 | } else { | |
| 135 | // Combined allocator expects that an 2^N allocation is always aligned | |
| 136 | // to 2^N. For this to work, the start of the space needs to be aligned | |
| 137 | // as high as the largest size class (which also needs to be a power of | |
| 138 | // 2). | |
| 139 | NonConstSpaceBeg = address_range.InitAligned( | |
| 140 | TotalSpaceSize, SizeClassMap::kMaxSize, PrimaryAllocatorName); | |
| 141 | CHECK_NE(NonConstSpaceBeg, ~(uptr)0); | |
| 142 | } | |
| 143 | RegionInfoSpace = SpaceEnd(); | |
| 144 | MapWithCallbackOrDie(RegionInfoSpace, AdditionalSize(), | |
| 145 | "SizeClassAllocator: region info"); | |
| 85 | 146 | } |
| 86 | 147 | SetReleaseToOSIntervalMs(release_to_os_interval_ms); |
| 87 | MapWithCallbackOrDie(SpaceEnd(), AdditionalSize(), | |
| 88 | "SizeClassAllocator: region info"); | |
| 89 | 148 | // Check that the RegionInfo array is aligned on the CacheLine size. |
| 90 | DCHECK_EQ(SpaceEnd() % kCacheLineSize, 0); | |
| 149 | DCHECK_EQ(RegionInfoSpace % kCacheLineSize, 0); | |
| 91 | 150 | } |
| 92 | 151 | |
| 93 | 152 | s32 ReleaseToOSIntervalMs() const { |
| ... | ... | @@ -100,9 +159,10 @@ class SizeClassAllocator64 { |
| 100 | 159 | } |
| 101 | 160 | |
| 102 | 161 | void ForceReleaseToOS() { |
| 162 | MemoryMapperT memory_mapper(*this); | |
| 103 | 163 | for (uptr class_id = 1; class_id < kNumClasses; class_id++) { |
| 104 | 164 | BlockingMutexLock l(&GetRegionInfo(class_id)->mutex); |
| 105 | MaybeReleaseToOS(class_id, true /*force*/); | |
| 165 | MaybeReleaseToOS(&memory_mapper, class_id, true /*force*/); | |
| 106 | 166 | } |
| 107 | 167 | } |
| 108 | 168 | |
| ... | ... | @@ -111,7 +171,8 @@ class SizeClassAllocator64 { |
| 111 | 171 | alignment <= SizeClassMap::kMaxSize; |
| 112 | 172 | } |
| 113 | 173 | |
| 114 | NOINLINE void ReturnToAllocator(AllocatorStats *stat, uptr class_id, | |
| 174 | NOINLINE void ReturnToAllocator(MemoryMapperT *memory_mapper, | |
| 175 | AllocatorStats *stat, uptr class_id, | |
| 115 | 176 | const CompactPtrT *chunks, uptr n_chunks) { |
| 116 | 177 | RegionInfo *region = GetRegionInfo(class_id); |
| 117 | 178 | uptr region_beg = GetRegionBeginBySizeClass(class_id); |
| ... | ... | @@ -134,7 +195,7 @@ class SizeClassAllocator64 { |
| 134 | 195 | region->num_freed_chunks = new_num_freed_chunks; |
| 135 | 196 | region->stats.n_freed += n_chunks; |
| 136 | 197 | |
| 137 | MaybeReleaseToOS(class_id, false /*force*/); | |
| 198 | MaybeReleaseToOS(memory_mapper, class_id, false /*force*/); | |
| 138 | 199 | } |
| 139 | 200 | |
| 140 | 201 | NOINLINE bool GetFromAllocator(AllocatorStats *stat, uptr class_id, |
| ... | ... | @@ -144,6 +205,17 @@ class SizeClassAllocator64 { |
| 144 | 205 | CompactPtrT *free_array = GetFreeArray(region_beg); |
| 145 | 206 | |
| 146 | 207 | BlockingMutexLock l(&region->mutex); |
| 208 | #if SANITIZER_WINDOWS | |
| 209 | /* On Windows unmapping of memory during __sanitizer_purge_allocator is | |
| 210 | explicit and immediate, so unmapped regions must be explicitly mapped back | |
| 211 | in when they are accessed again. */ | |
| 212 | if (region->rtoi.last_released_bytes > 0) { | |
| 213 | MmapFixedOrDie(region_beg, region->mapped_user, | |
| 214 | "SizeClassAllocator: region data"); | |
| 215 | region->rtoi.n_freed_at_last_release = 0; | |
| 216 | region->rtoi.last_released_bytes = 0; | |
| 217 | } | |
| 218 | #endif | |
| 147 | 219 | if (UNLIKELY(region->num_freed_chunks < n_chunks)) { |
| 148 | 220 | if (UNLIKELY(!PopulateFreeArray(stat, class_id, region, |
| 149 | 221 | n_chunks - region->num_freed_chunks))) |
| ... | ... | @@ -186,13 +258,13 @@ class SizeClassAllocator64 { |
| 186 | 258 | |
| 187 | 259 | void *GetBlockBegin(const void *p) { |
| 188 | 260 | uptr class_id = GetSizeClass(p); |
| 261 | if (class_id >= kNumClasses) return nullptr; | |
| 189 | 262 | uptr size = ClassIdToSize(class_id); |
| 190 | 263 | if (!size) return nullptr; |
| 191 | 264 | uptr chunk_idx = GetChunkIdx((uptr)p, size); |
| 192 | 265 | uptr reg_beg = GetRegionBegin(p); |
| 193 | 266 | uptr beg = chunk_idx * size; |
| 194 | 267 | uptr next_beg = beg + size; |
| 195 | if (class_id >= kNumClasses) return nullptr; | |
| 196 | 268 | const RegionInfo *region = AddressSpaceView::Load(GetRegionInfo(class_id)); |
| 197 | 269 | if (region->mapped_user >= next_beg) |
| 198 | 270 | return reinterpret_cast<void*>(reg_beg + beg); |
| ... | ... | @@ -207,6 +279,7 @@ class SizeClassAllocator64 { |
| 207 | 279 | static uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); } |
| 208 | 280 | |
| 209 | 281 | void *GetMetaData(const void *p) { |
| 282 | CHECK(kMetadataSize); | |
| 210 | 283 | uptr class_id = GetSizeClass(p); |
| 211 | 284 | uptr size = ClassIdToSize(class_id); |
| 212 | 285 | uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size); |
| ... | ... | @@ -280,13 +353,13 @@ class SizeClassAllocator64 { |
| 280 | 353 | |
| 281 | 354 | // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone |
| 282 | 355 | // introspection API. |
| 283 | void ForceLock() { | |
| 356 | void ForceLock() NO_THREAD_SAFETY_ANALYSIS { | |
| 284 | 357 | for (uptr i = 0; i < kNumClasses; i++) { |
| 285 | 358 | GetRegionInfo(i)->mutex.Lock(); |
| 286 | 359 | } |
| 287 | 360 | } |
| 288 | 361 | |
| 289 | void ForceUnlock() { | |
| 362 | void ForceUnlock() NO_THREAD_SAFETY_ANALYSIS { | |
| 290 | 363 | for (int i = (int)kNumClasses - 1; i >= 0; i--) { |
| 291 | 364 | GetRegionInfo(i)->mutex.Unlock(); |
| 292 | 365 | } |
| ... | ... | @@ -330,11 +403,11 @@ class SizeClassAllocator64 { |
| 330 | 403 | // For the performance sake, none of the accessors check the validity of the |
| 331 | 404 | // arguments, it is assumed that index is always in [0, n) range and the value |
| 332 | 405 | // is not incremented past max_value. |
| 333 | template<class MemoryMapperT> | |
| 334 | 406 | class PackedCounterArray { |
| 335 | 407 | public: |
| 336 | PackedCounterArray(u64 num_counters, u64 max_value, MemoryMapperT *mapper) | |
| 337 | : n(num_counters), memory_mapper(mapper) { | |
| 408 | template <typename MemoryMapper> | |
| 409 | PackedCounterArray(u64 num_counters, u64 max_value, MemoryMapper *mapper) | |
| 410 | : n(num_counters) { | |
| 338 | 411 | CHECK_GT(num_counters, 0); |
| 339 | 412 | CHECK_GT(max_value, 0); |
| 340 | 413 | constexpr u64 kMaxCounterBits = sizeof(*buffer) * 8ULL; |
| ... | ... | @@ -351,17 +424,8 @@ class SizeClassAllocator64 { |
| 351 | 424 | packing_ratio_log = Log2(packing_ratio); |
| 352 | 425 | bit_offset_mask = packing_ratio - 1; |
| 353 | 426 | |
| 354 | buffer_size = | |
| 355 | (RoundUpTo(n, 1ULL << packing_ratio_log) >> packing_ratio_log) * | |
| 356 | sizeof(*buffer); | |
| 357 | buffer = reinterpret_cast<u64*>( | |
| 358 | memory_mapper->MapPackedCounterArrayBuffer(buffer_size)); | |
| 359 | } | |
| 360 | ~PackedCounterArray() { | |
| 361 | if (buffer) { | |
| 362 | memory_mapper->UnmapPackedCounterArrayBuffer( | |
| 363 | reinterpret_cast<uptr>(buffer), buffer_size); | |
| 364 | } | |
| 427 | buffer = mapper->MapPackedCounterArrayBuffer( | |
| 428 | RoundUpTo(n, 1ULL << packing_ratio_log) >> packing_ratio_log); | |
| 365 | 429 | } |
| 366 | 430 | |
| 367 | 431 | bool IsAllocated() const { |
| ... | ... | @@ -398,19 +462,16 @@ class SizeClassAllocator64 { |
| 398 | 462 | u64 counter_mask; |
| 399 | 463 | u64 packing_ratio_log; |
| 400 | 464 | u64 bit_offset_mask; |
| 401 | ||
| 402 | MemoryMapperT* const memory_mapper; | |
| 403 | u64 buffer_size; | |
| 404 | 465 | u64* buffer; |
| 405 | 466 | }; |
| 406 | 467 | |
| 407 | template<class MemoryMapperT> | |
| 468 | template <class MemoryMapperT> | |
| 408 | 469 | class FreePagesRangeTracker { |
| 409 | 470 | public: |
| 410 | explicit FreePagesRangeTracker(MemoryMapperT* mapper) | |
| 471 | FreePagesRangeTracker(MemoryMapperT *mapper, uptr class_id) | |
| 411 | 472 | : memory_mapper(mapper), |
| 412 | page_size_scaled_log(Log2(GetPageSizeCached() >> kCompactPtrScale)), | |
| 413 | in_the_range(false), current_page(0), current_range_start_page(0) {} | |
| 473 | class_id(class_id), | |
| 474 | page_size_scaled_log(Log2(GetPageSizeCached() >> kCompactPtrScale)) {} | |
| 414 | 475 | |
| 415 | 476 | void NextPage(bool freed) { |
| 416 | 477 | if (freed) { |
| ... | ... | @@ -432,28 +493,30 @@ class SizeClassAllocator64 { |
| 432 | 493 | void CloseOpenedRange() { |
| 433 | 494 | if (in_the_range) { |
| 434 | 495 | memory_mapper->ReleasePageRangeToOS( |
| 435 | current_range_start_page << page_size_scaled_log, | |
| 496 | class_id, current_range_start_page << page_size_scaled_log, | |
| 436 | 497 | current_page << page_size_scaled_log); |
| 437 | 498 | in_the_range = false; |
| 438 | 499 | } |
| 439 | 500 | } |
| 440 | 501 | |
| 441 | MemoryMapperT* const memory_mapper; | |
| 442 | const uptr page_size_scaled_log; | |
| 443 | bool in_the_range; | |
| 444 | uptr current_page; | |
| 445 | uptr current_range_start_page; | |
| 502 | MemoryMapperT *const memory_mapper = nullptr; | |
| 503 | const uptr class_id = 0; | |
| 504 | const uptr page_size_scaled_log = 0; | |
| 505 | bool in_the_range = false; | |
| 506 | uptr current_page = 0; | |
| 507 | uptr current_range_start_page = 0; | |
| 446 | 508 | }; |
| 447 | 509 | |
| 448 | 510 | // Iterates over the free_array to identify memory pages containing freed |
| 449 | 511 | // chunks only and returns these pages back to OS. |
| 450 | 512 | // allocated_pages_count is the total number of pages allocated for the |
| 451 | 513 | // current bucket. |
| 452 | template<class MemoryMapperT> | |
| 514 | template <typename MemoryMapper> | |
| 453 | 515 | static void ReleaseFreeMemoryToOS(CompactPtrT *free_array, |
| 454 | 516 | uptr free_array_count, uptr chunk_size, |
| 455 | 517 | uptr allocated_pages_count, |
| 456 | MemoryMapperT *memory_mapper) { | |
| 518 | MemoryMapper *memory_mapper, | |
| 519 | uptr class_id) { | |
| 457 | 520 | const uptr page_size = GetPageSizeCached(); |
| 458 | 521 | |
| 459 | 522 | // Figure out the number of chunks per page and whether we can take a fast |
| ... | ... | @@ -489,9 +552,8 @@ class SizeClassAllocator64 { |
| 489 | 552 | UNREACHABLE("All chunk_size/page_size ratios must be handled."); |
| 490 | 553 | } |
| 491 | 554 | |
| 492 | PackedCounterArray<MemoryMapperT> counters(allocated_pages_count, | |
| 493 | full_pages_chunk_count_max, | |
| 494 | memory_mapper); | |
| 555 | PackedCounterArray counters(allocated_pages_count, | |
| 556 | full_pages_chunk_count_max, memory_mapper); | |
| 495 | 557 | if (!counters.IsAllocated()) |
| 496 | 558 | return; |
| 497 | 559 | |
| ... | ... | @@ -516,7 +578,7 @@ class SizeClassAllocator64 { |
| 516 | 578 | |
| 517 | 579 | // Iterate over pages detecting ranges of pages with chunk counters equal |
| 518 | 580 | // to the expected number of chunks for the particular page. |
| 519 | FreePagesRangeTracker<MemoryMapperT> range_tracker(memory_mapper); | |
| 581 | FreePagesRangeTracker<MemoryMapper> range_tracker(memory_mapper, class_id); | |
| 520 | 582 | if (same_chunk_count_per_page) { |
| 521 | 583 | // Fast path, every page has the same number of chunks affecting it. |
| 522 | 584 | for (uptr i = 0; i < counters.GetCount(); i++) |
| ... | ... | @@ -555,7 +617,7 @@ class SizeClassAllocator64 { |
| 555 | 617 | } |
| 556 | 618 | |
| 557 | 619 | private: |
| 558 | friend class MemoryMapper; | |
| 620 | friend class MemoryMapper<ThisT>; | |
| 559 | 621 | |
| 560 | 622 | ReservedAddressRange address_range; |
| 561 | 623 | |
| ... | ... | @@ -585,6 +647,11 @@ class SizeClassAllocator64 { |
| 585 | 647 | |
| 586 | 648 | atomic_sint32_t release_to_os_interval_ms_; |
| 587 | 649 | |
| 650 | uptr RegionInfoSpace; | |
| 651 | ||
| 652 | // True if the user has already mapped the entire heap R/W. | |
| 653 | bool PremappedHeap; | |
| 654 | ||
| 588 | 655 | struct Stats { |
| 589 | 656 | uptr n_allocated; |
| 590 | 657 | uptr n_freed; |
| ... | ... | @@ -614,7 +681,7 @@ class SizeClassAllocator64 { |
| 614 | 681 | |
| 615 | 682 | RegionInfo *GetRegionInfo(uptr class_id) const { |
| 616 | 683 | DCHECK_LT(class_id, kNumClasses); |
| 617 | RegionInfo *regions = reinterpret_cast<RegionInfo *>(SpaceEnd()); | |
| 684 | RegionInfo *regions = reinterpret_cast<RegionInfo *>(RegionInfoSpace); | |
| 618 | 685 | return &regions[class_id]; |
| 619 | 686 | } |
| 620 | 687 | |
| ... | ... | @@ -639,6 +706,9 @@ class SizeClassAllocator64 { |
| 639 | 706 | } |
| 640 | 707 | |
| 641 | 708 | bool MapWithCallback(uptr beg, uptr size, const char *name) { |
| 709 | if (PremappedHeap) | |
| 710 | return beg >= NonConstSpaceBeg && | |
| 711 | beg + size <= NonConstSpaceBeg + kSpaceSize; | |
| 642 | 712 | uptr mapped = address_range.Map(beg, size, name); |
| 643 | 713 | if (UNLIKELY(!mapped)) |
| 644 | 714 | return false; |
| ... | ... | @@ -648,11 +718,18 @@ class SizeClassAllocator64 { |
| 648 | 718 | } |
| 649 | 719 | |
| 650 | 720 | void MapWithCallbackOrDie(uptr beg, uptr size, const char *name) { |
| 721 | if (PremappedHeap) { | |
| 722 | CHECK_GE(beg, NonConstSpaceBeg); | |
| 723 | CHECK_LE(beg + size, NonConstSpaceBeg + kSpaceSize); | |
| 724 | return; | |
| 725 | } | |
| 651 | 726 | CHECK_EQ(beg, address_range.MapOrDie(beg, size, name)); |
| 652 | 727 | MapUnmapCallback().OnMap(beg, size); |
| 653 | 728 | } |
| 654 | 729 | |
| 655 | 730 | void UnmapWithCallbackOrDie(uptr beg, uptr size) { |
| 731 | if (PremappedHeap) | |
| 732 | return; | |
| 656 | 733 | MapUnmapCallback().OnUnmap(beg, size); |
| 657 | 734 | address_range.Unmap(beg, size); |
| 658 | 735 | } |
| ... | ... | @@ -774,55 +851,13 @@ class SizeClassAllocator64 { |
| 774 | 851 | return true; |
| 775 | 852 | } |
| 776 | 853 | |
| 777 | class MemoryMapper { | |
| 778 | public: | |
| 779 | MemoryMapper(const ThisT& base_allocator, uptr class_id) | |
| 780 | : allocator(base_allocator), | |
| 781 | region_base(base_allocator.GetRegionBeginBySizeClass(class_id)), | |
| 782 | released_ranges_count(0), | |
| 783 | released_bytes(0) { | |
| 784 | } | |
| 785 | ||
| 786 | uptr GetReleasedRangesCount() const { | |
| 787 | return released_ranges_count; | |
| 788 | } | |
| 789 | ||
| 790 | uptr GetReleasedBytes() const { | |
| 791 | return released_bytes; | |
| 792 | } | |
| 793 | ||
| 794 | uptr MapPackedCounterArrayBuffer(uptr buffer_size) { | |
| 795 | // TODO(alekseyshl): The idea to explore is to check if we have enough | |
| 796 | // space between num_freed_chunks*sizeof(CompactPtrT) and | |
| 797 | // mapped_free_array to fit buffer_size bytes and use that space instead | |
| 798 | // of mapping a temporary one. | |
| 799 | return reinterpret_cast<uptr>( | |
| 800 | MmapOrDieOnFatalError(buffer_size, "ReleaseToOSPageCounters")); | |
| 801 | } | |
| 802 | ||
| 803 | void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) { | |
| 804 | UnmapOrDie(reinterpret_cast<void *>(buffer), buffer_size); | |
| 805 | } | |
| 806 | ||
| 807 | // Releases [from, to) range of pages back to OS. | |
| 808 | void ReleasePageRangeToOS(CompactPtrT from, CompactPtrT to) { | |
| 809 | const uptr from_page = allocator.CompactPtrToPointer(region_base, from); | |
| 810 | const uptr to_page = allocator.CompactPtrToPointer(region_base, to); | |
| 811 | ReleaseMemoryPagesToOS(from_page, to_page); | |
| 812 | released_ranges_count++; | |
| 813 | released_bytes += to_page - from_page; | |
| 814 | } | |
| 815 | ||
| 816 | private: | |
| 817 | const ThisT& allocator; | |
| 818 | const uptr region_base; | |
| 819 | uptr released_ranges_count; | |
| 820 | uptr released_bytes; | |
| 821 | }; | |
| 822 | ||
| 823 | 854 | // Attempts to release RAM occupied by freed chunks back to OS. The region is |
| 824 | 855 | // expected to be locked. |
| 825 | void MaybeReleaseToOS(uptr class_id, bool force) { | |
| 856 | // | |
| 857 | // TODO(morehouse): Support a callback on memory release so HWASan can release | |
| 858 | // aliases as well. | |
| 859 | void MaybeReleaseToOS(MemoryMapperT *memory_mapper, uptr class_id, | |
| 860 | bool force) { | |
| 826 | 861 | RegionInfo *region = GetRegionInfo(class_id); |
| 827 | 862 | const uptr chunk_size = ClassIdToSize(class_id); |
| 828 | 863 | const uptr page_size = GetPageSizeCached(); |
| ... | ... | @@ -846,17 +881,16 @@ class SizeClassAllocator64 { |
| 846 | 881 | } |
| 847 | 882 | } |
| 848 | 883 | |
| 849 | MemoryMapper memory_mapper(*this, class_id); | |
| 850 | ||
| 851 | ReleaseFreeMemoryToOS<MemoryMapper>( | |
| 884 | ReleaseFreeMemoryToOS( | |
| 852 | 885 | GetFreeArray(GetRegionBeginBySizeClass(class_id)), n, chunk_size, |
| 853 | RoundUpTo(region->allocated_user, page_size) / page_size, | |
| 854 | &memory_mapper); | |
| 886 | RoundUpTo(region->allocated_user, page_size) / page_size, memory_mapper, | |
| 887 | class_id); | |
| 855 | 888 | |
| 856 | if (memory_mapper.GetReleasedRangesCount() > 0) { | |
| 889 | uptr ranges, bytes; | |
| 890 | if (memory_mapper->GetAndResetStats(ranges, bytes)) { | |
| 857 | 891 | region->rtoi.n_freed_at_last_release = region->stats.n_freed; |
| 858 | region->rtoi.num_releases += memory_mapper.GetReleasedRangesCount(); | |
| 859 | region->rtoi.last_released_bytes = memory_mapper.GetReleasedBytes(); | |
| 892 | region->rtoi.num_releases += ranges; | |
| 893 | region->rtoi.last_released_bytes = bytes; | |
| 860 | 894 | } |
| 861 | 895 | region->rtoi.last_release_at_ns = MonotonicNanoTime(); |
| 862 | 896 | } |
lib/tsan/sanitizer_common/sanitizer_allocator_report.cpp+8| ... | ... | @@ -134,4 +134,12 @@ void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack) { |
| 134 | 134 | Die(); |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | void NORETURN ReportRssLimitExceeded(const StackTrace *stack) { | |
| 138 | { | |
| 139 | ScopedAllocatorErrorReport report("rss-limit-exceeded", stack); | |
| 140 | Report("ERROR: %s: allocator exceeded the RSS limit\n", SanitizerToolName); | |
| 141 | } | |
| 142 | Die(); | |
| 143 | } | |
| 144 | ||
| 137 | 145 | } // namespace __sanitizer |
lib/tsan/sanitizer_common/sanitizer_allocator_report.h+1| ... | ... | @@ -33,6 +33,7 @@ void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment, |
| 33 | 33 | void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size, |
| 34 | 34 | const StackTrace *stack); |
| 35 | 35 | void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack); |
| 36 | void NORETURN ReportRssLimitExceeded(const StackTrace *stack); | |
| 36 | 37 | |
| 37 | 38 | } // namespace __sanitizer |
| 38 | 39 |
lib/tsan/sanitizer_common/sanitizer_allocator_secondary.h+6-10| ... | ... | @@ -18,8 +18,8 @@ |
| 18 | 18 | // (currently, 32 bits and internal allocator). |
| 19 | 19 | class LargeMmapAllocatorPtrArrayStatic { |
| 20 | 20 | public: |
| 21 | INLINE void *Init() { return &p_[0]; } | |
| 22 | INLINE void EnsureSpace(uptr n) { CHECK_LT(n, kMaxNumChunks); } | |
| 21 | inline void *Init() { return &p_[0]; } | |
| 22 | inline void EnsureSpace(uptr n) { CHECK_LT(n, kMaxNumChunks); } | |
| 23 | 23 | private: |
| 24 | 24 | static const int kMaxNumChunks = 1 << 15; |
| 25 | 25 | uptr p_[kMaxNumChunks]; |
| ... | ... | @@ -31,14 +31,14 @@ class LargeMmapAllocatorPtrArrayStatic { |
| 31 | 31 | // same functionality in Fuchsia case, which does not support MAP_NORESERVE. |
| 32 | 32 | class LargeMmapAllocatorPtrArrayDynamic { |
| 33 | 33 | public: |
| 34 | INLINE void *Init() { | |
| 34 | inline void *Init() { | |
| 35 | 35 | uptr p = address_range_.Init(kMaxNumChunks * sizeof(uptr), |
| 36 | 36 | SecondaryAllocatorName); |
| 37 | 37 | CHECK(p); |
| 38 | 38 | return reinterpret_cast<void*>(p); |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | INLINE void EnsureSpace(uptr n) { | |
| 41 | inline void EnsureSpace(uptr n) { | |
| 42 | 42 | CHECK_LT(n, kMaxNumChunks); |
| 43 | 43 | DCHECK(n <= n_reserved_); |
| 44 | 44 | if (UNLIKELY(n == n_reserved_)) { |
| ... | ... | @@ -267,13 +267,9 @@ class LargeMmapAllocator { |
| 267 | 267 | |
| 268 | 268 | // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone |
| 269 | 269 | // introspection API. |
| 270 | void ForceLock() { | |
| 271 | mutex_.Lock(); | |
| 272 | } | |
| 270 | void ForceLock() ACQUIRE(mutex_) { mutex_.Lock(); } | |
| 273 | 271 | |
| 274 | void ForceUnlock() { | |
| 275 | mutex_.Unlock(); | |
| 276 | } | |
| 272 | void ForceUnlock() RELEASE(mutex_) { mutex_.Unlock(); } | |
| 277 | 273 | |
| 278 | 274 | // Iterate over all existing chunks. |
| 279 | 275 | // The allocator must be locked when calling this function. |
lib/tsan/sanitizer_common/sanitizer_allocator_size_class_map.h+1-1| ... | ... | @@ -24,7 +24,7 @@ |
| 24 | 24 | // E.g. with kNumBits==3 all size classes after 2^kMidSizeLog |
| 25 | 25 | // look like 0b1xx0..0, where x is either 0 or 1. |
| 26 | 26 | // |
| 27 | // Example: kNumBits=3, kMidSizeLog=4, kMidSizeLog=8, kMaxSizeLog=17: | |
| 27 | // Example: kNumBits=3, kMinSizeLog=4, kMidSizeLog=8, kMaxSizeLog=17: | |
| 28 | 28 | // |
| 29 | 29 | // Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16). |
| 30 | 30 | // Next 4 classes: 256 + i * 64 (i = 1 to 4). |
lib/tsan/sanitizer_common/sanitizer_atomic.h+2-2| ... | ... | @@ -72,12 +72,12 @@ namespace __sanitizer { |
| 72 | 72 | // Clutter-reducing helpers. |
| 73 | 73 | |
| 74 | 74 | template<typename T> |
| 75 | INLINE typename T::Type atomic_load_relaxed(const volatile T *a) { | |
| 75 | inline typename T::Type atomic_load_relaxed(const volatile T *a) { | |
| 76 | 76 | return atomic_load(a, memory_order_relaxed); |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | 79 | template<typename T> |
| 80 | INLINE void atomic_store_relaxed(volatile T *a, typename T::Type v) { | |
| 80 | inline void atomic_store_relaxed(volatile T *a, typename T::Type v) { | |
| 81 | 81 | atomic_store(a, v, memory_order_relaxed); |
| 82 | 82 | } |
| 83 | 83 |
lib/tsan/sanitizer_common/sanitizer_atomic_clang.h+7-7| ... | ... | @@ -34,16 +34,16 @@ namespace __sanitizer { |
| 34 | 34 | // See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html |
| 35 | 35 | // for mappings of the memory model to different processors. |
| 36 | 36 | |
| 37 | INLINE void atomic_signal_fence(memory_order) { | |
| 37 | inline void atomic_signal_fence(memory_order) { | |
| 38 | 38 | __asm__ __volatile__("" ::: "memory"); |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | INLINE void atomic_thread_fence(memory_order) { | |
| 41 | inline void atomic_thread_fence(memory_order) { | |
| 42 | 42 | __sync_synchronize(); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | template<typename T> |
| 46 | INLINE typename T::Type atomic_fetch_add(volatile T *a, | |
| 46 | inline typename T::Type atomic_fetch_add(volatile T *a, | |
| 47 | 47 | typename T::Type v, memory_order mo) { |
| 48 | 48 | (void)mo; |
| 49 | 49 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -51,7 +51,7 @@ INLINE typename T::Type atomic_fetch_add(volatile T *a, |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | template<typename T> |
| 54 | INLINE typename T::Type atomic_fetch_sub(volatile T *a, | |
| 54 | inline typename T::Type atomic_fetch_sub(volatile T *a, | |
| 55 | 55 | typename T::Type v, memory_order mo) { |
| 56 | 56 | (void)mo; |
| 57 | 57 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -59,7 +59,7 @@ INLINE typename T::Type atomic_fetch_sub(volatile T *a, |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | template<typename T> |
| 62 | INLINE typename T::Type atomic_exchange(volatile T *a, | |
| 62 | inline typename T::Type atomic_exchange(volatile T *a, | |
| 63 | 63 | typename T::Type v, memory_order mo) { |
| 64 | 64 | DCHECK(!((uptr)a % sizeof(*a))); |
| 65 | 65 | if (mo & (memory_order_release | memory_order_acq_rel | memory_order_seq_cst)) |
| ... | ... | @@ -71,7 +71,7 @@ INLINE typename T::Type atomic_exchange(volatile T *a, |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | template <typename T> |
| 74 | INLINE bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp, | |
| 74 | inline bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp, | |
| 75 | 75 | typename T::Type xchg, |
| 76 | 76 | memory_order mo) { |
| 77 | 77 | typedef typename T::Type Type; |
| ... | ... | @@ -84,7 +84,7 @@ INLINE bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp, |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | template<typename T> |
| 87 | INLINE bool atomic_compare_exchange_weak(volatile T *a, | |
| 87 | inline bool atomic_compare_exchange_weak(volatile T *a, | |
| 88 | 88 | typename T::Type *cmp, |
| 89 | 89 | typename T::Type xchg, |
| 90 | 90 | memory_order mo) { |
lib/tsan/sanitizer_common/sanitizer_atomic_clang_mips.h+9-9| ... | ... | @@ -37,11 +37,11 @@ static struct { |
| 37 | 37 | } __attribute__((aligned(32))) lock = {0, {0}}; |
| 38 | 38 | |
| 39 | 39 | template <> |
| 40 | INLINE atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr, | |
| 40 | inline atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr, | |
| 41 | 41 | atomic_uint64_t::Type val, |
| 42 | 42 | memory_order mo) { |
| 43 | 43 | DCHECK(mo & |
| 44 | (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); | |
| 44 | (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); | |
| 45 | 45 | DCHECK(!((uptr)ptr % sizeof(*ptr))); |
| 46 | 46 | |
| 47 | 47 | atomic_uint64_t::Type ret; |
| ... | ... | @@ -55,19 +55,19 @@ INLINE atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr, |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | template <> |
| 58 | INLINE atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr, | |
| 58 | inline atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr, | |
| 59 | 59 | atomic_uint64_t::Type val, |
| 60 | 60 | memory_order mo) { |
| 61 | 61 | return atomic_fetch_add(ptr, -val, mo); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | template <> |
| 65 | INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr, | |
| 65 | inline bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr, | |
| 66 | 66 | atomic_uint64_t::Type *cmp, |
| 67 | 67 | atomic_uint64_t::Type xchg, |
| 68 | 68 | memory_order mo) { |
| 69 | 69 | DCHECK(mo & |
| 70 | (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); | |
| 70 | (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); | |
| 71 | 71 | DCHECK(!((uptr)ptr % sizeof(*ptr))); |
| 72 | 72 | |
| 73 | 73 | typedef atomic_uint64_t::Type Type; |
| ... | ... | @@ -87,10 +87,10 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr, |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | template <> |
| 90 | INLINE atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr, | |
| 90 | inline atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr, | |
| 91 | 91 | memory_order mo) { |
| 92 | 92 | DCHECK(mo & |
| 93 | (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); | |
| 93 | (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); | |
| 94 | 94 | DCHECK(!((uptr)ptr % sizeof(*ptr))); |
| 95 | 95 | |
| 96 | 96 | atomic_uint64_t::Type zero = 0; |
| ... | ... | @@ -100,10 +100,10 @@ INLINE atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr, |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | template <> |
| 103 | INLINE void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v, | |
| 103 | inline void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v, | |
| 104 | 104 | memory_order mo) { |
| 105 | 105 | DCHECK(mo & |
| 106 | (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); | |
| 106 | (memory_order_relaxed | memory_order_release | memory_order_seq_cst)); | |
| 107 | 107 | DCHECK(!((uptr)ptr % sizeof(*ptr))); |
| 108 | 108 | |
| 109 | 109 | __spin_lock(&lock.lock); |
lib/tsan/sanitizer_common/sanitizer_atomic_clang_other.h+6-18| ... | ... | @@ -17,12 +17,12 @@ |
| 17 | 17 | namespace __sanitizer { |
| 18 | 18 | |
| 19 | 19 | |
| 20 | INLINE void proc_yield(int cnt) { | |
| 20 | inline void proc_yield(int cnt) { | |
| 21 | 21 | __asm__ __volatile__("" ::: "memory"); |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | template<typename T> |
| 25 | INLINE typename T::Type atomic_load( | |
| 25 | inline typename T::Type atomic_load( | |
| 26 | 26 | const volatile T *a, memory_order mo) { |
| 27 | 27 | DCHECK(mo & (memory_order_relaxed | memory_order_consume |
| 28 | 28 | | memory_order_acquire | memory_order_seq_cst)); |
| ... | ... | @@ -50,17 +50,14 @@ INLINE typename T::Type atomic_load( |
| 50 | 50 | __sync_synchronize(); |
| 51 | 51 | } |
| 52 | 52 | } else { |
| 53 | // 64-bit load on 32-bit platform. | |
| 54 | // Gross, but simple and reliable. | |
| 55 | // Assume that it is not in read-only memory. | |
| 56 | v = __sync_fetch_and_add( | |
| 57 | const_cast<typename T::Type volatile *>(&a->val_dont_use), 0); | |
| 53 | __atomic_load(const_cast<typename T::Type volatile *>(&a->val_dont_use), &v, | |
| 54 | __ATOMIC_SEQ_CST); | |
| 58 | 55 | } |
| 59 | 56 | return v; |
| 60 | 57 | } |
| 61 | 58 | |
| 62 | 59 | template<typename T> |
| 63 | INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { | |
| 60 | inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { | |
| 64 | 61 | DCHECK(mo & (memory_order_relaxed | memory_order_release |
| 65 | 62 | | memory_order_seq_cst)); |
| 66 | 63 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -79,16 +76,7 @@ INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { |
| 79 | 76 | __sync_synchronize(); |
| 80 | 77 | } |
| 81 | 78 | } else { |
| 82 | // 64-bit store on 32-bit platform. | |
| 83 | // Gross, but simple and reliable. | |
| 84 | typename T::Type cmp = a->val_dont_use; | |
| 85 | typename T::Type cur; | |
| 86 | for (;;) { | |
| 87 | cur = __sync_val_compare_and_swap(&a->val_dont_use, cmp, v); | |
| 88 | if (cur == cmp || cur == v) | |
| 89 | break; | |
| 90 | cmp = cur; | |
| 91 | } | |
| 79 | __atomic_store(&a->val_dont_use, &v, __ATOMIC_SEQ_CST); | |
| 92 | 80 | } |
| 93 | 81 | } |
| 94 | 82 |
lib/tsan/sanitizer_common/sanitizer_atomic_clang_x86.h+3-3| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | |
| 17 | 17 | namespace __sanitizer { |
| 18 | 18 | |
| 19 | INLINE void proc_yield(int cnt) { | |
| 19 | inline void proc_yield(int cnt) { | |
| 20 | 20 | __asm__ __volatile__("" ::: "memory"); |
| 21 | 21 | for (int i = 0; i < cnt; i++) |
| 22 | 22 | __asm__ __volatile__("pause"); |
| ... | ... | @@ -24,7 +24,7 @@ INLINE void proc_yield(int cnt) { |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | template<typename T> |
| 27 | INLINE typename T::Type atomic_load( | |
| 27 | inline typename T::Type atomic_load( | |
| 28 | 28 | const volatile T *a, memory_order mo) { |
| 29 | 29 | DCHECK(mo & (memory_order_relaxed | memory_order_consume |
| 30 | 30 | | memory_order_acquire | memory_order_seq_cst)); |
| ... | ... | @@ -70,7 +70,7 @@ INLINE typename T::Type atomic_load( |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | template<typename T> |
| 73 | INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { | |
| 73 | inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { | |
| 74 | 74 | DCHECK(mo & (memory_order_relaxed | memory_order_release |
| 75 | 75 | | memory_order_seq_cst)); |
| 76 | 76 | DCHECK(!((uptr)a % sizeof(*a))); |
lib/tsan/sanitizer_common/sanitizer_atomic_msvc.h+18-18| ... | ... | @@ -54,21 +54,21 @@ extern "C" long long _InterlockedExchangeAdd64(long long volatile *Addend, |
| 54 | 54 | |
| 55 | 55 | namespace __sanitizer { |
| 56 | 56 | |
| 57 | INLINE void atomic_signal_fence(memory_order) { | |
| 57 | inline void atomic_signal_fence(memory_order) { | |
| 58 | 58 | _ReadWriteBarrier(); |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | INLINE void atomic_thread_fence(memory_order) { | |
| 61 | inline void atomic_thread_fence(memory_order) { | |
| 62 | 62 | _mm_mfence(); |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | INLINE void proc_yield(int cnt) { | |
| 65 | inline void proc_yield(int cnt) { | |
| 66 | 66 | for (int i = 0; i < cnt; i++) |
| 67 | 67 | _mm_pause(); |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | template<typename T> |
| 71 | INLINE typename T::Type atomic_load( | |
| 71 | inline typename T::Type atomic_load( | |
| 72 | 72 | const volatile T *a, memory_order mo) { |
| 73 | 73 | DCHECK(mo & (memory_order_relaxed | memory_order_consume |
| 74 | 74 | | memory_order_acquire | memory_order_seq_cst)); |
| ... | ... | @@ -86,7 +86,7 @@ INLINE typename T::Type atomic_load( |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | template<typename T> |
| 89 | INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { | |
| 89 | inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { | |
| 90 | 90 | DCHECK(mo & (memory_order_relaxed | memory_order_release |
| 91 | 91 | | memory_order_seq_cst)); |
| 92 | 92 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -102,7 +102,7 @@ INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { |
| 102 | 102 | atomic_thread_fence(memory_order_seq_cst); |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a, | |
| 105 | inline u32 atomic_fetch_add(volatile atomic_uint32_t *a, | |
| 106 | 106 | u32 v, memory_order mo) { |
| 107 | 107 | (void)mo; |
| 108 | 108 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -110,7 +110,7 @@ INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a, |
| 110 | 110 | (long)v); |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a, | |
| 113 | inline uptr atomic_fetch_add(volatile atomic_uintptr_t *a, | |
| 114 | 114 | uptr v, memory_order mo) { |
| 115 | 115 | (void)mo; |
| 116 | 116 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -123,7 +123,7 @@ INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a, |
| 123 | 123 | #endif |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a, | |
| 126 | inline u32 atomic_fetch_sub(volatile atomic_uint32_t *a, | |
| 127 | 127 | u32 v, memory_order mo) { |
| 128 | 128 | (void)mo; |
| 129 | 129 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -131,7 +131,7 @@ INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a, |
| 131 | 131 | -(long)v); |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a, | |
| 134 | inline uptr atomic_fetch_sub(volatile atomic_uintptr_t *a, | |
| 135 | 135 | uptr v, memory_order mo) { |
| 136 | 136 | (void)mo; |
| 137 | 137 | DCHECK(!((uptr)a % sizeof(*a))); |
| ... | ... | @@ -144,28 +144,28 @@ INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a, |
| 144 | 144 | #endif |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | INLINE u8 atomic_exchange(volatile atomic_uint8_t *a, | |
| 147 | inline u8 atomic_exchange(volatile atomic_uint8_t *a, | |
| 148 | 148 | u8 v, memory_order mo) { |
| 149 | 149 | (void)mo; |
| 150 | 150 | DCHECK(!((uptr)a % sizeof(*a))); |
| 151 | 151 | return (u8)_InterlockedExchange8((volatile char*)&a->val_dont_use, v); |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | INLINE u16 atomic_exchange(volatile atomic_uint16_t *a, | |
| 154 | inline u16 atomic_exchange(volatile atomic_uint16_t *a, | |
| 155 | 155 | u16 v, memory_order mo) { |
| 156 | 156 | (void)mo; |
| 157 | 157 | DCHECK(!((uptr)a % sizeof(*a))); |
| 158 | 158 | return (u16)_InterlockedExchange16((volatile short*)&a->val_dont_use, v); |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | INLINE u32 atomic_exchange(volatile atomic_uint32_t *a, | |
| 161 | inline u32 atomic_exchange(volatile atomic_uint32_t *a, | |
| 162 | 162 | u32 v, memory_order mo) { |
| 163 | 163 | (void)mo; |
| 164 | 164 | DCHECK(!((uptr)a % sizeof(*a))); |
| 165 | 165 | return (u32)_InterlockedExchange((volatile long*)&a->val_dont_use, v); |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | INLINE bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a, | |
| 168 | inline bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a, | |
| 169 | 169 | u8 *cmp, |
| 170 | 170 | u8 xchgv, |
| 171 | 171 | memory_order mo) { |
| ... | ... | @@ -191,7 +191,7 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a, |
| 191 | 191 | return false; |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a, | |
| 194 | inline bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a, | |
| 195 | 195 | uptr *cmp, |
| 196 | 196 | uptr xchg, |
| 197 | 197 | memory_order mo) { |
| ... | ... | @@ -204,7 +204,7 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a, |
| 204 | 204 | return false; |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | INLINE bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a, | |
| 207 | inline bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a, | |
| 208 | 208 | u16 *cmp, |
| 209 | 209 | u16 xchg, |
| 210 | 210 | memory_order mo) { |
| ... | ... | @@ -217,7 +217,7 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a, |
| 217 | 217 | return false; |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | INLINE bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a, | |
| 220 | inline bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a, | |
| 221 | 221 | u32 *cmp, |
| 222 | 222 | u32 xchg, |
| 223 | 223 | memory_order mo) { |
| ... | ... | @@ -230,7 +230,7 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a, |
| 230 | 230 | return false; |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a, | |
| 233 | inline bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a, | |
| 234 | 234 | u64 *cmp, |
| 235 | 235 | u64 xchg, |
| 236 | 236 | memory_order mo) { |
| ... | ... | @@ -244,7 +244,7 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a, |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | 246 | template<typename T> |
| 247 | INLINE bool atomic_compare_exchange_weak(volatile T *a, | |
| 247 | inline bool atomic_compare_exchange_weak(volatile T *a, | |
| 248 | 248 | typename T::Type *cmp, |
| 249 | 249 | typename T::Type xchg, |
| 250 | 250 | memory_order mo) { |
lib/tsan/sanitizer_common/sanitizer_common.cpp+20-5| ... | ... | @@ -37,10 +37,9 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, |
| 37 | 37 | const char *mmap_type, error_t err, |
| 38 | 38 | bool raw_report) { |
| 39 | 39 | static int recursion_count; |
| 40 | if (SANITIZER_RTEMS || raw_report || recursion_count) { | |
| 41 | // If we are on RTEMS or raw report is requested or we went into recursion, | |
| 42 | // just die. The Report() and CHECK calls below may call mmap recursively | |
| 43 | // and fail. | |
| 40 | if (raw_report || recursion_count) { | |
| 41 | // If raw report is requested or we went into recursion just die. The | |
| 42 | // Report() and CHECK calls below may call mmap recursively and fail. | |
| 44 | 43 | RawWrite("ERROR: Failed to mmap\n"); |
| 45 | 44 | Die(); |
| 46 | 45 | } |
| ... | ... | @@ -87,7 +86,7 @@ const char *StripModuleName(const char *module) { |
| 87 | 86 | void ReportErrorSummary(const char *error_message, const char *alt_tool_name) { |
| 88 | 87 | if (!common_flags()->print_summary) |
| 89 | 88 | return; |
| 90 | InternalScopedString buff(kMaxSummaryLength); | |
| 89 | InternalScopedString buff; | |
| 91 | 90 | buff.append("SUMMARY: %s: %s", |
| 92 | 91 | alt_tool_name ? alt_tool_name : SanitizerToolName, error_message); |
| 93 | 92 | __sanitizer_report_error_summary(buff.data()); |
| ... | ... | @@ -274,6 +273,14 @@ uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) { |
| 274 | 273 | return name_len; |
| 275 | 274 | } |
| 276 | 275 | |
| 276 | uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len) { | |
| 277 | ReadBinaryNameCached(buf, buf_len); | |
| 278 | const char *exec_name_pos = StripModuleName(buf); | |
| 279 | uptr name_len = exec_name_pos - buf; | |
| 280 | buf[name_len] = '\0'; | |
| 281 | return name_len; | |
| 282 | } | |
| 283 | ||
| 277 | 284 | #if !SANITIZER_GO |
| 278 | 285 | void PrintCmdline() { |
| 279 | 286 | char **argv = GetArgv(); |
| ... | ... | @@ -323,6 +330,14 @@ static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr), |
| 323 | 330 | return 0; |
| 324 | 331 | } |
| 325 | 332 | |
| 333 | void internal_sleep(unsigned seconds) { | |
| 334 | internal_usleep((u64)seconds * 1000 * 1000); | |
| 335 | } | |
| 336 | void SleepForSeconds(unsigned seconds) { | |
| 337 | internal_usleep((u64)seconds * 1000 * 1000); | |
| 338 | } | |
| 339 | void SleepForMillis(unsigned millis) { internal_usleep((u64)millis * 1000); } | |
| 340 | ||
| 326 | 341 | } // namespace __sanitizer |
| 327 | 342 | |
| 328 | 343 | using namespace __sanitizer; |
lib/tsan/sanitizer_common/sanitizer_common.h+135-57| ... | ... | @@ -44,7 +44,7 @@ const uptr kMaxPathLength = 4096; |
| 44 | 44 | |
| 45 | 45 | const uptr kMaxThreadStackSize = 1 << 30; // 1Gb |
| 46 | 46 | |
| 47 | static const uptr kErrorMessageBufferSize = 1 << 16; | |
| 47 | const uptr kErrorMessageBufferSize = 1 << 16; | |
| 48 | 48 | |
| 49 | 49 | // Denotes fake PC values that come from JIT/JAVA/etc. |
| 50 | 50 | // For such PC values __tsan_symbolize_external_ex() will be called. |
| ... | ... | @@ -53,25 +53,25 @@ const u64 kExternalPCBit = 1ULL << 60; |
| 53 | 53 | extern const char *SanitizerToolName; // Can be changed by the tool. |
| 54 | 54 | |
| 55 | 55 | extern atomic_uint32_t current_verbosity; |
| 56 | INLINE void SetVerbosity(int verbosity) { | |
| 56 | inline void SetVerbosity(int verbosity) { | |
| 57 | 57 | atomic_store(&current_verbosity, verbosity, memory_order_relaxed); |
| 58 | 58 | } |
| 59 | INLINE int Verbosity() { | |
| 59 | inline int Verbosity() { | |
| 60 | 60 | return atomic_load(&current_verbosity, memory_order_relaxed); |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | #if SANITIZER_ANDROID |
| 64 | INLINE uptr GetPageSize() { | |
| 64 | inline uptr GetPageSize() { | |
| 65 | 65 | // Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array. |
| 66 | 66 | return 4096; |
| 67 | 67 | } |
| 68 | INLINE uptr GetPageSizeCached() { | |
| 68 | inline uptr GetPageSizeCached() { | |
| 69 | 69 | return 4096; |
| 70 | 70 | } |
| 71 | 71 | #else |
| 72 | 72 | uptr GetPageSize(); |
| 73 | 73 | extern uptr PageSizeCached; |
| 74 | INLINE uptr GetPageSizeCached() { | |
| 74 | inline uptr GetPageSizeCached() { | |
| 75 | 75 | if (!PageSizeCached) |
| 76 | 76 | PageSizeCached = GetPageSize(); |
| 77 | 77 | return PageSizeCached; |
| ... | ... | @@ -91,7 +91,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, |
| 91 | 91 | |
| 92 | 92 | // Memory management |
| 93 | 93 | void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false); |
| 94 | INLINE void *MmapOrDieQuietly(uptr size, const char *mem_type) { | |
| 94 | inline void *MmapOrDieQuietly(uptr size, const char *mem_type) { | |
| 95 | 95 | return MmapOrDie(size, mem_type, /*raw_report*/ true); |
| 96 | 96 | } |
| 97 | 97 | void UnmapOrDie(void *addr, uptr size); |
| ... | ... | @@ -121,6 +121,40 @@ bool MprotectReadOnly(uptr addr, uptr size); |
| 121 | 121 | |
| 122 | 122 | void MprotectMallocZones(void *addr, int prot); |
| 123 | 123 | |
| 124 | #if SANITIZER_LINUX | |
| 125 | // Unmap memory. Currently only used on Linux. | |
| 126 | void UnmapFromTo(uptr from, uptr to); | |
| 127 | #endif | |
| 128 | ||
| 129 | // Maps shadow_size_bytes of shadow memory and returns shadow address. It will | |
| 130 | // be aligned to the mmap granularity * 2^shadow_scale, or to | |
| 131 | // 2^min_shadow_base_alignment if that is larger. The returned address will | |
| 132 | // have max(2^min_shadow_base_alignment, mmap granularity) on the left, and | |
| 133 | // shadow_size_bytes bytes on the right, which on linux is mapped no access. | |
| 134 | // The high_mem_end may be updated if the original shadow size doesn't fit. | |
| 135 | uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale, | |
| 136 | uptr min_shadow_base_alignment, uptr &high_mem_end); | |
| 137 | ||
| 138 | // Let S = max(shadow_size, num_aliases * alias_size, ring_buffer_size). | |
| 139 | // Reserves 2*S bytes of address space to the right of the returned address and | |
| 140 | // ring_buffer_size bytes to the left. The returned address is aligned to 2*S. | |
| 141 | // Also creates num_aliases regions of accessible memory starting at offset S | |
| 142 | // from the returned address. Each region has size alias_size and is backed by | |
| 143 | // the same physical memory. | |
| 144 | uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size, | |
| 145 | uptr num_aliases, uptr ring_buffer_size); | |
| 146 | ||
| 147 | // Reserve memory range [beg, end]. If madvise_shadow is true then apply | |
| 148 | // madvise (e.g. hugepages, core dumping) requested by options. | |
| 149 | void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name, | |
| 150 | bool madvise_shadow = true); | |
| 151 | ||
| 152 | // Protect size bytes of memory starting at addr. Also try to protect | |
| 153 | // several pages at the start of the address space as specified by | |
| 154 | // zero_base_shadow_start, at most up to the size or zero_base_max_shadow_start. | |
| 155 | void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start, | |
| 156 | uptr zero_base_max_shadow_start); | |
| 157 | ||
| 124 | 158 | // Find an available address space. |
| 125 | 159 | uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, |
| 126 | 160 | uptr *largest_gap_found, uptr *max_occupied_addr); |
| ... | ... | @@ -203,10 +237,16 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)); |
| 203 | 237 | // Lock sanitizer error reporting and protects against nested errors. |
| 204 | 238 | class ScopedErrorReportLock { |
| 205 | 239 | public: |
| 206 | ScopedErrorReportLock(); | |
| 207 | ~ScopedErrorReportLock(); | |
| 240 | ScopedErrorReportLock() ACQUIRE(mutex_) { Lock(); } | |
| 241 | ~ScopedErrorReportLock() RELEASE(mutex_) { Unlock(); } | |
| 208 | 242 | |
| 209 | static void CheckLocked(); | |
| 243 | static void Lock() ACQUIRE(mutex_); | |
| 244 | static void Unlock() RELEASE(mutex_); | |
| 245 | static void CheckLocked() CHECK_LOCKED(mutex_); | |
| 246 | ||
| 247 | private: | |
| 248 | static atomic_uintptr_t reporting_thread_; | |
| 249 | static StaticSpinMutex mutex_; | |
| 210 | 250 | }; |
| 211 | 251 | |
| 212 | 252 | extern uptr stoptheworld_tracer_pid; |
| ... | ... | @@ -223,13 +263,13 @@ const char *StripModuleName(const char *module); |
| 223 | 263 | // OS |
| 224 | 264 | uptr ReadBinaryName(/*out*/char *buf, uptr buf_len); |
| 225 | 265 | uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len); |
| 266 | uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len); | |
| 226 | 267 | uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len); |
| 227 | 268 | const char *GetProcessName(); |
| 228 | 269 | void UpdateProcessName(); |
| 229 | 270 | void CacheBinaryName(); |
| 230 | 271 | void DisableCoreDumperIfNecessary(); |
| 231 | 272 | void DumpProcessMap(); |
| 232 | void PrintModuleMap(); | |
| 233 | 273 | const char *GetEnv(const char *name); |
| 234 | 274 | bool SetEnv(const char *name, const char *value); |
| 235 | 275 | |
| ... | ... | @@ -254,8 +294,8 @@ void InitTlsSize(); |
| 254 | 294 | uptr GetTlsSize(); |
| 255 | 295 | |
| 256 | 296 | // Other |
| 257 | void SleepForSeconds(int seconds); | |
| 258 | void SleepForMillis(int millis); | |
| 297 | void SleepForSeconds(unsigned seconds); | |
| 298 | void SleepForMillis(unsigned millis); | |
| 259 | 299 | u64 NanoTime(); |
| 260 | 300 | u64 MonotonicNanoTime(); |
| 261 | 301 | int Atexit(void (*function)(void)); |
| ... | ... | @@ -270,8 +310,8 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, |
| 270 | 310 | const char *mmap_type, error_t err, |
| 271 | 311 | bool raw_report = false); |
| 272 | 312 | |
| 273 | // Specific tools may override behavior of "Die" and "CheckFailed" functions | |
| 274 | // to do tool-specific job. | |
| 313 | // Specific tools may override behavior of "Die" function to do tool-specific | |
| 314 | // job. | |
| 275 | 315 | typedef void (*DieCallbackType)(void); |
| 276 | 316 | |
| 277 | 317 | // It's possible to add several callbacks that would be run when "Die" is |
| ... | ... | @@ -283,9 +323,7 @@ bool RemoveDieCallback(DieCallbackType callback); |
| 283 | 323 | |
| 284 | 324 | void SetUserDieCallback(DieCallbackType callback); |
| 285 | 325 | |
| 286 | typedef void (*CheckFailedCallbackType)(const char *, int, const char *, | |
| 287 | u64, u64); | |
| 288 | void SetCheckFailedCallback(CheckFailedCallbackType callback); | |
| 326 | void SetCheckUnwindCallback(void (*callback)()); | |
| 289 | 327 | |
| 290 | 328 | // Callback will be called if soft_rss_limit_mb is given and the limit is |
| 291 | 329 | // exceeded (exceeded==true) or if rss went down below the limit |
| ... | ... | @@ -319,8 +357,6 @@ void ReportDeadlySignal(const SignalContext &sig, u32 tid, |
| 319 | 357 | void SetAlternateSignalStack(); |
| 320 | 358 | void UnsetAlternateSignalStack(); |
| 321 | 359 | |
| 322 | // We don't want a summary too long. | |
| 323 | const int kMaxSummaryLength = 1024; | |
| 324 | 360 | // Construct a one-line string: |
| 325 | 361 | // SUMMARY: SanitizerToolName: error_message |
| 326 | 362 | // and pass it to __sanitizer_report_error_summary. |
| ... | ... | @@ -349,7 +385,7 @@ unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); |
| 349 | 385 | } |
| 350 | 386 | #endif |
| 351 | 387 | |
| 352 | INLINE uptr MostSignificantSetBitIndex(uptr x) { | |
| 388 | inline uptr MostSignificantSetBitIndex(uptr x) { | |
| 353 | 389 | CHECK_NE(x, 0U); |
| 354 | 390 | unsigned long up; |
| 355 | 391 | #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) |
| ... | ... | @@ -366,7 +402,7 @@ INLINE uptr MostSignificantSetBitIndex(uptr x) { |
| 366 | 402 | return up; |
| 367 | 403 | } |
| 368 | 404 | |
| 369 | INLINE uptr LeastSignificantSetBitIndex(uptr x) { | |
| 405 | inline uptr LeastSignificantSetBitIndex(uptr x) { | |
| 370 | 406 | CHECK_NE(x, 0U); |
| 371 | 407 | unsigned long up; |
| 372 | 408 | #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) |
| ... | ... | @@ -383,11 +419,11 @@ INLINE uptr LeastSignificantSetBitIndex(uptr x) { |
| 383 | 419 | return up; |
| 384 | 420 | } |
| 385 | 421 | |
| 386 | INLINE bool IsPowerOfTwo(uptr x) { | |
| 422 | inline bool IsPowerOfTwo(uptr x) { | |
| 387 | 423 | return (x & (x - 1)) == 0; |
| 388 | 424 | } |
| 389 | 425 | |
| 390 | INLINE uptr RoundUpToPowerOfTwo(uptr size) { | |
| 426 | inline uptr RoundUpToPowerOfTwo(uptr size) { | |
| 391 | 427 | CHECK(size); |
| 392 | 428 | if (IsPowerOfTwo(size)) return size; |
| 393 | 429 | |
| ... | ... | @@ -397,28 +433,34 @@ INLINE uptr RoundUpToPowerOfTwo(uptr size) { |
| 397 | 433 | return 1ULL << (up + 1); |
| 398 | 434 | } |
| 399 | 435 | |
| 400 | INLINE uptr RoundUpTo(uptr size, uptr boundary) { | |
| 436 | inline uptr RoundUpTo(uptr size, uptr boundary) { | |
| 401 | 437 | RAW_CHECK(IsPowerOfTwo(boundary)); |
| 402 | 438 | return (size + boundary - 1) & ~(boundary - 1); |
| 403 | 439 | } |
| 404 | 440 | |
| 405 | INLINE uptr RoundDownTo(uptr x, uptr boundary) { | |
| 441 | inline uptr RoundDownTo(uptr x, uptr boundary) { | |
| 406 | 442 | return x & ~(boundary - 1); |
| 407 | 443 | } |
| 408 | 444 | |
| 409 | INLINE bool IsAligned(uptr a, uptr alignment) { | |
| 445 | inline bool IsAligned(uptr a, uptr alignment) { | |
| 410 | 446 | return (a & (alignment - 1)) == 0; |
| 411 | 447 | } |
| 412 | 448 | |
| 413 | INLINE uptr Log2(uptr x) { | |
| 449 | inline uptr Log2(uptr x) { | |
| 414 | 450 | CHECK(IsPowerOfTwo(x)); |
| 415 | 451 | return LeastSignificantSetBitIndex(x); |
| 416 | 452 | } |
| 417 | 453 | |
| 418 | 454 | // Don't use std::min, std::max or std::swap, to minimize dependency |
| 419 | 455 | // on libstdc++. |
| 420 | template<class T> T Min(T a, T b) { return a < b ? a : b; } | |
| 421 | template<class T> T Max(T a, T b) { return a > b ? a : b; } | |
| 456 | template <class T> | |
| 457 | constexpr T Min(T a, T b) { | |
| 458 | return a < b ? a : b; | |
| 459 | } | |
| 460 | template <class T> | |
| 461 | constexpr T Max(T a, T b) { | |
| 462 | return a > b ? a : b; | |
| 463 | } | |
| 422 | 464 | template<class T> void Swap(T& a, T& b) { |
| 423 | 465 | T tmp = a; |
| 424 | 466 | a = b; |
| ... | ... | @@ -426,14 +468,14 @@ template<class T> void Swap(T& a, T& b) { |
| 426 | 468 | } |
| 427 | 469 | |
| 428 | 470 | // Char handling |
| 429 | INLINE bool IsSpace(int c) { | |
| 471 | inline bool IsSpace(int c) { | |
| 430 | 472 | return (c == ' ') || (c == '\n') || (c == '\t') || |
| 431 | 473 | (c == '\f') || (c == '\r') || (c == '\v'); |
| 432 | 474 | } |
| 433 | INLINE bool IsDigit(int c) { | |
| 475 | inline bool IsDigit(int c) { | |
| 434 | 476 | return (c >= '0') && (c <= '9'); |
| 435 | 477 | } |
| 436 | INLINE int ToLower(int c) { | |
| 478 | inline int ToLower(int c) { | |
| 437 | 479 | return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c; |
| 438 | 480 | } |
| 439 | 481 | |
| ... | ... | @@ -443,6 +485,7 @@ INLINE int ToLower(int c) { |
| 443 | 485 | template<typename T> |
| 444 | 486 | class InternalMmapVectorNoCtor { |
| 445 | 487 | public: |
| 488 | using value_type = T; | |
| 446 | 489 | void Initialize(uptr initial_capacity) { |
| 447 | 490 | capacity_bytes_ = 0; |
| 448 | 491 | size_ = 0; |
| ... | ... | @@ -566,21 +609,21 @@ class InternalMmapVector : public InternalMmapVectorNoCtor<T> { |
| 566 | 609 | InternalMmapVector &operator=(InternalMmapVector &&) = delete; |
| 567 | 610 | }; |
| 568 | 611 | |
| 569 | class InternalScopedString : public InternalMmapVector<char> { | |
| 612 | class InternalScopedString { | |
| 570 | 613 | public: |
| 571 | explicit InternalScopedString(uptr max_length) | |
| 572 | : InternalMmapVector<char>(max_length), length_(0) { | |
| 573 | (*this)[0] = '\0'; | |
| 574 | } | |
| 575 | uptr length() { return length_; } | |
| 614 | InternalScopedString() : buffer_(1) { buffer_[0] = '\0'; } | |
| 615 | ||
| 616 | uptr length() const { return buffer_.size() - 1; } | |
| 576 | 617 | void clear() { |
| 577 | (*this)[0] = '\0'; | |
| 578 | length_ = 0; | |
| 618 | buffer_.resize(1); | |
| 619 | buffer_[0] = '\0'; | |
| 579 | 620 | } |
| 580 | 621 | void append(const char *format, ...); |
| 622 | const char *data() const { return buffer_.data(); } | |
| 623 | char *data() { return buffer_.data(); } | |
| 581 | 624 | |
| 582 | 625 | private: |
| 583 | uptr length_; | |
| 626 | InternalMmapVector<char> buffer_; | |
| 584 | 627 | }; |
| 585 | 628 | |
| 586 | 629 | template <class T> |
| ... | ... | @@ -627,9 +670,13 @@ void Sort(T *v, uptr size, Compare comp = {}) { |
| 627 | 670 | |
| 628 | 671 | // Works like std::lower_bound: finds the first element that is not less |
| 629 | 672 | // than the val. |
| 630 | template <class Container, class Value, class Compare> | |
| 631 | uptr InternalLowerBound(const Container &v, uptr first, uptr last, | |
| 632 | const Value &val, Compare comp) { | |
| 673 | template <class Container, | |
| 674 | class Compare = CompareLess<typename Container::value_type>> | |
| 675 | uptr InternalLowerBound(const Container &v, | |
| 676 | const typename Container::value_type &val, | |
| 677 | Compare comp = {}) { | |
| 678 | uptr first = 0; | |
| 679 | uptr last = v.size(); | |
| 633 | 680 | while (last > first) { |
| 634 | 681 | uptr mid = (first + last) / 2; |
| 635 | 682 | if (comp(v[mid], val)) |
| ... | ... | @@ -649,9 +696,31 @@ enum ModuleArch { |
| 649 | 696 | kModuleArchARMV7, |
| 650 | 697 | kModuleArchARMV7S, |
| 651 | 698 | kModuleArchARMV7K, |
| 652 | kModuleArchARM64 | |
| 699 | kModuleArchARM64, | |
| 700 | kModuleArchRISCV64 | |
| 653 | 701 | }; |
| 654 | 702 | |
| 703 | // Sorts and removes duplicates from the container. | |
| 704 | template <class Container, | |
| 705 | class Compare = CompareLess<typename Container::value_type>> | |
| 706 | void SortAndDedup(Container &v, Compare comp = {}) { | |
| 707 | Sort(v.data(), v.size(), comp); | |
| 708 | uptr size = v.size(); | |
| 709 | if (size < 2) | |
| 710 | return; | |
| 711 | uptr last = 0; | |
| 712 | for (uptr i = 1; i < size; ++i) { | |
| 713 | if (comp(v[last], v[i])) { | |
| 714 | ++last; | |
| 715 | if (last != i) | |
| 716 | v[last] = v[i]; | |
| 717 | } else { | |
| 718 | CHECK(!comp(v[i], v[last])); | |
| 719 | } | |
| 720 | } | |
| 721 | v.resize(last + 1); | |
| 722 | } | |
| 723 | ||
| 655 | 724 | // Opens the file 'file_name" and reads up to 'max_len' bytes. |
| 656 | 725 | // The resulting buffer is mmaped and stored in '*buff'. |
| 657 | 726 | // Returns true if file was successfully opened and read. |
| ... | ... | @@ -693,6 +762,8 @@ inline const char *ModuleArchToString(ModuleArch arch) { |
| 693 | 762 | return "armv7k"; |
| 694 | 763 | case kModuleArchARM64: |
| 695 | 764 | return "arm64"; |
| 765 | case kModuleArchRISCV64: | |
| 766 | return "riscv64"; | |
| 696 | 767 | } |
| 697 | 768 | CHECK(0 && "Invalid module arch"); |
| 698 | 769 | return ""; |
| ... | ... | @@ -815,15 +886,15 @@ void WriteToSyslog(const char *buffer); |
| 815 | 886 | #if SANITIZER_MAC || SANITIZER_WIN_TRACE |
| 816 | 887 | void LogFullErrorReport(const char *buffer); |
| 817 | 888 | #else |
| 818 | INLINE void LogFullErrorReport(const char *buffer) {} | |
| 889 | inline void LogFullErrorReport(const char *buffer) {} | |
| 819 | 890 | #endif |
| 820 | 891 | |
| 821 | 892 | #if SANITIZER_LINUX || SANITIZER_MAC |
| 822 | 893 | void WriteOneLineToSyslog(const char *s); |
| 823 | 894 | void LogMessageOnPrintf(const char *str); |
| 824 | 895 | #else |
| 825 | INLINE void WriteOneLineToSyslog(const char *s) {} | |
| 826 | INLINE void LogMessageOnPrintf(const char *str) {} | |
| 896 | inline void WriteOneLineToSyslog(const char *s) {} | |
| 897 | inline void LogMessageOnPrintf(const char *str) {} | |
| 827 | 898 | #endif |
| 828 | 899 | |
| 829 | 900 | #if SANITIZER_LINUX || SANITIZER_WIN_TRACE |
| ... | ... | @@ -831,21 +902,21 @@ INLINE void LogMessageOnPrintf(const char *str) {} |
| 831 | 902 | void AndroidLogInit(); |
| 832 | 903 | void SetAbortMessage(const char *); |
| 833 | 904 | #else |
| 834 | INLINE void AndroidLogInit() {} | |
| 905 | inline void AndroidLogInit() {} | |
| 835 | 906 | // FIXME: MacOS implementation could use CRSetCrashLogMessage. |
| 836 | INLINE void SetAbortMessage(const char *) {} | |
| 907 | inline void SetAbortMessage(const char *) {} | |
| 837 | 908 | #endif |
| 838 | 909 | |
| 839 | 910 | #if SANITIZER_ANDROID |
| 840 | 911 | void SanitizerInitializeUnwinder(); |
| 841 | 912 | AndroidApiLevel AndroidGetApiLevel(); |
| 842 | 913 | #else |
| 843 | INLINE void AndroidLogWrite(const char *buffer_unused) {} | |
| 844 | INLINE void SanitizerInitializeUnwinder() {} | |
| 845 | INLINE AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; } | |
| 914 | inline void AndroidLogWrite(const char *buffer_unused) {} | |
| 915 | inline void SanitizerInitializeUnwinder() {} | |
| 916 | inline AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; } | |
| 846 | 917 | #endif |
| 847 | 918 | |
| 848 | INLINE uptr GetPthreadDestructorIterations() { | |
| 919 | inline uptr GetPthreadDestructorIterations() { | |
| 849 | 920 | #if SANITIZER_ANDROID |
| 850 | 921 | return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4; |
| 851 | 922 | #elif SANITIZER_POSIX |
| ... | ... | @@ -951,7 +1022,7 @@ RunOnDestruction<Fn> at_scope_exit(Fn fn) { |
| 951 | 1022 | #if SANITIZER_LINUX && SANITIZER_S390_64 |
| 952 | 1023 | void AvoidCVE_2016_2143(); |
| 953 | 1024 | #else |
| 954 | INLINE void AvoidCVE_2016_2143() {} | |
| 1025 | inline void AvoidCVE_2016_2143() {} | |
| 955 | 1026 | #endif |
| 956 | 1027 | |
| 957 | 1028 | struct StackDepotStats { |
| ... | ... | @@ -972,7 +1043,7 @@ bool GetRandom(void *buffer, uptr length, bool blocking = true); |
| 972 | 1043 | // Returns the number of logical processors on the system. |
| 973 | 1044 | u32 GetNumberOfCPUs(); |
| 974 | 1045 | extern u32 NumberOfCPUsCached; |
| 975 | INLINE u32 GetNumberOfCPUsCached() { | |
| 1046 | inline u32 GetNumberOfCPUsCached() { | |
| 976 | 1047 | if (!NumberOfCPUsCached) |
| 977 | 1048 | NumberOfCPUsCached = GetNumberOfCPUs(); |
| 978 | 1049 | return NumberOfCPUsCached; |
| ... | ... | @@ -992,6 +1063,13 @@ class ArrayRef { |
| 992 | 1063 | T *end_ = nullptr; |
| 993 | 1064 | }; |
| 994 | 1065 | |
| 1066 | #define PRINTF_128(v) \ | |
| 1067 | (*((u8 *)&v + 0)), (*((u8 *)&v + 1)), (*((u8 *)&v + 2)), (*((u8 *)&v + 3)), \ | |
| 1068 | (*((u8 *)&v + 4)), (*((u8 *)&v + 5)), (*((u8 *)&v + 6)), \ | |
| 1069 | (*((u8 *)&v + 7)), (*((u8 *)&v + 8)), (*((u8 *)&v + 9)), \ | |
| 1070 | (*((u8 *)&v + 10)), (*((u8 *)&v + 11)), (*((u8 *)&v + 12)), \ | |
| 1071 | (*((u8 *)&v + 13)), (*((u8 *)&v + 14)), (*((u8 *)&v + 15)) | |
| 1072 | ||
| 995 | 1073 | } // namespace __sanitizer |
| 996 | 1074 | |
| 997 | 1075 | inline void *operator new(__sanitizer::operator_new_size_type size, |
lib/tsan/sanitizer_common/sanitizer_common_interceptors.inc+273-39| ... | ... | @@ -134,11 +134,11 @@ extern const short *_tolower_tab_; |
| 134 | 134 | |
| 135 | 135 | // Platform-specific options. |
| 136 | 136 | #if SANITIZER_MAC |
| 137 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false | |
| 137 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 | |
| 138 | 138 | #elif SANITIZER_WINDOWS64 |
| 139 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false | |
| 139 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 | |
| 140 | 140 | #else |
| 141 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true | |
| 141 | #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 | |
| 142 | 142 | #endif // SANITIZER_MAC |
| 143 | 143 | |
| 144 | 144 | #ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE |
| ... | ... | @@ -239,6 +239,23 @@ extern const short *_tolower_tab_; |
| 239 | 239 | COMMON_INTERCEPT_FUNCTION(fn) |
| 240 | 240 | #endif |
| 241 | 241 | |
| 242 | #if SANITIZER_GLIBC | |
| 243 | // If we could not find the versioned symbol, fall back to an unversioned | |
| 244 | // lookup. This is needed to work around a GLibc bug that causes dlsym | |
| 245 | // with RTLD_NEXT to return the oldest versioned symbol. | |
| 246 | // See https://sourceware.org/bugzilla/show_bug.cgi?id=14932. | |
| 247 | // For certain symbols (e.g. regexec) we have to perform a versioned lookup, | |
| 248 | // but that versioned symbol will only exist for architectures where the | |
| 249 | // oldest Glibc version pre-dates support for that architecture. | |
| 250 | // For example, regexec@GLIBC_2.3.4 exists on x86_64, but not RISC-V. | |
| 251 | // See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98920. | |
| 252 | #define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \ | |
| 253 | COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(fn, ver) | |
| 254 | #else | |
| 255 | #define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \ | |
| 256 | COMMON_INTERCEPT_FUNCTION(fn) | |
| 257 | #endif | |
| 258 | ||
| 242 | 259 | #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL |
| 243 | 260 | #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ |
| 244 | 261 | { \ |
| ... | ... | @@ -445,8 +462,10 @@ INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { |
| 445 | 462 | c2 = (unsigned char)s2[i]; |
| 446 | 463 | if (c1 != c2 || c1 == '\0') break; |
| 447 | 464 | } |
| 448 | COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); | |
| 449 | COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); | |
| 465 | if (common_flags()->intercept_strcmp) { | |
| 466 | COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); | |
| 467 | COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); | |
| 468 | } | |
| 450 | 469 | int result = CharCmpX(c1, c2); |
| 451 | 470 | CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1, |
| 452 | 471 | s2, result); |
| ... | ... | @@ -804,11 +823,11 @@ INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) { |
| 804 | 823 | // N.B.: If we switch this to internal_ we'll have to use internal_memmove |
| 805 | 824 | // due to memcpy being an alias of memmove on OS X. |
| 806 | 825 | void *ctx; |
| 807 | if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { | |
| 826 | #if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE | |
| 808 | 827 | COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size); |
| 809 | } else { | |
| 828 | #else | |
| 810 | 829 | COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); |
| 811 | } | |
| 830 | #endif | |
| 812 | 831 | } |
| 813 | 832 | |
| 814 | 833 | #define INIT_MEMCPY \ |
| ... | ... | @@ -938,6 +957,7 @@ INTERCEPTOR(double, frexp, double x, int *exp) { |
| 938 | 957 | // Assuming frexp() always writes to |exp|. |
| 939 | 958 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); |
| 940 | 959 | double res = REAL(frexp)(x, exp); |
| 960 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp)); | |
| 941 | 961 | return res; |
| 942 | 962 | } |
| 943 | 963 | |
| ... | ... | @@ -950,22 +970,18 @@ INTERCEPTOR(double, frexp, double x, int *exp) { |
| 950 | 970 | INTERCEPTOR(float, frexpf, float x, int *exp) { |
| 951 | 971 | void *ctx; |
| 952 | 972 | COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp); |
| 953 | // FIXME: under ASan the call below may write to freed memory and corrupt | |
| 954 | // its metadata. See | |
| 955 | // https://github.com/google/sanitizers/issues/321. | |
| 956 | float res = REAL(frexpf)(x, exp); | |
| 957 | 973 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); |
| 974 | float res = REAL(frexpf)(x, exp); | |
| 975 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp)); | |
| 958 | 976 | return res; |
| 959 | 977 | } |
| 960 | 978 | |
| 961 | 979 | INTERCEPTOR(long double, frexpl, long double x, int *exp) { |
| 962 | 980 | void *ctx; |
| 963 | 981 | COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp); |
| 964 | // FIXME: under ASan the call below may write to freed memory and corrupt | |
| 965 | // its metadata. See | |
| 966 | // https://github.com/google/sanitizers/issues/321. | |
| 967 | long double res = REAL(frexpl)(x, exp); | |
| 968 | 982 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); |
| 983 | long double res = REAL(frexpl)(x, exp); | |
| 984 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp)); | |
| 969 | 985 | return res; |
| 970 | 986 | } |
| 971 | 987 | |
| ... | ... | @@ -1862,7 +1878,7 @@ UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) { |
| 1862 | 1878 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos, |
| 1863 | 1879 | REAL(strlen)(pwd->pw_gecos) + 1); |
| 1864 | 1880 | #endif |
| 1865 | #if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD | |
| 1881 | #if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 1866 | 1882 | if (pwd->pw_class) |
| 1867 | 1883 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class, |
| 1868 | 1884 | REAL(strlen)(pwd->pw_class) + 1); |
| ... | ... | @@ -2176,6 +2192,7 @@ INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) { |
| 2176 | 2192 | } |
| 2177 | 2193 | return res; |
| 2178 | 2194 | } |
| 2195 | #if SANITIZER_GLIBC | |
| 2179 | 2196 | namespace __sanitizer { |
| 2180 | 2197 | extern "C" { |
| 2181 | 2198 | int real_clock_gettime(u32 clk_id, void *tp) { |
| ... | ... | @@ -2185,6 +2202,7 @@ int real_clock_gettime(u32 clk_id, void *tp) { |
| 2185 | 2202 | } |
| 2186 | 2203 | } // extern "C" |
| 2187 | 2204 | } // namespace __sanitizer |
| 2205 | #endif | |
| 2188 | 2206 | INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) { |
| 2189 | 2207 | void *ctx; |
| 2190 | 2208 | COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp); |
| ... | ... | @@ -3336,7 +3354,7 @@ INTERCEPTOR(char *, setlocale, int category, char *locale) { |
| 3336 | 3354 | COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1); |
| 3337 | 3355 | char *res = REAL(setlocale)(category, locale); |
| 3338 | 3356 | if (res) { |
| 3339 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); | |
| 3357 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); | |
| 3340 | 3358 | unpoison_ctype_arrays(ctx); |
| 3341 | 3359 | } |
| 3342 | 3360 | return res; |
| ... | ... | @@ -3748,7 +3766,7 @@ INTERCEPTOR(char *, strerror, int errnum) { |
| 3748 | 3766 | // static storage. |
| 3749 | 3767 | #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \ |
| 3750 | 3768 | SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD || \ |
| 3751 | SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 3769 | SANITIZER_FREEBSD | |
| 3752 | 3770 | // POSIX version. Spec is not clear on whether buf is NULL-terminated. |
| 3753 | 3771 | // At least on OSX, buf contents are valid even when the call fails. |
| 3754 | 3772 | INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) { |
| ... | ... | @@ -4011,7 +4029,7 @@ INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) { |
| 4011 | 4029 | // FIXME: under ASan the call below may write to freed memory and corrupt |
| 4012 | 4030 | // its metadata. See |
| 4013 | 4031 | // https://github.com/google/sanitizers/issues/321. |
| 4014 | int res = REAL(sigwait)(set, sig); | |
| 4032 | int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwait)(set, sig); | |
| 4015 | 4033 | if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig)); |
| 4016 | 4034 | return res; |
| 4017 | 4035 | } |
| ... | ... | @@ -4028,7 +4046,7 @@ INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) { |
| 4028 | 4046 | // FIXME: under ASan the call below may write to freed memory and corrupt |
| 4029 | 4047 | // its metadata. See |
| 4030 | 4048 | // https://github.com/google/sanitizers/issues/321. |
| 4031 | int res = REAL(sigwaitinfo)(set, info); | |
| 4049 | int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwaitinfo)(set, info); | |
| 4032 | 4050 | if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz); |
| 4033 | 4051 | return res; |
| 4034 | 4052 | } |
| ... | ... | @@ -4047,7 +4065,7 @@ INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info, |
| 4047 | 4065 | // FIXME: under ASan the call below may write to freed memory and corrupt |
| 4048 | 4066 | // its metadata. See |
| 4049 | 4067 | // https://github.com/google/sanitizers/issues/321. |
| 4050 | int res = REAL(sigtimedwait)(set, info, timeout); | |
| 4068 | int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigtimedwait)(set, info, timeout); | |
| 4051 | 4069 | if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz); |
| 4052 | 4070 | return res; |
| 4053 | 4071 | } |
| ... | ... | @@ -4085,6 +4103,41 @@ INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) { |
| 4085 | 4103 | #define INIT_SIGSETOPS |
| 4086 | 4104 | #endif |
| 4087 | 4105 | |
| 4106 | #if SANITIZER_INTERCEPT_SIGSET_LOGICOPS | |
| 4107 | INTERCEPTOR(int, sigandset, __sanitizer_sigset_t *dst, | |
| 4108 | __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) { | |
| 4109 | void *ctx; | |
| 4110 | COMMON_INTERCEPTOR_ENTER(ctx, sigandset, dst, src1, src2); | |
| 4111 | if (src1) | |
| 4112 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1)); | |
| 4113 | if (src2) | |
| 4114 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2)); | |
| 4115 | int res = REAL(sigandset)(dst, src1, src2); | |
| 4116 | if (!res && dst) | |
| 4117 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst)); | |
| 4118 | return res; | |
| 4119 | } | |
| 4120 | ||
| 4121 | INTERCEPTOR(int, sigorset, __sanitizer_sigset_t *dst, | |
| 4122 | __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) { | |
| 4123 | void *ctx; | |
| 4124 | COMMON_INTERCEPTOR_ENTER(ctx, sigorset, dst, src1, src2); | |
| 4125 | if (src1) | |
| 4126 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1)); | |
| 4127 | if (src2) | |
| 4128 | COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2)); | |
| 4129 | int res = REAL(sigorset)(dst, src1, src2); | |
| 4130 | if (!res && dst) | |
| 4131 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst)); | |
| 4132 | return res; | |
| 4133 | } | |
| 4134 | #define INIT_SIGSET_LOGICOPS \ | |
| 4135 | COMMON_INTERCEPT_FUNCTION(sigandset); \ | |
| 4136 | COMMON_INTERCEPT_FUNCTION(sigorset); | |
| 4137 | #else | |
| 4138 | #define INIT_SIGSET_LOGICOPS | |
| 4139 | #endif | |
| 4140 | ||
| 4088 | 4141 | #if SANITIZER_INTERCEPT_SIGPENDING |
| 4089 | 4142 | INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) { |
| 4090 | 4143 | void *ctx; |
| ... | ... | @@ -4838,6 +4891,34 @@ INTERCEPTOR(char *, tmpnam_r, char *s) { |
| 4838 | 4891 | #define INIT_TMPNAM_R |
| 4839 | 4892 | #endif |
| 4840 | 4893 | |
| 4894 | #if SANITIZER_INTERCEPT_PTSNAME | |
| 4895 | INTERCEPTOR(char *, ptsname, int fd) { | |
| 4896 | void *ctx; | |
| 4897 | COMMON_INTERCEPTOR_ENTER(ctx, ptsname, fd); | |
| 4898 | char *res = REAL(ptsname)(fd); | |
| 4899 | if (res != nullptr) | |
| 4900 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); | |
| 4901 | return res; | |
| 4902 | } | |
| 4903 | #define INIT_PTSNAME COMMON_INTERCEPT_FUNCTION(ptsname); | |
| 4904 | #else | |
| 4905 | #define INIT_PTSNAME | |
| 4906 | #endif | |
| 4907 | ||
| 4908 | #if SANITIZER_INTERCEPT_PTSNAME_R | |
| 4909 | INTERCEPTOR(int, ptsname_r, int fd, char *name, SIZE_T namesize) { | |
| 4910 | void *ctx; | |
| 4911 | COMMON_INTERCEPTOR_ENTER(ctx, ptsname_r, fd, name, namesize); | |
| 4912 | int res = REAL(ptsname_r)(fd, name, namesize); | |
| 4913 | if (res == 0) | |
| 4914 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1); | |
| 4915 | return res; | |
| 4916 | } | |
| 4917 | #define INIT_PTSNAME_R COMMON_INTERCEPT_FUNCTION(ptsname_r); | |
| 4918 | #else | |
| 4919 | #define INIT_PTSNAME_R | |
| 4920 | #endif | |
| 4921 | ||
| 4841 | 4922 | #if SANITIZER_INTERCEPT_TTYNAME |
| 4842 | 4923 | INTERCEPTOR(char *, ttyname, int fd) { |
| 4843 | 4924 | void *ctx; |
| ... | ... | @@ -5219,6 +5300,12 @@ INTERCEPTOR(__sanitizer_clock_t, times, void *tms) { |
| 5219 | 5300 | #define INIT_TIMES |
| 5220 | 5301 | #endif |
| 5221 | 5302 | |
| 5303 | #if SANITIZER_S390 && \ | |
| 5304 | (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET) | |
| 5305 | extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); | |
| 5306 | DEFINE_REAL(uptr, __tls_get_offset, void *arg) | |
| 5307 | #endif | |
| 5308 | ||
| 5222 | 5309 | #if SANITIZER_INTERCEPT_TLS_GET_ADDR |
| 5223 | 5310 | #if !SANITIZER_S390 |
| 5224 | 5311 | #define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr) |
| ... | ... | @@ -5258,11 +5345,7 @@ void *__tls_get_addr_opt(void *arg); |
| 5258 | 5345 | // descriptor offset as an argument instead of a pointer. GOT address |
| 5259 | 5346 | // is passed in r12, so it's necessary to write it in assembly. This is |
| 5260 | 5347 | // the function used by the compiler. |
| 5261 | extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); | |
| 5262 | 5348 | #define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset) |
| 5263 | DEFINE_REAL(uptr, __tls_get_offset, void *arg) | |
| 5264 | extern "C" uptr __tls_get_offset(void *arg); | |
| 5265 | extern "C" uptr __interceptor___tls_get_offset(void *arg); | |
| 5266 | 5349 | INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { |
| 5267 | 5350 | void *ctx; |
| 5268 | 5351 | COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg); |
| ... | ... | @@ -5278,6 +5361,15 @@ INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { |
| 5278 | 5361 | } |
| 5279 | 5362 | return res; |
| 5280 | 5363 | } |
| 5364 | #endif // SANITIZER_S390 | |
| 5365 | #else | |
| 5366 | #define INIT_TLS_GET_ADDR | |
| 5367 | #endif | |
| 5368 | ||
| 5369 | #if SANITIZER_S390 && \ | |
| 5370 | (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET) | |
| 5371 | extern "C" uptr __tls_get_offset(void *arg); | |
| 5372 | extern "C" uptr __interceptor___tls_get_offset(void *arg); | |
| 5281 | 5373 | // We need a hidden symbol aliasing the above, so that we can jump |
| 5282 | 5374 | // directly to it from the assembly below. |
| 5283 | 5375 | extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"), |
| ... | ... | @@ -5316,9 +5408,6 @@ asm( |
| 5316 | 5408 | "br %r3\n" |
| 5317 | 5409 | ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n" |
| 5318 | 5410 | ); |
| 5319 | #endif // SANITIZER_S390 | |
| 5320 | #else | |
| 5321 | #define INIT_TLS_GET_ADDR | |
| 5322 | 5411 | #endif |
| 5323 | 5412 | |
| 5324 | 5413 | #if SANITIZER_INTERCEPT_LISTXATTR |
| ... | ... | @@ -5809,6 +5898,79 @@ INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p, |
| 5809 | 5898 | #define INIT_XDR |
| 5810 | 5899 | #endif // SANITIZER_INTERCEPT_XDR |
| 5811 | 5900 | |
| 5901 | #if SANITIZER_INTERCEPT_XDRREC | |
| 5902 | typedef int (*xdrrec_cb)(char*, char*, int); | |
| 5903 | struct XdrRecWrapper { | |
| 5904 | char *handle; | |
| 5905 | xdrrec_cb rd, wr; | |
| 5906 | }; | |
| 5907 | typedef AddrHashMap<XdrRecWrapper *, 11> XdrRecWrapMap; | |
| 5908 | static XdrRecWrapMap *xdrrec_wrap_map; | |
| 5909 | ||
| 5910 | static int xdrrec_wr_wrap(char *handle, char *buf, int count) { | |
| 5911 | COMMON_INTERCEPTOR_UNPOISON_PARAM(3); | |
| 5912 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(buf, count); | |
| 5913 | XdrRecWrapper *wrap = (XdrRecWrapper *)handle; | |
| 5914 | return wrap->wr(wrap->handle, buf, count); | |
| 5915 | } | |
| 5916 | ||
| 5917 | static int xdrrec_rd_wrap(char *handle, char *buf, int count) { | |
| 5918 | COMMON_INTERCEPTOR_UNPOISON_PARAM(3); | |
| 5919 | XdrRecWrapper *wrap = (XdrRecWrapper *)handle; | |
| 5920 | return wrap->rd(wrap->handle, buf, count); | |
| 5921 | } | |
| 5922 | ||
| 5923 | // This doesn't apply to the solaris version as it has a different function | |
| 5924 | // signature. | |
| 5925 | INTERCEPTOR(void, xdrrec_create, __sanitizer_XDR *xdr, unsigned sndsize, | |
| 5926 | unsigned rcvsize, char *handle, int (*rd)(char*, char*, int), | |
| 5927 | int (*wr)(char*, char*, int)) { | |
| 5928 | void *ctx; | |
| 5929 | COMMON_INTERCEPTOR_ENTER(ctx, xdrrec_create, xdr, sndsize, rcvsize, | |
| 5930 | handle, rd, wr); | |
| 5931 | COMMON_INTERCEPTOR_READ_RANGE(ctx, &xdr->x_op, sizeof xdr->x_op); | |
| 5932 | ||
| 5933 | // We can't allocate a wrapper on the stack, as the handle is used outside | |
| 5934 | // this stack frame. So we put it on the heap, and keep track of it with | |
| 5935 | // the HashMap (keyed by x_private). When we later need to xdr_destroy, | |
| 5936 | // we can index the map, free the wrapper, and then clean the map entry. | |
| 5937 | XdrRecWrapper *wrap_data = | |
| 5938 | (XdrRecWrapper *)InternalAlloc(sizeof(XdrRecWrapper)); | |
| 5939 | wrap_data->handle = handle; | |
| 5940 | wrap_data->rd = rd; | |
| 5941 | wrap_data->wr = wr; | |
| 5942 | if (wr) | |
| 5943 | wr = xdrrec_wr_wrap; | |
| 5944 | if (rd) | |
| 5945 | rd = xdrrec_rd_wrap; | |
| 5946 | handle = (char *)wrap_data; | |
| 5947 | ||
| 5948 | REAL(xdrrec_create)(xdr, sndsize, rcvsize, handle, rd, wr); | |
| 5949 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdr, sizeof *xdr); | |
| 5950 | ||
| 5951 | XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, false, true); | |
| 5952 | *wrap = wrap_data; | |
| 5953 | } | |
| 5954 | ||
| 5955 | // We have to intercept this to be able to free wrapper memory; | |
| 5956 | // otherwise it's not necessary. | |
| 5957 | INTERCEPTOR(void, xdr_destroy, __sanitizer_XDR *xdr) { | |
| 5958 | void *ctx; | |
| 5959 | COMMON_INTERCEPTOR_ENTER(ctx, xdr_destroy, xdr); | |
| 5960 | ||
| 5961 | XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, true); | |
| 5962 | InternalFree(*wrap); | |
| 5963 | REAL(xdr_destroy)(xdr); | |
| 5964 | } | |
| 5965 | #define INIT_XDRREC_LINUX \ | |
| 5966 | static u64 xdrrec_wrap_mem[sizeof(XdrRecWrapMap) / sizeof(u64) + 1]; \ | |
| 5967 | xdrrec_wrap_map = new ((void *)&xdrrec_wrap_mem) XdrRecWrapMap(); \ | |
| 5968 | COMMON_INTERCEPT_FUNCTION(xdrrec_create); \ | |
| 5969 | COMMON_INTERCEPT_FUNCTION(xdr_destroy); | |
| 5970 | #else | |
| 5971 | #define INIT_XDRREC_LINUX | |
| 5972 | #endif | |
| 5973 | ||
| 5812 | 5974 | #if SANITIZER_INTERCEPT_TSEARCH |
| 5813 | 5975 | INTERCEPTOR(void *, tsearch, void *key, void **rootp, |
| 5814 | 5976 | int (*compar)(const void *, const void *)) { |
| ... | ... | @@ -5840,6 +6002,9 @@ void unpoison_file(__sanitizer_FILE *fp) { |
| 5840 | 6002 | if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end) |
| 5841 | 6003 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base, |
| 5842 | 6004 | fp->_IO_read_end - fp->_IO_read_base); |
| 6005 | if (fp->_IO_write_base && fp->_IO_write_base < fp->_IO_write_end) | |
| 6006 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_write_base, | |
| 6007 | fp->_IO_write_end - fp->_IO_write_base); | |
| 5843 | 6008 | #endif |
| 5844 | 6009 | #endif // SANITIZER_HAS_STRUCT_FILE |
| 5845 | 6010 | } |
| ... | ... | @@ -5939,6 +6104,40 @@ INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode, |
| 5939 | 6104 | #define INIT_FOPEN |
| 5940 | 6105 | #endif |
| 5941 | 6106 | |
| 6107 | #if SANITIZER_INTERCEPT_FLOPEN | |
| 6108 | INTERCEPTOR(int, flopen, const char *path, int flags, ...) { | |
| 6109 | void *ctx; | |
| 6110 | va_list ap; | |
| 6111 | va_start(ap, flags); | |
| 6112 | u16 mode = static_cast<u16>(va_arg(ap, u32)); | |
| 6113 | va_end(ap); | |
| 6114 | COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode); | |
| 6115 | if (path) { | |
| 6116 | COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); | |
| 6117 | } | |
| 6118 | return REAL(flopen)(path, flags, mode); | |
| 6119 | } | |
| 6120 | ||
| 6121 | INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) { | |
| 6122 | void *ctx; | |
| 6123 | va_list ap; | |
| 6124 | va_start(ap, flags); | |
| 6125 | u16 mode = static_cast<u16>(va_arg(ap, u32)); | |
| 6126 | va_end(ap); | |
| 6127 | COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode); | |
| 6128 | if (path) { | |
| 6129 | COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); | |
| 6130 | } | |
| 6131 | return REAL(flopenat)(dirfd, path, flags, mode); | |
| 6132 | } | |
| 6133 | ||
| 6134 | #define INIT_FLOPEN \ | |
| 6135 | COMMON_INTERCEPT_FUNCTION(flopen); \ | |
| 6136 | COMMON_INTERCEPT_FUNCTION(flopenat); | |
| 6137 | #else | |
| 6138 | #define INIT_FLOPEN | |
| 6139 | #endif | |
| 6140 | ||
| 5942 | 6141 | #if SANITIZER_INTERCEPT_FOPEN64 |
| 5943 | 6142 | INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) { |
| 5944 | 6143 | void *ctx; |
| ... | ... | @@ -6066,6 +6265,8 @@ INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) { |
| 6066 | 6265 | INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) { |
| 6067 | 6266 | void *ctx; |
| 6068 | 6267 | COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp); |
| 6268 | if (fp) | |
| 6269 | unpoison_file(fp); | |
| 6069 | 6270 | int res = REAL(fflush)(fp); |
| 6070 | 6271 | // FIXME: handle fp == NULL |
| 6071 | 6272 | if (fp) { |
| ... | ... | @@ -6085,6 +6286,8 @@ INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) { |
| 6085 | 6286 | COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp); |
| 6086 | 6287 | COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp); |
| 6087 | 6288 | const FileMetadata *m = GetInterceptorMetadata(fp); |
| 6289 | if (fp) | |
| 6290 | unpoison_file(fp); | |
| 6088 | 6291 | int res = REAL(fclose)(fp); |
| 6089 | 6292 | if (m) { |
| 6090 | 6293 | COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size); |
| ... | ... | @@ -6299,7 +6502,7 @@ INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) { |
| 6299 | 6502 | INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) { |
| 6300 | 6503 | void *ctx; |
| 6301 | 6504 | COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s); |
| 6302 | int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s); | |
| 6505 | int res = REAL(sem_trywait)(s); | |
| 6303 | 6506 | if (res == 0) { |
| 6304 | 6507 | COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s); |
| 6305 | 6508 | } |
| ... | ... | @@ -7634,7 +7837,7 @@ INTERCEPTOR(void, regfree, const void *preg) { |
| 7634 | 7837 | } |
| 7635 | 7838 | #define INIT_REGEX \ |
| 7636 | 7839 | COMMON_INTERCEPT_FUNCTION(regcomp); \ |
| 7637 | COMMON_INTERCEPT_FUNCTION(regexec); \ | |
| 7840 | COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(regexec, "GLIBC_2.3.4"); \ | |
| 7638 | 7841 | COMMON_INTERCEPT_FUNCTION(regerror); \ |
| 7639 | 7842 | COMMON_INTERCEPT_FUNCTION(regfree); |
| 7640 | 7843 | #else |
| ... | ... | @@ -9755,12 +9958,25 @@ INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size, |
| 9755 | 9958 | } |
| 9756 | 9959 | } |
| 9757 | 9960 | qsort_compar_f old_compar = qsort_compar; |
| 9758 | qsort_compar = compar; | |
| 9759 | 9961 | SIZE_T old_size = qsort_size; |
| 9760 | qsort_size = size; | |
| 9962 | // Handle qsort() implementations that recurse using an | |
| 9963 | // interposable function call: | |
| 9964 | bool already_wrapped = compar == wrapped_qsort_compar; | |
| 9965 | if (already_wrapped) { | |
| 9966 | // This case should only happen if the qsort() implementation calls itself | |
| 9967 | // using a preemptible function call (e.g. the FreeBSD libc version). | |
| 9968 | // Check that the size and comparator arguments are as expected. | |
| 9969 | CHECK_NE(compar, qsort_compar); | |
| 9970 | CHECK_EQ(qsort_size, size); | |
| 9971 | } else { | |
| 9972 | qsort_compar = compar; | |
| 9973 | qsort_size = size; | |
| 9974 | } | |
| 9761 | 9975 | REAL(qsort)(base, nmemb, size, wrapped_qsort_compar); |
| 9762 | qsort_compar = old_compar; | |
| 9763 | qsort_size = old_size; | |
| 9976 | if (!already_wrapped) { | |
| 9977 | qsort_compar = old_compar; | |
| 9978 | qsort_size = old_size; | |
| 9979 | } | |
| 9764 | 9980 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); |
| 9765 | 9981 | } |
| 9766 | 9982 | #define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort) |
| ... | ... | @@ -9793,12 +10009,25 @@ INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size, |
| 9793 | 10009 | } |
| 9794 | 10010 | } |
| 9795 | 10011 | qsort_r_compar_f old_compar = qsort_r_compar; |
| 9796 | qsort_r_compar = compar; | |
| 9797 | 10012 | SIZE_T old_size = qsort_r_size; |
| 9798 | qsort_r_size = size; | |
| 10013 | // Handle qsort_r() implementations that recurse using an | |
| 10014 | // interposable function call: | |
| 10015 | bool already_wrapped = compar == wrapped_qsort_r_compar; | |
| 10016 | if (already_wrapped) { | |
| 10017 | // This case should only happen if the qsort() implementation calls itself | |
| 10018 | // using a preemptible function call (e.g. the FreeBSD libc version). | |
| 10019 | // Check that the size and comparator arguments are as expected. | |
| 10020 | CHECK_NE(compar, qsort_r_compar); | |
| 10021 | CHECK_EQ(qsort_r_size, size); | |
| 10022 | } else { | |
| 10023 | qsort_r_compar = compar; | |
| 10024 | qsort_r_size = size; | |
| 10025 | } | |
| 9799 | 10026 | REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg); |
| 9800 | qsort_r_compar = old_compar; | |
| 9801 | qsort_r_size = old_size; | |
| 10027 | if (!already_wrapped) { | |
| 10028 | qsort_r_compar = old_compar; | |
| 10029 | qsort_r_size = old_size; | |
| 10030 | } | |
| 9802 | 10031 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); |
| 9803 | 10032 | } |
| 9804 | 10033 | #define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r) |
| ... | ... | @@ -9996,6 +10225,7 @@ static void InitializeCommonInterceptors() { |
| 9996 | 10225 | INIT_SIGWAITINFO; |
| 9997 | 10226 | INIT_SIGTIMEDWAIT; |
| 9998 | 10227 | INIT_SIGSETOPS; |
| 10228 | INIT_SIGSET_LOGICOPS; | |
| 9999 | 10229 | INIT_SIGPENDING; |
| 10000 | 10230 | INIT_SIGPROCMASK; |
| 10001 | 10231 | INIT_PTHREAD_SIGMASK; |
| ... | ... | @@ -10037,6 +10267,8 @@ static void InitializeCommonInterceptors() { |
| 10037 | 10267 | INIT_PTHREAD_BARRIERATTR_GETPSHARED; |
| 10038 | 10268 | INIT_TMPNAM; |
| 10039 | 10269 | INIT_TMPNAM_R; |
| 10270 | INIT_PTSNAME; | |
| 10271 | INIT_PTSNAME_R; | |
| 10040 | 10272 | INIT_TTYNAME; |
| 10041 | 10273 | INIT_TTYNAME_R; |
| 10042 | 10274 | INIT_TEMPNAM; |
| ... | ... | @@ -10066,10 +10298,12 @@ static void InitializeCommonInterceptors() { |
| 10066 | 10298 | INIT_BZERO; |
| 10067 | 10299 | INIT_FTIME; |
| 10068 | 10300 | INIT_XDR; |
| 10301 | INIT_XDRREC_LINUX; | |
| 10069 | 10302 | INIT_TSEARCH; |
| 10070 | 10303 | INIT_LIBIO_INTERNALS; |
| 10071 | 10304 | INIT_FOPEN; |
| 10072 | 10305 | INIT_FOPEN64; |
| 10306 | INIT_FLOPEN; | |
| 10073 | 10307 | INIT_OPEN_MEMSTREAM; |
| 10074 | 10308 | INIT_OBSTACK; |
| 10075 | 10309 | INIT_FFLUSH; |
lib/tsan/sanitizer_common/sanitizer_common_interceptors_format.inc+6| ... | ... | @@ -340,6 +340,12 @@ static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc, |
| 340 | 340 | size = 0; |
| 341 | 341 | } |
| 342 | 342 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size); |
| 343 | // For %ms/%mc, write the allocated output buffer as well. | |
| 344 | if (dir.allocate) { | |
| 345 | char *buf = *(char **)argp; | |
| 346 | if (buf) | |
| 347 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1); | |
| 348 | } | |
| 343 | 349 | } |
| 344 | 350 | } |
| 345 | 351 |
lib/tsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc+5-10| ... | ... | @@ -330,13 +330,17 @@ static void ioctl_table_fill() { |
| 330 | 330 | _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int)); |
| 331 | 331 | _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int)); |
| 332 | 332 | _(TCFLSH, NONE, 0); |
| 333 | #if SANITIZER_GLIBC | |
| 333 | 334 | _(TCGETA, WRITE, struct_termio_sz); |
| 335 | #endif | |
| 334 | 336 | _(TCGETS, WRITE, struct_termios_sz); |
| 335 | 337 | _(TCSBRK, NONE, 0); |
| 336 | 338 | _(TCSBRKP, NONE, 0); |
| 339 | #if SANITIZER_GLIBC | |
| 337 | 340 | _(TCSETA, READ, struct_termio_sz); |
| 338 | 341 | _(TCSETAF, READ, struct_termio_sz); |
| 339 | 342 | _(TCSETAW, READ, struct_termio_sz); |
| 343 | #endif | |
| 340 | 344 | _(TCSETS, READ, struct_termios_sz); |
| 341 | 345 | _(TCSETSF, READ, struct_termios_sz); |
| 342 | 346 | _(TCSETSW, READ, struct_termios_sz); |
| ... | ... | @@ -364,17 +368,8 @@ static void ioctl_table_fill() { |
| 364 | 368 | _(VT_WAITACTIVE, NONE, 0); |
| 365 | 369 | #endif |
| 366 | 370 | |
| 367 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 371 | #if SANITIZER_GLIBC | |
| 368 | 372 | // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE |
| 369 | _(CYGETDEFTHRESH, WRITE, sizeof(int)); | |
| 370 | _(CYGETDEFTIMEOUT, WRITE, sizeof(int)); | |
| 371 | _(CYGETMON, WRITE, struct_cyclades_monitor_sz); | |
| 372 | _(CYGETTHRESH, WRITE, sizeof(int)); | |
| 373 | _(CYGETTIMEOUT, WRITE, sizeof(int)); | |
| 374 | _(CYSETDEFTHRESH, NONE, 0); | |
| 375 | _(CYSETDEFTIMEOUT, NONE, 0); | |
| 376 | _(CYSETTHRESH, NONE, 0); | |
| 377 | _(CYSETTIMEOUT, NONE, 0); | |
| 378 | 373 | _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz); |
| 379 | 374 | _(EQL_ENSLAVE, WRITE, struct_ifreq_sz); |
| 380 | 375 | _(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz); |
lib/tsan/sanitizer_common/sanitizer_common_interface.inc+1| ... | ... | @@ -13,6 +13,7 @@ INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address) |
| 13 | 13 | INTERFACE_FUNCTION(__sanitizer_set_death_callback) |
| 14 | 14 | INTERFACE_FUNCTION(__sanitizer_set_report_path) |
| 15 | 15 | INTERFACE_FUNCTION(__sanitizer_set_report_fd) |
| 16 | INTERFACE_FUNCTION(__sanitizer_get_report_path) | |
| 16 | 17 | INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container) |
| 17 | 18 | INTERFACE_WEAK_FUNCTION(__sanitizer_on_print) |
| 18 | 19 | INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary) |
lib/tsan/sanitizer_common/sanitizer_common_libcdep.cpp+56-4| ... | ... | @@ -92,14 +92,13 @@ void *BackgroundThread(void *arg) { |
| 92 | 92 | #endif |
| 93 | 93 | |
| 94 | 94 | void WriteToSyslog(const char *msg) { |
| 95 | InternalScopedString msg_copy(kErrorMessageBufferSize); | |
| 95 | InternalScopedString msg_copy; | |
| 96 | 96 | msg_copy.append("%s", msg); |
| 97 | char *p = msg_copy.data(); | |
| 98 | char *q; | |
| 97 | const char *p = msg_copy.data(); | |
| 99 | 98 | |
| 100 | 99 | // Print one line at a time. |
| 101 | 100 | // syslog, at least on Android, has an implicit message length limit. |
| 102 | while ((q = internal_strchr(p, '\n'))) { | |
| 101 | while (char* q = internal_strchr(p, '\n')) { | |
| 103 | 102 | *q = '\0'; |
| 104 | 103 | WriteOneLineToSyslog(p); |
| 105 | 104 | p = q + 1; |
| ... | ... | @@ -139,6 +138,59 @@ uptr ReservedAddressRange::InitAligned(uptr size, uptr align, |
| 139 | 138 | return start; |
| 140 | 139 | } |
| 141 | 140 | |
| 141 | #if !SANITIZER_FUCHSIA | |
| 142 | ||
| 143 | // Reserve memory range [beg, end]. | |
| 144 | // We need to use inclusive range because end+1 may not be representable. | |
| 145 | void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name, | |
| 146 | bool madvise_shadow) { | |
| 147 | CHECK_EQ((beg % GetMmapGranularity()), 0); | |
| 148 | CHECK_EQ(((end + 1) % GetMmapGranularity()), 0); | |
| 149 | uptr size = end - beg + 1; | |
| 150 | DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb. | |
| 151 | if (madvise_shadow ? !MmapFixedSuperNoReserve(beg, size, name) | |
| 152 | : !MmapFixedNoReserve(beg, size, name)) { | |
| 153 | Report( | |
| 154 | "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. " | |
| 155 | "Perhaps you're using ulimit -v\n", | |
| 156 | size); | |
| 157 | Abort(); | |
| 158 | } | |
| 159 | if (madvise_shadow && common_flags()->use_madv_dontdump) | |
| 160 | DontDumpShadowMemory(beg, size); | |
| 161 | } | |
| 162 | ||
| 163 | void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start, | |
| 164 | uptr zero_base_max_shadow_start) { | |
| 165 | if (!size) | |
| 166 | return; | |
| 167 | void *res = MmapFixedNoAccess(addr, size, "shadow gap"); | |
| 168 | if (addr == (uptr)res) | |
| 169 | return; | |
| 170 | // A few pages at the start of the address space can not be protected. | |
| 171 | // But we really want to protect as much as possible, to prevent this memory | |
| 172 | // being returned as a result of a non-FIXED mmap(). | |
| 173 | if (addr == zero_base_shadow_start) { | |
| 174 | uptr step = GetMmapGranularity(); | |
| 175 | while (size > step && addr < zero_base_max_shadow_start) { | |
| 176 | addr += step; | |
| 177 | size -= step; | |
| 178 | void *res = MmapFixedNoAccess(addr, size, "shadow gap"); | |
| 179 | if (addr == (uptr)res) | |
| 180 | return; | |
| 181 | } | |
| 182 | } | |
| 183 | ||
| 184 | Report( | |
| 185 | "ERROR: Failed to protect the shadow gap. " | |
| 186 | "%s cannot proceed correctly. ABORTING.\n", | |
| 187 | SanitizerToolName); | |
| 188 | DumpProcessMap(); | |
| 189 | Die(); | |
| 190 | } | |
| 191 | ||
| 192 | #endif // !SANITIZER_FUCHSIA | |
| 193 | ||
| 142 | 194 | } // namespace __sanitizer |
| 143 | 195 | |
| 144 | 196 | SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify, |
lib/tsan/sanitizer_common/sanitizer_common_nolibc.cpp+3-2| ... | ... | @@ -10,9 +10,10 @@ |
| 10 | 10 | // libc in no-libcdep sources. |
| 11 | 11 | //===----------------------------------------------------------------------===// |
| 12 | 12 | |
| 13 | #include "sanitizer_platform.h" | |
| 14 | 13 | #include "sanitizer_common.h" |
| 14 | #include "sanitizer_flags.h" | |
| 15 | 15 | #include "sanitizer_libc.h" |
| 16 | #include "sanitizer_platform.h" | |
| 16 | 17 | |
| 17 | 18 | namespace __sanitizer { |
| 18 | 19 | |
| ... | ... | @@ -24,11 +25,11 @@ void LogMessageOnPrintf(const char *str) {} |
| 24 | 25 | #endif |
| 25 | 26 | void WriteToSyslog(const char *buffer) {} |
| 26 | 27 | void Abort() { internal__exit(1); } |
| 27 | void SleepForSeconds(int seconds) { internal_sleep(seconds); } | |
| 28 | 28 | #endif // !SANITIZER_WINDOWS |
| 29 | 29 | |
| 30 | 30 | #if !SANITIZER_WINDOWS && !SANITIZER_MAC |
| 31 | 31 | void ListOfModules::init() {} |
| 32 | void InitializePlatformCommonFlags(CommonFlags *cf) {} | |
| 32 | 33 | #endif |
| 33 | 34 | |
| 34 | 35 | } // namespace __sanitizer |
lib/tsan/sanitizer_common/sanitizer_common_syscalls.inc+8-6| ... | ... | @@ -2294,9 +2294,10 @@ PRE_SYSCALL(ni_syscall)() {} |
| 2294 | 2294 | POST_SYSCALL(ni_syscall)(long res) {} |
| 2295 | 2295 | |
| 2296 | 2296 | PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { |
| 2297 | #if !SANITIZER_ANDROID && \ | |
| 2298 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 2299 | defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__)) | |
| 2297 | #if !SANITIZER_ANDROID && \ | |
| 2298 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 2299 | defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ | |
| 2300 | SANITIZER_RISCV64) | |
| 2300 | 2301 | if (data) { |
| 2301 | 2302 | if (request == ptrace_setregs) { |
| 2302 | 2303 | PRE_READ((void *)data, struct_user_regs_struct_sz); |
| ... | ... | @@ -2315,9 +2316,10 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { |
| 2315 | 2316 | } |
| 2316 | 2317 | |
| 2317 | 2318 | POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) { |
| 2318 | #if !SANITIZER_ANDROID && \ | |
| 2319 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 2320 | defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__)) | |
| 2319 | #if !SANITIZER_ANDROID && \ | |
| 2320 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 2321 | defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ | |
| 2322 | SANITIZER_RISCV64) | |
| 2321 | 2323 | if (res >= 0 && data) { |
| 2322 | 2324 | // Note that this is different from the interceptor in |
| 2323 | 2325 | // sanitizer_common_interceptors.inc. |
lib/tsan/sanitizer_common/sanitizer_deadlock_detector1.cpp+2-2| ... | ... | @@ -32,7 +32,7 @@ struct DDLogicalThread { |
| 32 | 32 | bool report_pending; |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | struct DD : public DDetector { | |
| 35 | struct DD final : public DDetector { | |
| 36 | 36 | SpinMutex mtx; |
| 37 | 37 | DeadlockDetector<DDBV> dd; |
| 38 | 38 | DDFlags flags; |
| ... | ... | @@ -136,7 +136,7 @@ void DD::ReportDeadlock(DDCallback *cb, DDMutex *m) { |
| 136 | 136 | DDMutex *m0 = (DDMutex*)dd.getData(from); |
| 137 | 137 | DDMutex *m1 = (DDMutex*)dd.getData(to); |
| 138 | 138 | |
| 139 | u32 stk_from = -1U, stk_to = -1U; | |
| 139 | u32 stk_from = 0, stk_to = 0; | |
| 140 | 140 | int unique_tid = 0; |
| 141 | 141 | dd.findEdge(from, to, &stk_from, &stk_to, &unique_tid); |
| 142 | 142 | // Printf("Edge: %zd=>%zd: %u/%u T%d\n", from, to, stk_from, stk_to, |
lib/tsan/sanitizer_common/sanitizer_deadlock_detector2.cpp+16-18| ... | ... | @@ -73,14 +73,14 @@ struct DDLogicalThread { |
| 73 | 73 | int nlocked; |
| 74 | 74 | }; |
| 75 | 75 | |
| 76 | struct Mutex { | |
| 76 | struct MutexState { | |
| 77 | 77 | StaticSpinMutex mtx; |
| 78 | 78 | u32 seq; |
| 79 | 79 | int nlink; |
| 80 | 80 | Link link[kMaxLink]; |
| 81 | 81 | }; |
| 82 | 82 | |
| 83 | struct DD : public DDetector { | |
| 83 | struct DD final : public DDetector { | |
| 84 | 84 | explicit DD(const DDFlags *flags); |
| 85 | 85 | |
| 86 | 86 | DDPhysicalThread* CreatePhysicalThread(); |
| ... | ... | @@ -101,12 +101,12 @@ struct DD : public DDetector { |
| 101 | 101 | void CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, DDMutex *mtx); |
| 102 | 102 | void Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath); |
| 103 | 103 | u32 allocateId(DDCallback *cb); |
| 104 | Mutex *getMutex(u32 id); | |
| 105 | u32 getMutexId(Mutex *m); | |
| 104 | MutexState *getMutex(u32 id); | |
| 105 | u32 getMutexId(MutexState *m); | |
| 106 | 106 | |
| 107 | 107 | DDFlags flags; |
| 108 | 108 | |
| 109 | Mutex* mutex[kL1Size]; | |
| 109 | MutexState *mutex[kL1Size]; | |
| 110 | 110 | |
| 111 | 111 | SpinMutex mtx; |
| 112 | 112 | InternalMmapVector<u32> free_id; |
| ... | ... | @@ -152,13 +152,11 @@ void DD::MutexInit(DDCallback *cb, DDMutex *m) { |
| 152 | 152 | atomic_store(&m->owner, 0, memory_order_relaxed); |
| 153 | 153 | } |
| 154 | 154 | |
| 155 | Mutex *DD::getMutex(u32 id) { | |
| 156 | return &mutex[id / kL2Size][id % kL2Size]; | |
| 157 | } | |
| 155 | MutexState *DD::getMutex(u32 id) { return &mutex[id / kL2Size][id % kL2Size]; } | |
| 158 | 156 | |
| 159 | u32 DD::getMutexId(Mutex *m) { | |
| 157 | u32 DD::getMutexId(MutexState *m) { | |
| 160 | 158 | for (int i = 0; i < kL1Size; i++) { |
| 161 | Mutex *tab = mutex[i]; | |
| 159 | MutexState *tab = mutex[i]; | |
| 162 | 160 | if (tab == 0) |
| 163 | 161 | break; |
| 164 | 162 | if (m >= tab && m < tab + kL2Size) |
| ... | ... | @@ -176,8 +174,8 @@ u32 DD::allocateId(DDCallback *cb) { |
| 176 | 174 | } else { |
| 177 | 175 | CHECK_LT(id_gen, kMaxMutex); |
| 178 | 176 | if ((id_gen % kL2Size) == 0) { |
| 179 | mutex[id_gen / kL2Size] = (Mutex*)MmapOrDie(kL2Size * sizeof(Mutex), | |
| 180 | "deadlock detector (mutex table)"); | |
| 177 | mutex[id_gen / kL2Size] = (MutexState *)MmapOrDie( | |
| 178 | kL2Size * sizeof(MutexState), "deadlock detector (mutex table)"); | |
| 181 | 179 | } |
| 182 | 180 | id = id_gen++; |
| 183 | 181 | } |
| ... | ... | @@ -216,11 +214,11 @@ void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) { |
| 216 | 214 | } |
| 217 | 215 | |
| 218 | 216 | bool added = false; |
| 219 | Mutex *mtx = getMutex(m->id); | |
| 217 | MutexState *mtx = getMutex(m->id); | |
| 220 | 218 | for (int i = 0; i < lt->nlocked - 1; i++) { |
| 221 | 219 | u32 id1 = lt->locked[i].id; |
| 222 | 220 | u32 stk1 = lt->locked[i].stk; |
| 223 | Mutex *mtx1 = getMutex(id1); | |
| 221 | MutexState *mtx1 = getMutex(id1); | |
| 224 | 222 | SpinMutexLock l(&mtx1->mtx); |
| 225 | 223 | if (mtx1->nlink == kMaxLink) { |
| 226 | 224 | // FIXME(dvyukov): check stale links |
| ... | ... | @@ -342,7 +340,7 @@ void DD::MutexDestroy(DDCallback *cb, DDMutex *m) { |
| 342 | 340 | |
| 343 | 341 | // Clear and invalidate the mutex descriptor. |
| 344 | 342 | { |
| 345 | Mutex *mtx = getMutex(m->id); | |
| 343 | MutexState *mtx = getMutex(m->id); | |
| 346 | 344 | SpinMutexLock l(&mtx->mtx); |
| 347 | 345 | mtx->seq++; |
| 348 | 346 | mtx->nlink = 0; |
| ... | ... | @@ -361,7 +359,7 @@ void DD::CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, |
| 361 | 359 | int npath = 0; |
| 362 | 360 | int npending = 0; |
| 363 | 361 | { |
| 364 | Mutex *mtx = getMutex(m->id); | |
| 362 | MutexState *mtx = getMutex(m->id); | |
| 365 | 363 | SpinMutexLock l(&mtx->mtx); |
| 366 | 364 | for (int li = 0; li < mtx->nlink; li++) |
| 367 | 365 | pt->pending[npending++] = mtx->link[li]; |
| ... | ... | @@ -374,7 +372,7 @@ void DD::CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, |
| 374 | 372 | } |
| 375 | 373 | if (pt->visited[link.id]) |
| 376 | 374 | continue; |
| 377 | Mutex *mtx1 = getMutex(link.id); | |
| 375 | MutexState *mtx1 = getMutex(link.id); | |
| 378 | 376 | SpinMutexLock l(&mtx1->mtx); |
| 379 | 377 | if (mtx1->seq != link.seq) |
| 380 | 378 | continue; |
| ... | ... | @@ -387,7 +385,7 @@ void DD::CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, |
| 387 | 385 | return Report(pt, lt, npath); // Bingo! |
| 388 | 386 | for (int li = 0; li < mtx1->nlink; li++) { |
| 389 | 387 | Link *link1 = &mtx1->link[li]; |
| 390 | // Mutex *mtx2 = getMutex(link->id); | |
| 388 | // MutexState *mtx2 = getMutex(link->id); | |
| 391 | 389 | // FIXME(dvyukov): fast seq check |
| 392 | 390 | // FIXME(dvyukov): fast nlink != 0 check |
| 393 | 391 | // FIXME(dvyukov): fast pending check? |
lib/tsan/sanitizer_common/sanitizer_deadlock_detector_interface.h+6| ... | ... | @@ -66,6 +66,9 @@ struct DDCallback { |
| 66 | 66 | |
| 67 | 67 | virtual u32 Unwind() { return 0; } |
| 68 | 68 | virtual int UniqueTid() { return 0; } |
| 69 | ||
| 70 | protected: | |
| 71 | ~DDCallback() {} | |
| 69 | 72 | }; |
| 70 | 73 | |
| 71 | 74 | struct DDetector { |
| ... | ... | @@ -85,6 +88,9 @@ struct DDetector { |
| 85 | 88 | virtual void MutexDestroy(DDCallback *cb, DDMutex *m) {} |
| 86 | 89 | |
| 87 | 90 | virtual DDReport *GetReport(DDCallback *cb) { return nullptr; } |
| 91 | ||
| 92 | protected: | |
| 93 | ~DDetector() {} | |
| 88 | 94 | }; |
| 89 | 95 | |
| 90 | 96 | } // namespace __sanitizer |
lib/tsan/sanitizer_common/sanitizer_errno.h+1-2| ... | ... | @@ -23,8 +23,7 @@ |
| 23 | 23 | |
| 24 | 24 | #if SANITIZER_FREEBSD || SANITIZER_MAC |
| 25 | 25 | # define __errno_location __error |
| 26 | #elif SANITIZER_ANDROID || SANITIZER_NETBSD || SANITIZER_OPENBSD || \ | |
| 27 | SANITIZER_RTEMS | |
| 26 | #elif SANITIZER_ANDROID || SANITIZER_NETBSD | |
| 28 | 27 | # define __errno_location __errno |
| 29 | 28 | #elif SANITIZER_SOLARIS |
| 30 | 29 | # define __errno_location ___errno |
lib/tsan/sanitizer_common/sanitizer_errno_codes.h+1| ... | ... | @@ -24,6 +24,7 @@ namespace __sanitizer { |
| 24 | 24 | #define errno_ENOMEM 12 |
| 25 | 25 | #define errno_EBUSY 16 |
| 26 | 26 | #define errno_EINVAL 22 |
| 27 | #define errno_ENAMETOOLONG 36 | |
| 27 | 28 | |
| 28 | 29 | // Those might not present or their value differ on different platforms. |
| 29 | 30 | extern const int errno_EOWNERDEAD; |
lib/tsan/sanitizer_common/sanitizer_file.cpp+28-12| ... | ... | @@ -58,40 +58,52 @@ void ReportFile::ReopenIfNecessary() { |
| 58 | 58 | } else { |
| 59 | 59 | internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid); |
| 60 | 60 | } |
| 61 | fd = OpenFile(full_path, WrOnly); | |
| 61 | if (common_flags()->log_suffix) { | |
| 62 | internal_strlcat(full_path, common_flags()->log_suffix, kMaxPathLength); | |
| 63 | } | |
| 64 | error_t err; | |
| 65 | fd = OpenFile(full_path, WrOnly, &err); | |
| 62 | 66 | if (fd == kInvalidFd) { |
| 63 | 67 | const char *ErrorMsgPrefix = "ERROR: Can't open file: "; |
| 64 | 68 | WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix)); |
| 65 | 69 | WriteToFile(kStderrFd, full_path, internal_strlen(full_path)); |
| 70 | char errmsg[100]; | |
| 71 | internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)", err); | |
| 72 | WriteToFile(kStderrFd, errmsg, internal_strlen(errmsg)); | |
| 66 | 73 | Die(); |
| 67 | 74 | } |
| 68 | 75 | fd_pid = pid; |
| 69 | 76 | } |
| 70 | 77 | |
| 71 | 78 | void ReportFile::SetReportPath(const char *path) { |
| 72 | if (!path) | |
| 73 | return; | |
| 74 | uptr len = internal_strlen(path); | |
| 75 | if (len > sizeof(path_prefix) - 100) { | |
| 76 | Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", | |
| 77 | path[0], path[1], path[2], path[3], | |
| 78 | path[4], path[5], path[6], path[7]); | |
| 79 | Die(); | |
| 79 | if (path) { | |
| 80 | uptr len = internal_strlen(path); | |
| 81 | if (len > sizeof(path_prefix) - 100) { | |
| 82 | Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", path[0], path[1], | |
| 83 | path[2], path[3], path[4], path[5], path[6], path[7]); | |
| 84 | Die(); | |
| 85 | } | |
| 80 | 86 | } |
| 81 | 87 | |
| 82 | 88 | SpinMutexLock l(mu); |
| 83 | 89 | if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd) |
| 84 | 90 | CloseFile(fd); |
| 85 | 91 | fd = kInvalidFd; |
| 86 | if (internal_strcmp(path, "stdout") == 0) { | |
| 87 | fd = kStdoutFd; | |
| 88 | } else if (internal_strcmp(path, "stderr") == 0) { | |
| 92 | if (!path || internal_strcmp(path, "stderr") == 0) { | |
| 89 | 93 | fd = kStderrFd; |
| 94 | } else if (internal_strcmp(path, "stdout") == 0) { | |
| 95 | fd = kStdoutFd; | |
| 90 | 96 | } else { |
| 91 | 97 | internal_snprintf(path_prefix, kMaxPathLength, "%s", path); |
| 92 | 98 | } |
| 93 | 99 | } |
| 94 | 100 | |
| 101 | const char *ReportFile::GetReportPath() { | |
| 102 | SpinMutexLock l(mu); | |
| 103 | ReopenIfNecessary(); | |
| 104 | return full_path; | |
| 105 | } | |
| 106 | ||
| 95 | 107 | bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, |
| 96 | 108 | uptr *read_len, uptr max_len, error_t *errno_p) { |
| 97 | 109 | *buff = nullptr; |
| ... | ... | @@ -210,6 +222,10 @@ void __sanitizer_set_report_fd(void *fd) { |
| 210 | 222 | report_file.fd = (fd_t)reinterpret_cast<uptr>(fd); |
| 211 | 223 | report_file.fd_pid = internal_getpid(); |
| 212 | 224 | } |
| 225 | ||
| 226 | const char *__sanitizer_get_report_path() { | |
| 227 | return report_file.GetReportPath(); | |
| 228 | } | |
| 213 | 229 | } // extern "C" |
| 214 | 230 | |
| 215 | 231 | #endif // !SANITIZER_FUCHSIA |
lib/tsan/sanitizer_common/sanitizer_file.h+1| ... | ... | @@ -26,6 +26,7 @@ struct ReportFile { |
| 26 | 26 | void Write(const char *buffer, uptr length); |
| 27 | 27 | bool SupportsColors(); |
| 28 | 28 | void SetReportPath(const char *path); |
| 29 | const char *GetReportPath(); | |
| 29 | 30 | |
| 30 | 31 | // Don't use fields directly. They are only declared public to allow |
| 31 | 32 | // aggregate initialization. |
lib/tsan/sanitizer_common/sanitizer_flag_parser.h+1-1| ... | ... | @@ -42,7 +42,7 @@ class FlagHandlerBase { |
| 42 | 42 | }; |
| 43 | 43 | |
| 44 | 44 | template <typename T> |
| 45 | class FlagHandler : public FlagHandlerBase { | |
| 45 | class FlagHandler final : public FlagHandlerBase { | |
| 46 | 46 | T *t_; |
| 47 | 47 | |
| 48 | 48 | public: |
lib/tsan/sanitizer_common/sanitizer_flags.cpp+13-3| ... | ... | @@ -13,9 +13,10 @@ |
| 13 | 13 | #include "sanitizer_flags.h" |
| 14 | 14 | |
| 15 | 15 | #include "sanitizer_common.h" |
| 16 | #include "sanitizer_flag_parser.h" | |
| 16 | 17 | #include "sanitizer_libc.h" |
| 18 | #include "sanitizer_linux.h" | |
| 17 | 19 | #include "sanitizer_list.h" |
| 18 | #include "sanitizer_flag_parser.h" | |
| 19 | 20 | |
| 20 | 21 | namespace __sanitizer { |
| 21 | 22 | |
| ... | ... | @@ -34,6 +35,7 @@ void CommonFlags::CopyFrom(const CommonFlags &other) { |
| 34 | 35 | // Copy the string from "s" to "out", making the following substitutions: |
| 35 | 36 | // %b = binary basename |
| 36 | 37 | // %p = pid |
| 38 | // %d = binary directory | |
| 37 | 39 | void SubstituteForFlagValue(const char *s, char *out, uptr out_size) { |
| 38 | 40 | char *out_end = out + out_size; |
| 39 | 41 | while (*s && out < out_end - 1) { |
| ... | ... | @@ -63,6 +65,12 @@ void SubstituteForFlagValue(const char *s, char *out, uptr out_size) { |
| 63 | 65 | s += 2; // skip "%p" |
| 64 | 66 | break; |
| 65 | 67 | } |
| 68 | case 'd': { | |
| 69 | uptr len = ReadBinaryDir(out, out_end - out); | |
| 70 | out += len; | |
| 71 | s += 2; // skip "%d" | |
| 72 | break; | |
| 73 | } | |
| 66 | 74 | default: |
| 67 | 75 | *out++ = *s++; |
| 68 | 76 | break; |
| ... | ... | @@ -72,7 +80,7 @@ void SubstituteForFlagValue(const char *s, char *out, uptr out_size) { |
| 72 | 80 | *out = '\0'; |
| 73 | 81 | } |
| 74 | 82 | |
| 75 | class FlagHandlerInclude : public FlagHandlerBase { | |
| 83 | class FlagHandlerInclude final : public FlagHandlerBase { | |
| 76 | 84 | FlagParser *parser_; |
| 77 | 85 | bool ignore_missing_; |
| 78 | 86 | const char *original_path_; |
| ... | ... | @@ -91,7 +99,7 @@ class FlagHandlerInclude : public FlagHandlerBase { |
| 91 | 99 | } |
| 92 | 100 | return parser_->ParseFile(value, ignore_missing_); |
| 93 | 101 | } |
| 94 | bool Format(char *buffer, uptr size) { | |
| 102 | bool Format(char *buffer, uptr size) override { | |
| 95 | 103 | // Note `original_path_` isn't actually what's parsed due to `%` |
| 96 | 104 | // substitutions. Printing the substituted path would require holding onto |
| 97 | 105 | // mmap'ed memory. |
| ... | ... | @@ -124,6 +132,8 @@ void InitializeCommonFlags(CommonFlags *cf) { |
| 124 | 132 | // need to record coverage to generate coverage report. |
| 125 | 133 | cf->coverage |= cf->html_cov_report; |
| 126 | 134 | SetVerbosity(cf->verbosity); |
| 135 | ||
| 136 | InitializePlatformCommonFlags(cf); | |
| 127 | 137 | } |
| 128 | 138 | |
| 129 | 139 | } // namespace __sanitizer |
lib/tsan/sanitizer_common/sanitizer_flags.h+4| ... | ... | @@ -62,6 +62,10 @@ void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf); |
| 62 | 62 | // and perform initializations common to all sanitizers (e.g. setting |
| 63 | 63 | // verbosity). |
| 64 | 64 | void InitializeCommonFlags(CommonFlags *cf = &common_flags_dont_use); |
| 65 | ||
| 66 | // Platform specific flags initialization. | |
| 67 | void InitializePlatformCommonFlags(CommonFlags *cf); | |
| 68 | ||
| 65 | 69 | } // namespace __sanitizer |
| 66 | 70 | |
| 67 | 71 | #endif // SANITIZER_FLAGS_H |
lib/tsan/sanitizer_common/sanitizer_flags.inc+16-5| ... | ... | @@ -40,20 +40,27 @@ COMMON_FLAG(bool, fast_unwind_on_check, false, |
| 40 | 40 | COMMON_FLAG(bool, fast_unwind_on_fatal, false, |
| 41 | 41 | "If available, use the fast frame-pointer-based unwinder on fatal " |
| 42 | 42 | "errors.") |
| 43 | COMMON_FLAG(bool, fast_unwind_on_malloc, true, | |
| 43 | // ARM thumb/thumb2 frame pointer is inconsistent on GCC and Clang [1] | |
| 44 | // and fast-unwider is also unreliable with mixing arm and thumb code [2]. | |
| 45 | // [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92172 | |
| 46 | // [2] https://bugs.llvm.org/show_bug.cgi?id=44158 | |
| 47 | COMMON_FLAG(bool, fast_unwind_on_malloc, | |
| 48 | !(SANITIZER_LINUX && !SANITIZER_ANDROID && SANITIZER_ARM), | |
| 44 | 49 | "If available, use the fast frame-pointer-based unwinder on " |
| 45 | 50 | "malloc/free.") |
| 46 | 51 | COMMON_FLAG(bool, handle_ioctl, false, "Intercept and handle ioctl requests.") |
| 47 | 52 | COMMON_FLAG(int, malloc_context_size, 1, |
| 48 | 53 | "Max number of stack frames kept for each allocation/deallocation.") |
| 49 | 54 | COMMON_FLAG( |
| 50 | const char *, log_path, "stderr", | |
| 55 | const char *, log_path, nullptr, | |
| 51 | 56 | "Write logs to \"log_path.pid\". The special values are \"stdout\" and " |
| 52 | "\"stderr\". The default is \"stderr\".") | |
| 57 | "\"stderr\". If unspecified, defaults to \"stderr\".") | |
| 53 | 58 | COMMON_FLAG( |
| 54 | 59 | bool, log_exe_name, false, |
| 55 | 60 | "Mention name of executable when reporting error and " |
| 56 | 61 | "append executable name to logs (as in \"log_path.exe_name.pid\").") |
| 62 | COMMON_FLAG(const char *, log_suffix, nullptr, | |
| 63 | "String to append to log file name, e.g. \".txt\".") | |
| 57 | 64 | COMMON_FLAG( |
| 58 | 65 | bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC, |
| 59 | 66 | "Write all sanitizer output to syslog in addition to other means of " |
| ... | ... | @@ -77,8 +84,9 @@ COMMON_FLAG(bool, print_summary, true, |
| 77 | 84 | "If false, disable printing error summaries in addition to error " |
| 78 | 85 | "reports.") |
| 79 | 86 | COMMON_FLAG(int, print_module_map, 0, |
| 80 | "OS X only (0 - don't print, 1 - print only once before process " | |
| 81 | "exits, 2 - print after each report).") | |
| 87 | "Print the process module map where supported (0 - don't print, " | |
| 88 | "1 - print only once before process exits, 2 - print after each " | |
| 89 | "report).") | |
| 82 | 90 | COMMON_FLAG(bool, check_printf, true, "Check printf arguments.") |
| 83 | 91 | #define COMMON_FLAG_HANDLE_SIGNAL_HELP(signal) \ |
| 84 | 92 | "Controls custom tool's " #signal " handler (0 - do not registers the " \ |
| ... | ... | @@ -195,6 +203,9 @@ COMMON_FLAG(bool, intercept_strtok, true, |
| 195 | 203 | COMMON_FLAG(bool, intercept_strpbrk, true, |
| 196 | 204 | "If set, uses custom wrappers for strpbrk function " |
| 197 | 205 | "to find more errors.") |
| 206 | COMMON_FLAG( | |
| 207 | bool, intercept_strcmp, true, | |
| 208 | "If set, uses custom wrappers for strcmp functions to find more errors.") | |
| 198 | 209 | COMMON_FLAG(bool, intercept_strlen, true, |
| 199 | 210 | "If set, uses custom wrappers for strlen and strnlen functions " |
| 200 | 211 | "to find more errors.") |
lib/tsan/sanitizer_common/sanitizer_fuchsia.cpp+70-52| ... | ... | @@ -14,17 +14,17 @@ |
| 14 | 14 | #include "sanitizer_fuchsia.h" |
| 15 | 15 | #if SANITIZER_FUCHSIA |
| 16 | 16 | |
| 17 | #include "sanitizer_common.h" | |
| 18 | #include "sanitizer_libc.h" | |
| 19 | #include "sanitizer_mutex.h" | |
| 20 | ||
| 21 | #include <limits.h> | |
| 22 | 17 | #include <pthread.h> |
| 23 | 18 | #include <stdlib.h> |
| 24 | 19 | #include <unistd.h> |
| 25 | 20 | #include <zircon/errors.h> |
| 26 | 21 | #include <zircon/process.h> |
| 27 | 22 | #include <zircon/syscalls.h> |
| 23 | #include <zircon/utc.h> | |
| 24 | ||
| 25 | #include "sanitizer_common.h" | |
| 26 | #include "sanitizer_libc.h" | |
| 27 | #include "sanitizer_mutex.h" | |
| 28 | 28 | |
| 29 | 29 | namespace __sanitizer { |
| 30 | 30 | |
| ... | ... | @@ -36,19 +36,16 @@ uptr internal_sched_yield() { |
| 36 | 36 | return 0; // Why doesn't this return void? |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | static void internal_nanosleep(zx_time_t ns) { | |
| 40 | zx_status_t status = _zx_nanosleep(_zx_deadline_after(ns)); | |
| 39 | void internal_usleep(u64 useconds) { | |
| 40 | zx_status_t status = _zx_nanosleep(_zx_deadline_after(ZX_USEC(useconds))); | |
| 41 | 41 | CHECK_EQ(status, ZX_OK); |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | unsigned int internal_sleep(unsigned int seconds) { | |
| 45 | internal_nanosleep(ZX_SEC(seconds)); | |
| 46 | return 0; | |
| 47 | } | |
| 48 | ||
| 49 | 44 | u64 NanoTime() { |
| 45 | zx_handle_t utc_clock = _zx_utc_reference_get(); | |
| 46 | CHECK_NE(utc_clock, ZX_HANDLE_INVALID); | |
| 50 | 47 | zx_time_t time; |
| 51 | zx_status_t status = _zx_clock_get(ZX_CLOCK_UTC, &time); | |
| 48 | zx_status_t status = _zx_clock_read(utc_clock, &time); | |
| 52 | 49 | CHECK_EQ(status, ZX_OK); |
| 53 | 50 | return time; |
| 54 | 51 | } |
| ... | ... | @@ -66,9 +63,7 @@ uptr internal_getpid() { |
| 66 | 63 | return pid; |
| 67 | 64 | } |
| 68 | 65 | |
| 69 | int internal_dlinfo(void *handle, int request, void *p) { | |
| 70 | UNIMPLEMENTED(); | |
| 71 | } | |
| 66 | int internal_dlinfo(void *handle, int request, void *p) { UNIMPLEMENTED(); } | |
| 72 | 67 | |
| 73 | 68 | uptr GetThreadSelf() { return reinterpret_cast<uptr>(thrd_current()); } |
| 74 | 69 | |
| ... | ... | @@ -78,10 +73,6 @@ void Abort() { abort(); } |
| 78 | 73 | |
| 79 | 74 | int Atexit(void (*function)(void)) { return atexit(function); } |
| 80 | 75 | |
| 81 | void SleepForSeconds(int seconds) { internal_sleep(seconds); } | |
| 82 | ||
| 83 | void SleepForMillis(int millis) { internal_nanosleep(ZX_MSEC(millis)); } | |
| 84 | ||
| 85 | 76 | void GetThreadStackTopAndBottom(bool, uptr *stack_top, uptr *stack_bottom) { |
| 86 | 77 | pthread_attr_t attr; |
| 87 | 78 | CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); |
| ... | ... | @@ -105,12 +96,22 @@ void SetAlternateSignalStack() {} |
| 105 | 96 | void UnsetAlternateSignalStack() {} |
| 106 | 97 | void InitTlsSize() {} |
| 107 | 98 | |
| 108 | void PrintModuleMap() {} | |
| 109 | ||
| 110 | 99 | bool SignalContext::IsStackOverflow() const { return false; } |
| 111 | 100 | void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); } |
| 112 | 101 | const char *SignalContext::Describe() const { UNIMPLEMENTED(); } |
| 113 | 102 | |
| 103 | void FutexWait(atomic_uint32_t *p, u32 cmp) { | |
| 104 | zx_status_t status = _zx_futex_wait(reinterpret_cast<zx_futex_t *>(p), cmp, | |
| 105 | ZX_HANDLE_INVALID, ZX_TIME_INFINITE); | |
| 106 | if (status != ZX_ERR_BAD_STATE) // Normal race. | |
| 107 | CHECK_EQ(status, ZX_OK); | |
| 108 | } | |
| 109 | ||
| 110 | void FutexWake(atomic_uint32_t *p, u32 count) { | |
| 111 | zx_status_t status = _zx_futex_wake(reinterpret_cast<zx_futex_t *>(p), count); | |
| 112 | CHECK_EQ(status, ZX_OK); | |
| 113 | } | |
| 114 | ||
| 114 | 115 | enum MutexState : int { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; |
| 115 | 116 | |
| 116 | 117 | BlockingMutex::BlockingMutex() { |
| ... | ... | @@ -147,19 +148,21 @@ void BlockingMutex::Unlock() { |
| 147 | 148 | } |
| 148 | 149 | } |
| 149 | 150 | |
| 150 | void BlockingMutex::CheckLocked() { | |
| 151 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |
| 151 | void BlockingMutex::CheckLocked() const { | |
| 152 | auto m = reinterpret_cast<atomic_uint32_t const *>(&opaque_storage_); | |
| 152 | 153 | CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); |
| 153 | 154 | } |
| 154 | 155 | |
| 155 | uptr GetPageSize() { return PAGE_SIZE; } | |
| 156 | uptr GetPageSize() { return _zx_system_get_page_size(); } | |
| 156 | 157 | |
| 157 | uptr GetMmapGranularity() { return PAGE_SIZE; } | |
| 158 | uptr GetMmapGranularity() { return _zx_system_get_page_size(); } | |
| 158 | 159 | |
| 159 | 160 | sanitizer_shadow_bounds_t ShadowBounds; |
| 160 | 161 | |
| 162 | void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); } | |
| 163 | ||
| 161 | 164 | uptr GetMaxUserVirtualAddress() { |
| 162 | ShadowBounds = __sanitizer_shadow_bounds(); | |
| 165 | InitShadowBounds(); | |
| 163 | 166 | return ShadowBounds.memory_limit - 1; |
| 164 | 167 | } |
| 165 | 168 | |
| ... | ... | @@ -167,7 +170,7 @@ uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); } |
| 167 | 170 | |
| 168 | 171 | static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type, |
| 169 | 172 | bool raw_report, bool die_for_nomem) { |
| 170 | size = RoundUpTo(size, PAGE_SIZE); | |
| 173 | size = RoundUpTo(size, GetPageSize()); | |
| 171 | 174 | |
| 172 | 175 | zx_handle_t vmo; |
| 173 | 176 | zx_status_t status = _zx_vmo_create(size, 0, &vmo); |
| ... | ... | @@ -213,15 +216,14 @@ void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { |
| 213 | 216 | |
| 214 | 217 | uptr ReservedAddressRange::Init(uptr init_size, const char *name, |
| 215 | 218 | uptr fixed_addr) { |
| 216 | init_size = RoundUpTo(init_size, PAGE_SIZE); | |
| 219 | init_size = RoundUpTo(init_size, GetPageSize()); | |
| 217 | 220 | DCHECK_EQ(os_handle_, ZX_HANDLE_INVALID); |
| 218 | 221 | uintptr_t base; |
| 219 | 222 | zx_handle_t vmar; |
| 220 | zx_status_t status = | |
| 221 | _zx_vmar_allocate( | |
| 222 | _zx_vmar_root_self(), | |
| 223 | ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, | |
| 224 | 0, init_size, &vmar, &base); | |
| 223 | zx_status_t status = _zx_vmar_allocate( | |
| 224 | _zx_vmar_root_self(), | |
| 225 | ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, 0, | |
| 226 | init_size, &vmar, &base); | |
| 225 | 227 | if (status != ZX_OK) |
| 226 | 228 | ReportMmapFailureAndDie(init_size, name, "zx_vmar_allocate", status); |
| 227 | 229 | base_ = reinterpret_cast<void *>(base); |
| ... | ... | @@ -235,7 +237,7 @@ uptr ReservedAddressRange::Init(uptr init_size, const char *name, |
| 235 | 237 | static uptr DoMmapFixedOrDie(zx_handle_t vmar, uptr fixed_addr, uptr map_size, |
| 236 | 238 | void *base, const char *name, bool die_for_nomem) { |
| 237 | 239 | uptr offset = fixed_addr - reinterpret_cast<uptr>(base); |
| 238 | map_size = RoundUpTo(map_size, PAGE_SIZE); | |
| 240 | map_size = RoundUpTo(map_size, GetPageSize()); | |
| 239 | 241 | zx_handle_t vmo; |
| 240 | 242 | zx_status_t status = _zx_vmo_create(map_size, 0, &vmo); |
| 241 | 243 | if (status != ZX_OK) { |
| ... | ... | @@ -263,19 +265,19 @@ static uptr DoMmapFixedOrDie(zx_handle_t vmar, uptr fixed_addr, uptr map_size, |
| 263 | 265 | |
| 264 | 266 | uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size, |
| 265 | 267 | const char *name) { |
| 266 | return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, | |
| 267 | name_, false); | |
| 268 | return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, name_, | |
| 269 | false); | |
| 268 | 270 | } |
| 269 | 271 | |
| 270 | 272 | uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size, |
| 271 | 273 | const char *name) { |
| 272 | return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, | |
| 273 | name_, true); | |
| 274 | return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, name_, true); | |
| 274 | 275 | } |
| 275 | 276 | |
| 276 | 277 | void UnmapOrDieVmar(void *addr, uptr size, zx_handle_t target_vmar) { |
| 277 | if (!addr || !size) return; | |
| 278 | size = RoundUpTo(size, PAGE_SIZE); | |
| 278 | if (!addr || !size) | |
| 279 | return; | |
| 280 | size = RoundUpTo(size, GetPageSize()); | |
| 279 | 281 | |
| 280 | 282 | zx_status_t status = |
| 281 | 283 | _zx_vmar_unmap(target_vmar, reinterpret_cast<uintptr_t>(addr), size); |
| ... | ... | @@ -315,7 +317,7 @@ void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) { |
| 315 | 317 | |
| 316 | 318 | void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, |
| 317 | 319 | const char *mem_type) { |
| 318 | CHECK_GE(size, PAGE_SIZE); | |
| 320 | CHECK_GE(size, GetPageSize()); | |
| 319 | 321 | CHECK(IsPowerOfTwo(size)); |
| 320 | 322 | CHECK(IsPowerOfTwo(alignment)); |
| 321 | 323 | |
| ... | ... | @@ -355,7 +357,8 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, |
| 355 | 357 | _zx_vmar_root_self(), |
| 356 | 358 | ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC_OVERWRITE, |
| 357 | 359 | addr - info.base, vmo, 0, size, &new_addr); |
| 358 | if (status == ZX_OK) CHECK_EQ(new_addr, addr); | |
| 360 | if (status == ZX_OK) | |
| 361 | CHECK_EQ(new_addr, addr); | |
| 359 | 362 | } |
| 360 | 363 | } |
| 361 | 364 | if (status == ZX_OK && addr != map_addr) |
| ... | ... | @@ -380,9 +383,18 @@ void UnmapOrDie(void *addr, uptr size) { |
| 380 | 383 | UnmapOrDieVmar(addr, size, _zx_vmar_root_self()); |
| 381 | 384 | } |
| 382 | 385 | |
| 383 | // This is used on the shadow mapping, which cannot be changed. | |
| 384 | // Zircon doesn't have anything like MADV_DONTNEED. | |
| 385 | void ReleaseMemoryPagesToOS(uptr beg, uptr end) {} | |
| 386 | void ReleaseMemoryPagesToOS(uptr beg, uptr end) { | |
| 387 | uptr beg_aligned = RoundUpTo(beg, GetPageSize()); | |
| 388 | uptr end_aligned = RoundDownTo(end, GetPageSize()); | |
| 389 | if (beg_aligned < end_aligned) { | |
| 390 | zx_handle_t root_vmar = _zx_vmar_root_self(); | |
| 391 | CHECK_NE(root_vmar, ZX_HANDLE_INVALID); | |
| 392 | zx_status_t status = | |
| 393 | _zx_vmar_op_range(root_vmar, ZX_VMAR_OP_DECOMMIT, beg_aligned, | |
| 394 | end_aligned - beg_aligned, nullptr, 0); | |
| 395 | CHECK_EQ(status, ZX_OK); | |
| 396 | } | |
| 397 | } | |
| 386 | 398 | |
| 387 | 399 | void DumpProcessMap() { |
| 388 | 400 | // TODO(mcgrathr): write it |
| ... | ... | @@ -411,8 +423,9 @@ bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, |
| 411 | 423 | uint64_t vmo_size; |
| 412 | 424 | status = _zx_vmo_get_size(vmo, &vmo_size); |
| 413 | 425 | if (status == ZX_OK) { |
| 414 | if (vmo_size < max_len) max_len = vmo_size; | |
| 415 | size_t map_size = RoundUpTo(max_len, PAGE_SIZE); | |
| 426 | if (vmo_size < max_len) | |
| 427 | max_len = vmo_size; | |
| 428 | size_t map_size = RoundUpTo(max_len, GetPageSize()); | |
| 416 | 429 | uintptr_t addr; |
| 417 | 430 | status = _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ, 0, vmo, 0, |
| 418 | 431 | map_size, &addr); |
| ... | ... | @@ -424,7 +437,8 @@ bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, |
| 424 | 437 | } |
| 425 | 438 | _zx_handle_close(vmo); |
| 426 | 439 | } |
| 427 | if (status != ZX_OK && errno_p) *errno_p = status; | |
| 440 | if (status != ZX_OK && errno_p) | |
| 441 | *errno_p = status; | |
| 428 | 442 | return status == ZX_OK; |
| 429 | 443 | } |
| 430 | 444 | |
| ... | ... | @@ -498,12 +512,12 @@ bool GetRandom(void *buffer, uptr length, bool blocking) { |
| 498 | 512 | return true; |
| 499 | 513 | } |
| 500 | 514 | |
| 501 | u32 GetNumberOfCPUs() { | |
| 502 | return zx_system_get_num_cpus(); | |
| 503 | } | |
| 515 | u32 GetNumberOfCPUs() { return zx_system_get_num_cpus(); } | |
| 504 | 516 | |
| 505 | 517 | uptr GetRSS() { UNIMPLEMENTED(); } |
| 506 | 518 | |
| 519 | void InitializePlatformCommonFlags(CommonFlags *cf) {} | |
| 520 | ||
| 507 | 521 | } // namespace __sanitizer |
| 508 | 522 | |
| 509 | 523 | using namespace __sanitizer; |
| ... | ... | @@ -526,6 +540,10 @@ void __sanitizer_set_report_path(const char *path) { |
| 526 | 540 | void __sanitizer_set_report_fd(void *fd) { |
| 527 | 541 | UNREACHABLE("not available on Fuchsia"); |
| 528 | 542 | } |
| 543 | ||
| 544 | const char *__sanitizer_get_report_path() { | |
| 545 | UNREACHABLE("not available on Fuchsia"); | |
| 546 | } | |
| 529 | 547 | } // extern "C" |
| 530 | 548 | |
| 531 | 549 | #endif // SANITIZER_FUCHSIA |
lib/tsan/sanitizer_common/sanitizer_fuchsia.h+2| ... | ... | @@ -30,6 +30,8 @@ struct MemoryMappingLayoutData { |
| 30 | 30 | size_t current; // Current index into the vector. |
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | void InitShadowBounds(); | |
| 34 | ||
| 33 | 35 | } // namespace __sanitizer |
| 34 | 36 | |
| 35 | 37 | #endif // SANITIZER_FUCHSIA |
lib/tsan/sanitizer_common/sanitizer_getauxval.h+3-2| ... | ... | @@ -21,8 +21,9 @@ |
| 21 | 21 | |
| 22 | 22 | #if SANITIZER_LINUX || SANITIZER_FUCHSIA |
| 23 | 23 | |
| 24 | # if __GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \ | |
| 25 | SANITIZER_FUCHSIA | |
| 24 | # if (__GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \ | |
| 25 | SANITIZER_FUCHSIA) && \ | |
| 26 | !SANITIZER_GO | |
| 26 | 27 | # define SANITIZER_USE_GETAUXVAL 1 |
| 27 | 28 | # else |
| 28 | 29 | # define SANITIZER_USE_GETAUXVAL 0 |
lib/tsan/sanitizer_common/sanitizer_interface_internal.h+4| ... | ... | @@ -28,6 +28,10 @@ extern "C" { |
| 28 | 28 | // (casted to void *). |
| 29 | 29 | SANITIZER_INTERFACE_ATTRIBUTE |
| 30 | 30 | void __sanitizer_set_report_fd(void *fd); |
| 31 | // Get the current full report file path, if a path was specified by | |
| 32 | // an earlier call to __sanitizer_set_report_path. Returns null otherwise. | |
| 33 | SANITIZER_INTERFACE_ATTRIBUTE | |
| 34 | const char *__sanitizer_get_report_path(); | |
| 31 | 35 | |
| 32 | 36 | typedef struct { |
| 33 | 37 | int coverage_sandboxed; |
lib/tsan/sanitizer_common/sanitizer_internal_defs.h+11-13| ... | ... | @@ -39,7 +39,7 @@ |
| 39 | 39 | |
| 40 | 40 | // TLS is handled differently on different platforms |
| 41 | 41 | #if SANITIZER_LINUX || SANITIZER_NETBSD || \ |
| 42 | SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 42 | SANITIZER_FREEBSD | |
| 43 | 43 | # define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE \ |
| 44 | 44 | __attribute__((tls_model("initial-exec"))) thread_local |
| 45 | 45 | #else |
| ... | ... | @@ -104,8 +104,7 @@ |
| 104 | 104 | // |
| 105 | 105 | // FIXME: do we have anything like this on Mac? |
| 106 | 106 | #ifndef SANITIZER_CAN_USE_PREINIT_ARRAY |
| 107 | #if ((SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_OPENBSD || \ | |
| 108 | SANITIZER_FUCHSIA || SANITIZER_NETBSD) && !defined(PIC) | |
| 107 | #if (SANITIZER_LINUX || SANITIZER_FUCHSIA || SANITIZER_NETBSD) && !defined(PIC) | |
| 109 | 108 | #define SANITIZER_CAN_USE_PREINIT_ARRAY 1 |
| 110 | 109 | // Before Solaris 11.4, .preinit_array is fully supported only with GNU ld. |
| 111 | 110 | // FIXME: Check for those conditions. |
| ... | ... | @@ -170,7 +169,7 @@ typedef int pid_t; |
| 170 | 169 | #endif |
| 171 | 170 | |
| 172 | 171 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD || \ |
| 173 | SANITIZER_OPENBSD || SANITIZER_MAC || \ | |
| 172 | SANITIZER_MAC || \ | |
| 174 | 173 | (SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \ |
| 175 | 174 | (SANITIZER_LINUX && defined(__x86_64__)) |
| 176 | 175 | typedef u64 OFF_T; |
| ... | ... | @@ -182,7 +181,7 @@ typedef u64 OFF64_T; |
| 182 | 181 | #if (SANITIZER_WORDSIZE == 64) || SANITIZER_MAC |
| 183 | 182 | typedef uptr operator_new_size_type; |
| 184 | 183 | #else |
| 185 | # if SANITIZER_OPENBSD || defined(__s390__) && !defined(__s390x__) | |
| 184 | # if defined(__s390__) && !defined(__s390x__) | |
| 186 | 185 | // Special case: 31-bit s390 has unsigned long as size_t. |
| 187 | 186 | typedef unsigned long operator_new_size_type; |
| 188 | 187 | # else |
| ... | ... | @@ -196,9 +195,6 @@ typedef u64 tid_t; |
| 196 | 195 | // This header should NOT include any other headers to avoid portability issues. |
| 197 | 196 | |
| 198 | 197 | // Common defs. |
| 199 | #ifndef INLINE | |
| 200 | #define INLINE inline | |
| 201 | #endif | |
| 202 | 198 | #define INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE |
| 203 | 199 | #define SANITIZER_WEAK_DEFAULT_IMPL \ |
| 204 | 200 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE |
| ... | ... | @@ -333,14 +329,10 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, |
| 333 | 329 | |
| 334 | 330 | #define UNIMPLEMENTED() UNREACHABLE("unimplemented") |
| 335 | 331 | |
| 336 | #define COMPILER_CHECK(pred) IMPL_COMPILER_ASSERT(pred, __LINE__) | |
| 332 | #define COMPILER_CHECK(pred) static_assert(pred, "") | |
| 337 | 333 | |
| 338 | 334 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) |
| 339 | 335 | |
| 340 | #define IMPL_PASTE(a, b) a##b | |
| 341 | #define IMPL_COMPILER_ASSERT(pred, line) \ | |
| 342 | typedef char IMPL_PASTE(assertion_failed_##_, line)[2*(int)(pred)-1] | |
| 343 | ||
| 344 | 336 | // Limits for integral types. We have to redefine it in case we don't |
| 345 | 337 | // have stdint.h (like in Visual Studio 9). |
| 346 | 338 | #undef __INT64_C |
| ... | ... | @@ -417,6 +409,9 @@ inline void Trap() { |
| 417 | 409 | (void)enable_fp; \ |
| 418 | 410 | } while (0) |
| 419 | 411 | |
| 412 | constexpr u32 kInvalidTid = -1; | |
| 413 | constexpr u32 kMainTid = 0; | |
| 414 | ||
| 420 | 415 | } // namespace __sanitizer |
| 421 | 416 | |
| 422 | 417 | namespace __asan { |
| ... | ... | @@ -455,5 +450,8 @@ using namespace __sanitizer; |
| 455 | 450 | namespace __hwasan { |
| 456 | 451 | using namespace __sanitizer; |
| 457 | 452 | } |
| 453 | namespace __memprof { | |
| 454 | using namespace __sanitizer; | |
| 455 | } | |
| 458 | 456 | |
| 459 | 457 | #endif // SANITIZER_DEFS_H |
lib/tsan/sanitizer_common/sanitizer_libc.h+2-1| ... | ... | @@ -67,7 +67,8 @@ uptr internal_ftruncate(fd_t fd, uptr size); |
| 67 | 67 | |
| 68 | 68 | // OS |
| 69 | 69 | void NORETURN internal__exit(int exitcode); |
| 70 | unsigned int internal_sleep(unsigned int seconds); | |
| 70 | void internal_sleep(unsigned seconds); | |
| 71 | void internal_usleep(u64 useconds); | |
| 71 | 72 | |
| 72 | 73 | uptr internal_getpid(); |
| 73 | 74 | uptr internal_getppid(); |
lib/tsan/sanitizer_common/sanitizer_libignore.cpp+2-2| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | #include "sanitizer_platform.h" |
| 10 | 10 | |
| 11 | 11 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \ |
| 12 | SANITIZER_NETBSD || SANITIZER_OPENBSD | |
| 12 | SANITIZER_NETBSD | |
| 13 | 13 | |
| 14 | 14 | #include "sanitizer_libignore.h" |
| 15 | 15 | #include "sanitizer_flags.h" |
| ... | ... | @@ -38,7 +38,7 @@ void LibIgnore::AddIgnoredLibrary(const char *name_templ) { |
| 38 | 38 | void LibIgnore::OnLibraryLoaded(const char *name) { |
| 39 | 39 | BlockingMutexLock lock(&mutex_); |
| 40 | 40 | // Try to match suppressions with symlink target. |
| 41 | InternalScopedString buf(kMaxPathLength); | |
| 41 | InternalMmapVector<char> buf(kMaxPathLength); | |
| 42 | 42 | if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 && |
| 43 | 43 | buf[0]) { |
| 44 | 44 | for (uptr i = 0; i < count_; i++) { |
lib/tsan/sanitizer_common/sanitizer_linux.cpp+165-126| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | #include "sanitizer_platform.h" |
| 15 | 15 | |
| 16 | 16 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ |
| 17 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 17 | SANITIZER_SOLARIS | |
| 18 | 18 | |
| 19 | 19 | #include "sanitizer_common.h" |
| 20 | 20 | #include "sanitizer_flags.h" |
| ... | ... | @@ -38,6 +38,14 @@ |
| 38 | 38 | #include <asm/unistd.h> |
| 39 | 39 | #include <sys/types.h> |
| 40 | 40 | #define stat kernel_stat |
| 41 | #if SANITIZER_GO | |
| 42 | #undef st_atime | |
| 43 | #undef st_mtime | |
| 44 | #undef st_ctime | |
| 45 | #define st_atime st_atim | |
| 46 | #define st_mtime st_mtim | |
| 47 | #define st_ctime st_ctim | |
| 48 | #endif | |
| 41 | 49 | #include <asm/stat.h> |
| 42 | 50 | #undef stat |
| 43 | 51 | #endif |
| ... | ... | @@ -59,13 +67,7 @@ |
| 59 | 67 | #include <sys/syscall.h> |
| 60 | 68 | #include <sys/time.h> |
| 61 | 69 | #include <sys/types.h> |
| 62 | #if !SANITIZER_OPENBSD | |
| 63 | 70 | #include <ucontext.h> |
| 64 | #endif | |
| 65 | #if SANITIZER_OPENBSD | |
| 66 | #include <sys/futex.h> | |
| 67 | #include <sys/sysctl.h> | |
| 68 | #endif | |
| 69 | 71 | #include <unistd.h> |
| 70 | 72 | |
| 71 | 73 | #if SANITIZER_LINUX |
| ... | ... | @@ -129,7 +131,7 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG; |
| 129 | 131 | #endif |
| 130 | 132 | |
| 131 | 133 | // Note : FreeBSD had implemented both |
| 132 | // Linux and OpenBSD apis, available from | |
| 134 | // Linux apis, available from | |
| 133 | 135 | // future 12.x version most likely |
| 134 | 136 | #if SANITIZER_LINUX && defined(__NR_getrandom) |
| 135 | 137 | # if !defined(GRND_NONBLOCK) |
| ... | ... | @@ -140,20 +142,18 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG; |
| 140 | 142 | # define SANITIZER_USE_GETRANDOM 0 |
| 141 | 143 | #endif // SANITIZER_LINUX && defined(__NR_getrandom) |
| 142 | 144 | |
| 143 | #if SANITIZER_OPENBSD | |
| 144 | # define SANITIZER_USE_GETENTROPY 1 | |
| 145 | #if SANITIZER_FREEBSD && __FreeBSD_version >= 1200000 | |
| 146 | # define SANITIZER_USE_GETENTROPY 1 | |
| 145 | 147 | #else |
| 146 | # if SANITIZER_FREEBSD && __FreeBSD_version >= 1200000 | |
| 147 | # define SANITIZER_USE_GETENTROPY 1 | |
| 148 | # else | |
| 149 | # define SANITIZER_USE_GETENTROPY 0 | |
| 150 | # endif | |
| 151 | #endif // SANITIZER_USE_GETENTROPY | |
| 148 | # define SANITIZER_USE_GETENTROPY 0 | |
| 149 | #endif | |
| 152 | 150 | |
| 153 | 151 | namespace __sanitizer { |
| 154 | 152 | |
| 155 | 153 | #if SANITIZER_LINUX && defined(__x86_64__) |
| 156 | 154 | #include "sanitizer_syscall_linux_x86_64.inc" |
| 155 | #elif SANITIZER_LINUX && SANITIZER_RISCV64 | |
| 156 | #include "sanitizer_syscall_linux_riscv64.inc" | |
| 157 | 157 | #elif SANITIZER_LINUX && defined(__aarch64__) |
| 158 | 158 | #include "sanitizer_syscall_linux_aarch64.inc" |
| 159 | 159 | #elif SANITIZER_LINUX && defined(__arm__) |
| ... | ... | @@ -164,7 +164,7 @@ namespace __sanitizer { |
| 164 | 164 | |
| 165 | 165 | // --------------- sanitizer_libc.h |
| 166 | 166 | #if !SANITIZER_SOLARIS && !SANITIZER_NETBSD |
| 167 | #if !SANITIZER_S390 && !SANITIZER_OPENBSD | |
| 167 | #if !SANITIZER_S390 | |
| 168 | 168 | uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, |
| 169 | 169 | u64 offset) { |
| 170 | 170 | #if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS |
| ... | ... | @@ -177,17 +177,27 @@ uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, |
| 177 | 177 | offset / 4096); |
| 178 | 178 | #endif |
| 179 | 179 | } |
| 180 | #endif // !SANITIZER_S390 && !SANITIZER_OPENBSD | |
| 180 | #endif // !SANITIZER_S390 | |
| 181 | 181 | |
| 182 | #if !SANITIZER_OPENBSD | |
| 183 | 182 | uptr internal_munmap(void *addr, uptr length) { |
| 184 | 183 | return internal_syscall(SYSCALL(munmap), (uptr)addr, length); |
| 185 | 184 | } |
| 186 | 185 | |
| 186 | #if SANITIZER_LINUX | |
| 187 | uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags, | |
| 188 | void *new_address) { | |
| 189 | return internal_syscall(SYSCALL(mremap), (uptr)old_address, old_size, | |
| 190 | new_size, flags, (uptr)new_address); | |
| 191 | } | |
| 192 | #endif | |
| 193 | ||
| 187 | 194 | int internal_mprotect(void *addr, uptr length, int prot) { |
| 188 | 195 | return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot); |
| 189 | 196 | } |
| 190 | #endif | |
| 197 | ||
| 198 | int internal_madvise(uptr addr, uptr length, int advice) { | |
| 199 | return internal_syscall(SYSCALL(madvise), addr, length, advice); | |
| 200 | } | |
| 191 | 201 | |
| 192 | 202 | uptr internal_close(fd_t fd) { |
| 193 | 203 | return internal_syscall(SYSCALL(close), fd); |
| ... | ... | @@ -254,9 +264,11 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) { |
| 254 | 264 | // Undefine compatibility macros from <sys/stat.h> |
| 255 | 265 | // so that they would not clash with the kernel_stat |
| 256 | 266 | // st_[a|m|c]time fields |
| 267 | #if !SANITIZER_GO | |
| 257 | 268 | #undef st_atime |
| 258 | 269 | #undef st_mtime |
| 259 | 270 | #undef st_ctime |
| 271 | #endif | |
| 260 | 272 | #if defined(SANITIZER_ANDROID) |
| 261 | 273 | // Bionic sys/stat.h defines additional macros |
| 262 | 274 | // for compatibility with the old NDKs and |
| ... | ... | @@ -299,7 +311,7 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) { |
| 299 | 311 | #endif |
| 300 | 312 | |
| 301 | 313 | uptr internal_stat(const char *path, void *buf) { |
| 302 | #if SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 314 | #if SANITIZER_FREEBSD | |
| 303 | 315 | return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); |
| 304 | 316 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS |
| 305 | 317 | return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, |
| ... | ... | @@ -323,7 +335,7 @@ uptr internal_stat(const char *path, void *buf) { |
| 323 | 335 | } |
| 324 | 336 | |
| 325 | 337 | uptr internal_lstat(const char *path, void *buf) { |
| 326 | #if SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 338 | #if SANITIZER_FREEBSD | |
| 327 | 339 | return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, |
| 328 | 340 | AT_SYMLINK_NOFOLLOW); |
| 329 | 341 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS |
| ... | ... | @@ -348,9 +360,8 @@ uptr internal_lstat(const char *path, void *buf) { |
| 348 | 360 | } |
| 349 | 361 | |
| 350 | 362 | uptr internal_fstat(fd_t fd, void *buf) { |
| 351 | #if SANITIZER_FREEBSD || SANITIZER_OPENBSD || \ | |
| 352 | SANITIZER_LINUX_USES_64BIT_SYSCALLS | |
| 353 | #if SANITIZER_MIPS64 && !SANITIZER_OPENBSD | |
| 363 | #if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS | |
| 364 | #if SANITIZER_MIPS64 | |
| 354 | 365 | // For mips64, fstat syscall fills buffer in the format of kernel_stat |
| 355 | 366 | struct kernel_stat kbuf; |
| 356 | 367 | int res = internal_syscall(SYSCALL(fstat), fd, &kbuf); |
| ... | ... | @@ -390,16 +401,13 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) { |
| 390 | 401 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS |
| 391 | 402 | return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf, |
| 392 | 403 | bufsize); |
| 393 | #elif SANITIZER_OPENBSD | |
| 394 | return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf, | |
| 395 | bufsize); | |
| 396 | 404 | #else |
| 397 | 405 | return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize); |
| 398 | 406 | #endif |
| 399 | 407 | } |
| 400 | 408 | |
| 401 | 409 | uptr internal_unlink(const char *path) { |
| 402 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS || SANITIZER_OPENBSD | |
| 410 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS | |
| 403 | 411 | return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0); |
| 404 | 412 | #else |
| 405 | 413 | return internal_syscall(SYSCALL(unlink), (uptr)path); |
| ... | ... | @@ -410,7 +418,7 @@ uptr internal_rename(const char *oldpath, const char *newpath) { |
| 410 | 418 | #if defined(__riscv) |
| 411 | 419 | return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD, |
| 412 | 420 | (uptr)newpath, 0); |
| 413 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS || SANITIZER_OPENBSD | |
| 421 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS | |
| 414 | 422 | return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD, |
| 415 | 423 | (uptr)newpath); |
| 416 | 424 | #else |
| ... | ... | @@ -422,22 +430,11 @@ uptr internal_sched_yield() { |
| 422 | 430 | return internal_syscall(SYSCALL(sched_yield)); |
| 423 | 431 | } |
| 424 | 432 | |
| 425 | void internal__exit(int exitcode) { | |
| 426 | #if SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 427 | internal_syscall(SYSCALL(exit), exitcode); | |
| 428 | #else | |
| 429 | internal_syscall(SYSCALL(exit_group), exitcode); | |
| 430 | #endif | |
| 431 | Die(); // Unreachable. | |
| 432 | } | |
| 433 | ||
| 434 | unsigned int internal_sleep(unsigned int seconds) { | |
| 433 | void internal_usleep(u64 useconds) { | |
| 435 | 434 | struct timespec ts; |
| 436 | ts.tv_sec = seconds; | |
| 437 | ts.tv_nsec = 0; | |
| 438 | int res = internal_syscall(SYSCALL(nanosleep), &ts, &ts); | |
| 439 | if (res) return ts.tv_sec; | |
| 440 | return 0; | |
| 435 | ts.tv_sec = useconds / 1000000; | |
| 436 | ts.tv_nsec = (useconds % 1000000) * 1000; | |
| 437 | internal_syscall(SYSCALL(nanosleep), &ts, &ts); | |
| 441 | 438 | } |
| 442 | 439 | |
| 443 | 440 | uptr internal_execve(const char *filename, char *const argv[], |
| ... | ... | @@ -447,6 +444,17 @@ uptr internal_execve(const char *filename, char *const argv[], |
| 447 | 444 | } |
| 448 | 445 | #endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD |
| 449 | 446 | |
| 447 | #if !SANITIZER_NETBSD | |
| 448 | void internal__exit(int exitcode) { | |
| 449 | #if SANITIZER_FREEBSD || SANITIZER_SOLARIS | |
| 450 | internal_syscall(SYSCALL(exit), exitcode); | |
| 451 | #else | |
| 452 | internal_syscall(SYSCALL(exit_group), exitcode); | |
| 453 | #endif | |
| 454 | Die(); // Unreachable. | |
| 455 | } | |
| 456 | #endif // !SANITIZER_NETBSD | |
| 457 | ||
| 450 | 458 | // ----------------- sanitizer_common.h |
| 451 | 459 | bool FileExists(const char *filename) { |
| 452 | 460 | if (ShouldMockFailureToOpen(filename)) |
| ... | ... | @@ -468,8 +476,6 @@ tid_t GetTid() { |
| 468 | 476 | long Tid; |
| 469 | 477 | thr_self(&Tid); |
| 470 | 478 | return Tid; |
| 471 | #elif SANITIZER_OPENBSD | |
| 472 | return internal_syscall(SYSCALL(getthrid)); | |
| 473 | 479 | #elif SANITIZER_SOLARIS |
| 474 | 480 | return thr_self(); |
| 475 | 481 | #else |
| ... | ... | @@ -482,9 +488,6 @@ int TgKill(pid_t pid, tid_t tid, int sig) { |
| 482 | 488 | return internal_syscall(SYSCALL(tgkill), pid, tid, sig); |
| 483 | 489 | #elif SANITIZER_FREEBSD |
| 484 | 490 | return internal_syscall(SYSCALL(thr_kill2), pid, tid, sig); |
| 485 | #elif SANITIZER_OPENBSD | |
| 486 | (void)pid; | |
| 487 | return internal_syscall(SYSCALL(thrkill), tid, sig, nullptr); | |
| 488 | 491 | #elif SANITIZER_SOLARIS |
| 489 | 492 | (void)pid; |
| 490 | 493 | return thr_kill(tid, sig); |
| ... | ... | @@ -492,29 +495,30 @@ int TgKill(pid_t pid, tid_t tid, int sig) { |
| 492 | 495 | } |
| 493 | 496 | #endif |
| 494 | 497 | |
| 495 | #if !SANITIZER_SOLARIS && !SANITIZER_NETBSD | |
| 498 | #if SANITIZER_GLIBC | |
| 496 | 499 | u64 NanoTime() { |
| 497 | #if SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 498 | timeval tv; | |
| 499 | #else | |
| 500 | 500 | kernel_timeval tv; |
| 501 | #endif | |
| 502 | 501 | internal_memset(&tv, 0, sizeof(tv)); |
| 503 | 502 | internal_syscall(SYSCALL(gettimeofday), &tv, 0); |
| 504 | return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; | |
| 503 | return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000; | |
| 505 | 504 | } |
| 506 | ||
| 505 | // Used by real_clock_gettime. | |
| 507 | 506 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { |
| 508 | 507 | return internal_syscall(SYSCALL(clock_gettime), clk_id, tp); |
| 509 | 508 | } |
| 510 | #endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD | |
| 509 | #elif !SANITIZER_SOLARIS && !SANITIZER_NETBSD | |
| 510 | u64 NanoTime() { | |
| 511 | struct timespec ts; | |
| 512 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 513 | return (u64)ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec; | |
| 514 | } | |
| 515 | #endif | |
| 511 | 516 | |
| 512 | 517 | // Like getenv, but reads env directly from /proc (on Linux) or parses the |
| 513 | 518 | // 'environ' array (on some others) and does not use libc. This function |
| 514 | 519 | // should be called first inside __asan_init. |
| 515 | 520 | const char *GetEnv(const char *name) { |
| 516 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \ | |
| 517 | SANITIZER_SOLARIS | |
| 521 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS | |
| 518 | 522 | if (::environ != 0) { |
| 519 | 523 | uptr NameLen = internal_strlen(name); |
| 520 | 524 | for (char **Env = ::environ; *Env != 0; Env++) { |
| ... | ... | @@ -552,15 +556,13 @@ const char *GetEnv(const char *name) { |
| 552 | 556 | #endif |
| 553 | 557 | } |
| 554 | 558 | |
| 555 | #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_OPENBSD && \ | |
| 556 | !SANITIZER_GO | |
| 559 | #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_GO | |
| 557 | 560 | extern "C" { |
| 558 | 561 | SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; |
| 559 | 562 | } |
| 560 | 563 | #endif |
| 561 | 564 | |
| 562 | #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \ | |
| 563 | !SANITIZER_OPENBSD | |
| 565 | #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD | |
| 564 | 566 | static void ReadNullSepFileToArray(const char *path, char ***arr, |
| 565 | 567 | int arr_size) { |
| 566 | 568 | char *buff; |
| ... | ... | @@ -585,7 +587,6 @@ static void ReadNullSepFileToArray(const char *path, char ***arr, |
| 585 | 587 | } |
| 586 | 588 | #endif |
| 587 | 589 | |
| 588 | #if !SANITIZER_OPENBSD | |
| 589 | 590 | static void GetArgsAndEnv(char ***argv, char ***envp) { |
| 590 | 591 | #if SANITIZER_FREEBSD |
| 591 | 592 | // On FreeBSD, retrieving the argument and environment arrays is done via the |
| ... | ... | @@ -637,14 +638,28 @@ char **GetEnviron() { |
| 637 | 638 | return envp; |
| 638 | 639 | } |
| 639 | 640 | |
| 640 | #endif // !SANITIZER_OPENBSD | |
| 641 | ||
| 642 | 641 | #if !SANITIZER_SOLARIS |
| 643 | enum MutexState { | |
| 644 | MtxUnlocked = 0, | |
| 645 | MtxLocked = 1, | |
| 646 | MtxSleeping = 2 | |
| 647 | }; | |
| 642 | void FutexWait(atomic_uint32_t *p, u32 cmp) { | |
| 643 | # if SANITIZER_FREEBSD | |
| 644 | _umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0); | |
| 645 | # elif SANITIZER_NETBSD | |
| 646 | sched_yield(); /* No userspace futex-like synchronization */ | |
| 647 | # else | |
| 648 | internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAIT_PRIVATE, cmp, 0, 0, 0); | |
| 649 | # endif | |
| 650 | } | |
| 651 | ||
| 652 | void FutexWake(atomic_uint32_t *p, u32 count) { | |
| 653 | # if SANITIZER_FREEBSD | |
| 654 | _umtx_op(p, UMTX_OP_WAKE, count, 0, 0); | |
| 655 | # elif SANITIZER_NETBSD | |
| 656 | /* No userspace futex-like synchronization */ | |
| 657 | # else | |
| 658 | internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0); | |
| 659 | # endif | |
| 660 | } | |
| 661 | ||
| 662 | enum { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; | |
| 648 | 663 | |
| 649 | 664 | BlockingMutex::BlockingMutex() { |
| 650 | 665 | internal_memset(this, 0, sizeof(*this)); |
| ... | ... | @@ -682,11 +697,11 @@ void BlockingMutex::Unlock() { |
| 682 | 697 | } |
| 683 | 698 | } |
| 684 | 699 | |
| 685 | void BlockingMutex::CheckLocked() { | |
| 686 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |
| 700 | void BlockingMutex::CheckLocked() const { | |
| 701 | auto m = reinterpret_cast<atomic_uint32_t const *>(&opaque_storage_); | |
| 687 | 702 | CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); |
| 688 | 703 | } |
| 689 | #endif // !SANITIZER_SOLARIS | |
| 704 | # endif // !SANITIZER_SOLARIS | |
| 690 | 705 | |
| 691 | 706 | // ----------------- sanitizer_linux.h |
| 692 | 707 | // The actual size of this structure is specified by d_reclen. |
| ... | ... | @@ -694,19 +709,9 @@ void BlockingMutex::CheckLocked() { |
| 694 | 709 | // 32-bit syscall here. |
| 695 | 710 | #if SANITIZER_NETBSD |
| 696 | 711 | // Not used |
| 697 | #elif SANITIZER_OPENBSD | |
| 698 | // struct dirent is different for Linux and us. At this moment, we use only | |
| 699 | // d_fileno (Linux call this d_ino), d_reclen, and d_name. | |
| 700 | struct linux_dirent { | |
| 701 | u64 d_ino; // d_fileno | |
| 702 | u16 d_reclen; | |
| 703 | u16 d_namlen; // not used | |
| 704 | u8 d_type; // not used | |
| 705 | char d_name[NAME_MAX + 1]; | |
| 706 | }; | |
| 707 | 712 | #else |
| 708 | 713 | struct linux_dirent { |
| 709 | #if SANITIZER_X32 || defined(__aarch64__) | |
| 714 | #if SANITIZER_X32 || defined(__aarch64__) || SANITIZER_RISCV64 | |
| 710 | 715 | u64 d_ino; |
| 711 | 716 | u64 d_off; |
| 712 | 717 | #else |
| ... | ... | @@ -714,7 +719,7 @@ struct linux_dirent { |
| 714 | 719 | unsigned long d_off; |
| 715 | 720 | #endif |
| 716 | 721 | unsigned short d_reclen; |
| 717 | #ifdef __aarch64__ | |
| 722 | #if defined(__aarch64__) || SANITIZER_RISCV64 | |
| 718 | 723 | unsigned char d_type; |
| 719 | 724 | #endif |
| 720 | 725 | char d_name[256]; |
| ... | ... | @@ -781,28 +786,39 @@ int internal_fork() { |
| 781 | 786 | #endif |
| 782 | 787 | } |
| 783 | 788 | |
| 784 | #if SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 789 | #if SANITIZER_FREEBSD | |
| 785 | 790 | int internal_sysctl(const int *name, unsigned int namelen, void *oldp, |
| 786 | 791 | uptr *oldlenp, const void *newp, uptr newlen) { |
| 787 | #if SANITIZER_OPENBSD | |
| 788 | return sysctl(name, namelen, oldp, (size_t *)oldlenp, (void *)newp, | |
| 789 | (size_t)newlen); | |
| 790 | #else | |
| 791 | 792 | return internal_syscall(SYSCALL(__sysctl), name, namelen, oldp, |
| 792 | 793 | (size_t *)oldlenp, newp, (size_t)newlen); |
| 793 | #endif | |
| 794 | 794 | } |
| 795 | 795 | |
| 796 | #if SANITIZER_FREEBSD | |
| 797 | 796 | int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, |
| 798 | 797 | const void *newp, uptr newlen) { |
| 799 | static decltype(sysctlbyname) *real = nullptr; | |
| 800 | if (!real) | |
| 801 | real = (decltype(sysctlbyname) *)dlsym(RTLD_NEXT, "sysctlbyname"); | |
| 802 | CHECK(real); | |
| 803 | return real(sname, oldp, (size_t *)oldlenp, newp, (size_t)newlen); | |
| 804 | } | |
| 798 | // Note: this function can be called during startup, so we need to avoid | |
| 799 | // calling any interceptable functions. On FreeBSD >= 1300045 sysctlbyname() | |
| 800 | // is a real syscall, but for older versions it calls sysctlnametomib() | |
| 801 | // followed by sysctl(). To avoid calling the intercepted version and | |
| 802 | // asserting if this happens during startup, call the real sysctlnametomib() | |
| 803 | // followed by internal_sysctl() if the syscall is not available. | |
| 804 | #ifdef SYS___sysctlbyname | |
| 805 | return internal_syscall(SYSCALL(__sysctlbyname), sname, | |
| 806 | internal_strlen(sname), oldp, (size_t *)oldlenp, newp, | |
| 807 | (size_t)newlen); | |
| 808 | #else | |
| 809 | static decltype(sysctlnametomib) *real_sysctlnametomib = nullptr; | |
| 810 | if (!real_sysctlnametomib) | |
| 811 | real_sysctlnametomib = | |
| 812 | (decltype(sysctlnametomib) *)dlsym(RTLD_NEXT, "sysctlnametomib"); | |
| 813 | CHECK(real_sysctlnametomib); | |
| 814 | ||
| 815 | int oid[CTL_MAXNAME]; | |
| 816 | size_t len = CTL_MAXNAME; | |
| 817 | if (real_sysctlnametomib(sname, oid, &len) == -1) | |
| 818 | return (-1); | |
| 819 | return internal_sysctl(oid, len, oldp, oldlenp, newp, newlen); | |
| 805 | 820 | #endif |
| 821 | } | |
| 806 | 822 | #endif |
| 807 | 823 | |
| 808 | 824 | #if SANITIZER_LINUX |
| ... | ... | @@ -856,7 +872,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { |
| 856 | 872 | |
| 857 | 873 | uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, |
| 858 | 874 | __sanitizer_sigset_t *oldset) { |
| 859 | #if SANITIZER_FREEBSD || SANITIZER_OPENBSD | |
| 875 | #if SANITIZER_FREEBSD | |
| 860 | 876 | return internal_syscall(SYSCALL(sigprocmask), how, set, oldset); |
| 861 | 877 | #else |
| 862 | 878 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; |
| ... | ... | @@ -882,7 +898,7 @@ void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { |
| 882 | 898 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; |
| 883 | 899 | const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); |
| 884 | 900 | const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); |
| 885 | k_set->sig[idx] &= ~(1 << bit); | |
| 901 | k_set->sig[idx] &= ~((uptr)1 << bit); | |
| 886 | 902 | } |
| 887 | 903 | |
| 888 | 904 | bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { |
| ... | ... | @@ -892,7 +908,7 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { |
| 892 | 908 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; |
| 893 | 909 | const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); |
| 894 | 910 | const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); |
| 895 | return k_set->sig[idx] & (1 << bit); | |
| 911 | return k_set->sig[idx] & ((uptr)1 << bit); | |
| 896 | 912 | } |
| 897 | 913 | #elif SANITIZER_FREEBSD |
| 898 | 914 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { |
| ... | ... | @@ -1033,7 +1049,7 @@ static uptr GetKernelAreaSize() { |
| 1033 | 1049 | #endif // SANITIZER_WORDSIZE == 32 |
| 1034 | 1050 | |
| 1035 | 1051 | uptr GetMaxVirtualAddress() { |
| 1036 | #if (SANITIZER_NETBSD || SANITIZER_OPENBSD) && defined(__x86_64__) | |
| 1052 | #if SANITIZER_NETBSD && defined(__x86_64__) | |
| 1037 | 1053 | return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE) |
| 1038 | 1054 | #elif SANITIZER_WORDSIZE == 64 |
| 1039 | 1055 | # if defined(__powerpc64__) || defined(__aarch64__) |
| ... | ... | @@ -1045,6 +1061,8 @@ uptr GetMaxVirtualAddress() { |
| 1045 | 1061 | // This should (does) work for both PowerPC64 Endian modes. |
| 1046 | 1062 | // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit. |
| 1047 | 1063 | return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1; |
| 1064 | #elif SANITIZER_RISCV64 | |
| 1065 | return (1ULL << 38) - 1; | |
| 1048 | 1066 | # elif defined(__mips64) |
| 1049 | 1067 | return (1ULL << 40) - 1; // 0x000000ffffffffffUL; |
| 1050 | 1068 | # elif defined(__s390x__) |
| ... | ... | @@ -1094,7 +1112,6 @@ uptr GetPageSize() { |
| 1094 | 1112 | } |
| 1095 | 1113 | #endif // !SANITIZER_ANDROID |
| 1096 | 1114 | |
| 1097 | #if !SANITIZER_OPENBSD | |
| 1098 | 1115 | uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { |
| 1099 | 1116 | #if SANITIZER_SOLARIS |
| 1100 | 1117 | const char *default_module_name = getexecname(); |
| ... | ... | @@ -1131,7 +1148,6 @@ uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { |
| 1131 | 1148 | return module_name_len; |
| 1132 | 1149 | #endif |
| 1133 | 1150 | } |
| 1134 | #endif // !SANITIZER_OPENBSD | |
| 1135 | 1151 | |
| 1136 | 1152 | uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { |
| 1137 | 1153 | #if SANITIZER_LINUX |
| ... | ... | @@ -1164,10 +1180,10 @@ bool LibraryNameIs(const char *full_name, const char *base_name) { |
| 1164 | 1180 | // Call cb for each region mapped by map. |
| 1165 | 1181 | void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) { |
| 1166 | 1182 | CHECK_NE(map, nullptr); |
| 1167 | #if !SANITIZER_FREEBSD && !SANITIZER_OPENBSD | |
| 1183 | #if !SANITIZER_FREEBSD | |
| 1168 | 1184 | typedef ElfW(Phdr) Elf_Phdr; |
| 1169 | 1185 | typedef ElfW(Ehdr) Elf_Ehdr; |
| 1170 | #endif // !SANITIZER_FREEBSD && !SANITIZER_OPENBSD | |
| 1186 | #endif // !SANITIZER_FREEBSD | |
| 1171 | 1187 | char *base = (char *)map->l_addr; |
| 1172 | 1188 | Elf_Ehdr *ehdr = (Elf_Ehdr *)base; |
| 1173 | 1189 | char *phdrs = base + ehdr->e_phoff; |
| ... | ... | @@ -1339,6 +1355,47 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, |
| 1339 | 1355 | : "memory", "$29" ); |
| 1340 | 1356 | return res; |
| 1341 | 1357 | } |
| 1358 | #elif SANITIZER_RISCV64 | |
| 1359 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |
| 1360 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |
| 1361 | if (!fn || !child_stack) | |
| 1362 | return -EINVAL; | |
| 1363 | ||
| 1364 | CHECK_EQ(0, (uptr)child_stack % 16); | |
| 1365 | ||
| 1366 | register int res __asm__("a0"); | |
| 1367 | register int __flags __asm__("a0") = flags; | |
| 1368 | register void *__stack __asm__("a1") = child_stack; | |
| 1369 | register int *__ptid __asm__("a2") = parent_tidptr; | |
| 1370 | register void *__tls __asm__("a3") = newtls; | |
| 1371 | register int *__ctid __asm__("a4") = child_tidptr; | |
| 1372 | register int (*__fn)(void *) __asm__("a5") = fn; | |
| 1373 | register void *__arg __asm__("a6") = arg; | |
| 1374 | register int nr_clone __asm__("a7") = __NR_clone; | |
| 1375 | ||
| 1376 | __asm__ __volatile__( | |
| 1377 | "ecall\n" | |
| 1378 | ||
| 1379 | /* if (a0 != 0) | |
| 1380 | * return a0; | |
| 1381 | */ | |
| 1382 | "bnez a0, 1f\n" | |
| 1383 | ||
| 1384 | // In the child, now. Call "fn(arg)". | |
| 1385 | "mv a0, a6\n" | |
| 1386 | "jalr a5\n" | |
| 1387 | ||
| 1388 | // Call _exit(a0). | |
| 1389 | "addi a7, zero, %9\n" | |
| 1390 | "ecall\n" | |
| 1391 | "1:\n" | |
| 1392 | ||
| 1393 | : "=r"(res) | |
| 1394 | : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__tls), "r"(__ctid), | |
| 1395 | "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit) | |
| 1396 | : "memory"); | |
| 1397 | return res; | |
| 1398 | } | |
| 1342 | 1399 | #elif defined(__aarch64__) |
| 1343 | 1400 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, |
| 1344 | 1401 | int *parent_tidptr, void *newtls, int *child_tidptr) { |
| ... | ... | @@ -1768,11 +1825,7 @@ static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { |
| 1768 | 1825 | } |
| 1769 | 1826 | #endif |
| 1770 | 1827 | |
| 1771 | #if SANITIZER_OPENBSD | |
| 1772 | using Context = sigcontext; | |
| 1773 | #else | |
| 1774 | 1828 | using Context = ucontext_t; |
| 1775 | #endif | |
| 1776 | 1829 | |
| 1777 | 1830 | SignalContext::WriteFlag SignalContext::GetWriteFlag() const { |
| 1778 | 1831 | Context *ucontext = (Context *)context; |
| ... | ... | @@ -1782,8 +1835,6 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const { |
| 1782 | 1835 | uptr err = ucontext->uc_mcontext.mc_err; |
| 1783 | 1836 | #elif SANITIZER_NETBSD |
| 1784 | 1837 | uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR]; |
| 1785 | #elif SANITIZER_OPENBSD | |
| 1786 | uptr err = ucontext->sc_err; | |
| 1787 | 1838 | #elif SANITIZER_SOLARIS && defined(__i386__) |
| 1788 | 1839 | const int Err = 13; |
| 1789 | 1840 | uptr err = ucontext->uc_mcontext.gregs[Err]; |
| ... | ... | @@ -2009,11 +2060,6 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { |
| 2009 | 2060 | *pc = ucontext->uc_mcontext.mc_rip; |
| 2010 | 2061 | *bp = ucontext->uc_mcontext.mc_rbp; |
| 2011 | 2062 | *sp = ucontext->uc_mcontext.mc_rsp; |
| 2012 | #elif SANITIZER_OPENBSD | |
| 2013 | sigcontext *ucontext = (sigcontext *)context; | |
| 2014 | *pc = ucontext->sc_rip; | |
| 2015 | *bp = ucontext->sc_rbp; | |
| 2016 | *sp = ucontext->sc_rsp; | |
| 2017 | 2063 | # else |
| 2018 | 2064 | ucontext_t *ucontext = (ucontext_t*)context; |
| 2019 | 2065 | *pc = ucontext->uc_mcontext.gregs[REG_RIP]; |
| ... | ... | @@ -2026,11 +2072,6 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { |
| 2026 | 2072 | *pc = ucontext->uc_mcontext.mc_eip; |
| 2027 | 2073 | *bp = ucontext->uc_mcontext.mc_ebp; |
| 2028 | 2074 | *sp = ucontext->uc_mcontext.mc_esp; |
| 2029 | #elif SANITIZER_OPENBSD | |
| 2030 | sigcontext *ucontext = (sigcontext *)context; | |
| 2031 | *pc = ucontext->sc_eip; | |
| 2032 | *bp = ucontext->sc_ebp; | |
| 2033 | *sp = ucontext->sc_esp; | |
| 2034 | 2075 | # else |
| 2035 | 2076 | ucontext_t *ucontext = (ucontext_t*)context; |
| 2036 | 2077 | # if SANITIZER_SOLARIS |
| ... | ... | @@ -2203,8 +2244,6 @@ void CheckMPROTECT() { |
| 2203 | 2244 | #endif |
| 2204 | 2245 | } |
| 2205 | 2246 | |
| 2206 | void PrintModuleMap() { } | |
| 2207 | ||
| 2208 | 2247 | void CheckNoDeepBind(const char *filename, int flag) { |
| 2209 | 2248 | #ifdef RTLD_DEEPBIND |
| 2210 | 2249 | if (flag & RTLD_DEEPBIND) { |
lib/tsan/sanitizer_common/sanitizer_linux.h+7-7| ... | ... | @@ -14,12 +14,11 @@ |
| 14 | 14 | |
| 15 | 15 | #include "sanitizer_platform.h" |
| 16 | 16 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ |
| 17 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 17 | SANITIZER_SOLARIS | |
| 18 | 18 | #include "sanitizer_common.h" |
| 19 | 19 | #include "sanitizer_internal_defs.h" |
| 20 | 20 | #include "sanitizer_platform_limits_freebsd.h" |
| 21 | 21 | #include "sanitizer_platform_limits_netbsd.h" |
| 22 | #include "sanitizer_platform_limits_openbsd.h" | |
| 23 | 22 | #include "sanitizer_platform_limits_posix.h" |
| 24 | 23 | #include "sanitizer_platform_limits_solaris.h" |
| 25 | 24 | #include "sanitizer_posix.h" |
| ... | ... | @@ -50,7 +49,9 @@ uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); |
| 50 | 49 | uptr internal_sigaltstack(const void* ss, void* oss); |
| 51 | 50 | uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, |
| 52 | 51 | __sanitizer_sigset_t *oldset); |
| 52 | #if SANITIZER_GLIBC | |
| 53 | 53 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); |
| 54 | #endif | |
| 54 | 55 | |
| 55 | 56 | // Linux-only syscalls. |
| 56 | 57 | #if SANITIZER_LINUX |
| ... | ... | @@ -60,9 +61,9 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); |
| 60 | 61 | // internal_sigaction instead. |
| 61 | 62 | int internal_sigaction_norestorer(int signum, const void *act, void *oldact); |
| 62 | 63 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
| 63 | #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \ | |
| 64 | || defined(__powerpc64__) || defined(__s390__) || defined(__i386__) \ | |
| 65 | || defined(__arm__) | |
| 64 | #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ | |
| 65 | defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ | |
| 66 | defined(__arm__) || SANITIZER_RISCV64 | |
| 66 | 67 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, |
| 67 | 68 | int *parent_tidptr, void *newtls, int *child_tidptr); |
| 68 | 69 | #endif |
| ... | ... | @@ -97,7 +98,6 @@ class ThreadLister { |
| 97 | 98 | // Exposed for testing. |
| 98 | 99 | uptr ThreadDescriptorSize(); |
| 99 | 100 | uptr ThreadSelf(); |
| 100 | uptr ThreadSelfOffset(); | |
| 101 | 101 | |
| 102 | 102 | // Matches a library's file name against a base name (stripping path and version |
| 103 | 103 | // information). |
| ... | ... | @@ -109,7 +109,7 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); |
| 109 | 109 | // Releases memory pages entirely within the [beg, end] address range. |
| 110 | 110 | // The pages no longer count toward RSS; reads are guaranteed to return 0. |
| 111 | 111 | // Requires (but does not verify!) that pages are MAP_PRIVATE. |
| 112 | INLINE void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { | |
| 112 | inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { | |
| 113 | 113 | // man madvise on Linux promises zero-fill for anonymous private pages. |
| 114 | 114 | // Testing shows the same behaviour for private (but not anonymous) mappings |
| 115 | 115 | // of shm_open() files, as long as the underlying file is untouched. |
lib/tsan/sanitizer_common/sanitizer_linux_libcdep.cpp+383-229| ... | ... | @@ -13,8 +13,8 @@ |
| 13 | 13 | |
| 14 | 14 | #include "sanitizer_platform.h" |
| 15 | 15 | |
| 16 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ | |
| 17 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 16 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ | |
| 17 | SANITIZER_SOLARIS | |
| 18 | 18 | |
| 19 | 19 | #include "sanitizer_allocator_internal.h" |
| 20 | 20 | #include "sanitizer_atomic.h" |
| ... | ... | @@ -28,10 +28,15 @@ |
| 28 | 28 | #include "sanitizer_placement_new.h" |
| 29 | 29 | #include "sanitizer_procmaps.h" |
| 30 | 30 | |
| 31 | #if SANITIZER_NETBSD | |
| 32 | #define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast() | |
| 33 | #endif | |
| 34 | ||
| 31 | 35 | #include <dlfcn.h> // for dlsym() |
| 32 | 36 | #include <link.h> |
| 33 | 37 | #include <pthread.h> |
| 34 | 38 | #include <signal.h> |
| 39 | #include <sys/mman.h> | |
| 35 | 40 | #include <sys/resource.h> |
| 36 | 41 | #include <syslog.h> |
| 37 | 42 | |
| ... | ... | @@ -44,11 +49,10 @@ |
| 44 | 49 | #include <osreldate.h> |
| 45 | 50 | #include <sys/sysctl.h> |
| 46 | 51 | #define pthread_getattr_np pthread_attr_get_np |
| 47 | #endif | |
| 48 | ||
| 49 | #if SANITIZER_OPENBSD | |
| 50 | #include <pthread_np.h> | |
| 51 | #include <sys/sysctl.h> | |
| 52 | // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before | |
| 53 | // that, it was never implemented. So just define it to zero. | |
| 54 | #undef MAP_NORESERVE | |
| 55 | #define MAP_NORESERVE 0 | |
| 52 | 56 | #endif |
| 53 | 57 | |
| 54 | 58 | #if SANITIZER_NETBSD |
| ... | ... | @@ -138,18 +142,13 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, |
| 138 | 142 | CHECK_EQ(thr_stksegment(&ss), 0); |
| 139 | 143 | stacksize = ss.ss_size; |
| 140 | 144 | stackaddr = (char *)ss.ss_sp - stacksize; |
| 141 | #elif SANITIZER_OPENBSD | |
| 142 | stack_t sattr; | |
| 143 | CHECK_EQ(pthread_stackseg_np(pthread_self(), &sattr), 0); | |
| 144 | stackaddr = sattr.ss_sp; | |
| 145 | stacksize = sattr.ss_size; | |
| 146 | 145 | #else // !SANITIZER_SOLARIS |
| 147 | 146 | pthread_attr_t attr; |
| 148 | 147 | pthread_attr_init(&attr); |
| 149 | 148 | CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); |
| 150 | 149 | my_pthread_attr_getstack(&attr, &stackaddr, &stacksize); |
| 151 | 150 | pthread_attr_destroy(&attr); |
| 152 | #endif // SANITIZER_SOLARIS | |
| 151 | #endif // SANITIZER_SOLARIS | |
| 153 | 152 | |
| 154 | 153 | *stack_top = (uptr)stackaddr + stacksize; |
| 155 | 154 | *stack_bottom = (uptr)stackaddr; |
| ... | ... | @@ -189,86 +188,35 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor, |
| 189 | 188 | #endif |
| 190 | 189 | } |
| 191 | 190 | |
| 192 | #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO && \ | |
| 193 | !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_SOLARIS | |
| 194 | static uptr g_tls_size; | |
| 195 | ||
| 196 | #ifdef __i386__ | |
| 197 | # define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27)) | |
| 198 | #else | |
| 199 | # define CHECK_GET_TLS_STATIC_INFO_VERSION 0 | |
| 200 | #endif | |
| 201 | ||
| 202 | #if CHECK_GET_TLS_STATIC_INFO_VERSION | |
| 203 | # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall)) | |
| 204 | #else | |
| 205 | # define DL_INTERNAL_FUNCTION | |
| 206 | #endif | |
| 207 | ||
| 208 | namespace { | |
| 209 | struct GetTlsStaticInfoCall { | |
| 210 | typedef void (*get_tls_func)(size_t*, size_t*); | |
| 211 | }; | |
| 212 | struct GetTlsStaticInfoRegparmCall { | |
| 213 | typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; | |
| 214 | }; | |
| 215 | ||
| 216 | template <typename T> | |
| 217 | void CallGetTls(void* ptr, size_t* size, size_t* align) { | |
| 218 | typename T::get_tls_func get_tls; | |
| 219 | CHECK_EQ(sizeof(get_tls), sizeof(ptr)); | |
| 220 | internal_memcpy(&get_tls, &ptr, sizeof(ptr)); | |
| 221 | CHECK_NE(get_tls, 0); | |
| 222 | get_tls(size, align); | |
| 223 | } | |
| 224 | ||
| 225 | bool CmpLibcVersion(int major, int minor, int patch) { | |
| 226 | int ma; | |
| 227 | int mi; | |
| 228 | int pa; | |
| 229 | if (!GetLibcVersion(&ma, &mi, &pa)) | |
| 230 | return false; | |
| 231 | if (ma > major) | |
| 232 | return true; | |
| 233 | if (ma < major) | |
| 234 | return false; | |
| 235 | if (mi > minor) | |
| 236 | return true; | |
| 237 | if (mi < minor) | |
| 238 | return false; | |
| 239 | return pa >= patch; | |
| 240 | } | |
| 241 | ||
| 242 | } // namespace | |
| 191 | // True if we can use dlpi_tls_data. glibc before 2.25 may leave NULL (BZ | |
| 192 | // #19826) so dlpi_tls_data cannot be used. | |
| 193 | // | |
| 194 | // musl before 1.2.3 and FreeBSD as of 12.2 incorrectly set dlpi_tls_data to | |
| 195 | // the TLS initialization image | |
| 196 | // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=254774 | |
| 197 | __attribute__((unused)) static int g_use_dlpi_tls_data; | |
| 243 | 198 | |
| 199 | #if SANITIZER_GLIBC && !SANITIZER_GO | |
| 200 | __attribute__((unused)) static size_t g_tls_size; | |
| 244 | 201 | void InitTlsSize() { |
| 245 | // all current supported platforms have 16 bytes stack alignment | |
| 246 | const size_t kStackAlign = 16; | |
| 247 | void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); | |
| 248 | size_t tls_size = 0; | |
| 249 | size_t tls_align = 0; | |
| 250 | // On i?86, _dl_get_tls_static_info used to be internal_function, i.e. | |
| 251 | // __attribute__((regparm(3), stdcall)) before glibc 2.27 and is normal | |
| 252 | // function in 2.27 and later. | |
| 253 | if (CHECK_GET_TLS_STATIC_INFO_VERSION && !CmpLibcVersion(2, 27, 0)) | |
| 254 | CallGetTls<GetTlsStaticInfoRegparmCall>(get_tls_static_info_ptr, | |
| 255 | &tls_size, &tls_align); | |
| 256 | else | |
| 257 | CallGetTls<GetTlsStaticInfoCall>(get_tls_static_info_ptr, | |
| 258 | &tls_size, &tls_align); | |
| 259 | if (tls_align < kStackAlign) | |
| 260 | tls_align = kStackAlign; | |
| 261 | g_tls_size = RoundUpTo(tls_size, tls_align); | |
| 202 | int major, minor, patch; | |
| 203 | g_use_dlpi_tls_data = | |
| 204 | GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25; | |
| 205 | ||
| 206 | #if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__) | |
| 207 | void *get_tls_static_info = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); | |
| 208 | size_t tls_align; | |
| 209 | ((void (*)(size_t *, size_t *))get_tls_static_info)(&g_tls_size, &tls_align); | |
| 210 | #endif | |
| 262 | 211 | } |
| 263 | 212 | #else |
| 264 | 213 | void InitTlsSize() { } |
| 265 | #endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO && | |
| 266 | // !SANITIZER_NETBSD && !SANITIZER_SOLARIS | |
| 214 | #endif // SANITIZER_GLIBC && !SANITIZER_GO | |
| 267 | 215 | |
| 268 | #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) || \ | |
| 269 | defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__) || \ | |
| 270 | defined(__arm__)) && \ | |
| 271 | SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 216 | // On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage | |
| 217 | // of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan | |
| 218 | // to get the pointer to thread-specific data keys in the thread control block. | |
| 219 | #if (SANITIZER_FREEBSD || SANITIZER_LINUX) && !SANITIZER_ANDROID | |
| 272 | 220 | // sizeof(struct pthread) from glibc. |
| 273 | 221 | static atomic_uintptr_t thread_descriptor_size; |
| 274 | 222 | |
| ... | ... | @@ -301,41 +249,58 @@ uptr ThreadDescriptorSize() { |
| 301 | 249 | val = FIRST_32_SECOND_64(1168, 2288); |
| 302 | 250 | else if (minor <= 14) |
| 303 | 251 | val = FIRST_32_SECOND_64(1168, 2304); |
| 304 | else | |
| 252 | else if (minor < 32) // Unknown version | |
| 305 | 253 | val = FIRST_32_SECOND_64(1216, 2304); |
| 254 | else // minor == 32 | |
| 255 | val = FIRST_32_SECOND_64(1344, 2496); | |
| 306 | 256 | } |
| 257 | #elif defined(__s390__) || defined(__sparc__) | |
| 258 | // The size of a prefix of TCB including pthread::{specific_1stblock,specific} | |
| 259 | // suffices. Just return offsetof(struct pthread, specific_used), which hasn't | |
| 260 | // changed since 2007-05. Technically this applies to i386/x86_64 as well but | |
| 261 | // we call _dl_get_tls_static_info and need the precise size of struct | |
| 262 | // pthread. | |
| 263 | return FIRST_32_SECOND_64(524, 1552); | |
| 307 | 264 | #elif defined(__mips__) |
| 308 | 265 | // TODO(sagarthakur): add more values as per different glibc versions. |
| 309 | 266 | val = FIRST_32_SECOND_64(1152, 1776); |
| 267 | #elif SANITIZER_RISCV64 | |
| 268 | int major; | |
| 269 | int minor; | |
| 270 | int patch; | |
| 271 | if (GetLibcVersion(&major, &minor, &patch) && major == 2) { | |
| 272 | // TODO: consider adding an optional runtime check for an unknown (untested) | |
| 273 | // glibc version | |
| 274 | if (minor <= 28) // WARNING: the highest tested version is 2.29 | |
| 275 | val = 1772; // no guarantees for this one | |
| 276 | else if (minor <= 31) | |
| 277 | val = 1772; // tested against glibc 2.29, 2.31 | |
| 278 | else | |
| 279 | val = 1936; // tested against glibc 2.32 | |
| 280 | } | |
| 281 | ||
| 310 | 282 | #elif defined(__aarch64__) |
| 311 | 283 | // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22. |
| 312 | 284 | val = 1776; |
| 313 | 285 | #elif defined(__powerpc64__) |
| 314 | 286 | val = 1776; // from glibc.ppc64le 2.20-8.fc21 |
| 315 | #elif defined(__s390__) | |
| 316 | val = FIRST_32_SECOND_64(1152, 1776); // valid for glibc 2.22 | |
| 317 | 287 | #endif |
| 318 | 288 | if (val) |
| 319 | 289 | atomic_store_relaxed(&thread_descriptor_size, val); |
| 320 | 290 | return val; |
| 321 | 291 | } |
| 322 | 292 | |
| 323 | // The offset at which pointer to self is located in the thread descriptor. | |
| 324 | const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16); | |
| 325 | ||
| 326 | uptr ThreadSelfOffset() { | |
| 327 | return kThreadSelfOffset; | |
| 328 | } | |
| 329 | ||
| 330 | #if defined(__mips__) || defined(__powerpc64__) | |
| 293 | #if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 | |
| 331 | 294 | // TlsPreTcbSize includes size of struct pthread_descr and size of tcb |
| 332 | 295 | // head structure. It lies before the static tls blocks. |
| 333 | 296 | static uptr TlsPreTcbSize() { |
| 334 | # if defined(__mips__) | |
| 297 | #if defined(__mips__) | |
| 335 | 298 | const uptr kTcbHead = 16; // sizeof (tcbhead_t) |
| 336 | # elif defined(__powerpc64__) | |
| 299 | #elif defined(__powerpc64__) | |
| 337 | 300 | const uptr kTcbHead = 88; // sizeof (tcbhead_t) |
| 338 | # endif | |
| 301 | #elif SANITIZER_RISCV64 | |
| 302 | const uptr kTcbHead = 16; // sizeof (tcbhead_t) | |
| 303 | #endif | |
| 339 | 304 | const uptr kTlsAlign = 16; |
| 340 | 305 | const uptr kTlsPreTcbSize = |
| 341 | 306 | RoundUpTo(ThreadDescriptorSize() + kTcbHead, kTlsAlign); |
| ... | ... | @@ -343,68 +308,107 @@ static uptr TlsPreTcbSize() { |
| 343 | 308 | } |
| 344 | 309 | #endif |
| 345 | 310 | |
| 346 | uptr ThreadSelf() { | |
| 347 | uptr descr_addr; | |
| 348 | # if defined(__i386__) | |
| 349 | asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); | |
| 350 | # elif defined(__x86_64__) | |
| 351 | asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); | |
| 352 | # elif defined(__mips__) | |
| 353 | // MIPS uses TLS variant I. The thread pointer (in hardware register $29) | |
| 354 | // points to the end of the TCB + 0x7000. The pthread_descr structure is | |
| 355 | // immediately in front of the TCB. TlsPreTcbSize() includes the size of the | |
| 356 | // TCB and the size of pthread_descr. | |
| 357 | const uptr kTlsTcbOffset = 0x7000; | |
| 358 | uptr thread_pointer; | |
| 359 | asm volatile(".set push;\ | |
| 360 | .set mips64r2;\ | |
| 361 | rdhwr %0,$29;\ | |
| 362 | .set pop" : "=r" (thread_pointer)); | |
| 363 | descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize(); | |
| 364 | # elif defined(__aarch64__) || defined(__arm__) | |
| 365 | descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) - | |
| 366 | ThreadDescriptorSize(); | |
| 367 | # elif defined(__s390__) | |
| 368 | descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer()); | |
| 369 | # elif defined(__powerpc64__) | |
| 370 | // PPC64LE uses TLS variant I. The thread pointer (in GPR 13) | |
| 371 | // points to the end of the TCB + 0x7000. The pthread_descr structure is | |
| 372 | // immediately in front of the TCB. TlsPreTcbSize() includes the size of the | |
| 373 | // TCB and the size of pthread_descr. | |
| 374 | const uptr kTlsTcbOffset = 0x7000; | |
| 375 | uptr thread_pointer; | |
| 376 | asm("addi %0,13,%1" : "=r"(thread_pointer) : "I"(-kTlsTcbOffset)); | |
| 377 | descr_addr = thread_pointer - TlsPreTcbSize(); | |
| 378 | # else | |
| 379 | # error "unsupported CPU arch" | |
| 380 | # endif | |
| 381 | return descr_addr; | |
| 382 | } | |
| 383 | #endif // (x86_64 || i386 || MIPS) && SANITIZER_LINUX | |
| 311 | #if !SANITIZER_GO | |
| 312 | namespace { | |
| 313 | struct TlsBlock { | |
| 314 | uptr begin, end, align; | |
| 315 | size_t tls_modid; | |
| 316 | bool operator<(const TlsBlock &rhs) const { return begin < rhs.begin; } | |
| 317 | }; | |
| 318 | } // namespace | |
| 384 | 319 | |
| 385 | #if SANITIZER_FREEBSD | |
| 386 | static void **ThreadSelfSegbase() { | |
| 387 | void **segbase = 0; | |
| 388 | # if defined(__i386__) | |
| 389 | // sysarch(I386_GET_GSBASE, segbase); | |
| 390 | __asm __volatile("mov %%gs:0, %0" : "=r" (segbase)); | |
| 391 | # elif defined(__x86_64__) | |
| 392 | // sysarch(AMD64_GET_FSBASE, segbase); | |
| 393 | __asm __volatile("movq %%fs:0, %0" : "=r" (segbase)); | |
| 394 | # else | |
| 395 | # error "unsupported CPU arch" | |
| 396 | # endif | |
| 397 | return segbase; | |
| 320 | #ifdef __s390__ | |
| 321 | extern "C" uptr __tls_get_offset(void *arg); | |
| 322 | ||
| 323 | static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) { | |
| 324 | // The __tls_get_offset ABI requires %r12 to point to GOT and %r2 to be an | |
| 325 | // offset of a struct tls_index inside GOT. We don't possess either of the | |
| 326 | // two, so violate the letter of the "ELF Handling For Thread-Local | |
| 327 | // Storage" document and assume that the implementation just dereferences | |
| 328 | // %r2 + %r12. | |
| 329 | uptr tls_index[2] = {ti_module, ti_offset}; | |
| 330 | register uptr r2 asm("2") = 0; | |
| 331 | register void *r12 asm("12") = tls_index; | |
| 332 | asm("basr %%r14, %[__tls_get_offset]" | |
| 333 | : "+r"(r2) | |
| 334 | : [__tls_get_offset] "r"(__tls_get_offset), "r"(r12) | |
| 335 | : "memory", "cc", "0", "1", "3", "4", "5", "14"); | |
| 336 | return r2; | |
| 398 | 337 | } |
| 338 | #else | |
| 339 | extern "C" void *__tls_get_addr(size_t *); | |
| 340 | #endif | |
| 399 | 341 | |
| 400 | uptr ThreadSelf() { | |
| 401 | return (uptr)ThreadSelfSegbase()[2]; | |
| 342 | static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size, | |
| 343 | void *data) { | |
| 344 | if (!info->dlpi_tls_modid) | |
| 345 | return 0; | |
| 346 | uptr begin = (uptr)info->dlpi_tls_data; | |
| 347 | if (!g_use_dlpi_tls_data) { | |
| 348 | // Call __tls_get_addr as a fallback. This forces TLS allocation on glibc | |
| 349 | // and FreeBSD. | |
| 350 | #ifdef __s390__ | |
| 351 | begin = (uptr)__builtin_thread_pointer() + | |
| 352 | TlsGetOffset(info->dlpi_tls_modid, 0); | |
| 353 | #else | |
| 354 | size_t mod_and_off[2] = {info->dlpi_tls_modid, 0}; | |
| 355 | begin = (uptr)__tls_get_addr(mod_and_off); | |
| 356 | #endif | |
| 357 | } | |
| 358 | for (unsigned i = 0; i != info->dlpi_phnum; ++i) | |
| 359 | if (info->dlpi_phdr[i].p_type == PT_TLS) { | |
| 360 | static_cast<InternalMmapVector<TlsBlock> *>(data)->push_back( | |
| 361 | TlsBlock{begin, begin + info->dlpi_phdr[i].p_memsz, | |
| 362 | info->dlpi_phdr[i].p_align, info->dlpi_tls_modid}); | |
| 363 | break; | |
| 364 | } | |
| 365 | return 0; | |
| 402 | 366 | } |
| 403 | #endif // SANITIZER_FREEBSD | |
| 367 | ||
| 368 | __attribute__((unused)) static void GetStaticTlsBoundary(uptr *addr, uptr *size, | |
| 369 | uptr *align) { | |
| 370 | InternalMmapVector<TlsBlock> ranges; | |
| 371 | dl_iterate_phdr(CollectStaticTlsBlocks, &ranges); | |
| 372 | uptr len = ranges.size(); | |
| 373 | Sort(ranges.begin(), len); | |
| 374 | // Find the range with tls_modid=1. For glibc, because libc.so uses PT_TLS, | |
| 375 | // this module is guaranteed to exist and is one of the initially loaded | |
| 376 | // modules. | |
| 377 | uptr one = 0; | |
| 378 | while (one != len && ranges[one].tls_modid != 1) ++one; | |
| 379 | if (one == len) { | |
| 380 | // This may happen with musl if no module uses PT_TLS. | |
| 381 | *addr = 0; | |
| 382 | *size = 0; | |
| 383 | *align = 1; | |
| 384 | return; | |
| 385 | } | |
| 386 | // Find the maximum consecutive ranges. We consider two modules consecutive if | |
| 387 | // the gap is smaller than the alignment. The dynamic loader places static TLS | |
| 388 | // blocks this way not to waste space. | |
| 389 | uptr l = one; | |
| 390 | *align = ranges[l].align; | |
| 391 | while (l != 0 && ranges[l].begin < ranges[l - 1].end + ranges[l - 1].align) | |
| 392 | *align = Max(*align, ranges[--l].align); | |
| 393 | uptr r = one + 1; | |
| 394 | while (r != len && ranges[r].begin < ranges[r - 1].end + ranges[r - 1].align) | |
| 395 | *align = Max(*align, ranges[r++].align); | |
| 396 | *addr = ranges[l].begin; | |
| 397 | *size = ranges[r - 1].end - ranges[l].begin; | |
| 398 | } | |
| 399 | #endif // !SANITIZER_GO | |
| 400 | #endif // (x86_64 || i386 || mips || ...) && (SANITIZER_FREEBSD || | |
| 401 | // SANITIZER_LINUX) && !SANITIZER_ANDROID | |
| 404 | 402 | |
| 405 | 403 | #if SANITIZER_NETBSD |
| 406 | 404 | static struct tls_tcb * ThreadSelfTlsTcb() { |
| 407 | return (struct tls_tcb *)_lwp_getprivate(); | |
| 405 | struct tls_tcb *tcb = nullptr; | |
| 406 | #ifdef __HAVE___LWP_GETTCB_FAST | |
| 407 | tcb = (struct tls_tcb *)__lwp_gettcb_fast(); | |
| 408 | #elif defined(__HAVE___LWP_GETPRIVATE_FAST) | |
| 409 | tcb = (struct tls_tcb *)__lwp_getprivate_fast(); | |
| 410 | #endif | |
| 411 | return tcb; | |
| 408 | 412 | } |
| 409 | 413 | |
| 410 | 414 | uptr ThreadSelf() { |
| ... | ... | @@ -425,35 +429,91 @@ int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) { |
| 425 | 429 | } |
| 426 | 430 | #endif // SANITIZER_NETBSD |
| 427 | 431 | |
| 432 | #if SANITIZER_ANDROID | |
| 433 | // Bionic provides this API since S. | |
| 434 | extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_get_static_tls_bounds(void **, | |
| 435 | void **); | |
| 436 | #endif | |
| 437 | ||
| 428 | 438 | #if !SANITIZER_GO |
| 429 | 439 | static void GetTls(uptr *addr, uptr *size) { |
| 430 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 431 | # if defined(__x86_64__) || defined(__i386__) || defined(__s390__) | |
| 432 | *addr = ThreadSelf(); | |
| 433 | *size = GetTlsSize(); | |
| 440 | #if SANITIZER_ANDROID | |
| 441 | if (&__libc_get_static_tls_bounds) { | |
| 442 | void *start_addr; | |
| 443 | void *end_addr; | |
| 444 | __libc_get_static_tls_bounds(&start_addr, &end_addr); | |
| 445 | *addr = reinterpret_cast<uptr>(start_addr); | |
| 446 | *size = | |
| 447 | reinterpret_cast<uptr>(end_addr) - reinterpret_cast<uptr>(start_addr); | |
| 448 | } else { | |
| 449 | *addr = 0; | |
| 450 | *size = 0; | |
| 451 | } | |
| 452 | #elif SANITIZER_GLIBC && defined(__x86_64__) | |
| 453 | // For aarch64 and x86-64, use an O(1) approach which requires relatively | |
| 454 | // precise ThreadDescriptorSize. g_tls_size was initialized in InitTlsSize. | |
| 455 | asm("mov %%fs:16,%0" : "=r"(*addr)); | |
| 456 | *size = g_tls_size; | |
| 434 | 457 | *addr -= *size; |
| 435 | 458 | *addr += ThreadDescriptorSize(); |
| 436 | # elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) \ | |
| 437 | || defined(__arm__) | |
| 438 | *addr = ThreadSelf(); | |
| 439 | *size = GetTlsSize(); | |
| 440 | # else | |
| 441 | *addr = 0; | |
| 442 | *size = 0; | |
| 443 | # endif | |
| 444 | #elif SANITIZER_FREEBSD | |
| 445 | void** segbase = ThreadSelfSegbase(); | |
| 446 | *addr = 0; | |
| 447 | *size = 0; | |
| 448 | if (segbase != 0) { | |
| 449 | // tcbalign = 16 | |
| 450 | // tls_size = round(tls_static_space, tcbalign); | |
| 451 | // dtv = segbase[1]; | |
| 452 | // dtv[2] = segbase - tls_static_space; | |
| 453 | void **dtv = (void**) segbase[1]; | |
| 454 | *addr = (uptr) dtv[2]; | |
| 455 | *size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]); | |
| 459 | #elif SANITIZER_GLIBC && defined(__aarch64__) | |
| 460 | *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) - | |
| 461 | ThreadDescriptorSize(); | |
| 462 | *size = g_tls_size + ThreadDescriptorSize(); | |
| 463 | #elif SANITIZER_GLIBC && defined(__powerpc64__) | |
| 464 | // Workaround for glibc<2.25(?). 2.27 is known to not need this. | |
| 465 | uptr tp; | |
| 466 | asm("addi %0,13,-0x7000" : "=r"(tp)); | |
| 467 | const uptr pre_tcb_size = TlsPreTcbSize(); | |
| 468 | *addr = tp - pre_tcb_size; | |
| 469 | *size = g_tls_size + pre_tcb_size; | |
| 470 | #elif SANITIZER_FREEBSD || SANITIZER_LINUX | |
| 471 | uptr align; | |
| 472 | GetStaticTlsBoundary(addr, size, &align); | |
| 473 | #if defined(__x86_64__) || defined(__i386__) || defined(__s390__) || \ | |
| 474 | defined(__sparc__) | |
| 475 | if (SANITIZER_GLIBC) { | |
| 476 | #if defined(__x86_64__) || defined(__i386__) | |
| 477 | align = Max<uptr>(align, 64); | |
| 478 | #else | |
| 479 | align = Max<uptr>(align, 16); | |
| 480 | #endif | |
| 456 | 481 | } |
| 482 | const uptr tp = RoundUpTo(*addr + *size, align); | |
| 483 | ||
| 484 | // lsan requires the range to additionally cover the static TLS surplus | |
| 485 | // (elf/dl-tls.c defines 1664). Otherwise there may be false positives for | |
| 486 | // allocations only referenced by tls in dynamically loaded modules. | |
| 487 | if (SANITIZER_GLIBC) | |
| 488 | *size += 1644; | |
| 489 | else if (SANITIZER_FREEBSD) | |
| 490 | *size += 128; // RTLD_STATIC_TLS_EXTRA | |
| 491 | ||
| 492 | // Extend the range to include the thread control block. On glibc, lsan needs | |
| 493 | // the range to include pthread::{specific_1stblock,specific} so that | |
| 494 | // allocations only referenced by pthread_setspecific can be scanned. This may | |
| 495 | // underestimate by at most TLS_TCB_ALIGN-1 bytes but it should be fine | |
| 496 | // because the number of bytes after pthread::specific is larger. | |
| 497 | *addr = tp - RoundUpTo(*size, align); | |
| 498 | *size = tp - *addr + ThreadDescriptorSize(); | |
| 499 | #else | |
| 500 | if (SANITIZER_GLIBC) | |
| 501 | *size += 1664; | |
| 502 | else if (SANITIZER_FREEBSD) | |
| 503 | *size += 128; // RTLD_STATIC_TLS_EXTRA | |
| 504 | #if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 | |
| 505 | const uptr pre_tcb_size = TlsPreTcbSize(); | |
| 506 | *addr -= pre_tcb_size; | |
| 507 | *size += pre_tcb_size; | |
| 508 | #else | |
| 509 | // arm and aarch64 reserve two words at TP, so this underestimates the range. | |
| 510 | // However, this is sufficient for the purpose of finding the pointers to | |
| 511 | // thread-specific data keys. | |
| 512 | const uptr tcb_size = ThreadDescriptorSize(); | |
| 513 | *addr -= tcb_size; | |
| 514 | *size += tcb_size; | |
| 515 | #endif | |
| 516 | #endif | |
| 457 | 517 | #elif SANITIZER_NETBSD |
| 458 | 518 | struct tls_tcb * const tcb = ThreadSelfTlsTcb(); |
| 459 | 519 | *addr = 0; |
| ... | ... | @@ -468,33 +528,25 @@ static void GetTls(uptr *addr, uptr *size) { |
| 468 | 528 | *addr = (uptr)tcb->tcb_dtv[1]; |
| 469 | 529 | } |
| 470 | 530 | } |
| 471 | #elif SANITIZER_OPENBSD | |
| 472 | *addr = 0; | |
| 473 | *size = 0; | |
| 474 | #elif SANITIZER_ANDROID | |
| 475 | *addr = 0; | |
| 476 | *size = 0; | |
| 477 | 531 | #elif SANITIZER_SOLARIS |
| 478 | 532 | // FIXME |
| 479 | 533 | *addr = 0; |
| 480 | 534 | *size = 0; |
| 481 | 535 | #else |
| 482 | # error "Unknown OS" | |
| 536 | #error "Unknown OS" | |
| 483 | 537 | #endif |
| 484 | 538 | } |
| 485 | 539 | #endif |
| 486 | 540 | |
| 487 | 541 | #if !SANITIZER_GO |
| 488 | 542 | uptr GetTlsSize() { |
| 489 | #if SANITIZER_FREEBSD || SANITIZER_ANDROID || SANITIZER_NETBSD || \ | |
| 490 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 543 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ | |
| 544 | SANITIZER_SOLARIS | |
| 491 | 545 | uptr addr, size; |
| 492 | 546 | GetTls(&addr, &size); |
| 493 | 547 | return size; |
| 494 | #elif defined(__mips__) || defined(__powerpc64__) | |
| 495 | return RoundUpTo(g_tls_size + TlsPreTcbSize(), 16); | |
| 496 | 548 | #else |
| 497 | return g_tls_size; | |
| 549 | return 0; | |
| 498 | 550 | #endif |
| 499 | 551 | } |
| 500 | 552 | #endif |
| ... | ... | @@ -515,42 +567,33 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, |
| 515 | 567 | if (!main) { |
| 516 | 568 | // If stack and tls intersect, make them non-intersecting. |
| 517 | 569 | if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) { |
| 518 | CHECK_GT(*tls_addr + *tls_size, *stk_addr); | |
| 519 | CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size); | |
| 520 | *stk_size -= *tls_size; | |
| 521 | *tls_addr = *stk_addr + *stk_size; | |
| 570 | if (*stk_addr + *stk_size < *tls_addr + *tls_size) | |
| 571 | *tls_size = *stk_addr + *stk_size - *tls_addr; | |
| 572 | *stk_size = *tls_addr - *stk_addr; | |
| 522 | 573 | } |
| 523 | 574 | } |
| 524 | 575 | #endif |
| 525 | 576 | } |
| 526 | 577 | |
| 527 | #if !SANITIZER_FREEBSD && !SANITIZER_OPENBSD | |
| 578 | #if !SANITIZER_FREEBSD | |
| 528 | 579 | typedef ElfW(Phdr) Elf_Phdr; |
| 529 | #elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2 | |
| 580 | #elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2 | |
| 530 | 581 | #define Elf_Phdr XElf32_Phdr |
| 531 | 582 | #define dl_phdr_info xdl_phdr_info |
| 532 | 583 | #define dl_iterate_phdr(c, b) xdl_iterate_phdr((c), (b)) |
| 533 | #endif // !SANITIZER_FREEBSD && !SANITIZER_OPENBSD | |
| 584 | #endif // !SANITIZER_FREEBSD | |
| 534 | 585 | |
| 535 | 586 | struct DlIteratePhdrData { |
| 536 | 587 | InternalMmapVectorNoCtor<LoadedModule> *modules; |
| 537 | 588 | bool first; |
| 538 | 589 | }; |
| 539 | 590 | |
| 540 | static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { | |
| 541 | DlIteratePhdrData *data = (DlIteratePhdrData*)arg; | |
| 542 | InternalScopedString module_name(kMaxPathLength); | |
| 543 | if (data->first) { | |
| 544 | data->first = false; | |
| 545 | // First module is the binary itself. | |
| 546 | ReadBinaryNameCached(module_name.data(), module_name.size()); | |
| 547 | } else if (info->dlpi_name) { | |
| 548 | module_name.append("%s", info->dlpi_name); | |
| 549 | } | |
| 591 | static int AddModuleSegments(const char *module_name, dl_phdr_info *info, | |
| 592 | InternalMmapVectorNoCtor<LoadedModule> *modules) { | |
| 550 | 593 | if (module_name[0] == '\0') |
| 551 | 594 | return 0; |
| 552 | 595 | LoadedModule cur_module; |
| 553 | cur_module.set(module_name.data(), info->dlpi_addr); | |
| 596 | cur_module.set(module_name, info->dlpi_addr); | |
| 554 | 597 | for (int i = 0; i < (int)info->dlpi_phnum; i++) { |
| 555 | 598 | const Elf_Phdr *phdr = &info->dlpi_phdr[i]; |
| 556 | 599 | if (phdr->p_type == PT_LOAD) { |
| ... | ... | @@ -562,7 +605,26 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { |
| 562 | 605 | writable); |
| 563 | 606 | } |
| 564 | 607 | } |
| 565 | data->modules->push_back(cur_module); | |
| 608 | modules->push_back(cur_module); | |
| 609 | return 0; | |
| 610 | } | |
| 611 | ||
| 612 | static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { | |
| 613 | DlIteratePhdrData *data = (DlIteratePhdrData *)arg; | |
| 614 | if (data->first) { | |
| 615 | InternalMmapVector<char> module_name(kMaxPathLength); | |
| 616 | data->first = false; | |
| 617 | // First module is the binary itself. | |
| 618 | ReadBinaryNameCached(module_name.data(), module_name.size()); | |
| 619 | return AddModuleSegments(module_name.data(), info, data->modules); | |
| 620 | } | |
| 621 | ||
| 622 | if (info->dlpi_name) { | |
| 623 | InternalScopedString module_name; | |
| 624 | module_name.append("%s", info->dlpi_name); | |
| 625 | return AddModuleSegments(module_name.data(), info, data->modules); | |
| 626 | } | |
| 627 | ||
| 566 | 628 | return 0; |
| 567 | 629 | } |
| 568 | 630 | |
| ... | ... | @@ -650,7 +712,7 @@ uptr GetRSS() { |
| 650 | 712 | // sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used on most platforms as |
| 651 | 713 | // they allocate memory. |
| 652 | 714 | u32 GetNumberOfCPUs() { |
| 653 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD | |
| 715 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 654 | 716 | u32 ncpu; |
| 655 | 717 | int req[2]; |
| 656 | 718 | uptr len = sizeof(ncpu); |
| ... | ... | @@ -705,7 +767,7 @@ u32 GetNumberOfCPUs() { |
| 705 | 767 | |
| 706 | 768 | #if SANITIZER_LINUX |
| 707 | 769 | |
| 708 | # if SANITIZER_ANDROID | |
| 770 | #if SANITIZER_ANDROID | |
| 709 | 771 | static atomic_uint8_t android_log_initialized; |
| 710 | 772 | |
| 711 | 773 | void AndroidLogInit() { |
| ... | ... | @@ -749,7 +811,7 @@ void SetAbortMessage(const char *str) { |
| 749 | 811 | if (&android_set_abort_message) |
| 750 | 812 | android_set_abort_message(str); |
| 751 | 813 | } |
| 752 | # else | |
| 814 | #else | |
| 753 | 815 | void AndroidLogInit() {} |
| 754 | 816 | |
| 755 | 817 | static bool ShouldLogAfterPrintf() { return true; } |
| ... | ... | @@ -757,7 +819,7 @@ static bool ShouldLogAfterPrintf() { return true; } |
| 757 | 819 | void WriteOneLineToSyslog(const char *s) { syslog(LOG_INFO, "%s", s); } |
| 758 | 820 | |
| 759 | 821 | void SetAbortMessage(const char *str) {} |
| 760 | # endif // SANITIZER_ANDROID | |
| 822 | #endif // SANITIZER_ANDROID | |
| 761 | 823 | |
| 762 | 824 | void LogMessageOnPrintf(const char *str) { |
| 763 | 825 | if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) |
| ... | ... | @@ -766,20 +828,13 @@ void LogMessageOnPrintf(const char *str) { |
| 766 | 828 | |
| 767 | 829 | #endif // SANITIZER_LINUX |
| 768 | 830 | |
| 769 | #if SANITIZER_LINUX && !SANITIZER_GO | |
| 831 | #if SANITIZER_GLIBC && !SANITIZER_GO | |
| 770 | 832 | // glibc crashes when using clock_gettime from a preinit_array function as the |
| 771 | 833 | // vDSO function pointers haven't been initialized yet. __progname is |
| 772 | 834 | // initialized after the vDSO function pointers, so if it exists, is not null |
| 773 | 835 | // and is not empty, we can use clock_gettime. |
| 774 | 836 | extern "C" SANITIZER_WEAK_ATTRIBUTE char *__progname; |
| 775 | INLINE bool CanUseVDSO() { | |
| 776 | // Bionic is safe, it checks for the vDSO function pointers to be initialized. | |
| 777 | if (SANITIZER_ANDROID) | |
| 778 | return true; | |
| 779 | if (&__progname && __progname && *__progname) | |
| 780 | return true; | |
| 781 | return false; | |
| 782 | } | |
| 837 | inline bool CanUseVDSO() { return &__progname && __progname && *__progname; } | |
| 783 | 838 | |
| 784 | 839 | // MonotonicNanoTime is a timing function that can leverage the vDSO by calling |
| 785 | 840 | // clock_gettime. real_clock_gettime only exists if clock_gettime is |
| ... | ... | @@ -799,15 +854,14 @@ u64 MonotonicNanoTime() { |
| 799 | 854 | return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; |
| 800 | 855 | } |
| 801 | 856 | #else |
| 802 | // Non-Linux & Go always use the syscall. | |
| 857 | // Non-glibc & Go always use the regular function. | |
| 803 | 858 | u64 MonotonicNanoTime() { |
| 804 | 859 | timespec ts; |
| 805 | internal_clock_gettime(CLOCK_MONOTONIC, &ts); | |
| 860 | clock_gettime(CLOCK_MONOTONIC, &ts); | |
| 806 | 861 | return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; |
| 807 | 862 | } |
| 808 | #endif // SANITIZER_LINUX && !SANITIZER_GO | |
| 863 | #endif // SANITIZER_GLIBC && !SANITIZER_GO | |
| 809 | 864 | |
| 810 | #if !SANITIZER_OPENBSD | |
| 811 | 865 | void ReExec() { |
| 812 | 866 | const char *pathname = "/proc/self/exe"; |
| 813 | 867 | |
| ... | ... | @@ -839,7 +893,107 @@ void ReExec() { |
| 839 | 893 | Printf("execve failed, errno %d\n", rverrno); |
| 840 | 894 | Die(); |
| 841 | 895 | } |
| 842 | #endif // !SANITIZER_OPENBSD | |
| 896 | ||
| 897 | void UnmapFromTo(uptr from, uptr to) { | |
| 898 | if (to == from) | |
| 899 | return; | |
| 900 | CHECK(to >= from); | |
| 901 | uptr res = internal_munmap(reinterpret_cast<void *>(from), to - from); | |
| 902 | if (UNLIKELY(internal_iserror(res))) { | |
| 903 | Report("ERROR: %s failed to unmap 0x%zx (%zd) bytes at address %p\n", | |
| 904 | SanitizerToolName, to - from, to - from, (void *)from); | |
| 905 | CHECK("unable to unmap" && 0); | |
| 906 | } | |
| 907 | } | |
| 908 | ||
| 909 | uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale, | |
| 910 | uptr min_shadow_base_alignment, | |
| 911 | UNUSED uptr &high_mem_end) { | |
| 912 | const uptr granularity = GetMmapGranularity(); | |
| 913 | const uptr alignment = | |
| 914 | Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment); | |
| 915 | const uptr left_padding = | |
| 916 | Max<uptr>(granularity, 1ULL << min_shadow_base_alignment); | |
| 917 | ||
| 918 | const uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity); | |
| 919 | const uptr map_size = shadow_size + left_padding + alignment; | |
| 920 | ||
| 921 | const uptr map_start = (uptr)MmapNoAccess(map_size); | |
| 922 | CHECK_NE(map_start, ~(uptr)0); | |
| 923 | ||
| 924 | const uptr shadow_start = RoundUpTo(map_start + left_padding, alignment); | |
| 925 | ||
| 926 | UnmapFromTo(map_start, shadow_start - left_padding); | |
| 927 | UnmapFromTo(shadow_start + shadow_size, map_start + map_size); | |
| 928 | ||
| 929 | return shadow_start; | |
| 930 | } | |
| 931 | ||
| 932 | static uptr MmapSharedNoReserve(uptr addr, uptr size) { | |
| 933 | return internal_mmap( | |
| 934 | reinterpret_cast<void *>(addr), size, PROT_READ | PROT_WRITE, | |
| 935 | MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); | |
| 936 | } | |
| 937 | ||
| 938 | static uptr MremapCreateAlias(uptr base_addr, uptr alias_addr, | |
| 939 | uptr alias_size) { | |
| 940 | #if SANITIZER_LINUX | |
| 941 | return internal_mremap(reinterpret_cast<void *>(base_addr), 0, alias_size, | |
| 942 | MREMAP_MAYMOVE | MREMAP_FIXED, | |
| 943 | reinterpret_cast<void *>(alias_addr)); | |
| 944 | #else | |
| 945 | CHECK(false && "mremap is not supported outside of Linux"); | |
| 946 | return 0; | |
| 947 | #endif | |
| 948 | } | |
| 949 | ||
| 950 | static void CreateAliases(uptr start_addr, uptr alias_size, uptr num_aliases) { | |
| 951 | uptr total_size = alias_size * num_aliases; | |
| 952 | uptr mapped = MmapSharedNoReserve(start_addr, total_size); | |
| 953 | CHECK_EQ(mapped, start_addr); | |
| 954 | ||
| 955 | for (uptr i = 1; i < num_aliases; ++i) { | |
| 956 | uptr alias_addr = start_addr + i * alias_size; | |
| 957 | CHECK_EQ(MremapCreateAlias(start_addr, alias_addr, alias_size), alias_addr); | |
| 958 | } | |
| 959 | } | |
| 960 | ||
| 961 | uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size, | |
| 962 | uptr num_aliases, uptr ring_buffer_size) { | |
| 963 | CHECK_EQ(alias_size & (alias_size - 1), 0); | |
| 964 | CHECK_EQ(num_aliases & (num_aliases - 1), 0); | |
| 965 | CHECK_EQ(ring_buffer_size & (ring_buffer_size - 1), 0); | |
| 966 | ||
| 967 | const uptr granularity = GetMmapGranularity(); | |
| 968 | shadow_size = RoundUpTo(shadow_size, granularity); | |
| 969 | CHECK_EQ(shadow_size & (shadow_size - 1), 0); | |
| 970 | ||
| 971 | const uptr alias_region_size = alias_size * num_aliases; | |
| 972 | const uptr alignment = | |
| 973 | 2 * Max(Max(shadow_size, alias_region_size), ring_buffer_size); | |
| 974 | const uptr left_padding = ring_buffer_size; | |
| 975 | ||
| 976 | const uptr right_size = alignment; | |
| 977 | const uptr map_size = left_padding + 2 * alignment; | |
| 978 | ||
| 979 | const uptr map_start = reinterpret_cast<uptr>(MmapNoAccess(map_size)); | |
| 980 | CHECK_NE(map_start, static_cast<uptr>(-1)); | |
| 981 | const uptr right_start = RoundUpTo(map_start + left_padding, alignment); | |
| 982 | ||
| 983 | UnmapFromTo(map_start, right_start - left_padding); | |
| 984 | UnmapFromTo(right_start + right_size, map_start + map_size); | |
| 985 | ||
| 986 | CreateAliases(right_start + right_size / 2, alias_size, num_aliases); | |
| 987 | ||
| 988 | return right_start; | |
| 989 | } | |
| 990 | ||
| 991 | void InitializePlatformCommonFlags(CommonFlags *cf) { | |
| 992 | #if SANITIZER_ANDROID | |
| 993 | if (&__libc_get_static_tls_bounds == nullptr) | |
| 994 | cf->detect_leaks = false; | |
| 995 | #endif | |
| 996 | } | |
| 843 | 997 | |
| 844 | 998 | } // namespace __sanitizer |
| 845 | 999 |
lib/tsan/sanitizer_common/sanitizer_local_address_space_view.h+1-1| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | // |
| 9 | 9 | // `LocalAddressSpaceView` provides the local (i.e. target and current address |
| 10 | // space are the same) implementation of the `AddressSpaveView` interface which | |
| 10 | // space are the same) implementation of the `AddressSpaceView` interface which | |
| 11 | 11 | // provides a simple interface to load memory from another process (i.e. |
| 12 | 12 | // out-of-process) |
| 13 | 13 | // |
lib/tsan/sanitizer_common/sanitizer_mac.cpp+265-55| ... | ... | @@ -44,6 +44,14 @@ extern char **environ; |
| 44 | 44 | #define SANITIZER_OS_TRACE 0 |
| 45 | 45 | #endif |
| 46 | 46 | |
| 47 | // import new crash reporting api | |
| 48 | #if defined(__has_include) && __has_include(<CrashReporterClient.h>) | |
| 49 | #define HAVE_CRASHREPORTERCLIENT_H 1 | |
| 50 | #include <CrashReporterClient.h> | |
| 51 | #else | |
| 52 | #define HAVE_CRASHREPORTERCLIENT_H 0 | |
| 53 | #endif | |
| 54 | ||
| 47 | 55 | #if !SANITIZER_IOS |
| 48 | 56 | #include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron |
| 49 | 57 | #else |
| ... | ... | @@ -62,6 +70,7 @@ extern "C" { |
| 62 | 70 | #include <mach/mach_time.h> |
| 63 | 71 | #include <mach/vm_statistics.h> |
| 64 | 72 | #include <malloc/malloc.h> |
| 73 | #include <os/log.h> | |
| 65 | 74 | #include <pthread.h> |
| 66 | 75 | #include <sched.h> |
| 67 | 76 | #include <signal.h> |
| ... | ... | @@ -133,10 +142,20 @@ uptr internal_munmap(void *addr, uptr length) { |
| 133 | 142 | return munmap(addr, length); |
| 134 | 143 | } |
| 135 | 144 | |
| 145 | uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags, | |
| 146 | void *new_address) { | |
| 147 | CHECK(false && "internal_mremap is unimplemented on Mac"); | |
| 148 | return 0; | |
| 149 | } | |
| 150 | ||
| 136 | 151 | int internal_mprotect(void *addr, uptr length, int prot) { |
| 137 | 152 | return mprotect(addr, length, prot); |
| 138 | 153 | } |
| 139 | 154 | |
| 155 | int internal_madvise(uptr addr, uptr length, int advice) { | |
| 156 | return madvise((void *)addr, length, advice); | |
| 157 | } | |
| 158 | ||
| 140 | 159 | uptr internal_close(fd_t fd) { |
| 141 | 160 | return close(fd); |
| 142 | 161 | } |
| ... | ... | @@ -200,9 +219,7 @@ void internal__exit(int exitcode) { |
| 200 | 219 | _exit(exitcode); |
| 201 | 220 | } |
| 202 | 221 | |
| 203 | unsigned int internal_sleep(unsigned int seconds) { | |
| 204 | return sleep(seconds); | |
| 205 | } | |
| 222 | void internal_usleep(u64 useconds) { usleep(useconds); } | |
| 206 | 223 | |
| 207 | 224 | uptr internal_getpid() { |
| 208 | 225 | return getpid(); |
| ... | ... | @@ -440,7 +457,7 @@ uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { |
| 440 | 457 | // On OS X the executable path is saved to the stack by dyld. Reading it |
| 441 | 458 | // from there is much faster than calling dladdr, especially for large |
| 442 | 459 | // binaries with symbols. |
| 443 | InternalScopedString exe_path(kMaxPathLength); | |
| 460 | InternalMmapVector<char> exe_path(kMaxPathLength); | |
| 444 | 461 | uint32_t size = exe_path.size(); |
| 445 | 462 | if (_NSGetExecutablePath(exe_path.data(), &size) == 0 && |
| 446 | 463 | realpath(exe_path.data(), buf) != 0) { |
| ... | ... | @@ -492,6 +509,13 @@ void MprotectMallocZones(void *addr, int prot) { |
| 492 | 509 | } |
| 493 | 510 | } |
| 494 | 511 | |
| 512 | void FutexWait(atomic_uint32_t *p, u32 cmp) { | |
| 513 | // FIXME: implement actual blocking. | |
| 514 | sched_yield(); | |
| 515 | } | |
| 516 | ||
| 517 | void FutexWake(atomic_uint32_t *p, u32 count) {} | |
| 518 | ||
| 495 | 519 | BlockingMutex::BlockingMutex() { |
| 496 | 520 | internal_memset(this, 0, sizeof(*this)); |
| 497 | 521 | } |
| ... | ... | @@ -507,8 +531,8 @@ void BlockingMutex::Unlock() { |
| 507 | 531 | OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); |
| 508 | 532 | } |
| 509 | 533 | |
| 510 | void BlockingMutex::CheckLocked() { | |
| 511 | CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0); | |
| 534 | void BlockingMutex::CheckLocked() const { | |
| 535 | CHECK_NE(*(const OSSpinLock*)&opaque_storage_, 0); | |
| 512 | 536 | } |
| 513 | 537 | |
| 514 | 538 | u64 NanoTime() { |
| ... | ... | @@ -606,21 +630,103 @@ HandleSignalMode GetHandleSignalMode(int signum) { |
| 606 | 630 | return result; |
| 607 | 631 | } |
| 608 | 632 | |
| 609 | // This corresponds to Triple::getMacOSXVersion() in the Clang driver. | |
| 610 | static MacosVersion GetMacosAlignedVersionInternal() { | |
| 633 | // Offset example: | |
| 634 | // XNU 17 -- macOS 10.13 -- iOS 11 -- tvOS 11 -- watchOS 4 | |
| 635 | constexpr u16 GetOSMajorKernelOffset() { | |
| 636 | if (TARGET_OS_OSX) return 4; | |
| 637 | if (TARGET_OS_IOS || TARGET_OS_TV) return 6; | |
| 638 | if (TARGET_OS_WATCH) return 13; | |
| 639 | } | |
| 640 | ||
| 641 | using VersStr = char[64]; | |
| 642 | ||
| 643 | static uptr ApproximateOSVersionViaKernelVersion(VersStr vers) { | |
| 611 | 644 | u16 kernel_major = GetDarwinKernelVersion().major; |
| 612 | // Darwin 0-3 -> unsupported | |
| 613 | // Darwin 4-19 -> macOS 10.x | |
| 614 | // Darwin 20+ -> macOS 11+ | |
| 615 | CHECK_GE(kernel_major, 4); | |
| 616 | u16 major, minor; | |
| 617 | if (kernel_major < 20) { | |
| 618 | major = 10; | |
| 619 | minor = kernel_major - 4; | |
| 645 | u16 offset = GetOSMajorKernelOffset(); | |
| 646 | CHECK_GE(kernel_major, offset); | |
| 647 | u16 os_major = kernel_major - offset; | |
| 648 | ||
| 649 | const char *format = "%d.0"; | |
| 650 | if (TARGET_OS_OSX) { | |
| 651 | if (os_major >= 16) { // macOS 11+ | |
| 652 | os_major -= 5; | |
| 653 | } else { // macOS 10.15 and below | |
| 654 | format = "10.%d"; | |
| 655 | } | |
| 656 | } | |
| 657 | return internal_snprintf(vers, sizeof(VersStr), format, os_major); | |
| 658 | } | |
| 659 | ||
| 660 | static void GetOSVersion(VersStr vers) { | |
| 661 | uptr len = sizeof(VersStr); | |
| 662 | if (SANITIZER_IOSSIM) { | |
| 663 | const char *vers_env = GetEnv("SIMULATOR_RUNTIME_VERSION"); | |
| 664 | if (!vers_env) { | |
| 665 | Report("ERROR: Running in simulator but SIMULATOR_RUNTIME_VERSION env " | |
| 666 | "var is not set.\n"); | |
| 667 | Die(); | |
| 668 | } | |
| 669 | len = internal_strlcpy(vers, vers_env, len); | |
| 620 | 670 | } else { |
| 621 | major = 11 + kernel_major - 20; | |
| 622 | minor = 0; | |
| 671 | int res = | |
| 672 | internal_sysctlbyname("kern.osproductversion", vers, &len, nullptr, 0); | |
| 673 | ||
| 674 | // XNU 17 (macOS 10.13) and below do not provide the sysctl | |
| 675 | // `kern.osproductversion` entry (res != 0). | |
| 676 | bool no_os_version = res != 0; | |
| 677 | ||
| 678 | // For launchd, sanitizer initialization runs before sysctl is setup | |
| 679 | // (res == 0 && len != strlen(vers), vers is not a valid version). However, | |
| 680 | // the kernel version `kern.osrelease` is available. | |
| 681 | bool launchd = (res == 0 && internal_strlen(vers) < 3); | |
| 682 | if (launchd) CHECK_EQ(internal_getpid(), 1); | |
| 683 | ||
| 684 | if (no_os_version || launchd) { | |
| 685 | len = ApproximateOSVersionViaKernelVersion(vers); | |
| 686 | } | |
| 687 | } | |
| 688 | CHECK_LT(len, sizeof(VersStr)); | |
| 689 | } | |
| 690 | ||
| 691 | void ParseVersion(const char *vers, u16 *major, u16 *minor) { | |
| 692 | // Format: <major>.<minor>[.<patch>]\0 | |
| 693 | CHECK_GE(internal_strlen(vers), 3); | |
| 694 | const char *p = vers; | |
| 695 | *major = internal_simple_strtoll(p, &p, /*base=*/10); | |
| 696 | CHECK_EQ(*p, '.'); | |
| 697 | p += 1; | |
| 698 | *minor = internal_simple_strtoll(p, &p, /*base=*/10); | |
| 699 | } | |
| 700 | ||
| 701 | // Aligned versions example: | |
| 702 | // macOS 10.15 -- iOS 13 -- tvOS 13 -- watchOS 6 | |
| 703 | static void MapToMacos(u16 *major, u16 *minor) { | |
| 704 | if (TARGET_OS_OSX) | |
| 705 | return; | |
| 706 | ||
| 707 | if (TARGET_OS_IOS || TARGET_OS_TV) | |
| 708 | *major += 2; | |
| 709 | else if (TARGET_OS_WATCH) | |
| 710 | *major += 9; | |
| 711 | else | |
| 712 | UNREACHABLE("unsupported platform"); | |
| 713 | ||
| 714 | if (*major >= 16) { // macOS 11+ | |
| 715 | *major -= 5; | |
| 716 | } else { // macOS 10.15 and below | |
| 717 | *minor = *major; | |
| 718 | *major = 10; | |
| 623 | 719 | } |
| 720 | } | |
| 721 | ||
| 722 | static MacosVersion GetMacosAlignedVersionInternal() { | |
| 723 | VersStr vers = {}; | |
| 724 | GetOSVersion(vers); | |
| 725 | ||
| 726 | u16 major, minor; | |
| 727 | ParseVersion(vers, &major, &minor); | |
| 728 | MapToMacos(&major, &minor); | |
| 729 | ||
| 624 | 730 | return MacosVersion(major, minor); |
| 625 | 731 | } |
| 626 | 732 | |
| ... | ... | @@ -639,24 +745,15 @@ MacosVersion GetMacosAlignedVersion() { |
| 639 | 745 | return *reinterpret_cast<MacosVersion *>(&result); |
| 640 | 746 | } |
| 641 | 747 | |
| 642 | void ParseVersion(const char *vers, u16 *major, u16 *minor) { | |
| 643 | // Format: <major>.<minor>.<patch>\0 | |
| 644 | CHECK_GE(internal_strlen(vers), 5); | |
| 645 | const char *p = vers; | |
| 646 | *major = internal_simple_strtoll(p, &p, /*base=*/10); | |
| 647 | CHECK_EQ(*p, '.'); | |
| 648 | p += 1; | |
| 649 | *minor = internal_simple_strtoll(p, &p, /*base=*/10); | |
| 650 | } | |
| 651 | ||
| 652 | 748 | DarwinKernelVersion GetDarwinKernelVersion() { |
| 653 | char buf[100]; | |
| 654 | size_t len = sizeof(buf); | |
| 655 | int res = internal_sysctlbyname("kern.osrelease", buf, &len, nullptr, 0); | |
| 749 | VersStr vers = {}; | |
| 750 | uptr len = sizeof(VersStr); | |
| 751 | int res = internal_sysctlbyname("kern.osrelease", vers, &len, nullptr, 0); | |
| 656 | 752 | CHECK_EQ(res, 0); |
| 753 | CHECK_LT(len, sizeof(VersStr)); | |
| 657 | 754 | |
| 658 | 755 | u16 major, minor; |
| 659 | ParseVersion(buf, &major, &minor); | |
| 756 | ParseVersion(vers, &major, &minor); | |
| 660 | 757 | |
| 661 | 758 | return DarwinKernelVersion(major, minor); |
| 662 | 759 | } |
| ... | ... | @@ -693,7 +790,51 @@ static BlockingMutex syslog_lock(LINKER_INITIALIZED); |
| 693 | 790 | void WriteOneLineToSyslog(const char *s) { |
| 694 | 791 | #if !SANITIZER_GO |
| 695 | 792 | syslog_lock.CheckLocked(); |
| 696 | asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); | |
| 793 | if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) { | |
| 794 | os_log_error(OS_LOG_DEFAULT, "%{public}s", s); | |
| 795 | } else { | |
| 796 | asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); | |
| 797 | } | |
| 798 | #endif | |
| 799 | } | |
| 800 | ||
| 801 | // buffer to store crash report application information | |
| 802 | static char crashreporter_info_buff[__sanitizer::kErrorMessageBufferSize] = {}; | |
| 803 | static BlockingMutex crashreporter_info_mutex(LINKER_INITIALIZED); | |
| 804 | ||
| 805 | extern "C" { | |
| 806 | // Integrate with crash reporter libraries. | |
| 807 | #if HAVE_CRASHREPORTERCLIENT_H | |
| 808 | CRASH_REPORTER_CLIENT_HIDDEN | |
| 809 | struct crashreporter_annotations_t gCRAnnotations | |
| 810 | __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) = { | |
| 811 | CRASHREPORTER_ANNOTATIONS_VERSION, | |
| 812 | 0, | |
| 813 | 0, | |
| 814 | 0, | |
| 815 | 0, | |
| 816 | 0, | |
| 817 | 0, | |
| 818 | #if CRASHREPORTER_ANNOTATIONS_VERSION > 4 | |
| 819 | 0, | |
| 820 | #endif | |
| 821 | }; | |
| 822 | ||
| 823 | #else | |
| 824 | // fall back to old crashreporter api | |
| 825 | static const char *__crashreporter_info__ __attribute__((__used__)) = | |
| 826 | &crashreporter_info_buff[0]; | |
| 827 | asm(".desc ___crashreporter_info__, 0x10"); | |
| 828 | #endif | |
| 829 | ||
| 830 | } // extern "C" | |
| 831 | ||
| 832 | static void CRAppendCrashLogMessage(const char *msg) { | |
| 833 | BlockingMutexLock l(&crashreporter_info_mutex); | |
| 834 | internal_strlcat(crashreporter_info_buff, msg, | |
| 835 | sizeof(crashreporter_info_buff)); | |
| 836 | #if HAVE_CRASHREPORTERCLIENT_H | |
| 837 | (void)CRSetCrashLogMessage(crashreporter_info_buff); | |
| 697 | 838 | #endif |
| 698 | 839 | } |
| 699 | 840 | |
| ... | ... | @@ -796,6 +937,19 @@ void SignalContext::InitPcSpBp() { |
| 796 | 937 | GetPcSpBp(context, &pc, &sp, &bp); |
| 797 | 938 | } |
| 798 | 939 | |
| 940 | // ASan/TSan use mmap in a way that creates “deallocation gaps” which triggers | |
| 941 | // EXC_GUARD exceptions on macOS 10.15+ (XNU 19.0+). | |
| 942 | static void DisableMmapExcGuardExceptions() { | |
| 943 | using task_exc_guard_behavior_t = uint32_t; | |
| 944 | using task_set_exc_guard_behavior_t = | |
| 945 | kern_return_t(task_t task, task_exc_guard_behavior_t behavior); | |
| 946 | auto *set_behavior = (task_set_exc_guard_behavior_t *)dlsym( | |
| 947 | RTLD_DEFAULT, "task_set_exc_guard_behavior"); | |
| 948 | if (set_behavior == nullptr) return; | |
| 949 | const task_exc_guard_behavior_t task_exc_guard_none = 0; | |
| 950 | set_behavior(mach_task_self(), task_exc_guard_none); | |
| 951 | } | |
| 952 | ||
| 799 | 953 | void InitializePlatformEarly() { |
| 800 | 954 | // Only use xnu_fast_mmap when on x86_64 and the kernel supports it. |
| 801 | 955 | use_xnu_fast_mmap = |
| ... | ... | @@ -804,6 +958,8 @@ void InitializePlatformEarly() { |
| 804 | 958 | #else |
| 805 | 959 | false; |
| 806 | 960 | #endif |
| 961 | if (GetDarwinKernelVersion() >= DarwinKernelVersion(19, 0)) | |
| 962 | DisableMmapExcGuardExceptions(); | |
| 807 | 963 | } |
| 808 | 964 | |
| 809 | 965 | #if !SANITIZER_GO |
| ... | ... | @@ -844,20 +1000,10 @@ bool ReexecDisabled() { |
| 844 | 1000 | return false; |
| 845 | 1001 | } |
| 846 | 1002 | |
| 847 | extern "C" SANITIZER_WEAK_ATTRIBUTE double dyldVersionNumber; | |
| 848 | static const double kMinDyldVersionWithAutoInterposition = 360.0; | |
| 849 | ||
| 850 | bool DyldNeedsEnvVariable() { | |
| 851 | // Although sanitizer support was added to LLVM on OS X 10.7+, GCC users | |
| 852 | // still may want use them on older systems. On older Darwin platforms, dyld | |
| 853 | // doesn't export dyldVersionNumber symbol and we simply return true. | |
| 854 | if (!&dyldVersionNumber) return true; | |
| 1003 | static bool DyldNeedsEnvVariable() { | |
| 855 | 1004 | // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if |
| 856 | // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via | |
| 857 | // GetMacosAlignedVersion() doesn't work for the simulator. Let's instead | |
| 858 | // check `dyldVersionNumber`, which is exported by dyld, against a known | |
| 859 | // version number from the first OS release where this appeared. | |
| 860 | return dyldVersionNumber < kMinDyldVersionWithAutoInterposition; | |
| 1005 | // DYLD_INSERT_LIBRARIES is not set. | |
| 1006 | return GetMacosAlignedVersion() < MacosVersion(10, 11); | |
| 861 | 1007 | } |
| 862 | 1008 | |
| 863 | 1009 | void MaybeReexec() { |
| ... | ... | @@ -884,7 +1030,7 @@ void MaybeReexec() { |
| 884 | 1030 | if (DyldNeedsEnvVariable() && !lib_is_in_env) { |
| 885 | 1031 | // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime |
| 886 | 1032 | // library. |
| 887 | InternalScopedString program_name(1024); | |
| 1033 | InternalMmapVector<char> program_name(1024); | |
| 888 | 1034 | uint32_t buf_size = program_name.size(); |
| 889 | 1035 | _NSGetExecutablePath(program_name.data(), &buf_size); |
| 890 | 1036 | char *new_env = const_cast<char*>(info.dli_fname); |
| ... | ... | @@ -1003,7 +1149,7 @@ char **GetArgv() { |
| 1003 | 1149 | return *_NSGetArgv(); |
| 1004 | 1150 | } |
| 1005 | 1151 | |
| 1006 | #if SANITIZER_IOS | |
| 1152 | #if SANITIZER_IOS && !SANITIZER_IOSSIM | |
| 1007 | 1153 | // The task_vm_info struct is normally provided by the macOS SDK, but we need |
| 1008 | 1154 | // fields only available in 10.12+. Declare the struct manually to be able to |
| 1009 | 1155 | // build against older SDKs. |
| ... | ... | @@ -1043,26 +1189,35 @@ static uptr GetTaskInfoMaxAddress() { |
| 1043 | 1189 | |
| 1044 | 1190 | uptr GetMaxUserVirtualAddress() { |
| 1045 | 1191 | static uptr max_vm = GetTaskInfoMaxAddress(); |
| 1046 | if (max_vm != 0) | |
| 1047 | return max_vm - 1; | |
| 1192 | if (max_vm != 0) { | |
| 1193 | const uptr ret_value = max_vm - 1; | |
| 1194 | CHECK_LE(ret_value, SANITIZER_MMAP_RANGE_SIZE); | |
| 1195 | return ret_value; | |
| 1196 | } | |
| 1048 | 1197 | |
| 1049 | 1198 | // xnu cannot provide vm address limit |
| 1050 | 1199 | # if SANITIZER_WORDSIZE == 32 |
| 1051 | return 0xffe00000 - 1; | |
| 1200 | constexpr uptr fallback_max_vm = 0xffe00000 - 1; | |
| 1052 | 1201 | # else |
| 1053 | return 0x200000000 - 1; | |
| 1202 | constexpr uptr fallback_max_vm = 0x200000000 - 1; | |
| 1054 | 1203 | # endif |
| 1204 | static_assert(fallback_max_vm <= SANITIZER_MMAP_RANGE_SIZE, | |
| 1205 | "Max virtual address must be less than mmap range size."); | |
| 1206 | return fallback_max_vm; | |
| 1055 | 1207 | } |
| 1056 | 1208 | |
| 1057 | 1209 | #else // !SANITIZER_IOS |
| 1058 | 1210 | |
| 1059 | 1211 | uptr GetMaxUserVirtualAddress() { |
| 1060 | 1212 | # if SANITIZER_WORDSIZE == 64 |
| 1061 | return (1ULL << 47) - 1; // 0x00007fffffffffffUL; | |
| 1213 | constexpr uptr max_vm = (1ULL << 47) - 1; // 0x00007fffffffffffUL; | |
| 1062 | 1214 | # else // SANITIZER_WORDSIZE == 32 |
| 1063 | 1215 | static_assert(SANITIZER_WORDSIZE == 32, "Wrong wordsize"); |
| 1064 | return (1ULL << 32) - 1; // 0xffffffff; | |
| 1216 | constexpr uptr max_vm = (1ULL << 32) - 1; // 0xffffffff; | |
| 1065 | 1217 | # endif |
| 1218 | static_assert(max_vm <= SANITIZER_MMAP_RANGE_SIZE, | |
| 1219 | "Max virtual address must be less than mmap range size."); | |
| 1220 | return max_vm; | |
| 1066 | 1221 | } |
| 1067 | 1222 | #endif |
| 1068 | 1223 | |
| ... | ... | @@ -1070,6 +1225,59 @@ uptr GetMaxVirtualAddress() { |
| 1070 | 1225 | return GetMaxUserVirtualAddress(); |
| 1071 | 1226 | } |
| 1072 | 1227 | |
| 1228 | uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale, | |
| 1229 | uptr min_shadow_base_alignment, uptr &high_mem_end) { | |
| 1230 | const uptr granularity = GetMmapGranularity(); | |
| 1231 | const uptr alignment = | |
| 1232 | Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment); | |
| 1233 | const uptr left_padding = | |
| 1234 | Max<uptr>(granularity, 1ULL << min_shadow_base_alignment); | |
| 1235 | ||
| 1236 | uptr space_size = shadow_size_bytes + left_padding; | |
| 1237 | ||
| 1238 | uptr largest_gap_found = 0; | |
| 1239 | uptr max_occupied_addr = 0; | |
| 1240 | VReport(2, "FindDynamicShadowStart, space_size = %p\n", space_size); | |
| 1241 | uptr shadow_start = | |
| 1242 | FindAvailableMemoryRange(space_size, alignment, granularity, | |
| 1243 | &largest_gap_found, &max_occupied_addr); | |
| 1244 | // If the shadow doesn't fit, restrict the address space to make it fit. | |
| 1245 | if (shadow_start == 0) { | |
| 1246 | VReport( | |
| 1247 | 2, | |
| 1248 | "Shadow doesn't fit, largest_gap_found = %p, max_occupied_addr = %p\n", | |
| 1249 | largest_gap_found, max_occupied_addr); | |
| 1250 | uptr new_max_vm = RoundDownTo(largest_gap_found << shadow_scale, alignment); | |
| 1251 | if (new_max_vm < max_occupied_addr) { | |
| 1252 | Report("Unable to find a memory range for dynamic shadow.\n"); | |
| 1253 | Report( | |
| 1254 | "space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, " | |
| 1255 | "new_max_vm = %p\n", | |
| 1256 | space_size, largest_gap_found, max_occupied_addr, new_max_vm); | |
| 1257 | CHECK(0 && "cannot place shadow"); | |
| 1258 | } | |
| 1259 | RestrictMemoryToMaxAddress(new_max_vm); | |
| 1260 | high_mem_end = new_max_vm - 1; | |
| 1261 | space_size = (high_mem_end >> shadow_scale) + left_padding; | |
| 1262 | VReport(2, "FindDynamicShadowStart, space_size = %p\n", space_size); | |
| 1263 | shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity, | |
| 1264 | nullptr, nullptr); | |
| 1265 | if (shadow_start == 0) { | |
| 1266 | Report("Unable to find a memory range after restricting VM.\n"); | |
| 1267 | CHECK(0 && "cannot place shadow after restricting vm"); | |
| 1268 | } | |
| 1269 | } | |
| 1270 | CHECK_NE((uptr)0, shadow_start); | |
| 1271 | CHECK(IsAligned(shadow_start, alignment)); | |
| 1272 | return shadow_start; | |
| 1273 | } | |
| 1274 | ||
| 1275 | uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size, | |
| 1276 | uptr num_aliases, uptr ring_buffer_size) { | |
| 1277 | CHECK(false && "HWASan aliasing is unimplemented on Mac"); | |
| 1278 | return 0; | |
| 1279 | } | |
| 1280 | ||
| 1073 | 1281 | uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, |
| 1074 | 1282 | uptr *largest_gap_found, |
| 1075 | 1283 | uptr *max_occupied_addr) { |
| ... | ... | @@ -1190,7 +1398,7 @@ void FormatUUID(char *out, uptr size, const u8 *uuid) { |
| 1190 | 1398 | uuid[12], uuid[13], uuid[14], uuid[15]); |
| 1191 | 1399 | } |
| 1192 | 1400 | |
| 1193 | void PrintModuleMap() { | |
| 1401 | void DumpProcessMap() { | |
| 1194 | 1402 | Printf("Process module map:\n"); |
| 1195 | 1403 | MemoryMappingLayout memory_mapping(false); |
| 1196 | 1404 | InternalMmapVector<LoadedModule> modules; |
| ... | ... | @@ -1223,6 +1431,8 @@ u32 GetNumberOfCPUs() { |
| 1223 | 1431 | return (u32)sysconf(_SC_NPROCESSORS_ONLN); |
| 1224 | 1432 | } |
| 1225 | 1433 | |
| 1434 | void InitializePlatformCommonFlags(CommonFlags *cf) {} | |
| 1435 | ||
| 1226 | 1436 | } // namespace __sanitizer |
| 1227 | 1437 | |
| 1228 | 1438 | #endif // SANITIZER_MAC |
lib/tsan/sanitizer_common/sanitizer_mac.h+1-17| ... | ... | @@ -44,6 +44,7 @@ struct VersionBase { |
| 44 | 44 | return major > other.major || |
| 45 | 45 | (major == other.major && minor >= other.minor); |
| 46 | 46 | } |
| 47 | bool operator<(const VersionType &other) const { return !(*this >= other); } | |
| 47 | 48 | }; |
| 48 | 49 | |
| 49 | 50 | struct MacosVersion : VersionBase<MacosVersion> { |
| ... | ... | @@ -63,22 +64,5 @@ void RestrictMemoryToMaxAddress(uptr max_address); |
| 63 | 64 | |
| 64 | 65 | } // namespace __sanitizer |
| 65 | 66 | |
| 66 | extern "C" { | |
| 67 | static char __crashreporter_info_buff__[__sanitizer::kErrorMessageBufferSize] = | |
| 68 | {}; | |
| 69 | static const char *__crashreporter_info__ __attribute__((__used__)) = | |
| 70 | &__crashreporter_info_buff__[0]; | |
| 71 | asm(".desc ___crashreporter_info__, 0x10"); | |
| 72 | } // extern "C" | |
| 73 | ||
| 74 | namespace __sanitizer { | |
| 75 | static BlockingMutex crashreporter_info_mutex(LINKER_INITIALIZED); | |
| 76 | ||
| 77 | INLINE void CRAppendCrashLogMessage(const char *msg) { | |
| 78 | BlockingMutexLock l(&crashreporter_info_mutex); | |
| 79 | internal_strlcat(__crashreporter_info_buff__, msg, | |
| 80 | sizeof(__crashreporter_info_buff__)); } | |
| 81 | } // namespace __sanitizer | |
| 82 | ||
| 83 | 67 | #endif // SANITIZER_MAC |
| 84 | 68 | #endif // SANITIZER_MAC_H |
lib/tsan/sanitizer_common/sanitizer_malloc_mac.inc+1-5| ... | ... | @@ -120,11 +120,7 @@ INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { |
| 120 | 120 | |
| 121 | 121 | INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { |
| 122 | 122 | COMMON_MALLOC_ENTER(); |
| 123 | // Allocate |sizeof(COMMON_MALLOC_ZONE_NAME "-") + internal_strlen(name)| | |
| 124 | // bytes. | |
| 125 | size_t buflen = | |
| 126 | sizeof(COMMON_MALLOC_ZONE_NAME "-") + (name ? internal_strlen(name) : 0); | |
| 127 | InternalScopedString new_name(buflen); | |
| 123 | InternalScopedString new_name; | |
| 128 | 124 | if (name && zone->introspect == sanitizer_zone.introspect) { |
| 129 | 125 | new_name.append(COMMON_MALLOC_ZONE_NAME "-%s", name); |
| 130 | 126 | name = new_name.data(); |
lib/tsan/sanitizer_common/sanitizer_mutex.cpp created+225| ... | ... | @@ -0,0 +1,225 @@ |
| 1 | //===-- sanitizer_mutex.cpp -----------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is shared between AddressSanitizer and ThreadSanitizer | |
| 10 | // run-time libraries. | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | ||
| 13 | #include "sanitizer_mutex.h" | |
| 14 | ||
| 15 | #include "sanitizer_common.h" | |
| 16 | ||
| 17 | namespace __sanitizer { | |
| 18 | ||
| 19 | void StaticSpinMutex::LockSlow() { | |
| 20 | for (int i = 0;; i++) { | |
| 21 | if (i < 100) | |
| 22 | proc_yield(1); | |
| 23 | else | |
| 24 | internal_sched_yield(); | |
| 25 | if (atomic_load(&state_, memory_order_relaxed) == 0 && | |
| 26 | atomic_exchange(&state_, 1, memory_order_acquire) == 0) | |
| 27 | return; | |
| 28 | } | |
| 29 | } | |
| 30 | ||
| 31 | void Semaphore::Wait() { | |
| 32 | u32 count = atomic_load(&state_, memory_order_relaxed); | |
| 33 | for (;;) { | |
| 34 | if (count == 0) { | |
| 35 | FutexWait(&state_, 0); | |
| 36 | count = atomic_load(&state_, memory_order_relaxed); | |
| 37 | continue; | |
| 38 | } | |
| 39 | if (atomic_compare_exchange_weak(&state_, &count, count - 1, | |
| 40 | memory_order_acquire)) | |
| 41 | break; | |
| 42 | } | |
| 43 | } | |
| 44 | ||
| 45 | void Semaphore::Post(u32 count) { | |
| 46 | CHECK_NE(count, 0); | |
| 47 | atomic_fetch_add(&state_, count, memory_order_release); | |
| 48 | FutexWake(&state_, count); | |
| 49 | } | |
| 50 | ||
| 51 | #if SANITIZER_CHECK_DEADLOCKS | |
| 52 | // An empty mutex meta table, it effectively disables deadlock detection. | |
| 53 | // Each tool can override the table to define own mutex hierarchy and | |
| 54 | // enable deadlock detection. | |
| 55 | // The table defines a static mutex type hierarchy (what mutex types can be locked | |
| 56 | // under what mutex types). This table is checked to be acyclic and then | |
| 57 | // actual mutex lock/unlock operations are checked to adhere to this hierarchy. | |
| 58 | // The checking happens on mutex types rather than on individual mutex instances | |
| 59 | // because doing it on mutex instances will both significantly complicate | |
| 60 | // the implementation, worsen performance and memory overhead and is mostly | |
| 61 | // unnecessary (we almost never lock multiple mutexes of the same type recursively). | |
| 62 | static constexpr int kMutexTypeMax = 20; | |
| 63 | SANITIZER_WEAK_ATTRIBUTE MutexMeta mutex_meta[kMutexTypeMax] = {}; | |
| 64 | SANITIZER_WEAK_ATTRIBUTE void PrintMutexPC(uptr pc) {} | |
| 65 | static StaticSpinMutex mutex_meta_mtx; | |
| 66 | static int mutex_type_count = -1; | |
| 67 | // Adjacency matrix of what mutexes can be locked under what mutexes. | |
| 68 | static bool mutex_can_lock[kMutexTypeMax][kMutexTypeMax]; | |
| 69 | // Mutex types with MutexMulti mark. | |
| 70 | static bool mutex_multi[kMutexTypeMax]; | |
| 71 | ||
| 72 | void DebugMutexInit() { | |
| 73 | // Build adjacency matrix. | |
| 74 | bool leaf[kMutexTypeMax]; | |
| 75 | internal_memset(&leaf, 0, sizeof(leaf)); | |
| 76 | int cnt[kMutexTypeMax] = {}; | |
| 77 | internal_memset(&cnt, 0, sizeof(cnt)); | |
| 78 | for (int t = 0; t < kMutexTypeMax; t++) { | |
| 79 | mutex_type_count = t; | |
| 80 | if (!mutex_meta[t].name) | |
| 81 | break; | |
| 82 | CHECK_EQ(t, mutex_meta[t].type); | |
| 83 | for (uptr j = 0; j < ARRAY_SIZE(mutex_meta[t].can_lock); j++) { | |
| 84 | MutexType z = mutex_meta[t].can_lock[j]; | |
| 85 | if (z == MutexInvalid) | |
| 86 | break; | |
| 87 | if (z == MutexLeaf) { | |
| 88 | CHECK(!leaf[t]); | |
| 89 | leaf[t] = true; | |
| 90 | continue; | |
| 91 | } | |
| 92 | if (z == MutexMulti) { | |
| 93 | mutex_multi[t] = true; | |
| 94 | continue; | |
| 95 | } | |
| 96 | CHECK_LT(z, kMutexTypeMax); | |
| 97 | CHECK(!mutex_can_lock[t][z]); | |
| 98 | mutex_can_lock[t][z] = true; | |
| 99 | cnt[t]++; | |
| 100 | } | |
| 101 | } | |
| 102 | // Indicates the array is not properly terminated. | |
| 103 | CHECK_LT(mutex_type_count, kMutexTypeMax); | |
| 104 | // Add leaf mutexes. | |
| 105 | for (int t = 0; t < mutex_type_count; t++) { | |
| 106 | if (!leaf[t]) | |
| 107 | continue; | |
| 108 | CHECK_EQ(cnt[t], 0); | |
| 109 | for (int z = 0; z < mutex_type_count; z++) { | |
| 110 | if (z == MutexInvalid || t == z || leaf[z]) | |
| 111 | continue; | |
| 112 | CHECK(!mutex_can_lock[z][t]); | |
| 113 | mutex_can_lock[z][t] = true; | |
| 114 | } | |
| 115 | } | |
| 116 | // Build the transitive closure and check that the graphs is acyclic. | |
| 117 | u32 trans[kMutexTypeMax]; | |
| 118 | static_assert(sizeof(trans[0]) * 8 >= kMutexTypeMax, | |
| 119 | "kMutexTypeMax does not fit into u32, switch to u64"); | |
| 120 | internal_memset(&trans, 0, sizeof(trans)); | |
| 121 | for (int i = 0; i < mutex_type_count; i++) { | |
| 122 | for (int j = 0; j < mutex_type_count; j++) | |
| 123 | if (mutex_can_lock[i][j]) | |
| 124 | trans[i] |= 1 << j; | |
| 125 | } | |
| 126 | for (int k = 0; k < mutex_type_count; k++) { | |
| 127 | for (int i = 0; i < mutex_type_count; i++) { | |
| 128 | if (trans[i] & (1 << k)) | |
| 129 | trans[i] |= trans[k]; | |
| 130 | } | |
| 131 | } | |
| 132 | for (int i = 0; i < mutex_type_count; i++) { | |
| 133 | if (trans[i] & (1 << i)) { | |
| 134 | Printf("Mutex %s participates in a cycle\n", mutex_meta[i].name); | |
| 135 | Die(); | |
| 136 | } | |
| 137 | } | |
| 138 | } | |
| 139 | ||
| 140 | struct InternalDeadlockDetector { | |
| 141 | struct LockDesc { | |
| 142 | u64 seq; | |
| 143 | uptr pc; | |
| 144 | int recursion; | |
| 145 | }; | |
| 146 | int initialized; | |
| 147 | u64 sequence; | |
| 148 | LockDesc locked[kMutexTypeMax]; | |
| 149 | ||
| 150 | void Lock(MutexType type, uptr pc) { | |
| 151 | if (!Initialize(type)) | |
| 152 | return; | |
| 153 | CHECK_LT(type, mutex_type_count); | |
| 154 | // Find the last locked mutex type. | |
| 155 | // This is the type we will use for hierarchy checks. | |
| 156 | u64 max_seq = 0; | |
| 157 | MutexType max_idx = MutexInvalid; | |
| 158 | for (int i = 0; i != mutex_type_count; i++) { | |
| 159 | if (locked[i].seq == 0) | |
| 160 | continue; | |
| 161 | CHECK_NE(locked[i].seq, max_seq); | |
| 162 | if (max_seq < locked[i].seq) { | |
| 163 | max_seq = locked[i].seq; | |
| 164 | max_idx = (MutexType)i; | |
| 165 | } | |
| 166 | } | |
| 167 | if (max_idx == type && mutex_multi[type]) { | |
| 168 | // Recursive lock of the same type. | |
| 169 | CHECK_EQ(locked[type].seq, max_seq); | |
| 170 | CHECK(locked[type].pc); | |
| 171 | locked[type].recursion++; | |
| 172 | return; | |
| 173 | } | |
| 174 | if (max_idx != MutexInvalid && !mutex_can_lock[max_idx][type]) { | |
| 175 | Printf("%s: internal deadlock: can't lock %s under %s mutex\n", SanitizerToolName, | |
| 176 | mutex_meta[type].name, mutex_meta[max_idx].name); | |
| 177 | PrintMutexPC(pc); | |
| 178 | CHECK(0); | |
| 179 | } | |
| 180 | locked[type].seq = ++sequence; | |
| 181 | locked[type].pc = pc; | |
| 182 | locked[type].recursion = 1; | |
| 183 | } | |
| 184 | ||
| 185 | void Unlock(MutexType type) { | |
| 186 | if (!Initialize(type)) | |
| 187 | return; | |
| 188 | CHECK_LT(type, mutex_type_count); | |
| 189 | CHECK(locked[type].seq); | |
| 190 | CHECK_GT(locked[type].recursion, 0); | |
| 191 | if (--locked[type].recursion) | |
| 192 | return; | |
| 193 | locked[type].seq = 0; | |
| 194 | locked[type].pc = 0; | |
| 195 | } | |
| 196 | ||
| 197 | void CheckNoLocks() { | |
| 198 | for (int i = 0; i < mutex_type_count; i++) CHECK_EQ(locked[i].recursion, 0); | |
| 199 | } | |
| 200 | ||
| 201 | bool Initialize(MutexType type) { | |
| 202 | if (type == MutexUnchecked || type == MutexInvalid) | |
| 203 | return false; | |
| 204 | CHECK_GT(type, MutexInvalid); | |
| 205 | if (initialized != 0) | |
| 206 | return initialized > 0; | |
| 207 | initialized = -1; | |
| 208 | SpinMutexLock lock(&mutex_meta_mtx); | |
| 209 | if (mutex_type_count < 0) | |
| 210 | DebugMutexInit(); | |
| 211 | initialized = mutex_type_count ? 1 : -1; | |
| 212 | return initialized > 0; | |
| 213 | } | |
| 214 | }; | |
| 215 | ||
| 216 | static THREADLOCAL InternalDeadlockDetector deadlock_detector; | |
| 217 | ||
| 218 | void CheckedMutex::LockImpl(uptr pc) { deadlock_detector.Lock(type_, pc); } | |
| 219 | ||
| 220 | void CheckedMutex::UnlockImpl() { deadlock_detector.Unlock(type_); } | |
| 221 | ||
| 222 | void CheckedMutex::CheckNoLocksImpl() { deadlock_detector.CheckNoLocks(); } | |
| 223 | #endif | |
| 224 | ||
| 225 | } // namespace __sanitizer |
lib/tsan/sanitizer_common/sanitizer_mutex.h+316-52| ... | ... | @@ -16,67 +16,335 @@ |
| 16 | 16 | #include "sanitizer_atomic.h" |
| 17 | 17 | #include "sanitizer_internal_defs.h" |
| 18 | 18 | #include "sanitizer_libc.h" |
| 19 | #include "sanitizer_thread_safety.h" | |
| 19 | 20 | |
| 20 | 21 | namespace __sanitizer { |
| 21 | 22 | |
| 22 | class StaticSpinMutex { | |
| 23 | class MUTEX StaticSpinMutex { | |
| 23 | 24 | public: |
| 24 | 25 | void Init() { |
| 25 | 26 | atomic_store(&state_, 0, memory_order_relaxed); |
| 26 | 27 | } |
| 27 | 28 | |
| 28 | void Lock() { | |
| 29 | if (TryLock()) | |
| 29 | void Lock() ACQUIRE() { | |
| 30 | if (LIKELY(TryLock())) | |
| 30 | 31 | return; |
| 31 | 32 | LockSlow(); |
| 32 | 33 | } |
| 33 | 34 | |
| 34 | bool TryLock() { | |
| 35 | bool TryLock() TRY_ACQUIRE(true) { | |
| 35 | 36 | return atomic_exchange(&state_, 1, memory_order_acquire) == 0; |
| 36 | 37 | } |
| 37 | 38 | |
| 38 | void Unlock() { | |
| 39 | atomic_store(&state_, 0, memory_order_release); | |
| 40 | } | |
| 39 | void Unlock() RELEASE() { atomic_store(&state_, 0, memory_order_release); } | |
| 41 | 40 | |
| 42 | void CheckLocked() { | |
| 41 | void CheckLocked() const CHECK_LOCKED() { | |
| 43 | 42 | CHECK_EQ(atomic_load(&state_, memory_order_relaxed), 1); |
| 44 | 43 | } |
| 45 | 44 | |
| 46 | 45 | private: |
| 47 | 46 | atomic_uint8_t state_; |
| 48 | 47 | |
| 49 | void NOINLINE LockSlow() { | |
| 50 | for (int i = 0;; i++) { | |
| 51 | if (i < 10) | |
| 52 | proc_yield(10); | |
| 53 | else | |
| 54 | internal_sched_yield(); | |
| 55 | if (atomic_load(&state_, memory_order_relaxed) == 0 | |
| 56 | && atomic_exchange(&state_, 1, memory_order_acquire) == 0) | |
| 57 | return; | |
| 58 | } | |
| 59 | } | |
| 48 | void LockSlow(); | |
| 60 | 49 | }; |
| 61 | 50 | |
| 62 | class SpinMutex : public StaticSpinMutex { | |
| 51 | class MUTEX SpinMutex : public StaticSpinMutex { | |
| 63 | 52 | public: |
| 64 | 53 | SpinMutex() { |
| 65 | 54 | Init(); |
| 66 | 55 | } |
| 67 | 56 | |
| 57 | SpinMutex(const SpinMutex &) = delete; | |
| 58 | void operator=(const SpinMutex &) = delete; | |
| 59 | }; | |
| 60 | ||
| 61 | // Semaphore provides an OS-dependent way to park/unpark threads. | |
| 62 | // The last thread returned from Wait can destroy the object | |
| 63 | // (destruction-safety). | |
| 64 | class Semaphore { | |
| 65 | public: | |
| 66 | constexpr Semaphore() {} | |
| 67 | Semaphore(const Semaphore &) = delete; | |
| 68 | void operator=(const Semaphore &) = delete; | |
| 69 | ||
| 70 | void Wait(); | |
| 71 | void Post(u32 count = 1); | |
| 72 | ||
| 68 | 73 | private: |
| 69 | SpinMutex(const SpinMutex&); | |
| 70 | void operator=(const SpinMutex&); | |
| 74 | atomic_uint32_t state_ = {0}; | |
| 71 | 75 | }; |
| 72 | 76 | |
| 73 | class BlockingMutex { | |
| 77 | typedef int MutexType; | |
| 78 | ||
| 79 | enum { | |
| 80 | // Used as sentinel and to catch unassigned types | |
| 81 | // (should not be used as real Mutex type). | |
| 82 | MutexInvalid = 0, | |
| 83 | MutexThreadRegistry, | |
| 84 | // Each tool own mutexes must start at this number. | |
| 85 | MutexLastCommon, | |
| 86 | // Type for legacy mutexes that are not checked for deadlocks. | |
| 87 | MutexUnchecked = -1, | |
| 88 | // Special marks that can be used in MutexMeta::can_lock table. | |
| 89 | // The leaf mutexes can be locked under any other non-leaf mutex, | |
| 90 | // but no other mutex can be locked while under a leaf mutex. | |
| 91 | MutexLeaf = -1, | |
| 92 | // Multiple mutexes of this type can be locked at the same time. | |
| 93 | MutexMulti = -3, | |
| 94 | }; | |
| 95 | ||
| 96 | // Go linker does not support THREADLOCAL variables, | |
| 97 | // so we can't use per-thread state. | |
| 98 | #define SANITIZER_CHECK_DEADLOCKS (SANITIZER_DEBUG && !SANITIZER_GO) | |
| 99 | ||
| 100 | #if SANITIZER_CHECK_DEADLOCKS | |
| 101 | struct MutexMeta { | |
| 102 | MutexType type; | |
| 103 | const char *name; | |
| 104 | // The table fixes what mutexes can be locked under what mutexes. | |
| 105 | // If the entry for MutexTypeFoo contains MutexTypeBar, | |
| 106 | // then Bar mutex can be locked while under Foo mutex. | |
| 107 | // Can also contain the special MutexLeaf/MutexMulti marks. | |
| 108 | MutexType can_lock[10]; | |
| 109 | }; | |
| 110 | #endif | |
| 111 | ||
| 112 | class CheckedMutex { | |
| 113 | public: | |
| 114 | constexpr CheckedMutex(MutexType type) | |
| 115 | #if SANITIZER_CHECK_DEADLOCKS | |
| 116 | : type_(type) | |
| 117 | #endif | |
| 118 | { | |
| 119 | } | |
| 120 | ||
| 121 | ALWAYS_INLINE void Lock() { | |
| 122 | #if SANITIZER_CHECK_DEADLOCKS | |
| 123 | LockImpl(GET_CALLER_PC()); | |
| 124 | #endif | |
| 125 | } | |
| 126 | ||
| 127 | ALWAYS_INLINE void Unlock() { | |
| 128 | #if SANITIZER_CHECK_DEADLOCKS | |
| 129 | UnlockImpl(); | |
| 130 | #endif | |
| 131 | } | |
| 132 | ||
| 133 | // Checks that the current thread does not hold any mutexes | |
| 134 | // (e.g. when returning from a runtime function to user code). | |
| 135 | static void CheckNoLocks() { | |
| 136 | #if SANITIZER_CHECK_DEADLOCKS | |
| 137 | CheckNoLocksImpl(); | |
| 138 | #endif | |
| 139 | } | |
| 140 | ||
| 141 | private: | |
| 142 | #if SANITIZER_CHECK_DEADLOCKS | |
| 143 | const MutexType type_; | |
| 144 | ||
| 145 | void LockImpl(uptr pc); | |
| 146 | void UnlockImpl(); | |
| 147 | static void CheckNoLocksImpl(); | |
| 148 | #endif | |
| 149 | }; | |
| 150 | ||
| 151 | // Reader-writer mutex. | |
| 152 | // Derive from CheckedMutex for the purposes of EBO. | |
| 153 | // We could make it a field marked with [[no_unique_address]], | |
| 154 | // but this attribute is not supported by some older compilers. | |
| 155 | class MUTEX Mutex : CheckedMutex { | |
| 156 | public: | |
| 157 | constexpr Mutex(MutexType type = MutexUnchecked) : CheckedMutex(type) {} | |
| 158 | ||
| 159 | void Lock() ACQUIRE() { | |
| 160 | CheckedMutex::Lock(); | |
| 161 | u64 reset_mask = ~0ull; | |
| 162 | u64 state = atomic_load_relaxed(&state_); | |
| 163 | const uptr kMaxSpinIters = 1500; | |
| 164 | for (uptr spin_iters = 0;; spin_iters++) { | |
| 165 | u64 new_state; | |
| 166 | bool locked = (state & (kWriterLock | kReaderLockMask)) != 0; | |
| 167 | if (LIKELY(!locked)) { | |
| 168 | // The mutex is not read-/write-locked, try to lock. | |
| 169 | new_state = (state | kWriterLock) & reset_mask; | |
| 170 | } else if (spin_iters > kMaxSpinIters) { | |
| 171 | // We've spun enough, increment waiting writers count and block. | |
| 172 | // The counter will be decremented by whoever wakes us. | |
| 173 | new_state = (state + kWaitingWriterInc) & reset_mask; | |
| 174 | } else if ((state & kWriterSpinWait) == 0) { | |
| 175 | // Active spinning, but denote our presence so that unlocking | |
| 176 | // thread does not wake up other threads. | |
| 177 | new_state = state | kWriterSpinWait; | |
| 178 | } else { | |
| 179 | // Active spinning. | |
| 180 | state = atomic_load(&state_, memory_order_relaxed); | |
| 181 | continue; | |
| 182 | } | |
| 183 | if (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state, | |
| 184 | memory_order_acquire))) | |
| 185 | continue; | |
| 186 | if (LIKELY(!locked)) | |
| 187 | return; // We've locked the mutex. | |
| 188 | if (spin_iters > kMaxSpinIters) { | |
| 189 | // We've incremented waiting writers, so now block. | |
| 190 | writers_.Wait(); | |
| 191 | spin_iters = 0; | |
| 192 | state = atomic_load(&state_, memory_order_relaxed); | |
| 193 | DCHECK_NE(state & kWriterSpinWait, 0); | |
| 194 | } else { | |
| 195 | // We've set kWriterSpinWait, but we are still in active spinning. | |
| 196 | } | |
| 197 | // We either blocked and were unblocked, | |
| 198 | // or we just spun but set kWriterSpinWait. | |
| 199 | // Either way we need to reset kWriterSpinWait | |
| 200 | // next time we take the lock or block again. | |
| 201 | reset_mask = ~kWriterSpinWait; | |
| 202 | } | |
| 203 | } | |
| 204 | ||
| 205 | void Unlock() RELEASE() { | |
| 206 | CheckedMutex::Unlock(); | |
| 207 | bool wake_writer; | |
| 208 | u64 wake_readers; | |
| 209 | u64 new_state; | |
| 210 | u64 state = atomic_load_relaxed(&state_); | |
| 211 | do { | |
| 212 | DCHECK_NE(state & kWriterLock, 0); | |
| 213 | DCHECK_EQ(state & kReaderLockMask, 0); | |
| 214 | new_state = state & ~kWriterLock; | |
| 215 | wake_writer = | |
| 216 | (state & kWriterSpinWait) == 0 && (state & kWaitingWriterMask) != 0; | |
| 217 | if (wake_writer) | |
| 218 | new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait; | |
| 219 | wake_readers = | |
| 220 | (state & (kWriterSpinWait | kWaitingWriterMask)) != 0 | |
| 221 | ? 0 | |
| 222 | : ((state & kWaitingReaderMask) >> kWaitingReaderShift); | |
| 223 | if (wake_readers) | |
| 224 | new_state = (new_state & ~kWaitingReaderMask) + | |
| 225 | (wake_readers << kReaderLockShift); | |
| 226 | } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state, | |
| 227 | memory_order_release))); | |
| 228 | if (UNLIKELY(wake_writer)) | |
| 229 | writers_.Post(); | |
| 230 | else if (UNLIKELY(wake_readers)) | |
| 231 | readers_.Post(wake_readers); | |
| 232 | } | |
| 233 | ||
| 234 | void ReadLock() ACQUIRE_SHARED() { | |
| 235 | CheckedMutex::Lock(); | |
| 236 | bool locked; | |
| 237 | u64 new_state; | |
| 238 | u64 state = atomic_load_relaxed(&state_); | |
| 239 | do { | |
| 240 | locked = | |
| 241 | (state & kReaderLockMask) == 0 && | |
| 242 | (state & (kWriterLock | kWriterSpinWait | kWaitingWriterMask)) != 0; | |
| 243 | if (LIKELY(!locked)) | |
| 244 | new_state = state + kReaderLockInc; | |
| 245 | else | |
| 246 | new_state = state + kWaitingReaderInc; | |
| 247 | } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state, | |
| 248 | memory_order_acquire))); | |
| 249 | if (UNLIKELY(locked)) | |
| 250 | readers_.Wait(); | |
| 251 | DCHECK_EQ(atomic_load_relaxed(&state_) & kWriterLock, 0); | |
| 252 | DCHECK_NE(atomic_load_relaxed(&state_) & kReaderLockMask, 0); | |
| 253 | } | |
| 254 | ||
| 255 | void ReadUnlock() RELEASE_SHARED() { | |
| 256 | CheckedMutex::Unlock(); | |
| 257 | bool wake; | |
| 258 | u64 new_state; | |
| 259 | u64 state = atomic_load_relaxed(&state_); | |
| 260 | do { | |
| 261 | DCHECK_NE(state & kReaderLockMask, 0); | |
| 262 | DCHECK_EQ(state & (kWaitingReaderMask | kWriterLock), 0); | |
| 263 | new_state = state - kReaderLockInc; | |
| 264 | wake = (new_state & (kReaderLockMask | kWriterSpinWait)) == 0 && | |
| 265 | (new_state & kWaitingWriterMask) != 0; | |
| 266 | if (wake) | |
| 267 | new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait; | |
| 268 | } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state, | |
| 269 | memory_order_release))); | |
| 270 | if (UNLIKELY(wake)) | |
| 271 | writers_.Post(); | |
| 272 | } | |
| 273 | ||
| 274 | // This function does not guarantee an explicit check that the calling thread | |
| 275 | // is the thread which owns the mutex. This behavior, while more strictly | |
| 276 | // correct, causes problems in cases like StopTheWorld, where a parent thread | |
| 277 | // owns the mutex but a child checks that it is locked. Rather than | |
| 278 | // maintaining complex state to work around those situations, the check only | |
| 279 | // checks that the mutex is owned. | |
| 280 | void CheckWriteLocked() const CHECK_LOCKED() { | |
| 281 | CHECK(atomic_load(&state_, memory_order_relaxed) & kWriterLock); | |
| 282 | } | |
| 283 | ||
| 284 | void CheckLocked() const CHECK_LOCKED() { CheckWriteLocked(); } | |
| 285 | ||
| 286 | void CheckReadLocked() const CHECK_LOCKED() { | |
| 287 | CHECK(atomic_load(&state_, memory_order_relaxed) & kReaderLockMask); | |
| 288 | } | |
| 289 | ||
| 290 | private: | |
| 291 | atomic_uint64_t state_ = {0}; | |
| 292 | Semaphore writers_; | |
| 293 | Semaphore readers_; | |
| 294 | ||
| 295 | // The state has 3 counters: | |
| 296 | // - number of readers holding the lock, | |
| 297 | // if non zero, the mutex is read-locked | |
| 298 | // - number of waiting readers, | |
| 299 | // if not zero, the mutex is write-locked | |
| 300 | // - number of waiting writers, | |
| 301 | // if non zero, the mutex is read- or write-locked | |
| 302 | // And 2 flags: | |
| 303 | // - writer lock | |
| 304 | // if set, the mutex is write-locked | |
| 305 | // - a writer is awake and spin-waiting | |
| 306 | // the flag is used to prevent thundering herd problem | |
| 307 | // (new writers are not woken if this flag is set) | |
| 308 | // | |
| 309 | // Writer support active spinning, readers does not. | |
| 310 | // But readers are more aggressive and always take the mutex | |
| 311 | // if there are any other readers. | |
| 312 | // Writers hand off the mutex to readers: after wake up readers | |
| 313 | // already assume ownership of the mutex (don't need to do any | |
| 314 | // state updates). But the mutex is not handed off to writers, | |
| 315 | // after wake up writers compete to lock the mutex again. | |
| 316 | // This is needed to allow repeated write locks even in presence | |
| 317 | // of other blocked writers. | |
| 318 | static constexpr u64 kCounterWidth = 20; | |
| 319 | static constexpr u64 kReaderLockShift = 0; | |
| 320 | static constexpr u64 kReaderLockInc = 1ull << kReaderLockShift; | |
| 321 | static constexpr u64 kReaderLockMask = ((1ull << kCounterWidth) - 1) | |
| 322 | << kReaderLockShift; | |
| 323 | static constexpr u64 kWaitingReaderShift = kCounterWidth; | |
| 324 | static constexpr u64 kWaitingReaderInc = 1ull << kWaitingReaderShift; | |
| 325 | static constexpr u64 kWaitingReaderMask = ((1ull << kCounterWidth) - 1) | |
| 326 | << kWaitingReaderShift; | |
| 327 | static constexpr u64 kWaitingWriterShift = 2 * kCounterWidth; | |
| 328 | static constexpr u64 kWaitingWriterInc = 1ull << kWaitingWriterShift; | |
| 329 | static constexpr u64 kWaitingWriterMask = ((1ull << kCounterWidth) - 1) | |
| 330 | << kWaitingWriterShift; | |
| 331 | static constexpr u64 kWriterLock = 1ull << (3 * kCounterWidth); | |
| 332 | static constexpr u64 kWriterSpinWait = 1ull << (3 * kCounterWidth + 1); | |
| 333 | ||
| 334 | Mutex(const Mutex &) = delete; | |
| 335 | void operator=(const Mutex &) = delete; | |
| 336 | }; | |
| 337 | ||
| 338 | void FutexWait(atomic_uint32_t *p, u32 cmp); | |
| 339 | void FutexWake(atomic_uint32_t *p, u32 count); | |
| 340 | ||
| 341 | class MUTEX BlockingMutex { | |
| 74 | 342 | public: |
| 75 | 343 | explicit constexpr BlockingMutex(LinkerInitialized) |
| 76 | 344 | : opaque_storage_ {0, }, owner_ {0} {} |
| 77 | 345 | BlockingMutex(); |
| 78 | void Lock(); | |
| 79 | void Unlock(); | |
| 346 | void Lock() ACQUIRE(); | |
| 347 | void Unlock() RELEASE(); | |
| 80 | 348 | |
| 81 | 349 | // This function does not guarantee an explicit check that the calling thread |
| 82 | 350 | // is the thread which owns the mutex. This behavior, while more strictly |
| ... | ... | @@ -85,7 +353,7 @@ class BlockingMutex { |
| 85 | 353 | // maintaining complex state to work around those situations, the check only |
| 86 | 354 | // checks that the mutex is owned, and assumes callers to be generally |
| 87 | 355 | // well-behaved. |
| 88 | void CheckLocked(); | |
| 356 | void CheckLocked() const CHECK_LOCKED(); | |
| 89 | 357 | |
| 90 | 358 | private: |
| 91 | 359 | // Solaris mutex_t has a member that requires 64-bit alignment. |
| ... | ... | @@ -94,7 +362,7 @@ class BlockingMutex { |
| 94 | 362 | }; |
| 95 | 363 | |
| 96 | 364 | // Reader-writer spin mutex. |
| 97 | class RWMutex { | |
| 365 | class MUTEX RWMutex { | |
| 98 | 366 | public: |
| 99 | 367 | RWMutex() { |
| 100 | 368 | atomic_store(&state_, kUnlocked, memory_order_relaxed); |
| ... | ... | @@ -104,7 +372,7 @@ class RWMutex { |
| 104 | 372 | CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked); |
| 105 | 373 | } |
| 106 | 374 | |
| 107 | void Lock() { | |
| 375 | void Lock() ACQUIRE() { | |
| 108 | 376 | u32 cmp = kUnlocked; |
| 109 | 377 | if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock, |
| 110 | 378 | memory_order_acquire)) |
| ... | ... | @@ -112,27 +380,27 @@ class RWMutex { |
| 112 | 380 | LockSlow(); |
| 113 | 381 | } |
| 114 | 382 | |
| 115 | void Unlock() { | |
| 383 | void Unlock() RELEASE() { | |
| 116 | 384 | u32 prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release); |
| 117 | 385 | DCHECK_NE(prev & kWriteLock, 0); |
| 118 | 386 | (void)prev; |
| 119 | 387 | } |
| 120 | 388 | |
| 121 | void ReadLock() { | |
| 389 | void ReadLock() ACQUIRE_SHARED() { | |
| 122 | 390 | u32 prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire); |
| 123 | 391 | if ((prev & kWriteLock) == 0) |
| 124 | 392 | return; |
| 125 | 393 | ReadLockSlow(); |
| 126 | 394 | } |
| 127 | 395 | |
| 128 | void ReadUnlock() { | |
| 396 | void ReadUnlock() RELEASE_SHARED() { | |
| 129 | 397 | u32 prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release); |
| 130 | 398 | DCHECK_EQ(prev & kWriteLock, 0); |
| 131 | 399 | DCHECK_GT(prev & ~kWriteLock, 0); |
| 132 | 400 | (void)prev; |
| 133 | 401 | } |
| 134 | 402 | |
| 135 | void CheckLocked() { | |
| 403 | void CheckLocked() const CHECK_LOCKED() { | |
| 136 | 404 | CHECK_NE(atomic_load(&state_, memory_order_relaxed), kUnlocked); |
| 137 | 405 | } |
| 138 | 406 | |
| ... | ... | @@ -171,52 +439,48 @@ class RWMutex { |
| 171 | 439 | } |
| 172 | 440 | } |
| 173 | 441 | |
| 174 | RWMutex(const RWMutex&); | |
| 175 | void operator = (const RWMutex&); | |
| 442 | RWMutex(const RWMutex &) = delete; | |
| 443 | void operator=(const RWMutex &) = delete; | |
| 176 | 444 | }; |
| 177 | 445 | |
| 178 | template<typename MutexType> | |
| 179 | class GenericScopedLock { | |
| 446 | template <typename MutexType> | |
| 447 | class SCOPED_LOCK GenericScopedLock { | |
| 180 | 448 | public: |
| 181 | explicit GenericScopedLock(MutexType *mu) | |
| 182 | : mu_(mu) { | |
| 449 | explicit GenericScopedLock(MutexType *mu) ACQUIRE(mu) : mu_(mu) { | |
| 183 | 450 | mu_->Lock(); |
| 184 | 451 | } |
| 185 | 452 | |
| 186 | ~GenericScopedLock() { | |
| 187 | mu_->Unlock(); | |
| 188 | } | |
| 453 | ~GenericScopedLock() RELEASE() { mu_->Unlock(); } | |
| 189 | 454 | |
| 190 | 455 | private: |
| 191 | 456 | MutexType *mu_; |
| 192 | 457 | |
| 193 | GenericScopedLock(const GenericScopedLock&); | |
| 194 | void operator=(const GenericScopedLock&); | |
| 458 | GenericScopedLock(const GenericScopedLock &) = delete; | |
| 459 | void operator=(const GenericScopedLock &) = delete; | |
| 195 | 460 | }; |
| 196 | 461 | |
| 197 | template<typename MutexType> | |
| 198 | class GenericScopedReadLock { | |
| 462 | template <typename MutexType> | |
| 463 | class SCOPED_LOCK GenericScopedReadLock { | |
| 199 | 464 | public: |
| 200 | explicit GenericScopedReadLock(MutexType *mu) | |
| 201 | : mu_(mu) { | |
| 465 | explicit GenericScopedReadLock(MutexType *mu) ACQUIRE(mu) : mu_(mu) { | |
| 202 | 466 | mu_->ReadLock(); |
| 203 | 467 | } |
| 204 | 468 | |
| 205 | ~GenericScopedReadLock() { | |
| 206 | mu_->ReadUnlock(); | |
| 207 | } | |
| 469 | ~GenericScopedReadLock() RELEASE() { mu_->ReadUnlock(); } | |
| 208 | 470 | |
| 209 | 471 | private: |
| 210 | 472 | MutexType *mu_; |
| 211 | 473 | |
| 212 | GenericScopedReadLock(const GenericScopedReadLock&); | |
| 213 | void operator=(const GenericScopedReadLock&); | |
| 474 | GenericScopedReadLock(const GenericScopedReadLock &) = delete; | |
| 475 | void operator=(const GenericScopedReadLock &) = delete; | |
| 214 | 476 | }; |
| 215 | 477 | |
| 216 | 478 | typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock; |
| 217 | 479 | typedef GenericScopedLock<BlockingMutex> BlockingMutexLock; |
| 218 | 480 | typedef GenericScopedLock<RWMutex> RWMutexLock; |
| 219 | 481 | typedef GenericScopedReadLock<RWMutex> RWMutexReadLock; |
| 482 | typedef GenericScopedLock<Mutex> Lock; | |
| 483 | typedef GenericScopedReadLock<Mutex> ReadLock; | |
| 220 | 484 | |
| 221 | 485 | } // namespace __sanitizer |
| 222 | 486 |
lib/tsan/sanitizer_common/sanitizer_netbsd.cpp+15-7| ... | ... | @@ -105,11 +105,22 @@ uptr internal_munmap(void *addr, uptr length) { |
| 105 | 105 | return _REAL(munmap, addr, length); |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags, | |
| 109 | void *new_address) { | |
| 110 | CHECK(false && "internal_mremap is unimplemented on NetBSD"); | |
| 111 | return 0; | |
| 112 | } | |
| 113 | ||
| 108 | 114 | int internal_mprotect(void *addr, uptr length, int prot) { |
| 109 | 115 | DEFINE__REAL(int, mprotect, void *a, uptr b, int c); |
| 110 | 116 | return _REAL(mprotect, addr, length, prot); |
| 111 | 117 | } |
| 112 | 118 | |
| 119 | int internal_madvise(uptr addr, uptr length, int advice) { | |
| 120 | DEFINE__REAL(int, madvise, void *a, uptr b, int c); | |
| 121 | return _REAL(madvise, (void *)addr, length, advice); | |
| 122 | } | |
| 123 | ||
| 113 | 124 | uptr internal_close(fd_t fd) { |
| 114 | 125 | CHECK(&_sys_close); |
| 115 | 126 | return _sys_close(fd); |
| ... | ... | @@ -204,15 +215,12 @@ void internal__exit(int exitcode) { |
| 204 | 215 | Die(); // Unreachable. |
| 205 | 216 | } |
| 206 | 217 | |
| 207 | unsigned int internal_sleep(unsigned int seconds) { | |
| 218 | void internal_usleep(u64 useconds) { | |
| 208 | 219 | struct timespec ts; |
| 209 | ts.tv_sec = seconds; | |
| 210 | ts.tv_nsec = 0; | |
| 220 | ts.tv_sec = useconds / 1000000; | |
| 221 | ts.tv_nsec = (useconds % 1000000) * 1000; | |
| 211 | 222 | CHECK(&_sys___nanosleep50); |
| 212 | int res = _sys___nanosleep50(&ts, &ts); | |
| 213 | if (res) | |
| 214 | return ts.tv_sec; | |
| 215 | return 0; | |
| 223 | _sys___nanosleep50(&ts, &ts); | |
| 216 | 224 | } |
| 217 | 225 | |
| 218 | 226 | uptr internal_execve(const char *filename, char *const argv[], |
lib/tsan/sanitizer_common/sanitizer_openbsd.cpp-115| ... | ... | @@ -1,115 +0,0 @@ |
| 1 | //===-- sanitizer_openbsd.cpp ---------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is shared between various sanitizers' runtime libraries and | |
| 10 | // implements Solaris-specific functions. | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | ||
| 13 | #include "sanitizer_platform.h" | |
| 14 | #if SANITIZER_OPENBSD | |
| 15 | ||
| 16 | #include <stdio.h> | |
| 17 | ||
| 18 | #include "sanitizer_common.h" | |
| 19 | #include "sanitizer_flags.h" | |
| 20 | #include "sanitizer_internal_defs.h" | |
| 21 | #include "sanitizer_libc.h" | |
| 22 | #include "sanitizer_placement_new.h" | |
| 23 | #include "sanitizer_platform_limits_posix.h" | |
| 24 | #include "sanitizer_procmaps.h" | |
| 25 | ||
| 26 | #include <errno.h> | |
| 27 | #include <fcntl.h> | |
| 28 | #include <limits.h> | |
| 29 | #include <pthread.h> | |
| 30 | #include <sched.h> | |
| 31 | #include <signal.h> | |
| 32 | #include <stdio.h> | |
| 33 | #include <stdlib.h> | |
| 34 | #include <sys/mman.h> | |
| 35 | #include <sys/shm.h> | |
| 36 | #include <sys/sysctl.h> | |
| 37 | #include <sys/types.h> | |
| 38 | #include <unistd.h> | |
| 39 | ||
| 40 | extern char **environ; | |
| 41 | ||
| 42 | namespace __sanitizer { | |
| 43 | ||
| 44 | uptr internal_mmap(void *addr, size_t length, int prot, int flags, int fd, | |
| 45 | u64 offset) { | |
| 46 | return (uptr)mmap(addr, length, prot, flags, fd, offset); | |
| 47 | } | |
| 48 | ||
| 49 | uptr internal_munmap(void *addr, uptr length) { return munmap(addr, length); } | |
| 50 | ||
| 51 | int internal_mprotect(void *addr, uptr length, int prot) { | |
| 52 | return mprotect(addr, length, prot); | |
| 53 | } | |
| 54 | ||
| 55 | int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, | |
| 56 | const void *newp, uptr newlen) { | |
| 57 | Printf("internal_sysctlbyname not implemented for OpenBSD"); | |
| 58 | Die(); | |
| 59 | return 0; | |
| 60 | } | |
| 61 | ||
| 62 | uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { | |
| 63 | // On OpenBSD we cannot get the full path | |
| 64 | struct kinfo_proc kp; | |
| 65 | uptr kl; | |
| 66 | const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; | |
| 67 | if (internal_sysctl(Mib, ARRAY_SIZE(Mib), &kp, &kl, NULL, 0) != -1) | |
| 68 | return internal_snprintf(buf, | |
| 69 | (KI_MAXCOMLEN < buf_len ? KI_MAXCOMLEN : buf_len), | |
| 70 | "%s", kp.p_comm); | |
| 71 | return (uptr)0; | |
| 72 | } | |
| 73 | ||
| 74 | static void GetArgsAndEnv(char ***argv, char ***envp) { | |
| 75 | uptr nargv; | |
| 76 | uptr nenv; | |
| 77 | int argvmib[4] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV}; | |
| 78 | int envmib[4] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ENV}; | |
| 79 | if (internal_sysctl(argvmib, 4, NULL, &nargv, NULL, 0) == -1) { | |
| 80 | Printf("sysctl KERN_PROC_NARGV failed\n"); | |
| 81 | Die(); | |
| 82 | } | |
| 83 | if (internal_sysctl(envmib, 4, NULL, &nenv, NULL, 0) == -1) { | |
| 84 | Printf("sysctl KERN_PROC_NENV failed\n"); | |
| 85 | Die(); | |
| 86 | } | |
| 87 | if (internal_sysctl(argvmib, 4, &argv, &nargv, NULL, 0) == -1) { | |
| 88 | Printf("sysctl KERN_PROC_ARGV failed\n"); | |
| 89 | Die(); | |
| 90 | } | |
| 91 | if (internal_sysctl(envmib, 4, &envp, &nenv, NULL, 0) == -1) { | |
| 92 | Printf("sysctl KERN_PROC_ENV failed\n"); | |
| 93 | Die(); | |
| 94 | } | |
| 95 | } | |
| 96 | ||
| 97 | char **GetArgv() { | |
| 98 | char **argv, **envp; | |
| 99 | GetArgsAndEnv(&argv, &envp); | |
| 100 | return argv; | |
| 101 | } | |
| 102 | ||
| 103 | char **GetEnviron() { | |
| 104 | char **argv, **envp; | |
| 105 | GetArgsAndEnv(&argv, &envp); | |
| 106 | return envp; | |
| 107 | } | |
| 108 | ||
| 109 | void ReExec() { | |
| 110 | UNIMPLEMENTED(); | |
| 111 | } | |
| 112 | ||
| 113 | } // namespace __sanitizer | |
| 114 | ||
| 115 | #endif // SANITIZER_OPENBSD |
lib/tsan/sanitizer_common/sanitizer_platform.h+42-26| ... | ... | @@ -13,10 +13,16 @@ |
| 13 | 13 | #define SANITIZER_PLATFORM_H |
| 14 | 14 | |
| 15 | 15 | #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ |
| 16 | !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(_WIN32) && \ | |
| 17 | !defined(__Fuchsia__) && !defined(__rtems__) && \ | |
| 18 | !(defined(__sun__) && defined(__svr4__)) | |
| 19 | # error "This operating system is not supported" | |
| 16 | !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) && \ | |
| 17 | !(defined(__sun__) && defined(__svr4__)) | |
| 18 | # error "This operating system is not supported" | |
| 19 | #endif | |
| 20 | ||
| 21 | // Get __GLIBC__ on a glibc platform. Exclude Android: features.h includes C | |
| 22 | // function declarations into a .S file which doesn't compile. | |
| 23 | // https://crbug.com/1162741 | |
| 24 | #if __has_include(<features.h>) && !defined(__ANDROID__) | |
| 25 | #include <features.h> | |
| 20 | 26 | #endif |
| 21 | 27 | |
| 22 | 28 | #if defined(__linux__) |
| ... | ... | @@ -25,6 +31,12 @@ |
| 25 | 31 | # define SANITIZER_LINUX 0 |
| 26 | 32 | #endif |
| 27 | 33 | |
| 34 | #if defined(__GLIBC__) | |
| 35 | # define SANITIZER_GLIBC 1 | |
| 36 | #else | |
| 37 | # define SANITIZER_GLIBC 0 | |
| 38 | #endif | |
| 39 | ||
| 28 | 40 | #if defined(__FreeBSD__) |
| 29 | 41 | # define SANITIZER_FREEBSD 1 |
| 30 | 42 | #else |
| ... | ... | @@ -37,12 +49,6 @@ |
| 37 | 49 | # define SANITIZER_NETBSD 0 |
| 38 | 50 | #endif |
| 39 | 51 | |
| 40 | #if defined(__OpenBSD__) | |
| 41 | # define SANITIZER_OPENBSD 1 | |
| 42 | #else | |
| 43 | # define SANITIZER_OPENBSD 0 | |
| 44 | #endif | |
| 45 | ||
| 46 | 52 | #if defined(__sun__) && defined(__svr4__) |
| 47 | 53 | # define SANITIZER_SOLARIS 1 |
| 48 | 54 | #else |
| ... | ... | @@ -52,6 +58,11 @@ |
| 52 | 58 | #if defined(__APPLE__) |
| 53 | 59 | # define SANITIZER_MAC 1 |
| 54 | 60 | # include <TargetConditionals.h> |
| 61 | # if TARGET_OS_OSX | |
| 62 | # define SANITIZER_OSX 1 | |
| 63 | # else | |
| 64 | # define SANITIZER_OSX 0 | |
| 65 | # endif | |
| 55 | 66 | # if TARGET_OS_IPHONE |
| 56 | 67 | # define SANITIZER_IOS 1 |
| 57 | 68 | # else |
| ... | ... | @@ -66,6 +77,7 @@ |
| 66 | 77 | # define SANITIZER_MAC 0 |
| 67 | 78 | # define SANITIZER_IOS 0 |
| 68 | 79 | # define SANITIZER_IOSSIM 0 |
| 80 | # define SANITIZER_OSX 0 | |
| 69 | 81 | #endif |
| 70 | 82 | |
| 71 | 83 | #if defined(__APPLE__) && TARGET_OS_IPHONE && TARGET_OS_WATCH |
| ... | ... | @@ -104,15 +116,9 @@ |
| 104 | 116 | # define SANITIZER_FUCHSIA 0 |
| 105 | 117 | #endif |
| 106 | 118 | |
| 107 | #if defined(__rtems__) | |
| 108 | # define SANITIZER_RTEMS 1 | |
| 109 | #else | |
| 110 | # define SANITIZER_RTEMS 0 | |
| 111 | #endif | |
| 112 | ||
| 113 | 119 | #define SANITIZER_POSIX \ |
| 114 | 120 | (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \ |
| 115 | SANITIZER_NETBSD || SANITIZER_OPENBSD || SANITIZER_SOLARIS) | |
| 121 | SANITIZER_NETBSD || SANITIZER_SOLARIS) | |
| 116 | 122 | |
| 117 | 123 | #if __LP64__ || defined(_WIN64) |
| 118 | 124 | # define SANITIZER_WORDSIZE 64 |
| ... | ... | @@ -213,10 +219,10 @@ |
| 213 | 219 | # define SANITIZER_SOLARIS32 0 |
| 214 | 220 | #endif |
| 215 | 221 | |
| 216 | #if defined(__myriad2__) | |
| 217 | # define SANITIZER_MYRIAD2 1 | |
| 222 | #if defined(__riscv) && (__riscv_xlen == 64) | |
| 223 | #define SANITIZER_RISCV64 1 | |
| 218 | 224 | #else |
| 219 | # define SANITIZER_MYRIAD2 0 | |
| 225 | #define SANITIZER_RISCV64 0 | |
| 220 | 226 | #endif |
| 221 | 227 | |
| 222 | 228 | // By default we allow to use SizeClassAllocator64 on 64-bit platform. |
| ... | ... | @@ -238,11 +244,21 @@ |
| 238 | 244 | // FIXME: this value should be different on different platforms. Larger values |
| 239 | 245 | // will still work but will consume more memory for TwoLevelByteMap. |
| 240 | 246 | #if defined(__mips__) |
| 247 | #if SANITIZER_GO && defined(__mips64) | |
| 248 | #define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47) | |
| 249 | #else | |
| 241 | 250 | # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40) |
| 251 | #endif | |
| 252 | #elif SANITIZER_RISCV64 | |
| 253 | #define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 38) | |
| 242 | 254 | #elif defined(__aarch64__) |
| 243 | 255 | # if SANITIZER_MAC |
| 244 | // Darwin iOS/ARM64 has a 36-bit VMA, 64GiB VM | |
| 245 | # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 36) | |
| 256 | # if SANITIZER_OSX || SANITIZER_IOSSIM | |
| 257 | # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47) | |
| 258 | # else | |
| 259 | // Darwin iOS/ARM64 has a 36-bit VMA, 64GiB VM | |
| 260 | # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 36) | |
| 261 | # endif | |
| 246 | 262 | # else |
| 247 | 263 | # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 48) |
| 248 | 264 | # endif |
| ... | ... | @@ -331,7 +347,7 @@ |
| 331 | 347 | #endif |
| 332 | 348 | |
| 333 | 349 | #if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD || \ |
| 334 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 350 | SANITIZER_SOLARIS | |
| 335 | 351 | # define SANITIZER_MADVISE_DONTNEED MADV_FREE |
| 336 | 352 | #else |
| 337 | 353 | # define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED |
| ... | ... | @@ -345,9 +361,9 @@ |
| 345 | 361 | # define SANITIZER_CACHE_LINE_SIZE 64 |
| 346 | 362 | #endif |
| 347 | 363 | |
| 348 | // Enable offline markup symbolizer for Fuchsia and RTEMS. | |
| 349 | #if SANITIZER_FUCHSIA || SANITIZER_RTEMS | |
| 350 | #define SANITIZER_SYMBOLIZER_MARKUP 1 | |
| 364 | // Enable offline markup symbolizer for Fuchsia. | |
| 365 | #if SANITIZER_FUCHSIA | |
| 366 | # define SANITIZER_SYMBOLIZER_MARKUP 1 | |
| 351 | 367 | #else |
| 352 | 368 | #define SANITIZER_SYMBOLIZER_MARKUP 0 |
| 353 | 369 | #endif |
lib/tsan/sanitizer_common/sanitizer_platform_interceptors.h+184-190| ... | ... | @@ -15,133 +15,127 @@ |
| 15 | 15 | |
| 16 | 16 | #include "sanitizer_glibc_version.h" |
| 17 | 17 | #include "sanitizer_internal_defs.h" |
| 18 | #include "sanitizer_platform.h" | |
| 18 | 19 | |
| 19 | 20 | #if SANITIZER_POSIX |
| 20 | # define SI_POSIX 1 | |
| 21 | #define SI_POSIX 1 | |
| 21 | 22 | #else |
| 22 | # define SI_POSIX 0 | |
| 23 | #define SI_POSIX 0 | |
| 23 | 24 | #endif |
| 24 | 25 | |
| 25 | 26 | #if !SANITIZER_WINDOWS |
| 26 | # define SI_WINDOWS 0 | |
| 27 | #define SI_WINDOWS 0 | |
| 27 | 28 | #else |
| 28 | # define SI_WINDOWS 1 | |
| 29 | #define SI_WINDOWS 1 | |
| 29 | 30 | #endif |
| 30 | 31 | |
| 31 | 32 | #if SI_WINDOWS && SI_POSIX |
| 32 | # error "Windows is not POSIX!" | |
| 33 | #error "Windows is not POSIX!" | |
| 33 | 34 | #endif |
| 34 | 35 | |
| 35 | 36 | #if SI_POSIX |
| 36 | # include "sanitizer_platform_limits_freebsd.h" | |
| 37 | # include "sanitizer_platform_limits_netbsd.h" | |
| 38 | # include "sanitizer_platform_limits_openbsd.h" | |
| 39 | # include "sanitizer_platform_limits_posix.h" | |
| 40 | # include "sanitizer_platform_limits_solaris.h" | |
| 37 | #include "sanitizer_platform_limits_freebsd.h" | |
| 38 | #include "sanitizer_platform_limits_netbsd.h" | |
| 39 | #include "sanitizer_platform_limits_posix.h" | |
| 40 | #include "sanitizer_platform_limits_solaris.h" | |
| 41 | 41 | #endif |
| 42 | 42 | |
| 43 | 43 | #if SANITIZER_LINUX && !SANITIZER_ANDROID |
| 44 | # define SI_LINUX_NOT_ANDROID 1 | |
| 44 | #define SI_LINUX_NOT_ANDROID 1 | |
| 45 | 45 | #else |
| 46 | # define SI_LINUX_NOT_ANDROID 0 | |
| 46 | #define SI_LINUX_NOT_ANDROID 0 | |
| 47 | 47 | #endif |
| 48 | 48 | |
| 49 | #if SANITIZER_ANDROID | |
| 50 | # define SI_ANDROID 1 | |
| 49 | #if SANITIZER_GLIBC | |
| 50 | #define SI_GLIBC 1 | |
| 51 | 51 | #else |
| 52 | # define SI_ANDROID 0 | |
| 52 | #define SI_GLIBC 0 | |
| 53 | 53 | #endif |
| 54 | 54 | |
| 55 | #if SANITIZER_FREEBSD | |
| 56 | # define SI_FREEBSD 1 | |
| 55 | #if SANITIZER_ANDROID | |
| 56 | #define SI_ANDROID 1 | |
| 57 | 57 | #else |
| 58 | # define SI_FREEBSD 0 | |
| 58 | #define SI_ANDROID 0 | |
| 59 | 59 | #endif |
| 60 | 60 | |
| 61 | #if SANITIZER_NETBSD | |
| 62 | # define SI_NETBSD 1 | |
| 61 | #if SANITIZER_FREEBSD | |
| 62 | #define SI_FREEBSD 1 | |
| 63 | 63 | #else |
| 64 | # define SI_NETBSD 0 | |
| 64 | #define SI_FREEBSD 0 | |
| 65 | 65 | #endif |
| 66 | 66 | |
| 67 | #if SANITIZER_OPENBSD | |
| 68 | #define SI_OPENBSD 1 | |
| 67 | #if SANITIZER_NETBSD | |
| 68 | #define SI_NETBSD 1 | |
| 69 | 69 | #else |
| 70 | #define SI_OPENBSD 0 | |
| 70 | #define SI_NETBSD 0 | |
| 71 | 71 | #endif |
| 72 | 72 | |
| 73 | 73 | #if SANITIZER_LINUX |
| 74 | # define SI_LINUX 1 | |
| 74 | #define SI_LINUX 1 | |
| 75 | 75 | #else |
| 76 | # define SI_LINUX 0 | |
| 76 | #define SI_LINUX 0 | |
| 77 | 77 | #endif |
| 78 | 78 | |
| 79 | 79 | #if SANITIZER_MAC |
| 80 | # define SI_MAC 1 | |
| 81 | # define SI_NOT_MAC 0 | |
| 80 | #define SI_MAC 1 | |
| 81 | #define SI_NOT_MAC 0 | |
| 82 | 82 | #else |
| 83 | # define SI_MAC 0 | |
| 84 | # define SI_NOT_MAC 1 | |
| 83 | #define SI_MAC 0 | |
| 84 | #define SI_NOT_MAC 1 | |
| 85 | 85 | #endif |
| 86 | 86 | |
| 87 | 87 | #if SANITIZER_IOS |
| 88 | # define SI_IOS 1 | |
| 88 | #define SI_IOS 1 | |
| 89 | 89 | #else |
| 90 | # define SI_IOS 0 | |
| 90 | #define SI_IOS 0 | |
| 91 | 91 | #endif |
| 92 | 92 | |
| 93 | 93 | #if SANITIZER_IOSSIM |
| 94 | # define SI_IOSSIM 1 | |
| 94 | #define SI_IOSSIM 1 | |
| 95 | 95 | #else |
| 96 | # define SI_IOSSIM 0 | |
| 96 | #define SI_IOSSIM 0 | |
| 97 | 97 | #endif |
| 98 | 98 | |
| 99 | 99 | #if SANITIZER_WATCHOS |
| 100 | # define SI_WATCHOS 1 | |
| 100 | #define SI_WATCHOS 1 | |
| 101 | 101 | #else |
| 102 | # define SI_WATCHOS 0 | |
| 102 | #define SI_WATCHOS 0 | |
| 103 | 103 | #endif |
| 104 | 104 | |
| 105 | 105 | #if SANITIZER_TVOS |
| 106 | # define SI_TVOS 1 | |
| 106 | #define SI_TVOS 1 | |
| 107 | 107 | #else |
| 108 | # define SI_TVOS 0 | |
| 108 | #define SI_TVOS 0 | |
| 109 | 109 | #endif |
| 110 | 110 | |
| 111 | 111 | #if SANITIZER_FUCHSIA |
| 112 | # define SI_NOT_FUCHSIA 0 | |
| 113 | #else | |
| 114 | # define SI_NOT_FUCHSIA 1 | |
| 115 | #endif | |
| 116 | ||
| 117 | #if SANITIZER_RTEMS | |
| 118 | # define SI_NOT_RTEMS 0 | |
| 112 | #define SI_NOT_FUCHSIA 0 | |
| 119 | 113 | #else |
| 120 | # define SI_NOT_RTEMS 1 | |
| 114 | #define SI_NOT_FUCHSIA 1 | |
| 121 | 115 | #endif |
| 122 | 116 | |
| 123 | 117 | #if SANITIZER_SOLARIS |
| 124 | # define SI_SOLARIS 1 | |
| 118 | #define SI_SOLARIS 1 | |
| 125 | 119 | #else |
| 126 | # define SI_SOLARIS 0 | |
| 120 | #define SI_SOLARIS 0 | |
| 127 | 121 | #endif |
| 128 | 122 | |
| 129 | 123 | #if SANITIZER_SOLARIS32 |
| 130 | # define SI_SOLARIS32 1 | |
| 124 | #define SI_SOLARIS32 1 | |
| 131 | 125 | #else |
| 132 | # define SI_SOLARIS32 0 | |
| 126 | #define SI_SOLARIS32 0 | |
| 133 | 127 | #endif |
| 134 | 128 | |
| 135 | 129 | #if SANITIZER_POSIX && !SANITIZER_MAC |
| 136 | # define SI_POSIX_NOT_MAC 1 | |
| 130 | #define SI_POSIX_NOT_MAC 1 | |
| 137 | 131 | #else |
| 138 | # define SI_POSIX_NOT_MAC 0 | |
| 132 | #define SI_POSIX_NOT_MAC 0 | |
| 139 | 133 | #endif |
| 140 | 134 | |
| 141 | 135 | #if SANITIZER_LINUX && !SANITIZER_FREEBSD |
| 142 | # define SI_LINUX_NOT_FREEBSD 1 | |
| 143 | # else | |
| 144 | # define SI_LINUX_NOT_FREEBSD 0 | |
| 136 | #define SI_LINUX_NOT_FREEBSD 1 | |
| 137 | #else | |
| 138 | #define SI_LINUX_NOT_FREEBSD 0 | |
| 145 | 139 | #endif |
| 146 | 140 | |
| 147 | 141 | #define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA |
| ... | ... | @@ -163,21 +157,20 @@ |
| 163 | 157 | #define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA |
| 164 | 158 | #define SANITIZER_INTERCEPT_BCMP \ |
| 165 | 159 | SANITIZER_INTERCEPT_MEMCMP && \ |
| 166 | ((SI_POSIX && _GNU_SOURCE) || SI_NETBSD || SI_OPENBSD || SI_FREEBSD) | |
| 160 | ((SI_POSIX && _GNU_SOURCE) || SI_NETBSD || SI_FREEBSD) | |
| 167 | 161 | #define SANITIZER_INTERCEPT_STRNDUP SI_POSIX |
| 168 | #define SANITIZER_INTERCEPT___STRNDUP SI_LINUX_NOT_FREEBSD | |
| 162 | #define SANITIZER_INTERCEPT___STRNDUP SI_GLIBC | |
| 169 | 163 | #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ |
| 170 | 164 | __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 |
| 171 | # define SI_MAC_DEPLOYMENT_BELOW_10_7 1 | |
| 165 | #define SI_MAC_DEPLOYMENT_BELOW_10_7 1 | |
| 172 | 166 | #else |
| 173 | # define SI_MAC_DEPLOYMENT_BELOW_10_7 0 | |
| 167 | #define SI_MAC_DEPLOYMENT_BELOW_10_7 0 | |
| 174 | 168 | #endif |
| 175 | 169 | // memmem on Darwin doesn't exist on 10.6 |
| 176 | 170 | // FIXME: enable memmem on Windows. |
| 177 | 171 | #define SANITIZER_INTERCEPT_MEMMEM (SI_POSIX && !SI_MAC_DEPLOYMENT_BELOW_10_7) |
| 178 | 172 | #define SANITIZER_INTERCEPT_MEMCHR SI_NOT_FUCHSIA |
| 179 | #define SANITIZER_INTERCEPT_MEMRCHR \ | |
| 180 | (SI_FREEBSD || SI_LINUX || SI_NETBSD || SI_OPENBSD) | |
| 173 | #define SANITIZER_INTERCEPT_MEMRCHR (SI_FREEBSD || SI_LINUX || SI_NETBSD) | |
| 181 | 174 | |
| 182 | 175 | #define SANITIZER_INTERCEPT_READ SI_POSIX |
| 183 | 176 | #define SANITIZER_INTERCEPT_PREAD SI_POSIX |
| ... | ... | @@ -190,64 +183,60 @@ |
| 190 | 183 | #define SANITIZER_INTERCEPT_FPUTS SI_POSIX |
| 191 | 184 | #define SANITIZER_INTERCEPT_PUTS SI_POSIX |
| 192 | 185 | |
| 193 | #define SANITIZER_INTERCEPT_PREAD64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 | |
| 194 | #define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 | |
| 186 | #define SANITIZER_INTERCEPT_PREAD64 (SI_GLIBC || SI_SOLARIS32) | |
| 187 | #define SANITIZER_INTERCEPT_PWRITE64 (SI_GLIBC || SI_SOLARIS32) | |
| 195 | 188 | |
| 196 | 189 | #define SANITIZER_INTERCEPT_READV SI_POSIX |
| 197 | 190 | #define SANITIZER_INTERCEPT_WRITEV SI_POSIX |
| 198 | 191 | |
| 199 | 192 | #define SANITIZER_INTERCEPT_PREADV \ |
| 200 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID) | |
| 193 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID) | |
| 201 | 194 | #define SANITIZER_INTERCEPT_PWRITEV SI_LINUX_NOT_ANDROID |
| 202 | #define SANITIZER_INTERCEPT_PREADV64 SI_LINUX_NOT_ANDROID | |
| 203 | #define SANITIZER_INTERCEPT_PWRITEV64 SI_LINUX_NOT_ANDROID | |
| 195 | #define SANITIZER_INTERCEPT_PREADV64 SI_GLIBC | |
| 196 | #define SANITIZER_INTERCEPT_PWRITEV64 SI_GLIBC | |
| 204 | 197 | |
| 205 | #define SANITIZER_INTERCEPT_PRCTL SI_LINUX | |
| 198 | #define SANITIZER_INTERCEPT_PRCTL SI_LINUX | |
| 206 | 199 | |
| 207 | 200 | #define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_POSIX |
| 208 | 201 | #define SANITIZER_INTERCEPT_STRPTIME SI_POSIX |
| 209 | 202 | |
| 210 | 203 | #define SANITIZER_INTERCEPT_SCANF SI_POSIX |
| 211 | #define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX_NOT_ANDROID | |
| 204 | #define SANITIZER_INTERCEPT_ISOC99_SCANF SI_GLIBC | |
| 212 | 205 | |
| 213 | 206 | #ifndef SANITIZER_INTERCEPT_PRINTF |
| 214 | # define SANITIZER_INTERCEPT_PRINTF SI_POSIX | |
| 215 | # define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD) | |
| 216 | # define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_LINUX_NOT_ANDROID | |
| 207 | #define SANITIZER_INTERCEPT_PRINTF SI_POSIX | |
| 208 | #define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD) | |
| 209 | #define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC | |
| 217 | 210 | #endif |
| 218 | 211 | |
| 219 | 212 | #define SANITIZER_INTERCEPT___PRINTF_CHK \ |
| 220 | (SANITIZER_INTERCEPT_PRINTF && SI_LINUX_NOT_ANDROID) | |
| 213 | (SANITIZER_INTERCEPT_PRINTF && SI_GLIBC) | |
| 221 | 214 | |
| 222 | 215 | #define SANITIZER_INTERCEPT_FREXP SI_NOT_FUCHSIA |
| 223 | 216 | #define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_POSIX |
| 224 | 217 | |
| 225 | 218 | #define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_POSIX |
| 226 | #define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \ | |
| 227 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ | |
| 228 | SI_SOLARIS) | |
| 229 | #define SANITIZER_INTERCEPT_GETPWENT \ | |
| 230 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ | |
| 231 | SI_SOLARIS) | |
| 232 | #define SANITIZER_INTERCEPT_FGETGRENT_R \ | |
| 233 | (SI_FREEBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 219 | #define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \ | |
| 220 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 221 | #define SANITIZER_INTERCEPT_GETPWENT \ | |
| 222 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 223 | #define SANITIZER_INTERCEPT_FGETGRENT_R (SI_GLIBC || SI_SOLARIS) | |
| 234 | 224 | #define SANITIZER_INTERCEPT_FGETPWENT SI_LINUX_NOT_ANDROID || SI_SOLARIS |
| 235 | 225 | #define SANITIZER_INTERCEPT_GETPWENT_R \ |
| 236 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 237 | #define SANITIZER_INTERCEPT_FGETPWENT_R \ | |
| 238 | (SI_FREEBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 226 | (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) | |
| 227 | #define SANITIZER_INTERCEPT_FGETPWENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS) | |
| 239 | 228 | #define SANITIZER_INTERCEPT_SETPWENT \ |
| 240 | 229 | (SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) |
| 241 | 230 | #define SANITIZER_INTERCEPT_CLOCK_GETTIME \ |
| 242 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX || SI_SOLARIS) | |
| 231 | (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS) | |
| 243 | 232 | #define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID SI_LINUX |
| 244 | 233 | #define SANITIZER_INTERCEPT_GETITIMER SI_POSIX |
| 245 | 234 | #define SANITIZER_INTERCEPT_TIME SI_POSIX |
| 246 | #define SANITIZER_INTERCEPT_GLOB SI_LINUX_NOT_ANDROID || SI_SOLARIS | |
| 247 | #define SANITIZER_INTERCEPT_GLOB64 SI_LINUX_NOT_ANDROID | |
| 235 | #define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS) | |
| 236 | #define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC | |
| 248 | 237 | #define SANITIZER_INTERCEPT_WAIT SI_POSIX |
| 249 | 238 | #define SANITIZER_INTERCEPT_INET SI_POSIX |
| 250 | #define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM (SI_POSIX && !SI_OPENBSD) | |
| 239 | #define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_POSIX | |
| 251 | 240 | #define SANITIZER_INTERCEPT_GETADDRINFO SI_POSIX |
| 252 | 241 | #define SANITIZER_INTERCEPT_GETNAMEINFO SI_POSIX |
| 253 | 242 | #define SANITIZER_INTERCEPT_GETSOCKNAME SI_POSIX |
| ... | ... | @@ -259,12 +248,10 @@ |
| 259 | 248 | (SI_FREEBSD || SI_LINUX_NOT_ANDROID) |
| 260 | 249 | #define SANITIZER_INTERCEPT_GETHOSTBYADDR_R \ |
| 261 | 250 | (SI_FREEBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) |
| 262 | #define SANITIZER_INTERCEPT_GETHOSTENT_R \ | |
| 263 | (SI_FREEBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 251 | #define SANITIZER_INTERCEPT_GETHOSTENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS) | |
| 264 | 252 | #define SANITIZER_INTERCEPT_GETSOCKOPT SI_POSIX |
| 265 | 253 | #define SANITIZER_INTERCEPT_ACCEPT SI_POSIX |
| 266 | #define SANITIZER_INTERCEPT_ACCEPT4 \ | |
| 267 | (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_OPENBSD) | |
| 254 | #define SANITIZER_INTERCEPT_ACCEPT4 (SI_LINUX_NOT_ANDROID || SI_NETBSD) | |
| 268 | 255 | #define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD |
| 269 | 256 | #define SANITIZER_INTERCEPT_MODF SI_POSIX |
| 270 | 257 | #define SANITIZER_INTERCEPT_RECVMSG SI_POSIX |
| ... | ... | @@ -278,10 +265,10 @@ |
| 278 | 265 | #define SANITIZER_INTERCEPT_SYSINFO SI_LINUX |
| 279 | 266 | #define SANITIZER_INTERCEPT_READDIR SI_POSIX |
| 280 | 267 | #define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 |
| 281 | #if SI_LINUX_NOT_ANDROID && \ | |
| 282 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 283 | defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ | |
| 284 | defined(__s390__)) | |
| 268 | #if SI_LINUX_NOT_ANDROID && \ | |
| 269 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 270 | defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ | |
| 271 | defined(__s390__) || SANITIZER_RISCV64) | |
| 285 | 272 | #define SANITIZER_INTERCEPT_PTRACE 1 |
| 286 | 273 | #else |
| 287 | 274 | #define SANITIZER_INTERCEPT_PTRACE 0 |
| ... | ... | @@ -298,46 +285,42 @@ |
| 298 | 285 | #define SANITIZER_INTERCEPT___STRXFRM_L SI_LINUX |
| 299 | 286 | #define SANITIZER_INTERCEPT_WCSXFRM SI_POSIX |
| 300 | 287 | #define SANITIZER_INTERCEPT___WCSXFRM_L SI_LINUX |
| 301 | #define SANITIZER_INTERCEPT_WCSNRTOMBS \ | |
| 302 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ | |
| 303 | SI_SOLARIS) | |
| 304 | #define SANITIZER_INTERCEPT_WCRTOMB \ | |
| 305 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ | |
| 306 | SI_SOLARIS) | |
| 307 | #define SANITIZER_INTERCEPT_WCTOMB \ | |
| 308 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ | |
| 309 | SI_SOLARIS) | |
| 288 | #define SANITIZER_INTERCEPT_WCSNRTOMBS \ | |
| 289 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 290 | #define SANITIZER_INTERCEPT_WCRTOMB \ | |
| 291 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 292 | #define SANITIZER_INTERCEPT_WCTOMB \ | |
| 293 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 310 | 294 | #define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX_NOT_ANDROID || SI_SOLARIS |
| 311 | 295 | #define SANITIZER_INTERCEPT_REALPATH SI_POSIX |
| 312 | #define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME \ | |
| 313 | (SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 314 | #define SANITIZER_INTERCEPT_CONFSTR \ | |
| 315 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ | |
| 316 | SI_SOLARIS) | |
| 296 | #define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME (SI_GLIBC || SI_SOLARIS) | |
| 297 | #define SANITIZER_INTERCEPT_CONFSTR \ | |
| 298 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 317 | 299 | #define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID |
| 318 | 300 | #define SANITIZER_INTERCEPT_SCHED_GETPARAM SI_LINUX_NOT_ANDROID || SI_SOLARIS |
| 319 | 301 | #define SANITIZER_INTERCEPT_STRERROR SI_POSIX |
| 320 | 302 | #define SANITIZER_INTERCEPT_STRERROR_R SI_POSIX |
| 321 | 303 | #define SANITIZER_INTERCEPT_XPG_STRERROR_R SI_LINUX_NOT_ANDROID |
| 322 | 304 | #define SANITIZER_INTERCEPT_SCANDIR \ |
| 323 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 305 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 324 | 306 | #define SANITIZER_INTERCEPT_SCANDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 |
| 325 | 307 | #define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX |
| 326 | 308 | #define SANITIZER_INTERCEPT_POLL SI_POSIX |
| 327 | 309 | #define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS |
| 328 | #define SANITIZER_INTERCEPT_WORDEXP \ | |
| 310 | #define SANITIZER_INTERCEPT_WORDEXP \ | |
| 329 | 311 | (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \ |
| 330 | SI_SOLARIS) | |
| 312 | SI_SOLARIS) // NOLINT | |
| 331 | 313 | #define SANITIZER_INTERCEPT_SIGWAIT SI_POSIX |
| 332 | 314 | #define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID || SI_SOLARIS |
| 333 | 315 | #define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID || SI_SOLARIS |
| 334 | 316 | #define SANITIZER_INTERCEPT_SIGSETOPS \ |
| 335 | 317 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) |
| 318 | #define SANITIZER_INTERCEPT_SIGSET_LOGICOPS SI_LINUX_NOT_ANDROID | |
| 336 | 319 | #define SANITIZER_INTERCEPT_SIGPENDING SI_POSIX |
| 337 | 320 | #define SANITIZER_INTERCEPT_SIGPROCMASK SI_POSIX |
| 338 | 321 | #define SANITIZER_INTERCEPT_PTHREAD_SIGMASK SI_POSIX |
| 339 | 322 | #define SANITIZER_INTERCEPT_BACKTRACE \ |
| 340 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 323 | (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) | |
| 341 | 324 | #define SANITIZER_INTERCEPT_GETMNTENT SI_LINUX |
| 342 | 325 | #define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID |
| 343 | 326 | #define SANITIZER_INTERCEPT_STATFS \ |
| ... | ... | @@ -345,25 +328,25 @@ |
| 345 | 328 | #define SANITIZER_INTERCEPT_STATFS64 \ |
| 346 | 329 | (((SI_MAC && !TARGET_CPU_ARM64) && !SI_IOS) || SI_LINUX_NOT_ANDROID) |
| 347 | 330 | #define SANITIZER_INTERCEPT_STATVFS \ |
| 348 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID) | |
| 331 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID) | |
| 349 | 332 | #define SANITIZER_INTERCEPT_STATVFS64 SI_LINUX_NOT_ANDROID |
| 350 | 333 | #define SANITIZER_INTERCEPT_INITGROUPS SI_POSIX |
| 351 | #define SANITIZER_INTERCEPT_ETHER_NTOA_ATON (SI_POSIX && !SI_OPENBSD) | |
| 334 | #define SANITIZER_INTERCEPT_ETHER_NTOA_ATON SI_POSIX | |
| 352 | 335 | #define SANITIZER_INTERCEPT_ETHER_HOST \ |
| 353 | 336 | (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID) |
| 354 | 337 | #define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID) |
| 355 | 338 | #define SANITIZER_INTERCEPT_SHMCTL \ |
| 356 | 339 | (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \ |
| 357 | SI_NETBSD || SI_OPENBSD || SI_SOLARIS) // NOLINT | |
| 358 | #define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID | |
| 340 | SI_NETBSD || SI_SOLARIS) // NOLINT | |
| 341 | #define SANITIZER_INTERCEPT_RANDOM_R SI_GLIBC | |
| 359 | 342 | #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX |
| 360 | 343 | #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \ |
| 361 | 344 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) |
| 362 | #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_LINUX_NOT_ANDROID | |
| 363 | #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED (SI_POSIX && !SI_OPENBSD) | |
| 345 | #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_GLIBC | |
| 346 | #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED SI_POSIX | |
| 364 | 347 | #define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED \ |
| 365 | (SI_POSIX && !SI_NETBSD && !SI_OPENBSD) | |
| 366 | #define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE (SI_POSIX && !SI_OPENBSD) | |
| 348 | (SI_POSIX && !SI_NETBSD) | |
| 349 | #define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE SI_POSIX | |
| 367 | 350 | #define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL \ |
| 368 | 351 | (SI_MAC || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) |
| 369 | 352 | #define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING \ |
| ... | ... | @@ -372,17 +355,18 @@ |
| 372 | 355 | (SI_LINUX_NOT_ANDROID || SI_SOLARIS) |
| 373 | 356 | #define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP SI_LINUX_NOT_ANDROID |
| 374 | 357 | #define SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED \ |
| 375 | (SI_POSIX && !SI_NETBSD && !SI_OPENBSD) | |
| 376 | #define SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP SI_LINUX_NOT_ANDROID | |
| 377 | #define SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED \ | |
| 378 | (SI_POSIX && !SI_NETBSD && !SI_OPENBSD) | |
| 358 | (SI_POSIX && !SI_NETBSD) | |
| 359 | #define SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP SI_GLIBC | |
| 360 | #define SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED (SI_POSIX && !SI_NETBSD) | |
| 379 | 361 | #define SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK \ |
| 380 | 362 | (SI_LINUX_NOT_ANDROID || SI_SOLARIS) |
| 381 | 363 | #define SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED \ |
| 382 | (SI_LINUX_NOT_ANDROID && !SI_NETBSD && !SI_OPENBSD) | |
| 364 | (SI_LINUX_NOT_ANDROID && !SI_NETBSD) | |
| 383 | 365 | #define SANITIZER_INTERCEPT_THR_EXIT SI_FREEBSD |
| 384 | 366 | #define SANITIZER_INTERCEPT_TMPNAM SI_POSIX |
| 385 | #define SANITIZER_INTERCEPT_TMPNAM_R SI_LINUX_NOT_ANDROID || SI_SOLARIS | |
| 367 | #define SANITIZER_INTERCEPT_TMPNAM_R (SI_GLIBC || SI_SOLARIS) | |
| 368 | #define SANITIZER_INTERCEPT_PTSNAME SI_LINUX | |
| 369 | #define SANITIZER_INTERCEPT_PTSNAME_R SI_LINUX | |
| 386 | 370 | #define SANITIZER_INTERCEPT_TTYNAME SI_POSIX |
| 387 | 371 | #define SANITIZER_INTERCEPT_TTYNAME_R SI_POSIX |
| 388 | 372 | #define SANITIZER_INTERCEPT_TEMPNAM SI_POSIX |
| ... | ... | @@ -393,71 +377,67 @@ |
| 393 | 377 | #define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD) |
| 394 | 378 | #define SANITIZER_INTERCEPT_LGAMMA_R (SI_FREEBSD || SI_LINUX || SI_SOLARIS) |
| 395 | 379 | #define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID || SI_SOLARIS |
| 396 | #define SANITIZER_INTERCEPT_DRAND48_R SI_LINUX_NOT_ANDROID | |
| 397 | #define SANITIZER_INTERCEPT_RAND_R \ | |
| 398 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ | |
| 399 | SI_SOLARIS) | |
| 380 | #define SANITIZER_INTERCEPT_DRAND48_R SI_GLIBC | |
| 381 | #define SANITIZER_INTERCEPT_RAND_R \ | |
| 382 | (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 400 | 383 | #define SANITIZER_INTERCEPT_ICONV \ |
| 401 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 384 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 402 | 385 | #define SANITIZER_INTERCEPT_TIMES SI_POSIX |
| 403 | 386 | |
| 404 | 387 | // FIXME: getline seems to be available on OSX 10.7 |
| 405 | 388 | #define SANITIZER_INTERCEPT_GETLINE \ |
| 406 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 389 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 407 | 390 | |
| 408 | 391 | #define SANITIZER_INTERCEPT__EXIT \ |
| 409 | (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_SOLARIS) | |
| 392 | (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_MAC || SI_SOLARIS) | |
| 410 | 393 | |
| 411 | 394 | #define SANITIZER_INTERCEPT_PTHREAD_MUTEX SI_POSIX |
| 412 | #define SANITIZER_INTERCEPT___PTHREAD_MUTEX SI_LINUX_NOT_ANDROID | |
| 395 | #define SANITIZER_INTERCEPT___PTHREAD_MUTEX SI_GLIBC | |
| 413 | 396 | #define SANITIZER_INTERCEPT___LIBC_MUTEX SI_NETBSD |
| 414 | 397 | #define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \ |
| 415 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 398 | (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) | |
| 416 | 399 | #define SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP \ |
| 417 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 400 | (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) | |
| 418 | 401 | |
| 419 | 402 | #define SANITIZER_INTERCEPT_TLS_GET_ADDR \ |
| 420 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 403 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) | |
| 421 | 404 | |
| 422 | 405 | #define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX |
| 423 | 406 | #define SANITIZER_INTERCEPT_GETXATTR SI_LINUX |
| 424 | 407 | #define SANITIZER_INTERCEPT_GETRESID SI_LINUX |
| 425 | #define SANITIZER_INTERCEPT_GETIFADDRS \ | |
| 426 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_MAC || \ | |
| 427 | SI_SOLARIS) | |
| 428 | #define SANITIZER_INTERCEPT_IF_INDEXTONAME \ | |
| 429 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_MAC || \ | |
| 430 | SI_SOLARIS) | |
| 408 | #define SANITIZER_INTERCEPT_GETIFADDRS \ | |
| 409 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_MAC || SI_SOLARIS) | |
| 410 | #define SANITIZER_INTERCEPT_IF_INDEXTONAME \ | |
| 411 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_MAC || SI_SOLARIS) | |
| 431 | 412 | #define SANITIZER_INTERCEPT_CAPGET SI_LINUX_NOT_ANDROID |
| 432 | 413 | #if SI_LINUX && defined(__arm__) |
| 433 | 414 | #define SANITIZER_INTERCEPT_AEABI_MEM 1 |
| 434 | 415 | #else |
| 435 | 416 | #define SANITIZER_INTERCEPT_AEABI_MEM 0 |
| 436 | 417 | #endif |
| 437 | #define SANITIZER_INTERCEPT___BZERO SI_MAC || SI_LINUX_NOT_ANDROID | |
| 418 | #define SANITIZER_INTERCEPT___BZERO SI_MAC || SI_GLIBC | |
| 438 | 419 | #define SANITIZER_INTERCEPT_BZERO SI_LINUX_NOT_ANDROID |
| 439 | #define SANITIZER_INTERCEPT_FTIME \ | |
| 440 | (!SI_FREEBSD && !SI_NETBSD && !SI_OPENBSD && SI_POSIX) | |
| 441 | #define SANITIZER_INTERCEPT_XDR SI_LINUX_NOT_ANDROID || SI_SOLARIS | |
| 420 | #define SANITIZER_INTERCEPT_FTIME (!SI_FREEBSD && !SI_NETBSD && SI_POSIX) | |
| 421 | #define SANITIZER_INTERCEPT_XDR (SI_GLIBC || SI_SOLARIS) | |
| 422 | #define SANITIZER_INTERCEPT_XDRREC SI_GLIBC | |
| 442 | 423 | #define SANITIZER_INTERCEPT_TSEARCH \ |
| 443 | (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD || SI_OPENBSD || SI_SOLARIS) | |
| 444 | #define SANITIZER_INTERCEPT_LIBIO_INTERNALS SI_LINUX_NOT_ANDROID | |
| 424 | (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD || SI_SOLARIS) | |
| 425 | #define SANITIZER_INTERCEPT_LIBIO_INTERNALS SI_GLIBC | |
| 445 | 426 | #define SANITIZER_INTERCEPT_FOPEN SI_POSIX |
| 446 | #define SANITIZER_INTERCEPT_FOPEN64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 | |
| 427 | #define SANITIZER_INTERCEPT_FOPEN64 (SI_GLIBC || SI_SOLARIS32) | |
| 447 | 428 | #define SANITIZER_INTERCEPT_OPEN_MEMSTREAM \ |
| 448 | (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_OPENBSD || SI_SOLARIS) | |
| 449 | #define SANITIZER_INTERCEPT_OBSTACK SI_LINUX_NOT_ANDROID | |
| 429 | (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_SOLARIS) | |
| 430 | #define SANITIZER_INTERCEPT_OBSTACK SI_GLIBC | |
| 450 | 431 | #define SANITIZER_INTERCEPT_FFLUSH SI_POSIX |
| 451 | 432 | #define SANITIZER_INTERCEPT_FCLOSE SI_POSIX |
| 452 | 433 | |
| 453 | 434 | #ifndef SANITIZER_INTERCEPT_DLOPEN_DLCLOSE |
| 454 | #define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \ | |
| 455 | (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_MAC || \ | |
| 456 | SI_SOLARIS) | |
| 435 | #define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \ | |
| 436 | (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_MAC || SI_SOLARIS) | |
| 457 | 437 | #endif |
| 458 | 438 | |
| 459 | 439 | #define SANITIZER_INTERCEPT_GETPASS \ |
| 460 | (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD || SI_OPENBSD) | |
| 440 | (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD) | |
| 461 | 441 | #define SANITIZER_INTERCEPT_TIMERFD SI_LINUX_NOT_ANDROID |
| 462 | 442 | |
| 463 | 443 | #define SANITIZER_INTERCEPT_MLOCKX SI_POSIX |
| ... | ... | @@ -465,21 +445,20 @@ |
| 465 | 445 | #define SANITIZER_INTERCEPT_SEM \ |
| 466 | 446 | (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_SOLARIS) |
| 467 | 447 | #define SANITIZER_INTERCEPT_PTHREAD_SETCANCEL SI_POSIX |
| 468 | #define SANITIZER_INTERCEPT_MINCORE \ | |
| 469 | (SI_LINUX || SI_NETBSD || SI_OPENBSD || SI_SOLARIS) | |
| 448 | #define SANITIZER_INTERCEPT_MINCORE (SI_LINUX || SI_NETBSD || SI_SOLARIS) | |
| 470 | 449 | #define SANITIZER_INTERCEPT_PROCESS_VM_READV SI_LINUX |
| 471 | 450 | #define SANITIZER_INTERCEPT_CTERMID \ |
| 472 | (SI_LINUX || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_SOLARIS) | |
| 451 | (SI_LINUX || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_SOLARIS) | |
| 473 | 452 | #define SANITIZER_INTERCEPT_CTERMID_R (SI_MAC || SI_FREEBSD || SI_SOLARIS) |
| 474 | 453 | |
| 475 | 454 | #define SANITIZER_INTERCEPTOR_HOOKS \ |
| 476 | (SI_LINUX || SI_MAC || SI_WINDOWS || SI_NETBSD) | |
| 455 | (SI_LINUX || SI_MAC || SI_WINDOWS || SI_FREEBSD || SI_NETBSD || SI_SOLARIS) | |
| 477 | 456 | #define SANITIZER_INTERCEPT_RECV_RECVFROM SI_POSIX |
| 478 | 457 | #define SANITIZER_INTERCEPT_SEND_SENDTO SI_POSIX |
| 479 | 458 | #define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE SI_LINUX |
| 480 | 459 | |
| 481 | 460 | #define SANITIZER_INTERCEPT_STAT \ |
| 482 | (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_OPENBSD || SI_SOLARIS) | |
| 461 | (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS) | |
| 483 | 462 | #define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD) |
| 484 | 463 | #define SANITIZER_INTERCEPT___XSTAT (!SANITIZER_INTERCEPT_STAT && SI_POSIX) |
| 485 | 464 | #define SANITIZER_INTERCEPT___XSTAT64 SI_LINUX_NOT_ANDROID |
| ... | ... | @@ -492,41 +471,34 @@ |
| 492 | 471 | (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD) |
| 493 | 472 | |
| 494 | 473 | #define SANITIZER_INTERCEPT_GETLOADAVG \ |
| 495 | (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_OPENBSD) | |
| 474 | (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD) | |
| 496 | 475 | |
| 497 | 476 | #define SANITIZER_INTERCEPT_MMAP SI_POSIX |
| 498 | 477 | #define SANITIZER_INTERCEPT_MMAP64 SI_LINUX_NOT_ANDROID |
| 499 | #define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO \ | |
| 500 | (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \ | |
| 501 | SI_NOT_RTEMS) | |
| 502 | #define SANITIZER_INTERCEPT_MEMALIGN \ | |
| 503 | (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_RTEMS) | |
| 504 | #define SANITIZER_INTERCEPT_PVALLOC \ | |
| 505 | (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \ | |
| 506 | SI_NOT_RTEMS) | |
| 507 | #define SANITIZER_INTERCEPT_CFREE \ | |
| 508 | (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \ | |
| 509 | SI_NOT_RTEMS) | |
| 478 | #define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (SI_GLIBC || SI_ANDROID) | |
| 479 | #define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD) | |
| 480 | #define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC | |
| 481 | #define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID) | |
| 482 | #define SANITIZER_INTERCEPT_CFREE (SI_GLIBC && !SANITIZER_RISCV64) | |
| 510 | 483 | #define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX |
| 511 | #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS) | |
| 512 | #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE \ | |
| 513 | (!SI_MAC && !SI_OPENBSD && !SI_NETBSD) | |
| 484 | #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC) | |
| 485 | #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD) | |
| 514 | 486 | #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID |
| 515 | 487 | #define SANITIZER_INTERCEPT_WCSCAT SI_POSIX |
| 516 | 488 | #define SANITIZER_INTERCEPT_WCSDUP SI_POSIX |
| 517 | 489 | #define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA) |
| 518 | 490 | #define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID |
| 519 | 491 | |
| 520 | #define SANITIZER_INTERCEPT_ACCT (SI_NETBSD || SI_OPENBSD || SI_FREEBSD) | |
| 492 | #define SANITIZER_INTERCEPT_ACCT (SI_NETBSD || SI_FREEBSD) | |
| 521 | 493 | #define SANITIZER_INTERCEPT_USER_FROM_UID SI_NETBSD |
| 522 | 494 | #define SANITIZER_INTERCEPT_UID_FROM_USER SI_NETBSD |
| 523 | 495 | #define SANITIZER_INTERCEPT_GROUP_FROM_GID SI_NETBSD |
| 524 | 496 | #define SANITIZER_INTERCEPT_GID_FROM_GROUP SI_NETBSD |
| 525 | #define SANITIZER_INTERCEPT_ACCESS (SI_NETBSD || SI_OPENBSD || SI_FREEBSD) | |
| 526 | #define SANITIZER_INTERCEPT_FACCESSAT (SI_NETBSD || SI_OPENBSD || SI_FREEBSD) | |
| 527 | #define SANITIZER_INTERCEPT_GETGROUPLIST (SI_NETBSD || SI_OPENBSD) | |
| 528 | #define SANITIZER_INTERCEPT_STRLCPY \ | |
| 529 | (SI_NETBSD || SI_FREEBSD || SI_OPENBSD || SI_MAC || SI_ANDROID) | |
| 497 | #define SANITIZER_INTERCEPT_ACCESS (SI_NETBSD || SI_FREEBSD) | |
| 498 | #define SANITIZER_INTERCEPT_FACCESSAT (SI_NETBSD || SI_FREEBSD) | |
| 499 | #define SANITIZER_INTERCEPT_GETGROUPLIST SI_NETBSD | |
| 500 | #define SANITIZER_INTERCEPT_STRLCPY \ | |
| 501 | (SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID) | |
| 530 | 502 | |
| 531 | 503 | #define SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT SI_LINUX_NOT_ANDROID |
| 532 | 504 | #define SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT SI_LINUX_NOT_ANDROID |
| ... | ... | @@ -534,23 +506,23 @@ |
| 534 | 506 | #define SANITIZER_INTERCEPT_READLINK SI_POSIX |
| 535 | 507 | #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ |
| 536 | 508 | __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000 |
| 537 | # define SI_MAC_DEPLOYMENT_BELOW_10_10 1 | |
| 509 | #define SI_MAC_DEPLOYMENT_BELOW_10_10 1 | |
| 538 | 510 | #else |
| 539 | # define SI_MAC_DEPLOYMENT_BELOW_10_10 0 | |
| 511 | #define SI_MAC_DEPLOYMENT_BELOW_10_10 0 | |
| 540 | 512 | #endif |
| 541 | 513 | #define SANITIZER_INTERCEPT_READLINKAT \ |
| 542 | 514 | (SI_POSIX && !SI_MAC_DEPLOYMENT_BELOW_10_10) |
| 543 | 515 | |
| 544 | #define SANITIZER_INTERCEPT_DEVNAME (SI_NETBSD || SI_OPENBSD || SI_FREEBSD) | |
| 516 | #define SANITIZER_INTERCEPT_DEVNAME (SI_NETBSD || SI_FREEBSD) | |
| 545 | 517 | #define SANITIZER_INTERCEPT_DEVNAME_R (SI_NETBSD || SI_FREEBSD) |
| 546 | 518 | #define SANITIZER_INTERCEPT_FGETLN (SI_NETBSD || SI_FREEBSD) |
| 547 | 519 | #define SANITIZER_INTERCEPT_STRMODE (SI_NETBSD || SI_FREEBSD) |
| 548 | 520 | #define SANITIZER_INTERCEPT_TTYENT SI_NETBSD |
| 549 | 521 | #define SANITIZER_INTERCEPT_PROTOENT (SI_NETBSD || SI_LINUX) |
| 550 | #define SANITIZER_INTERCEPT_PROTOENT_R (SI_LINUX_NOT_ANDROID) | |
| 522 | #define SANITIZER_INTERCEPT_PROTOENT_R SI_GLIBC | |
| 551 | 523 | #define SANITIZER_INTERCEPT_NETENT SI_NETBSD |
| 552 | #define SANITIZER_INTERCEPT_SETVBUF (SI_NETBSD || SI_FREEBSD || \ | |
| 553 | SI_LINUX || SI_MAC) | |
| 524 | #define SANITIZER_INTERCEPT_SETVBUF \ | |
| 525 | (SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC) | |
| 554 | 526 | #define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC) |
| 555 | 527 | #define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD |
| 556 | 528 | #define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD |
| ... | ... | @@ -598,12 +570,34 @@ |
| 598 | 570 | #define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD |
| 599 | 571 | #define SANITIZER_INTERCEPT_QSORT \ |
| 600 | 572 | (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID) |
| 601 | #define SANITIZER_INTERCEPT_QSORT_R (SI_LINUX && !SI_ANDROID) | |
| 573 | #define SANITIZER_INTERCEPT_QSORT_R SI_GLIBC | |
| 602 | 574 | // sigaltstack on i386 macOS cannot be intercepted due to setjmp() |
| 603 | 575 | // calling it and assuming that it does not clobber registers. |
| 604 | 576 | #define SANITIZER_INTERCEPT_SIGALTSTACK \ |
| 605 | 577 | (SI_POSIX && !(SANITIZER_MAC && SANITIZER_I386)) |
| 606 | 578 | #define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD) |
| 607 | 579 | #define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD |
| 580 | #define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD | |
| 581 | ||
| 582 | // This macro gives a way for downstream users to override the above | |
| 583 | // interceptor macros irrespective of the platform they are on. They have | |
| 584 | // to do two things: | |
| 585 | // 1. Build compiler-rt with -DSANITIZER_OVERRIDE_INTERCEPTORS. | |
| 586 | // 2. Provide a header file named sanitizer_intercept_overriders.h in the | |
| 587 | // include path for their compiler-rt build. | |
| 588 | // An example of an overrider for strlen interceptor that one can list in | |
| 589 | // sanitizer_intercept_overriders.h is as follows: | |
| 590 | // | |
| 591 | // #ifdef SANITIZER_INTERCEPT_STRLEN | |
| 592 | // #undef SANITIZER_INTERCEPT_STRLEN | |
| 593 | // #define SANITIZER_INTERCEPT_STRLEN <value of choice> | |
| 594 | // #endif | |
| 595 | // | |
| 596 | // This "feature" is useful for downstream users who do not want some of | |
| 597 | // their libc funtions to be intercepted. They can selectively disable | |
| 598 | // interception of those functions. | |
| 599 | #ifdef SANITIZER_OVERRIDE_INTERCEPTORS | |
| 600 | #include <sanitizer_intercept_overriders.h> | |
| 601 | #endif | |
| 608 | 602 | |
| 609 | 603 | #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H |
lib/tsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp+3-2| ... | ... | @@ -35,7 +35,10 @@ |
| 35 | 35 | #include <sys/stat.h> |
| 36 | 36 | #include <sys/statvfs.h> |
| 37 | 37 | #include <sys/time.h> |
| 38 | #pragma clang diagnostic push | |
| 39 | #pragma clang diagnostic ignored "-W#warnings" | |
| 38 | 40 | #include <sys/timeb.h> |
| 41 | #pragma clang diagnostic pop | |
| 39 | 42 | #include <sys/times.h> |
| 40 | 43 | #include <sys/timespec.h> |
| 41 | 44 | #include <sys/types.h> |
| ... | ... | @@ -81,8 +84,6 @@ |
| 81 | 84 | #include <sys/shm.h> |
| 82 | 85 | #undef _KERNEL |
| 83 | 86 | |
| 84 | #undef INLINE // to avoid clashes with sanitizers' definitions | |
| 85 | ||
| 86 | 87 | #undef IOC_DIRMASK |
| 87 | 88 | |
| 88 | 89 | // Include these after system headers to avoid name clashes and ambiguities. |
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.cpp+154-1| ... | ... | @@ -34,6 +34,7 @@ |
| 34 | 34 | #include <sys/chio.h> |
| 35 | 35 | #include <sys/clockctl.h> |
| 36 | 36 | #include <sys/cpuio.h> |
| 37 | #include <sys/dkbad.h> | |
| 37 | 38 | #include <sys/dkio.h> |
| 38 | 39 | #include <sys/drvctlio.h> |
| 39 | 40 | #include <sys/dvdio.h> |
| ... | ... | @@ -83,6 +84,7 @@ |
| 83 | 84 | |
| 84 | 85 | #include <sys/resource.h> |
| 85 | 86 | #include <sys/sem.h> |
| 87 | #include <sys/scsiio.h> | |
| 86 | 88 | #include <sys/sha1.h> |
| 87 | 89 | #include <sys/sha2.h> |
| 88 | 90 | #include <sys/shm.h> |
| ... | ... | @@ -139,7 +141,158 @@ |
| 139 | 141 | #include <dev/ir/irdaio.h> |
| 140 | 142 | #include <dev/isa/isvio.h> |
| 141 | 143 | #include <dev/isa/wtreg.h> |
| 144 | #if __has_include(<dev/iscsi/iscsi_ioctl.h>) | |
| 142 | 145 | #include <dev/iscsi/iscsi_ioctl.h> |
| 146 | #else | |
| 147 | /* Fallback for MKISCSI=no */ | |
| 148 | ||
| 149 | typedef struct { | |
| 150 | uint32_t status; | |
| 151 | uint32_t session_id; | |
| 152 | uint32_t connection_id; | |
| 153 | } iscsi_conn_status_parameters_t; | |
| 154 | ||
| 155 | typedef struct { | |
| 156 | uint32_t status; | |
| 157 | uint16_t interface_version; | |
| 158 | uint16_t major; | |
| 159 | uint16_t minor; | |
| 160 | uint8_t version_string[224]; | |
| 161 | } iscsi_get_version_parameters_t; | |
| 162 | ||
| 163 | typedef struct { | |
| 164 | uint32_t status; | |
| 165 | uint32_t session_id; | |
| 166 | uint32_t connection_id; | |
| 167 | struct { | |
| 168 | unsigned int immediate : 1; | |
| 169 | } options; | |
| 170 | uint64_t lun; | |
| 171 | scsireq_t req; /* from <sys/scsiio.h> */ | |
| 172 | } iscsi_iocommand_parameters_t; | |
| 173 | ||
| 174 | typedef enum { | |
| 175 | ISCSI_AUTH_None = 0, | |
| 176 | ISCSI_AUTH_CHAP = 1, | |
| 177 | ISCSI_AUTH_KRB5 = 2, | |
| 178 | ISCSI_AUTH_SRP = 3 | |
| 179 | } iscsi_auth_types_t; | |
| 180 | ||
| 181 | typedef enum { | |
| 182 | ISCSI_LOGINTYPE_DISCOVERY = 0, | |
| 183 | ISCSI_LOGINTYPE_NOMAP = 1, | |
| 184 | ISCSI_LOGINTYPE_MAP = 2 | |
| 185 | } iscsi_login_session_type_t; | |
| 186 | ||
| 187 | typedef enum { ISCSI_DIGEST_None = 0, ISCSI_DIGEST_CRC32C = 1 } iscsi_digest_t; | |
| 188 | ||
| 189 | typedef enum { | |
| 190 | ISCSI_SESSION_TERMINATED = 1, | |
| 191 | ISCSI_CONNECTION_TERMINATED, | |
| 192 | ISCSI_RECOVER_CONNECTION, | |
| 193 | ISCSI_DRIVER_TERMINATING | |
| 194 | } iscsi_event_t; | |
| 195 | ||
| 196 | typedef struct { | |
| 197 | unsigned int mutual_auth : 1; | |
| 198 | unsigned int is_secure : 1; | |
| 199 | unsigned int auth_number : 4; | |
| 200 | iscsi_auth_types_t auth_type[4]; | |
| 201 | } iscsi_auth_info_t; | |
| 202 | ||
| 203 | typedef struct { | |
| 204 | uint32_t status; | |
| 205 | int socket; | |
| 206 | struct { | |
| 207 | unsigned int HeaderDigest : 1; | |
| 208 | unsigned int DataDigest : 1; | |
| 209 | unsigned int MaxConnections : 1; | |
| 210 | unsigned int DefaultTime2Wait : 1; | |
| 211 | unsigned int DefaultTime2Retain : 1; | |
| 212 | unsigned int MaxRecvDataSegmentLength : 1; | |
| 213 | unsigned int auth_info : 1; | |
| 214 | unsigned int user_name : 1; | |
| 215 | unsigned int password : 1; | |
| 216 | unsigned int target_password : 1; | |
| 217 | unsigned int TargetName : 1; | |
| 218 | unsigned int TargetAlias : 1; | |
| 219 | unsigned int ErrorRecoveryLevel : 1; | |
| 220 | } is_present; | |
| 221 | iscsi_auth_info_t auth_info; | |
| 222 | iscsi_login_session_type_t login_type; | |
| 223 | iscsi_digest_t HeaderDigest; | |
| 224 | iscsi_digest_t DataDigest; | |
| 225 | uint32_t session_id; | |
| 226 | uint32_t connection_id; | |
| 227 | uint32_t MaxRecvDataSegmentLength; | |
| 228 | uint16_t MaxConnections; | |
| 229 | uint16_t DefaultTime2Wait; | |
| 230 | uint16_t DefaultTime2Retain; | |
| 231 | uint16_t ErrorRecoveryLevel; | |
| 232 | void *user_name; | |
| 233 | void *password; | |
| 234 | void *target_password; | |
| 235 | void *TargetName; | |
| 236 | void *TargetAlias; | |
| 237 | } iscsi_login_parameters_t; | |
| 238 | ||
| 239 | typedef struct { | |
| 240 | uint32_t status; | |
| 241 | uint32_t session_id; | |
| 242 | } iscsi_logout_parameters_t; | |
| 243 | ||
| 244 | typedef struct { | |
| 245 | uint32_t status; | |
| 246 | uint32_t event_id; | |
| 247 | } iscsi_register_event_parameters_t; | |
| 248 | ||
| 249 | typedef struct { | |
| 250 | uint32_t status; | |
| 251 | uint32_t session_id; | |
| 252 | uint32_t connection_id; | |
| 253 | } iscsi_remove_parameters_t; | |
| 254 | ||
| 255 | typedef struct { | |
| 256 | uint32_t status; | |
| 257 | uint32_t session_id; | |
| 258 | void *response_buffer; | |
| 259 | uint32_t response_size; | |
| 260 | uint32_t response_used; | |
| 261 | uint32_t response_total; | |
| 262 | uint8_t key[224]; | |
| 263 | } iscsi_send_targets_parameters_t; | |
| 264 | ||
| 265 | typedef struct { | |
| 266 | uint32_t status; | |
| 267 | uint8_t InitiatorName[224]; | |
| 268 | uint8_t InitiatorAlias[224]; | |
| 269 | uint8_t ISID[6]; | |
| 270 | } iscsi_set_node_name_parameters_t; | |
| 271 | ||
| 272 | typedef struct { | |
| 273 | uint32_t status; | |
| 274 | uint32_t event_id; | |
| 275 | iscsi_event_t event_kind; | |
| 276 | uint32_t session_id; | |
| 277 | uint32_t connection_id; | |
| 278 | uint32_t reason; | |
| 279 | } iscsi_wait_event_parameters_t; | |
| 280 | ||
| 281 | #define ISCSI_GET_VERSION _IOWR(0, 1, iscsi_get_version_parameters_t) | |
| 282 | #define ISCSI_LOGIN _IOWR(0, 2, iscsi_login_parameters_t) | |
| 283 | #define ISCSI_LOGOUT _IOWR(0, 3, iscsi_logout_parameters_t) | |
| 284 | #define ISCSI_ADD_CONNECTION _IOWR(0, 4, iscsi_login_parameters_t) | |
| 285 | #define ISCSI_RESTORE_CONNECTION _IOWR(0, 5, iscsi_login_parameters_t) | |
| 286 | #define ISCSI_REMOVE_CONNECTION _IOWR(0, 6, iscsi_remove_parameters_t) | |
| 287 | #define ISCSI_CONNECTION_STATUS _IOWR(0, 7, iscsi_conn_status_parameters_t) | |
| 288 | #define ISCSI_SEND_TARGETS _IOWR(0, 8, iscsi_send_targets_parameters_t) | |
| 289 | #define ISCSI_SET_NODE_NAME _IOWR(0, 9, iscsi_set_node_name_parameters_t) | |
| 290 | #define ISCSI_IO_COMMAND _IOWR(0, 10, iscsi_iocommand_parameters_t) | |
| 291 | #define ISCSI_REGISTER_EVENT _IOWR(0, 11, iscsi_register_event_parameters_t) | |
| 292 | #define ISCSI_DEREGISTER_EVENT _IOWR(0, 12, iscsi_register_event_parameters_t) | |
| 293 | #define ISCSI_WAIT_EVENT _IOWR(0, 13, iscsi_wait_event_parameters_t) | |
| 294 | #define ISCSI_POLL_EVENT _IOWR(0, 14, iscsi_wait_event_parameters_t) | |
| 295 | #endif | |
| 143 | 296 | #include <dev/ofw/openfirmio.h> |
| 144 | 297 | #include <dev/pci/amrio.h> |
| 145 | 298 | #include <dev/pci/mlyreg.h> |
| ... | ... | @@ -372,7 +525,7 @@ struct urio_command { |
| 372 | 525 | #include "sanitizer_platform_limits_netbsd.h" |
| 373 | 526 | |
| 374 | 527 | namespace __sanitizer { |
| 375 | void *__sanitizer_get_link_map_by_dlopen_handle(void* handle) { | |
| 528 | void *__sanitizer_get_link_map_by_dlopen_handle(void *handle) { | |
| 376 | 529 | void *p = nullptr; |
| 377 | 530 | return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) == 0 ? p : nullptr; |
| 378 | 531 | } |
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.h+2-4| ... | ... | @@ -21,8 +21,8 @@ |
| 21 | 21 | |
| 22 | 22 | namespace __sanitizer { |
| 23 | 23 | void *__sanitizer_get_link_map_by_dlopen_handle(void *handle); |
| 24 | # define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ | |
| 25 | (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle) | |
| 24 | #define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ | |
| 25 | (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle) | |
| 26 | 26 | |
| 27 | 27 | extern unsigned struct_utsname_sz; |
| 28 | 28 | extern unsigned struct_stat_sz; |
| ... | ... | @@ -1024,12 +1024,10 @@ extern unsigned struct_RF_ProgressInfo_sz; |
| 1024 | 1024 | extern unsigned struct_nvlist_ref_sz; |
| 1025 | 1025 | extern unsigned struct_StringList_sz; |
| 1026 | 1026 | |
| 1027 | ||
| 1028 | 1027 | // A special value to mark ioctls that are not present on the target platform, |
| 1029 | 1028 | // when it can not be determined without including any system headers. |
| 1030 | 1029 | extern const unsigned IOCTL_NOT_PRESENT; |
| 1031 | 1030 | |
| 1032 | ||
| 1033 | 1031 | extern unsigned IOCTL_AFM_ADDFMAP; |
| 1034 | 1032 | extern unsigned IOCTL_AFM_DELFMAP; |
| 1035 | 1033 | extern unsigned IOCTL_AFM_CLEANFMAP; |
lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.cpp-279| ... | ... | @@ -1,279 +0,0 @@ |
| 1 | //===-- sanitizer_platform_limits_openbsd.cpp -----------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is a part of Sanitizer common code. | |
| 10 | // | |
| 11 | // Sizes and layouts of platform-specific NetBSD data structures. | |
| 12 | //===----------------------------------------------------------------------===// | |
| 13 | ||
| 14 | #include "sanitizer_platform.h" | |
| 15 | ||
| 16 | #if SANITIZER_OPENBSD | |
| 17 | #include <arpa/inet.h> | |
| 18 | #include <dirent.h> | |
| 19 | #include <glob.h> | |
| 20 | #include <grp.h> | |
| 21 | #include <ifaddrs.h> | |
| 22 | #include <limits.h> | |
| 23 | #include <link_elf.h> | |
| 24 | #include <sys/socket.h> | |
| 25 | #include <net/if.h> | |
| 26 | #include <net/ppp_defs.h> | |
| 27 | #include <net/route.h> | |
| 28 | #include <netdb.h> | |
| 29 | #include <netinet/in.h> | |
| 30 | #include <netinet/ip_mroute.h> | |
| 31 | #include <poll.h> | |
| 32 | #include <pthread.h> | |
| 33 | #include <pwd.h> | |
| 34 | #include <semaphore.h> | |
| 35 | #include <signal.h> | |
| 36 | #include <soundcard.h> | |
| 37 | #include <stddef.h> | |
| 38 | #include <stdint.h> | |
| 39 | #include <sys/filio.h> | |
| 40 | #include <sys/ipc.h> | |
| 41 | #include <sys/mman.h> | |
| 42 | #include <sys/mount.h> | |
| 43 | #include <sys/msg.h> | |
| 44 | #include <sys/mtio.h> | |
| 45 | #include <sys/ptrace.h> | |
| 46 | #include <sys/resource.h> | |
| 47 | #include <sys/shm.h> | |
| 48 | #include <sys/signal.h> | |
| 49 | #include <sys/sockio.h> | |
| 50 | #include <sys/stat.h> | |
| 51 | #include <sys/statvfs.h> | |
| 52 | #include <sys/time.h> | |
| 53 | #include <sys/times.h> | |
| 54 | #include <sys/types.h> | |
| 55 | #include <sys/utsname.h> | |
| 56 | #include <term.h> | |
| 57 | #include <time.h> | |
| 58 | #include <utime.h> | |
| 59 | #include <utmp.h> | |
| 60 | #include <wchar.h> | |
| 61 | ||
| 62 | // Include these after system headers to avoid name clashes and ambiguities. | |
| 63 | #include "sanitizer_internal_defs.h" | |
| 64 | #include "sanitizer_platform_limits_openbsd.h" | |
| 65 | ||
| 66 | namespace __sanitizer { | |
| 67 | unsigned struct_utsname_sz = sizeof(struct utsname); | |
| 68 | unsigned struct_stat_sz = sizeof(struct stat); | |
| 69 | unsigned struct_rusage_sz = sizeof(struct rusage); | |
| 70 | unsigned struct_tm_sz = sizeof(struct tm); | |
| 71 | unsigned struct_passwd_sz = sizeof(struct passwd); | |
| 72 | unsigned struct_group_sz = sizeof(struct group); | |
| 73 | unsigned siginfo_t_sz = sizeof(siginfo_t); | |
| 74 | unsigned struct_sigaction_sz = sizeof(struct sigaction); | |
| 75 | unsigned struct_stack_t_sz = sizeof(stack_t); | |
| 76 | unsigned struct_itimerval_sz = sizeof(struct itimerval); | |
| 77 | unsigned pthread_t_sz = sizeof(pthread_t); | |
| 78 | unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t); | |
| 79 | unsigned pthread_cond_t_sz = sizeof(pthread_cond_t); | |
| 80 | unsigned pid_t_sz = sizeof(pid_t); | |
| 81 | unsigned timeval_sz = sizeof(timeval); | |
| 82 | unsigned uid_t_sz = sizeof(uid_t); | |
| 83 | unsigned gid_t_sz = sizeof(gid_t); | |
| 84 | unsigned mbstate_t_sz = sizeof(mbstate_t); | |
| 85 | unsigned sigset_t_sz = sizeof(sigset_t); | |
| 86 | unsigned struct_timezone_sz = sizeof(struct timezone); | |
| 87 | unsigned struct_tms_sz = sizeof(struct tms); | |
| 88 | unsigned struct_sched_param_sz = sizeof(struct sched_param); | |
| 89 | unsigned struct_sockaddr_sz = sizeof(struct sockaddr); | |
| 90 | unsigned struct_rlimit_sz = sizeof(struct rlimit); | |
| 91 | unsigned struct_timespec_sz = sizeof(struct timespec); | |
| 92 | unsigned struct_utimbuf_sz = sizeof(struct utimbuf); | |
| 93 | unsigned struct_itimerspec_sz = sizeof(struct itimerspec); | |
| 94 | unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds); | |
| 95 | unsigned struct_statvfs_sz = sizeof(struct statvfs); | |
| 96 | ||
| 97 | const uptr sig_ign = (uptr)SIG_IGN; | |
| 98 | const uptr sig_dfl = (uptr)SIG_DFL; | |
| 99 | const uptr sig_err = (uptr)SIG_ERR; | |
| 100 | const uptr sa_siginfo = (uptr)SA_SIGINFO; | |
| 101 | ||
| 102 | int shmctl_ipc_stat = (int)IPC_STAT; | |
| 103 | ||
| 104 | unsigned struct_utmp_sz = sizeof(struct utmp); | |
| 105 | ||
| 106 | int map_fixed = MAP_FIXED; | |
| 107 | ||
| 108 | int af_inet = (int)AF_INET; | |
| 109 | int af_inet6 = (int)AF_INET6; | |
| 110 | ||
| 111 | uptr __sanitizer_in_addr_sz(int af) { | |
| 112 | if (af == AF_INET) | |
| 113 | return sizeof(struct in_addr); | |
| 114 | else if (af == AF_INET6) | |
| 115 | return sizeof(struct in6_addr); | |
| 116 | else | |
| 117 | return 0; | |
| 118 | } | |
| 119 | ||
| 120 | unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); | |
| 121 | ||
| 122 | int glob_nomatch = GLOB_NOMATCH; | |
| 123 | int glob_altdirfunc = GLOB_ALTDIRFUNC; | |
| 124 | ||
| 125 | unsigned path_max = PATH_MAX; | |
| 126 | ||
| 127 | const int si_SEGV_MAPERR = SEGV_MAPERR; | |
| 128 | const int si_SEGV_ACCERR = SEGV_ACCERR; | |
| 129 | } // namespace __sanitizer | |
| 130 | ||
| 131 | using namespace __sanitizer; | |
| 132 | ||
| 133 | COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t)); | |
| 134 | ||
| 135 | COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned)); | |
| 136 | CHECK_TYPE_SIZE(pthread_key_t); | |
| 137 | ||
| 138 | CHECK_TYPE_SIZE(dl_phdr_info); | |
| 139 | CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr); | |
| 140 | CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name); | |
| 141 | CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr); | |
| 142 | CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum); | |
| 143 | ||
| 144 | CHECK_TYPE_SIZE(glob_t); | |
| 145 | CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc); | |
| 146 | CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv); | |
| 147 | CHECK_SIZE_AND_OFFSET(glob_t, gl_offs); | |
| 148 | CHECK_SIZE_AND_OFFSET(glob_t, gl_flags); | |
| 149 | CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir); | |
| 150 | CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir); | |
| 151 | CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir); | |
| 152 | CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat); | |
| 153 | CHECK_SIZE_AND_OFFSET(glob_t, gl_stat); | |
| 154 | ||
| 155 | CHECK_TYPE_SIZE(addrinfo); | |
| 156 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags); | |
| 157 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_family); | |
| 158 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype); | |
| 159 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol); | |
| 160 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen); | |
| 161 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr); | |
| 162 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname); | |
| 163 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_next); | |
| 164 | ||
| 165 | CHECK_TYPE_SIZE(hostent); | |
| 166 | CHECK_SIZE_AND_OFFSET(hostent, h_name); | |
| 167 | CHECK_SIZE_AND_OFFSET(hostent, h_aliases); | |
| 168 | CHECK_SIZE_AND_OFFSET(hostent, h_addrtype); | |
| 169 | CHECK_SIZE_AND_OFFSET(hostent, h_length); | |
| 170 | CHECK_SIZE_AND_OFFSET(hostent, h_addr_list); | |
| 171 | ||
| 172 | CHECK_TYPE_SIZE(iovec); | |
| 173 | CHECK_SIZE_AND_OFFSET(iovec, iov_base); | |
| 174 | CHECK_SIZE_AND_OFFSET(iovec, iov_len); | |
| 175 | ||
| 176 | CHECK_TYPE_SIZE(msghdr); | |
| 177 | CHECK_SIZE_AND_OFFSET(msghdr, msg_name); | |
| 178 | CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen); | |
| 179 | CHECK_SIZE_AND_OFFSET(msghdr, msg_iov); | |
| 180 | CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen); | |
| 181 | CHECK_SIZE_AND_OFFSET(msghdr, msg_control); | |
| 182 | CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen); | |
| 183 | CHECK_SIZE_AND_OFFSET(msghdr, msg_flags); | |
| 184 | ||
| 185 | CHECK_TYPE_SIZE(cmsghdr); | |
| 186 | CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len); | |
| 187 | CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level); | |
| 188 | CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type); | |
| 189 | ||
| 190 | COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent)); | |
| 191 | CHECK_SIZE_AND_OFFSET(dirent, d_fileno); | |
| 192 | CHECK_SIZE_AND_OFFSET(dirent, d_off); | |
| 193 | CHECK_SIZE_AND_OFFSET(dirent, d_reclen); | |
| 194 | ||
| 195 | CHECK_TYPE_SIZE(ifconf); | |
| 196 | CHECK_SIZE_AND_OFFSET(ifconf, ifc_len); | |
| 197 | CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu); | |
| 198 | ||
| 199 | CHECK_TYPE_SIZE(pollfd); | |
| 200 | CHECK_SIZE_AND_OFFSET(pollfd, fd); | |
| 201 | CHECK_SIZE_AND_OFFSET(pollfd, events); | |
| 202 | CHECK_SIZE_AND_OFFSET(pollfd, revents); | |
| 203 | ||
| 204 | CHECK_TYPE_SIZE(nfds_t); | |
| 205 | ||
| 206 | CHECK_TYPE_SIZE(sigset_t); | |
| 207 | ||
| 208 | COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction)); | |
| 209 | // Can't write checks for sa_handler and sa_sigaction due to them being | |
| 210 | // preprocessor macros. | |
| 211 | CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask); | |
| 212 | ||
| 213 | CHECK_TYPE_SIZE(tm); | |
| 214 | CHECK_SIZE_AND_OFFSET(tm, tm_sec); | |
| 215 | CHECK_SIZE_AND_OFFSET(tm, tm_min); | |
| 216 | CHECK_SIZE_AND_OFFSET(tm, tm_hour); | |
| 217 | CHECK_SIZE_AND_OFFSET(tm, tm_mday); | |
| 218 | CHECK_SIZE_AND_OFFSET(tm, tm_mon); | |
| 219 | CHECK_SIZE_AND_OFFSET(tm, tm_year); | |
| 220 | CHECK_SIZE_AND_OFFSET(tm, tm_wday); | |
| 221 | CHECK_SIZE_AND_OFFSET(tm, tm_yday); | |
| 222 | CHECK_SIZE_AND_OFFSET(tm, tm_isdst); | |
| 223 | CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff); | |
| 224 | CHECK_SIZE_AND_OFFSET(tm, tm_zone); | |
| 225 | ||
| 226 | CHECK_TYPE_SIZE(ipc_perm); | |
| 227 | CHECK_SIZE_AND_OFFSET(ipc_perm, cuid); | |
| 228 | CHECK_SIZE_AND_OFFSET(ipc_perm, cgid); | |
| 229 | CHECK_SIZE_AND_OFFSET(ipc_perm, uid); | |
| 230 | CHECK_SIZE_AND_OFFSET(ipc_perm, gid); | |
| 231 | CHECK_SIZE_AND_OFFSET(ipc_perm, mode); | |
| 232 | CHECK_SIZE_AND_OFFSET(ipc_perm, seq); | |
| 233 | CHECK_SIZE_AND_OFFSET(ipc_perm, key); | |
| 234 | ||
| 235 | CHECK_TYPE_SIZE(shmid_ds); | |
| 236 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm); | |
| 237 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz); | |
| 238 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime); | |
| 239 | CHECK_SIZE_AND_OFFSET(shmid_ds, __shm_atimensec); | |
| 240 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime); | |
| 241 | CHECK_SIZE_AND_OFFSET(shmid_ds, __shm_dtimensec); | |
| 242 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime); | |
| 243 | CHECK_SIZE_AND_OFFSET(shmid_ds, __shm_ctimensec); | |
| 244 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid); | |
| 245 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid); | |
| 246 | CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch); | |
| 247 | ||
| 248 | CHECK_TYPE_SIZE(clock_t); | |
| 249 | ||
| 250 | CHECK_TYPE_SIZE(ifaddrs); | |
| 251 | CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next); | |
| 252 | CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name); | |
| 253 | CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr); | |
| 254 | CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask); | |
| 255 | // Compare against the union, because we can't reach into the union in a | |
| 256 | // compliant way. | |
| 257 | #ifdef ifa_dstaddr | |
| 258 | #undef ifa_dstaddr | |
| 259 | #endif | |
| 260 | CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr); | |
| 261 | CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data); | |
| 262 | ||
| 263 | CHECK_TYPE_SIZE(passwd); | |
| 264 | CHECK_SIZE_AND_OFFSET(passwd, pw_name); | |
| 265 | CHECK_SIZE_AND_OFFSET(passwd, pw_passwd); | |
| 266 | CHECK_SIZE_AND_OFFSET(passwd, pw_uid); | |
| 267 | CHECK_SIZE_AND_OFFSET(passwd, pw_gid); | |
| 268 | CHECK_SIZE_AND_OFFSET(passwd, pw_dir); | |
| 269 | CHECK_SIZE_AND_OFFSET(passwd, pw_shell); | |
| 270 | ||
| 271 | CHECK_SIZE_AND_OFFSET(passwd, pw_gecos); | |
| 272 | ||
| 273 | CHECK_TYPE_SIZE(group); | |
| 274 | CHECK_SIZE_AND_OFFSET(group, gr_name); | |
| 275 | CHECK_SIZE_AND_OFFSET(group, gr_passwd); | |
| 276 | CHECK_SIZE_AND_OFFSET(group, gr_gid); | |
| 277 | CHECK_SIZE_AND_OFFSET(group, gr_mem); | |
| 278 | ||
| 279 | #endif // SANITIZER_OPENBSD |
lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.h-382| ... | ... | @@ -1,382 +0,0 @@ |
| 1 | //===-- sanitizer_platform_limits_openbsd.h -------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is a part of Sanitizer common code. | |
| 10 | // | |
| 11 | // Sizes and layouts of platform-specific OpenBSD data structures. | |
| 12 | //===----------------------------------------------------------------------===// | |
| 13 | ||
| 14 | #ifndef SANITIZER_PLATFORM_LIMITS_OPENBSD_H | |
| 15 | #define SANITIZER_PLATFORM_LIMITS_OPENBSD_H | |
| 16 | ||
| 17 | #if SANITIZER_OPENBSD | |
| 18 | ||
| 19 | #include "sanitizer_internal_defs.h" | |
| 20 | #include "sanitizer_platform.h" | |
| 21 | ||
| 22 | #define _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, shift) \ | |
| 23 | ((link_map *)((handle) == nullptr ? nullptr : ((char *)(handle) + (shift)))) | |
| 24 | ||
| 25 | #if defined(__x86_64__) | |
| 26 | #define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ | |
| 27 | _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, 312) | |
| 28 | #elif defined(__i386__) | |
| 29 | #define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ | |
| 30 | _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, 164) | |
| 31 | #endif | |
| 32 | ||
| 33 | #define RLIMIT_AS RLIMIT_DATA | |
| 34 | ||
| 35 | namespace __sanitizer { | |
| 36 | extern unsigned struct_utsname_sz; | |
| 37 | extern unsigned struct_stat_sz; | |
| 38 | extern unsigned struct_rusage_sz; | |
| 39 | extern unsigned siginfo_t_sz; | |
| 40 | extern unsigned struct_itimerval_sz; | |
| 41 | extern unsigned pthread_t_sz; | |
| 42 | extern unsigned pthread_mutex_t_sz; | |
| 43 | extern unsigned pthread_cond_t_sz; | |
| 44 | extern unsigned pid_t_sz; | |
| 45 | extern unsigned timeval_sz; | |
| 46 | extern unsigned uid_t_sz; | |
| 47 | extern unsigned gid_t_sz; | |
| 48 | extern unsigned mbstate_t_sz; | |
| 49 | extern unsigned struct_timezone_sz; | |
| 50 | extern unsigned struct_tms_sz; | |
| 51 | extern unsigned struct_itimerspec_sz; | |
| 52 | extern unsigned struct_sigevent_sz; | |
| 53 | extern unsigned struct_stack_t_sz; | |
| 54 | extern unsigned struct_statfs_sz; | |
| 55 | extern unsigned struct_sockaddr_sz; | |
| 56 | ||
| 57 | extern unsigned struct_rlimit_sz; | |
| 58 | extern unsigned struct_utimbuf_sz; | |
| 59 | extern unsigned struct_timespec_sz; | |
| 60 | ||
| 61 | struct __sanitizer_iocb { | |
| 62 | u64 aio_offset; | |
| 63 | uptr aio_buf; | |
| 64 | long aio_nbytes; | |
| 65 | u32 aio_fildes; | |
| 66 | u32 aio_lio_opcode; | |
| 67 | long aio_reqprio; | |
| 68 | #if SANITIZER_WORDSIZE == 64 | |
| 69 | u8 aio_sigevent[32]; | |
| 70 | #else | |
| 71 | u8 aio_sigevent[20]; | |
| 72 | #endif | |
| 73 | u32 _state; | |
| 74 | u32 _errno; | |
| 75 | long _retval; | |
| 76 | }; | |
| 77 | ||
| 78 | struct __sanitizer___sysctl_args { | |
| 79 | int *name; | |
| 80 | int nlen; | |
| 81 | void *oldval; | |
| 82 | uptr *oldlenp; | |
| 83 | void *newval; | |
| 84 | uptr newlen; | |
| 85 | }; | |
| 86 | ||
| 87 | struct __sanitizer_sem_t { | |
| 88 | uptr data[5]; | |
| 89 | }; | |
| 90 | ||
| 91 | struct __sanitizer_ipc_perm { | |
| 92 | u32 cuid; | |
| 93 | u32 cgid; | |
| 94 | u32 uid; | |
| 95 | u32 gid; | |
| 96 | u32 mode; | |
| 97 | unsigned short seq; | |
| 98 | long key; | |
| 99 | }; | |
| 100 | ||
| 101 | struct __sanitizer_shmid_ds { | |
| 102 | __sanitizer_ipc_perm shm_perm; | |
| 103 | int shm_segsz; | |
| 104 | u32 shm_lpid; | |
| 105 | u32 shm_cpid; | |
| 106 | short shm_nattch; | |
| 107 | u64 shm_atime; | |
| 108 | long __shm_atimensec; | |
| 109 | u64 shm_dtime; | |
| 110 | long __shm_dtimensec; | |
| 111 | u64 shm_ctime; | |
| 112 | long __shm_ctimensec; | |
| 113 | void *_shm_internal; | |
| 114 | }; | |
| 115 | ||
| 116 | extern unsigned struct_msqid_ds_sz; | |
| 117 | extern unsigned struct_mq_attr_sz; | |
| 118 | extern unsigned struct_timex_sz; | |
| 119 | extern unsigned struct_statvfs_sz; | |
| 120 | ||
| 121 | struct __sanitizer_iovec { | |
| 122 | void *iov_base; | |
| 123 | uptr iov_len; | |
| 124 | }; | |
| 125 | ||
| 126 | struct __sanitizer_ifaddrs { | |
| 127 | struct __sanitizer_ifaddrs *ifa_next; | |
| 128 | char *ifa_name; | |
| 129 | unsigned int ifa_flags; | |
| 130 | struct __sanitizer_sockaddr *ifa_addr; // (struct sockaddr *) | |
| 131 | struct __sanitizer_sockaddr *ifa_netmask; // (struct sockaddr *) | |
| 132 | struct __sanitizer_sockaddr *ifa_dstaddr; // (struct sockaddr *) | |
| 133 | void *ifa_data; | |
| 134 | }; | |
| 135 | ||
| 136 | typedef unsigned __sanitizer_pthread_key_t; | |
| 137 | ||
| 138 | typedef long long __sanitizer_time_t; | |
| 139 | typedef int __sanitizer_suseconds_t; | |
| 140 | ||
| 141 | struct __sanitizer_timeval { | |
| 142 | __sanitizer_time_t tv_sec; | |
| 143 | __sanitizer_suseconds_t tv_usec; | |
| 144 | }; | |
| 145 | ||
| 146 | struct __sanitizer_itimerval { | |
| 147 | struct __sanitizer_timeval it_interval; | |
| 148 | struct __sanitizer_timeval it_value; | |
| 149 | }; | |
| 150 | ||
| 151 | struct __sanitizer_passwd { | |
| 152 | char *pw_name; | |
| 153 | char *pw_passwd; | |
| 154 | int pw_uid; | |
| 155 | int pw_gid; | |
| 156 | __sanitizer_time_t pw_change; | |
| 157 | char *pw_class; | |
| 158 | char *pw_gecos; | |
| 159 | char *pw_dir; | |
| 160 | char *pw_shell; | |
| 161 | __sanitizer_time_t pw_expire; | |
| 162 | }; | |
| 163 | ||
| 164 | struct __sanitizer_group { | |
| 165 | char *gr_name; | |
| 166 | char *gr_passwd; | |
| 167 | int gr_gid; | |
| 168 | char **gr_mem; | |
| 169 | }; | |
| 170 | ||
| 171 | struct __sanitizer_ether_addr { | |
| 172 | u8 octet[6]; | |
| 173 | }; | |
| 174 | ||
| 175 | struct __sanitizer_tm { | |
| 176 | int tm_sec; | |
| 177 | int tm_min; | |
| 178 | int tm_hour; | |
| 179 | int tm_mday; | |
| 180 | int tm_mon; | |
| 181 | int tm_year; | |
| 182 | int tm_wday; | |
| 183 | int tm_yday; | |
| 184 | int tm_isdst; | |
| 185 | long int tm_gmtoff; | |
| 186 | const char *tm_zone; | |
| 187 | }; | |
| 188 | ||
| 189 | struct __sanitizer_msghdr { | |
| 190 | void *msg_name; | |
| 191 | unsigned msg_namelen; | |
| 192 | struct __sanitizer_iovec *msg_iov; | |
| 193 | unsigned msg_iovlen; | |
| 194 | void *msg_control; | |
| 195 | unsigned msg_controllen; | |
| 196 | int msg_flags; | |
| 197 | }; | |
| 198 | struct __sanitizer_cmsghdr { | |
| 199 | unsigned cmsg_len; | |
| 200 | int cmsg_level; | |
| 201 | int cmsg_type; | |
| 202 | }; | |
| 203 | ||
| 204 | struct __sanitizer_dirent { | |
| 205 | u64 d_fileno; | |
| 206 | u64 d_off; | |
| 207 | u16 d_reclen; | |
| 208 | }; | |
| 209 | ||
| 210 | typedef u64 __sanitizer_clock_t; | |
| 211 | typedef u32 __sanitizer_clockid_t; | |
| 212 | ||
| 213 | typedef u32 __sanitizer___kernel_uid_t; | |
| 214 | typedef u32 __sanitizer___kernel_gid_t; | |
| 215 | typedef u64 __sanitizer___kernel_off_t; | |
| 216 | typedef struct { | |
| 217 | u32 fds_bits[8]; | |
| 218 | } __sanitizer___kernel_fd_set; | |
| 219 | ||
| 220 | typedef struct { | |
| 221 | unsigned int pta_magic; | |
| 222 | int pta_flags; | |
| 223 | void *pta_private; | |
| 224 | } __sanitizer_pthread_attr_t; | |
| 225 | ||
| 226 | typedef unsigned int __sanitizer_sigset_t; | |
| 227 | ||
| 228 | struct __sanitizer_siginfo { | |
| 229 | // The size is determined by looking at sizeof of real siginfo_t on linux. | |
| 230 | u64 opaque[128 / sizeof(u64)]; | |
| 231 | }; | |
| 232 | ||
| 233 | using __sanitizer_sighandler_ptr = void (*)(int sig); | |
| 234 | using __sanitizer_sigactionhandler_ptr = void (*)(int sig, | |
| 235 | __sanitizer_siginfo *siginfo, | |
| 236 | void *uctx); | |
| 237 | ||
| 238 | struct __sanitizer_sigaction { | |
| 239 | union { | |
| 240 | __sanitizer_sighandler_ptr handler; | |
| 241 | __sanitizer_sigactionhandler_ptr sigaction; | |
| 242 | }; | |
| 243 | __sanitizer_sigset_t sa_mask; | |
| 244 | int sa_flags; | |
| 245 | }; | |
| 246 | ||
| 247 | typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t; | |
| 248 | ||
| 249 | struct __sanitizer_kernel_sigaction_t { | |
| 250 | union { | |
| 251 | void (*handler)(int signo); | |
| 252 | void (*sigaction)(int signo, void *info, void *ctx); | |
| 253 | }; | |
| 254 | unsigned long sa_flags; | |
| 255 | void (*sa_restorer)(void); | |
| 256 | __sanitizer_kernel_sigset_t sa_mask; | |
| 257 | }; | |
| 258 | ||
| 259 | extern const uptr sig_ign; | |
| 260 | extern const uptr sig_dfl; | |
| 261 | extern const uptr sig_err; | |
| 262 | extern const uptr sa_siginfo; | |
| 263 | ||
| 264 | extern int af_inet; | |
| 265 | extern int af_inet6; | |
| 266 | uptr __sanitizer_in_addr_sz(int af); | |
| 267 | ||
| 268 | struct __sanitizer_dl_phdr_info { | |
| 269 | #if SANITIZER_WORDSIZE == 64 | |
| 270 | u64 dlpi_addr; | |
| 271 | #else | |
| 272 | u32 dlpi_addr; | |
| 273 | #endif | |
| 274 | const char *dlpi_name; | |
| 275 | const void *dlpi_phdr; | |
| 276 | #if SANITIZER_WORDSIZE == 64 | |
| 277 | u32 dlpi_phnum; | |
| 278 | #else | |
| 279 | u16 dlpi_phnum; | |
| 280 | #endif | |
| 281 | }; | |
| 282 | ||
| 283 | extern unsigned struct_ElfW_Phdr_sz; | |
| 284 | ||
| 285 | struct __sanitizer_addrinfo { | |
| 286 | int ai_flags; | |
| 287 | int ai_family; | |
| 288 | int ai_socktype; | |
| 289 | int ai_protocol; | |
| 290 | unsigned ai_addrlen; | |
| 291 | struct __sanitizer_sockaddr *ai_addr; | |
| 292 | char *ai_canonname; | |
| 293 | struct __sanitizer_addrinfo *ai_next; | |
| 294 | }; | |
| 295 | ||
| 296 | struct __sanitizer_hostent { | |
| 297 | char *h_name; | |
| 298 | char **h_aliases; | |
| 299 | int h_addrtype; | |
| 300 | int h_length; | |
| 301 | char **h_addr_list; | |
| 302 | }; | |
| 303 | ||
| 304 | struct __sanitizer_pollfd { | |
| 305 | int fd; | |
| 306 | short events; | |
| 307 | short revents; | |
| 308 | }; | |
| 309 | ||
| 310 | typedef unsigned __sanitizer_nfds_t; | |
| 311 | ||
| 312 | struct __sanitizer_glob_t { | |
| 313 | int gl_pathc; | |
| 314 | int gl_matchc; | |
| 315 | int gl_offs; | |
| 316 | int gl_flags; | |
| 317 | char **gl_pathv; | |
| 318 | void **gl_statv; | |
| 319 | int (*gl_errfunc)(const char *, int); | |
| 320 | void (*gl_closedir)(void *dirp); | |
| 321 | struct dirent *(*gl_readdir)(void *dirp); | |
| 322 | void *(*gl_opendir)(const char *); | |
| 323 | int (*gl_lstat)(const char *, void * /* struct stat* */); | |
| 324 | int (*gl_stat)(const char *, void * /* struct stat* */); | |
| 325 | }; | |
| 326 | ||
| 327 | extern int glob_nomatch; | |
| 328 | extern int glob_altdirfunc; | |
| 329 | ||
| 330 | extern unsigned path_max; | |
| 331 | ||
| 332 | typedef char __sanitizer_FILE; | |
| 333 | #define SANITIZER_HAS_STRUCT_FILE 0 | |
| 334 | ||
| 335 | extern int shmctl_ipc_stat; | |
| 336 | ||
| 337 | // This simplifies generic code | |
| 338 | #define struct_shminfo_sz -1 | |
| 339 | #define struct_shm_info_sz -1 | |
| 340 | #define shmctl_shm_stat -1 | |
| 341 | #define shmctl_ipc_info -1 | |
| 342 | #define shmctl_shm_info -1 | |
| 343 | ||
| 344 | extern unsigned struct_utmp_sz; | |
| 345 | extern unsigned struct_utmpx_sz; | |
| 346 | ||
| 347 | extern int map_fixed; | |
| 348 | ||
| 349 | // ioctl arguments | |
| 350 | struct __sanitizer_ifconf { | |
| 351 | int ifc_len; | |
| 352 | union { | |
| 353 | void *ifcu_req; | |
| 354 | } ifc_ifcu; | |
| 355 | }; | |
| 356 | ||
| 357 | extern const int si_SEGV_MAPERR; | |
| 358 | extern const int si_SEGV_ACCERR; | |
| 359 | } // namespace __sanitizer | |
| 360 | ||
| 361 | #define CHECK_TYPE_SIZE(TYPE) \ | |
| 362 | COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE)) | |
| 363 | ||
| 364 | #define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \ | |
| 365 | COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \ | |
| 366 | sizeof(((CLASS *)NULL)->MEMBER)); \ | |
| 367 | COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \ | |
| 368 | offsetof(CLASS, MEMBER)) | |
| 369 | ||
| 370 | // For sigaction, which is a function and struct at the same time, | |
| 371 | // and thus requires explicit "struct" in sizeof() expression. | |
| 372 | #define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \ | |
| 373 | COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \ | |
| 374 | sizeof(((struct CLASS *)NULL)->MEMBER)); \ | |
| 375 | COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \ | |
| 376 | offsetof(struct CLASS, MEMBER)) | |
| 377 | ||
| 378 | #define SIGACTION_SYMNAME __sigaction14 | |
| 379 | ||
| 380 | #endif // SANITIZER_OPENBSD | |
| 381 | ||
| 382 | #endif |
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.cpp+66-53| ... | ... | @@ -11,18 +11,19 @@ |
| 11 | 11 | // Sizes and layouts of platform-specific POSIX data structures. |
| 12 | 12 | //===----------------------------------------------------------------------===// |
| 13 | 13 | |
| 14 | #include "sanitizer_platform.h" | |
| 15 | ||
| 16 | #if SANITIZER_LINUX || SANITIZER_MAC | |
| 14 | #if defined(__linux__) || defined(__APPLE__) | |
| 17 | 15 | // Tests in this file assume that off_t-dependent data structures match the |
| 18 | 16 | // libc ABI. For example, struct dirent here is what readdir() function (as |
| 19 | 17 | // exported from libc) returns, and not the user-facing "dirent", which |
| 20 | 18 | // depends on _FILE_OFFSET_BITS setting. |
| 21 | 19 | // To get this "true" dirent definition, we undefine _FILE_OFFSET_BITS below. |
| 22 | #ifdef _FILE_OFFSET_BITS | |
| 23 | 20 | #undef _FILE_OFFSET_BITS |
| 24 | 21 | #endif |
| 25 | 22 | |
| 23 | // Must go after undef _FILE_OFFSET_BITS. | |
| 24 | #include "sanitizer_platform.h" | |
| 25 | ||
| 26 | #if SANITIZER_LINUX || SANITIZER_MAC | |
| 26 | 27 | // Must go after undef _FILE_OFFSET_BITS. |
| 27 | 28 | #include "sanitizer_glibc_version.h" |
| 28 | 29 | |
| ... | ... | @@ -37,6 +38,7 @@ |
| 37 | 38 | #include <pwd.h> |
| 38 | 39 | #include <signal.h> |
| 39 | 40 | #include <stddef.h> |
| 41 | #include <stdio.h> | |
| 40 | 42 | #include <sys/mman.h> |
| 41 | 43 | #include <sys/resource.h> |
| 42 | 44 | #include <sys/socket.h> |
| ... | ... | @@ -58,7 +60,6 @@ |
| 58 | 60 | #endif |
| 59 | 61 | |
| 60 | 62 | #if !SANITIZER_ANDROID |
| 61 | #include <fstab.h> | |
| 62 | 63 | #include <sys/mount.h> |
| 63 | 64 | #include <sys/timeb.h> |
| 64 | 65 | #include <utmpx.h> |
| ... | ... | @@ -90,7 +91,8 @@ |
| 90 | 91 | #if SANITIZER_LINUX |
| 91 | 92 | # include <utime.h> |
| 92 | 93 | # include <sys/ptrace.h> |
| 93 | # if defined(__mips64) || defined(__aarch64__) || defined(__arm__) | |
| 94 | #if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \ | |
| 95 | SANITIZER_RISCV64 | |
| 94 | 96 | # include <asm/ptrace.h> |
| 95 | 97 | # ifdef __arm__ |
| 96 | 98 | typedef struct user_fpregs elf_fpregset_t; |
| ... | ... | @@ -109,20 +111,31 @@ typedef struct user_fpregs elf_fpregset_t; |
| 109 | 111 | #include <wordexp.h> |
| 110 | 112 | #endif |
| 111 | 113 | |
| 112 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 113 | #include <glob.h> | |
| 114 | #include <obstack.h> | |
| 115 | #include <mqueue.h> | |
| 114 | #if SANITIZER_LINUX | |
| 115 | #if SANITIZER_GLIBC | |
| 116 | #include <fstab.h> | |
| 116 | 117 | #include <net/if_ppp.h> |
| 117 | 118 | #include <netax25/ax25.h> |
| 118 | 119 | #include <netipx/ipx.h> |
| 119 | 120 | #include <netrom/netrom.h> |
| 121 | #include <obstack.h> | |
| 120 | 122 | #if HAVE_RPC_XDR_H |
| 121 | 123 | # include <rpc/xdr.h> |
| 122 | 124 | #endif |
| 123 | 125 | #include <scsi/scsi.h> |
| 124 | #include <sys/mtio.h> | |
| 126 | #else | |
| 127 | #include <linux/if_ppp.h> | |
| 128 | #include <linux/kd.h> | |
| 129 | #include <linux/ppp_defs.h> | |
| 130 | #endif // SANITIZER_GLIBC | |
| 131 | ||
| 132 | #if SANITIZER_ANDROID | |
| 133 | #include <linux/mtio.h> | |
| 134 | #else | |
| 135 | #include <glob.h> | |
| 136 | #include <mqueue.h> | |
| 125 | 137 | #include <sys/kd.h> |
| 138 | #include <sys/mtio.h> | |
| 126 | 139 | #include <sys/shm.h> |
| 127 | 140 | #include <sys/statvfs.h> |
| 128 | 141 | #include <sys/timex.h> |
| ... | ... | @@ -130,7 +143,6 @@ typedef struct user_fpregs elf_fpregset_t; |
| 130 | 143 | # include <sys/procfs.h> |
| 131 | 144 | #endif |
| 132 | 145 | #include <sys/user.h> |
| 133 | #include <linux/cyclades.h> | |
| 134 | 146 | #include <linux/if_eql.h> |
| 135 | 147 | #include <linux/if_plip.h> |
| 136 | 148 | #include <linux/lp.h> |
| ... | ... | @@ -141,20 +153,14 @@ typedef struct user_fpregs elf_fpregset_t; |
| 141 | 153 | #include <sys/msg.h> |
| 142 | 154 | #include <sys/ipc.h> |
| 143 | 155 | #include <crypt.h> |
| 144 | #endif // SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 156 | #endif // SANITIZER_ANDROID | |
| 145 | 157 | |
| 146 | #if SANITIZER_ANDROID | |
| 147 | #include <linux/kd.h> | |
| 148 | #include <linux/mtio.h> | |
| 149 | #include <linux/ppp_defs.h> | |
| 150 | #include <linux/if_ppp.h> | |
| 151 | #endif | |
| 152 | ||
| 153 | #if SANITIZER_LINUX | |
| 154 | 158 | #include <link.h> |
| 155 | 159 | #include <sys/vfs.h> |
| 156 | 160 | #include <sys/epoll.h> |
| 157 | 161 | #include <linux/capability.h> |
| 162 | #else | |
| 163 | #include <fstab.h> | |
| 158 | 164 | #endif // SANITIZER_LINUX |
| 159 | 165 | |
| 160 | 166 | #if SANITIZER_MAC |
| ... | ... | @@ -201,8 +207,11 @@ namespace __sanitizer { |
| 201 | 207 | unsigned struct_statfs64_sz = sizeof(struct statfs64); |
| 202 | 208 | #endif // (SANITIZER_MAC && !TARGET_CPU_ARM64) && !SANITIZER_IOS |
| 203 | 209 | |
| 204 | #if !SANITIZER_ANDROID | |
| 210 | #if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_MAC | |
| 205 | 211 | unsigned struct_fstab_sz = sizeof(struct fstab); |
| 212 | #endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD || | |
| 213 | // SANITIZER_MAC | |
| 214 | #if !SANITIZER_ANDROID | |
| 206 | 215 | unsigned struct_statfs_sz = sizeof(struct statfs); |
| 207 | 216 | unsigned struct_sockaddr_sz = sizeof(struct sockaddr); |
| 208 | 217 | unsigned ucontext_t_sz = sizeof(ucontext_t); |
| ... | ... | @@ -229,9 +238,9 @@ namespace __sanitizer { |
| 229 | 238 | #if SANITIZER_LINUX && !SANITIZER_ANDROID |
| 230 | 239 | // Use pre-computed size of struct ustat to avoid <sys/ustat.h> which |
| 231 | 240 | // has been removed from glibc 2.28. |
| 232 | #if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \ | |
| 233 | || defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) \ | |
| 234 | || defined(__x86_64__) || (defined(__riscv) && __riscv_xlen == 64) | |
| 241 | #if defined(__aarch64__) || defined(__s390x__) || defined(__mips64) || \ | |
| 242 | defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) || \ | |
| 243 | defined(__x86_64__) || SANITIZER_RISCV64 | |
| 235 | 244 | #define SIZEOF_STRUCT_USTAT 32 |
| 236 | 245 | #elif defined(__arm__) || defined(__i386__) || defined(__mips__) \ |
| 237 | 246 | || defined(__powerpc__) || defined(__s390__) || defined(__sparc__) |
| ... | ... | @@ -298,18 +307,21 @@ unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr)); |
| 298 | 307 | unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 299 | 308 | #endif |
| 300 | 309 | |
| 301 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 310 | #if SANITIZER_GLIBC | |
| 302 | 311 | int glob_nomatch = GLOB_NOMATCH; |
| 303 | 312 | int glob_altdirfunc = GLOB_ALTDIRFUNC; |
| 304 | 313 | #endif |
| 305 | 314 | |
| 306 | #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ | |
| 307 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 308 | defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ | |
| 309 | defined(__s390__)) | |
| 315 | #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ | |
| 316 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ | |
| 317 | defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ | |
| 318 | defined(__s390__) || SANITIZER_RISCV64) | |
| 310 | 319 | #if defined(__mips64) || defined(__powerpc64__) || defined(__arm__) |
| 311 | 320 | unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs); |
| 312 | 321 | unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t); |
| 322 | #elif SANITIZER_RISCV64 | |
| 323 | unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct); | |
| 324 | unsigned struct_user_fpregs_struct_sz = sizeof(struct __riscv_q_ext_state); | |
| 313 | 325 | #elif defined(__aarch64__) |
| 314 | 326 | unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs); |
| 315 | 327 | unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpsimd_state); |
| ... | ... | @@ -321,7 +333,8 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 321 | 333 | unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct); |
| 322 | 334 | #endif // __mips64 || __powerpc64__ || __aarch64__ |
| 323 | 335 | #if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \ |
| 324 | defined(__aarch64__) || defined(__arm__) || defined(__s390__) | |
| 336 | defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \ | |
| 337 | SANITIZER_RISCV64 | |
| 325 | 338 | unsigned struct_user_fpxregs_struct_sz = 0; |
| 326 | 339 | #else |
| 327 | 340 | unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct); |
| ... | ... | @@ -417,7 +430,9 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 417 | 430 | unsigned struct_input_id_sz = sizeof(struct input_id); |
| 418 | 431 | unsigned struct_mtpos_sz = sizeof(struct mtpos); |
| 419 | 432 | unsigned struct_rtentry_sz = sizeof(struct rtentry); |
| 433 | #if SANITIZER_GLIBC || SANITIZER_ANDROID | |
| 420 | 434 | unsigned struct_termio_sz = sizeof(struct termio); |
| 435 | #endif | |
| 421 | 436 | unsigned struct_vt_consize_sz = sizeof(struct vt_consize); |
| 422 | 437 | unsigned struct_vt_sizes_sz = sizeof(struct vt_sizes); |
| 423 | 438 | unsigned struct_vt_stat_sz = sizeof(struct vt_stat); |
| ... | ... | @@ -442,9 +457,8 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 442 | 457 | unsigned struct_vt_mode_sz = sizeof(struct vt_mode); |
| 443 | 458 | #endif // SANITIZER_LINUX |
| 444 | 459 | |
| 445 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 460 | #if SANITIZER_GLIBC | |
| 446 | 461 | unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct); |
| 447 | unsigned struct_cyclades_monitor_sz = sizeof(struct cyclades_monitor); | |
| 448 | 462 | #if EV_VERSION > (0x010000) |
| 449 | 463 | unsigned struct_input_keymap_entry_sz = sizeof(struct input_keymap_entry); |
| 450 | 464 | #else |
| ... | ... | @@ -465,12 +479,10 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 465 | 479 | unsigned struct_sockaddr_ax25_sz = sizeof(struct sockaddr_ax25); |
| 466 | 480 | unsigned struct_unimapdesc_sz = sizeof(struct unimapdesc); |
| 467 | 481 | unsigned struct_unimapinit_sz = sizeof(struct unimapinit); |
| 468 | #endif // SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 469 | 482 | |
| 470 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 471 | 483 | unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info); |
| 472 | 484 | unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats); |
| 473 | #endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID | |
| 485 | #endif // SANITIZER_GLIBC | |
| 474 | 486 | |
| 475 | 487 | #if !SANITIZER_ANDROID && !SANITIZER_MAC |
| 476 | 488 | unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req); |
| ... | ... | @@ -810,15 +822,6 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 810 | 822 | #endif // SANITIZER_LINUX |
| 811 | 823 | |
| 812 | 824 | #if SANITIZER_LINUX && !SANITIZER_ANDROID |
| 813 | unsigned IOCTL_CYGETDEFTHRESH = CYGETDEFTHRESH; | |
| 814 | unsigned IOCTL_CYGETDEFTIMEOUT = CYGETDEFTIMEOUT; | |
| 815 | unsigned IOCTL_CYGETMON = CYGETMON; | |
| 816 | unsigned IOCTL_CYGETTHRESH = CYGETTHRESH; | |
| 817 | unsigned IOCTL_CYGETTIMEOUT = CYGETTIMEOUT; | |
| 818 | unsigned IOCTL_CYSETDEFTHRESH = CYSETDEFTHRESH; | |
| 819 | unsigned IOCTL_CYSETDEFTIMEOUT = CYSETDEFTIMEOUT; | |
| 820 | unsigned IOCTL_CYSETTHRESH = CYSETTHRESH; | |
| 821 | unsigned IOCTL_CYSETTIMEOUT = CYSETTIMEOUT; | |
| 822 | 825 | unsigned IOCTL_EQL_EMANCIPATE = EQL_EMANCIPATE; |
| 823 | 826 | unsigned IOCTL_EQL_ENSLAVE = EQL_ENSLAVE; |
| 824 | 827 | unsigned IOCTL_EQL_GETMASTRCFG = EQL_GETMASTRCFG; |
| ... | ... | @@ -876,6 +879,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 876 | 879 | unsigned IOCTL_PIO_UNIMAP = PIO_UNIMAP; |
| 877 | 880 | unsigned IOCTL_PIO_UNIMAPCLR = PIO_UNIMAPCLR; |
| 878 | 881 | unsigned IOCTL_PIO_UNISCRNMAP = PIO_UNISCRNMAP; |
| 882 | #if SANITIZER_GLIBC | |
| 879 | 883 | unsigned IOCTL_SCSI_IOCTL_GET_IDLUN = SCSI_IOCTL_GET_IDLUN; |
| 880 | 884 | unsigned IOCTL_SCSI_IOCTL_PROBE_HOST = SCSI_IOCTL_PROBE_HOST; |
| 881 | 885 | unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE = SCSI_IOCTL_TAGGED_DISABLE; |
| ... | ... | @@ -894,6 +898,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); |
| 894 | 898 | unsigned IOCTL_SIOCNRGETPARMS = SIOCNRGETPARMS; |
| 895 | 899 | unsigned IOCTL_SIOCNRRTCTL = SIOCNRRTCTL; |
| 896 | 900 | unsigned IOCTL_SIOCNRSETPARMS = SIOCNRSETPARMS; |
| 901 | #endif | |
| 897 | 902 | unsigned IOCTL_TIOCGSERIAL = TIOCGSERIAL; |
| 898 | 903 | unsigned IOCTL_TIOCSERGETMULTI = TIOCSERGETMULTI; |
| 899 | 904 | unsigned IOCTL_TIOCSERSETMULTI = TIOCSERSETMULTI; |
| ... | ... | @@ -964,7 +969,7 @@ CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr); |
| 964 | 969 | CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum); |
| 965 | 970 | #endif // SANITIZER_LINUX || SANITIZER_FREEBSD |
| 966 | 971 | |
| 967 | #if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID | |
| 972 | #if SANITIZER_GLIBC || SANITIZER_FREEBSD | |
| 968 | 973 | CHECK_TYPE_SIZE(glob_t); |
| 969 | 974 | CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc); |
| 970 | 975 | CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv); |
| ... | ... | @@ -975,7 +980,7 @@ CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir); |
| 975 | 980 | CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir); |
| 976 | 981 | CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat); |
| 977 | 982 | CHECK_SIZE_AND_OFFSET(glob_t, gl_stat); |
| 978 | #endif | |
| 983 | #endif // SANITIZER_GLIBC || SANITIZER_FREEBSD | |
| 979 | 984 | |
| 980 | 985 | CHECK_TYPE_SIZE(addrinfo); |
| 981 | 986 | CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags); |
| ... | ... | @@ -998,17 +1003,27 @@ CHECK_TYPE_SIZE(iovec); |
| 998 | 1003 | CHECK_SIZE_AND_OFFSET(iovec, iov_base); |
| 999 | 1004 | CHECK_SIZE_AND_OFFSET(iovec, iov_len); |
| 1000 | 1005 | |
| 1006 | // In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but | |
| 1007 | // many implementations don't conform to the standard. Since we pick the | |
| 1008 | // non-conforming glibc definition, exclude the checks for musl (incompatible | |
| 1009 | // sizes but compatible offsets). | |
| 1001 | 1010 | CHECK_TYPE_SIZE(msghdr); |
| 1002 | 1011 | CHECK_SIZE_AND_OFFSET(msghdr, msg_name); |
| 1003 | 1012 | CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen); |
| 1004 | 1013 | CHECK_SIZE_AND_OFFSET(msghdr, msg_iov); |
| 1014 | #if SANITIZER_GLIBC || SANITIZER_ANDROID | |
| 1005 | 1015 | CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen); |
| 1016 | #endif | |
| 1006 | 1017 | CHECK_SIZE_AND_OFFSET(msghdr, msg_control); |
| 1018 | #if SANITIZER_GLIBC || SANITIZER_ANDROID | |
| 1007 | 1019 | CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen); |
| 1020 | #endif | |
| 1008 | 1021 | CHECK_SIZE_AND_OFFSET(msghdr, msg_flags); |
| 1009 | 1022 | |
| 1010 | 1023 | CHECK_TYPE_SIZE(cmsghdr); |
| 1024 | #if SANITIZER_GLIBC || SANITIZER_ANDROID | |
| 1011 | 1025 | CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len); |
| 1026 | #endif | |
| 1012 | 1027 | CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level); |
| 1013 | 1028 | CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type); |
| 1014 | 1029 | |
| ... | ... | @@ -1116,7 +1131,7 @@ CHECK_SIZE_AND_OFFSET(mntent, mnt_passno); |
| 1116 | 1131 | |
| 1117 | 1132 | CHECK_TYPE_SIZE(ether_addr); |
| 1118 | 1133 | |
| 1119 | #if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID | |
| 1134 | #if SANITIZER_GLIBC || SANITIZER_FREEBSD | |
| 1120 | 1135 | CHECK_TYPE_SIZE(ipc_perm); |
| 1121 | 1136 | # if SANITIZER_FREEBSD |
| 1122 | 1137 | CHECK_SIZE_AND_OFFSET(ipc_perm, key); |
| ... | ... | @@ -1178,7 +1193,7 @@ CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr); |
| 1178 | 1193 | CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data); |
| 1179 | 1194 | #endif |
| 1180 | 1195 | |
| 1181 | #if SANITIZER_LINUX | |
| 1196 | #if SANITIZER_GLIBC || SANITIZER_ANDROID | |
| 1182 | 1197 | COMPILER_CHECK(sizeof(__sanitizer_struct_mallinfo) == sizeof(struct mallinfo)); |
| 1183 | 1198 | #endif |
| 1184 | 1199 | |
| ... | ... | @@ -1228,7 +1243,7 @@ COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE); |
| 1228 | 1243 | COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE); |
| 1229 | 1244 | #endif |
| 1230 | 1245 | |
| 1231 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 1246 | #if SANITIZER_GLIBC | |
| 1232 | 1247 | COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE)); |
| 1233 | 1248 | CHECK_SIZE_AND_OFFSET(FILE, _flags); |
| 1234 | 1249 | CHECK_SIZE_AND_OFFSET(FILE, _IO_read_ptr); |
| ... | ... | @@ -1245,9 +1260,7 @@ CHECK_SIZE_AND_OFFSET(FILE, _IO_save_end); |
| 1245 | 1260 | CHECK_SIZE_AND_OFFSET(FILE, _markers); |
| 1246 | 1261 | CHECK_SIZE_AND_OFFSET(FILE, _chain); |
| 1247 | 1262 | CHECK_SIZE_AND_OFFSET(FILE, _fileno); |
| 1248 | #endif | |
| 1249 | 1263 | |
| 1250 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
| 1251 | 1264 | COMPILER_CHECK(sizeof(__sanitizer__obstack_chunk) <= sizeof(_obstack_chunk)); |
| 1252 | 1265 | CHECK_SIZE_AND_OFFSET(_obstack_chunk, limit); |
| 1253 | 1266 | CHECK_SIZE_AND_OFFSET(_obstack_chunk, prev); |
| ... | ... | @@ -1262,7 +1275,7 @@ CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, read); |
| 1262 | 1275 | CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, write); |
| 1263 | 1276 | CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, seek); |
| 1264 | 1277 | CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, close); |
| 1265 | #endif | |
| 1278 | #endif // SANITIZER_GLIBC | |
| 1266 | 1279 | |
| 1267 | 1280 | #if SANITIZER_LINUX || SANITIZER_FREEBSD |
| 1268 | 1281 | CHECK_TYPE_SIZE(sem_t); |
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.h+10-18| ... | ... | @@ -99,9 +99,9 @@ const unsigned struct_kernel_stat64_sz = 144; |
| 99 | 99 | const unsigned struct___old_kernel_stat_sz = 0; |
| 100 | 100 | const unsigned struct_kernel_stat_sz = 64; |
| 101 | 101 | const unsigned struct_kernel_stat64_sz = 104; |
| 102 | #elif defined(__riscv) && __riscv_xlen == 64 | |
| 102 | #elif SANITIZER_RISCV64 | |
| 103 | 103 | const unsigned struct_kernel_stat_sz = 128; |
| 104 | const unsigned struct_kernel_stat64_sz = 104; | |
| 104 | const unsigned struct_kernel_stat64_sz = 0; // RISCV64 does not use stat64 | |
| 105 | 105 | #endif |
| 106 | 106 | struct __sanitizer_perf_event_attr { |
| 107 | 107 | unsigned type; |
| ... | ... | @@ -443,6 +443,8 @@ struct __sanitizer_cmsghdr { |
| 443 | 443 | int cmsg_type; |
| 444 | 444 | }; |
| 445 | 445 | #else |
| 446 | // In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but | |
| 447 | // many implementations don't conform to the standard. | |
| 446 | 448 | struct __sanitizer_msghdr { |
| 447 | 449 | void *msg_name; |
| 448 | 450 | unsigned msg_namelen; |
| ... | ... | @@ -648,14 +650,14 @@ struct __sanitizer_sigaction { |
| 648 | 650 | #endif // !SANITIZER_ANDROID |
| 649 | 651 | |
| 650 | 652 | #if defined(__mips__) |
| 651 | struct __sanitizer_kernel_sigset_t { | |
| 652 | uptr sig[2]; | |
| 653 | }; | |
| 653 | #define __SANITIZER_KERNEL_NSIG 128 | |
| 654 | 654 | #else |
| 655 | #define __SANITIZER_KERNEL_NSIG 64 | |
| 656 | #endif | |
| 657 | ||
| 655 | 658 | struct __sanitizer_kernel_sigset_t { |
| 656 | u8 sig[8]; | |
| 659 | uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)]; | |
| 657 | 660 | }; |
| 658 | #endif | |
| 659 | 661 | |
| 660 | 662 | // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros. |
| 661 | 663 | #if SANITIZER_MIPS |
| ... | ... | @@ -804,7 +806,7 @@ typedef void __sanitizer_FILE; |
| 804 | 806 | #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ |
| 805 | 807 | (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ |
| 806 | 808 | defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ |
| 807 | defined(__s390__)) | |
| 809 | defined(__s390__) || SANITIZER_RISCV64) | |
| 808 | 810 | extern unsigned struct_user_regs_struct_sz; |
| 809 | 811 | extern unsigned struct_user_fpregs_struct_sz; |
| 810 | 812 | extern unsigned struct_user_fpxregs_struct_sz; |
| ... | ... | @@ -981,7 +983,6 @@ extern unsigned struct_vt_mode_sz; |
| 981 | 983 | |
| 982 | 984 | #if SANITIZER_LINUX && !SANITIZER_ANDROID |
| 983 | 985 | extern unsigned struct_ax25_parms_struct_sz; |
| 984 | extern unsigned struct_cyclades_monitor_sz; | |
| 985 | 986 | extern unsigned struct_input_keymap_entry_sz; |
| 986 | 987 | extern unsigned struct_ipx_config_data_sz; |
| 987 | 988 | extern unsigned struct_kbdiacrs_sz; |
| ... | ... | @@ -1326,15 +1327,6 @@ extern unsigned IOCTL_VT_WAITACTIVE; |
| 1326 | 1327 | #endif // SANITIZER_LINUX |
| 1327 | 1328 | |
| 1328 | 1329 | #if SANITIZER_LINUX && !SANITIZER_ANDROID |
| 1329 | extern unsigned IOCTL_CYGETDEFTHRESH; | |
| 1330 | extern unsigned IOCTL_CYGETDEFTIMEOUT; | |
| 1331 | extern unsigned IOCTL_CYGETMON; | |
| 1332 | extern unsigned IOCTL_CYGETTHRESH; | |
| 1333 | extern unsigned IOCTL_CYGETTIMEOUT; | |
| 1334 | extern unsigned IOCTL_CYSETDEFTHRESH; | |
| 1335 | extern unsigned IOCTL_CYSETDEFTIMEOUT; | |
| 1336 | extern unsigned IOCTL_CYSETTHRESH; | |
| 1337 | extern unsigned IOCTL_CYSETTIMEOUT; | |
| 1338 | 1330 | extern unsigned IOCTL_EQL_EMANCIPATE; |
| 1339 | 1331 | extern unsigned IOCTL_EQL_ENSLAVE; |
| 1340 | 1332 | extern unsigned IOCTL_EQL_GETMASTRCFG; |
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.cpp+2-1| ... | ... | @@ -202,7 +202,8 @@ CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name); |
| 202 | 202 | CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr); |
| 203 | 203 | CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum); |
| 204 | 204 | |
| 205 | CHECK_TYPE_SIZE(glob_t); | |
| 205 | // There are additional fields we are not interested in. | |
| 206 | COMPILER_CHECK(sizeof(__sanitizer_glob_t) <= sizeof(glob_t)); | |
| 206 | 207 | CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc); |
| 207 | 208 | CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv); |
| 208 | 209 | CHECK_SIZE_AND_OFFSET(glob_t, gl_offs); |
lib/tsan/sanitizer_common/sanitizer_posix.cpp+9-7| ... | ... | @@ -239,6 +239,7 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { |
| 239 | 239 | return true; |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | #if !SANITIZER_MAC | |
| 242 | 243 | void DumpProcessMap() { |
| 243 | 244 | MemoryMappingLayout proc_maps(/*cache_enabled*/true); |
| 244 | 245 | const sptr kBufSize = 4095; |
| ... | ... | @@ -252,6 +253,7 @@ void DumpProcessMap() { |
| 252 | 253 | Report("End of process memory map.\n"); |
| 253 | 254 | UnmapOrDie(filename, kBufSize); |
| 254 | 255 | } |
| 256 | #endif | |
| 255 | 257 | |
| 256 | 258 | const char *GetPwd() { |
| 257 | 259 | return GetEnv("PWD"); |
| ... | ... | @@ -273,8 +275,8 @@ void ReportFile::Write(const char *buffer, uptr length) { |
| 273 | 275 | |
| 274 | 276 | bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { |
| 275 | 277 | MemoryMappingLayout proc_maps(/*cache_enabled*/false); |
| 276 | InternalScopedString buff(kMaxPathLength); | |
| 277 | MemoryMappedSegment segment(buff.data(), kMaxPathLength); | |
| 278 | InternalMmapVector<char> buff(kMaxPathLength); | |
| 279 | MemoryMappedSegment segment(buff.data(), buff.size()); | |
| 278 | 280 | while (proc_maps.Next(&segment)) { |
| 279 | 281 | if (segment.IsExecutable() && |
| 280 | 282 | internal_strcmp(module, segment.filename) == 0) { |
| ... | ... | @@ -293,7 +295,7 @@ uptr SignalContext::GetAddress() const { |
| 293 | 295 | |
| 294 | 296 | bool SignalContext::IsMemoryAccess() const { |
| 295 | 297 | auto si = static_cast<const siginfo_t *>(siginfo); |
| 296 | return si->si_signo == SIGSEGV; | |
| 298 | return si->si_signo == SIGSEGV || si->si_signo == SIGBUS; | |
| 297 | 299 | } |
| 298 | 300 | |
| 299 | 301 | int SignalContext::GetType() const { |
| ... | ... | @@ -354,11 +356,11 @@ int GetNamedMappingFd(const char *name, uptr size, int *flags) { |
| 354 | 356 | int fd = ReserveStandardFds( |
| 355 | 357 | internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | o_cloexec, S_IRWXU)); |
| 356 | 358 | CHECK_GE(fd, 0); |
| 357 | if (!o_cloexec) { | |
| 358 | int res = fcntl(fd, F_SETFD, FD_CLOEXEC); | |
| 359 | CHECK_EQ(0, res); | |
| 360 | } | |
| 361 | 359 | int res = internal_ftruncate(fd, size); |
| 360 | #if !defined(O_CLOEXEC) | |
| 361 | res = fcntl(fd, F_SETFD, FD_CLOEXEC); | |
| 362 | CHECK_EQ(0, res); | |
| 363 | #endif | |
| 362 | 364 | CHECK_EQ(0, res); |
| 363 | 365 | res = internal_unlink(shmname); |
| 364 | 366 | CHECK_EQ(0, res); |
lib/tsan/sanitizer_common/sanitizer_posix.h+5-1| ... | ... | @@ -17,7 +17,6 @@ |
| 17 | 17 | #include "sanitizer_internal_defs.h" |
| 18 | 18 | #include "sanitizer_platform_limits_freebsd.h" |
| 19 | 19 | #include "sanitizer_platform_limits_netbsd.h" |
| 20 | #include "sanitizer_platform_limits_openbsd.h" | |
| 21 | 20 | #include "sanitizer_platform_limits_posix.h" |
| 22 | 21 | #include "sanitizer_platform_limits_solaris.h" |
| 23 | 22 | |
| ... | ... | @@ -41,7 +40,12 @@ uptr internal_write(fd_t fd, const void *buf, uptr count); |
| 41 | 40 | uptr internal_mmap(void *addr, uptr length, int prot, int flags, |
| 42 | 41 | int fd, u64 offset); |
| 43 | 42 | uptr internal_munmap(void *addr, uptr length); |
| 43 | #if SANITIZER_LINUX | |
| 44 | uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags, | |
| 45 | void *new_address); | |
| 46 | #endif | |
| 44 | 47 | int internal_mprotect(void *addr, uptr length, int prot); |
| 48 | int internal_madvise(uptr addr, uptr length, int advice); | |
| 45 | 49 | |
| 46 | 50 | // OS |
| 47 | 51 | uptr internal_filesize(fd_t fd); // -1 on error. |
lib/tsan/sanitizer_common/sanitizer_posix_libcdep.cpp+16-24| ... | ... | @@ -18,7 +18,6 @@ |
| 18 | 18 | #include "sanitizer_common.h" |
| 19 | 19 | #include "sanitizer_flags.h" |
| 20 | 20 | #include "sanitizer_platform_limits_netbsd.h" |
| 21 | #include "sanitizer_platform_limits_openbsd.h" | |
| 22 | 21 | #include "sanitizer_platform_limits_posix.h" |
| 23 | 22 | #include "sanitizer_platform_limits_solaris.h" |
| 24 | 23 | #include "sanitizer_posix.h" |
| ... | ... | @@ -61,27 +60,24 @@ void ReleaseMemoryPagesToOS(uptr beg, uptr end) { |
| 61 | 60 | uptr beg_aligned = RoundUpTo(beg, page_size); |
| 62 | 61 | uptr end_aligned = RoundDownTo(end, page_size); |
| 63 | 62 | if (beg_aligned < end_aligned) |
| 64 | // In the default Solaris compilation environment, madvise() is declared | |
| 65 | // to take a caddr_t arg; casting it to void * results in an invalid | |
| 66 | // conversion error, so use char * instead. | |
| 67 | madvise((char *)beg_aligned, end_aligned - beg_aligned, | |
| 68 | SANITIZER_MADVISE_DONTNEED); | |
| 63 | internal_madvise(beg_aligned, end_aligned - beg_aligned, | |
| 64 | SANITIZER_MADVISE_DONTNEED); | |
| 69 | 65 | } |
| 70 | 66 | |
| 71 | 67 | void SetShadowRegionHugePageMode(uptr addr, uptr size) { |
| 72 | 68 | #ifdef MADV_NOHUGEPAGE // May not be defined on old systems. |
| 73 | 69 | if (common_flags()->no_huge_pages_for_shadow) |
| 74 | madvise((char *)addr, size, MADV_NOHUGEPAGE); | |
| 70 | internal_madvise(addr, size, MADV_NOHUGEPAGE); | |
| 75 | 71 | else |
| 76 | madvise((char *)addr, size, MADV_HUGEPAGE); | |
| 72 | internal_madvise(addr, size, MADV_HUGEPAGE); | |
| 77 | 73 | #endif // MADV_NOHUGEPAGE |
| 78 | 74 | } |
| 79 | 75 | |
| 80 | 76 | bool DontDumpShadowMemory(uptr addr, uptr length) { |
| 81 | 77 | #if defined(MADV_DONTDUMP) |
| 82 | return madvise((char *)addr, length, MADV_DONTDUMP) == 0; | |
| 78 | return internal_madvise(addr, length, MADV_DONTDUMP) == 0; | |
| 83 | 79 | #elif defined(MADV_NOCORE) |
| 84 | return madvise((char *)addr, length, MADV_NOCORE) == 0; | |
| 80 | return internal_madvise(addr, length, MADV_NOCORE) == 0; | |
| 85 | 81 | #else |
| 86 | 82 | return true; |
| 87 | 83 | #endif // MADV_DONTDUMP |
| ... | ... | @@ -132,14 +128,6 @@ void SetAddressSpaceUnlimited() { |
| 132 | 128 | CHECK(AddressSpaceIsUnlimited()); |
| 133 | 129 | } |
| 134 | 130 | |
| 135 | void SleepForSeconds(int seconds) { | |
| 136 | sleep(seconds); | |
| 137 | } | |
| 138 | ||
| 139 | void SleepForMillis(int millis) { | |
| 140 | usleep(millis * 1000); | |
| 141 | } | |
| 142 | ||
| 143 | 131 | void Abort() { |
| 144 | 132 | #if !SANITIZER_GO |
| 145 | 133 | // If we are handling SIGABRT, unhandle it first. |
| ... | ... | @@ -147,7 +135,7 @@ void Abort() { |
| 147 | 135 | if (GetHandleSignalMode(SIGABRT) != kHandleSignalNo) { |
| 148 | 136 | struct sigaction sigact; |
| 149 | 137 | internal_memset(&sigact, 0, sizeof(sigact)); |
| 150 | sigact.sa_sigaction = (sa_sigaction_t)SIG_DFL; | |
| 138 | sigact.sa_handler = SIG_DFL; | |
| 151 | 139 | internal_sigaction(SIGABRT, &sigact, nullptr); |
| 152 | 140 | } |
| 153 | 141 | #endif |
| ... | ... | @@ -169,7 +157,12 @@ bool SupportsColoredOutput(fd_t fd) { |
| 169 | 157 | |
| 170 | 158 | #if !SANITIZER_GO |
| 171 | 159 | // TODO(glider): different tools may require different altstack size. |
| 172 | static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. | |
| 160 | static uptr GetAltStackSize() { | |
| 161 | // Note: since GLIBC_2.31, SIGSTKSZ may be a function call, so this may be | |
| 162 | // more costly that you think. However GetAltStackSize is only call 2-3 times | |
| 163 | // per thread so don't cache the evaluation. | |
| 164 | return SIGSTKSZ * 4; | |
| 165 | } | |
| 173 | 166 | |
| 174 | 167 | void SetAlternateSignalStack() { |
| 175 | 168 | stack_t altstack, oldstack; |
| ... | ... | @@ -180,10 +173,9 @@ void SetAlternateSignalStack() { |
| 180 | 173 | // TODO(glider): the mapped stack should have the MAP_STACK flag in the |
| 181 | 174 | // future. It is not required by man 2 sigaltstack now (they're using |
| 182 | 175 | // malloc()). |
| 183 | void* base = MmapOrDie(kAltStackSize, __func__); | |
| 184 | altstack.ss_sp = (char*) base; | |
| 176 | altstack.ss_size = GetAltStackSize(); | |
| 177 | altstack.ss_sp = (char *)MmapOrDie(altstack.ss_size, __func__); | |
| 185 | 178 | altstack.ss_flags = 0; |
| 186 | altstack.ss_size = kAltStackSize; | |
| 187 | 179 | CHECK_EQ(0, sigaltstack(&altstack, nullptr)); |
| 188 | 180 | } |
| 189 | 181 | |
| ... | ... | @@ -191,7 +183,7 @@ void UnsetAlternateSignalStack() { |
| 191 | 183 | stack_t altstack, oldstack; |
| 192 | 184 | altstack.ss_sp = nullptr; |
| 193 | 185 | altstack.ss_flags = SS_DISABLE; |
| 194 | altstack.ss_size = kAltStackSize; // Some sane value required on Darwin. | |
| 186 | altstack.ss_size = GetAltStackSize(); // Some sane value required on Darwin. | |
| 195 | 187 | CHECK_EQ(0, sigaltstack(&altstack, &oldstack)); |
| 196 | 188 | UnmapOrDie(oldstack.ss_sp, oldstack.ss_size); |
| 197 | 189 | } |
lib/tsan/sanitizer_common/sanitizer_printf.cpp+49-35| ... | ... | @@ -20,6 +20,10 @@ |
| 20 | 20 | #include <stdio.h> |
| 21 | 21 | #include <stdarg.h> |
| 22 | 22 | |
| 23 | #if defined(__x86_64__) | |
| 24 | # include <emmintrin.h> | |
| 25 | #endif | |
| 26 | ||
| 23 | 27 | #if SANITIZER_WINDOWS && defined(_MSC_VER) && _MSC_VER < 1800 && \ |
| 24 | 28 | !defined(va_copy) |
| 25 | 29 | # define va_copy(dst, src) ((dst) = (src)) |
| ... | ... | @@ -128,7 +132,7 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) { |
| 128 | 132 | int VSNPrintf(char *buff, int buff_length, |
| 129 | 133 | const char *format, va_list args) { |
| 130 | 134 | static const char *kPrintfFormatsHelp = |
| 131 | "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; " | |
| 135 | "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X,V}; %p; " | |
| 132 | 136 | "%[-]([0-9]*)?(\\.\\*)?s; %c\n"; |
| 133 | 137 | RAW_CHECK(format); |
| 134 | 138 | RAW_CHECK(buff_length > 0); |
| ... | ... | @@ -162,17 +166,15 @@ int VSNPrintf(char *buff, int buff_length, |
| 162 | 166 | cur += have_z; |
| 163 | 167 | bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l'); |
| 164 | 168 | cur += have_ll * 2; |
| 165 | s64 dval; | |
| 166 | u64 uval; | |
| 167 | 169 | const bool have_length = have_z || have_ll; |
| 168 | 170 | const bool have_flags = have_width || have_length; |
| 169 | 171 | // At the moment only %s supports precision and left-justification. |
| 170 | 172 | CHECK(!((precision >= 0 || left_justified) && *cur != 's')); |
| 171 | 173 | switch (*cur) { |
| 172 | 174 | case 'd': { |
| 173 | dval = have_ll ? va_arg(args, s64) | |
| 174 | : have_z ? va_arg(args, sptr) | |
| 175 | : va_arg(args, int); | |
| 175 | s64 dval = have_ll ? va_arg(args, s64) | |
| 176 | : have_z ? va_arg(args, sptr) | |
| 177 | : va_arg(args, int); | |
| 176 | 178 | result += AppendSignedDecimal(&buff, buff_end, dval, width, |
| 177 | 179 | pad_with_zero); |
| 178 | 180 | break; |
| ... | ... | @@ -180,14 +182,21 @@ int VSNPrintf(char *buff, int buff_length, |
| 180 | 182 | case 'u': |
| 181 | 183 | case 'x': |
| 182 | 184 | case 'X': { |
| 183 | uval = have_ll ? va_arg(args, u64) | |
| 184 | : have_z ? va_arg(args, uptr) | |
| 185 | : va_arg(args, unsigned); | |
| 185 | u64 uval = have_ll ? va_arg(args, u64) | |
| 186 | : have_z ? va_arg(args, uptr) | |
| 187 | : va_arg(args, unsigned); | |
| 186 | 188 | bool uppercase = (*cur == 'X'); |
| 187 | 189 | result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16, |
| 188 | 190 | width, pad_with_zero, uppercase); |
| 189 | 191 | break; |
| 190 | 192 | } |
| 193 | case 'V': { | |
| 194 | for (uptr i = 0; i < 16; i++) { | |
| 195 | unsigned x = va_arg(args, unsigned); | |
| 196 | result += AppendUnsigned(&buff, buff_end, x, 16, 2, true, false); | |
| 197 | } | |
| 198 | break; | |
| 199 | } | |
| 191 | 200 | case 'p': { |
| 192 | 201 | RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); |
| 193 | 202 | result += AppendPointer(&buff, buff_end, va_arg(args, uptr)); |
| ... | ... | @@ -249,26 +258,21 @@ static void NOINLINE SharedPrintfCodeNoBuffer(bool append_pid, |
| 249 | 258 | va_list args) { |
| 250 | 259 | va_list args2; |
| 251 | 260 | va_copy(args2, args); |
| 252 | const int kLen = 16 * 1024; | |
| 253 | int needed_length; | |
| 261 | InternalMmapVector<char> v; | |
| 262 | int needed_length = 0; | |
| 254 | 263 | char *buffer = local_buffer; |
| 255 | 264 | // First try to print a message using a local buffer, and then fall back to |
| 256 | 265 | // mmaped buffer. |
| 257 | for (int use_mmap = 0; use_mmap < 2; use_mmap++) { | |
| 266 | for (int use_mmap = 0;; use_mmap++) { | |
| 258 | 267 | if (use_mmap) { |
| 259 | 268 | va_end(args); |
| 260 | 269 | va_copy(args, args2); |
| 261 | buffer = (char*)MmapOrDie(kLen, "Report"); | |
| 262 | buffer_size = kLen; | |
| 270 | v.resize(needed_length + 1); | |
| 271 | buffer_size = v.capacity(); | |
| 272 | v.resize(buffer_size); | |
| 273 | buffer = &v[0]; | |
| 263 | 274 | } |
| 264 | 275 | needed_length = 0; |
| 265 | // Check that data fits into the current buffer. | |
| 266 | # define CHECK_NEEDED_LENGTH \ | |
| 267 | if (needed_length >= buffer_size) { \ | |
| 268 | if (!use_mmap) continue; \ | |
| 269 | RAW_CHECK_MSG(needed_length < kLen, \ | |
| 270 | "Buffer in Report is too short!\n"); \ | |
| 271 | } | |
| 272 | 276 | // Fuchsia's logging infrastructure always keeps track of the logging |
| 273 | 277 | // process, thread, and timestamp, so never prepend such information. |
| 274 | 278 | if (!SANITIZER_FUCHSIA && append_pid) { |
| ... | ... | @@ -277,18 +281,20 @@ static void NOINLINE SharedPrintfCodeNoBuffer(bool append_pid, |
| 277 | 281 | if (common_flags()->log_exe_name && exe_name) { |
| 278 | 282 | needed_length += internal_snprintf(buffer, buffer_size, |
| 279 | 283 | "==%s", exe_name); |
| 280 | CHECK_NEEDED_LENGTH | |
| 284 | if (needed_length >= buffer_size) | |
| 285 | continue; | |
| 281 | 286 | } |
| 282 | 287 | needed_length += internal_snprintf( |
| 283 | 288 | buffer + needed_length, buffer_size - needed_length, "==%d==", pid); |
| 284 | CHECK_NEEDED_LENGTH | |
| 289 | if (needed_length >= buffer_size) | |
| 290 | continue; | |
| 285 | 291 | } |
| 286 | 292 | needed_length += VSNPrintf(buffer + needed_length, |
| 287 | 293 | buffer_size - needed_length, format, args); |
| 288 | CHECK_NEEDED_LENGTH | |
| 294 | if (needed_length >= buffer_size) | |
| 295 | continue; | |
| 289 | 296 | // If the message fit into the buffer, print it and exit. |
| 290 | 297 | break; |
| 291 | # undef CHECK_NEEDED_LENGTH | |
| 292 | 298 | } |
| 293 | 299 | RawWrite(buffer); |
| 294 | 300 | |
| ... | ... | @@ -297,9 +303,6 @@ static void NOINLINE SharedPrintfCodeNoBuffer(bool append_pid, |
| 297 | 303 | CallPrintfAndReportCallback(buffer); |
| 298 | 304 | LogMessageOnPrintf(buffer); |
| 299 | 305 | |
| 300 | // If we had mapped any memory, clean up. | |
| 301 | if (buffer != local_buffer) | |
| 302 | UnmapOrDie((void *)buffer, buffer_size); | |
| 303 | 306 | va_end(args2); |
| 304 | 307 | } |
| 305 | 308 | |
| ... | ... | @@ -346,13 +349,24 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) { |
| 346 | 349 | |
| 347 | 350 | FORMAT(2, 3) |
| 348 | 351 | void InternalScopedString::append(const char *format, ...) { |
| 349 | CHECK_LT(length_, size()); | |
| 350 | va_list args; | |
| 351 | va_start(args, format); | |
| 352 | VSNPrintf(data() + length_, size() - length_, format, args); | |
| 353 | va_end(args); | |
| 354 | length_ += internal_strlen(data() + length_); | |
| 355 | CHECK_LT(length_, size()); | |
| 352 | uptr prev_len = length(); | |
| 353 | ||
| 354 | while (true) { | |
| 355 | buffer_.resize(buffer_.capacity()); | |
| 356 | ||
| 357 | va_list args; | |
| 358 | va_start(args, format); | |
| 359 | uptr sz = VSNPrintf(buffer_.data() + prev_len, buffer_.size() - prev_len, | |
| 360 | format, args); | |
| 361 | va_end(args); | |
| 362 | if (sz < buffer_.size() - prev_len) { | |
| 363 | buffer_.resize(prev_len + sz + 1); | |
| 364 | break; | |
| 365 | } | |
| 366 | ||
| 367 | buffer_.reserve(buffer_.capacity() * 2); | |
| 368 | } | |
| 369 | CHECK_EQ(buffer_[length()], '\0'); | |
| 356 | 370 | } |
| 357 | 371 | |
| 358 | 372 | } // namespace __sanitizer |
lib/tsan/sanitizer_common/sanitizer_procmaps.h+1-1| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | #include "sanitizer_platform.h" |
| 17 | 17 | |
| 18 | 18 | #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ |
| 19 | SANITIZER_OPENBSD || SANITIZER_MAC || SANITIZER_SOLARIS || \ | |
| 19 | SANITIZER_MAC || SANITIZER_SOLARIS || \ | |
| 20 | 20 | SANITIZER_FUCHSIA |
| 21 | 21 | |
| 22 | 22 | #include "sanitizer_common.h" |
lib/tsan/sanitizer_common/sanitizer_procmaps_bsd.cpp+2-29| ... | ... | @@ -7,11 +7,11 @@ |
| 7 | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | // |
| 9 | 9 | // Information about the process mappings |
| 10 | // (FreeBSD, OpenBSD and NetBSD-specific parts). | |
| 10 | // (FreeBSD and NetBSD-specific parts). | |
| 11 | 11 | //===----------------------------------------------------------------------===// |
| 12 | 12 | |
| 13 | 13 | #include "sanitizer_platform.h" |
| 14 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD | |
| 14 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 15 | 15 | #include "sanitizer_common.h" |
| 16 | 16 | #if SANITIZER_FREEBSD |
| 17 | 17 | #include "sanitizer_freebsd.h" |
| ... | ... | @@ -28,11 +28,6 @@ |
| 28 | 28 | #endif |
| 29 | 29 | |
| 30 | 30 | #include <limits.h> |
| 31 | #if SANITIZER_OPENBSD | |
| 32 | #define KVME_PROT_READ KVE_PROT_READ | |
| 33 | #define KVME_PROT_WRITE KVE_PROT_WRITE | |
| 34 | #define KVME_PROT_EXEC KVE_PROT_EXEC | |
| 35 | #endif | |
| 36 | 31 | |
| 37 | 32 | // Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode. |
| 38 | 33 | #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) |
| ... | ... | @@ -51,10 +46,6 @@ void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { |
| 51 | 46 | KERN_PROC, |
| 52 | 47 | KERN_PROC_VMMAP, |
| 53 | 48 | getpid() |
| 54 | #elif SANITIZER_OPENBSD | |
| 55 | CTL_KERN, | |
| 56 | KERN_PROC_VMMAP, | |
| 57 | getpid() | |
| 58 | 49 | #elif SANITIZER_NETBSD |
| 59 | 50 | CTL_VM, |
| 60 | 51 | VM_PROC, |
| ... | ... | @@ -71,28 +62,12 @@ void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { |
| 71 | 62 | CHECK_EQ(Err, 0); |
| 72 | 63 | CHECK_GT(Size, 0); |
| 73 | 64 | |
| 74 | #if !SANITIZER_OPENBSD | |
| 75 | 65 | size_t MmapedSize = Size * 4 / 3; |
| 76 | 66 | void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()"); |
| 77 | 67 | Size = MmapedSize; |
| 78 | 68 | Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0); |
| 79 | 69 | CHECK_EQ(Err, 0); |
| 80 | 70 | proc_maps->data = (char *)VmMap; |
| 81 | #else | |
| 82 | size_t PageSize = GetPageSize(); | |
| 83 | size_t MmapedSize = Size; | |
| 84 | MmapedSize = ((MmapedSize - 1) / PageSize + 1) * PageSize; | |
| 85 | char *Mem = (char *)MmapOrDie(MmapedSize, "ReadProcMaps()"); | |
| 86 | Size = 2 * Size + 10 * sizeof(struct kinfo_vmentry); | |
| 87 | if (Size > 0x10000) | |
| 88 | Size = 0x10000; | |
| 89 | Size = (Size / sizeof(struct kinfo_vmentry)) * sizeof(struct kinfo_vmentry); | |
| 90 | Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), Mem, &Size, NULL, 0); | |
| 91 | CHECK_EQ(Err, 0); | |
| 92 | MmapedSize = Size; | |
| 93 | proc_maps->data = Mem; | |
| 94 | #endif | |
| 95 | ||
| 96 | 71 | proc_maps->mmaped_size = MmapedSize; |
| 97 | 72 | proc_maps->len = Size; |
| 98 | 73 | } |
| ... | ... | @@ -117,13 +92,11 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { |
| 117 | 92 | if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) |
| 118 | 93 | segment->protection |= kProtectionExecute; |
| 119 | 94 | |
| 120 | #if !SANITIZER_OPENBSD | |
| 121 | 95 | if (segment->filename != NULL && segment->filename_size > 0) { |
| 122 | 96 | internal_snprintf(segment->filename, |
| 123 | 97 | Min(segment->filename_size, (uptr)PATH_MAX), "%s", |
| 124 | 98 | VmEntry->kve_path); |
| 125 | 99 | } |
| 126 | #endif | |
| 127 | 100 | |
| 128 | 101 | #if SANITIZER_FREEBSD |
| 129 | 102 | data_.current += VmEntry->kve_structsize; |
lib/tsan/sanitizer_common/sanitizer_procmaps_common.cpp+2-2| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | #include "sanitizer_platform.h" |
| 13 | 13 | |
| 14 | 14 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ |
| 15 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 15 | SANITIZER_SOLARIS | |
| 16 | 16 | |
| 17 | 17 | #include "sanitizer_common.h" |
| 18 | 18 | #include "sanitizer_placement_new.h" |
| ... | ... | @@ -120,7 +120,7 @@ void MemoryMappingLayout::LoadFromCache() { |
| 120 | 120 | void MemoryMappingLayout::DumpListOfModules( |
| 121 | 121 | InternalMmapVectorNoCtor<LoadedModule> *modules) { |
| 122 | 122 | Reset(); |
| 123 | InternalScopedString module_name(kMaxPathLength); | |
| 123 | InternalMmapVector<char> module_name(kMaxPathLength); | |
| 124 | 124 | MemoryMappedSegment segment(module_name.data(), module_name.size()); |
| 125 | 125 | for (uptr i = 0; Next(&segment); i++) { |
| 126 | 126 | const char *cur_name = segment.filename; |
lib/tsan/sanitizer_common/sanitizer_procmaps_mac.cpp+2-2| ... | ... | @@ -354,8 +354,8 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { |
| 354 | 354 | void MemoryMappingLayout::DumpListOfModules( |
| 355 | 355 | InternalMmapVectorNoCtor<LoadedModule> *modules) { |
| 356 | 356 | Reset(); |
| 357 | InternalScopedString module_name(kMaxPathLength); | |
| 358 | MemoryMappedSegment segment(module_name.data(), kMaxPathLength); | |
| 357 | InternalMmapVector<char> module_name(kMaxPathLength); | |
| 358 | MemoryMappedSegment segment(module_name.data(), module_name.size()); | |
| 359 | 359 | MemoryMappedSegmentData data; |
| 360 | 360 | segment.data_ = &data; |
| 361 | 361 | while (Next(&segment)) { |
lib/tsan/sanitizer_common/sanitizer_procmaps_solaris.cpp+4-3| ... | ... | @@ -9,13 +9,13 @@ |
| 9 | 9 | // Information about the process mappings (Solaris-specific parts). |
| 10 | 10 | //===----------------------------------------------------------------------===// |
| 11 | 11 | |
| 12 | // Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment. | |
| 13 | #undef _FILE_OFFSET_BITS | |
| 12 | 14 | #include "sanitizer_platform.h" |
| 13 | 15 | #if SANITIZER_SOLARIS |
| 14 | 16 | #include "sanitizer_common.h" |
| 15 | 17 | #include "sanitizer_procmaps.h" |
| 16 | 18 | |
| 17 | // Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment. | |
| 18 | #undef _FILE_OFFSET_BITS | |
| 19 | 19 | #include <procfs.h> |
| 20 | 20 | #include <limits.h> |
| 21 | 21 | |
| ... | ... | @@ -35,7 +35,8 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { |
| 35 | 35 | char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; |
| 36 | 36 | if (data_.current >= last) return false; |
| 37 | 37 | |
| 38 | prxmap_t *xmapentry = (prxmap_t*)data_.current; | |
| 38 | prxmap_t *xmapentry = | |
| 39 | const_cast<prxmap_t *>(reinterpret_cast<const prxmap_t *>(data_.current)); | |
| 39 | 40 | |
| 40 | 41 | segment->start = (uptr)xmapentry->pr_vaddr; |
| 41 | 42 | segment->end = (uptr)(xmapentry->pr_vaddr + xmapentry->pr_size); |
lib/tsan/sanitizer_common/sanitizer_ptrauth.h+20| ... | ... | @@ -11,6 +11,24 @@ |
| 11 | 11 | |
| 12 | 12 | #if __has_feature(ptrauth_calls) |
| 13 | 13 | #include <ptrauth.h> |
| 14 | #elif defined(__ARM_FEATURE_PAC_DEFAULT) && !defined(__APPLE__) | |
| 15 | inline unsigned long ptrauth_strip(void* __value, unsigned int __key) { | |
| 16 | // On the stack the link register is protected with Pointer | |
| 17 | // Authentication Code when compiled with -mbranch-protection. | |
| 18 | // Let's stripping the PAC unconditionally because xpaclri is in | |
| 19 | // the NOP space so will do nothing when it is not enabled or not available. | |
| 20 | unsigned long ret; | |
| 21 | asm volatile( | |
| 22 | "mov x30, %1\n\t" | |
| 23 | "hint #7\n\t" // xpaclri | |
| 24 | "mov %0, x30\n\t" | |
| 25 | : "=r"(ret) | |
| 26 | : "r"(__value) | |
| 27 | : "x30"); | |
| 28 | return ret; | |
| 29 | } | |
| 30 | #define ptrauth_auth_data(__value, __old_key, __old_data) __value | |
| 31 | #define ptrauth_string_discriminator(__string) ((int)0) | |
| 14 | 32 | #else |
| 15 | 33 | // Copied from <ptrauth.h> |
| 16 | 34 | #define ptrauth_strip(__value, __key) __value |
| ... | ... | @@ -18,4 +36,6 @@ |
| 18 | 36 | #define ptrauth_string_discriminator(__string) ((int)0) |
| 19 | 37 | #endif |
| 20 | 38 | |
| 39 | #define STRIP_PAC_PC(pc) ((uptr)ptrauth_strip(pc, 0)) | |
| 40 | ||
| 21 | 41 | #endif // SANITIZER_PTRAUTH_H |
lib/tsan/sanitizer_common/sanitizer_quarantine.h+2-1| ... | ... | @@ -149,7 +149,8 @@ class Quarantine { |
| 149 | 149 | Cache cache_; |
| 150 | 150 | char pad2_[kCacheLineSize]; |
| 151 | 151 | |
| 152 | void NOINLINE Recycle(uptr min_size, Callback cb) { | |
| 152 | void NOINLINE Recycle(uptr min_size, Callback cb) REQUIRES(recycle_mutex_) | |
| 153 | RELEASE(recycle_mutex_) { | |
| 153 | 154 | Cache tmp; |
| 154 | 155 | { |
| 155 | 156 | SpinMutexLock l(&cache_mutex_); |
lib/tsan/sanitizer_common/sanitizer_rtems.cpp deleted-283| ... | ... | @@ -1,283 +0,0 @@ |
| 1 | //===-- sanitizer_rtems.cpp -----------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is shared between various sanitizers' runtime libraries and | |
| 10 | // implements RTEMS-specific functions. | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | ||
| 13 | #include "sanitizer_rtems.h" | |
| 14 | #if SANITIZER_RTEMS | |
| 15 | ||
| 16 | #define posix_memalign __real_posix_memalign | |
| 17 | #define free __real_free | |
| 18 | #define memset __real_memset | |
| 19 | ||
| 20 | #include "sanitizer_file.h" | |
| 21 | #include "sanitizer_symbolizer.h" | |
| 22 | #include <errno.h> | |
| 23 | #include <fcntl.h> | |
| 24 | #include <pthread.h> | |
| 25 | #include <sched.h> | |
| 26 | #include <stdio.h> | |
| 27 | #include <stdlib.h> | |
| 28 | #include <string.h> | |
| 29 | #include <unistd.h> | |
| 30 | ||
| 31 | // There is no mmap on RTEMS. Use memalign, etc. | |
| 32 | #define __mmap_alloc_aligned posix_memalign | |
| 33 | #define __mmap_free free | |
| 34 | #define __mmap_memset memset | |
| 35 | ||
| 36 | namespace __sanitizer { | |
| 37 | ||
| 38 | #include "sanitizer_syscall_generic.inc" | |
| 39 | ||
| 40 | void NORETURN internal__exit(int exitcode) { | |
| 41 | _exit(exitcode); | |
| 42 | } | |
| 43 | ||
| 44 | uptr internal_sched_yield() { | |
| 45 | return sched_yield(); | |
| 46 | } | |
| 47 | ||
| 48 | uptr internal_getpid() { | |
| 49 | return getpid(); | |
| 50 | } | |
| 51 | ||
| 52 | int internal_dlinfo(void *handle, int request, void *p) { | |
| 53 | UNIMPLEMENTED(); | |
| 54 | } | |
| 55 | ||
| 56 | bool FileExists(const char *filename) { | |
| 57 | struct stat st; | |
| 58 | if (stat(filename, &st)) | |
| 59 | return false; | |
| 60 | // Sanity check: filename is a regular file. | |
| 61 | return S_ISREG(st.st_mode); | |
| 62 | } | |
| 63 | ||
| 64 | uptr GetThreadSelf() { return static_cast<uptr>(pthread_self()); } | |
| 65 | ||
| 66 | tid_t GetTid() { return GetThreadSelf(); } | |
| 67 | ||
| 68 | void Abort() { abort(); } | |
| 69 | ||
| 70 | int Atexit(void (*function)(void)) { return atexit(function); } | |
| 71 | ||
| 72 | void SleepForSeconds(int seconds) { sleep(seconds); } | |
| 73 | ||
| 74 | void SleepForMillis(int millis) { usleep(millis * 1000); } | |
| 75 | ||
| 76 | bool SupportsColoredOutput(fd_t fd) { return false; } | |
| 77 | ||
| 78 | void GetThreadStackTopAndBottom(bool at_initialization, | |
| 79 | uptr *stack_top, uptr *stack_bottom) { | |
| 80 | pthread_attr_t attr; | |
| 81 | pthread_attr_init(&attr); | |
| 82 | CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); | |
| 83 | void *base = nullptr; | |
| 84 | size_t size = 0; | |
| 85 | CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0); | |
| 86 | CHECK_EQ(pthread_attr_destroy(&attr), 0); | |
| 87 | ||
| 88 | *stack_bottom = reinterpret_cast<uptr>(base); | |
| 89 | *stack_top = *stack_bottom + size; | |
| 90 | } | |
| 91 | ||
| 92 | void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, | |
| 93 | uptr *tls_addr, uptr *tls_size) { | |
| 94 | uptr stack_top, stack_bottom; | |
| 95 | GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); | |
| 96 | *stk_addr = stack_bottom; | |
| 97 | *stk_size = stack_top - stack_bottom; | |
| 98 | *tls_addr = *tls_size = 0; | |
| 99 | } | |
| 100 | ||
| 101 | void InitializePlatformEarly() {} | |
| 102 | void MaybeReexec() {} | |
| 103 | void CheckASLR() {} | |
| 104 | void CheckMPROTECT() {} | |
| 105 | void DisableCoreDumperIfNecessary() {} | |
| 106 | void InstallDeadlySignalHandlers(SignalHandlerType handler) {} | |
| 107 | void SetAlternateSignalStack() {} | |
| 108 | void UnsetAlternateSignalStack() {} | |
| 109 | void InitTlsSize() {} | |
| 110 | ||
| 111 | void PrintModuleMap() {} | |
| 112 | ||
| 113 | void SignalContext::DumpAllRegisters(void *context) {} | |
| 114 | const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); } | |
| 115 | ||
| 116 | enum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; | |
| 117 | ||
| 118 | BlockingMutex::BlockingMutex() { | |
| 119 | internal_memset(this, 0, sizeof(*this)); | |
| 120 | } | |
| 121 | ||
| 122 | void BlockingMutex::Lock() { | |
| 123 | CHECK_EQ(owner_, 0); | |
| 124 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |
| 125 | if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) | |
| 126 | return; | |
| 127 | while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) { | |
| 128 | internal_sched_yield(); | |
| 129 | } | |
| 130 | } | |
| 131 | ||
| 132 | void BlockingMutex::Unlock() { | |
| 133 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |
| 134 | u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release); | |
| 135 | CHECK_NE(v, MtxUnlocked); | |
| 136 | } | |
| 137 | ||
| 138 | void BlockingMutex::CheckLocked() { | |
| 139 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |
| 140 | CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed)); | |
| 141 | } | |
| 142 | ||
| 143 | uptr GetPageSize() { return getpagesize(); } | |
| 144 | ||
| 145 | uptr GetMmapGranularity() { return GetPageSize(); } | |
| 146 | ||
| 147 | uptr GetMaxVirtualAddress() { | |
| 148 | return (1ULL << 32) - 1; // 0xffffffff | |
| 149 | } | |
| 150 | ||
| 151 | void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { | |
| 152 | void* ptr = 0; | |
| 153 | int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size); | |
| 154 | if (UNLIKELY(res)) | |
| 155 | ReportMmapFailureAndDie(size, mem_type, "allocate", res, raw_report); | |
| 156 | __mmap_memset(ptr, 0, size); | |
| 157 | IncreaseTotalMmap(size); | |
| 158 | return ptr; | |
| 159 | } | |
| 160 | ||
| 161 | void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { | |
| 162 | void* ptr = 0; | |
| 163 | int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size); | |
| 164 | if (UNLIKELY(res)) { | |
| 165 | if (res == ENOMEM) | |
| 166 | return nullptr; | |
| 167 | ReportMmapFailureAndDie(size, mem_type, "allocate", false); | |
| 168 | } | |
| 169 | __mmap_memset(ptr, 0, size); | |
| 170 | IncreaseTotalMmap(size); | |
| 171 | return ptr; | |
| 172 | } | |
| 173 | ||
| 174 | void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, | |
| 175 | const char *mem_type) { | |
| 176 | CHECK(IsPowerOfTwo(size)); | |
| 177 | CHECK(IsPowerOfTwo(alignment)); | |
| 178 | void* ptr = 0; | |
| 179 | int res = __mmap_alloc_aligned(&ptr, alignment, size); | |
| 180 | if (res) | |
| 181 | ReportMmapFailureAndDie(size, mem_type, "align allocate", res, false); | |
| 182 | __mmap_memset(ptr, 0, size); | |
| 183 | IncreaseTotalMmap(size); | |
| 184 | return ptr; | |
| 185 | } | |
| 186 | ||
| 187 | void *MmapNoReserveOrDie(uptr size, const char *mem_type) { | |
| 188 | return MmapOrDie(size, mem_type, false); | |
| 189 | } | |
| 190 | ||
| 191 | void UnmapOrDie(void *addr, uptr size) { | |
| 192 | if (!addr || !size) return; | |
| 193 | __mmap_free(addr); | |
| 194 | DecreaseTotalMmap(size); | |
| 195 | } | |
| 196 | ||
| 197 | fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { | |
| 198 | int flags; | |
| 199 | switch (mode) { | |
| 200 | case RdOnly: flags = O_RDONLY; break; | |
| 201 | case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break; | |
| 202 | case RdWr: flags = O_RDWR | O_CREAT; break; | |
| 203 | } | |
| 204 | fd_t res = open(filename, flags, 0660); | |
| 205 | if (internal_iserror(res, errno_p)) | |
| 206 | return kInvalidFd; | |
| 207 | return res; | |
| 208 | } | |
| 209 | ||
| 210 | void CloseFile(fd_t fd) { | |
| 211 | close(fd); | |
| 212 | } | |
| 213 | ||
| 214 | bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, | |
| 215 | error_t *error_p) { | |
| 216 | uptr res = read(fd, buff, buff_size); | |
| 217 | if (internal_iserror(res, error_p)) | |
| 218 | return false; | |
| 219 | if (bytes_read) | |
| 220 | *bytes_read = res; | |
| 221 | return true; | |
| 222 | } | |
| 223 | ||
| 224 | bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, | |
| 225 | error_t *error_p) { | |
| 226 | uptr res = write(fd, buff, buff_size); | |
| 227 | if (internal_iserror(res, error_p)) | |
| 228 | return false; | |
| 229 | if (bytes_written) | |
| 230 | *bytes_written = res; | |
| 231 | return true; | |
| 232 | } | |
| 233 | ||
| 234 | void ReleaseMemoryPagesToOS(uptr beg, uptr end) {} | |
| 235 | void DumpProcessMap() {} | |
| 236 | ||
| 237 | // There is no page protection so everything is "accessible." | |
| 238 | bool IsAccessibleMemoryRange(uptr beg, uptr size) { | |
| 239 | return true; | |
| 240 | } | |
| 241 | ||
| 242 | char **GetArgv() { return nullptr; } | |
| 243 | char **GetEnviron() { return nullptr; } | |
| 244 | ||
| 245 | const char *GetEnv(const char *name) { | |
| 246 | return getenv(name); | |
| 247 | } | |
| 248 | ||
| 249 | uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { | |
| 250 | internal_strncpy(buf, "StubBinaryName", buf_len); | |
| 251 | return internal_strlen(buf); | |
| 252 | } | |
| 253 | ||
| 254 | uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { | |
| 255 | internal_strncpy(buf, "StubProcessName", buf_len); | |
| 256 | return internal_strlen(buf); | |
| 257 | } | |
| 258 | ||
| 259 | bool IsPathSeparator(const char c) { | |
| 260 | return c == '/'; | |
| 261 | } | |
| 262 | ||
| 263 | bool IsAbsolutePath(const char *path) { | |
| 264 | return path != nullptr && IsPathSeparator(path[0]); | |
| 265 | } | |
| 266 | ||
| 267 | void ReportFile::Write(const char *buffer, uptr length) { | |
| 268 | SpinMutexLock l(mu); | |
| 269 | static const char *kWriteError = | |
| 270 | "ReportFile::Write() can't output requested buffer!\n"; | |
| 271 | ReopenIfNecessary(); | |
| 272 | if (length != write(fd, buffer, length)) { | |
| 273 | write(fd, kWriteError, internal_strlen(kWriteError)); | |
| 274 | Die(); | |
| 275 | } | |
| 276 | } | |
| 277 | ||
| 278 | uptr MainThreadStackBase, MainThreadStackSize; | |
| 279 | uptr MainThreadTlsBase, MainThreadTlsSize; | |
| 280 | ||
| 281 | } // namespace __sanitizer | |
| 282 | ||
| 283 | #endif // SANITIZER_RTEMS |
lib/tsan/sanitizer_common/sanitizer_rtems.h deleted-20| ... | ... | @@ -1,20 +0,0 @@ |
| 1 | //===-- sanitizer_rtems.h ---------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is shared between various sanitizers' runtime libraries and | |
| 10 | // provides definitions for RTEMS-specific functions. | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | #ifndef SANITIZER_RTEMS_H | |
| 13 | #define SANITIZER_RTEMS_H | |
| 14 | ||
| 15 | #include "sanitizer_platform.h" | |
| 16 | #if SANITIZER_RTEMS | |
| 17 | #include "sanitizer_common.h" | |
| 18 | ||
| 19 | #endif // SANITIZER_RTEMS | |
| 20 | #endif // SANITIZER_RTEMS_H |
lib/tsan/sanitizer_common/sanitizer_signal_interceptors.inc+4-1| ... | ... | @@ -53,7 +53,10 @@ INTERCEPTOR(uptr, signal, int signum, uptr handler) { |
| 53 | 53 | |
| 54 | 54 | INTERCEPTOR(int, sigaction_symname, int signum, |
| 55 | 55 | const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) { |
| 56 | if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0; | |
| 56 | if (GetHandleSignalMode(signum) == kHandleSignalExclusive) { | |
| 57 | if (!oldact) return 0; | |
| 58 | act = nullptr; | |
| 59 | } | |
| 57 | 60 | SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact); |
| 58 | 61 | } |
| 59 | 62 | #define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname) |
lib/tsan/sanitizer_common/sanitizer_solaris.cpp+27-5| ... | ... | @@ -74,6 +74,20 @@ DECLARE__REAL_AND_INTERNAL(int, mprotect, void *addr, uptr length, int prot) { |
| 74 | 74 | return _REAL(mprotect)(addr, length, prot); |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | // Illumos' declaration of madvise cannot be made visible if _XOPEN_SOURCE | |
| 78 | // is defined as g++ does on Solaris. | |
| 79 | // | |
| 80 | // This declaration is consistent with Solaris 11.4. Both Illumos and Solaris | |
| 81 | // versions older than 11.4 declared madvise with a caddr_t as the first | |
| 82 | // argument, but we don't currently support Solaris versions older than 11.4, | |
| 83 | // and as mentioned above the declaration is not visible on Illumos so we can | |
| 84 | // use any declaration we like on Illumos. | |
| 85 | extern "C" int madvise(void *, size_t, int); | |
| 86 | ||
| 87 | int internal_madvise(uptr addr, uptr length, int advice) { | |
| 88 | return madvise((void *)addr, length, advice); | |
| 89 | } | |
| 90 | ||
| 77 | 91 | DECLARE__REAL_AND_INTERNAL(uptr, close, fd_t fd) { |
| 78 | 92 | return _REAL(close)(fd); |
| 79 | 93 | } |
| ... | ... | @@ -146,8 +160,11 @@ DECLARE__REAL_AND_INTERNAL(uptr, sched_yield, void) { |
| 146 | 160 | return sched_yield(); |
| 147 | 161 | } |
| 148 | 162 | |
| 149 | DECLARE__REAL_AND_INTERNAL(void, _exit, int exitcode) { | |
| 150 | _exit(exitcode); | |
| 163 | DECLARE__REAL_AND_INTERNAL(void, usleep, u64 useconds) { | |
| 164 | struct timespec ts; | |
| 165 | ts.tv_sec = useconds / 1000000; | |
| 166 | ts.tv_nsec = (useconds % 1000000) * 1000; | |
| 167 | nanosleep(&ts, nullptr); | |
| 151 | 168 | } |
| 152 | 169 | |
| 153 | 170 | DECLARE__REAL_AND_INTERNAL(uptr, execve, const char *filename, |
| ... | ... | @@ -201,6 +218,13 @@ uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { |
| 201 | 218 | } |
| 202 | 219 | |
| 203 | 220 | // ----------------- sanitizer_common.h |
| 221 | void FutexWait(atomic_uint32_t *p, u32 cmp) { | |
| 222 | // FIXME: implement actual blocking. | |
| 223 | sched_yield(); | |
| 224 | } | |
| 225 | ||
| 226 | void FutexWake(atomic_uint32_t *p, u32 count) {} | |
| 227 | ||
| 204 | 228 | BlockingMutex::BlockingMutex() { |
| 205 | 229 | CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_)); |
| 206 | 230 | internal_memset(this, 0, sizeof(*this)); |
| ... | ... | @@ -221,9 +245,7 @@ void BlockingMutex::Unlock() { |
| 221 | 245 | CHECK_EQ(mutex_unlock((mutex_t *)&opaque_storage_), 0); |
| 222 | 246 | } |
| 223 | 247 | |
| 224 | void BlockingMutex::CheckLocked() { | |
| 225 | CHECK_EQ((uptr)thr_self(), owner_); | |
| 226 | } | |
| 248 | void BlockingMutex::CheckLocked() const { CHECK_EQ((uptr)thr_self(), owner_); } | |
| 227 | 249 | |
| 228 | 250 | } // namespace __sanitizer |
| 229 | 251 |
lib/tsan/sanitizer_common/sanitizer_stackdepot.cpp+7-2| ... | ... | @@ -115,6 +115,12 @@ void StackDepotUnlockAll() { |
| 115 | 115 | theDepot.UnlockAll(); |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | void StackDepotPrintAll() { | |
| 119 | #if !SANITIZER_GO | |
| 120 | theDepot.PrintAll(); | |
| 121 | #endif | |
| 122 | } | |
| 123 | ||
| 118 | 124 | bool StackDepotReverseMap::IdDescPair::IdComparator( |
| 119 | 125 | const StackDepotReverseMap::IdDescPair &a, |
| 120 | 126 | const StackDepotReverseMap::IdDescPair &b) { |
| ... | ... | @@ -139,8 +145,7 @@ StackTrace StackDepotReverseMap::Get(u32 id) { |
| 139 | 145 | if (!map_.size()) |
| 140 | 146 | return StackTrace(); |
| 141 | 147 | IdDescPair pair = {id, nullptr}; |
| 142 | uptr idx = | |
| 143 | InternalLowerBound(map_, 0, map_.size(), pair, IdDescPair::IdComparator); | |
| 148 | uptr idx = InternalLowerBound(map_, pair, IdDescPair::IdComparator); | |
| 144 | 149 | if (idx > map_.size() || map_[idx].id != id) |
| 145 | 150 | return StackTrace(); |
| 146 | 151 | return map_[idx].desc->load(); |
lib/tsan/sanitizer_common/sanitizer_stackdepot.h+1| ... | ... | @@ -41,6 +41,7 @@ StackTrace StackDepotGet(u32 id); |
| 41 | 41 | |
| 42 | 42 | void StackDepotLockAll(); |
| 43 | 43 | void StackDepotUnlockAll(); |
| 44 | void StackDepotPrintAll(); | |
| 44 | 45 | |
| 45 | 46 | // Instantiating this class creates a snapshot of StackDepot which can be |
| 46 | 47 | // efficiently queried with StackDepotGet(). You can use it concurrently with |
lib/tsan/sanitizer_common/sanitizer_stackdepotbase.h+19-1| ... | ... | @@ -13,9 +13,11 @@ |
| 13 | 13 | #ifndef SANITIZER_STACKDEPOTBASE_H |
| 14 | 14 | #define SANITIZER_STACKDEPOTBASE_H |
| 15 | 15 | |
| 16 | #include <stdio.h> | |
| 17 | ||
| 18 | #include "sanitizer_atomic.h" | |
| 16 | 19 | #include "sanitizer_internal_defs.h" |
| 17 | 20 | #include "sanitizer_mutex.h" |
| 18 | #include "sanitizer_atomic.h" | |
| 19 | 21 | #include "sanitizer_persistent_allocator.h" |
| 20 | 22 | |
| 21 | 23 | namespace __sanitizer { |
| ... | ... | @@ -34,6 +36,7 @@ class StackDepotBase { |
| 34 | 36 | |
| 35 | 37 | void LockAll(); |
| 36 | 38 | void UnlockAll(); |
| 39 | void PrintAll(); | |
| 37 | 40 | |
| 38 | 41 | private: |
| 39 | 42 | static Node *find(Node *s, args_type args, u32 hash); |
| ... | ... | @@ -172,6 +175,21 @@ void StackDepotBase<Node, kReservedBits, kTabSizeLog>::UnlockAll() { |
| 172 | 175 | } |
| 173 | 176 | } |
| 174 | 177 | |
| 178 | template <class Node, int kReservedBits, int kTabSizeLog> | |
| 179 | void StackDepotBase<Node, kReservedBits, kTabSizeLog>::PrintAll() { | |
| 180 | for (int i = 0; i < kTabSize; ++i) { | |
| 181 | atomic_uintptr_t *p = &tab[i]; | |
| 182 | lock(p); | |
| 183 | uptr v = atomic_load(p, memory_order_relaxed); | |
| 184 | Node *s = (Node *)(v & ~1UL); | |
| 185 | for (; s; s = s->link) { | |
| 186 | Printf("Stack for id %u:\n", s->id); | |
| 187 | s->load().Print(); | |
| 188 | } | |
| 189 | unlock(p, s); | |
| 190 | } | |
| 191 | } | |
| 192 | ||
| 175 | 193 | } // namespace __sanitizer |
| 176 | 194 | |
| 177 | 195 | #endif // SANITIZER_STACKDEPOTBASE_H |
lib/tsan/sanitizer_common/sanitizer_stacktrace.cpp+37-3| ... | ... | @@ -10,9 +10,12 @@ |
| 10 | 10 | // run-time libraries. |
| 11 | 11 | //===----------------------------------------------------------------------===// |
| 12 | 12 | |
| 13 | #include "sanitizer_stacktrace.h" | |
| 14 | ||
| 13 | 15 | #include "sanitizer_common.h" |
| 14 | 16 | #include "sanitizer_flags.h" |
| 15 | #include "sanitizer_stacktrace.h" | |
| 17 | #include "sanitizer_platform.h" | |
| 18 | #include "sanitizer_ptrauth.h" | |
| 16 | 19 | |
| 17 | 20 | namespace __sanitizer { |
| 18 | 21 | |
| ... | ... | @@ -21,6 +24,28 @@ uptr StackTrace::GetNextInstructionPc(uptr pc) { |
| 21 | 24 | return pc + 8; |
| 22 | 25 | #elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__) |
| 23 | 26 | return pc + 4; |
| 27 | #elif SANITIZER_RISCV64 | |
| 28 | // Current check order is 4 -> 2 -> 6 -> 8 | |
| 29 | u8 InsnByte = *(u8 *)(pc); | |
| 30 | if (((InsnByte & 0x3) == 0x3) && ((InsnByte & 0x1c) != 0x1c)) { | |
| 31 | // xxxxxxxxxxxbbb11 | 32 bit | bbb != 111 | |
| 32 | return pc + 4; | |
| 33 | } | |
| 34 | if ((InsnByte & 0x3) != 0x3) { | |
| 35 | // xxxxxxxxxxxxxxaa | 16 bit | aa != 11 | |
| 36 | return pc + 2; | |
| 37 | } | |
| 38 | // RISC-V encoding allows instructions to be up to 8 bytes long | |
| 39 | if ((InsnByte & 0x3f) == 0x1f) { | |
| 40 | // xxxxxxxxxx011111 | 48 bit | | |
| 41 | return pc + 6; | |
| 42 | } | |
| 43 | if ((InsnByte & 0x7f) == 0x3f) { | |
| 44 | // xxxxxxxxx0111111 | 64 bit | | |
| 45 | return pc + 8; | |
| 46 | } | |
| 47 | // bail-out if could not figure out the instruction size | |
| 48 | return 0; | |
| 24 | 49 | #else |
| 25 | 50 | return pc + 1; |
| 26 | 51 | #endif |
| ... | ... | @@ -94,8 +119,11 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top, |
| 94 | 119 | uhwptr pc1 = caller_frame[2]; |
| 95 | 120 | #elif defined(__s390__) |
| 96 | 121 | uhwptr pc1 = frame[14]; |
| 122 | #elif defined(__riscv) | |
| 123 | // frame[-1] contains the return address | |
| 124 | uhwptr pc1 = frame[-1]; | |
| 97 | 125 | #else |
| 98 | uhwptr pc1 = frame[1]; | |
| 126 | uhwptr pc1 = STRIP_PAC_PC((void *)frame[1]); | |
| 99 | 127 | #endif |
| 100 | 128 | // Let's assume that any pointer in the 0th page (i.e. <0x1000 on i386 and |
| 101 | 129 | // x86_64) is invalid and stop unwinding here. If we're adding support for |
| ... | ... | @@ -106,7 +134,13 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top, |
| 106 | 134 | trace_buffer[size++] = (uptr) pc1; |
| 107 | 135 | } |
| 108 | 136 | bottom = (uptr)frame; |
| 109 | frame = GetCanonicFrame((uptr)frame[0], stack_top, bottom); | |
| 137 | #if defined(__riscv) | |
| 138 | // frame[-2] contain fp of the previous frame | |
| 139 | uptr new_bp = (uptr)frame[-2]; | |
| 140 | #else | |
| 141 | uptr new_bp = (uptr)frame[0]; | |
| 142 | #endif | |
| 143 | frame = GetCanonicFrame(new_bp, stack_top, bottom); | |
| 110 | 144 | } |
| 111 | 145 | } |
| 112 | 146 |
lib/tsan/sanitizer_common/sanitizer_stacktrace.h+52-7| ... | ... | @@ -12,7 +12,9 @@ |
| 12 | 12 | #ifndef SANITIZER_STACKTRACE_H |
| 13 | 13 | #define SANITIZER_STACKTRACE_H |
| 14 | 14 | |
| 15 | #include "sanitizer_common.h" | |
| 15 | 16 | #include "sanitizer_internal_defs.h" |
| 17 | #include "sanitizer_platform.h" | |
| 16 | 18 | |
| 17 | 19 | namespace __sanitizer { |
| 18 | 20 | |
| ... | ... | @@ -24,8 +26,6 @@ static const u32 kStackTraceMax = 256; |
| 24 | 26 | # define SANITIZER_CAN_FAST_UNWIND 0 |
| 25 | 27 | #elif SANITIZER_WINDOWS |
| 26 | 28 | # define SANITIZER_CAN_FAST_UNWIND 0 |
| 27 | #elif SANITIZER_OPENBSD | |
| 28 | # define SANITIZER_CAN_FAST_UNWIND 0 | |
| 29 | 29 | #else |
| 30 | 30 | # define SANITIZER_CAN_FAST_UNWIND 1 |
| 31 | 31 | #endif |
| ... | ... | @@ -33,8 +33,8 @@ static const u32 kStackTraceMax = 256; |
| 33 | 33 | // Fast unwind is the only option on Mac for now; we will need to |
| 34 | 34 | // revisit this macro when slow unwind works on Mac, see |
| 35 | 35 | // https://github.com/google/sanitizers/issues/137 |
| 36 | #if SANITIZER_MAC || SANITIZER_OPENBSD || SANITIZER_RTEMS | |
| 37 | # define SANITIZER_CAN_SLOW_UNWIND 0 | |
| 36 | #if SANITIZER_MAC | |
| 37 | # define SANITIZER_CAN_SLOW_UNWIND 0 | |
| 38 | 38 | #else |
| 39 | 39 | # define SANITIZER_CAN_SLOW_UNWIND 1 |
| 40 | 40 | #endif |
| ... | ... | @@ -57,6 +57,16 @@ struct StackTrace { |
| 57 | 57 | // Prints a symbolized stacktrace, followed by an empty line. |
| 58 | 58 | void Print() const; |
| 59 | 59 | |
| 60 | // Prints a symbolized stacktrace to the output string, followed by an empty | |
| 61 | // line. | |
| 62 | void PrintTo(InternalScopedString *output) const; | |
| 63 | ||
| 64 | // Prints a symbolized stacktrace to the output buffer, followed by an empty | |
| 65 | // line. Returns the number of symbols that should have been written to buffer | |
| 66 | // (not including trailing '\0'). Thus, the string is truncated iff return | |
| 67 | // value is not less than "out_buf_size". | |
| 68 | uptr PrintTo(char *out_buf, uptr out_buf_size) const; | |
| 69 | ||
| 60 | 70 | static bool WillUseFastUnwind(bool request_fast_unwind) { |
| 61 | 71 | if (!SANITIZER_CAN_FAST_UNWIND) |
| 62 | 72 | return false; |
| ... | ... | @@ -68,8 +78,6 @@ struct StackTrace { |
| 68 | 78 | static uptr GetCurrentPc(); |
| 69 | 79 | static inline uptr GetPreviousInstructionPc(uptr pc); |
| 70 | 80 | static uptr GetNextInstructionPc(uptr pc); |
| 71 | typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer, | |
| 72 | int out_size); | |
| 73 | 81 | }; |
| 74 | 82 | |
| 75 | 83 | // Performance-critical, must be in the header. |
| ... | ... | @@ -85,6 +93,14 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) { |
| 85 | 93 | return pc - 4; |
| 86 | 94 | #elif defined(__sparc__) || defined(__mips__) |
| 87 | 95 | return pc - 8; |
| 96 | #elif SANITIZER_RISCV64 | |
| 97 | // RV-64 has variable instruciton length... | |
| 98 | // C extentions gives us 2-byte instructoins | |
| 99 | // RV-64 has 4-byte instructions | |
| 100 | // + RISCV architecture allows instructions up to 8 bytes | |
| 101 | // It seems difficult to figure out the exact instruction length - | |
| 102 | // pc - 2 seems like a safe option for the purposes of stack tracing | |
| 103 | return pc - 2; | |
| 88 | 104 | #else |
| 89 | 105 | return pc - 1; |
| 90 | 106 | #endif |
| ... | ... | @@ -143,9 +159,17 @@ struct BufferedStackTrace : public StackTrace { |
| 143 | 159 | friend class FastUnwindTest; |
| 144 | 160 | }; |
| 145 | 161 | |
| 162 | #if defined(__s390x__) | |
| 163 | static const uptr kFrameSize = 160; | |
| 164 | #elif defined(__s390__) | |
| 165 | static const uptr kFrameSize = 96; | |
| 166 | #else | |
| 167 | static const uptr kFrameSize = 2 * sizeof(uhwptr); | |
| 168 | #endif | |
| 169 | ||
| 146 | 170 | // Check if given pointer points into allocated stack area. |
| 147 | 171 | static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) { |
| 148 | return frame > stack_bottom && frame < stack_top - 2 * sizeof (uhwptr); | |
| 172 | return frame > stack_bottom && frame < stack_top - kFrameSize; | |
| 149 | 173 | } |
| 150 | 174 | |
| 151 | 175 | } // namespace __sanitizer |
| ... | ... | @@ -172,5 +196,26 @@ static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) { |
| 172 | 196 | uptr local_stack; \ |
| 173 | 197 | uptr sp = (uptr)&local_stack |
| 174 | 198 | |
| 199 | // GET_CURRENT_PC() is equivalent to StackTrace::GetCurrentPc(). | |
| 200 | // Optimized x86 version is faster than GetCurrentPc because | |
| 201 | // it does not involve a function call, instead it reads RIP register. | |
| 202 | // Reads of RIP by an instruction return RIP pointing to the next | |
| 203 | // instruction, which is exactly what we want here, thus 0 offset. | |
| 204 | // It needs to be a macro because otherwise we will get the name | |
| 205 | // of this function on the top of most stacks. Attribute artificial | |
| 206 | // does not do what it claims to do, unfortunatley. And attribute | |
| 207 | // __nodebug__ is clang-only. If we would have an attribute that | |
| 208 | // would remove this function from debug info, we could simply make | |
| 209 | // StackTrace::GetCurrentPc() faster. | |
| 210 | #if defined(__x86_64__) | |
| 211 | # define GET_CURRENT_PC() \ | |
| 212 | ({ \ | |
| 213 | uptr pc; \ | |
| 214 | asm("lea 0(%%rip), %0" : "=r"(pc)); \ | |
| 215 | pc; \ | |
| 216 | }) | |
| 217 | #else | |
| 218 | # define GET_CURRENT_PC() StackTrace::GetCurrentPc() | |
| 219 | #endif | |
| 175 | 220 | |
| 176 | 221 | #endif // SANITIZER_STACKTRACE_H |
lib/tsan/sanitizer_common/sanitizer_stacktrace_libcdep.cpp+120-54| ... | ... | @@ -18,40 +18,119 @@ |
| 18 | 18 | |
| 19 | 19 | namespace __sanitizer { |
| 20 | 20 | |
| 21 | void StackTrace::Print() const { | |
| 21 | namespace { | |
| 22 | ||
| 23 | class StackTraceTextPrinter { | |
| 24 | public: | |
| 25 | StackTraceTextPrinter(const char *stack_trace_fmt, char frame_delimiter, | |
| 26 | InternalScopedString *output, | |
| 27 | InternalScopedString *dedup_token) | |
| 28 | : stack_trace_fmt_(stack_trace_fmt), | |
| 29 | frame_delimiter_(frame_delimiter), | |
| 30 | output_(output), | |
| 31 | dedup_token_(dedup_token), | |
| 32 | symbolize_(RenderNeedsSymbolization(stack_trace_fmt)) {} | |
| 33 | ||
| 34 | bool ProcessAddressFrames(uptr pc) { | |
| 35 | SymbolizedStack *frames = symbolize_ | |
| 36 | ? Symbolizer::GetOrInit()->SymbolizePC(pc) | |
| 37 | : SymbolizedStack::New(pc); | |
| 38 | if (!frames) | |
| 39 | return false; | |
| 40 | ||
| 41 | for (SymbolizedStack *cur = frames; cur; cur = cur->next) { | |
| 42 | uptr prev_len = output_->length(); | |
| 43 | RenderFrame(output_, stack_trace_fmt_, frame_num_++, cur->info.address, | |
| 44 | symbolize_ ? &cur->info : nullptr, | |
| 45 | common_flags()->symbolize_vs_style, | |
| 46 | common_flags()->strip_path_prefix); | |
| 47 | ||
| 48 | if (prev_len != output_->length()) | |
| 49 | output_->append("%c", frame_delimiter_); | |
| 50 | ||
| 51 | ExtendDedupToken(cur); | |
| 52 | } | |
| 53 | frames->ClearAll(); | |
| 54 | return true; | |
| 55 | } | |
| 56 | ||
| 57 | private: | |
| 58 | // Extend the dedup token by appending a new frame. | |
| 59 | void ExtendDedupToken(SymbolizedStack *stack) { | |
| 60 | if (!dedup_token_) | |
| 61 | return; | |
| 62 | ||
| 63 | if (dedup_frames_-- > 0) { | |
| 64 | if (dedup_token_->length()) | |
| 65 | dedup_token_->append("--"); | |
| 66 | if (stack->info.function != nullptr) | |
| 67 | dedup_token_->append(stack->info.function); | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | const char *stack_trace_fmt_; | |
| 72 | const char frame_delimiter_; | |
| 73 | int dedup_frames_ = common_flags()->dedup_token_length; | |
| 74 | uptr frame_num_ = 0; | |
| 75 | InternalScopedString *output_; | |
| 76 | InternalScopedString *dedup_token_; | |
| 77 | const bool symbolize_ = false; | |
| 78 | }; | |
| 79 | ||
| 80 | static void CopyStringToBuffer(const InternalScopedString &str, char *out_buf, | |
| 81 | uptr out_buf_size) { | |
| 82 | if (!out_buf_size) | |
| 83 | return; | |
| 84 | ||
| 85 | CHECK_GT(out_buf_size, 0); | |
| 86 | uptr copy_size = Min(str.length(), out_buf_size - 1); | |
| 87 | internal_memcpy(out_buf, str.data(), copy_size); | |
| 88 | out_buf[copy_size] = '\0'; | |
| 89 | } | |
| 90 | ||
| 91 | } // namespace | |
| 92 | ||
| 93 | void StackTrace::PrintTo(InternalScopedString *output) const { | |
| 94 | CHECK(output); | |
| 95 | ||
| 96 | InternalScopedString dedup_token; | |
| 97 | StackTraceTextPrinter printer(common_flags()->stack_trace_format, '\n', | |
| 98 | output, &dedup_token); | |
| 99 | ||
| 22 | 100 | if (trace == nullptr || size == 0) { |
| 23 | Printf(" <empty stack>\n\n"); | |
| 101 | output->append(" <empty stack>\n\n"); | |
| 24 | 102 | return; |
| 25 | 103 | } |
| 26 | InternalScopedString frame_desc(GetPageSizeCached() * 2); | |
| 27 | InternalScopedString dedup_token(GetPageSizeCached()); | |
| 28 | int dedup_frames = common_flags()->dedup_token_length; | |
| 29 | uptr frame_num = 0; | |
| 104 | ||
| 30 | 105 | for (uptr i = 0; i < size && trace[i]; i++) { |
| 31 | 106 | // PCs in stack traces are actually the return addresses, that is, |
| 32 | 107 | // addresses of the next instructions after the call. |
| 33 | 108 | uptr pc = GetPreviousInstructionPc(trace[i]); |
| 34 | SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(pc); | |
| 35 | CHECK(frames); | |
| 36 | for (SymbolizedStack *cur = frames; cur; cur = cur->next) { | |
| 37 | frame_desc.clear(); | |
| 38 | RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++, | |
| 39 | cur->info, common_flags()->symbolize_vs_style, | |
| 40 | common_flags()->strip_path_prefix); | |
| 41 | Printf("%s\n", frame_desc.data()); | |
| 42 | if (dedup_frames-- > 0) { | |
| 43 | if (dedup_token.length()) | |
| 44 | dedup_token.append("--"); | |
| 45 | if (cur->info.function != nullptr) | |
| 46 | dedup_token.append(cur->info.function); | |
| 47 | } | |
| 48 | } | |
| 49 | frames->ClearAll(); | |
| 109 | CHECK(printer.ProcessAddressFrames(pc)); | |
| 50 | 110 | } |
| 51 | // Always print a trailing empty line after stack trace. | |
| 52 | Printf("\n"); | |
| 111 | ||
| 112 | // Always add a trailing empty line after stack trace. | |
| 113 | output->append("\n"); | |
| 114 | ||
| 115 | // Append deduplication token, if non-empty. | |
| 53 | 116 | if (dedup_token.length()) |
| 54 | Printf("DEDUP_TOKEN: %s\n", dedup_token.data()); | |
| 117 | output->append("DEDUP_TOKEN: %s\n", dedup_token.data()); | |
| 118 | } | |
| 119 | ||
| 120 | uptr StackTrace::PrintTo(char *out_buf, uptr out_buf_size) const { | |
| 121 | CHECK(out_buf); | |
| 122 | ||
| 123 | InternalScopedString output; | |
| 124 | PrintTo(&output); | |
| 125 | CopyStringToBuffer(output, out_buf, out_buf_size); | |
| 126 | ||
| 127 | return output.length(); | |
| 128 | } | |
| 129 | ||
| 130 | void StackTrace::Print() const { | |
| 131 | InternalScopedString output; | |
| 132 | PrintTo(&output); | |
| 133 | Printf("%s", output.data()); | |
| 55 | 134 | } |
| 56 | 135 | |
| 57 | 136 | void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context, |
| ... | ... | @@ -76,12 +155,15 @@ void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context, |
| 76 | 155 | UnwindSlow(pc, context, max_depth); |
| 77 | 156 | else |
| 78 | 157 | UnwindSlow(pc, max_depth); |
| 158 | // If there are too few frames, the program may be built with | |
| 159 | // -fno-asynchronous-unwind-tables. Fall back to fast unwinder below. | |
| 160 | if (size > 2 || size >= max_depth) | |
| 161 | return; | |
| 79 | 162 | #else |
| 80 | 163 | UNREACHABLE("slow unwind requested but not available"); |
| 81 | 164 | #endif |
| 82 | } else { | |
| 83 | UnwindFast(pc, bp, stack_top, stack_bottom, max_depth); | |
| 84 | 165 | } |
| 166 | UnwindFast(pc, bp, stack_top, stack_bottom, max_depth); | |
| 85 | 167 | } |
| 86 | 168 | |
| 87 | 169 | static int GetModuleAndOffsetForPc(uptr pc, char *module_name, |
| ... | ... | @@ -106,34 +188,18 @@ extern "C" { |
| 106 | 188 | SANITIZER_INTERFACE_ATTRIBUTE |
| 107 | 189 | void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf, |
| 108 | 190 | uptr out_buf_size) { |
| 109 | if (!out_buf_size) return; | |
| 110 | pc = StackTrace::GetPreviousInstructionPc(pc); | |
| 111 | SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); | |
| 112 | if (!frame) { | |
| 113 | internal_strncpy(out_buf, "<can't symbolize>", out_buf_size); | |
| 114 | out_buf[out_buf_size - 1] = 0; | |
| 191 | if (!out_buf_size) | |
| 115 | 192 | return; |
| 193 | ||
| 194 | pc = StackTrace::GetPreviousInstructionPc(pc); | |
| 195 | ||
| 196 | InternalScopedString output; | |
| 197 | StackTraceTextPrinter printer(fmt, '\0', &output, nullptr); | |
| 198 | if (!printer.ProcessAddressFrames(pc)) { | |
| 199 | output.clear(); | |
| 200 | output.append("<can't symbolize>"); | |
| 116 | 201 | } |
| 117 | InternalScopedString frame_desc(GetPageSizeCached()); | |
| 118 | uptr frame_num = 0; | |
| 119 | // Reserve one byte for the final 0. | |
| 120 | char *out_end = out_buf + out_buf_size - 1; | |
| 121 | for (SymbolizedStack *cur = frame; cur && out_buf < out_end; | |
| 122 | cur = cur->next) { | |
| 123 | frame_desc.clear(); | |
| 124 | RenderFrame(&frame_desc, fmt, frame_num++, cur->info, | |
| 125 | common_flags()->symbolize_vs_style, | |
| 126 | common_flags()->strip_path_prefix); | |
| 127 | if (!frame_desc.length()) | |
| 128 | continue; | |
| 129 | // Reserve one byte for the terminating 0. | |
| 130 | uptr n = out_end - out_buf - 1; | |
| 131 | internal_strncpy(out_buf, frame_desc.data(), n); | |
| 132 | out_buf += __sanitizer::Min<uptr>(n, frame_desc.length()); | |
| 133 | *out_buf++ = 0; | |
| 134 | } | |
| 135 | CHECK(out_buf <= out_end); | |
| 136 | *out_buf = 0; | |
| 202 | CopyStringToBuffer(output, out_buf, out_buf_size); | |
| 137 | 203 | } |
| 138 | 204 | |
| 139 | 205 | SANITIZER_INTERFACE_ATTRIBUTE |
| ... | ... | @@ -143,7 +209,7 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt, |
| 143 | 209 | out_buf[0] = 0; |
| 144 | 210 | DataInfo DI; |
| 145 | 211 | if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr, &DI)) return; |
| 146 | InternalScopedString data_desc(GetPageSizeCached()); | |
| 212 | InternalScopedString data_desc; | |
| 147 | 213 | RenderData(&data_desc, fmt, &DI, common_flags()->strip_path_prefix); |
| 148 | 214 | internal_strncpy(out_buf, data_desc.data(), out_buf_size); |
| 149 | 215 | out_buf[out_buf_size - 1] = 0; |
lib/tsan/sanitizer_common/sanitizer_stacktrace_printer.cpp+60-32| ... | ... | @@ -107,8 +107,14 @@ static const char *DemangleFunctionName(const char *function) { |
| 107 | 107 | static const char kDefaultFormat[] = " #%n %p %F %L"; |
| 108 | 108 | |
| 109 | 109 | void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, |
| 110 | const AddressInfo &info, bool vs_style, | |
| 110 | uptr address, const AddressInfo *info, bool vs_style, | |
| 111 | 111 | const char *strip_path_prefix, const char *strip_func_prefix) { |
| 112 | // info will be null in the case where symbolization is not needed for the | |
| 113 | // given format. This ensures that the code below will get a hard failure | |
| 114 | // rather than print incorrect information in case RenderNeedsSymbolization | |
| 115 | // ever ends up out of sync with this function. If non-null, the addresses | |
| 116 | // should match. | |
| 117 | CHECK(!info || address == info->address); | |
| 112 | 118 | if (0 == internal_strcmp(format, "DEFAULT")) |
| 113 | 119 | format = kDefaultFormat; |
| 114 | 120 | for (const char *p = format; *p != '\0'; p++) { |
| ... | ... | @@ -126,71 +132,70 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, |
| 126 | 132 | buffer->append("%zu", frame_no); |
| 127 | 133 | break; |
| 128 | 134 | case 'p': |
| 129 | buffer->append("0x%zx", info.address); | |
| 135 | buffer->append("0x%zx", address); | |
| 130 | 136 | break; |
| 131 | 137 | case 'm': |
| 132 | buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix)); | |
| 138 | buffer->append("%s", StripPathPrefix(info->module, strip_path_prefix)); | |
| 133 | 139 | break; |
| 134 | 140 | case 'o': |
| 135 | buffer->append("0x%zx", info.module_offset); | |
| 141 | buffer->append("0x%zx", info->module_offset); | |
| 136 | 142 | break; |
| 137 | 143 | case 'f': |
| 138 | buffer->append("%s", | |
| 139 | DemangleFunctionName( | |
| 140 | StripFunctionName(info.function, strip_func_prefix))); | |
| 144 | buffer->append("%s", DemangleFunctionName(StripFunctionName( | |
| 145 | info->function, strip_func_prefix))); | |
| 141 | 146 | break; |
| 142 | 147 | case 'q': |
| 143 | buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown | |
| 144 | ? info.function_offset | |
| 148 | buffer->append("0x%zx", info->function_offset != AddressInfo::kUnknown | |
| 149 | ? info->function_offset | |
| 145 | 150 | : 0x0); |
| 146 | 151 | break; |
| 147 | 152 | case 's': |
| 148 | buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix)); | |
| 153 | buffer->append("%s", StripPathPrefix(info->file, strip_path_prefix)); | |
| 149 | 154 | break; |
| 150 | 155 | case 'l': |
| 151 | buffer->append("%d", info.line); | |
| 156 | buffer->append("%d", info->line); | |
| 152 | 157 | break; |
| 153 | 158 | case 'c': |
| 154 | buffer->append("%d", info.column); | |
| 159 | buffer->append("%d", info->column); | |
| 155 | 160 | break; |
| 156 | 161 | // Smarter special cases. |
| 157 | 162 | case 'F': |
| 158 | 163 | // Function name and offset, if file is unknown. |
| 159 | if (info.function) { | |
| 160 | buffer->append("in %s", | |
| 161 | DemangleFunctionName( | |
| 162 | StripFunctionName(info.function, strip_func_prefix))); | |
| 163 | if (!info.file && info.function_offset != AddressInfo::kUnknown) | |
| 164 | buffer->append("+0x%zx", info.function_offset); | |
| 164 | if (info->function) { | |
| 165 | buffer->append("in %s", DemangleFunctionName(StripFunctionName( | |
| 166 | info->function, strip_func_prefix))); | |
| 167 | if (!info->file && info->function_offset != AddressInfo::kUnknown) | |
| 168 | buffer->append("+0x%zx", info->function_offset); | |
| 165 | 169 | } |
| 166 | 170 | break; |
| 167 | 171 | case 'S': |
| 168 | 172 | // File/line information. |
| 169 | RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style, | |
| 170 | strip_path_prefix); | |
| 173 | RenderSourceLocation(buffer, info->file, info->line, info->column, | |
| 174 | vs_style, strip_path_prefix); | |
| 171 | 175 | break; |
| 172 | 176 | case 'L': |
| 173 | 177 | // Source location, or module location. |
| 174 | if (info.file) { | |
| 175 | RenderSourceLocation(buffer, info.file, info.line, info.column, | |
| 178 | if (info->file) { | |
| 179 | RenderSourceLocation(buffer, info->file, info->line, info->column, | |
| 176 | 180 | vs_style, strip_path_prefix); |
| 177 | } else if (info.module) { | |
| 178 | RenderModuleLocation(buffer, info.module, info.module_offset, | |
| 179 | info.module_arch, strip_path_prefix); | |
| 181 | } else if (info->module) { | |
| 182 | RenderModuleLocation(buffer, info->module, info->module_offset, | |
| 183 | info->module_arch, strip_path_prefix); | |
| 180 | 184 | } else { |
| 181 | 185 | buffer->append("(<unknown module>)"); |
| 182 | 186 | } |
| 183 | 187 | break; |
| 184 | 188 | case 'M': |
| 185 | 189 | // Module basename and offset, or PC. |
| 186 | if (info.address & kExternalPCBit) | |
| 187 | {} // There PCs are not meaningful. | |
| 188 | else if (info.module) | |
| 190 | if (address & kExternalPCBit) { | |
| 191 | // There PCs are not meaningful. | |
| 192 | } else if (info->module) { | |
| 189 | 193 | // Always strip the module name for %M. |
| 190 | RenderModuleLocation(buffer, StripModuleName(info.module), | |
| 191 | info.module_offset, info.module_arch, ""); | |
| 192 | else | |
| 193 | buffer->append("(%p)", (void *)info.address); | |
| 194 | RenderModuleLocation(buffer, StripModuleName(info->module), | |
| 195 | info->module_offset, info->module_arch, ""); | |
| 196 | } else { | |
| 197 | buffer->append("(%p)", (void *)address); | |
| 198 | } | |
| 194 | 199 | break; |
| 195 | 200 | default: |
| 196 | 201 | Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p, |
| ... | ... | @@ -200,6 +205,29 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, |
| 200 | 205 | } |
| 201 | 206 | } |
| 202 | 207 | |
| 208 | bool RenderNeedsSymbolization(const char *format) { | |
| 209 | if (0 == internal_strcmp(format, "DEFAULT")) | |
| 210 | format = kDefaultFormat; | |
| 211 | for (const char *p = format; *p != '\0'; p++) { | |
| 212 | if (*p != '%') | |
| 213 | continue; | |
| 214 | p++; | |
| 215 | switch (*p) { | |
| 216 | case '%': | |
| 217 | break; | |
| 218 | case 'n': | |
| 219 | // frame_no | |
| 220 | break; | |
| 221 | case 'p': | |
| 222 | // address | |
| 223 | break; | |
| 224 | default: | |
| 225 | return true; | |
| 226 | } | |
| 227 | } | |
| 228 | return false; | |
| 229 | } | |
| 230 | ||
| 203 | 231 | void RenderData(InternalScopedString *buffer, const char *format, |
| 204 | 232 | const DataInfo *DI, const char *strip_path_prefix) { |
| 205 | 233 | for (const char *p = format; *p != '\0'; p++) { |
lib/tsan/sanitizer_common/sanitizer_stacktrace_printer.h+3-1| ... | ... | @@ -47,10 +47,12 @@ namespace __sanitizer { |
| 47 | 47 | // module+offset if it is known, or (<unknown module>) string. |
| 48 | 48 | // %M - prints module basename and offset, if it is known, or PC. |
| 49 | 49 | void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, |
| 50 | const AddressInfo &info, bool vs_style, | |
| 50 | uptr address, const AddressInfo *info, bool vs_style, | |
| 51 | 51 | const char *strip_path_prefix = "", |
| 52 | 52 | const char *strip_func_prefix = ""); |
| 53 | 53 | |
| 54 | bool RenderNeedsSymbolization(const char *format); | |
| 55 | ||
| 54 | 56 | void RenderSourceLocation(InternalScopedString *buffer, const char *file, |
| 55 | 57 | int line, int column, bool vs_style, |
| 56 | 58 | const char *strip_path_prefix); |
lib/tsan/sanitizer_common/sanitizer_stoptheworld.h+7-6| ... | ... | @@ -32,20 +32,21 @@ class SuspendedThreadsList { |
| 32 | 32 | |
| 33 | 33 | // Can't declare pure virtual functions in sanitizer runtimes: |
| 34 | 34 | // __cxa_pure_virtual might be unavailable. Use UNIMPLEMENTED() instead. |
| 35 | virtual PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, | |
| 36 | uptr *sp) const { | |
| 35 | virtual PtraceRegistersStatus GetRegistersAndSP( | |
| 36 | uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const { | |
| 37 | 37 | UNIMPLEMENTED(); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | // The buffer in GetRegistersAndSP should be at least this big. | |
| 41 | virtual uptr RegisterCount() const { UNIMPLEMENTED(); } | |
| 42 | 40 | virtual uptr ThreadCount() const { UNIMPLEMENTED(); } |
| 43 | 41 | virtual tid_t GetThreadID(uptr index) const { UNIMPLEMENTED(); } |
| 44 | 42 | |
| 43 | protected: | |
| 44 | ~SuspendedThreadsList() {} | |
| 45 | ||
| 45 | 46 | private: |
| 46 | 47 | // Prohibit copy and assign. |
| 47 | SuspendedThreadsList(const SuspendedThreadsList&); | |
| 48 | void operator=(const SuspendedThreadsList&); | |
| 48 | SuspendedThreadsList(const SuspendedThreadsList &) = delete; | |
| 49 | void operator=(const SuspendedThreadsList &) = delete; | |
| 49 | 50 | }; |
| 50 | 51 | |
| 51 | 52 | typedef void (*StopTheWorldCallback)( |
lib/tsan/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp+2-1| ... | ... | @@ -17,6 +17,7 @@ |
| 17 | 17 | #include <zircon/sanitizer.h> |
| 18 | 18 | |
| 19 | 19 | #include "sanitizer_stoptheworld.h" |
| 20 | #include "sanitizer_stoptheworld_fuchsia.h" | |
| 20 | 21 | |
| 21 | 22 | namespace __sanitizer { |
| 22 | 23 | |
| ... | ... | @@ -32,7 +33,7 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) { |
| 32 | 33 | nullptr, nullptr, nullptr, nullptr, |
| 33 | 34 | [](zx_status_t, void *data) { |
| 34 | 35 | auto params = reinterpret_cast<Params *>(data); |
| 35 | params->callback({}, params->argument); | |
| 36 | params->callback(SuspendedThreadsListFuchsia(), params->argument); | |
| 36 | 37 | }, |
| 37 | 38 | &params); |
| 38 | 39 | } |
lib/tsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp+78-28| ... | ... | @@ -13,10 +13,10 @@ |
| 13 | 13 | |
| 14 | 14 | #include "sanitizer_platform.h" |
| 15 | 15 | |
| 16 | #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || \ | |
| 17 | defined(__aarch64__) || defined(__powerpc64__) || \ | |
| 18 | defined(__s390__) || defined(__i386__) || \ | |
| 19 | defined(__arm__)) | |
| 16 | #if SANITIZER_LINUX && \ | |
| 17 | (defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ | |
| 18 | defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ | |
| 19 | defined(__arm__) || SANITIZER_RISCV64) | |
| 20 | 20 | |
| 21 | 21 | #include "sanitizer_stoptheworld.h" |
| 22 | 22 | |
| ... | ... | @@ -31,7 +31,7 @@ |
| 31 | 31 | #include <sys/types.h> // for pid_t |
| 32 | 32 | #include <sys/uio.h> // for iovec |
| 33 | 33 | #include <elf.h> // for NT_PRSTATUS |
| 34 | #if defined(__aarch64__) && !SANITIZER_ANDROID | |
| 34 | #if (defined(__aarch64__) || SANITIZER_RISCV64) && !SANITIZER_ANDROID | |
| 35 | 35 | // GLIBC 2.20+ sys/user does not include asm/ptrace.h |
| 36 | 36 | # include <asm/ptrace.h> |
| 37 | 37 | #endif |
| ... | ... | @@ -85,18 +85,18 @@ |
| 85 | 85 | |
| 86 | 86 | namespace __sanitizer { |
| 87 | 87 | |
| 88 | class SuspendedThreadsListLinux : public SuspendedThreadsList { | |
| 88 | class SuspendedThreadsListLinux final : public SuspendedThreadsList { | |
| 89 | 89 | public: |
| 90 | 90 | SuspendedThreadsListLinux() { thread_ids_.reserve(1024); } |
| 91 | 91 | |
| 92 | tid_t GetThreadID(uptr index) const; | |
| 93 | uptr ThreadCount() const; | |
| 92 | tid_t GetThreadID(uptr index) const override; | |
| 93 | uptr ThreadCount() const override; | |
| 94 | 94 | bool ContainsTid(tid_t thread_id) const; |
| 95 | 95 | void Append(tid_t tid); |
| 96 | 96 | |
| 97 | PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, | |
| 98 | uptr *sp) const; | |
| 99 | uptr RegisterCount() const; | |
| 97 | PtraceRegistersStatus GetRegistersAndSP(uptr index, | |
| 98 | InternalMmapVector<uptr> *buffer, | |
| 99 | uptr *sp) const override; | |
| 100 | 100 | |
| 101 | 101 | private: |
| 102 | 102 | InternalMmapVector<tid_t> thread_ids_; |
| ... | ... | @@ -485,6 +485,16 @@ typedef user_regs_struct regs_struct; |
| 485 | 485 | #else |
| 486 | 486 | #define REG_SP rsp |
| 487 | 487 | #endif |
| 488 | #define ARCH_IOVEC_FOR_GETREGSET | |
| 489 | // Support ptrace extensions even when compiled without required kernel support | |
| 490 | #ifndef NT_X86_XSTATE | |
| 491 | #define NT_X86_XSTATE 0x202 | |
| 492 | #endif | |
| 493 | #ifndef PTRACE_GETREGSET | |
| 494 | #define PTRACE_GETREGSET 0x4204 | |
| 495 | #endif | |
| 496 | // Compiler may use FP registers to store pointers. | |
| 497 | static constexpr uptr kExtraRegs[] = {NT_X86_XSTATE, NT_FPREGSET}; | |
| 488 | 498 | |
| 489 | 499 | #elif defined(__powerpc__) || defined(__powerpc64__) |
| 490 | 500 | typedef pt_regs regs_struct; |
| ... | ... | @@ -501,11 +511,21 @@ typedef struct user regs_struct; |
| 501 | 511 | #elif defined(__aarch64__) |
| 502 | 512 | typedef struct user_pt_regs regs_struct; |
| 503 | 513 | #define REG_SP sp |
| 514 | static constexpr uptr kExtraRegs[] = {0}; | |
| 515 | #define ARCH_IOVEC_FOR_GETREGSET | |
| 516 | ||
| 517 | #elif SANITIZER_RISCV64 | |
| 518 | typedef struct user_regs_struct regs_struct; | |
| 519 | // sys/ucontext.h already defines REG_SP as 2. Undefine it first. | |
| 520 | #undef REG_SP | |
| 521 | #define REG_SP sp | |
| 522 | static constexpr uptr kExtraRegs[] = {0}; | |
| 504 | 523 | #define ARCH_IOVEC_FOR_GETREGSET |
| 505 | 524 | |
| 506 | 525 | #elif defined(__s390__) |
| 507 | 526 | typedef _user_regs_struct regs_struct; |
| 508 | 527 | #define REG_SP gprs[15] |
| 528 | static constexpr uptr kExtraRegs[] = {0}; | |
| 509 | 529 | #define ARCH_IOVEC_FOR_GETREGSET |
| 510 | 530 | |
| 511 | 531 | #else |
| ... | ... | @@ -533,24 +553,58 @@ void SuspendedThreadsListLinux::Append(tid_t tid) { |
| 533 | 553 | } |
| 534 | 554 | |
| 535 | 555 | PtraceRegistersStatus SuspendedThreadsListLinux::GetRegistersAndSP( |
| 536 | uptr index, uptr *buffer, uptr *sp) const { | |
| 556 | uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const { | |
| 537 | 557 | pid_t tid = GetThreadID(index); |
| 538 | regs_struct regs; | |
| 558 | constexpr uptr uptr_sz = sizeof(uptr); | |
| 539 | 559 | int pterrno; |
| 540 | 560 | #ifdef ARCH_IOVEC_FOR_GETREGSET |
| 541 | struct iovec regset_io; | |
| 542 | regset_io.iov_base = &regs; | |
| 543 | regset_io.iov_len = sizeof(regs_struct); | |
| 544 | bool isErr = internal_iserror(internal_ptrace(PTRACE_GETREGSET, tid, | |
| 545 | (void*)NT_PRSTATUS, (void*)&regset_io), | |
| 546 | &pterrno); | |
| 561 | auto append = [&](uptr regset) { | |
| 562 | uptr size = buffer->size(); | |
| 563 | // NT_X86_XSTATE requires 64bit alignment. | |
| 564 | uptr size_up = RoundUpTo(size, 8 / uptr_sz); | |
| 565 | buffer->reserve(Max<uptr>(1024, size_up)); | |
| 566 | struct iovec regset_io; | |
| 567 | for (;; buffer->resize(buffer->capacity() * 2)) { | |
| 568 | buffer->resize(buffer->capacity()); | |
| 569 | uptr available_bytes = (buffer->size() - size_up) * uptr_sz; | |
| 570 | regset_io.iov_base = buffer->data() + size_up; | |
| 571 | regset_io.iov_len = available_bytes; | |
| 572 | bool fail = | |
| 573 | internal_iserror(internal_ptrace(PTRACE_GETREGSET, tid, | |
| 574 | (void *)regset, (void *)&regset_io), | |
| 575 | &pterrno); | |
| 576 | if (fail) { | |
| 577 | VReport(1, "Could not get regset %p from thread %d (errno %d).\n", | |
| 578 | (void *)regset, tid, pterrno); | |
| 579 | buffer->resize(size); | |
| 580 | return false; | |
| 581 | } | |
| 582 | ||
| 583 | // Far enough from the buffer size, no need to resize and repeat. | |
| 584 | if (regset_io.iov_len + 64 < available_bytes) | |
| 585 | break; | |
| 586 | } | |
| 587 | buffer->resize(size_up + RoundUpTo(regset_io.iov_len, uptr_sz) / uptr_sz); | |
| 588 | return true; | |
| 589 | }; | |
| 590 | ||
| 591 | buffer->clear(); | |
| 592 | bool fail = !append(NT_PRSTATUS); | |
| 593 | if (!fail) { | |
| 594 | // Accept the first available and do not report errors. | |
| 595 | for (uptr regs : kExtraRegs) | |
| 596 | if (regs && append(regs)) | |
| 597 | break; | |
| 598 | } | |
| 547 | 599 | #else |
| 548 | bool isErr = internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, nullptr, | |
| 549 | &regs), &pterrno); | |
| 550 | #endif | |
| 551 | if (isErr) { | |
| 600 | buffer->resize(RoundUpTo(sizeof(regs_struct), uptr_sz) / uptr_sz); | |
| 601 | bool fail = internal_iserror( | |
| 602 | internal_ptrace(PTRACE_GETREGS, tid, nullptr, buffer->data()), &pterrno); | |
| 603 | if (fail) | |
| 552 | 604 | VReport(1, "Could not get registers from thread %d (errno %d).\n", tid, |
| 553 | 605 | pterrno); |
| 606 | #endif | |
| 607 | if (fail) { | |
| 554 | 608 | // ESRCH means that the given thread is not suspended or already dead. |
| 555 | 609 | // Therefore it's unsafe to inspect its data (e.g. walk through stack) and |
| 556 | 610 | // we should notify caller about this. |
| ... | ... | @@ -558,14 +612,10 @@ PtraceRegistersStatus SuspendedThreadsListLinux::GetRegistersAndSP( |
| 558 | 612 | : REGISTERS_UNAVAILABLE; |
| 559 | 613 | } |
| 560 | 614 | |
| 561 | *sp = regs.REG_SP; | |
| 562 | internal_memcpy(buffer, &regs, sizeof(regs)); | |
| 615 | *sp = reinterpret_cast<regs_struct *>(buffer->data())[0].REG_SP; | |
| 563 | 616 | return REGISTERS_AVAILABLE; |
| 564 | 617 | } |
| 565 | 618 | |
| 566 | uptr SuspendedThreadsListLinux::RegisterCount() const { | |
| 567 | return sizeof(regs_struct) / sizeof(uptr); | |
| 568 | } | |
| 569 | 619 | } // namespace __sanitizer |
| 570 | 620 | |
| 571 | 621 | #endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) |
lib/tsan/sanitizer_common/sanitizer_stoptheworld_mac.cpp+9-11| ... | ... | @@ -27,19 +27,19 @@ typedef struct { |
| 27 | 27 | thread_t thread; |
| 28 | 28 | } SuspendedThreadInfo; |
| 29 | 29 | |
| 30 | class SuspendedThreadsListMac : public SuspendedThreadsList { | |
| 30 | class SuspendedThreadsListMac final : public SuspendedThreadsList { | |
| 31 | 31 | public: |
| 32 | 32 | SuspendedThreadsListMac() : threads_(1024) {} |
| 33 | 33 | |
| 34 | tid_t GetThreadID(uptr index) const; | |
| 34 | tid_t GetThreadID(uptr index) const override; | |
| 35 | 35 | thread_t GetThread(uptr index) const; |
| 36 | uptr ThreadCount() const; | |
| 36 | uptr ThreadCount() const override; | |
| 37 | 37 | bool ContainsThread(thread_t thread) const; |
| 38 | 38 | void Append(thread_t thread); |
| 39 | 39 | |
| 40 | PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, | |
| 41 | uptr *sp) const; | |
| 42 | uptr RegisterCount() const; | |
| 40 | PtraceRegistersStatus GetRegistersAndSP(uptr index, | |
| 41 | InternalMmapVector<uptr> *buffer, | |
| 42 | uptr *sp) const override; | |
| 43 | 43 | |
| 44 | 44 | private: |
| 45 | 45 | InternalMmapVector<SuspendedThreadInfo> threads_; |
| ... | ... | @@ -142,7 +142,7 @@ void SuspendedThreadsListMac::Append(thread_t thread) { |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP( |
| 145 | uptr index, uptr *buffer, uptr *sp) const { | |
| 145 | uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const { | |
| 146 | 146 | thread_t thread = GetThread(index); |
| 147 | 147 | regs_struct regs; |
| 148 | 148 | int err; |
| ... | ... | @@ -159,7 +159,8 @@ PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP( |
| 159 | 159 | : REGISTERS_UNAVAILABLE; |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | internal_memcpy(buffer, &regs, sizeof(regs)); | |
| 162 | buffer->resize(RoundUpTo(sizeof(regs), sizeof(uptr)) / sizeof(uptr)); | |
| 163 | internal_memcpy(buffer->data(), &regs, sizeof(regs)); | |
| 163 | 164 | #if defined(__aarch64__) && defined(arm_thread_state64_get_sp) |
| 164 | 165 | *sp = arm_thread_state64_get_sp(regs); |
| 165 | 166 | #else |
| ... | ... | @@ -173,9 +174,6 @@ PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP( |
| 173 | 174 | return REGISTERS_AVAILABLE; |
| 174 | 175 | } |
| 175 | 176 | |
| 176 | uptr SuspendedThreadsListMac::RegisterCount() const { | |
| 177 | return MACHINE_THREAD_STATE_COUNT; | |
| 178 | } | |
| 179 | 177 | } // namespace __sanitizer |
| 180 | 178 | |
| 181 | 179 | #endif // SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__)) || |
lib/tsan/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp+7-9| ... | ... | @@ -48,7 +48,7 @@ |
| 48 | 48 | |
| 49 | 49 | namespace __sanitizer { |
| 50 | 50 | |
| 51 | class SuspendedThreadsListNetBSD : public SuspendedThreadsList { | |
| 51 | class SuspendedThreadsListNetBSD final : public SuspendedThreadsList { | |
| 52 | 52 | public: |
| 53 | 53 | SuspendedThreadsListNetBSD() { thread_ids_.reserve(1024); } |
| 54 | 54 | |
| ... | ... | @@ -57,9 +57,9 @@ class SuspendedThreadsListNetBSD : public SuspendedThreadsList { |
| 57 | 57 | bool ContainsTid(tid_t thread_id) const; |
| 58 | 58 | void Append(tid_t tid); |
| 59 | 59 | |
| 60 | PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, | |
| 60 | PtraceRegistersStatus GetRegistersAndSP(uptr index, | |
| 61 | InternalMmapVector<uptr> *buffer, | |
| 61 | 62 | uptr *sp) const; |
| 62 | uptr RegisterCount() const; | |
| 63 | 63 | |
| 64 | 64 | private: |
| 65 | 65 | InternalMmapVector<tid_t> thread_ids_; |
| ... | ... | @@ -131,7 +131,7 @@ bool ThreadSuspender::SuspendAllThreads() { |
| 131 | 131 | pl.pl_lwpid = 0; |
| 132 | 132 | |
| 133 | 133 | int val; |
| 134 | while ((val = ptrace(op, pid_, (void *)&pl, sizeof(pl))) != -1 && | |
| 134 | while ((val = internal_ptrace(op, pid_, (void *)&pl, sizeof(pl))) != -1 && | |
| 135 | 135 | pl.pl_lwpid != 0) { |
| 136 | 136 | suspended_threads_list_.Append(pl.pl_lwpid); |
| 137 | 137 | VReport(2, "Appended thread %d in process %d.\n", pl.pl_lwpid, pid_); |
| ... | ... | @@ -335,7 +335,7 @@ void SuspendedThreadsListNetBSD::Append(tid_t tid) { |
| 335 | 335 | } |
| 336 | 336 | |
| 337 | 337 | PtraceRegistersStatus SuspendedThreadsListNetBSD::GetRegistersAndSP( |
| 338 | uptr index, uptr *buffer, uptr *sp) const { | |
| 338 | uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const { | |
| 339 | 339 | lwpid_t tid = GetThreadID(index); |
| 340 | 340 | pid_t ppid = internal_getppid(); |
| 341 | 341 | struct reg regs; |
| ... | ... | @@ -351,14 +351,12 @@ PtraceRegistersStatus SuspendedThreadsListNetBSD::GetRegistersAndSP( |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | 353 | *sp = PTRACE_REG_SP(&regs); |
| 354 | internal_memcpy(buffer, &regs, sizeof(regs)); | |
| 354 | buffer->resize(RoundUpTo(sizeof(regs), sizeof(uptr)) / sizeof(uptr)); | |
| 355 | internal_memcpy(buffer->data(), &regs, sizeof(regs)); | |
| 355 | 356 | |
| 356 | 357 | return REGISTERS_AVAILABLE; |
| 357 | 358 | } |
| 358 | 359 | |
| 359 | uptr SuspendedThreadsListNetBSD::RegisterCount() const { | |
| 360 | return sizeof(struct reg) / sizeof(uptr); | |
| 361 | } | |
| 362 | 360 | } // namespace __sanitizer |
| 363 | 361 | |
| 364 | 362 | #endif |
lib/tsan/sanitizer_common/sanitizer_suppressions.cpp+2-2| ... | ... | @@ -34,7 +34,7 @@ SuppressionContext::SuppressionContext(const char *suppression_types[], |
| 34 | 34 | static bool GetPathAssumingFileIsRelativeToExec(const char *file_path, |
| 35 | 35 | /*out*/char *new_file_path, |
| 36 | 36 | uptr new_file_path_size) { |
| 37 | InternalScopedString exec(kMaxPathLength); | |
| 37 | InternalMmapVector<char> exec(kMaxPathLength); | |
| 38 | 38 | if (ReadBinaryNameCached(exec.data(), exec.size())) { |
| 39 | 39 | const char *file_name_pos = StripModuleName(exec.data()); |
| 40 | 40 | uptr path_to_exec_len = file_name_pos - exec.data(); |
| ... | ... | @@ -69,7 +69,7 @@ void SuppressionContext::ParseFromFile(const char *filename) { |
| 69 | 69 | if (filename[0] == '\0') |
| 70 | 70 | return; |
| 71 | 71 | |
| 72 | InternalScopedString new_file_path(kMaxPathLength); | |
| 72 | InternalMmapVector<char> new_file_path(kMaxPathLength); | |
| 73 | 73 | filename = FindFile(filename, new_file_path.data(), new_file_path.size()); |
| 74 | 74 | |
| 75 | 75 | // Read the file. |
lib/tsan/sanitizer_common/sanitizer_symbolizer_internal.h+6-1| ... | ... | @@ -74,6 +74,9 @@ class SymbolizerTool { |
| 74 | 74 | // Usually this is a safe place to call code that might need to use user |
| 75 | 75 | // memory allocators. |
| 76 | 76 | virtual void LateInitialize() {} |
| 77 | ||
| 78 | protected: | |
| 79 | ~SymbolizerTool() {} | |
| 77 | 80 | }; |
| 78 | 81 | |
| 79 | 82 | // SymbolizerProcess encapsulates communication between the tool and |
| ... | ... | @@ -85,6 +88,8 @@ class SymbolizerProcess { |
| 85 | 88 | const char *SendCommand(const char *command); |
| 86 | 89 | |
| 87 | 90 | protected: |
| 91 | ~SymbolizerProcess() {} | |
| 92 | ||
| 88 | 93 | /// The maximum number of arguments required to invoke a tool process. |
| 89 | 94 | static const unsigned kArgVMax = 6; |
| 90 | 95 | |
| ... | ... | @@ -128,7 +133,7 @@ class LLVMSymbolizerProcess; |
| 128 | 133 | |
| 129 | 134 | // This tool invokes llvm-symbolizer in a subprocess. It should be as portable |
| 130 | 135 | // as the llvm-symbolizer tool is. |
| 131 | class LLVMSymbolizer : public SymbolizerTool { | |
| 136 | class LLVMSymbolizer final : public SymbolizerTool { | |
| 132 | 137 | public: |
| 133 | 138 | explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator); |
| 134 | 139 |
lib/tsan/sanitizer_common/sanitizer_symbolizer_libbacktrace.h+1-1| ... | ... | @@ -28,7 +28,7 @@ |
| 28 | 28 | |
| 29 | 29 | namespace __sanitizer { |
| 30 | 30 | |
| 31 | class LibbacktraceSymbolizer : public SymbolizerTool { | |
| 31 | class LibbacktraceSymbolizer final : public SymbolizerTool { | |
| 32 | 32 | public: |
| 33 | 33 | static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc); |
| 34 | 34 |
lib/tsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp+7-4| ... | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | |
| 13 | 13 | #include "sanitizer_allocator_internal.h" |
| 14 | 14 | #include "sanitizer_internal_defs.h" |
| 15 | #include "sanitizer_platform.h" | |
| 15 | 16 | #include "sanitizer_symbolizer_internal.h" |
| 16 | 17 | |
| 17 | 18 | namespace __sanitizer { |
| ... | ... | @@ -236,7 +237,7 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { |
| 236 | 237 | // <file_name>:<line_number>:<column_number> |
| 237 | 238 | // ... |
| 238 | 239 | // <empty line> |
| 239 | class LLVMSymbolizerProcess : public SymbolizerProcess { | |
| 240 | class LLVMSymbolizerProcess final : public SymbolizerProcess { | |
| 240 | 241 | public: |
| 241 | 242 | explicit LLVMSymbolizerProcess(const char *path) |
| 242 | 243 | : SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_MAC) {} |
| ... | ... | @@ -258,6 +259,8 @@ class LLVMSymbolizerProcess : public SymbolizerProcess { |
| 258 | 259 | const char* const kSymbolizerArch = "--default-arch=x86_64"; |
| 259 | 260 | #elif defined(__i386__) |
| 260 | 261 | const char* const kSymbolizerArch = "--default-arch=i386"; |
| 262 | #elif SANITIZER_RISCV64 | |
| 263 | const char *const kSymbolizerArch = "--default-arch=riscv64"; | |
| 261 | 264 | #elif defined(__aarch64__) |
| 262 | 265 | const char* const kSymbolizerArch = "--default-arch=arm64"; |
| 263 | 266 | #elif defined(__arm__) |
| ... | ... | @@ -275,8 +278,8 @@ class LLVMSymbolizerProcess : public SymbolizerProcess { |
| 275 | 278 | #endif |
| 276 | 279 | |
| 277 | 280 | const char *const inline_flag = common_flags()->symbolize_inline_frames |
| 278 | ? "--inlining=true" | |
| 279 | : "--inlining=false"; | |
| 281 | ? "--inlines" | |
| 282 | : "--no-inlines"; | |
| 280 | 283 | int i = 0; |
| 281 | 284 | argv[i++] = path_to_binary; |
| 282 | 285 | argv[i++] = inline_flag; |
| ... | ... | @@ -353,7 +356,7 @@ void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) { |
| 353 | 356 | InternalFree(info->function); |
| 354 | 357 | info->function = 0; |
| 355 | 358 | } |
| 356 | if (0 == internal_strcmp(info->file, "??")) { | |
| 359 | if (info->file && 0 == internal_strcmp(info->file, "??")) { | |
| 357 | 360 | InternalFree(info->file); |
| 358 | 361 | info->file = 0; |
| 359 | 362 | } |
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.cpp+14-7| ... | ... | @@ -33,8 +33,15 @@ bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { |
| 33 | 33 | int result = dladdr((const void *)addr, &info); |
| 34 | 34 | if (!result) return false; |
| 35 | 35 | |
| 36 | CHECK(addr >= reinterpret_cast<uptr>(info.dli_saddr)); | |
| 37 | stack->info.function_offset = addr - reinterpret_cast<uptr>(info.dli_saddr); | |
| 36 | // Compute offset if possible. `dladdr()` doesn't always ensure that `addr >= | |
| 37 | // sym_addr` so only compute the offset when this holds. Failure to find the | |
| 38 | // function offset is not treated as a failure because it might still be | |
| 39 | // possible to get the symbol name. | |
| 40 | uptr sym_addr = reinterpret_cast<uptr>(info.dli_saddr); | |
| 41 | if (addr >= sym_addr) { | |
| 42 | stack->info.function_offset = addr - sym_addr; | |
| 43 | } | |
| 44 | ||
| 38 | 45 | const char *demangled = DemangleSwiftAndCXX(info.dli_sname); |
| 39 | 46 | if (!demangled) return false; |
| 40 | 47 | stack->info.function = internal_strdup(demangled); |
| ... | ... | @@ -58,7 +65,7 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) { |
| 58 | 65 | // kAsanInternalHeapMagic. |
| 59 | 66 | static char kAtosMachPortEnvEntry[] = K_ATOS_ENV_VAR "=000000000000000"; |
| 60 | 67 | |
| 61 | class AtosSymbolizerProcess : public SymbolizerProcess { | |
| 68 | class AtosSymbolizerProcess final : public SymbolizerProcess { | |
| 62 | 69 | public: |
| 63 | 70 | explicit AtosSymbolizerProcess(const char *path) |
| 64 | 71 | : SymbolizerProcess(path, /*use_posix_spawn*/ true) { |
| ... | ... | @@ -219,10 +226,10 @@ bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { |
| 219 | 226 | start_address = reinterpret_cast<uptr>(info.dli_saddr); |
| 220 | 227 | } |
| 221 | 228 | |
| 222 | // Only assig to `function_offset` if we were able to get the function's | |
| 223 | // start address. | |
| 224 | if (start_address != AddressInfo::kUnknown) { | |
| 225 | CHECK(addr >= start_address); | |
| 229 | // Only assign to `function_offset` if we were able to get the function's | |
| 230 | // start address and we got a sensible `start_address` (dladdr doesn't always | |
| 231 | // ensure that `addr >= sym_addr`). | |
| 232 | if (start_address != AddressInfo::kUnknown && addr >= start_address) { | |
| 226 | 233 | stack->info.function_offset = addr - start_address; |
| 227 | 234 | } |
| 228 | 235 | return true; |
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.h+2-2| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | |
| 22 | 22 | namespace __sanitizer { |
| 23 | 23 | |
| 24 | class DlAddrSymbolizer : public SymbolizerTool { | |
| 24 | class DlAddrSymbolizer final : public SymbolizerTool { | |
| 25 | 25 | public: |
| 26 | 26 | bool SymbolizePC(uptr addr, SymbolizedStack *stack) override; |
| 27 | 27 | bool SymbolizeData(uptr addr, DataInfo *info) override; |
| ... | ... | @@ -29,7 +29,7 @@ class DlAddrSymbolizer : public SymbolizerTool { |
| 29 | 29 | |
| 30 | 30 | class AtosSymbolizerProcess; |
| 31 | 31 | |
| 32 | class AtosSymbolizer : public SymbolizerTool { | |
| 32 | class AtosSymbolizer final : public SymbolizerTool { | |
| 33 | 33 | public: |
| 34 | 34 | explicit AtosSymbolizer(const char *path, LowLevelAllocator *allocator); |
| 35 | 35 |
lib/tsan/sanitizer_common/sanitizer_symbolizer_markup.cpp+15-9| ... | ... | @@ -16,14 +16,13 @@ |
| 16 | 16 | |
| 17 | 17 | #if SANITIZER_FUCHSIA |
| 18 | 18 | #include "sanitizer_symbolizer_fuchsia.h" |
| 19 | #elif SANITIZER_RTEMS | |
| 20 | #include "sanitizer_symbolizer_rtems.h" | |
| 21 | #endif | |
| 22 | #include "sanitizer_stacktrace.h" | |
| 23 | #include "sanitizer_symbolizer.h" | |
| 19 | # endif | |
| 24 | 20 | |
| 25 | #include <limits.h> | |
| 26 | #include <unwind.h> | |
| 21 | # include <limits.h> | |
| 22 | # include <unwind.h> | |
| 23 | ||
| 24 | # include "sanitizer_stacktrace.h" | |
| 25 | # include "sanitizer_symbolizer.h" | |
| 27 | 26 | |
| 28 | 27 | namespace __sanitizer { |
| 29 | 28 | |
| ... | ... | @@ -54,6 +53,10 @@ bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, |
| 54 | 53 | return false; |
| 55 | 54 | } |
| 56 | 55 | |
| 56 | // This is mainly used by hwasan for online symbolization. This isn't needed | |
| 57 | // since hwasan can always just dump stack frames for offline symbolization. | |
| 58 | bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { return false; } | |
| 59 | ||
| 57 | 60 | // This is used in some places for suppression checking, which we |
| 58 | 61 | // don't really support for Fuchsia. It's also used in UBSan to |
| 59 | 62 | // identify a PC location to a function name, so we always fill in |
| ... | ... | @@ -83,11 +86,14 @@ void RenderData(InternalScopedString *buffer, const char *format, |
| 83 | 86 | buffer->append(kFormatData, DI->start); |
| 84 | 87 | } |
| 85 | 88 | |
| 89 | bool RenderNeedsSymbolization(const char *format) { return false; } | |
| 90 | ||
| 86 | 91 | // We don't support the stack_trace_format flag at all. |
| 87 | 92 | void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, |
| 88 | const AddressInfo &info, bool vs_style, | |
| 93 | uptr address, const AddressInfo *info, bool vs_style, | |
| 89 | 94 | const char *strip_path_prefix, const char *strip_func_prefix) { |
| 90 | buffer->append(kFormatFrame, frame_no, info.address); | |
| 95 | CHECK(!RenderNeedsSymbolization(format)); | |
| 96 | buffer->append(kFormatFrame, frame_no, address); | |
| 91 | 97 | } |
| 92 | 98 | |
| 93 | 99 | Symbolizer *Symbolizer::PlatformInit() { |
lib/tsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp+14-5| ... | ... | @@ -201,7 +201,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { |
| 201 | 201 | return true; |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | class Addr2LineProcess : public SymbolizerProcess { | |
| 204 | class Addr2LineProcess final : public SymbolizerProcess { | |
| 205 | 205 | public: |
| 206 | 206 | Addr2LineProcess(const char *path, const char *module_name) |
| 207 | 207 | : SymbolizerProcess(path), module_name_(internal_strdup(module_name)) {} |
| ... | ... | @@ -261,7 +261,7 @@ bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer, |
| 261 | 261 | output_terminator_, kTerminatorLen); |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | class Addr2LinePool : public SymbolizerTool { | |
| 264 | class Addr2LinePool final : public SymbolizerTool { | |
| 265 | 265 | public: |
| 266 | 266 | explicit Addr2LinePool(const char *addr2line_path, |
| 267 | 267 | LowLevelAllocator *allocator) |
| ... | ... | @@ -328,7 +328,7 @@ int __sanitizer_symbolize_demangle(const char *Name, char *Buffer, |
| 328 | 328 | int MaxLength); |
| 329 | 329 | } // extern "C" |
| 330 | 330 | |
| 331 | class InternalSymbolizer : public SymbolizerTool { | |
| 331 | class InternalSymbolizer final : public SymbolizerTool { | |
| 332 | 332 | public: |
| 333 | 333 | static InternalSymbolizer *get(LowLevelAllocator *alloc) { |
| 334 | 334 | if (__sanitizer_symbolize_code != 0 && |
| ... | ... | @@ -387,7 +387,7 @@ class InternalSymbolizer : public SymbolizerTool { |
| 387 | 387 | }; |
| 388 | 388 | #else // SANITIZER_SUPPORTS_WEAK_HOOKS |
| 389 | 389 | |
| 390 | class InternalSymbolizer : public SymbolizerTool { | |
| 390 | class InternalSymbolizer final : public SymbolizerTool { | |
| 391 | 391 | public: |
| 392 | 392 | static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; } |
| 393 | 393 | }; |
| ... | ... | @@ -400,11 +400,20 @@ const char *Symbolizer::PlatformDemangle(const char *name) { |
| 400 | 400 | |
| 401 | 401 | static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) { |
| 402 | 402 | const char *path = common_flags()->external_symbolizer_path; |
| 403 | ||
| 404 | if (path && internal_strchr(path, '%')) { | |
| 405 | char *new_path = (char *)InternalAlloc(kMaxPathLength); | |
| 406 | SubstituteForFlagValue(path, new_path, kMaxPathLength); | |
| 407 | path = new_path; | |
| 408 | } | |
| 409 | ||
| 403 | 410 | const char *binary_name = path ? StripModuleName(path) : ""; |
| 411 | static const char kLLVMSymbolizerPrefix[] = "llvm-symbolizer"; | |
| 404 | 412 | if (path && path[0] == '\0') { |
| 405 | 413 | VReport(2, "External symbolizer is explicitly disabled.\n"); |
| 406 | 414 | return nullptr; |
| 407 | } else if (!internal_strcmp(binary_name, "llvm-symbolizer")) { | |
| 415 | } else if (!internal_strncmp(binary_name, kLLVMSymbolizerPrefix, | |
| 416 | internal_strlen(kLLVMSymbolizerPrefix))) { | |
| 408 | 417 | VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path); |
| 409 | 418 | return new(*allocator) LLVMSymbolizer(path, allocator); |
| 410 | 419 | } else if (!internal_strcmp(binary_name, "atos")) { |
lib/tsan/sanitizer_common/sanitizer_symbolizer_report.cpp+17-18| ... | ... | @@ -31,9 +31,10 @@ namespace __sanitizer { |
| 31 | 31 | void ReportErrorSummary(const char *error_type, const AddressInfo &info, |
| 32 | 32 | const char *alt_tool_name) { |
| 33 | 33 | if (!common_flags()->print_summary) return; |
| 34 | InternalScopedString buff(kMaxSummaryLength); | |
| 34 | InternalScopedString buff; | |
| 35 | 35 | buff.append("%s ", error_type); |
| 36 | RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style, | |
| 36 | RenderFrame(&buff, "%L %F", 0, info.address, &info, | |
| 37 | common_flags()->symbolize_vs_style, | |
| 37 | 38 | common_flags()->strip_path_prefix); |
| 38 | 39 | ReportErrorSummary(buff.data(), alt_tool_name); |
| 39 | 40 | } |
| ... | ... | @@ -47,14 +48,14 @@ bool ReportFile::SupportsColors() { |
| 47 | 48 | return SupportsColoredOutput(fd); |
| 48 | 49 | } |
| 49 | 50 | |
| 50 | static INLINE bool ReportSupportsColors() { | |
| 51 | static inline bool ReportSupportsColors() { | |
| 51 | 52 | return report_file.SupportsColors(); |
| 52 | 53 | } |
| 53 | 54 | |
| 54 | 55 | #else // SANITIZER_FUCHSIA |
| 55 | 56 | |
| 56 | 57 | // Fuchsia's logs always go through post-processing that handles colorization. |
| 57 | static INLINE bool ReportSupportsColors() { return true; } | |
| 58 | static inline bool ReportSupportsColors() { return true; } | |
| 58 | 59 | |
| 59 | 60 | #endif // !SANITIZER_FUCHSIA |
| 60 | 61 | |
| ... | ... | @@ -119,7 +120,7 @@ void ReportMmapWriteExec(int prot) { |
| 119 | 120 | #endif |
| 120 | 121 | } |
| 121 | 122 | |
| 122 | #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS && !SANITIZER_GO | |
| 123 | #if !SANITIZER_FUCHSIA && !SANITIZER_GO | |
| 123 | 124 | void StartReportDeadlySignal() { |
| 124 | 125 | // Write the first message using fd=2, just in case. |
| 125 | 126 | // It may actually fail to write in case stderr is closed. |
| ... | ... | @@ -149,7 +150,7 @@ static void PrintMemoryByte(InternalScopedString *str, const char *before, |
| 149 | 150 | static void MaybeDumpInstructionBytes(uptr pc) { |
| 150 | 151 | if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) |
| 151 | 152 | return; |
| 152 | InternalScopedString str(1024); | |
| 153 | InternalScopedString str; | |
| 153 | 154 | str.append("First 16 instruction bytes at pc: "); |
| 154 | 155 | if (IsAccessibleMemoryRange(pc, 16)) { |
| 155 | 156 | for (int i = 0; i < 16; ++i) { |
| ... | ... | @@ -210,7 +211,7 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid, |
| 210 | 211 | Report("The signal is caused by a %s memory access.\n", access_type); |
| 211 | 212 | if (!sig.is_true_faulting_addr) |
| 212 | 213 | Report("Hint: this fault was caused by a dereference of a high value " |
| 213 | "address (see register values below). Dissassemble the provided " | |
| 214 | "address (see register values below). Disassemble the provided " | |
| 214 | 215 | "pc to learn which register was used.\n"); |
| 215 | 216 | else if (sig.addr < GetPageSizeCached()) |
| 216 | 217 | Report("Hint: address points to the zero page.\n"); |
| ... | ... | @@ -249,17 +250,17 @@ void HandleDeadlySignal(void *siginfo, void *context, u32 tid, |
| 249 | 250 | |
| 250 | 251 | #endif // !SANITIZER_FUCHSIA && !SANITIZER_GO |
| 251 | 252 | |
| 252 | static atomic_uintptr_t reporting_thread = {0}; | |
| 253 | static StaticSpinMutex CommonSanitizerReportMutex; | |
| 253 | atomic_uintptr_t ScopedErrorReportLock::reporting_thread_ = {0}; | |
| 254 | StaticSpinMutex ScopedErrorReportLock::mutex_; | |
| 254 | 255 | |
| 255 | ScopedErrorReportLock::ScopedErrorReportLock() { | |
| 256 | void ScopedErrorReportLock::Lock() { | |
| 256 | 257 | uptr current = GetThreadSelf(); |
| 257 | 258 | for (;;) { |
| 258 | 259 | uptr expected = 0; |
| 259 | if (atomic_compare_exchange_strong(&reporting_thread, &expected, current, | |
| 260 | if (atomic_compare_exchange_strong(&reporting_thread_, &expected, current, | |
| 260 | 261 | memory_order_relaxed)) { |
| 261 | 262 | // We've claimed reporting_thread so proceed. |
| 262 | CommonSanitizerReportMutex.Lock(); | |
| 263 | mutex_.Lock(); | |
| 263 | 264 | return; |
| 264 | 265 | } |
| 265 | 266 | |
| ... | ... | @@ -281,13 +282,11 @@ ScopedErrorReportLock::ScopedErrorReportLock() { |
| 281 | 282 | } |
| 282 | 283 | } |
| 283 | 284 | |
| 284 | ScopedErrorReportLock::~ScopedErrorReportLock() { | |
| 285 | CommonSanitizerReportMutex.Unlock(); | |
| 286 | atomic_store_relaxed(&reporting_thread, 0); | |
| 285 | void ScopedErrorReportLock::Unlock() { | |
| 286 | mutex_.Unlock(); | |
| 287 | atomic_store_relaxed(&reporting_thread_, 0); | |
| 287 | 288 | } |
| 288 | 289 | |
| 289 | void ScopedErrorReportLock::CheckLocked() { | |
| 290 | CommonSanitizerReportMutex.CheckLocked(); | |
| 291 | } | |
| 290 | void ScopedErrorReportLock::CheckLocked() { mutex_.CheckLocked(); } | |
| 292 | 291 | |
| 293 | 292 | } // namespace __sanitizer |
lib/tsan/sanitizer_common/sanitizer_symbolizer_rtems.h deleted-40| ... | ... | @@ -1,40 +0,0 @@ |
| 1 | //===-- sanitizer_symbolizer_rtems.h -----------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is shared between various sanitizers' runtime libraries. | |
| 10 | // | |
| 11 | // Define RTEMS's string formats and limits for the markup symbolizer. | |
| 12 | //===----------------------------------------------------------------------===// | |
| 13 | #ifndef SANITIZER_SYMBOLIZER_RTEMS_H | |
| 14 | #define SANITIZER_SYMBOLIZER_RTEMS_H | |
| 15 | ||
| 16 | #include "sanitizer_internal_defs.h" | |
| 17 | ||
| 18 | namespace __sanitizer { | |
| 19 | ||
| 20 | // The Myriad RTEMS symbolizer currently only parses backtrace lines, | |
| 21 | // so use a format that the symbolizer understands. For other | |
| 22 | // markups, keep them the same as the Fuchsia's. | |
| 23 | ||
| 24 | // This is used by UBSan for type names, and by ASan for global variable names. | |
| 25 | constexpr const char *kFormatDemangle = "{{{symbol:%s}}}"; | |
| 26 | constexpr uptr kFormatDemangleMax = 1024; // Arbitrary. | |
| 27 | ||
| 28 | // Function name or equivalent from PC location. | |
| 29 | constexpr const char *kFormatFunction = "{{{pc:%p}}}"; | |
| 30 | constexpr uptr kFormatFunctionMax = 64; // More than big enough for 64-bit hex. | |
| 31 | ||
| 32 | // Global variable name or equivalent from data memory address. | |
| 33 | constexpr const char *kFormatData = "{{{data:%p}}}"; | |
| 34 | ||
| 35 | // One frame in a backtrace (printed on a line by itself). | |
| 36 | constexpr const char *kFormatFrame = " [%u] IP: %p"; | |
| 37 | ||
| 38 | } // namespace __sanitizer | |
| 39 | ||
| 40 | #endif // SANITIZER_SYMBOLIZER_RTEMS_H |
lib/tsan/sanitizer_common/sanitizer_symbolizer_win.cpp+14-6| ... | ... | @@ -33,7 +33,7 @@ decltype(::UnDecorateSymbolName) *UnDecorateSymbolName; |
| 33 | 33 | |
| 34 | 34 | namespace { |
| 35 | 35 | |
| 36 | class WinSymbolizerTool : public SymbolizerTool { | |
| 36 | class WinSymbolizerTool final : public SymbolizerTool { | |
| 37 | 37 | public: |
| 38 | 38 | // The constructor is provided to avoid synthesized memsets. |
| 39 | 39 | WinSymbolizerTool() {} |
| ... | ... | @@ -136,9 +136,10 @@ void InitializeDbgHelpIfNeeded() { |
| 136 | 136 | bool WinSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *frame) { |
| 137 | 137 | InitializeDbgHelpIfNeeded(); |
| 138 | 138 | |
| 139 | // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx | |
| 140 | char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; | |
| 141 | PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; | |
| 139 | // See https://docs.microsoft.com/en-us/windows/win32/debug/retrieving-symbol-information-by-address | |
| 140 | InternalMmapVector<char> buffer(sizeof(SYMBOL_INFO) + | |
| 141 | MAX_SYM_NAME * sizeof(CHAR)); | |
| 142 | PSYMBOL_INFO symbol = (PSYMBOL_INFO)&buffer[0]; | |
| 142 | 143 | symbol->SizeOfStruct = sizeof(SYMBOL_INFO); |
| 143 | 144 | symbol->MaxNameLen = MAX_SYM_NAME; |
| 144 | 145 | DWORD64 offset = 0; |
| ... | ... | @@ -223,7 +224,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { |
| 223 | 224 | // Compute the command line. Wrap double quotes around everything. |
| 224 | 225 | const char *argv[kArgVMax]; |
| 225 | 226 | GetArgV(path_, argv); |
| 226 | InternalScopedString command_line(kMaxPathLength * 3); | |
| 227 | InternalScopedString command_line; | |
| 227 | 228 | for (int i = 0; argv[i]; i++) { |
| 228 | 229 | const char *arg = argv[i]; |
| 229 | 230 | int arglen = internal_strlen(arg); |
| ... | ... | @@ -281,8 +282,15 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list, |
| 281 | 282 | return; |
| 282 | 283 | } |
| 283 | 284 | |
| 284 | // Add llvm-symbolizer in case the binary has dwarf. | |
| 285 | // Add llvm-symbolizer. | |
| 285 | 286 | const char *user_path = common_flags()->external_symbolizer_path; |
| 287 | ||
| 288 | if (user_path && internal_strchr(user_path, '%')) { | |
| 289 | char *new_path = (char *)InternalAlloc(kMaxPathLength); | |
| 290 | SubstituteForFlagValue(user_path, new_path, kMaxPathLength); | |
| 291 | user_path = new_path; | |
| 292 | } | |
| 293 | ||
| 286 | 294 | const char *path = |
| 287 | 295 | user_path ? user_path : FindPathToBinary("llvm-symbolizer.exe"); |
| 288 | 296 | if (path) { |
lib/tsan/sanitizer_common/sanitizer_syscall_generic.inc+1-1| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | // NetBSD uses libc calls directly |
| 14 | 14 | #if !SANITIZER_NETBSD |
| 15 | 15 | |
| 16 | #if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
| 16 | #if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_SOLARIS | |
| 17 | 17 | # define SYSCALL(name) SYS_ ## name |
| 18 | 18 | #else |
| 19 | 19 | # define SYSCALL(name) __NR_ ## name |
lib/tsan/sanitizer_common/sanitizer_syscalls_netbsd.inc+113-6| ... | ... | @@ -42,8 +42,8 @@ |
| 42 | 42 | // DO NOT EDIT! THIS FILE HAS BEEN GENERATED! |
| 43 | 43 | // |
| 44 | 44 | // Generated with: generate_netbsd_syscalls.awk |
| 45 | // Generated date: 2019-12-24 | |
| 46 | // Generated from: syscalls.master,v 1.296 2019/09/22 22:59:39 christos Exp | |
| 45 | // Generated date: 2020-09-10 | |
| 46 | // Generated from: syscalls.master,v 1.306 2020/08/14 00:53:16 riastradh Exp | |
| 47 | 47 | // |
| 48 | 48 | //===----------------------------------------------------------------------===// |
| 49 | 49 | |
| ... | ... | @@ -872,7 +872,13 @@ PRE_SYSCALL(dup2)(long long from_, long long to_) { /* Nothing to do */ } |
| 872 | 872 | POST_SYSCALL(dup2)(long long res, long long from_, long long to_) { |
| 873 | 873 | /* Nothing to do */ |
| 874 | 874 | } |
| 875 | /* syscall 91 has been skipped */ | |
| 875 | PRE_SYSCALL(getrandom)(void *buf_, long long buflen_, long long flags_) { | |
| 876 | /* TODO */ | |
| 877 | } | |
| 878 | POST_SYSCALL(getrandom) | |
| 879 | (long long res, void *buf_, long long buflen_, long long flags_) { | |
| 880 | /* TODO */ | |
| 881 | } | |
| 876 | 882 | PRE_SYSCALL(fcntl)(long long fd_, long long cmd_, void *arg_) { |
| 877 | 883 | /* Nothing to do */ |
| 878 | 884 | } |
| ... | ... | @@ -1332,9 +1338,29 @@ PRE_SYSCALL(compat_09_ouname)(void *name_) { /* TODO */ } |
| 1332 | 1338 | POST_SYSCALL(compat_09_ouname)(long long res, void *name_) { /* TODO */ } |
| 1333 | 1339 | PRE_SYSCALL(sysarch)(long long op_, void *parms_) { /* TODO */ } |
| 1334 | 1340 | POST_SYSCALL(sysarch)(long long res, long long op_, void *parms_) { /* TODO */ } |
| 1335 | /* syscall 166 has been skipped */ | |
| 1336 | /* syscall 167 has been skipped */ | |
| 1337 | /* syscall 168 has been skipped */ | |
| 1341 | PRE_SYSCALL(__futex) | |
| 1342 | (void *uaddr_, long long op_, long long val_, void *timeout_, void *uaddr2_, | |
| 1343 | long long val2_, long long val3_) { | |
| 1344 | /* TODO */ | |
| 1345 | } | |
| 1346 | POST_SYSCALL(__futex) | |
| 1347 | (long long res, void *uaddr_, long long op_, long long val_, void *timeout_, | |
| 1348 | void *uaddr2_, long long val2_, long long val3_) { | |
| 1349 | /* TODO */ | |
| 1350 | } | |
| 1351 | PRE_SYSCALL(__futex_set_robust_list)(void *head_, long long len_) { /* TODO */ } | |
| 1352 | POST_SYSCALL(__futex_set_robust_list) | |
| 1353 | (long long res, void *head_, long long len_) { | |
| 1354 | /* TODO */ | |
| 1355 | } | |
| 1356 | PRE_SYSCALL(__futex_get_robust_list) | |
| 1357 | (long long lwpid_, void **headp_, void *lenp_) { | |
| 1358 | /* TODO */ | |
| 1359 | } | |
| 1360 | POST_SYSCALL(__futex_get_robust_list) | |
| 1361 | (long long res, long long lwpid_, void **headp_, void *lenp_) { | |
| 1362 | /* TODO */ | |
| 1363 | } | |
| 1338 | 1364 | #if !defined(_LP64) |
| 1339 | 1365 | PRE_SYSCALL(compat_10_osemsys) |
| 1340 | 1366 | (long long which_, long long a2_, long long a3_, long long a4_, long long a5_) { |
| ... | ... | @@ -3824,6 +3850,87 @@ PRE_SYSCALL(__fhstatvfs190) |
| 3824 | 3850 | } |
| 3825 | 3851 | POST_SYSCALL(__fhstatvfs190) |
| 3826 | 3852 | (long long res, void *fhp_, long long fh_size_, void *buf_, long long flags_) {} |
| 3853 | PRE_SYSCALL(__acl_get_link)(void *path_, long long type_, void *aclp_) { | |
| 3854 | /* TODO */ | |
| 3855 | } | |
| 3856 | POST_SYSCALL(__acl_get_link) | |
| 3857 | (long long res, void *path_, long long type_, void *aclp_) { | |
| 3858 | /* TODO */ | |
| 3859 | } | |
| 3860 | PRE_SYSCALL(__acl_set_link)(void *path_, long long type_, void *aclp_) { | |
| 3861 | /* TODO */ | |
| 3862 | } | |
| 3863 | POST_SYSCALL(__acl_set_link) | |
| 3864 | (long long res, void *path_, long long type_, void *aclp_) { | |
| 3865 | /* TODO */ | |
| 3866 | } | |
| 3867 | PRE_SYSCALL(__acl_delete_link)(void *path_, long long type_) { /* TODO */ } | |
| 3868 | POST_SYSCALL(__acl_delete_link)(long long res, void *path_, long long type_) { | |
| 3869 | /* TODO */ | |
| 3870 | } | |
| 3871 | PRE_SYSCALL(__acl_aclcheck_link)(void *path_, long long type_, void *aclp_) { | |
| 3872 | /* TODO */ | |
| 3873 | } | |
| 3874 | POST_SYSCALL(__acl_aclcheck_link) | |
| 3875 | (long long res, void *path_, long long type_, void *aclp_) { | |
| 3876 | /* TODO */ | |
| 3877 | } | |
| 3878 | PRE_SYSCALL(__acl_get_file)(void *path_, long long type_, void *aclp_) { | |
| 3879 | /* TODO */ | |
| 3880 | } | |
| 3881 | POST_SYSCALL(__acl_get_file) | |
| 3882 | (long long res, void *path_, long long type_, void *aclp_) { | |
| 3883 | /* TODO */ | |
| 3884 | } | |
| 3885 | PRE_SYSCALL(__acl_set_file)(void *path_, long long type_, void *aclp_) { | |
| 3886 | /* TODO */ | |
| 3887 | } | |
| 3888 | POST_SYSCALL(__acl_set_file) | |
| 3889 | (long long res, void *path_, long long type_, void *aclp_) { | |
| 3890 | /* TODO */ | |
| 3891 | } | |
| 3892 | PRE_SYSCALL(__acl_get_fd)(long long filedes_, long long type_, void *aclp_) { | |
| 3893 | /* TODO */ | |
| 3894 | } | |
| 3895 | POST_SYSCALL(__acl_get_fd) | |
| 3896 | (long long res, long long filedes_, long long type_, void *aclp_) { | |
| 3897 | /* TODO */ | |
| 3898 | } | |
| 3899 | PRE_SYSCALL(__acl_set_fd)(long long filedes_, long long type_, void *aclp_) { | |
| 3900 | /* TODO */ | |
| 3901 | } | |
| 3902 | POST_SYSCALL(__acl_set_fd) | |
| 3903 | (long long res, long long filedes_, long long type_, void *aclp_) { | |
| 3904 | /* TODO */ | |
| 3905 | } | |
| 3906 | PRE_SYSCALL(__acl_delete_file)(void *path_, long long type_) { /* TODO */ } | |
| 3907 | POST_SYSCALL(__acl_delete_file)(long long res, void *path_, long long type_) { | |
| 3908 | /* TODO */ | |
| 3909 | } | |
| 3910 | PRE_SYSCALL(__acl_delete_fd)(long long filedes_, long long type_) { /* TODO */ } | |
| 3911 | POST_SYSCALL(__acl_delete_fd) | |
| 3912 | (long long res, long long filedes_, long long type_) { | |
| 3913 | /* TODO */ | |
| 3914 | } | |
| 3915 | PRE_SYSCALL(__acl_aclcheck_file)(void *path_, long long type_, void *aclp_) { | |
| 3916 | /* TODO */ | |
| 3917 | } | |
| 3918 | POST_SYSCALL(__acl_aclcheck_file) | |
| 3919 | (long long res, void *path_, long long type_, void *aclp_) { | |
| 3920 | /* TODO */ | |
| 3921 | } | |
| 3922 | PRE_SYSCALL(__acl_aclcheck_fd) | |
| 3923 | (long long filedes_, long long type_, void *aclp_) { | |
| 3924 | /* TODO */ | |
| 3925 | } | |
| 3926 | POST_SYSCALL(__acl_aclcheck_fd) | |
| 3927 | (long long res, long long filedes_, long long type_, void *aclp_) { | |
| 3928 | /* TODO */ | |
| 3929 | } | |
| 3930 | PRE_SYSCALL(lpathconf)(void *path_, long long name_) { /* TODO */ } | |
| 3931 | POST_SYSCALL(lpathconf)(long long res, void *path_, long long name_) { | |
| 3932 | /* TODO */ | |
| 3933 | } | |
| 3827 | 3934 | #undef SYS_MAXSYSARGS |
| 3828 | 3935 | } // extern "C" |
| 3829 | 3936 |
lib/tsan/sanitizer_common/sanitizer_termination.cpp+19-14| ... | ... | @@ -59,26 +59,31 @@ void NORETURN Die() { |
| 59 | 59 | internal__exit(common_flags()->exitcode); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | static CheckFailedCallbackType CheckFailedCallback; | |
| 63 | void SetCheckFailedCallback(CheckFailedCallbackType callback) { | |
| 64 | CheckFailedCallback = callback; | |
| 62 | static void (*CheckUnwindCallback)(); | |
| 63 | void SetCheckUnwindCallback(void (*callback)()) { | |
| 64 | CheckUnwindCallback = callback; | |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | const int kSecondsToSleepWhenRecursiveCheckFailed = 2; | |
| 68 | ||
| 69 | 67 | void NORETURN CheckFailed(const char *file, int line, const char *cond, |
| 70 | 68 | u64 v1, u64 v2) { |
| 71 | static atomic_uint32_t num_calls; | |
| 72 | if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) > 10) { | |
| 73 | SleepForSeconds(kSecondsToSleepWhenRecursiveCheckFailed); | |
| 69 | u32 tid = GetTid(); | |
| 70 | Printf("%s: CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx) (tid=%u)\n", | |
| 71 | SanitizerToolName, StripModuleName(file), line, cond, (uptr)v1, | |
| 72 | (uptr)v2, tid); | |
| 73 | static atomic_uint32_t first_tid; | |
| 74 | u32 cmp = 0; | |
| 75 | if (!atomic_compare_exchange_strong(&first_tid, &cmp, tid, | |
| 76 | memory_order_relaxed)) { | |
| 77 | if (cmp == tid) { | |
| 78 | // Recursing into CheckFailed. | |
| 79 | } else { | |
| 80 | // Another thread fails already, let it print the stack and terminate. | |
| 81 | SleepForSeconds(2); | |
| 82 | } | |
| 74 | 83 | Trap(); |
| 75 | 84 | } |
| 76 | ||
| 77 | if (CheckFailedCallback) { | |
| 78 | CheckFailedCallback(file, line, cond, v1, v2); | |
| 79 | } | |
| 80 | Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond, | |
| 81 | v1, v2); | |
| 85 | if (CheckUnwindCallback) | |
| 86 | CheckUnwindCallback(); | |
| 82 | 87 | Die(); |
| 83 | 88 | } |
| 84 | 89 |
lib/tsan/sanitizer_common/sanitizer_thread_registry.cpp+18-23| ... | ... | @@ -85,7 +85,7 @@ void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id, |
| 85 | 85 | unique_id = _unique_id; |
| 86 | 86 | detached = _detached; |
| 87 | 87 | // Parent tid makes no sense for the main thread. |
| 88 | if (tid != 0) | |
| 88 | if (tid != kMainTid) | |
| 89 | 89 | parent_tid = _parent_tid; |
| 90 | 90 | OnCreated(arg); |
| 91 | 91 | } |
| ... | ... | @@ -99,7 +99,8 @@ void ThreadContextBase::Reset() { |
| 99 | 99 | |
| 100 | 100 | // ThreadRegistry implementation. |
| 101 | 101 | |
| 102 | const u32 ThreadRegistry::kUnknownTid = ~0U; | |
| 102 | ThreadRegistry::ThreadRegistry(ThreadContextFactory factory) | |
| 103 | : ThreadRegistry(factory, UINT32_MAX, UINT32_MAX, 0) {} | |
| 103 | 104 | |
| 104 | 105 | ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads, |
| 105 | 106 | u32 thread_quarantine_size, u32 max_reuse) |
| ... | ... | @@ -108,13 +109,10 @@ ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads, |
| 108 | 109 | thread_quarantine_size_(thread_quarantine_size), |
| 109 | 110 | max_reuse_(max_reuse), |
| 110 | 111 | mtx_(), |
| 111 | n_contexts_(0), | |
| 112 | 112 | total_threads_(0), |
| 113 | 113 | alive_threads_(0), |
| 114 | 114 | max_alive_threads_(0), |
| 115 | 115 | running_threads_(0) { |
| 116 | threads_ = (ThreadContextBase **)MmapOrDie(max_threads_ * sizeof(threads_[0]), | |
| 117 | "ThreadRegistry"); | |
| 118 | 116 | dead_threads_.clear(); |
| 119 | 117 | invalid_threads_.clear(); |
| 120 | 118 | } |
| ... | ... | @@ -122,7 +120,8 @@ ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads, |
| 122 | 120 | void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running, |
| 123 | 121 | uptr *alive) { |
| 124 | 122 | BlockingMutexLock l(&mtx_); |
| 125 | if (total) *total = n_contexts_; | |
| 123 | if (total) | |
| 124 | *total = threads_.size(); | |
| 126 | 125 | if (running) *running = running_threads_; |
| 127 | 126 | if (alive) *alive = alive_threads_; |
| 128 | 127 | } |
| ... | ... | @@ -135,15 +134,15 @@ uptr ThreadRegistry::GetMaxAliveThreads() { |
| 135 | 134 | u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, |
| 136 | 135 | void *arg) { |
| 137 | 136 | BlockingMutexLock l(&mtx_); |
| 138 | u32 tid = kUnknownTid; | |
| 137 | u32 tid = kInvalidTid; | |
| 139 | 138 | ThreadContextBase *tctx = QuarantinePop(); |
| 140 | 139 | if (tctx) { |
| 141 | 140 | tid = tctx->tid; |
| 142 | } else if (n_contexts_ < max_threads_) { | |
| 141 | } else if (threads_.size() < max_threads_) { | |
| 143 | 142 | // Allocate new thread context and tid. |
| 144 | tid = n_contexts_++; | |
| 143 | tid = threads_.size(); | |
| 145 | 144 | tctx = context_factory_(tid); |
| 146 | threads_[tid] = tctx; | |
| 145 | threads_.push_back(tctx); | |
| 147 | 146 | } else { |
| 148 | 147 | #if !SANITIZER_GO |
| 149 | 148 | Report("%s: Thread limit (%u threads) exceeded. Dying.\n", |
| ... | ... | @@ -155,7 +154,7 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, |
| 155 | 154 | Die(); |
| 156 | 155 | } |
| 157 | 156 | CHECK_NE(tctx, 0); |
| 158 | CHECK_NE(tid, kUnknownTid); | |
| 157 | CHECK_NE(tid, kInvalidTid); | |
| 159 | 158 | CHECK_LT(tid, max_threads_); |
| 160 | 159 | CHECK_EQ(tctx->status, ThreadStatusInvalid); |
| 161 | 160 | alive_threads_++; |
| ... | ... | @@ -171,7 +170,7 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, |
| 171 | 170 | void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb, |
| 172 | 171 | void *arg) { |
| 173 | 172 | CheckLocked(); |
| 174 | for (u32 tid = 0; tid < n_contexts_; tid++) { | |
| 173 | for (u32 tid = 0; tid < threads_.size(); tid++) { | |
| 175 | 174 | ThreadContextBase *tctx = threads_[tid]; |
| 176 | 175 | if (tctx == 0) |
| 177 | 176 | continue; |
| ... | ... | @@ -181,18 +180,18 @@ void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb, |
| 181 | 180 | |
| 182 | 181 | u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) { |
| 183 | 182 | BlockingMutexLock l(&mtx_); |
| 184 | for (u32 tid = 0; tid < n_contexts_; tid++) { | |
| 183 | for (u32 tid = 0; tid < threads_.size(); tid++) { | |
| 185 | 184 | ThreadContextBase *tctx = threads_[tid]; |
| 186 | 185 | if (tctx != 0 && cb(tctx, arg)) |
| 187 | 186 | return tctx->tid; |
| 188 | 187 | } |
| 189 | return kUnknownTid; | |
| 188 | return kInvalidTid; | |
| 190 | 189 | } |
| 191 | 190 | |
| 192 | 191 | ThreadContextBase * |
| 193 | 192 | ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) { |
| 194 | 193 | CheckLocked(); |
| 195 | for (u32 tid = 0; tid < n_contexts_; tid++) { | |
| 194 | for (u32 tid = 0; tid < threads_.size(); tid++) { | |
| 196 | 195 | ThreadContextBase *tctx = threads_[tid]; |
| 197 | 196 | if (tctx != 0 && cb(tctx, arg)) |
| 198 | 197 | return tctx; |
| ... | ... | @@ -213,7 +212,6 @@ ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) { |
| 213 | 212 | |
| 214 | 213 | void ThreadRegistry::SetThreadName(u32 tid, const char *name) { |
| 215 | 214 | BlockingMutexLock l(&mtx_); |
| 216 | CHECK_LT(tid, n_contexts_); | |
| 217 | 215 | ThreadContextBase *tctx = threads_[tid]; |
| 218 | 216 | CHECK_NE(tctx, 0); |
| 219 | 217 | CHECK_EQ(SANITIZER_FUCHSIA ? ThreadStatusCreated : ThreadStatusRunning, |
| ... | ... | @@ -223,7 +221,7 @@ void ThreadRegistry::SetThreadName(u32 tid, const char *name) { |
| 223 | 221 | |
| 224 | 222 | void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) { |
| 225 | 223 | BlockingMutexLock l(&mtx_); |
| 226 | for (u32 tid = 0; tid < n_contexts_; tid++) { | |
| 224 | for (u32 tid = 0; tid < threads_.size(); tid++) { | |
| 227 | 225 | ThreadContextBase *tctx = threads_[tid]; |
| 228 | 226 | if (tctx != 0 && tctx->user_id == user_id && |
| 229 | 227 | tctx->status != ThreadStatusInvalid) { |
| ... | ... | @@ -235,7 +233,6 @@ void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) { |
| 235 | 233 | |
| 236 | 234 | void ThreadRegistry::DetachThread(u32 tid, void *arg) { |
| 237 | 235 | BlockingMutexLock l(&mtx_); |
| 238 | CHECK_LT(tid, n_contexts_); | |
| 239 | 236 | ThreadContextBase *tctx = threads_[tid]; |
| 240 | 237 | CHECK_NE(tctx, 0); |
| 241 | 238 | if (tctx->status == ThreadStatusInvalid) { |
| ... | ... | @@ -256,7 +253,6 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) { |
| 256 | 253 | do { |
| 257 | 254 | { |
| 258 | 255 | BlockingMutexLock l(&mtx_); |
| 259 | CHECK_LT(tid, n_contexts_); | |
| 260 | 256 | ThreadContextBase *tctx = threads_[tid]; |
| 261 | 257 | CHECK_NE(tctx, 0); |
| 262 | 258 | if (tctx->status == ThreadStatusInvalid) { |
| ... | ... | @@ -278,14 +274,14 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) { |
| 278 | 274 | // really started. We just did CreateThread for a prospective new |
| 279 | 275 | // thread before trying to create it, and then failed to actually |
| 280 | 276 | // create it, and so never called StartThread. |
| 281 | void ThreadRegistry::FinishThread(u32 tid) { | |
| 277 | ThreadStatus ThreadRegistry::FinishThread(u32 tid) { | |
| 282 | 278 | BlockingMutexLock l(&mtx_); |
| 283 | 279 | CHECK_GT(alive_threads_, 0); |
| 284 | 280 | alive_threads_--; |
| 285 | CHECK_LT(tid, n_contexts_); | |
| 286 | 281 | ThreadContextBase *tctx = threads_[tid]; |
| 287 | 282 | CHECK_NE(tctx, 0); |
| 288 | 283 | bool dead = tctx->detached; |
| 284 | ThreadStatus prev_status = tctx->status; | |
| 289 | 285 | if (tctx->status == ThreadStatusRunning) { |
| 290 | 286 | CHECK_GT(running_threads_, 0); |
| 291 | 287 | running_threads_--; |
| ... | ... | @@ -300,13 +296,13 @@ void ThreadRegistry::FinishThread(u32 tid) { |
| 300 | 296 | QuarantinePush(tctx); |
| 301 | 297 | } |
| 302 | 298 | tctx->SetDestroyed(); |
| 299 | return prev_status; | |
| 303 | 300 | } |
| 304 | 301 | |
| 305 | 302 | void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type, |
| 306 | 303 | void *arg) { |
| 307 | 304 | BlockingMutexLock l(&mtx_); |
| 308 | 305 | running_threads_++; |
| 309 | CHECK_LT(tid, n_contexts_); | |
| 310 | 306 | ThreadContextBase *tctx = threads_[tid]; |
| 311 | 307 | CHECK_NE(tctx, 0); |
| 312 | 308 | CHECK_EQ(ThreadStatusCreated, tctx->status); |
| ... | ... | @@ -339,7 +335,6 @@ ThreadContextBase *ThreadRegistry::QuarantinePop() { |
| 339 | 335 | |
| 340 | 336 | void ThreadRegistry::SetThreadUserId(u32 tid, uptr user_id) { |
| 341 | 337 | BlockingMutexLock l(&mtx_); |
| 342 | CHECK_LT(tid, n_contexts_); | |
| 343 | 338 | ThreadContextBase *tctx = threads_[tid]; |
| 344 | 339 | CHECK_NE(tctx, 0); |
| 345 | 340 | CHECK_NE(tctx->status, ThreadStatusInvalid); |
lib/tsan/sanitizer_common/sanitizer_thread_registry.h+14-16| ... | ... | @@ -39,8 +39,6 @@ enum class ThreadType { |
| 39 | 39 | class ThreadContextBase { |
| 40 | 40 | public: |
| 41 | 41 | explicit ThreadContextBase(u32 tid); |
| 42 | ~ThreadContextBase(); // Should never be called. | |
| 43 | ||
| 44 | 42 | const u32 tid; // Thread ID. Main thread should have tid = 0. |
| 45 | 43 | u64 unique_id; // Unique thread ID. |
| 46 | 44 | u32 reuse_count; // Number of times this tid was reused. |
| ... | ... | @@ -80,28 +78,29 @@ class ThreadContextBase { |
| 80 | 78 | virtual void OnCreated(void *arg) {} |
| 81 | 79 | virtual void OnReset() {} |
| 82 | 80 | virtual void OnDetached(void *arg) {} |
| 81 | ||
| 82 | protected: | |
| 83 | ~ThreadContextBase(); | |
| 83 | 84 | }; |
| 84 | 85 | |
| 85 | 86 | typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid); |
| 86 | 87 | |
| 87 | class ThreadRegistry { | |
| 88 | class MUTEX ThreadRegistry { | |
| 88 | 89 | public: |
| 89 | static const u32 kUnknownTid; | |
| 90 | ||
| 90 | ThreadRegistry(ThreadContextFactory factory); | |
| 91 | 91 | ThreadRegistry(ThreadContextFactory factory, u32 max_threads, |
| 92 | u32 thread_quarantine_size, u32 max_reuse = 0); | |
| 92 | u32 thread_quarantine_size, u32 max_reuse); | |
| 93 | 93 | void GetNumberOfThreads(uptr *total = nullptr, uptr *running = nullptr, |
| 94 | 94 | uptr *alive = nullptr); |
| 95 | 95 | uptr GetMaxAliveThreads(); |
| 96 | 96 | |
| 97 | void Lock() { mtx_.Lock(); } | |
| 98 | void CheckLocked() { mtx_.CheckLocked(); } | |
| 99 | void Unlock() { mtx_.Unlock(); } | |
| 97 | void Lock() ACQUIRE() { mtx_.Lock(); } | |
| 98 | void CheckLocked() const CHECK_LOCKED() { mtx_.CheckLocked(); } | |
| 99 | void Unlock() RELEASE() { mtx_.Unlock(); } | |
| 100 | 100 | |
| 101 | 101 | // Should be guarded by ThreadRegistryLock. |
| 102 | 102 | ThreadContextBase *GetThreadLocked(u32 tid) { |
| 103 | DCHECK_LT(tid, n_contexts_); | |
| 104 | return threads_[tid]; | |
| 103 | return threads_.empty() ? nullptr : threads_[tid]; | |
| 105 | 104 | } |
| 106 | 105 | |
| 107 | 106 | u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg); |
| ... | ... | @@ -112,7 +111,7 @@ class ThreadRegistry { |
| 112 | 111 | void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg); |
| 113 | 112 | |
| 114 | 113 | typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg); |
| 115 | // Finds a thread using the provided callback. Returns kUnknownTid if no | |
| 114 | // Finds a thread using the provided callback. Returns kInvalidTid if no | |
| 116 | 115 | // thread is found. |
| 117 | 116 | u32 FindThread(FindThreadCallback cb, void *arg); |
| 118 | 117 | // Should be guarded by ThreadRegistryLock. Return 0 if no thread |
| ... | ... | @@ -125,7 +124,8 @@ class ThreadRegistry { |
| 125 | 124 | void SetThreadNameByUserId(uptr user_id, const char *name); |
| 126 | 125 | void DetachThread(u32 tid, void *arg); |
| 127 | 126 | void JoinThread(u32 tid, void *arg); |
| 128 | void FinishThread(u32 tid); | |
| 127 | // Finishes thread and returns previous status. | |
| 128 | ThreadStatus FinishThread(u32 tid); | |
| 129 | 129 | void StartThread(u32 tid, tid_t os_id, ThreadType thread_type, void *arg); |
| 130 | 130 | void SetThreadUserId(u32 tid, uptr user_id); |
| 131 | 131 | |
| ... | ... | @@ -137,15 +137,13 @@ class ThreadRegistry { |
| 137 | 137 | |
| 138 | 138 | BlockingMutex mtx_; |
| 139 | 139 | |
| 140 | u32 n_contexts_; // Number of created thread contexts, | |
| 141 | // at most max_threads_. | |
| 142 | 140 | u64 total_threads_; // Total number of created threads. May be greater than |
| 143 | 141 | // max_threads_ if contexts were reused. |
| 144 | 142 | uptr alive_threads_; // Created or running. |
| 145 | 143 | uptr max_alive_threads_; |
| 146 | 144 | uptr running_threads_; |
| 147 | 145 | |
| 148 | ThreadContextBase **threads_; // Array of thread contexts is leaked. | |
| 146 | InternalMmapVector<ThreadContextBase *> threads_; | |
| 149 | 147 | IntrusiveList<ThreadContextBase> dead_threads_; |
| 150 | 148 | IntrusiveList<ThreadContextBase> invalid_threads_; |
| 151 | 149 |
lib/tsan/sanitizer_common/sanitizer_thread_safety.h created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | //===-- sanitizer_thread_safety.h -------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is shared between sanitizer tools. | |
| 10 | // | |
| 11 | // Wrappers around thread safety annotations. | |
| 12 | // https://clang.llvm.org/docs/ThreadSafetyAnalysis.html | |
| 13 | //===----------------------------------------------------------------------===// | |
| 14 | ||
| 15 | #ifndef SANITIZER_THREAD_SAFETY_H | |
| 16 | #define SANITIZER_THREAD_SAFETY_H | |
| 17 | ||
| 18 | #if defined(__clang__) | |
| 19 | # define THREAD_ANNOTATION(x) __attribute__((x)) | |
| 20 | #else | |
| 21 | # define THREAD_ANNOTATION(x) | |
| 22 | #endif | |
| 23 | ||
| 24 | #define MUTEX THREAD_ANNOTATION(capability("mutex")) | |
| 25 | #define SCOPED_LOCK THREAD_ANNOTATION(scoped_lockable) | |
| 26 | #define GUARDED_BY(x) THREAD_ANNOTATION(guarded_by(x)) | |
| 27 | #define PT_GUARDED_BY(x) THREAD_ANNOTATION(pt_guarded_by(x)) | |
| 28 | #define REQUIRES(...) THREAD_ANNOTATION(requires_capability(__VA_ARGS__)) | |
| 29 | #define REQUIRES_SHARED(...) \ | |
| 30 | THREAD_ANNOTATION(requires_shared_capability(__VA_ARGS__)) | |
| 31 | #define ACQUIRE(...) THREAD_ANNOTATION(acquire_capability(__VA_ARGS__)) | |
| 32 | #define ACQUIRE_SHARED(...) \ | |
| 33 | THREAD_ANNOTATION(acquire_shared_capability(__VA_ARGS__)) | |
| 34 | #define TRY_ACQUIRE(...) THREAD_ANNOTATION(try_acquire_capability(__VA_ARGS__)) | |
| 35 | #define RELEASE(...) THREAD_ANNOTATION(release_capability(__VA_ARGS__)) | |
| 36 | #define RELEASE_SHARED(...) \ | |
| 37 | THREAD_ANNOTATION(release_shared_capability(__VA_ARGS__)) | |
| 38 | #define EXCLUDES(...) THREAD_ANNOTATION(locks_excluded(__VA_ARGS__)) | |
| 39 | #define CHECK_LOCKED(...) THREAD_ANNOTATION(assert_capability(__VA_ARGS__)) | |
| 40 | #define NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION(no_thread_safety_analysis) | |
| 41 | ||
| 42 | #endif |
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.cpp+54-32| ... | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | |
| 13 | 13 | #include "sanitizer_tls_get_addr.h" |
| 14 | 14 | |
| 15 | #include "sanitizer_atomic.h" | |
| 15 | 16 | #include "sanitizer_flags.h" |
| 16 | 17 | #include "sanitizer_platform_interceptors.h" |
| 17 | 18 | |
| ... | ... | @@ -42,46 +43,66 @@ static atomic_uintptr_t number_of_live_dtls; |
| 42 | 43 | |
| 43 | 44 | static const uptr kDestroyedThread = -1; |
| 44 | 45 | |
| 45 | static inline void DTLS_Deallocate(DTLS::DTV *dtv, uptr size) { | |
| 46 | if (!size) return; | |
| 47 | VReport(2, "__tls_get_addr: DTLS_Deallocate %p %zd\n", dtv, size); | |
| 48 | UnmapOrDie(dtv, size * sizeof(DTLS::DTV)); | |
| 46 | static void DTLS_Deallocate(DTLS::DTVBlock *block) { | |
| 47 | VReport(2, "__tls_get_addr: DTLS_Deallocate %p %zd\n", block); | |
| 48 | UnmapOrDie(block, sizeof(DTLS::DTVBlock)); | |
| 49 | 49 | atomic_fetch_sub(&number_of_live_dtls, 1, memory_order_relaxed); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | static inline void DTLS_Resize(uptr new_size) { | |
| 53 | if (dtls.dtv_size >= new_size) return; | |
| 54 | new_size = RoundUpToPowerOfTwo(new_size); | |
| 55 | new_size = Max(new_size, 4096UL / sizeof(DTLS::DTV)); | |
| 56 | DTLS::DTV *new_dtv = | |
| 57 | (DTLS::DTV *)MmapOrDie(new_size * sizeof(DTLS::DTV), "DTLS_Resize"); | |
| 52 | static DTLS::DTVBlock *DTLS_NextBlock(atomic_uintptr_t *cur) { | |
| 53 | uptr v = atomic_load(cur, memory_order_acquire); | |
| 54 | if (v == kDestroyedThread) | |
| 55 | return nullptr; | |
| 56 | DTLS::DTVBlock *next = (DTLS::DTVBlock *)v; | |
| 57 | if (next) | |
| 58 | return next; | |
| 59 | DTLS::DTVBlock *new_dtv = | |
| 60 | (DTLS::DTVBlock *)MmapOrDie(sizeof(DTLS::DTVBlock), "DTLS_NextBlock"); | |
| 61 | uptr prev = 0; | |
| 62 | if (!atomic_compare_exchange_strong(cur, &prev, (uptr)new_dtv, | |
| 63 | memory_order_seq_cst)) { | |
| 64 | UnmapOrDie(new_dtv, sizeof(DTLS::DTVBlock)); | |
| 65 | return (DTLS::DTVBlock *)prev; | |
| 66 | } | |
| 58 | 67 | uptr num_live_dtls = |
| 59 | 68 | atomic_fetch_add(&number_of_live_dtls, 1, memory_order_relaxed); |
| 60 | VReport(2, "__tls_get_addr: DTLS_Resize %p %zd\n", &dtls, num_live_dtls); | |
| 61 | CHECK_LT(num_live_dtls, 1 << 20); | |
| 62 | uptr old_dtv_size = dtls.dtv_size; | |
| 63 | DTLS::DTV *old_dtv = dtls.dtv; | |
| 64 | if (old_dtv_size) | |
| 65 | internal_memcpy(new_dtv, dtls.dtv, dtls.dtv_size * sizeof(DTLS::DTV)); | |
| 66 | dtls.dtv = new_dtv; | |
| 67 | dtls.dtv_size = new_size; | |
| 68 | if (old_dtv_size) | |
| 69 | DTLS_Deallocate(old_dtv, old_dtv_size); | |
| 69 | VReport(2, "__tls_get_addr: DTLS_NextBlock %p %zd\n", &dtls, num_live_dtls); | |
| 70 | return new_dtv; | |
| 71 | } | |
| 72 | ||
| 73 | static DTLS::DTV *DTLS_Find(uptr id) { | |
| 74 | VReport(2, "__tls_get_addr: DTLS_Find %p %zd\n", &dtls, id); | |
| 75 | static constexpr uptr kPerBlock = ARRAY_SIZE(DTLS::DTVBlock::dtvs); | |
| 76 | DTLS::DTVBlock *cur = DTLS_NextBlock(&dtls.dtv_block); | |
| 77 | if (!cur) | |
| 78 | return nullptr; | |
| 79 | for (; id >= kPerBlock; id -= kPerBlock) cur = DTLS_NextBlock(&cur->next); | |
| 80 | return cur->dtvs + id; | |
| 70 | 81 | } |
| 71 | 82 | |
| 72 | 83 | void DTLS_Destroy() { |
| 73 | 84 | if (!common_flags()->intercept_tls_get_addr) return; |
| 74 | VReport(2, "__tls_get_addr: DTLS_Destroy %p %zd\n", &dtls, dtls.dtv_size); | |
| 75 | uptr s = dtls.dtv_size; | |
| 76 | dtls.dtv_size = kDestroyedThread; // Do this before unmap for AS-safety. | |
| 77 | DTLS_Deallocate(dtls.dtv, s); | |
| 85 | VReport(2, "__tls_get_addr: DTLS_Destroy %p\n", &dtls); | |
| 86 | DTLS::DTVBlock *block = (DTLS::DTVBlock *)atomic_exchange( | |
| 87 | &dtls.dtv_block, kDestroyedThread, memory_order_release); | |
| 88 | while (block) { | |
| 89 | DTLS::DTVBlock *next = | |
| 90 | (DTLS::DTVBlock *)atomic_load(&block->next, memory_order_acquire); | |
| 91 | DTLS_Deallocate(block); | |
| 92 | block = next; | |
| 93 | } | |
| 78 | 94 | } |
| 79 | 95 | |
| 80 | 96 | #if defined(__powerpc64__) || defined(__mips__) |
| 81 | 97 | // This is glibc's TLS_DTV_OFFSET: |
| 82 | 98 | // "Dynamic thread vector pointers point 0x8000 past the start of each |
| 83 | // TLS block." | |
| 99 | // TLS block." (sysdeps/<arch>/dl-tls.h) | |
| 84 | 100 | static const uptr kDtvOffset = 0x8000; |
| 101 | #elif defined(__riscv) | |
| 102 | // This is glibc's TLS_DTV_OFFSET: | |
| 103 | // "Dynamic thread vector pointers point 0x800 past the start of each | |
| 104 | // TLS block." (sysdeps/riscv/dl-tls.h) | |
| 105 | static const uptr kDtvOffset = 0x800; | |
| 85 | 106 | #else |
| 86 | 107 | static const uptr kDtvOffset = 0; |
| 87 | 108 | #endif |
| ... | ... | @@ -91,9 +112,9 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res, |
| 91 | 112 | if (!common_flags()->intercept_tls_get_addr) return 0; |
| 92 | 113 | TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void); |
| 93 | 114 | uptr dso_id = arg->dso_id; |
| 94 | if (dtls.dtv_size == kDestroyedThread) return 0; | |
| 95 | DTLS_Resize(dso_id + 1); | |
| 96 | if (dtls.dtv[dso_id].beg) return 0; | |
| 115 | DTLS::DTV *dtv = DTLS_Find(dso_id); | |
| 116 | if (!dtv || dtv->beg) | |
| 117 | return 0; | |
| 97 | 118 | uptr tls_size = 0; |
| 98 | 119 | uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset; |
| 99 | 120 | VReport(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p " |
| ... | ... | @@ -121,9 +142,9 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res, |
| 121 | 142 | // This may happen inside the DTOR of main thread, so just ignore it. |
| 122 | 143 | tls_size = 0; |
| 123 | 144 | } |
| 124 | dtls.dtv[dso_id].beg = tls_beg; | |
| 125 | dtls.dtv[dso_id].size = tls_size; | |
| 126 | return dtls.dtv + dso_id; | |
| 145 | dtv->beg = tls_beg; | |
| 146 | dtv->size = tls_size; | |
| 147 | return dtv; | |
| 127 | 148 | } |
| 128 | 149 | |
| 129 | 150 | void DTLS_on_libc_memalign(void *ptr, uptr size) { |
| ... | ... | @@ -136,7 +157,8 @@ void DTLS_on_libc_memalign(void *ptr, uptr size) { |
| 136 | 157 | DTLS *DTLS_Get() { return &dtls; } |
| 137 | 158 | |
| 138 | 159 | bool DTLSInDestruction(DTLS *dtls) { |
| 139 | return dtls->dtv_size == kDestroyedThread; | |
| 160 | return atomic_load(&dtls->dtv_block, memory_order_relaxed) == | |
| 161 | kDestroyedThread; | |
| 140 | 162 | } |
| 141 | 163 | |
| 142 | 164 | #else |
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.h+19-2| ... | ... | @@ -28,6 +28,7 @@ |
| 28 | 28 | #ifndef SANITIZER_TLS_GET_ADDR_H |
| 29 | 29 | #define SANITIZER_TLS_GET_ADDR_H |
| 30 | 30 | |
| 31 | #include "sanitizer_atomic.h" | |
| 31 | 32 | #include "sanitizer_common.h" |
| 32 | 33 | |
| 33 | 34 | namespace __sanitizer { |
| ... | ... | @@ -38,15 +39,31 @@ struct DTLS { |
| 38 | 39 | struct DTV { |
| 39 | 40 | uptr beg, size; |
| 40 | 41 | }; |
| 42 | struct DTVBlock { | |
| 43 | atomic_uintptr_t next; | |
| 44 | DTV dtvs[(4096UL - sizeof(next)) / sizeof(DTLS::DTV)]; | |
| 45 | }; | |
| 46 | ||
| 47 | static_assert(sizeof(DTVBlock) <= 4096UL, "Unexpected block size"); | |
| 41 | 48 | |
| 42 | uptr dtv_size; | |
| 43 | DTV *dtv; // dtv_size elements, allocated by MmapOrDie. | |
| 49 | atomic_uintptr_t dtv_block; | |
| 44 | 50 | |
| 45 | 51 | // Auxiliary fields, don't access them outside sanitizer_tls_get_addr.cpp |
| 46 | 52 | uptr last_memalign_size; |
| 47 | 53 | uptr last_memalign_ptr; |
| 48 | 54 | }; |
| 49 | 55 | |
| 56 | template <typename Fn> | |
| 57 | void ForEachDVT(DTLS *dtls, const Fn &fn) { | |
| 58 | DTLS::DTVBlock *block = | |
| 59 | (DTLS::DTVBlock *)atomic_load(&dtls->dtv_block, memory_order_acquire); | |
| 60 | while (block) { | |
| 61 | int id = 0; | |
| 62 | for (auto &d : block->dtvs) fn(d, id++); | |
| 63 | block = (DTLS::DTVBlock *)atomic_load(&block->next, memory_order_acquire); | |
| 64 | } | |
| 65 | } | |
| 66 | ||
| 50 | 67 | // Returns pointer and size of a linker-allocated TLS block. |
| 51 | 68 | // Each block is returned exactly once. |
| 52 | 69 | DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res, uptr static_tls_begin, |
lib/tsan/sanitizer_common/sanitizer_unwind_win.cpp+11| ... | ... | @@ -37,8 +37,16 @@ void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { |
| 37 | 37 | // Skip the RTL frames by searching for the PC in the stacktrace. |
| 38 | 38 | uptr pc_location = LocatePcInTrace(pc); |
| 39 | 39 | PopStackFrames(pc_location); |
| 40 | ||
| 41 | // Replace the first frame with the PC because the frame in the | |
| 42 | // stacktrace might be incorrect. | |
| 43 | trace_buffer[0] = pc; | |
| 40 | 44 | } |
| 41 | 45 | |
| 46 | #ifdef __clang__ | |
| 47 | #pragma clang diagnostic push | |
| 48 | #pragma clang diagnostic ignored "-Wframe-larger-than=" | |
| 49 | #endif | |
| 42 | 50 | void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { |
| 43 | 51 | CHECK(context); |
| 44 | 52 | CHECK_GE(max_depth, 2); |
| ... | ... | @@ -70,6 +78,9 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { |
| 70 | 78 | trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; |
| 71 | 79 | } |
| 72 | 80 | } |
| 81 | #ifdef __clang__ | |
| 82 | #pragma clang diagnostic pop | |
| 83 | #endif | |
| 73 | 84 | #endif // #if !SANITIZER_GO |
| 74 | 85 | |
| 75 | 86 | #endif // SANITIZER_WINDOWS |
lib/tsan/sanitizer_common/sanitizer_win.cpp+91-39| ... | ... | @@ -44,6 +44,9 @@ TRACELOGGING_DEFINE_PROVIDER(g_asan_provider, "AddressSanitizerLoggingProvider", |
| 44 | 44 | #define TraceLoggingUnregister(x) |
| 45 | 45 | #endif |
| 46 | 46 | |
| 47 | // For WaitOnAddress | |
| 48 | # pragma comment(lib, "synchronization.lib") | |
| 49 | ||
| 47 | 50 | // A macro to tell the compiler that this part of the code cannot be reached, |
| 48 | 51 | // if the compiler supports this feature. Since we're using this in |
| 49 | 52 | // code that is called when terminating the process, the expansion of the |
| ... | ... | @@ -334,8 +337,12 @@ bool MprotectNoAccess(uptr addr, uptr size) { |
| 334 | 337 | } |
| 335 | 338 | |
| 336 | 339 | void ReleaseMemoryPagesToOS(uptr beg, uptr end) { |
| 337 | // This is almost useless on 32-bits. | |
| 338 | // FIXME: add madvise-analog when we move to 64-bits. | |
| 340 | uptr beg_aligned = RoundDownTo(beg, GetPageSizeCached()), | |
| 341 | end_aligned = RoundDownTo(end, GetPageSizeCached()); | |
| 342 | CHECK(beg < end); // make sure the region is sane | |
| 343 | if (beg_aligned == end_aligned) // make sure we're freeing at least 1 page; | |
| 344 | return; | |
| 345 | UnmapOrDie((void *)beg, end_aligned - beg_aligned); | |
| 339 | 346 | } |
| 340 | 347 | |
| 341 | 348 | void SetShadowRegionHugePageMode(uptr addr, uptr size) { |
| ... | ... | @@ -348,6 +355,22 @@ bool DontDumpShadowMemory(uptr addr, uptr length) { |
| 348 | 355 | return true; |
| 349 | 356 | } |
| 350 | 357 | |
| 358 | uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale, | |
| 359 | uptr min_shadow_base_alignment, | |
| 360 | UNUSED uptr &high_mem_end) { | |
| 361 | const uptr granularity = GetMmapGranularity(); | |
| 362 | const uptr alignment = | |
| 363 | Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment); | |
| 364 | const uptr left_padding = | |
| 365 | Max<uptr>(granularity, 1ULL << min_shadow_base_alignment); | |
| 366 | uptr space_size = shadow_size_bytes + left_padding; | |
| 367 | uptr shadow_start = FindAvailableMemoryRange(space_size, alignment, | |
| 368 | granularity, nullptr, nullptr); | |
| 369 | CHECK_NE((uptr)0, shadow_start); | |
| 370 | CHECK(IsAligned(shadow_start, alignment)); | |
| 371 | return shadow_start; | |
| 372 | } | |
| 373 | ||
| 351 | 374 | uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, |
| 352 | 375 | uptr *largest_gap_found, |
| 353 | 376 | uptr *max_occupied_addr) { |
| ... | ... | @@ -370,6 +393,12 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, |
| 370 | 393 | return 0; |
| 371 | 394 | } |
| 372 | 395 | |
| 396 | uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size, | |
| 397 | uptr num_aliases, uptr ring_buffer_size) { | |
| 398 | CHECK(false && "HWASan aliasing is unimplemented on Windows"); | |
| 399 | return 0; | |
| 400 | } | |
| 401 | ||
| 373 | 402 | bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { |
| 374 | 403 | MEMORY_BASIC_INFORMATION mbi; |
| 375 | 404 | CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi))); |
| ... | ... | @@ -475,8 +504,6 @@ void DumpProcessMap() { |
| 475 | 504 | } |
| 476 | 505 | #endif |
| 477 | 506 | |
| 478 | void PrintModuleMap() { } | |
| 479 | ||
| 480 | 507 | void DisableCoreDumperIfNecessary() { |
| 481 | 508 | // Do nothing. |
| 482 | 509 | } |
| ... | ... | @@ -517,13 +544,7 @@ bool IsAbsolutePath(const char *path) { |
| 517 | 544 | IsPathSeparator(path[2]); |
| 518 | 545 | } |
| 519 | 546 | |
| 520 | void SleepForSeconds(int seconds) { | |
| 521 | Sleep(seconds * 1000); | |
| 522 | } | |
| 523 | ||
| 524 | void SleepForMillis(int millis) { | |
| 525 | Sleep(millis); | |
| 526 | } | |
| 547 | void internal_usleep(u64 useconds) { Sleep(useconds / 1000); } | |
| 527 | 548 | |
| 528 | 549 | u64 NanoTime() { |
| 529 | 550 | static LARGE_INTEGER frequency = {}; |
| ... | ... | @@ -550,7 +571,7 @@ void Abort() { |
| 550 | 571 | // load the image at this address. Therefore, we call it the preferred base. Any |
| 551 | 572 | // addresses in the DWARF typically assume that the object has been loaded at |
| 552 | 573 | // this address. |
| 553 | static uptr GetPreferredBase(const char *modname) { | |
| 574 | static uptr GetPreferredBase(const char *modname, char *buf, size_t buf_size) { | |
| 554 | 575 | fd_t fd = OpenFile(modname, RdOnly, nullptr); |
| 555 | 576 | if (fd == kInvalidFd) |
| 556 | 577 | return 0; |
| ... | ... | @@ -572,12 +593,10 @@ static uptr GetPreferredBase(const char *modname) { |
| 572 | 593 | // IMAGE_FILE_HEADER |
| 573 | 594 | // IMAGE_OPTIONAL_HEADER |
| 574 | 595 | // Seek to e_lfanew and read all that data. |
| 575 | char buf[4 + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER)]; | |
| 576 | 596 | if (::SetFilePointer(fd, dos_header.e_lfanew, nullptr, FILE_BEGIN) == |
| 577 | 597 | INVALID_SET_FILE_POINTER) |
| 578 | 598 | return 0; |
| 579 | if (!ReadFromFile(fd, &buf[0], sizeof(buf), &bytes_read) || | |
| 580 | bytes_read != sizeof(buf)) | |
| 599 | if (!ReadFromFile(fd, buf, buf_size, &bytes_read) || bytes_read != buf_size) | |
| 581 | 600 | return 0; |
| 582 | 601 | |
| 583 | 602 | // Check for "PE\0\0" before the PE header. |
| ... | ... | @@ -619,6 +638,10 @@ void ListOfModules::init() { |
| 619 | 638 | } |
| 620 | 639 | } |
| 621 | 640 | |
| 641 | InternalMmapVector<char> buf(4 + sizeof(IMAGE_FILE_HEADER) + | |
| 642 | sizeof(IMAGE_OPTIONAL_HEADER)); | |
| 643 | InternalMmapVector<wchar_t> modname_utf16(kMaxPathLength); | |
| 644 | InternalMmapVector<char> module_name(kMaxPathLength); | |
| 622 | 645 | // |num_modules| is the number of modules actually present, |
| 623 | 646 | size_t num_modules = bytes_required / sizeof(HMODULE); |
| 624 | 647 | for (size_t i = 0; i < num_modules; ++i) { |
| ... | ... | @@ -628,15 +651,13 @@ void ListOfModules::init() { |
| 628 | 651 | continue; |
| 629 | 652 | |
| 630 | 653 | // Get the UTF-16 path and convert to UTF-8. |
| 631 | wchar_t modname_utf16[kMaxPathLength]; | |
| 632 | 654 | int modname_utf16_len = |
| 633 | GetModuleFileNameW(handle, modname_utf16, kMaxPathLength); | |
| 655 | GetModuleFileNameW(handle, &modname_utf16[0], kMaxPathLength); | |
| 634 | 656 | if (modname_utf16_len == 0) |
| 635 | 657 | modname_utf16[0] = '\0'; |
| 636 | char module_name[kMaxPathLength]; | |
| 637 | int module_name_len = | |
| 638 | ::WideCharToMultiByte(CP_UTF8, 0, modname_utf16, modname_utf16_len + 1, | |
| 639 | &module_name[0], kMaxPathLength, NULL, NULL); | |
| 658 | int module_name_len = ::WideCharToMultiByte( | |
| 659 | CP_UTF8, 0, &modname_utf16[0], modname_utf16_len + 1, &module_name[0], | |
| 660 | kMaxPathLength, NULL, NULL); | |
| 640 | 661 | module_name[module_name_len] = '\0'; |
| 641 | 662 | |
| 642 | 663 | uptr base_address = (uptr)mi.lpBaseOfDll; |
| ... | ... | @@ -646,15 +667,16 @@ void ListOfModules::init() { |
| 646 | 667 | // RVA when computing the module offset. This helps llvm-symbolizer find the |
| 647 | 668 | // right DWARF CU. In the common case that the image is loaded at it's |
| 648 | 669 | // preferred address, we will now print normal virtual addresses. |
| 649 | uptr preferred_base = GetPreferredBase(&module_name[0]); | |
| 670 | uptr preferred_base = | |
| 671 | GetPreferredBase(&module_name[0], &buf[0], buf.size()); | |
| 650 | 672 | uptr adjusted_base = base_address - preferred_base; |
| 651 | 673 | |
| 652 | LoadedModule cur_module; | |
| 653 | cur_module.set(module_name, adjusted_base); | |
| 674 | modules_.push_back(LoadedModule()); | |
| 675 | LoadedModule &cur_module = modules_.back(); | |
| 676 | cur_module.set(&module_name[0], adjusted_base); | |
| 654 | 677 | // We add the whole module as one single address range. |
| 655 | 678 | cur_module.addAddressRange(base_address, end_address, /*executable*/ true, |
| 656 | 679 | /*writable*/ true); |
| 657 | modules_.push_back(cur_module); | |
| 658 | 680 | } |
| 659 | 681 | UnmapOrDie(hmodules, modules_buffer_size); |
| 660 | 682 | } |
| ... | ... | @@ -794,6 +816,17 @@ uptr GetRSS() { |
| 794 | 816 | void *internal_start_thread(void *(*func)(void *arg), void *arg) { return 0; } |
| 795 | 817 | void internal_join_thread(void *th) { } |
| 796 | 818 | |
| 819 | void FutexWait(atomic_uint32_t *p, u32 cmp) { | |
| 820 | WaitOnAddress(p, &cmp, sizeof(cmp), INFINITE); | |
| 821 | } | |
| 822 | ||
| 823 | void FutexWake(atomic_uint32_t *p, u32 count) { | |
| 824 | if (count == 1) | |
| 825 | WakeByAddressSingle(p); | |
| 826 | else | |
| 827 | WakeByAddressAll(p); | |
| 828 | } | |
| 829 | ||
| 797 | 830 | // ---------------------- BlockingMutex ---------------- {{{1 |
| 798 | 831 | |
| 799 | 832 | BlockingMutex::BlockingMutex() { |
| ... | ... | @@ -813,9 +846,7 @@ void BlockingMutex::Unlock() { |
| 813 | 846 | ReleaseSRWLockExclusive((PSRWLOCK)opaque_storage_); |
| 814 | 847 | } |
| 815 | 848 | |
| 816 | void BlockingMutex::CheckLocked() { | |
| 817 | CHECK_EQ(owner_, GetThreadSelf()); | |
| 818 | } | |
| 849 | void BlockingMutex::CheckLocked() const { CHECK_EQ(owner_, GetThreadSelf()); } | |
| 819 | 850 | |
| 820 | 851 | uptr GetTlsSize() { |
| 821 | 852 | return 0; |
| ... | ... | @@ -942,22 +973,27 @@ void SignalContext::InitPcSpBp() { |
| 942 | 973 | |
| 943 | 974 | uptr SignalContext::GetAddress() const { |
| 944 | 975 | EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; |
| 945 | return exception_record->ExceptionInformation[1]; | |
| 976 | if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) | |
| 977 | return exception_record->ExceptionInformation[1]; | |
| 978 | return (uptr)exception_record->ExceptionAddress; | |
| 946 | 979 | } |
| 947 | 980 | |
| 948 | 981 | bool SignalContext::IsMemoryAccess() const { |
| 949 | return GetWriteFlag() != SignalContext::UNKNOWN; | |
| 982 | return ((EXCEPTION_RECORD *)siginfo)->ExceptionCode == | |
| 983 | EXCEPTION_ACCESS_VIOLATION; | |
| 950 | 984 | } |
| 951 | 985 | |
| 952 | bool SignalContext::IsTrueFaultingAddress() const { | |
| 953 | // FIXME: Provide real implementation for this. See Linux and Mac variants. | |
| 954 | return IsMemoryAccess(); | |
| 955 | } | |
| 986 | bool SignalContext::IsTrueFaultingAddress() const { return true; } | |
| 956 | 987 | |
| 957 | 988 | SignalContext::WriteFlag SignalContext::GetWriteFlag() const { |
| 958 | 989 | EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; |
| 990 | ||
| 991 | // The write flag is only available for access violation exceptions. | |
| 992 | if (exception_record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) | |
| 993 | return SignalContext::UNKNOWN; | |
| 994 | ||
| 959 | 995 | // The contents of this array are documented at |
| 960 | // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx | |
| 996 | // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record | |
| 961 | 997 | // The first element indicates read as 0, write as 1, or execute as 8. The |
| 962 | 998 | // second element is the faulting address. |
| 963 | 999 | switch (exception_record->ExceptionInformation[0]) { |
| ... | ... | @@ -1023,10 +1059,24 @@ const char *SignalContext::Describe() const { |
| 1023 | 1059 | } |
| 1024 | 1060 | |
| 1025 | 1061 | uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { |
| 1026 | // FIXME: Actually implement this function. | |
| 1027 | CHECK_GT(buf_len, 0); | |
| 1028 | buf[0] = 0; | |
| 1029 | return 0; | |
| 1062 | if (buf_len == 0) | |
| 1063 | return 0; | |
| 1064 | ||
| 1065 | // Get the UTF-16 path and convert to UTF-8. | |
| 1066 | InternalMmapVector<wchar_t> binname_utf16(kMaxPathLength); | |
| 1067 | int binname_utf16_len = | |
| 1068 | GetModuleFileNameW(NULL, &binname_utf16[0], kMaxPathLength); | |
| 1069 | if (binname_utf16_len == 0) { | |
| 1070 | buf[0] = '\0'; | |
| 1071 | return 0; | |
| 1072 | } | |
| 1073 | int binary_name_len = | |
| 1074 | ::WideCharToMultiByte(CP_UTF8, 0, &binname_utf16[0], binname_utf16_len, | |
| 1075 | buf, buf_len, NULL, NULL); | |
| 1076 | if ((unsigned)binary_name_len == buf_len) | |
| 1077 | --binary_name_len; | |
| 1078 | buf[binary_name_len] = '\0'; | |
| 1079 | return binary_name_len; | |
| 1030 | 1080 | } |
| 1031 | 1081 | |
| 1032 | 1082 | uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) { |
| ... | ... | @@ -1124,6 +1174,8 @@ void LogFullErrorReport(const char *buffer) { |
| 1124 | 1174 | } |
| 1125 | 1175 | #endif // SANITIZER_WIN_TRACE |
| 1126 | 1176 | |
| 1177 | void InitializePlatformCommonFlags(CommonFlags *cf) {} | |
| 1178 | ||
| 1127 | 1179 | } // namespace __sanitizer |
| 1128 | 1180 | |
| 1129 | 1181 | #endif // _WIN32 |
lib/tsan/tsan_clock.cpp+18-48| ... | ... | @@ -80,14 +80,6 @@ |
| 80 | 80 | // release-store operation by the thread with release_store_tid_ index. |
| 81 | 81 | // release_store_reused_ - reuse count of release_store_tid_. |
| 82 | 82 | |
| 83 | // We don't have ThreadState in these methods, so this is an ugly hack that | |
| 84 | // works only in C++. | |
| 85 | #if !SANITIZER_GO | |
| 86 | # define CPP_STAT_INC(typ) StatInc(cur_thread(), typ) | |
| 87 | #else | |
| 88 | # define CPP_STAT_INC(typ) (void)0 | |
| 89 | #endif | |
| 90 | ||
| 91 | 83 | namespace __tsan { |
| 92 | 84 | |
| 93 | 85 | static atomic_uint32_t *ref_ptr(ClockBlock *cb) { |
| ... | ... | @@ -138,19 +130,16 @@ void ThreadClock::ResetCached(ClockCache *c) { |
| 138 | 130 | void ThreadClock::acquire(ClockCache *c, SyncClock *src) { |
| 139 | 131 | DCHECK_LE(nclk_, kMaxTid); |
| 140 | 132 | DCHECK_LE(src->size_, kMaxTid); |
| 141 | CPP_STAT_INC(StatClockAcquire); | |
| 142 | 133 | |
| 143 | 134 | // Check if it's empty -> no need to do anything. |
| 144 | 135 | const uptr nclk = src->size_; |
| 145 | if (nclk == 0) { | |
| 146 | CPP_STAT_INC(StatClockAcquireEmpty); | |
| 136 | if (nclk == 0) | |
| 147 | 137 | return; |
| 148 | } | |
| 149 | 138 | |
| 150 | 139 | bool acquired = false; |
| 151 | 140 | for (unsigned i = 0; i < kDirtyTids; i++) { |
| 152 | 141 | SyncClock::Dirty dirty = src->dirty_[i]; |
| 153 | unsigned tid = dirty.tid; | |
| 142 | unsigned tid = dirty.tid(); | |
| 154 | 143 | if (tid != kInvalidTid) { |
| 155 | 144 | if (clk_[tid] < dirty.epoch) { |
| 156 | 145 | clk_[tid] = dirty.epoch; |
| ... | ... | @@ -162,7 +151,6 @@ void ThreadClock::acquire(ClockCache *c, SyncClock *src) { |
| 162 | 151 | // Check if we've already acquired src after the last release operation on src |
| 163 | 152 | if (tid_ >= nclk || src->elem(tid_).reused != reused_) { |
| 164 | 153 | // O(N) acquire. |
| 165 | CPP_STAT_INC(StatClockAcquireFull); | |
| 166 | 154 | nclk_ = max(nclk_, nclk); |
| 167 | 155 | u64 *dst_pos = &clk_[0]; |
| 168 | 156 | for (ClockElem &src_elem : *src) { |
| ... | ... | @@ -180,7 +168,6 @@ void ThreadClock::acquire(ClockCache *c, SyncClock *src) { |
| 180 | 168 | } |
| 181 | 169 | |
| 182 | 170 | if (acquired) { |
| 183 | CPP_STAT_INC(StatClockAcquiredSomething); | |
| 184 | 171 | last_acquire_ = clk_[tid_]; |
| 185 | 172 | ResetCached(c); |
| 186 | 173 | } |
| ... | ... | @@ -223,7 +210,6 @@ void ThreadClock::releaseStoreAcquire(ClockCache *c, SyncClock *sc) { |
| 223 | 210 | sc->release_store_reused_ = 0; |
| 224 | 211 | |
| 225 | 212 | if (acquired) { |
| 226 | CPP_STAT_INC(StatClockAcquiredSomething); | |
| 227 | 213 | last_acquire_ = clk_[tid_]; |
| 228 | 214 | ResetCached(c); |
| 229 | 215 | } |
| ... | ... | @@ -240,7 +226,6 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { |
| 240 | 226 | return; |
| 241 | 227 | } |
| 242 | 228 | |
| 243 | CPP_STAT_INC(StatClockRelease); | |
| 244 | 229 | // Check if we need to resize dst. |
| 245 | 230 | if (dst->size_ < nclk_) |
| 246 | 231 | dst->Resize(c, nclk_); |
| ... | ... | @@ -257,12 +242,9 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { |
| 257 | 242 | } |
| 258 | 243 | |
| 259 | 244 | // O(N) release. |
| 260 | CPP_STAT_INC(StatClockReleaseFull); | |
| 261 | 245 | dst->Unshare(c); |
| 262 | 246 | // First, remember whether we've acquired dst. |
| 263 | 247 | bool acquired = IsAlreadyAcquired(dst); |
| 264 | if (acquired) | |
| 265 | CPP_STAT_INC(StatClockReleaseAcquired); | |
| 266 | 248 | // Update dst->clk_. |
| 267 | 249 | dst->FlushDirty(); |
| 268 | 250 | uptr i = 0; |
| ... | ... | @@ -272,8 +254,6 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { |
| 272 | 254 | i++; |
| 273 | 255 | } |
| 274 | 256 | // Clear 'acquired' flag in the remaining elements. |
| 275 | if (nclk_ < dst->size_) | |
| 276 | CPP_STAT_INC(StatClockReleaseClearTail); | |
| 277 | 257 | dst->release_store_tid_ = kInvalidTid; |
| 278 | 258 | dst->release_store_reused_ = 0; |
| 279 | 259 | // If we've acquired dst, remember this fact, |
| ... | ... | @@ -285,7 +265,6 @@ void ThreadClock::release(ClockCache *c, SyncClock *dst) { |
| 285 | 265 | void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { |
| 286 | 266 | DCHECK_LE(nclk_, kMaxTid); |
| 287 | 267 | DCHECK_LE(dst->size_, kMaxTid); |
| 288 | CPP_STAT_INC(StatClockStore); | |
| 289 | 268 | |
| 290 | 269 | if (dst->size_ == 0 && cached_idx_ != 0) { |
| 291 | 270 | // Reuse the cached clock. |
| ... | ... | @@ -299,10 +278,10 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { |
| 299 | 278 | dst->tab_idx_ = cached_idx_; |
| 300 | 279 | dst->size_ = cached_size_; |
| 301 | 280 | dst->blocks_ = cached_blocks_; |
| 302 | CHECK_EQ(dst->dirty_[0].tid, kInvalidTid); | |
| 281 | CHECK_EQ(dst->dirty_[0].tid(), kInvalidTid); | |
| 303 | 282 | // The cached clock is shared (immutable), |
| 304 | 283 | // so this is where we store the current clock. |
| 305 | dst->dirty_[0].tid = tid_; | |
| 284 | dst->dirty_[0].set_tid(tid_); | |
| 306 | 285 | dst->dirty_[0].epoch = clk_[tid_]; |
| 307 | 286 | dst->release_store_tid_ = tid_; |
| 308 | 287 | dst->release_store_reused_ = reused_; |
| ... | ... | @@ -320,13 +299,11 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { |
| 320 | 299 | if (dst->release_store_tid_ == tid_ && |
| 321 | 300 | dst->release_store_reused_ == reused_ && |
| 322 | 301 | !HasAcquiredAfterRelease(dst)) { |
| 323 | CPP_STAT_INC(StatClockStoreFast); | |
| 324 | 302 | UpdateCurrentThread(c, dst); |
| 325 | 303 | return; |
| 326 | 304 | } |
| 327 | 305 | |
| 328 | 306 | // O(N) release-store. |
| 329 | CPP_STAT_INC(StatClockStoreFull); | |
| 330 | 307 | dst->Unshare(c); |
| 331 | 308 | // Note: dst can be larger than this ThreadClock. |
| 332 | 309 | // This is fine since clk_ beyond size is all zeros. |
| ... | ... | @@ -336,8 +313,7 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { |
| 336 | 313 | ce.reused = 0; |
| 337 | 314 | i++; |
| 338 | 315 | } |
| 339 | for (uptr i = 0; i < kDirtyTids; i++) | |
| 340 | dst->dirty_[i].tid = kInvalidTid; | |
| 316 | for (uptr i = 0; i < kDirtyTids; i++) dst->dirty_[i].set_tid(kInvalidTid); | |
| 341 | 317 | dst->release_store_tid_ = tid_; |
| 342 | 318 | dst->release_store_reused_ = reused_; |
| 343 | 319 | // Rememeber that we don't need to acquire it in future. |
| ... | ... | @@ -359,7 +335,6 @@ void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) { |
| 359 | 335 | } |
| 360 | 336 | |
| 361 | 337 | void ThreadClock::acq_rel(ClockCache *c, SyncClock *dst) { |
| 362 | CPP_STAT_INC(StatClockAcquireRelease); | |
| 363 | 338 | acquire(c, dst); |
| 364 | 339 | ReleaseStore(c, dst); |
| 365 | 340 | } |
| ... | ... | @@ -369,10 +344,9 @@ void ThreadClock::UpdateCurrentThread(ClockCache *c, SyncClock *dst) const { |
| 369 | 344 | // Update the threads time, but preserve 'acquired' flag. |
| 370 | 345 | for (unsigned i = 0; i < kDirtyTids; i++) { |
| 371 | 346 | SyncClock::Dirty *dirty = &dst->dirty_[i]; |
| 372 | const unsigned tid = dirty->tid; | |
| 347 | const unsigned tid = dirty->tid(); | |
| 373 | 348 | if (tid == tid_ || tid == kInvalidTid) { |
| 374 | CPP_STAT_INC(StatClockReleaseFast); | |
| 375 | dirty->tid = tid_; | |
| 349 | dirty->set_tid(tid_); | |
| 376 | 350 | dirty->epoch = clk_[tid_]; |
| 377 | 351 | return; |
| 378 | 352 | } |
| ... | ... | @@ -380,7 +354,6 @@ void ThreadClock::UpdateCurrentThread(ClockCache *c, SyncClock *dst) const { |
| 380 | 354 | // Reset all 'acquired' flags, O(N). |
| 381 | 355 | // We are going to touch dst elements, so we need to unshare it. |
| 382 | 356 | dst->Unshare(c); |
| 383 | CPP_STAT_INC(StatClockReleaseSlow); | |
| 384 | 357 | dst->elem(tid_).epoch = clk_[tid_]; |
| 385 | 358 | for (uptr i = 0; i < dst->size_; i++) |
| 386 | 359 | dst->elem(i).reused = 0; |
| ... | ... | @@ -393,8 +366,8 @@ bool ThreadClock::IsAlreadyAcquired(const SyncClock *src) const { |
| 393 | 366 | return false; |
| 394 | 367 | for (unsigned i = 0; i < kDirtyTids; i++) { |
| 395 | 368 | SyncClock::Dirty dirty = src->dirty_[i]; |
| 396 | if (dirty.tid != kInvalidTid) { | |
| 397 | if (clk_[dirty.tid] < dirty.epoch) | |
| 369 | if (dirty.tid() != kInvalidTid) { | |
| 370 | if (clk_[dirty.tid()] < dirty.epoch) | |
| 398 | 371 | return false; |
| 399 | 372 | } |
| 400 | 373 | } |
| ... | ... | @@ -453,12 +426,10 @@ void SyncClock::ResetImpl() { |
| 453 | 426 | blocks_ = 0; |
| 454 | 427 | release_store_tid_ = kInvalidTid; |
| 455 | 428 | release_store_reused_ = 0; |
| 456 | for (uptr i = 0; i < kDirtyTids; i++) | |
| 457 | dirty_[i].tid = kInvalidTid; | |
| 429 | for (uptr i = 0; i < kDirtyTids; i++) dirty_[i].set_tid(kInvalidTid); | |
| 458 | 430 | } |
| 459 | 431 | |
| 460 | 432 | void SyncClock::Resize(ClockCache *c, uptr nclk) { |
| 461 | CPP_STAT_INC(StatClockReleaseResize); | |
| 462 | 433 | Unshare(c); |
| 463 | 434 | if (nclk <= capacity()) { |
| 464 | 435 | // Memory is already allocated, just increase the size. |
| ... | ... | @@ -503,10 +474,10 @@ void SyncClock::Resize(ClockCache *c, uptr nclk) { |
| 503 | 474 | void SyncClock::FlushDirty() { |
| 504 | 475 | for (unsigned i = 0; i < kDirtyTids; i++) { |
| 505 | 476 | Dirty *dirty = &dirty_[i]; |
| 506 | if (dirty->tid != kInvalidTid) { | |
| 507 | CHECK_LT(dirty->tid, size_); | |
| 508 | elem(dirty->tid).epoch = dirty->epoch; | |
| 509 | dirty->tid = kInvalidTid; | |
| 477 | if (dirty->tid() != kInvalidTid) { | |
| 478 | CHECK_LT(dirty->tid(), size_); | |
| 479 | elem(dirty->tid()).epoch = dirty->epoch; | |
| 480 | dirty->set_tid(kInvalidTid); | |
| 510 | 481 | } |
| 511 | 482 | } |
| 512 | 483 | } |
| ... | ... | @@ -559,7 +530,7 @@ ALWAYS_INLINE bool SyncClock::Cachable() const { |
| 559 | 530 | if (size_ == 0) |
| 560 | 531 | return false; |
| 561 | 532 | for (unsigned i = 0; i < kDirtyTids; i++) { |
| 562 | if (dirty_[i].tid != kInvalidTid) | |
| 533 | if (dirty_[i].tid() != kInvalidTid) | |
| 563 | 534 | return false; |
| 564 | 535 | } |
| 565 | 536 | return atomic_load_relaxed(ref_ptr(tab_)) == 1; |
| ... | ... | @@ -606,7 +577,7 @@ ALWAYS_INLINE void SyncClock::append_block(u32 idx) { |
| 606 | 577 | u64 SyncClock::get(unsigned tid) const { |
| 607 | 578 | for (unsigned i = 0; i < kDirtyTids; i++) { |
| 608 | 579 | Dirty dirty = dirty_[i]; |
| 609 | if (dirty.tid == tid) | |
| 580 | if (dirty.tid() == tid) | |
| 610 | 581 | return dirty.epoch; |
| 611 | 582 | } |
| 612 | 583 | return elem(tid).epoch; |
| ... | ... | @@ -625,9 +596,8 @@ void SyncClock::DebugDump(int(*printf)(const char *s, ...)) { |
| 625 | 596 | for (uptr i = 0; i < size_; i++) |
| 626 | 597 | printf("%s%llu", i == 0 ? "" : ",", elem(i).reused); |
| 627 | 598 | printf("] release_store_tid=%d/%d dirty_tids=%d[%llu]/%d[%llu]", |
| 628 | release_store_tid_, release_store_reused_, | |
| 629 | dirty_[0].tid, dirty_[0].epoch, | |
| 630 | dirty_[1].tid, dirty_[1].epoch); | |
| 599 | release_store_tid_, release_store_reused_, dirty_[0].tid(), | |
| 600 | dirty_[0].epoch, dirty_[1].tid(), dirty_[1].epoch); | |
| 631 | 601 | } |
| 632 | 602 | |
| 633 | 603 | void SyncClock::Iter::Next() { |
lib/tsan/tsan_clock.h+13-3| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | |
| 18 | 18 | namespace __tsan { |
| 19 | 19 | |
| 20 | typedef DenseSlabAlloc<ClockBlock, 1<<16, 1<<10> ClockAlloc; | |
| 20 | typedef DenseSlabAlloc<ClockBlock, 1 << 22, 1 << 10> ClockAlloc; | |
| 21 | 21 | typedef DenseSlabAllocCache ClockCache; |
| 22 | 22 | |
| 23 | 23 | // The clock that lives in sync variables (mutexes, atomics, etc). |
| ... | ... | @@ -65,10 +65,20 @@ class SyncClock { |
| 65 | 65 | static const uptr kDirtyTids = 2; |
| 66 | 66 | |
| 67 | 67 | struct Dirty { |
| 68 | u64 epoch : kClkBits; | |
| 69 | u64 tid : 64 - kClkBits; // kInvalidId if not active | |
| 68 | u32 tid() const { return tid_ == kShortInvalidTid ? kInvalidTid : tid_; } | |
| 69 | void set_tid(u32 tid) { | |
| 70 | tid_ = tid == kInvalidTid ? kShortInvalidTid : tid; | |
| 71 | } | |
| 72 | u64 epoch : kClkBits; | |
| 73 | ||
| 74 | private: | |
| 75 | // Full kInvalidTid won't fit into Dirty::tid. | |
| 76 | static const u64 kShortInvalidTid = (1ull << (64 - kClkBits)) - 1; | |
| 77 | u64 tid_ : 64 - kClkBits; // kInvalidId if not active | |
| 70 | 78 | }; |
| 71 | 79 | |
| 80 | static_assert(sizeof(Dirty) == 8, "Dirty is not 64bit"); | |
| 81 | ||
| 72 | 82 | unsigned release_store_tid_; |
| 73 | 83 | unsigned release_store_reused_; |
| 74 | 84 | Dirty dirty_[kDirtyTids]; |
lib/tsan/tsan_defs.h+12-18| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | |
| 16 | 16 | #include "sanitizer_common/sanitizer_internal_defs.h" |
| 17 | 17 | #include "sanitizer_common/sanitizer_libc.h" |
| 18 | #include "tsan_stat.h" | |
| 18 | #include "sanitizer_common/sanitizer_mutex.h" | |
| 19 | 19 | #include "ubsan/ubsan_platform.h" |
| 20 | 20 | |
| 21 | 21 | // Setup defaults for compile definitions. |
| ... | ... | @@ -23,10 +23,6 @@ |
| 23 | 23 | # define TSAN_NO_HISTORY 0 |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | #ifndef TSAN_COLLECT_STATS | |
| 27 | # define TSAN_COLLECT_STATS 0 | |
| 28 | #endif | |
| 29 | ||
| 30 | 26 | #ifndef TSAN_CONTAINS_UBSAN |
| 31 | 27 | # if CAN_SANITIZE_UB && !SANITIZER_GO |
| 32 | 28 | # define TSAN_CONTAINS_UBSAN 1 |
| ... | ... | @@ -98,8 +94,6 @@ const bool kCollectHistory = false; |
| 98 | 94 | const bool kCollectHistory = true; |
| 99 | 95 | #endif |
| 100 | 96 | |
| 101 | const u16 kInvalidTid = kMaxTid + 1; | |
| 102 | ||
| 103 | 97 | // The following "build consistency" machinery ensures that all source files |
| 104 | 98 | // are built in the same configuration. Inconsistent builds lead to |
| 105 | 99 | // hard to debug crashes. |
| ... | ... | @@ -109,23 +103,12 @@ void build_consistency_debug(); |
| 109 | 103 | void build_consistency_release(); |
| 110 | 104 | #endif |
| 111 | 105 | |
| 112 | #if TSAN_COLLECT_STATS | |
| 113 | void build_consistency_stats(); | |
| 114 | #else | |
| 115 | void build_consistency_nostats(); | |
| 116 | #endif | |
| 117 | ||
| 118 | 106 | static inline void USED build_consistency() { |
| 119 | 107 | #if SANITIZER_DEBUG |
| 120 | 108 | build_consistency_debug(); |
| 121 | 109 | #else |
| 122 | 110 | build_consistency_release(); |
| 123 | 111 | #endif |
| 124 | #if TSAN_COLLECT_STATS | |
| 125 | build_consistency_stats(); | |
| 126 | #else | |
| 127 | build_consistency_nostats(); | |
| 128 | #endif | |
| 129 | 112 | } |
| 130 | 113 | |
| 131 | 114 | template<typename T> |
| ... | ... | @@ -190,6 +173,17 @@ enum ExternalTag : uptr { |
| 190 | 173 | // as 16-bit values, see tsan_defs.h. |
| 191 | 174 | }; |
| 192 | 175 | |
| 176 | enum MutexType { | |
| 177 | MutexTypeTrace = MutexLastCommon, | |
| 178 | MutexTypeReport, | |
| 179 | MutexTypeSyncVar, | |
| 180 | MutexTypeAnnotations, | |
| 181 | MutexTypeAtExit, | |
| 182 | MutexTypeFired, | |
| 183 | MutexTypeRacy, | |
| 184 | MutexTypeGlobalProc, | |
| 185 | }; | |
| 186 | ||
| 193 | 187 | } // namespace __tsan |
| 194 | 188 | |
| 195 | 189 | #endif // TSAN_DEFS_H |
lib/tsan/tsan_dense_alloc.h+22-11| ... | ... | @@ -20,7 +20,6 @@ |
| 20 | 20 | |
| 21 | 21 | #include "sanitizer_common/sanitizer_common.h" |
| 22 | 22 | #include "tsan_defs.h" |
| 23 | #include "tsan_mutex.h" | |
| 24 | 23 | |
| 25 | 24 | namespace __tsan { |
| 26 | 25 | |
| ... | ... | @@ -29,28 +28,40 @@ class DenseSlabAllocCache { |
| 29 | 28 | typedef u32 IndexT; |
| 30 | 29 | uptr pos; |
| 31 | 30 | IndexT cache[kSize]; |
| 32 | template<typename T, uptr kL1Size, uptr kL2Size> friend class DenseSlabAlloc; | |
| 31 | template <typename, uptr, uptr, u64> | |
| 32 | friend class DenseSlabAlloc; | |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | template<typename T, uptr kL1Size, uptr kL2Size> | |
| 35 | template <typename T, uptr kL1Size, uptr kL2Size, u64 kReserved = 0> | |
| 36 | 36 | class DenseSlabAlloc { |
| 37 | 37 | public: |
| 38 | 38 | typedef DenseSlabAllocCache Cache; |
| 39 | 39 | typedef typename Cache::IndexT IndexT; |
| 40 | 40 | |
| 41 | explicit DenseSlabAlloc(const char *name) { | |
| 42 | // Check that kL1Size and kL2Size are sane. | |
| 43 | CHECK_EQ(kL1Size & (kL1Size - 1), 0); | |
| 44 | CHECK_EQ(kL2Size & (kL2Size - 1), 0); | |
| 45 | CHECK_GE(1ull << (sizeof(IndexT) * 8), kL1Size * kL2Size); | |
| 46 | // Check that it makes sense to use the dense alloc. | |
| 47 | CHECK_GE(sizeof(T), sizeof(IndexT)); | |
| 48 | internal_memset(map_, 0, sizeof(map_)); | |
| 41 | static_assert((kL1Size & (kL1Size - 1)) == 0, | |
| 42 | "kL1Size must be a power-of-two"); | |
| 43 | static_assert((kL2Size & (kL2Size - 1)) == 0, | |
| 44 | "kL2Size must be a power-of-two"); | |
| 45 | static_assert((kL1Size * kL2Size) <= (1ull << (sizeof(IndexT) * 8)), | |
| 46 | "kL1Size/kL2Size are too large"); | |
| 47 | static_assert(((kL1Size * kL2Size - 1) & kReserved) == 0, | |
| 48 | "reserved bits don't fit"); | |
| 49 | static_assert(sizeof(T) > sizeof(IndexT), | |
| 50 | "it doesn't make sense to use dense alloc"); | |
| 51 | ||
| 52 | explicit DenseSlabAlloc(LinkerInitialized, const char *name) { | |
| 49 | 53 | freelist_ = 0; |
| 50 | 54 | fillpos_ = 0; |
| 51 | 55 | name_ = name; |
| 52 | 56 | } |
| 53 | 57 | |
| 58 | explicit DenseSlabAlloc(const char *name) | |
| 59 | : DenseSlabAlloc(LINKER_INITIALIZED, name) { | |
| 60 | // It can be very large. | |
| 61 | // Don't page it in for linker initialized objects. | |
| 62 | internal_memset(map_, 0, sizeof(map_)); | |
| 63 | } | |
| 64 | ||
| 54 | 65 | ~DenseSlabAlloc() { |
| 55 | 66 | for (uptr i = 0; i < kL1Size; i++) { |
| 56 | 67 | if (map_[i] != 0) |
lib/tsan/tsan_external.cpp+6-5| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | //===----------------------------------------------------------------------===// |
| 12 | 12 | #include "tsan_rtl.h" |
| 13 | 13 | #include "tsan_interceptors.h" |
| 14 | #include "sanitizer_common/sanitizer_ptrauth.h" | |
| 14 | 15 | |
| 15 | 16 | namespace __tsan { |
| 16 | 17 | |
| ... | ... | @@ -57,13 +58,13 @@ uptr TagFromShadowStackFrame(uptr pc) { |
| 57 | 58 | #if !SANITIZER_GO |
| 58 | 59 | |
| 59 | 60 | typedef void(*AccessFunc)(ThreadState *, uptr, uptr, int); |
| 60 | void ExternalAccess(void *addr, void *caller_pc, void *tag, AccessFunc access) { | |
| 61 | void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessFunc access) { | |
| 61 | 62 | CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed)); |
| 62 | 63 | ThreadState *thr = cur_thread(); |
| 63 | if (caller_pc) FuncEntry(thr, (uptr)caller_pc); | |
| 64 | if (caller_pc) FuncEntry(thr, caller_pc); | |
| 64 | 65 | InsertShadowStackFrameForTag(thr, (uptr)tag); |
| 65 | 66 | bool in_ignored_lib; |
| 66 | if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) { | |
| 67 | if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib)) { | |
| 67 | 68 | access(thr, CALLERPC, (uptr)addr, kSizeLog1); |
| 68 | 69 | } |
| 69 | 70 | FuncExit(thr); |
| ... | ... | @@ -110,12 +111,12 @@ void __tsan_external_assign_tag(void *addr, void *tag) { |
| 110 | 111 | |
| 111 | 112 | SANITIZER_INTERFACE_ATTRIBUTE |
| 112 | 113 | void __tsan_external_read(void *addr, void *caller_pc, void *tag) { |
| 113 | ExternalAccess(addr, caller_pc, tag, MemoryRead); | |
| 114 | ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, MemoryRead); | |
| 114 | 115 | } |
| 115 | 116 | |
| 116 | 117 | SANITIZER_INTERFACE_ATTRIBUTE |
| 117 | 118 | void __tsan_external_write(void *addr, void *caller_pc, void *tag) { |
| 118 | ExternalAccess(addr, caller_pc, tag, MemoryWrite); | |
| 119 | ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, MemoryWrite); | |
| 119 | 120 | } |
| 120 | 121 | } // extern "C" |
| 121 | 122 |
lib/tsan/tsan_flags.cpp+1-1| ... | ... | @@ -87,7 +87,7 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) { |
| 87 | 87 | // Let a frontend override. |
| 88 | 88 | parser.ParseString(__tsan_default_options()); |
| 89 | 89 | #if TSAN_CONTAINS_UBSAN |
| 90 | const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); | |
| 90 | const char *ubsan_default_options = __ubsan_default_options(); | |
| 91 | 91 | ubsan_parser.ParseString(ubsan_default_options); |
| 92 | 92 | #endif |
| 93 | 93 | // Override from command line. |
lib/tsan/tsan_interceptors.h+9-9| ... | ... | @@ -22,7 +22,7 @@ class ScopedInterceptor { |
| 22 | 22 | LibIgnore *libignore(); |
| 23 | 23 | |
| 24 | 24 | #if !SANITIZER_GO |
| 25 | INLINE bool in_symbolizer() { | |
| 25 | inline bool in_symbolizer() { | |
| 26 | 26 | cur_thread_init(); |
| 27 | 27 | return UNLIKELY(cur_thread()->in_symbolizer); |
| 28 | 28 | } |
| ... | ... | @@ -30,14 +30,14 @@ INLINE bool in_symbolizer() { |
| 30 | 30 | |
| 31 | 31 | } // namespace __tsan |
| 32 | 32 | |
| 33 | #define SCOPED_INTERCEPTOR_RAW(func, ...) \ | |
| 34 | cur_thread_init(); \ | |
| 35 | ThreadState *thr = cur_thread(); \ | |
| 36 | const uptr caller_pc = GET_CALLER_PC(); \ | |
| 37 | ScopedInterceptor si(thr, #func, caller_pc); \ | |
| 38 | const uptr pc = StackTrace::GetCurrentPc(); \ | |
| 39 | (void)pc; \ | |
| 40 | /**/ | |
| 33 | #define SCOPED_INTERCEPTOR_RAW(func, ...) \ | |
| 34 | cur_thread_init(); \ | |
| 35 | ThreadState *thr = cur_thread(); \ | |
| 36 | const uptr caller_pc = GET_CALLER_PC(); \ | |
| 37 | ScopedInterceptor si(thr, #func, caller_pc); \ | |
| 38 | const uptr pc = GET_CURRENT_PC(); \ | |
| 39 | (void)pc; \ | |
| 40 | /**/ | |
| 41 | 41 | |
| 42 | 42 | #define SCOPED_TSAN_INTERCEPTOR(func, ...) \ |
| 43 | 43 | SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ |
lib/tsan/tsan_interceptors_mac.cpp+6-4| ... | ... | @@ -44,8 +44,9 @@ namespace __tsan { |
| 44 | 44 | // actually aliases of each other, and we cannot have different interceptors for |
| 45 | 45 | // them, because they're actually the same function. Thus, we have to stay |
| 46 | 46 | // conservative and treat the non-barrier versions as mo_acq_rel. |
| 47 | static const morder kMacOrderBarrier = mo_acq_rel; | |
| 48 | static const morder kMacOrderNonBarrier = mo_acq_rel; | |
| 47 | static constexpr morder kMacOrderBarrier = mo_acq_rel; | |
| 48 | static constexpr morder kMacOrderNonBarrier = mo_acq_rel; | |
| 49 | static constexpr morder kMacFailureOrder = mo_relaxed; | |
| 49 | 50 | |
| 50 | 51 | #define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \ |
| 51 | 52 | TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \ |
| ... | ... | @@ -110,7 +111,7 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor, |
| 110 | 111 | SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \ |
| 111 | 112 | return tsan_atomic_f##_compare_exchange_strong( \ |
| 112 | 113 | (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ |
| 113 | kMacOrderNonBarrier, kMacOrderNonBarrier); \ | |
| 114 | kMacOrderNonBarrier, kMacFailureOrder); \ | |
| 114 | 115 | } \ |
| 115 | 116 | \ |
| 116 | 117 | TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \ |
| ... | ... | @@ -118,7 +119,7 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor, |
| 118 | 119 | SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \ |
| 119 | 120 | return tsan_atomic_f##_compare_exchange_strong( \ |
| 120 | 121 | (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ |
| 121 | kMacOrderBarrier, kMacOrderNonBarrier); \ | |
| 122 | kMacOrderBarrier, kMacFailureOrder); \ | |
| 122 | 123 | } |
| 123 | 124 | |
| 124 | 125 | OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int) |
| ... | ... | @@ -438,6 +439,7 @@ struct fake_shared_weak_count { |
| 438 | 439 | virtual void on_zero_shared() = 0; |
| 439 | 440 | virtual void _unused_0x18() = 0; |
| 440 | 441 | virtual void on_zero_shared_weak() = 0; |
| 442 | virtual ~fake_shared_weak_count() = 0; // suppress -Wnon-virtual-dtor | |
| 441 | 443 | }; |
| 442 | 444 | } // namespace |
| 443 | 445 |
lib/tsan/tsan_interceptors_mach_vm.cpp+10-9| ... | ... | @@ -19,12 +19,11 @@ |
| 19 | 19 | |
| 20 | 20 | namespace __tsan { |
| 21 | 21 | |
| 22 | static bool intersects_with_shadow(mach_vm_address_t *address, | |
| 22 | static bool intersects_with_shadow(mach_vm_address_t address, | |
| 23 | 23 | mach_vm_size_t size, int flags) { |
| 24 | 24 | // VM_FLAGS_FIXED is 0x0, so we have to test for VM_FLAGS_ANYWHERE. |
| 25 | 25 | if (flags & VM_FLAGS_ANYWHERE) return false; |
| 26 | uptr ptr = *address; | |
| 27 | return !IsAppMem(ptr) || !IsAppMem(ptr + size - 1); | |
| 26 | return !IsAppMem(address) || !IsAppMem(address + size - 1); | |
| 28 | 27 | } |
| 29 | 28 | |
| 30 | 29 | TSAN_INTERCEPTOR(kern_return_t, mach_vm_allocate, vm_map_t target, |
| ... | ... | @@ -32,12 +31,12 @@ TSAN_INTERCEPTOR(kern_return_t, mach_vm_allocate, vm_map_t target, |
| 32 | 31 | SCOPED_TSAN_INTERCEPTOR(mach_vm_allocate, target, address, size, flags); |
| 33 | 32 | if (target != mach_task_self()) |
| 34 | 33 | return REAL(mach_vm_allocate)(target, address, size, flags); |
| 35 | if (intersects_with_shadow(address, size, flags)) | |
| 34 | if (address && intersects_with_shadow(*address, size, flags)) | |
| 36 | 35 | return KERN_NO_SPACE; |
| 37 | kern_return_t res = REAL(mach_vm_allocate)(target, address, size, flags); | |
| 38 | if (res == KERN_SUCCESS) | |
| 36 | kern_return_t kr = REAL(mach_vm_allocate)(target, address, size, flags); | |
| 37 | if (kr == KERN_SUCCESS) | |
| 39 | 38 | MemoryRangeImitateWriteOrResetRange(thr, pc, *address, size); |
| 40 | return res; | |
| 39 | return kr; | |
| 41 | 40 | } |
| 42 | 41 | |
| 43 | 42 | TSAN_INTERCEPTOR(kern_return_t, mach_vm_deallocate, vm_map_t target, |
| ... | ... | @@ -45,8 +44,10 @@ TSAN_INTERCEPTOR(kern_return_t, mach_vm_deallocate, vm_map_t target, |
| 45 | 44 | SCOPED_TSAN_INTERCEPTOR(mach_vm_deallocate, target, address, size); |
| 46 | 45 | if (target != mach_task_self()) |
| 47 | 46 | return REAL(mach_vm_deallocate)(target, address, size); |
| 48 | UnmapShadow(thr, address, size); | |
| 49 | return REAL(mach_vm_deallocate)(target, address, size); | |
| 47 | kern_return_t kr = REAL(mach_vm_deallocate)(target, address, size); | |
| 48 | if (kr == KERN_SUCCESS && address) | |
| 49 | UnmapShadow(thr, address, size); | |
| 50 | return kr; | |
| 50 | 51 | } |
| 51 | 52 | |
| 52 | 53 | } // namespace __tsan |
lib/tsan/tsan_interceptors_posix.cpp+164-74| ... | ... | @@ -31,6 +31,8 @@ |
| 31 | 31 | #include "tsan_mman.h" |
| 32 | 32 | #include "tsan_fd.h" |
| 33 | 33 | |
| 34 | #include <stdarg.h> | |
| 35 | ||
| 34 | 36 | using namespace __tsan; |
| 35 | 37 | |
| 36 | 38 | #if SANITIZER_FREEBSD || SANITIZER_MAC |
| ... | ... | @@ -52,10 +54,6 @@ using namespace __tsan; |
| 52 | 54 | #define vfork __vfork14 |
| 53 | 55 | #endif |
| 54 | 56 | |
| 55 | #if SANITIZER_ANDROID | |
| 56 | #define mallopt(a, b) | |
| 57 | #endif | |
| 58 | ||
| 59 | 57 | #ifdef __mips__ |
| 60 | 58 | const int kSigCount = 129; |
| 61 | 59 | #else |
| ... | ... | @@ -73,7 +71,8 @@ struct ucontext_t { |
| 73 | 71 | }; |
| 74 | 72 | #endif |
| 75 | 73 | |
| 76 | #if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 | |
| 74 | #if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \ | |
| 75 | defined(__s390x__) | |
| 77 | 76 | #define PTHREAD_ABI_BASE "GLIBC_2.3.2" |
| 78 | 77 | #elif defined(__aarch64__) || SANITIZER_PPC64V2 |
| 79 | 78 | #define PTHREAD_ABI_BASE "GLIBC_2.17" |
| ... | ... | @@ -83,6 +82,8 @@ extern "C" int pthread_attr_init(void *attr); |
| 83 | 82 | extern "C" int pthread_attr_destroy(void *attr); |
| 84 | 83 | DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *) |
| 85 | 84 | extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize); |
| 85 | extern "C" int pthread_atfork(void (*prepare)(void), void (*parent)(void), | |
| 86 | void (*child)(void)); | |
| 86 | 87 | extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v)); |
| 87 | 88 | extern "C" int pthread_setspecific(unsigned key, const void *v); |
| 88 | 89 | DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *) |
| ... | ... | @@ -95,7 +96,7 @@ extern "C" void _exit(int status); |
| 95 | 96 | extern "C" int fileno_unlocked(void *stream); |
| 96 | 97 | extern "C" int dirfd(void *dirp); |
| 97 | 98 | #endif |
| 98 | #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_NETBSD | |
| 99 | #if SANITIZER_GLIBC | |
| 99 | 100 | extern "C" int mallopt(int param, int value); |
| 100 | 101 | #endif |
| 101 | 102 | #if SANITIZER_NETBSD |
| ... | ... | @@ -135,6 +136,7 @@ const int PTHREAD_BARRIER_SERIAL_THREAD = -1; |
| 135 | 136 | #endif |
| 136 | 137 | const int MAP_FIXED = 0x10; |
| 137 | 138 | typedef long long_t; |
| 139 | typedef __sanitizer::u16 mode_t; | |
| 138 | 140 | |
| 139 | 141 | // From /usr/include/unistd.h |
| 140 | 142 | # define F_ULOCK 0 /* Unlock a previously locked region. */ |
| ... | ... | @@ -194,12 +196,10 @@ struct InterceptorContext { |
| 194 | 196 | unsigned finalize_key; |
| 195 | 197 | #endif |
| 196 | 198 | |
| 197 | BlockingMutex atexit_mu; | |
| 199 | Mutex atexit_mu; | |
| 198 | 200 | Vector<struct AtExitCtx *> AtExitStack; |
| 199 | 201 | |
| 200 | InterceptorContext() | |
| 201 | : libignore(LINKER_INITIALIZED), AtExitStack() { | |
| 202 | } | |
| 202 | InterceptorContext() : libignore(LINKER_INITIALIZED), atexit_mu(MutexTypeAtExit), AtExitStack() {} | |
| 203 | 203 | }; |
| 204 | 204 | |
| 205 | 205 | static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)]; |
| ... | ... | @@ -265,7 +265,7 @@ ScopedInterceptor::~ScopedInterceptor() { |
| 265 | 265 | if (!thr_->ignore_interceptors) { |
| 266 | 266 | ProcessPendingSignals(thr_); |
| 267 | 267 | FuncExit(thr_); |
| 268 | CheckNoLocks(thr_); | |
| 268 | CheckedMutex::CheckNoLocks(); | |
| 269 | 269 | } |
| 270 | 270 | } |
| 271 | 271 | |
| ... | ... | @@ -375,7 +375,7 @@ static void at_exit_wrapper() { |
| 375 | 375 | AtExitCtx *ctx; |
| 376 | 376 | { |
| 377 | 377 | // Ensure thread-safety. |
| 378 | BlockingMutexLock l(&interceptor_ctx()->atexit_mu); | |
| 378 | Lock l(&interceptor_ctx()->atexit_mu); | |
| 379 | 379 | |
| 380 | 380 | // Pop AtExitCtx from the top of the stack of callback functions |
| 381 | 381 | uptr element = interceptor_ctx()->AtExitStack.Size() - 1; |
| ... | ... | @@ -431,7 +431,10 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(), |
| 431 | 431 | // Store ctx in a local stack-like structure |
| 432 | 432 | |
| 433 | 433 | // Ensure thread-safety. |
| 434 | BlockingMutexLock l(&interceptor_ctx()->atexit_mu); | |
| 434 | Lock l(&interceptor_ctx()->atexit_mu); | |
| 435 | // __cxa_atexit calls calloc. If we don't ignore interceptors, we will fail | |
| 436 | // due to atexit_mu held on exit from the calloc interceptor. | |
| 437 | ScopedIgnoreInterceptors ignore; | |
| 435 | 438 | |
| 436 | 439 | res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0); |
| 437 | 440 | // Push AtExitCtx on the top of the stack of callback functions |
| ... | ... | @@ -656,8 +659,11 @@ TSAN_INTERCEPTOR(void*, malloc, uptr size) { |
| 656 | 659 | return p; |
| 657 | 660 | } |
| 658 | 661 | |
| 662 | // In glibc<2.25, dynamic TLS blocks are allocated by __libc_memalign. Intercept | |
| 663 | // __libc_memalign so that (1) we can detect races (2) free will not be called | |
| 664 | // on libc internally allocated blocks. | |
| 659 | 665 | TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { |
| 660 | SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); | |
| 666 | SCOPED_INTERCEPTOR_RAW(__libc_memalign, align, sz); | |
| 661 | 667 | return user_memalign(thr, pc, align, sz); |
| 662 | 668 | } |
| 663 | 669 | |
| ... | ... | @@ -770,6 +776,11 @@ static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap, |
| 770 | 776 | if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED; |
| 771 | 777 | void *res = real_mmap(addr, sz, prot, flags, fd, off); |
| 772 | 778 | if (res != MAP_FAILED) { |
| 779 | if (!IsAppMem((uptr)res) || !IsAppMem((uptr)res + sz - 1)) { | |
| 780 | Report("ThreadSanitizer: mmap at bad address: addr=%p size=%p res=%p\n", | |
| 781 | addr, (void*)sz, res); | |
| 782 | Die(); | |
| 783 | } | |
| 773 | 784 | if (fd > 0) FdAccess(thr, pc, fd); |
| 774 | 785 | MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz); |
| 775 | 786 | } |
| ... | ... | @@ -1119,27 +1130,37 @@ static void *init_cond(void *c, bool force = false) { |
| 1119 | 1130 | return (void*)cond; |
| 1120 | 1131 | } |
| 1121 | 1132 | |
| 1133 | namespace { | |
| 1134 | ||
| 1135 | template <class Fn> | |
| 1122 | 1136 | struct CondMutexUnlockCtx { |
| 1123 | 1137 | ScopedInterceptor *si; |
| 1124 | 1138 | ThreadState *thr; |
| 1125 | 1139 | uptr pc; |
| 1126 | 1140 | void *m; |
| 1141 | void *c; | |
| 1142 | const Fn &fn; | |
| 1143 | ||
| 1144 | int Cancel() const { return fn(); } | |
| 1145 | void Unlock() const; | |
| 1127 | 1146 | }; |
| 1128 | 1147 | |
| 1129 | static void cond_mutex_unlock(CondMutexUnlockCtx *arg) { | |
| 1148 | template <class Fn> | |
| 1149 | void CondMutexUnlockCtx<Fn>::Unlock() const { | |
| 1130 | 1150 | // pthread_cond_wait interceptor has enabled async signal delivery |
| 1131 | 1151 | // (see BlockingCall below). Disable async signals since we are running |
| 1132 | 1152 | // tsan code. Also ScopedInterceptor and BlockingCall destructors won't run |
| 1133 | 1153 | // since the thread is cancelled, so we have to manually execute them |
| 1134 | 1154 | // (the thread still can run some user code due to pthread_cleanup_push). |
| 1135 | ThreadSignalContext *ctx = SigCtx(arg->thr); | |
| 1155 | ThreadSignalContext *ctx = SigCtx(thr); | |
| 1136 | 1156 | CHECK_EQ(atomic_load(&ctx->in_blocking_func, memory_order_relaxed), 1); |
| 1137 | 1157 | atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed); |
| 1138 | MutexPostLock(arg->thr, arg->pc, (uptr)arg->m, MutexFlagDoPreLockOnPostLock); | |
| 1158 | MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock); | |
| 1139 | 1159 | // Undo BlockingCall ctor effects. |
| 1140 | arg->thr->ignore_interceptors--; | |
| 1141 | arg->si->~ScopedInterceptor(); | |
| 1160 | thr->ignore_interceptors--; | |
| 1161 | si->~ScopedInterceptor(); | |
| 1142 | 1162 | } |
| 1163 | } // namespace | |
| 1143 | 1164 | |
| 1144 | 1165 | INTERCEPTOR(int, pthread_cond_init, void *c, void *a) { |
| 1145 | 1166 | void *cond = init_cond(c, true); |
| ... | ... | @@ -1148,20 +1169,24 @@ INTERCEPTOR(int, pthread_cond_init, void *c, void *a) { |
| 1148 | 1169 | return REAL(pthread_cond_init)(cond, a); |
| 1149 | 1170 | } |
| 1150 | 1171 | |
| 1151 | static int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si, | |
| 1152 | int (*fn)(void *c, void *m, void *abstime), void *c, | |
| 1153 | void *m, void *t) { | |
| 1172 | template <class Fn> | |
| 1173 | int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si, const Fn &fn, | |
| 1174 | void *c, void *m) { | |
| 1154 | 1175 | MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); |
| 1155 | 1176 | MutexUnlock(thr, pc, (uptr)m); |
| 1156 | CondMutexUnlockCtx arg = {si, thr, pc, m}; | |
| 1157 | 1177 | int res = 0; |
| 1158 | 1178 | // This ensures that we handle mutex lock even in case of pthread_cancel. |
| 1159 | 1179 | // See test/tsan/cond_cancel.cpp. |
| 1160 | 1180 | { |
| 1161 | 1181 | // Enable signal delivery while the thread is blocked. |
| 1162 | 1182 | BlockingCall bc(thr); |
| 1183 | CondMutexUnlockCtx<Fn> arg = {si, thr, pc, m, c, fn}; | |
| 1163 | 1184 | res = call_pthread_cancel_with_cleanup( |
| 1164 | fn, c, m, t, (void (*)(void *arg))cond_mutex_unlock, &arg); | |
| 1185 | [](void *arg) -> int { | |
| 1186 | return ((const CondMutexUnlockCtx<Fn> *)arg)->Cancel(); | |
| 1187 | }, | |
| 1188 | [](void *arg) { ((const CondMutexUnlockCtx<Fn> *)arg)->Unlock(); }, | |
| 1189 | &arg); | |
| 1165 | 1190 | } |
| 1166 | 1191 | if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m); |
| 1167 | 1192 | MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock); |
| ... | ... | @@ -1171,25 +1196,46 @@ static int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si, |
| 1171 | 1196 | INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) { |
| 1172 | 1197 | void *cond = init_cond(c); |
| 1173 | 1198 | SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m); |
| 1174 | return cond_wait(thr, pc, &si, (int (*)(void *c, void *m, void *abstime))REAL( | |
| 1175 | pthread_cond_wait), | |
| 1176 | cond, m, 0); | |
| 1199 | return cond_wait( | |
| 1200 | thr, pc, &si, [=]() { return REAL(pthread_cond_wait)(cond, m); }, cond, | |
| 1201 | m); | |
| 1177 | 1202 | } |
| 1178 | 1203 | |
| 1179 | 1204 | INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) { |
| 1180 | 1205 | void *cond = init_cond(c); |
| 1181 | 1206 | SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime); |
| 1182 | return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait), cond, m, | |
| 1183 | abstime); | |
| 1207 | return cond_wait( | |
| 1208 | thr, pc, &si, | |
| 1209 | [=]() { return REAL(pthread_cond_timedwait)(cond, m, abstime); }, cond, | |
| 1210 | m); | |
| 1184 | 1211 | } |
| 1185 | 1212 | |
| 1213 | #if SANITIZER_LINUX | |
| 1214 | INTERCEPTOR(int, pthread_cond_clockwait, void *c, void *m, | |
| 1215 | __sanitizer_clockid_t clock, void *abstime) { | |
| 1216 | void *cond = init_cond(c); | |
| 1217 | SCOPED_TSAN_INTERCEPTOR(pthread_cond_clockwait, cond, m, clock, abstime); | |
| 1218 | return cond_wait( | |
| 1219 | thr, pc, &si, | |
| 1220 | [=]() { return REAL(pthread_cond_clockwait)(cond, m, clock, abstime); }, | |
| 1221 | cond, m); | |
| 1222 | } | |
| 1223 | #define TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT TSAN_INTERCEPT(pthread_cond_clockwait) | |
| 1224 | #else | |
| 1225 | #define TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT | |
| 1226 | #endif | |
| 1227 | ||
| 1186 | 1228 | #if SANITIZER_MAC |
| 1187 | 1229 | INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m, |
| 1188 | 1230 | void *reltime) { |
| 1189 | 1231 | void *cond = init_cond(c); |
| 1190 | 1232 | SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_relative_np, cond, m, reltime); |
| 1191 | return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait_relative_np), cond, | |
| 1192 | m, reltime); | |
| 1233 | return cond_wait( | |
| 1234 | thr, pc, &si, | |
| 1235 | [=]() { | |
| 1236 | return REAL(pthread_cond_timedwait_relative_np)(cond, m, reltime); | |
| 1237 | }, | |
| 1238 | cond, m); | |
| 1193 | 1239 | } |
| 1194 | 1240 | #endif |
| 1195 | 1241 | |
| ... | ... | @@ -1508,20 +1554,28 @@ TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { |
| 1508 | 1554 | #define TSAN_MAYBE_INTERCEPT_FSTAT64 |
| 1509 | 1555 | #endif |
| 1510 | 1556 | |
| 1511 | TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) { | |
| 1512 | SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode); | |
| 1557 | TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) { | |
| 1558 | va_list ap; | |
| 1559 | va_start(ap, oflag); | |
| 1560 | mode_t mode = va_arg(ap, int); | |
| 1561 | va_end(ap); | |
| 1562 | SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode); | |
| 1513 | 1563 | READ_STRING(thr, pc, name, 0); |
| 1514 | int fd = REAL(open)(name, flags, mode); | |
| 1564 | int fd = REAL(open)(name, oflag, mode); | |
| 1515 | 1565 | if (fd >= 0) |
| 1516 | 1566 | FdFileCreate(thr, pc, fd); |
| 1517 | 1567 | return fd; |
| 1518 | 1568 | } |
| 1519 | 1569 | |
| 1520 | 1570 | #if SANITIZER_LINUX |
| 1521 | TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) { | |
| 1522 | SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode); | |
| 1571 | TSAN_INTERCEPTOR(int, open64, const char *name, int oflag, ...) { | |
| 1572 | va_list ap; | |
| 1573 | va_start(ap, oflag); | |
| 1574 | mode_t mode = va_arg(ap, int); | |
| 1575 | va_end(ap); | |
| 1576 | SCOPED_TSAN_INTERCEPTOR(open64, name, oflag, mode); | |
| 1523 | 1577 | READ_STRING(thr, pc, name, 0); |
| 1524 | int fd = REAL(open64)(name, flags, mode); | |
| 1578 | int fd = REAL(open64)(name, oflag, mode); | |
| 1525 | 1579 | if (fd >= 0) |
| 1526 | 1580 | FdFileCreate(thr, pc, fd); |
| 1527 | 1581 | return fd; |
| ... | ... | @@ -1926,7 +1980,8 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire, |
| 1926 | 1980 | // because in async signal processing case (when handler is called directly |
| 1927 | 1981 | // from rtl_generic_sighandler) we have not yet received the reraised |
| 1928 | 1982 | // signal; and it looks too fragile to intercept all ways to reraise a signal. |
| 1929 | if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) { | |
| 1983 | if (ShouldReport(thr, ReportTypeErrnoInSignal) && !sync && sig != SIGTERM && | |
| 1984 | errno != 99) { | |
| 1930 | 1985 | VarSizeStackTrace stack; |
| 1931 | 1986 | // StackTrace::GetNestInstructionPc(pc) is used because return address is |
| 1932 | 1987 | // expected, OutputReport() will undo this. |
| ... | ... | @@ -2096,26 +2151,32 @@ TSAN_INTERCEPTOR(int, fork, int fake) { |
| 2096 | 2151 | if (in_symbolizer()) |
| 2097 | 2152 | return REAL(fork)(fake); |
| 2098 | 2153 | SCOPED_INTERCEPTOR_RAW(fork, fake); |
| 2154 | return REAL(fork)(fake); | |
| 2155 | } | |
| 2156 | ||
| 2157 | void atfork_prepare() { | |
| 2158 | if (in_symbolizer()) | |
| 2159 | return; | |
| 2160 | ThreadState *thr = cur_thread(); | |
| 2161 | const uptr pc = StackTrace::GetCurrentPc(); | |
| 2099 | 2162 | ForkBefore(thr, pc); |
| 2100 | int pid; | |
| 2101 | { | |
| 2102 | // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and | |
| 2103 | // we'll assert in CheckNoLocks() unless we ignore interceptors. | |
| 2104 | ScopedIgnoreInterceptors ignore; | |
| 2105 | pid = REAL(fork)(fake); | |
| 2106 | } | |
| 2107 | if (pid == 0) { | |
| 2108 | // child | |
| 2109 | ForkChildAfter(thr, pc); | |
| 2110 | FdOnFork(thr, pc); | |
| 2111 | } else if (pid > 0) { | |
| 2112 | // parent | |
| 2113 | ForkParentAfter(thr, pc); | |
| 2114 | } else { | |
| 2115 | // error | |
| 2116 | ForkParentAfter(thr, pc); | |
| 2117 | } | |
| 2118 | return pid; | |
| 2163 | } | |
| 2164 | ||
| 2165 | void atfork_parent() { | |
| 2166 | if (in_symbolizer()) | |
| 2167 | return; | |
| 2168 | ThreadState *thr = cur_thread(); | |
| 2169 | const uptr pc = StackTrace::GetCurrentPc(); | |
| 2170 | ForkParentAfter(thr, pc); | |
| 2171 | } | |
| 2172 | ||
| 2173 | void atfork_child() { | |
| 2174 | if (in_symbolizer()) | |
| 2175 | return; | |
| 2176 | ThreadState *thr = cur_thread(); | |
| 2177 | const uptr pc = StackTrace::GetCurrentPc(); | |
| 2178 | ForkChildAfter(thr, pc); | |
| 2179 | FdOnFork(thr, pc); | |
| 2119 | 2180 | } |
| 2120 | 2181 | |
| 2121 | 2182 | TSAN_INTERCEPTOR(int, vfork, int fake) { |
| ... | ... | @@ -2211,11 +2272,14 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, |
| 2211 | 2272 | #define NEED_TLS_GET_ADDR |
| 2212 | 2273 | #endif |
| 2213 | 2274 | #undef SANITIZER_INTERCEPT_TLS_GET_ADDR |
| 2275 | #define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1 | |
| 2214 | 2276 | #undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK |
| 2215 | 2277 | |
| 2216 | 2278 | #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) |
| 2217 | 2279 | #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ |
| 2218 | 2280 | INTERCEPT_FUNCTION_VER(name, ver) |
| 2281 | #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \ | |
| 2282 | (INTERCEPT_FUNCTION_VER(name, ver) || INTERCEPT_FUNCTION(name)) | |
| 2219 | 2283 | |
| 2220 | 2284 | #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ |
| 2221 | 2285 | MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \ |
| ... | ... | @@ -2359,6 +2423,10 @@ int sigaction_impl(int sig, const __sanitizer_sigaction *act, |
| 2359 | 2423 | // the signal handler through rtl_sigaction, very bad things will happen. |
| 2360 | 2424 | // The handler will run synchronously and corrupt tsan per-thread state. |
| 2361 | 2425 | SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old); |
| 2426 | if (sig <= 0 || sig >= kSigCount) { | |
| 2427 | errno = errno_EINVAL; | |
| 2428 | return -1; | |
| 2429 | } | |
| 2362 | 2430 | __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions; |
| 2363 | 2431 | __sanitizer_sigaction old_stored; |
| 2364 | 2432 | if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored)); |
| ... | ... | @@ -2437,13 +2505,13 @@ static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) { |
| 2437 | 2505 | MemoryAccessRange(thr, pc, p, s, write); |
| 2438 | 2506 | } |
| 2439 | 2507 | |
| 2440 | static void syscall_acquire(uptr pc, uptr addr) { | |
| 2508 | static USED void syscall_acquire(uptr pc, uptr addr) { | |
| 2441 | 2509 | TSAN_SYSCALL(); |
| 2442 | 2510 | Acquire(thr, pc, addr); |
| 2443 | 2511 | DPrintf("syscall_acquire(%p)\n", addr); |
| 2444 | 2512 | } |
| 2445 | 2513 | |
| 2446 | static void syscall_release(uptr pc, uptr addr) { | |
| 2514 | static USED void syscall_release(uptr pc, uptr addr) { | |
| 2447 | 2515 | TSAN_SYSCALL(); |
| 2448 | 2516 | DPrintf("syscall_release(%p)\n", addr); |
| 2449 | 2517 | Release(thr, pc, addr); |
| ... | ... | @@ -2466,13 +2534,10 @@ static USED void syscall_fd_release(uptr pc, int fd) { |
| 2466 | 2534 | FdRelease(thr, pc, fd); |
| 2467 | 2535 | } |
| 2468 | 2536 | |
| 2469 | static void syscall_pre_fork(uptr pc) { | |
| 2470 | TSAN_SYSCALL(); | |
| 2471 | ForkBefore(thr, pc); | |
| 2472 | } | |
| 2537 | static void syscall_pre_fork(uptr pc) { ForkBefore(cur_thread(), pc); } | |
| 2473 | 2538 | |
| 2474 | 2539 | static void syscall_post_fork(uptr pc, int pid) { |
| 2475 | TSAN_SYSCALL(); | |
| 2540 | ThreadState *thr = cur_thread(); | |
| 2476 | 2541 | if (pid == 0) { |
| 2477 | 2542 | // child |
| 2478 | 2543 | ForkChildAfter(thr, pc); |
| ... | ... | @@ -2527,6 +2592,20 @@ static void syscall_post_fork(uptr pc, int pid) { |
| 2527 | 2592 | #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" |
| 2528 | 2593 | |
| 2529 | 2594 | #ifdef NEED_TLS_GET_ADDR |
| 2595 | ||
| 2596 | static void handle_tls_addr(void *arg, void *res) { | |
| 2597 | ThreadState *thr = cur_thread(); | |
| 2598 | if (!thr) | |
| 2599 | return; | |
| 2600 | DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, | |
| 2601 | thr->tls_addr + thr->tls_size); | |
| 2602 | if (!dtv) | |
| 2603 | return; | |
| 2604 | // New DTLS block has been allocated. | |
| 2605 | MemoryResetRange(thr, 0, dtv->beg, dtv->size); | |
| 2606 | } | |
| 2607 | ||
| 2608 | #if !SANITIZER_S390 | |
| 2530 | 2609 | // Define own interceptor instead of sanitizer_common's for three reasons: |
| 2531 | 2610 | // 1. It must not process pending signals. |
| 2532 | 2611 | // Signal handlers may contain MOVDQA instruction (see below). |
| ... | ... | @@ -2539,17 +2618,17 @@ static void syscall_post_fork(uptr pc, int pid) { |
| 2539 | 2618 | // execute MOVDQA with stack addresses. |
| 2540 | 2619 | TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) { |
| 2541 | 2620 | void *res = REAL(__tls_get_addr)(arg); |
| 2542 | ThreadState *thr = cur_thread(); | |
| 2543 | if (!thr) | |
| 2544 | return res; | |
| 2545 | DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, | |
| 2546 | thr->tls_addr + thr->tls_size); | |
| 2547 | if (!dtv) | |
| 2548 | return res; | |
| 2549 | // New DTLS block has been allocated. | |
| 2550 | MemoryResetRange(thr, 0, dtv->beg, dtv->size); | |
| 2621 | handle_tls_addr(arg, res); | |
| 2551 | 2622 | return res; |
| 2552 | 2623 | } |
| 2624 | #else // SANITIZER_S390 | |
| 2625 | TSAN_INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { | |
| 2626 | uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset)); | |
| 2627 | char *tp = static_cast<char *>(__builtin_thread_pointer()); | |
| 2628 | handle_tls_addr(arg, res + tp); | |
| 2629 | return res; | |
| 2630 | } | |
| 2631 | #endif | |
| 2553 | 2632 | #endif |
| 2554 | 2633 | |
| 2555 | 2634 | #if SANITIZER_NETBSD |
| ... | ... | @@ -2622,7 +2701,7 @@ void InitializeInterceptors() { |
| 2622 | 2701 | #endif |
| 2623 | 2702 | |
| 2624 | 2703 | // Instruct libc malloc to consume less memory. |
| 2625 | #if SANITIZER_LINUX | |
| 2704 | #if SANITIZER_GLIBC | |
| 2626 | 2705 | mallopt(1, 0); // M_MXFAST |
| 2627 | 2706 | mallopt(-3, 32*1024); // M_MMAP_THRESHOLD |
| 2628 | 2707 | #endif |
| ... | ... | @@ -2685,6 +2764,8 @@ void InitializeInterceptors() { |
| 2685 | 2764 | TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE); |
| 2686 | 2765 | TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE); |
| 2687 | 2766 | |
| 2767 | TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT; | |
| 2768 | ||
| 2688 | 2769 | TSAN_INTERCEPT(pthread_mutex_init); |
| 2689 | 2770 | TSAN_INTERCEPT(pthread_mutex_destroy); |
| 2690 | 2771 | TSAN_INTERCEPT(pthread_mutex_trylock); |
| ... | ... | @@ -2770,7 +2851,12 @@ void InitializeInterceptors() { |
| 2770 | 2851 | TSAN_INTERCEPT(_exit); |
| 2771 | 2852 | |
| 2772 | 2853 | #ifdef NEED_TLS_GET_ADDR |
| 2854 | #if !SANITIZER_S390 | |
| 2773 | 2855 | TSAN_INTERCEPT(__tls_get_addr); |
| 2856 | #else | |
| 2857 | TSAN_INTERCEPT(__tls_get_addr_internal); | |
| 2858 | TSAN_INTERCEPT(__tls_get_offset); | |
| 2859 | #endif | |
| 2774 | 2860 | #endif |
| 2775 | 2861 | |
| 2776 | 2862 | TSAN_MAYBE_INTERCEPT__LWP_EXIT; |
| ... | ... | @@ -2786,6 +2872,10 @@ void InitializeInterceptors() { |
| 2786 | 2872 | Printf("ThreadSanitizer: failed to setup atexit callback\n"); |
| 2787 | 2873 | Die(); |
| 2788 | 2874 | } |
| 2875 | if (pthread_atfork(atfork_prepare, atfork_parent, atfork_child)) { | |
| 2876 | Printf("ThreadSanitizer: failed to setup atfork callbacks\n"); | |
| 2877 | Die(); | |
| 2878 | } | |
| 2789 | 2879 | |
| 2790 | 2880 | #if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD |
| 2791 | 2881 | if (pthread_key_create(&interceptor_ctx()->finalize_key, &thread_finalize)) { |
lib/tsan/tsan_interface.cpp+5-8| ... | ... | @@ -14,15 +14,12 @@ |
| 14 | 14 | #include "tsan_interface_ann.h" |
| 15 | 15 | #include "tsan_rtl.h" |
| 16 | 16 | #include "sanitizer_common/sanitizer_internal_defs.h" |
| 17 | #include "sanitizer_common/sanitizer_ptrauth.h" | |
| 17 | 18 | |
| 18 | 19 | #define CALLERPC ((uptr)__builtin_return_address(0)) |
| 19 | 20 | |
| 20 | 21 | using namespace __tsan; |
| 21 | 22 | |
| 22 | typedef u16 uint16_t; | |
| 23 | typedef u32 uint32_t; | |
| 24 | typedef u64 uint64_t; | |
| 25 | ||
| 26 | 23 | void __tsan_init() { |
| 27 | 24 | cur_thread_init(); |
| 28 | 25 | Initialize(cur_thread()); |
| ... | ... | @@ -43,13 +40,13 @@ void __tsan_write16(void *addr) { |
| 43 | 40 | } |
| 44 | 41 | |
| 45 | 42 | void __tsan_read16_pc(void *addr, void *pc) { |
| 46 | MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); | |
| 47 | MemoryRead(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8); | |
| 43 | MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8); | |
| 44 | MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr + 8, kSizeLog8); | |
| 48 | 45 | } |
| 49 | 46 | |
| 50 | 47 | void __tsan_write16_pc(void *addr, void *pc) { |
| 51 | MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); | |
| 52 | MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8); | |
| 48 | MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8); | |
| 49 | MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr + 8, kSizeLog8); | |
| 53 | 50 | } |
| 54 | 51 | |
| 55 | 52 | // __tsan_unaligned_read/write calls are emitted by compiler. |
lib/tsan/tsan_interface.h+10-2| ... | ... | @@ -196,7 +196,8 @@ typedef unsigned short a16; |
| 196 | 196 | typedef unsigned int a32; |
| 197 | 197 | typedef unsigned long long a64; |
| 198 | 198 | #if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \ |
| 199 | || (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64) | |
| 199 | || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \ | |
| 200 | !defined(__mips64) && !defined(__s390x__) | |
| 200 | 201 | __extension__ typedef __int128 a128; |
| 201 | 202 | # define __TSAN_HAS_INT128 1 |
| 202 | 203 | #else |
| ... | ... | @@ -204,7 +205,7 @@ __extension__ typedef __int128 a128; |
| 204 | 205 | #endif |
| 205 | 206 | |
| 206 | 207 | // Part of ABI, do not change. |
| 207 | // https://github.com/llvm/llvm-project/blob/master/libcxx/include/atomic | |
| 208 | // https://github.com/llvm/llvm-project/blob/main/libcxx/include/atomic | |
| 208 | 209 | typedef enum { |
| 209 | 210 | mo_relaxed, |
| 210 | 211 | mo_consume, |
| ... | ... | @@ -415,6 +416,13 @@ void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc, |
| 415 | 416 | SANITIZER_INTERFACE_ATTRIBUTE |
| 416 | 417 | void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc, |
| 417 | 418 | u8 *a); |
| 419 | ||
| 420 | SANITIZER_INTERFACE_ATTRIBUTE | |
| 421 | void __tsan_on_initialize(); | |
| 422 | ||
| 423 | SANITIZER_INTERFACE_ATTRIBUTE | |
| 424 | int __tsan_on_finalize(int failed); | |
| 425 | ||
| 418 | 426 | } // extern "C" |
| 419 | 427 | |
| 420 | 428 | } // namespace __tsan |
lib/tsan/tsan_interface_ann.cpp+2-7| ... | ... | @@ -15,7 +15,6 @@ |
| 15 | 15 | #include "sanitizer_common/sanitizer_stacktrace.h" |
| 16 | 16 | #include "sanitizer_common/sanitizer_vector.h" |
| 17 | 17 | #include "tsan_interface_ann.h" |
| 18 | #include "tsan_mutex.h" | |
| 19 | 18 | #include "tsan_report.h" |
| 20 | 19 | #include "tsan_rtl.h" |
| 21 | 20 | #include "tsan_mman.h" |
| ... | ... | @@ -38,7 +37,7 @@ class ScopedAnnotation { |
| 38 | 37 | |
| 39 | 38 | ~ScopedAnnotation() { |
| 40 | 39 | FuncExit(thr_); |
| 41 | CheckNoLocks(thr_); | |
| 40 | CheckedMutex::CheckNoLocks(); | |
| 42 | 41 | } |
| 43 | 42 | private: |
| 44 | 43 | ThreadState *const thr_; |
| ... | ... | @@ -49,8 +48,6 @@ class ScopedAnnotation { |
| 49 | 48 | return ret; \ |
| 50 | 49 | ThreadState *thr = cur_thread(); \ |
| 51 | 50 | const uptr caller_pc = (uptr)__builtin_return_address(0); \ |
| 52 | StatInc(thr, StatAnnotation); \ | |
| 53 | StatInc(thr, Stat##typ); \ | |
| 54 | 51 | ScopedAnnotation sa(thr, __func__, caller_pc); \ |
| 55 | 52 | const uptr pc = StackTrace::GetCurrentPc(); \ |
| 56 | 53 | (void)pc; \ |
| ... | ... | @@ -77,9 +74,7 @@ struct DynamicAnnContext { |
| 77 | 74 | ExpectRace expect; |
| 78 | 75 | ExpectRace benign; |
| 79 | 76 | |
| 80 | DynamicAnnContext() | |
| 81 | : mtx(MutexTypeAnnotations, StatMtxAnnotations) { | |
| 82 | } | |
| 77 | DynamicAnnContext() : mtx(MutexTypeAnnotations) {} | |
| 83 | 78 | }; |
| 84 | 79 | |
| 85 | 80 | static DynamicAnnContext *dyn_ann_ctx; |
lib/tsan/tsan_interface_atomic.cpp+35-39| ... | ... | @@ -218,8 +218,9 @@ static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) { |
| 218 | 218 | } |
| 219 | 219 | #endif |
| 220 | 220 | |
| 221 | template<typename T> | |
| 222 | static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) { | |
| 221 | template <typename T> | |
| 222 | static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, | |
| 223 | morder mo) NO_THREAD_SAFETY_ANALYSIS { | |
| 223 | 224 | CHECK(IsLoadOrder(mo)); |
| 224 | 225 | // This fast-path is critical for performance. |
| 225 | 226 | // Assume the access is atomic. |
| ... | ... | @@ -254,9 +255,9 @@ static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) { |
| 254 | 255 | } |
| 255 | 256 | #endif |
| 256 | 257 | |
| 257 | template<typename T> | |
| 258 | template <typename T> | |
| 258 | 259 | static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v, |
| 259 | morder mo) { | |
| 260 | morder mo) NO_THREAD_SAFETY_ANALYSIS { | |
| 260 | 261 | CHECK(IsStoreOrder(mo)); |
| 261 | 262 | MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>()); |
| 262 | 263 | // This fast-path is critical for performance. |
| ... | ... | @@ -277,8 +278,9 @@ static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v, |
| 277 | 278 | s->mtx.Unlock(); |
| 278 | 279 | } |
| 279 | 280 | |
| 280 | template<typename T, T (*F)(volatile T *v, T op)> | |
| 281 | static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) { | |
| 281 | template <typename T, T (*F)(volatile T *v, T op)> | |
| 282 | static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, | |
| 283 | morder mo) NO_THREAD_SAFETY_ANALYSIS { | |
| 282 | 284 | MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>()); |
| 283 | 285 | SyncVar *s = 0; |
| 284 | 286 | if (mo != mo_relaxed) { |
| ... | ... | @@ -399,37 +401,48 @@ static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) { |
| 399 | 401 | return c; |
| 400 | 402 | } |
| 401 | 403 | |
| 402 | template<typename T> | |
| 403 | static bool AtomicCAS(ThreadState *thr, uptr pc, | |
| 404 | volatile T *a, T *c, T v, morder mo, morder fmo) { | |
| 405 | (void)fmo; // Unused because llvm does not pass it yet. | |
| 404 | template <typename T> | |
| 405 | static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v, morder mo, | |
| 406 | morder fmo) NO_THREAD_SAFETY_ANALYSIS { | |
| 407 | // 31.7.2.18: "The failure argument shall not be memory_order_release | |
| 408 | // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic | |
| 409 | // (mo_relaxed) when those are used. | |
| 410 | CHECK(IsLoadOrder(fmo)); | |
| 411 | ||
| 406 | 412 | MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>()); |
| 407 | 413 | SyncVar *s = 0; |
| 408 | bool write_lock = mo != mo_acquire && mo != mo_consume; | |
| 409 | if (mo != mo_relaxed) { | |
| 414 | bool write_lock = IsReleaseOrder(mo); | |
| 415 | ||
| 416 | if (mo != mo_relaxed || fmo != mo_relaxed) | |
| 410 | 417 | s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock); |
| 418 | ||
| 419 | T cc = *c; | |
| 420 | T pr = func_cas(a, cc, v); | |
| 421 | bool success = pr == cc; | |
| 422 | if (!success) { | |
| 423 | *c = pr; | |
| 424 | mo = fmo; | |
| 425 | } | |
| 426 | ||
| 427 | if (s) { | |
| 411 | 428 | thr->fast_state.IncrementEpoch(); |
| 412 | 429 | // Can't increment epoch w/o writing to the trace as well. |
| 413 | 430 | TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0); |
| 414 | if (IsAcqRelOrder(mo)) | |
| 431 | ||
| 432 | if (success && IsAcqRelOrder(mo)) | |
| 415 | 433 | AcquireReleaseImpl(thr, pc, &s->clock); |
| 416 | else if (IsReleaseOrder(mo)) | |
| 434 | else if (success && IsReleaseOrder(mo)) | |
| 417 | 435 | ReleaseImpl(thr, pc, &s->clock); |
| 418 | 436 | else if (IsAcquireOrder(mo)) |
| 419 | 437 | AcquireImpl(thr, pc, &s->clock); |
| 420 | } | |
| 421 | T cc = *c; | |
| 422 | T pr = func_cas(a, cc, v); | |
| 423 | if (s) { | |
| 438 | ||
| 424 | 439 | if (write_lock) |
| 425 | 440 | s->mtx.Unlock(); |
| 426 | 441 | else |
| 427 | 442 | s->mtx.ReadUnlock(); |
| 428 | 443 | } |
| 429 | if (pr == cc) | |
| 430 | return true; | |
| 431 | *c = pr; | |
| 432 | return false; | |
| 444 | ||
| 445 | return success; | |
| 433 | 446 | } |
| 434 | 447 | |
| 435 | 448 | template<typename T> |
| ... | ... | @@ -481,7 +494,6 @@ static morder convert_morder(morder mo) { |
| 481 | 494 | const uptr callpc = (uptr)__builtin_return_address(0); \ |
| 482 | 495 | uptr pc = StackTrace::GetCurrentPc(); \ |
| 483 | 496 | mo = convert_morder(mo); \ |
| 484 | AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \ | |
| 485 | 497 | ScopedAtomic sa(thr, callpc, a, mo, __func__); \ |
| 486 | 498 | return Atomic##func(thr, pc, __VA_ARGS__); \ |
| 487 | 499 | /**/ |
| ... | ... | @@ -502,22 +514,6 @@ class ScopedAtomic { |
| 502 | 514 | ThreadState *thr_; |
| 503 | 515 | }; |
| 504 | 516 | |
| 505 | static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) { | |
| 506 | StatInc(thr, StatAtomic); | |
| 507 | StatInc(thr, t); | |
| 508 | StatInc(thr, size == 1 ? StatAtomic1 | |
| 509 | : size == 2 ? StatAtomic2 | |
| 510 | : size == 4 ? StatAtomic4 | |
| 511 | : size == 8 ? StatAtomic8 | |
| 512 | : StatAtomic16); | |
| 513 | StatInc(thr, mo == mo_relaxed ? StatAtomicRelaxed | |
| 514 | : mo == mo_consume ? StatAtomicConsume | |
| 515 | : mo == mo_acquire ? StatAtomicAcquire | |
| 516 | : mo == mo_release ? StatAtomicRelease | |
| 517 | : mo == mo_acq_rel ? StatAtomicAcq_Rel | |
| 518 | : StatAtomicSeq_Cst); | |
| 519 | } | |
| 520 | ||
| 521 | 517 | extern "C" { |
| 522 | 518 | SANITIZER_INTERFACE_ATTRIBUTE |
| 523 | 519 | a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) { |
lib/tsan/tsan_interface_inl.h+12-11| ... | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | |
| 13 | 13 | #include "tsan_interface.h" |
| 14 | 14 | #include "tsan_rtl.h" |
| 15 | #include "sanitizer_common/sanitizer_ptrauth.h" | |
| 15 | 16 | |
| 16 | 17 | #define CALLERPC ((uptr)__builtin_return_address(0)) |
| 17 | 18 | |
| ... | ... | @@ -50,35 +51,35 @@ void __tsan_write8(void *addr) { |
| 50 | 51 | } |
| 51 | 52 | |
| 52 | 53 | void __tsan_read1_pc(void *addr, void *pc) { |
| 53 | MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog1); | |
| 54 | MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog1); | |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | 57 | void __tsan_read2_pc(void *addr, void *pc) { |
| 57 | MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog2); | |
| 58 | MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog2); | |
| 58 | 59 | } |
| 59 | 60 | |
| 60 | 61 | void __tsan_read4_pc(void *addr, void *pc) { |
| 61 | MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog4); | |
| 62 | MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog4); | |
| 62 | 63 | } |
| 63 | 64 | |
| 64 | 65 | void __tsan_read8_pc(void *addr, void *pc) { |
| 65 | MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); | |
| 66 | MemoryRead(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8); | |
| 66 | 67 | } |
| 67 | 68 | |
| 68 | 69 | void __tsan_write1_pc(void *addr, void *pc) { |
| 69 | MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog1); | |
| 70 | MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog1); | |
| 70 | 71 | } |
| 71 | 72 | |
| 72 | 73 | void __tsan_write2_pc(void *addr, void *pc) { |
| 73 | MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog2); | |
| 74 | MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog2); | |
| 74 | 75 | } |
| 75 | 76 | |
| 76 | 77 | void __tsan_write4_pc(void *addr, void *pc) { |
| 77 | MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog4); | |
| 78 | MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog4); | |
| 78 | 79 | } |
| 79 | 80 | |
| 80 | 81 | void __tsan_write8_pc(void *addr, void *pc) { |
| 81 | MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); | |
| 82 | MemoryWrite(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, kSizeLog8); | |
| 82 | 83 | } |
| 83 | 84 | |
| 84 | 85 | void __tsan_vptr_update(void **vptr_p, void *new_val) { |
| ... | ... | @@ -100,7 +101,7 @@ void __tsan_vptr_read(void **vptr_p) { |
| 100 | 101 | } |
| 101 | 102 | |
| 102 | 103 | void __tsan_func_entry(void *pc) { |
| 103 | FuncEntry(cur_thread(), (uptr)pc); | |
| 104 | FuncEntry(cur_thread(), STRIP_PAC_PC(pc)); | |
| 104 | 105 | } |
| 105 | 106 | |
| 106 | 107 | void __tsan_func_exit() { |
| ... | ... | @@ -124,9 +125,9 @@ void __tsan_write_range(void *addr, uptr size) { |
| 124 | 125 | } |
| 125 | 126 | |
| 126 | 127 | void __tsan_read_range_pc(void *addr, uptr size, void *pc) { |
| 127 | MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, false); | |
| 128 | MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, false); | |
| 128 | 129 | } |
| 129 | 130 | |
| 130 | 131 | void __tsan_write_range_pc(void *addr, uptr size, void *pc) { |
| 131 | MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, true); | |
| 132 | MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true); | |
| 132 | 133 | } |
lib/tsan/tsan_interface_java.cpp-1| ... | ... | @@ -12,7 +12,6 @@ |
| 12 | 12 | |
| 13 | 13 | #include "tsan_interface_java.h" |
| 14 | 14 | #include "tsan_rtl.h" |
| 15 | #include "tsan_mutex.h" | |
| 16 | 15 | #include "sanitizer_common/sanitizer_internal_defs.h" |
| 17 | 16 | #include "sanitizer_common/sanitizer_common.h" |
| 18 | 17 | #include "sanitizer_common/sanitizer_placement_new.h" |
lib/tsan/tsan_mman.cpp+2-5| ... | ... | @@ -70,10 +70,7 @@ struct GlobalProc { |
| 70 | 70 | Mutex mtx; |
| 71 | 71 | Processor *proc; |
| 72 | 72 | |
| 73 | GlobalProc() | |
| 74 | : mtx(MutexTypeGlobalProc, StatMtxGlobalProc) | |
| 75 | , proc(ProcCreate()) { | |
| 76 | } | |
| 73 | GlobalProc() : mtx(MutexTypeGlobalProc), proc(ProcCreate()) {} | |
| 77 | 74 | }; |
| 78 | 75 | |
| 79 | 76 | static char global_proc_placeholder[sizeof(GlobalProc)] ALIGNED(64); |
| ... | ... | @@ -145,7 +142,7 @@ void AllocatorPrintStats() { |
| 145 | 142 | |
| 146 | 143 | static void SignalUnsafeCall(ThreadState *thr, uptr pc) { |
| 147 | 144 | if (atomic_load_relaxed(&thr->in_signal_handler) == 0 || |
| 148 | !flags()->report_signal_unsafe) | |
| 145 | !ShouldReport(thr, ReportTypeSignalUnsafe)) | |
| 149 | 146 | return; |
| 150 | 147 | VarSizeStackTrace stack; |
| 151 | 148 | ObtainCurrentStack(thr, pc, &stack); |
lib/tsan/tsan_mutex.cpp deleted-289| ... | ... | @@ -1,289 +0,0 @@ |
| 1 | //===-- tsan_mutex.cpp ----------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is a part of ThreadSanitizer (TSan), a race detector. | |
| 10 | // | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | #include "sanitizer_common/sanitizer_libc.h" | |
| 13 | #include "tsan_mutex.h" | |
| 14 | #include "tsan_platform.h" | |
| 15 | #include "tsan_rtl.h" | |
| 16 | ||
| 17 | namespace __tsan { | |
| 18 | ||
| 19 | // Simple reader-writer spin-mutex. Optimized for not-so-contended case. | |
| 20 | // Readers have preference, can possibly starvate writers. | |
| 21 | ||
| 22 | // The table fixes what mutexes can be locked under what mutexes. | |
| 23 | // E.g. if the row for MutexTypeThreads contains MutexTypeReport, | |
| 24 | // then Report mutex can be locked while under Threads mutex. | |
| 25 | // The leaf mutexes can be locked under any other mutexes. | |
| 26 | // Recursive locking is not supported. | |
| 27 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 28 | const MutexType MutexTypeLeaf = (MutexType)-1; | |
| 29 | static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = { | |
| 30 | /*0 MutexTypeInvalid*/ {}, | |
| 31 | /*1 MutexTypeTrace*/ {MutexTypeLeaf}, | |
| 32 | /*2 MutexTypeThreads*/ {MutexTypeReport}, | |
| 33 | /*3 MutexTypeReport*/ {MutexTypeSyncVar, | |
| 34 | MutexTypeMBlock, MutexTypeJavaMBlock}, | |
| 35 | /*4 MutexTypeSyncVar*/ {MutexTypeDDetector}, | |
| 36 | /*5 MutexTypeSyncTab*/ {}, // unused | |
| 37 | /*6 MutexTypeSlab*/ {MutexTypeLeaf}, | |
| 38 | /*7 MutexTypeAnnotations*/ {}, | |
| 39 | /*8 MutexTypeAtExit*/ {MutexTypeSyncVar}, | |
| 40 | /*9 MutexTypeMBlock*/ {MutexTypeSyncVar}, | |
| 41 | /*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar}, | |
| 42 | /*11 MutexTypeDDetector*/ {}, | |
| 43 | /*12 MutexTypeFired*/ {MutexTypeLeaf}, | |
| 44 | /*13 MutexTypeRacy*/ {MutexTypeLeaf}, | |
| 45 | /*14 MutexTypeGlobalProc*/ {}, | |
| 46 | }; | |
| 47 | ||
| 48 | static bool CanLockAdj[MutexTypeCount][MutexTypeCount]; | |
| 49 | #endif | |
| 50 | ||
| 51 | void InitializeMutex() { | |
| 52 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 53 | // Build the "can lock" adjacency matrix. | |
| 54 | // If [i][j]==true, then one can lock mutex j while under mutex i. | |
| 55 | const int N = MutexTypeCount; | |
| 56 | int cnt[N] = {}; | |
| 57 | bool leaf[N] = {}; | |
| 58 | for (int i = 1; i < N; i++) { | |
| 59 | for (int j = 0; j < N; j++) { | |
| 60 | MutexType z = CanLockTab[i][j]; | |
| 61 | if (z == MutexTypeInvalid) | |
| 62 | continue; | |
| 63 | if (z == MutexTypeLeaf) { | |
| 64 | CHECK(!leaf[i]); | |
| 65 | leaf[i] = true; | |
| 66 | continue; | |
| 67 | } | |
| 68 | CHECK(!CanLockAdj[i][(int)z]); | |
| 69 | CanLockAdj[i][(int)z] = true; | |
| 70 | cnt[i]++; | |
| 71 | } | |
| 72 | } | |
| 73 | for (int i = 0; i < N; i++) { | |
| 74 | CHECK(!leaf[i] || cnt[i] == 0); | |
| 75 | } | |
| 76 | // Add leaf mutexes. | |
| 77 | for (int i = 0; i < N; i++) { | |
| 78 | if (!leaf[i]) | |
| 79 | continue; | |
| 80 | for (int j = 0; j < N; j++) { | |
| 81 | if (i == j || leaf[j] || j == MutexTypeInvalid) | |
| 82 | continue; | |
| 83 | CHECK(!CanLockAdj[j][i]); | |
| 84 | CanLockAdj[j][i] = true; | |
| 85 | } | |
| 86 | } | |
| 87 | // Build the transitive closure. | |
| 88 | bool CanLockAdj2[MutexTypeCount][MutexTypeCount]; | |
| 89 | for (int i = 0; i < N; i++) { | |
| 90 | for (int j = 0; j < N; j++) { | |
| 91 | CanLockAdj2[i][j] = CanLockAdj[i][j]; | |
| 92 | } | |
| 93 | } | |
| 94 | for (int k = 0; k < N; k++) { | |
| 95 | for (int i = 0; i < N; i++) { | |
| 96 | for (int j = 0; j < N; j++) { | |
| 97 | if (CanLockAdj2[i][k] && CanLockAdj2[k][j]) { | |
| 98 | CanLockAdj2[i][j] = true; | |
| 99 | } | |
| 100 | } | |
| 101 | } | |
| 102 | } | |
| 103 | #if 0 | |
| 104 | Printf("Can lock graph:\n"); | |
| 105 | for (int i = 0; i < N; i++) { | |
| 106 | for (int j = 0; j < N; j++) { | |
| 107 | Printf("%d ", CanLockAdj[i][j]); | |
| 108 | } | |
| 109 | Printf("\n"); | |
| 110 | } | |
| 111 | Printf("Can lock graph closure:\n"); | |
| 112 | for (int i = 0; i < N; i++) { | |
| 113 | for (int j = 0; j < N; j++) { | |
| 114 | Printf("%d ", CanLockAdj2[i][j]); | |
| 115 | } | |
| 116 | Printf("\n"); | |
| 117 | } | |
| 118 | #endif | |
| 119 | // Verify that the graph is acyclic. | |
| 120 | for (int i = 0; i < N; i++) { | |
| 121 | if (CanLockAdj2[i][i]) { | |
| 122 | Printf("Mutex %d participates in a cycle\n", i); | |
| 123 | Die(); | |
| 124 | } | |
| 125 | } | |
| 126 | #endif | |
| 127 | } | |
| 128 | ||
| 129 | InternalDeadlockDetector::InternalDeadlockDetector() { | |
| 130 | // Rely on zero initialization because some mutexes can be locked before ctor. | |
| 131 | } | |
| 132 | ||
| 133 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 134 | void InternalDeadlockDetector::Lock(MutexType t) { | |
| 135 | // Printf("LOCK %d @%zu\n", t, seq_ + 1); | |
| 136 | CHECK_GT(t, MutexTypeInvalid); | |
| 137 | CHECK_LT(t, MutexTypeCount); | |
| 138 | u64 max_seq = 0; | |
| 139 | u64 max_idx = MutexTypeInvalid; | |
| 140 | for (int i = 0; i != MutexTypeCount; i++) { | |
| 141 | if (locked_[i] == 0) | |
| 142 | continue; | |
| 143 | CHECK_NE(locked_[i], max_seq); | |
| 144 | if (max_seq < locked_[i]) { | |
| 145 | max_seq = locked_[i]; | |
| 146 | max_idx = i; | |
| 147 | } | |
| 148 | } | |
| 149 | locked_[t] = ++seq_; | |
| 150 | if (max_idx == MutexTypeInvalid) | |
| 151 | return; | |
| 152 | // Printf(" last %d @%zu\n", max_idx, max_seq); | |
| 153 | if (!CanLockAdj[max_idx][t]) { | |
| 154 | Printf("ThreadSanitizer: internal deadlock detected\n"); | |
| 155 | Printf("ThreadSanitizer: can't lock %d while under %zu\n", | |
| 156 | t, (uptr)max_idx); | |
| 157 | CHECK(0); | |
| 158 | } | |
| 159 | } | |
| 160 | ||
| 161 | void InternalDeadlockDetector::Unlock(MutexType t) { | |
| 162 | // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]); | |
| 163 | CHECK(locked_[t]); | |
| 164 | locked_[t] = 0; | |
| 165 | } | |
| 166 | ||
| 167 | void InternalDeadlockDetector::CheckNoLocks() { | |
| 168 | for (int i = 0; i != MutexTypeCount; i++) { | |
| 169 | CHECK_EQ(locked_[i], 0); | |
| 170 | } | |
| 171 | } | |
| 172 | #endif | |
| 173 | ||
| 174 | void CheckNoLocks(ThreadState *thr) { | |
| 175 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 176 | thr->internal_deadlock_detector.CheckNoLocks(); | |
| 177 | #endif | |
| 178 | } | |
| 179 | ||
| 180 | const uptr kUnlocked = 0; | |
| 181 | const uptr kWriteLock = 1; | |
| 182 | const uptr kReadLock = 2; | |
| 183 | ||
| 184 | class Backoff { | |
| 185 | public: | |
| 186 | Backoff() | |
| 187 | : iter_() { | |
| 188 | } | |
| 189 | ||
| 190 | bool Do() { | |
| 191 | if (iter_++ < kActiveSpinIters) | |
| 192 | proc_yield(kActiveSpinCnt); | |
| 193 | else | |
| 194 | internal_sched_yield(); | |
| 195 | return true; | |
| 196 | } | |
| 197 | ||
| 198 | u64 Contention() const { | |
| 199 | u64 active = iter_ % kActiveSpinIters; | |
| 200 | u64 passive = iter_ - active; | |
| 201 | return active + 10 * passive; | |
| 202 | } | |
| 203 | ||
| 204 | private: | |
| 205 | int iter_; | |
| 206 | static const int kActiveSpinIters = 10; | |
| 207 | static const int kActiveSpinCnt = 20; | |
| 208 | }; | |
| 209 | ||
| 210 | Mutex::Mutex(MutexType type, StatType stat_type) { | |
| 211 | CHECK_GT(type, MutexTypeInvalid); | |
| 212 | CHECK_LT(type, MutexTypeCount); | |
| 213 | #if SANITIZER_DEBUG | |
| 214 | type_ = type; | |
| 215 | #endif | |
| 216 | #if TSAN_COLLECT_STATS | |
| 217 | stat_type_ = stat_type; | |
| 218 | #endif | |
| 219 | atomic_store(&state_, kUnlocked, memory_order_relaxed); | |
| 220 | } | |
| 221 | ||
| 222 | Mutex::~Mutex() { | |
| 223 | CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked); | |
| 224 | } | |
| 225 | ||
| 226 | void Mutex::Lock() { | |
| 227 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 228 | cur_thread()->internal_deadlock_detector.Lock(type_); | |
| 229 | #endif | |
| 230 | uptr cmp = kUnlocked; | |
| 231 | if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock, | |
| 232 | memory_order_acquire)) | |
| 233 | return; | |
| 234 | for (Backoff backoff; backoff.Do();) { | |
| 235 | if (atomic_load(&state_, memory_order_relaxed) == kUnlocked) { | |
| 236 | cmp = kUnlocked; | |
| 237 | if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock, | |
| 238 | memory_order_acquire)) { | |
| 239 | #if TSAN_COLLECT_STATS && !SANITIZER_GO | |
| 240 | StatInc(cur_thread(), stat_type_, backoff.Contention()); | |
| 241 | #endif | |
| 242 | return; | |
| 243 | } | |
| 244 | } | |
| 245 | } | |
| 246 | } | |
| 247 | ||
| 248 | void Mutex::Unlock() { | |
| 249 | uptr prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release); | |
| 250 | (void)prev; | |
| 251 | DCHECK_NE(prev & kWriteLock, 0); | |
| 252 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 253 | cur_thread()->internal_deadlock_detector.Unlock(type_); | |
| 254 | #endif | |
| 255 | } | |
| 256 | ||
| 257 | void Mutex::ReadLock() { | |
| 258 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 259 | cur_thread()->internal_deadlock_detector.Lock(type_); | |
| 260 | #endif | |
| 261 | uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire); | |
| 262 | if ((prev & kWriteLock) == 0) | |
| 263 | return; | |
| 264 | for (Backoff backoff; backoff.Do();) { | |
| 265 | prev = atomic_load(&state_, memory_order_acquire); | |
| 266 | if ((prev & kWriteLock) == 0) { | |
| 267 | #if TSAN_COLLECT_STATS && !SANITIZER_GO | |
| 268 | StatInc(cur_thread(), stat_type_, backoff.Contention()); | |
| 269 | #endif | |
| 270 | return; | |
| 271 | } | |
| 272 | } | |
| 273 | } | |
| 274 | ||
| 275 | void Mutex::ReadUnlock() { | |
| 276 | uptr prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release); | |
| 277 | (void)prev; | |
| 278 | DCHECK_EQ(prev & kWriteLock, 0); | |
| 279 | DCHECK_GT(prev & ~kWriteLock, 0); | |
| 280 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 281 | cur_thread()->internal_deadlock_detector.Unlock(type_); | |
| 282 | #endif | |
| 283 | } | |
| 284 | ||
| 285 | void Mutex::CheckLocked() { | |
| 286 | CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0); | |
| 287 | } | |
| 288 | ||
| 289 | } // namespace __tsan |
lib/tsan/tsan_mutex.h deleted-90| ... | ... | @@ -1,90 +0,0 @@ |
| 1 | //===-- tsan_mutex.h --------------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is a part of ThreadSanitizer (TSan), a race detector. | |
| 10 | // | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | #ifndef TSAN_MUTEX_H | |
| 13 | #define TSAN_MUTEX_H | |
| 14 | ||
| 15 | #include "sanitizer_common/sanitizer_atomic.h" | |
| 16 | #include "sanitizer_common/sanitizer_mutex.h" | |
| 17 | #include "tsan_defs.h" | |
| 18 | ||
| 19 | namespace __tsan { | |
| 20 | ||
| 21 | enum MutexType { | |
| 22 | MutexTypeInvalid, | |
| 23 | MutexTypeTrace, | |
| 24 | MutexTypeThreads, | |
| 25 | MutexTypeReport, | |
| 26 | MutexTypeSyncVar, | |
| 27 | MutexTypeSyncTab, | |
| 28 | MutexTypeSlab, | |
| 29 | MutexTypeAnnotations, | |
| 30 | MutexTypeAtExit, | |
| 31 | MutexTypeMBlock, | |
| 32 | MutexTypeJavaMBlock, | |
| 33 | MutexTypeDDetector, | |
| 34 | MutexTypeFired, | |
| 35 | MutexTypeRacy, | |
| 36 | MutexTypeGlobalProc, | |
| 37 | ||
| 38 | // This must be the last. | |
| 39 | MutexTypeCount | |
| 40 | }; | |
| 41 | ||
| 42 | class Mutex { | |
| 43 | public: | |
| 44 | explicit Mutex(MutexType type, StatType stat_type); | |
| 45 | ~Mutex(); | |
| 46 | ||
| 47 | void Lock(); | |
| 48 | void Unlock(); | |
| 49 | ||
| 50 | void ReadLock(); | |
| 51 | void ReadUnlock(); | |
| 52 | ||
| 53 | void CheckLocked(); | |
| 54 | ||
| 55 | private: | |
| 56 | atomic_uintptr_t state_; | |
| 57 | #if SANITIZER_DEBUG | |
| 58 | MutexType type_; | |
| 59 | #endif | |
| 60 | #if TSAN_COLLECT_STATS | |
| 61 | StatType stat_type_; | |
| 62 | #endif | |
| 63 | ||
| 64 | Mutex(const Mutex&); | |
| 65 | void operator = (const Mutex&); | |
| 66 | }; | |
| 67 | ||
| 68 | typedef GenericScopedLock<Mutex> Lock; | |
| 69 | typedef GenericScopedReadLock<Mutex> ReadLock; | |
| 70 | ||
| 71 | class InternalDeadlockDetector { | |
| 72 | public: | |
| 73 | InternalDeadlockDetector(); | |
| 74 | void Lock(MutexType t); | |
| 75 | void Unlock(MutexType t); | |
| 76 | void CheckNoLocks(); | |
| 77 | private: | |
| 78 | u64 seq_; | |
| 79 | u64 locked_[MutexTypeCount]; | |
| 80 | }; | |
| 81 | ||
| 82 | void InitializeMutex(); | |
| 83 | ||
| 84 | // Checks that the current thread does not hold any runtime locks | |
| 85 | // (e.g. when returning from an interceptor). | |
| 86 | void CheckNoLocks(ThreadState *thr); | |
| 87 | ||
| 88 | } // namespace __tsan | |
| 89 | ||
| 90 | #endif // TSAN_MUTEX_H |
lib/tsan/tsan_platform.h+191-8| ... | ... | @@ -23,9 +23,21 @@ |
| 23 | 23 | |
| 24 | 24 | namespace __tsan { |
| 25 | 25 | |
| 26 | #if defined(__x86_64__) | |
| 27 | #define HAS_48_BIT_ADDRESS_SPACE 1 | |
| 28 | #elif SANITIZER_IOSSIM // arm64 iOS simulators (order of #if matters) | |
| 29 | #define HAS_48_BIT_ADDRESS_SPACE 1 | |
| 30 | #elif SANITIZER_IOS // arm64 iOS devices (order of #if matters) | |
| 31 | #define HAS_48_BIT_ADDRESS_SPACE 0 | |
| 32 | #elif SANITIZER_MAC // arm64 macOS (order of #if matters) | |
| 33 | #define HAS_48_BIT_ADDRESS_SPACE 1 | |
| 34 | #else | |
| 35 | #define HAS_48_BIT_ADDRESS_SPACE 0 | |
| 36 | #endif | |
| 37 | ||
| 26 | 38 | #if !SANITIZER_GO |
| 27 | 39 | |
| 28 | #if defined(__x86_64__) | |
| 40 | #if HAS_48_BIT_ADDRESS_SPACE | |
| 29 | 41 | /* |
| 30 | 42 | C/C++ on linux/x86_64 and freebsd/x86_64 |
| 31 | 43 | 0000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB) |
| ... | ... | @@ -93,7 +105,7 @@ fe00 0000 00 - ff00 0000 00: heap (4 GB) |
| 93 | 105 | ff00 0000 00 - ff80 0000 00: - (2 GB) |
| 94 | 106 | ff80 0000 00 - ffff ffff ff: modules and main thread stack (<2 GB) |
| 95 | 107 | */ |
| 96 | struct Mapping { | |
| 108 | struct Mapping40 { | |
| 97 | 109 | static const uptr kMetaShadowBeg = 0x4000000000ull; |
| 98 | 110 | static const uptr kMetaShadowEnd = 0x5000000000ull; |
| 99 | 111 | static const uptr kTraceMemBeg = 0xb000000000ull; |
| ... | ... | @@ -114,6 +126,7 @@ struct Mapping { |
| 114 | 126 | }; |
| 115 | 127 | |
| 116 | 128 | #define TSAN_MID_APP_RANGE 1 |
| 129 | #define TSAN_RUNTIME_VMA 1 | |
| 117 | 130 | #elif defined(__aarch64__) && defined(__APPLE__) |
| 118 | 131 | /* |
| 119 | 132 | C/C++ on Darwin/iOS/ARM64 (36-bit VMA, 64 GB VM) |
| ... | ... | @@ -146,7 +159,7 @@ struct Mapping { |
| 146 | 159 | static const uptr kVdsoBeg = 0x7000000000000000ull; |
| 147 | 160 | }; |
| 148 | 161 | |
| 149 | #elif defined(__aarch64__) | |
| 162 | #elif defined(__aarch64__) && !defined(__APPLE__) | |
| 150 | 163 | // AArch64 supports multiple VMA which leads to multiple address transformation |
| 151 | 164 | // functions. To support these multiple VMAS transformations and mappings TSAN |
| 152 | 165 | // runtime for AArch64 uses an external memory read (vmaSize) to select which |
| ... | ... | @@ -352,9 +365,41 @@ struct Mapping47 { |
| 352 | 365 | |
| 353 | 366 | // Indicates the runtime will define the memory regions at runtime. |
| 354 | 367 | #define TSAN_RUNTIME_VMA 1 |
| 368 | #elif defined(__s390x__) | |
| 369 | /* | |
| 370 | C/C++ on linux/s390x | |
| 371 | While the kernel provides a 64-bit address space, we have to restrict ourselves | |
| 372 | to 48 bits due to how e.g. SyncVar::GetId() works. | |
| 373 | 0000 0000 1000 - 0e00 0000 0000: binary, modules, stacks - 14 TiB | |
| 374 | 0e00 0000 0000 - 4000 0000 0000: - | |
| 375 | 4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app) | |
| 376 | 8000 0000 0000 - 9000 0000 0000: - | |
| 377 | 9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app) | |
| 378 | 9800 0000 0000 - a000 0000 0000: - | |
| 379 | a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads) | |
| 380 | b000 0000 0000 - be00 0000 0000: - | |
| 381 | be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator) | |
| 382 | */ | |
| 383 | struct Mapping { | |
| 384 | static const uptr kMetaShadowBeg = 0x900000000000ull; | |
| 385 | static const uptr kMetaShadowEnd = 0x980000000000ull; | |
| 386 | static const uptr kTraceMemBeg = 0xa00000000000ull; | |
| 387 | static const uptr kTraceMemEnd = 0xb00000000000ull; | |
| 388 | static const uptr kShadowBeg = 0x400000000000ull; | |
| 389 | static const uptr kShadowEnd = 0x800000000000ull; | |
| 390 | static const uptr kHeapMemBeg = 0xbe0000000000ull; | |
| 391 | static const uptr kHeapMemEnd = 0xc00000000000ull; | |
| 392 | static const uptr kLoAppMemBeg = 0x000000001000ull; | |
| 393 | static const uptr kLoAppMemEnd = 0x0e0000000000ull; | |
| 394 | static const uptr kHiAppMemBeg = 0xc00000004000ull; | |
| 395 | static const uptr kHiAppMemEnd = 0xc00000004000ull; | |
| 396 | static const uptr kAppMemMsk = 0xb00000000000ull; | |
| 397 | static const uptr kAppMemXor = 0x100000000000ull; | |
| 398 | static const uptr kVdsoBeg = 0xfffffffff000ull; | |
| 399 | }; | |
| 355 | 400 | #endif |
| 356 | 401 | |
| 357 | #elif SANITIZER_GO && !SANITIZER_WINDOWS && defined(__x86_64__) | |
| 402 | #elif SANITIZER_GO && !SANITIZER_WINDOWS && HAS_48_BIT_ADDRESS_SPACE | |
| 358 | 403 | |
| 359 | 404 | /* Go on linux, darwin and freebsd on x86_64 |
| 360 | 405 | 0000 0000 1000 - 0000 1000 0000: executable |
| ... | ... | @@ -461,7 +506,7 @@ struct Mapping47 { |
| 461 | 506 | |
| 462 | 507 | #elif SANITIZER_GO && defined(__aarch64__) |
| 463 | 508 | |
| 464 | /* Go on linux/aarch64 (48-bit VMA) | |
| 509 | /* Go on linux/aarch64 (48-bit VMA) and darwin/aarch64 (47-bit VMA) | |
| 465 | 510 | 0000 0000 1000 - 0000 1000 0000: executable |
| 466 | 511 | 0000 1000 0000 - 00c0 0000 0000: - |
| 467 | 512 | 00c0 0000 0000 - 00e0 0000 0000: heap |
| ... | ... | @@ -488,6 +533,55 @@ struct Mapping { |
| 488 | 533 | // Indicates the runtime will define the memory regions at runtime. |
| 489 | 534 | #define TSAN_RUNTIME_VMA 1 |
| 490 | 535 | |
| 536 | #elif SANITIZER_GO && defined(__mips64) | |
| 537 | /* | |
| 538 | Go on linux/mips64 (47-bit VMA) | |
| 539 | 0000 0000 1000 - 0000 1000 0000: executable | |
| 540 | 0000 1000 0000 - 00c0 0000 0000: - | |
| 541 | 00c0 0000 0000 - 00e0 0000 0000: heap | |
| 542 | 00e0 0000 0000 - 2000 0000 0000: - | |
| 543 | 2000 0000 0000 - 3000 0000 0000: shadow | |
| 544 | 3000 0000 0000 - 3000 0000 0000: - | |
| 545 | 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) | |
| 546 | 4000 0000 0000 - 6000 0000 0000: - | |
| 547 | 6000 0000 0000 - 6200 0000 0000: traces | |
| 548 | 6200 0000 0000 - 8000 0000 0000: - | |
| 549 | */ | |
| 550 | struct Mapping47 { | |
| 551 | static const uptr kMetaShadowBeg = 0x300000000000ull; | |
| 552 | static const uptr kMetaShadowEnd = 0x400000000000ull; | |
| 553 | static const uptr kTraceMemBeg = 0x600000000000ull; | |
| 554 | static const uptr kTraceMemEnd = 0x620000000000ull; | |
| 555 | static const uptr kShadowBeg = 0x200000000000ull; | |
| 556 | static const uptr kShadowEnd = 0x300000000000ull; | |
| 557 | static const uptr kAppMemBeg = 0x000000001000ull; | |
| 558 | static const uptr kAppMemEnd = 0x00e000000000ull; | |
| 559 | }; | |
| 560 | ||
| 561 | #define TSAN_RUNTIME_VMA 1 | |
| 562 | ||
| 563 | #elif SANITIZER_GO && defined(__s390x__) | |
| 564 | /* | |
| 565 | Go on linux/s390x | |
| 566 | 0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB | |
| 567 | 1000 0000 0000 - 4000 0000 0000: - | |
| 568 | 4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app) | |
| 569 | 8000 0000 0000 - 9000 0000 0000: - | |
| 570 | 9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app) | |
| 571 | 9800 0000 0000 - a000 0000 0000: - | |
| 572 | a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads) | |
| 573 | */ | |
| 574 | struct Mapping { | |
| 575 | static const uptr kMetaShadowBeg = 0x900000000000ull; | |
| 576 | static const uptr kMetaShadowEnd = 0x980000000000ull; | |
| 577 | static const uptr kTraceMemBeg = 0xa00000000000ull; | |
| 578 | static const uptr kTraceMemEnd = 0xb00000000000ull; | |
| 579 | static const uptr kShadowBeg = 0x400000000000ull; | |
| 580 | static const uptr kShadowEnd = 0x800000000000ull; | |
| 581 | static const uptr kAppMemBeg = 0x000000001000ull; | |
| 582 | static const uptr kAppMemEnd = 0x100000000000ull; | |
| 583 | }; | |
| 584 | ||
| 491 | 585 | #else |
| 492 | 586 | # error "Unknown platform" |
| 493 | 587 | #endif |
| ... | ... | @@ -568,6 +662,16 @@ uptr MappingArchImpl(void) { |
| 568 | 662 | } |
| 569 | 663 | DCHECK(0); |
| 570 | 664 | return 0; |
| 665 | #elif defined(__mips64) | |
| 666 | switch (vmaSize) { | |
| 667 | #if !SANITIZER_GO | |
| 668 | case 40: return MappingImpl<Mapping40, Type>(); | |
| 669 | #else | |
| 670 | case 47: return MappingImpl<Mapping47, Type>(); | |
| 671 | #endif | |
| 672 | } | |
| 673 | DCHECK(0); | |
| 674 | return 0; | |
| 571 | 675 | #else |
| 572 | 676 | return MappingImpl<Mapping, Type>(); |
| 573 | 677 | #endif |
| ... | ... | @@ -725,6 +829,16 @@ bool IsAppMem(uptr mem) { |
| 725 | 829 | } |
| 726 | 830 | DCHECK(0); |
| 727 | 831 | return false; |
| 832 | #elif defined(__mips64) | |
| 833 | switch (vmaSize) { | |
| 834 | #if !SANITIZER_GO | |
| 835 | case 40: return IsAppMemImpl<Mapping40>(mem); | |
| 836 | #else | |
| 837 | case 47: return IsAppMemImpl<Mapping47>(mem); | |
| 838 | #endif | |
| 839 | } | |
| 840 | DCHECK(0); | |
| 841 | return false; | |
| 728 | 842 | #else |
| 729 | 843 | return IsAppMemImpl<Mapping>(mem); |
| 730 | 844 | #endif |
| ... | ... | @@ -756,6 +870,16 @@ bool IsShadowMem(uptr mem) { |
| 756 | 870 | } |
| 757 | 871 | DCHECK(0); |
| 758 | 872 | return false; |
| 873 | #elif defined(__mips64) | |
| 874 | switch (vmaSize) { | |
| 875 | #if !SANITIZER_GO | |
| 876 | case 40: return IsShadowMemImpl<Mapping40>(mem); | |
| 877 | #else | |
| 878 | case 47: return IsShadowMemImpl<Mapping47>(mem); | |
| 879 | #endif | |
| 880 | } | |
| 881 | DCHECK(0); | |
| 882 | return false; | |
| 759 | 883 | #else |
| 760 | 884 | return IsShadowMemImpl<Mapping>(mem); |
| 761 | 885 | #endif |
| ... | ... | @@ -787,6 +911,16 @@ bool IsMetaMem(uptr mem) { |
| 787 | 911 | } |
| 788 | 912 | DCHECK(0); |
| 789 | 913 | return false; |
| 914 | #elif defined(__mips64) | |
| 915 | switch (vmaSize) { | |
| 916 | #if !SANITIZER_GO | |
| 917 | case 40: return IsMetaMemImpl<Mapping40>(mem); | |
| 918 | #else | |
| 919 | case 47: return IsMetaMemImpl<Mapping47>(mem); | |
| 920 | #endif | |
| 921 | } | |
| 922 | DCHECK(0); | |
| 923 | return false; | |
| 790 | 924 | #else |
| 791 | 925 | return IsMetaMemImpl<Mapping>(mem); |
| 792 | 926 | #endif |
| ... | ... | @@ -828,6 +962,16 @@ uptr MemToShadow(uptr x) { |
| 828 | 962 | } |
| 829 | 963 | DCHECK(0); |
| 830 | 964 | return 0; |
| 965 | #elif defined(__mips64) | |
| 966 | switch (vmaSize) { | |
| 967 | #if !SANITIZER_GO | |
| 968 | case 40: return MemToShadowImpl<Mapping40>(x); | |
| 969 | #else | |
| 970 | case 47: return MemToShadowImpl<Mapping47>(x); | |
| 971 | #endif | |
| 972 | } | |
| 973 | DCHECK(0); | |
| 974 | return 0; | |
| 831 | 975 | #else |
| 832 | 976 | return MemToShadowImpl<Mapping>(x); |
| 833 | 977 | #endif |
| ... | ... | @@ -871,6 +1015,16 @@ u32 *MemToMeta(uptr x) { |
| 871 | 1015 | } |
| 872 | 1016 | DCHECK(0); |
| 873 | 1017 | return 0; |
| 1018 | #elif defined(__mips64) | |
| 1019 | switch (vmaSize) { | |
| 1020 | #if !SANITIZER_GO | |
| 1021 | case 40: return MemToMetaImpl<Mapping40>(x); | |
| 1022 | #else | |
| 1023 | case 47: return MemToMetaImpl<Mapping47>(x); | |
| 1024 | #endif | |
| 1025 | } | |
| 1026 | DCHECK(0); | |
| 1027 | return 0; | |
| 874 | 1028 | #else |
| 875 | 1029 | return MemToMetaImpl<Mapping>(x); |
| 876 | 1030 | #endif |
| ... | ... | @@ -927,6 +1081,16 @@ uptr ShadowToMem(uptr s) { |
| 927 | 1081 | } |
| 928 | 1082 | DCHECK(0); |
| 929 | 1083 | return 0; |
| 1084 | #elif defined(__mips64) | |
| 1085 | switch (vmaSize) { | |
| 1086 | #if !SANITIZER_GO | |
| 1087 | case 40: return ShadowToMemImpl<Mapping40>(s); | |
| 1088 | #else | |
| 1089 | case 47: return ShadowToMemImpl<Mapping47>(s); | |
| 1090 | #endif | |
| 1091 | } | |
| 1092 | DCHECK(0); | |
| 1093 | return 0; | |
| 930 | 1094 | #else |
| 931 | 1095 | return ShadowToMemImpl<Mapping>(s); |
| 932 | 1096 | #endif |
| ... | ... | @@ -966,6 +1130,16 @@ uptr GetThreadTrace(int tid) { |
| 966 | 1130 | } |
| 967 | 1131 | DCHECK(0); |
| 968 | 1132 | return 0; |
| 1133 | #elif defined(__mips64) | |
| 1134 | switch (vmaSize) { | |
| 1135 | #if !SANITIZER_GO | |
| 1136 | case 40: return GetThreadTraceImpl<Mapping40>(tid); | |
| 1137 | #else | |
| 1138 | case 47: return GetThreadTraceImpl<Mapping47>(tid); | |
| 1139 | #endif | |
| 1140 | } | |
| 1141 | DCHECK(0); | |
| 1142 | return 0; | |
| 969 | 1143 | #else |
| 970 | 1144 | return GetThreadTraceImpl<Mapping>(tid); |
| 971 | 1145 | #endif |
| ... | ... | @@ -1000,6 +1174,16 @@ uptr GetThreadTraceHeader(int tid) { |
| 1000 | 1174 | } |
| 1001 | 1175 | DCHECK(0); |
| 1002 | 1176 | return 0; |
| 1177 | #elif defined(__mips64) | |
| 1178 | switch (vmaSize) { | |
| 1179 | #if !SANITIZER_GO | |
| 1180 | case 40: return GetThreadTraceHeaderImpl<Mapping40>(tid); | |
| 1181 | #else | |
| 1182 | case 47: return GetThreadTraceHeaderImpl<Mapping47>(tid); | |
| 1183 | #endif | |
| 1184 | } | |
| 1185 | DCHECK(0); | |
| 1186 | return 0; | |
| 1003 | 1187 | #else |
| 1004 | 1188 | return GetThreadTraceHeaderImpl<Mapping>(tid); |
| 1005 | 1189 | #endif |
| ... | ... | @@ -1016,9 +1200,8 @@ int ExtractRecvmsgFDs(void *msg, int *fds, int nfd); |
| 1016 | 1200 | uptr ExtractLongJmpSp(uptr *env); |
| 1017 | 1201 | void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size); |
| 1018 | 1202 | |
| 1019 | int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, | |
| 1020 | void *abstime), void *c, void *m, void *abstime, | |
| 1021 | void(*cleanup)(void *arg), void *arg); | |
| 1203 | int call_pthread_cancel_with_cleanup(int (*fn)(void *arg), | |
| 1204 | void (*cleanup)(void *arg), void *arg); | |
| 1022 | 1205 | |
| 1023 | 1206 | void DestroyThreadState(); |
| 1024 | 1207 | void PlatformCleanUpThreadState(ThreadState *thr); |
lib/tsan/tsan_platform_linux.cpp+33-13| ... | ... | @@ -12,14 +12,12 @@ |
| 12 | 12 | //===----------------------------------------------------------------------===// |
| 13 | 13 | |
| 14 | 14 | #include "sanitizer_common/sanitizer_platform.h" |
| 15 | #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ | |
| 16 | SANITIZER_OPENBSD | |
| 15 | #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD | |
| 17 | 16 | |
| 18 | 17 | #include "sanitizer_common/sanitizer_common.h" |
| 19 | 18 | #include "sanitizer_common/sanitizer_libc.h" |
| 20 | 19 | #include "sanitizer_common/sanitizer_linux.h" |
| 21 | 20 | #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" |
| 22 | #include "sanitizer_common/sanitizer_platform_limits_openbsd.h" | |
| 23 | 21 | #include "sanitizer_common/sanitizer_platform_limits_posix.h" |
| 24 | 22 | #include "sanitizer_common/sanitizer_posix.h" |
| 25 | 23 | #include "sanitizer_common/sanitizer_procmaps.h" |
| ... | ... | @@ -252,6 +250,20 @@ void InitializePlatformEarly() { |
| 252 | 250 | Die(); |
| 253 | 251 | } |
| 254 | 252 | # endif |
| 253 | #elif defined(__mips64) | |
| 254 | # if !SANITIZER_GO | |
| 255 | if (vmaSize != 40) { | |
| 256 | Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); | |
| 257 | Printf("FATAL: Found %zd - Supported 40\n", vmaSize); | |
| 258 | Die(); | |
| 259 | } | |
| 260 | # else | |
| 261 | if (vmaSize != 47) { | |
| 262 | Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); | |
| 263 | Printf("FATAL: Found %zd - Supported 47\n", vmaSize); | |
| 264 | Die(); | |
| 265 | } | |
| 266 | # endif | |
| 255 | 267 | #endif |
| 256 | 268 | #endif |
| 257 | 269 | } |
| ... | ... | @@ -379,22 +391,32 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { |
| 379 | 391 | return mangled_sp ^ xor_key; |
| 380 | 392 | #elif defined(__mips__) |
| 381 | 393 | return mangled_sp; |
| 394 | #elif defined(__s390x__) | |
| 395 | // tcbhead_t.stack_guard | |
| 396 | uptr xor_key = ((uptr *)__builtin_thread_pointer())[5]; | |
| 397 | return mangled_sp ^ xor_key; | |
| 382 | 398 | #else |
| 383 | 399 | #error "Unknown platform" |
| 384 | 400 | #endif |
| 385 | 401 | } |
| 386 | 402 | |
| 387 | #ifdef __powerpc__ | |
| 403 | #if SANITIZER_NETBSD | |
| 404 | # ifdef __x86_64__ | |
| 405 | # define LONG_JMP_SP_ENV_SLOT 6 | |
| 406 | # else | |
| 407 | # error unsupported | |
| 408 | # endif | |
| 409 | #elif defined(__powerpc__) | |
| 388 | 410 | # define LONG_JMP_SP_ENV_SLOT 0 |
| 389 | 411 | #elif SANITIZER_FREEBSD |
| 390 | 412 | # define LONG_JMP_SP_ENV_SLOT 2 |
| 391 | #elif SANITIZER_NETBSD | |
| 392 | # define LONG_JMP_SP_ENV_SLOT 6 | |
| 393 | 413 | #elif SANITIZER_LINUX |
| 394 | 414 | # ifdef __aarch64__ |
| 395 | 415 | # define LONG_JMP_SP_ENV_SLOT 13 |
| 396 | 416 | # elif defined(__mips64) |
| 397 | 417 | # define LONG_JMP_SP_ENV_SLOT 1 |
| 418 | # elif defined(__s390x__) | |
| 419 | # define LONG_JMP_SP_ENV_SLOT 9 | |
| 398 | 420 | # else |
| 399 | 421 | # define LONG_JMP_SP_ENV_SLOT 6 |
| 400 | 422 | # endif |
| ... | ... | @@ -441,14 +463,13 @@ void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { |
| 441 | 463 | |
| 442 | 464 | // Note: this function runs with async signals enabled, |
| 443 | 465 | // so it must not touch any tsan state. |
| 444 | int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, | |
| 445 | void *abstime), void *c, void *m, void *abstime, | |
| 446 | void(*cleanup)(void *arg), void *arg) { | |
| 466 | int call_pthread_cancel_with_cleanup(int (*fn)(void *arg), | |
| 467 | void (*cleanup)(void *arg), void *arg) { | |
| 447 | 468 | // pthread_cleanup_push/pop are hardcore macros mess. |
| 448 | 469 | // We can't intercept nor call them w/o including pthread.h. |
| 449 | 470 | int res; |
| 450 | 471 | pthread_cleanup_push(cleanup, arg); |
| 451 | res = fn(c, m, abstime); | |
| 472 | res = fn(arg); | |
| 452 | 473 | pthread_cleanup_pop(0); |
| 453 | 474 | return res; |
| 454 | 475 | } |
| ... | ... | @@ -482,7 +503,7 @@ ThreadState *cur_thread() { |
| 482 | 503 | dead_thread_state->fast_state.SetIgnoreBit(); |
| 483 | 504 | dead_thread_state->ignore_interceptors = 1; |
| 484 | 505 | dead_thread_state->is_dead = true; |
| 485 | *const_cast<int*>(&dead_thread_state->tid) = -1; | |
| 506 | *const_cast<u32*>(&dead_thread_state->tid) = -1; | |
| 486 | 507 | CHECK_EQ(0, internal_mprotect(dead_thread_state, sizeof(ThreadState), |
| 487 | 508 | PROT_READ)); |
| 488 | 509 | } |
| ... | ... | @@ -513,5 +534,4 @@ void cur_thread_finalize() { |
| 513 | 534 | |
| 514 | 535 | } // namespace __tsan |
| 515 | 536 | |
| 516 | #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || | |
| 517 | // SANITIZER_OPENBSD | |
| 537 | #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD |
lib/tsan/tsan_platform_mac.cpp+4-5| ... | ... | @@ -234,7 +234,7 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread, |
| 234 | 234 | #endif |
| 235 | 235 | |
| 236 | 236 | void InitializePlatformEarly() { |
| 237 | #if defined(__aarch64__) | |
| 237 | #if !SANITIZER_GO && !HAS_48_BIT_ADDRESS_SPACE | |
| 238 | 238 | uptr max_vm = GetMaxUserVirtualAddress() + 1; |
| 239 | 239 | if (max_vm != Mapping::kHiAppMemEnd) { |
| 240 | 240 | Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n", |
| ... | ... | @@ -306,14 +306,13 @@ void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { |
| 306 | 306 | #if !SANITIZER_GO |
| 307 | 307 | // Note: this function runs with async signals enabled, |
| 308 | 308 | // so it must not touch any tsan state. |
| 309 | int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, | |
| 310 | void *abstime), void *c, void *m, void *abstime, | |
| 311 | void(*cleanup)(void *arg), void *arg) { | |
| 309 | int call_pthread_cancel_with_cleanup(int (*fn)(void *arg), | |
| 310 | void (*cleanup)(void *arg), void *arg) { | |
| 312 | 311 | // pthread_cleanup_push/pop are hardcore macros mess. |
| 313 | 312 | // We can't intercept nor call them w/o including pthread.h. |
| 314 | 313 | int res; |
| 315 | 314 | pthread_cleanup_push(cleanup, arg); |
| 316 | res = fn(c, m, abstime); | |
| 315 | res = fn(arg); | |
| 317 | 316 | pthread_cleanup_pop(0); |
| 318 | 317 | return res; |
| 319 | 318 | } |
lib/tsan/tsan_platform_posix.cpp+21-48| ... | ... | @@ -29,10 +29,6 @@ static const char kShadowMemoryMappingHint[] = |
| 29 | 29 | "HINT: if %s is not supported in your environment, you may set " |
| 30 | 30 | "TSAN_OPTIONS=%s=0\n"; |
| 31 | 31 | |
| 32 | static void NoHugePagesInShadow(uptr addr, uptr size) { | |
| 33 | SetShadowRegionHugePageMode(addr, size); | |
| 34 | } | |
| 35 | ||
| 36 | 32 | static void DontDumpShadow(uptr addr, uptr size) { |
| 37 | 33 | if (common_flags()->use_madv_dontdump) |
| 38 | 34 | if (!DontDumpShadowMemory(addr, size)) { |
| ... | ... | @@ -46,7 +42,8 @@ static void DontDumpShadow(uptr addr, uptr size) { |
| 46 | 42 | #if !SANITIZER_GO |
| 47 | 43 | void InitializeShadowMemory() { |
| 48 | 44 | // Map memory shadow. |
| 49 | if (!MmapFixedNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), "shadow")) { | |
| 45 | if (!MmapFixedSuperNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), | |
| 46 | "shadow")) { | |
| 50 | 47 | Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); |
| 51 | 48 | Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); |
| 52 | 49 | Die(); |
| ... | ... | @@ -55,43 +52,6 @@ void InitializeShadowMemory() { |
| 55 | 52 | // Frequently a thread uses only a small part of stack and similarly |
| 56 | 53 | // a program uses a small part of large mmap. On some programs |
| 57 | 54 | // we see 20% memory usage reduction without huge pages for this range. |
| 58 | // FIXME: don't use constants here. | |
| 59 | #if defined(__x86_64__) | |
| 60 | const uptr kMadviseRangeBeg = 0x7f0000000000ull; | |
| 61 | const uptr kMadviseRangeSize = 0x010000000000ull; | |
| 62 | #elif defined(__mips64) | |
| 63 | const uptr kMadviseRangeBeg = 0xff00000000ull; | |
| 64 | const uptr kMadviseRangeSize = 0x0100000000ull; | |
| 65 | #elif defined(__aarch64__) && defined(__APPLE__) | |
| 66 | uptr kMadviseRangeBeg = LoAppMemBeg(); | |
| 67 | uptr kMadviseRangeSize = LoAppMemEnd() - LoAppMemBeg(); | |
| 68 | #elif defined(__aarch64__) | |
| 69 | uptr kMadviseRangeBeg = 0; | |
| 70 | uptr kMadviseRangeSize = 0; | |
| 71 | if (vmaSize == 39) { | |
| 72 | kMadviseRangeBeg = 0x7d00000000ull; | |
| 73 | kMadviseRangeSize = 0x0300000000ull; | |
| 74 | } else if (vmaSize == 42) { | |
| 75 | kMadviseRangeBeg = 0x3f000000000ull; | |
| 76 | kMadviseRangeSize = 0x01000000000ull; | |
| 77 | } else { | |
| 78 | DCHECK(0); | |
| 79 | } | |
| 80 | #elif defined(__powerpc64__) | |
| 81 | uptr kMadviseRangeBeg = 0; | |
| 82 | uptr kMadviseRangeSize = 0; | |
| 83 | if (vmaSize == 44) { | |
| 84 | kMadviseRangeBeg = 0x0f60000000ull; | |
| 85 | kMadviseRangeSize = 0x0010000000ull; | |
| 86 | } else if (vmaSize == 46) { | |
| 87 | kMadviseRangeBeg = 0x3f0000000000ull; | |
| 88 | kMadviseRangeSize = 0x010000000000ull; | |
| 89 | } else { | |
| 90 | DCHECK(0); | |
| 91 | } | |
| 92 | #endif | |
| 93 | NoHugePagesInShadow(MemToShadow(kMadviseRangeBeg), | |
| 94 | kMadviseRangeSize * kShadowMultiplier); | |
| 95 | 55 | DontDumpShadow(ShadowBeg(), ShadowEnd() - ShadowBeg()); |
| 96 | 56 | DPrintf("memory shadow: %zx-%zx (%zuGB)\n", |
| 97 | 57 | ShadowBeg(), ShadowEnd(), |
| ... | ... | @@ -100,12 +60,11 @@ void InitializeShadowMemory() { |
| 100 | 60 | // Map meta shadow. |
| 101 | 61 | const uptr meta = MetaShadowBeg(); |
| 102 | 62 | const uptr meta_size = MetaShadowEnd() - meta; |
| 103 | if (!MmapFixedNoReserve(meta, meta_size, "meta shadow")) { | |
| 63 | if (!MmapFixedSuperNoReserve(meta, meta_size, "meta shadow")) { | |
| 104 | 64 | Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); |
| 105 | 65 | Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); |
| 106 | 66 | Die(); |
| 107 | 67 | } |
| 108 | NoHugePagesInShadow(meta, meta_size); | |
| 109 | 68 | DontDumpShadow(meta, meta_size); |
| 110 | 69 | DPrintf("meta shadow: %zx-%zx (%zuGB)\n", |
| 111 | 70 | meta, meta + meta_size, meta_size >> 30); |
| ... | ... | @@ -113,11 +72,15 @@ void InitializeShadowMemory() { |
| 113 | 72 | InitializeShadowMemoryPlatform(); |
| 114 | 73 | } |
| 115 | 74 | |
| 116 | static void ProtectRange(uptr beg, uptr end) { | |
| 75 | static bool TryProtectRange(uptr beg, uptr end) { | |
| 117 | 76 | CHECK_LE(beg, end); |
| 118 | 77 | if (beg == end) |
| 119 | return; | |
| 120 | if (beg != (uptr)MmapFixedNoAccess(beg, end - beg)) { | |
| 78 | return true; | |
| 79 | return beg == (uptr)MmapFixedNoAccess(beg, end - beg); | |
| 80 | } | |
| 81 | ||
| 82 | static void ProtectRange(uptr beg, uptr end) { | |
| 83 | if (!TryProtectRange(beg, end)) { | |
| 121 | 84 | Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); |
| 122 | 85 | Printf("FATAL: Make sure you are not using unlimited stack\n"); |
| 123 | 86 | Die(); |
| ... | ... | @@ -140,7 +103,7 @@ void CheckAndProtect() { |
| 140 | 103 | Die(); |
| 141 | 104 | } |
| 142 | 105 | |
| 143 | #if defined(__aarch64__) && defined(__APPLE__) | |
| 106 | #if defined(__aarch64__) && defined(__APPLE__) && !HAS_48_BIT_ADDRESS_SPACE | |
| 144 | 107 | ProtectRange(HeapMemEnd(), ShadowBeg()); |
| 145 | 108 | ProtectRange(ShadowEnd(), MetaShadowBeg()); |
| 146 | 109 | ProtectRange(MetaShadowEnd(), TraceMemBeg()); |
| ... | ... | @@ -159,6 +122,16 @@ void CheckAndProtect() { |
| 159 | 122 | ProtectRange(TraceMemEnd(), HeapMemBeg()); |
| 160 | 123 | ProtectRange(HeapEnd(), HiAppMemBeg()); |
| 161 | 124 | #endif |
| 125 | ||
| 126 | #if defined(__s390x__) | |
| 127 | // Protect the rest of the address space. | |
| 128 | const uptr user_addr_max_l4 = 0x0020000000000000ull; | |
| 129 | const uptr user_addr_max_l5 = 0xfffffffffffff000ull; | |
| 130 | // All the maintained s390x kernels support at least 4-level page tables. | |
| 131 | ProtectRange(HiAppMemEnd(), user_addr_max_l4); | |
| 132 | // Older s390x kernels may not support 5-level page tables. | |
| 133 | TryProtectRange(user_addr_max_l4, user_addr_max_l5); | |
| 134 | #endif | |
| 162 | 135 | } |
| 163 | 136 | #endif |
| 164 | 137 |
lib/tsan/tsan_report.cpp+11-9| ... | ... | @@ -69,7 +69,7 @@ ReportDesc::~ReportDesc() { |
| 69 | 69 | |
| 70 | 70 | const int kThreadBufSize = 32; |
| 71 | 71 | const char *thread_name(char *buf, int tid) { |
| 72 | if (tid == 0) | |
| 72 | if (tid == kMainTid) | |
| 73 | 73 | return "main thread"; |
| 74 | 74 | internal_snprintf(buf, kThreadBufSize, "thread T%d", tid); |
| 75 | 75 | return buf; |
| ... | ... | @@ -127,8 +127,9 @@ void PrintStack(const ReportStack *ent) { |
| 127 | 127 | } |
| 128 | 128 | SymbolizedStack *frame = ent->frames; |
| 129 | 129 | for (int i = 0; frame && frame->info.address; frame = frame->next, i++) { |
| 130 | InternalScopedString res(2 * GetPageSizeCached()); | |
| 131 | RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info, | |
| 130 | InternalScopedString res; | |
| 131 | RenderFrame(&res, common_flags()->stack_trace_format, i, | |
| 132 | frame->info.address, &frame->info, | |
| 132 | 133 | common_flags()->symbolize_vs_style, |
| 133 | 134 | common_flags()->strip_path_prefix, kInterposedFunctionPrefix); |
| 134 | 135 | Printf("%s\n", res.data()); |
| ... | ... | @@ -249,7 +250,7 @@ static void PrintMutex(const ReportMutex *rm) { |
| 249 | 250 | |
| 250 | 251 | static void PrintThread(const ReportThread *rt) { |
| 251 | 252 | Decorator d; |
| 252 | if (rt->id == 0) // Little sense in describing the main thread. | |
| 253 | if (rt->id == kMainTid) // Little sense in describing the main thread. | |
| 253 | 254 | return; |
| 254 | 255 | Printf("%s", d.ThreadDescription()); |
| 255 | 256 | Printf(" Thread T%d", rt->id); |
| ... | ... | @@ -385,14 +386,15 @@ void PrintReport(const ReportDesc *rep) { |
| 385 | 386 | ReportErrorSummary(rep_typ_str, frame->info); |
| 386 | 387 | } |
| 387 | 388 | |
| 388 | if (common_flags()->print_module_map == 2) PrintModuleMap(); | |
| 389 | if (common_flags()->print_module_map == 2) | |
| 390 | DumpProcessMap(); | |
| 389 | 391 | |
| 390 | 392 | Printf("==================\n"); |
| 391 | 393 | } |
| 392 | 394 | |
| 393 | 395 | #else // #if !SANITIZER_GO |
| 394 | 396 | |
| 395 | const int kMainThreadId = 1; | |
| 397 | const u32 kMainGoroutineId = 1; | |
| 396 | 398 | |
| 397 | 399 | void PrintStack(const ReportStack *ent) { |
| 398 | 400 | if (ent == 0 || ent->frames == 0) { |
| ... | ... | @@ -413,7 +415,7 @@ static void PrintMop(const ReportMop *mop, bool first) { |
| 413 | 415 | Printf("%s at %p by ", |
| 414 | 416 | (first ? (mop->write ? "Write" : "Read") |
| 415 | 417 | : (mop->write ? "Previous write" : "Previous read")), mop->addr); |
| 416 | if (mop->tid == kMainThreadId) | |
| 418 | if (mop->tid == kMainGoroutineId) | |
| 417 | 419 | Printf("main goroutine:\n"); |
| 418 | 420 | else |
| 419 | 421 | Printf("goroutine %d:\n", mop->tid); |
| ... | ... | @@ -426,7 +428,7 @@ static void PrintLocation(const ReportLocation *loc) { |
| 426 | 428 | Printf("\n"); |
| 427 | 429 | Printf("Heap block of size %zu at %p allocated by ", |
| 428 | 430 | loc->heap_chunk_size, loc->heap_chunk_start); |
| 429 | if (loc->tid == kMainThreadId) | |
| 431 | if (loc->tid == kMainGoroutineId) | |
| 430 | 432 | Printf("main goroutine:\n"); |
| 431 | 433 | else |
| 432 | 434 | Printf("goroutine %d:\n", loc->tid); |
| ... | ... | @@ -446,7 +448,7 @@ static void PrintLocation(const ReportLocation *loc) { |
| 446 | 448 | } |
| 447 | 449 | |
| 448 | 450 | static void PrintThread(const ReportThread *rt) { |
| 449 | if (rt->id == kMainThreadId) | |
| 451 | if (rt->id == kMainGoroutineId) | |
| 450 | 452 | return; |
| 451 | 453 | Printf("\n"); |
| 452 | 454 | Printf("Goroutine %d (%s) created at:\n", |
lib/tsan/tsan_rtl.cpp+123-91| ... | ... | @@ -11,17 +11,19 @@ |
| 11 | 11 | // Main file (entry points) for the TSan run-time. |
| 12 | 12 | //===----------------------------------------------------------------------===// |
| 13 | 13 | |
| 14 | #include "tsan_rtl.h" | |
| 15 | ||
| 14 | 16 | #include "sanitizer_common/sanitizer_atomic.h" |
| 15 | 17 | #include "sanitizer_common/sanitizer_common.h" |
| 16 | 18 | #include "sanitizer_common/sanitizer_file.h" |
| 17 | 19 | #include "sanitizer_common/sanitizer_libc.h" |
| 18 | #include "sanitizer_common/sanitizer_stackdepot.h" | |
| 19 | 20 | #include "sanitizer_common/sanitizer_placement_new.h" |
| 21 | #include "sanitizer_common/sanitizer_stackdepot.h" | |
| 20 | 22 | #include "sanitizer_common/sanitizer_symbolizer.h" |
| 21 | 23 | #include "tsan_defs.h" |
| 22 | #include "tsan_platform.h" | |
| 23 | #include "tsan_rtl.h" | |
| 24 | #include "tsan_interface.h" | |
| 24 | 25 | #include "tsan_mman.h" |
| 26 | #include "tsan_platform.h" | |
| 25 | 27 | #include "tsan_suppressions.h" |
| 26 | 28 | #include "tsan_symbolize.h" |
| 27 | 29 | #include "ubsan/ubsan_init.h" |
| ... | ... | @@ -56,15 +58,26 @@ Context *ctx; |
| 56 | 58 | bool OnFinalize(bool failed); |
| 57 | 59 | void OnInitialize(); |
| 58 | 60 | #else |
| 61 | #include <dlfcn.h> | |
| 59 | 62 | SANITIZER_WEAK_CXX_DEFAULT_IMPL |
| 60 | 63 | bool OnFinalize(bool failed) { |
| 64 | #if !SANITIZER_GO | |
| 65 | if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_finalize")) | |
| 66 | return reinterpret_cast<decltype(&__tsan_on_finalize)>(ptr)(failed); | |
| 67 | #endif | |
| 61 | 68 | return failed; |
| 62 | 69 | } |
| 63 | 70 | SANITIZER_WEAK_CXX_DEFAULT_IMPL |
| 64 | void OnInitialize() {} | |
| 71 | void OnInitialize() { | |
| 72 | #if !SANITIZER_GO | |
| 73 | if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_initialize")) { | |
| 74 | return reinterpret_cast<decltype(&__tsan_on_initialize)>(ptr)(); | |
| 75 | } | |
| 76 | #endif | |
| 77 | } | |
| 65 | 78 | #endif |
| 66 | 79 | |
| 67 | static char thread_registry_placeholder[sizeof(ThreadRegistry)]; | |
| 80 | static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; | |
| 68 | 81 | |
| 69 | 82 | static ThreadContextBase *CreateThreadContext(u32 tid) { |
| 70 | 83 | // Map thread trace when context is created. |
| ... | ... | @@ -77,12 +90,19 @@ static ThreadContextBase *CreateThreadContext(u32 tid) { |
| 77 | 90 | new((void*)hdr) Trace(); |
| 78 | 91 | // We are going to use only a small part of the trace with the default |
| 79 | 92 | // value of history_size. However, the constructor writes to the whole trace. |
| 80 | // Unmap the unused part. | |
| 93 | // Release the unused part. | |
| 81 | 94 | uptr hdr_end = hdr + sizeof(Trace); |
| 82 | 95 | hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts()); |
| 83 | 96 | hdr_end = RoundUp(hdr_end, GetPageSizeCached()); |
| 84 | if (hdr_end < hdr + sizeof(Trace)) | |
| 85 | UnmapOrDie((void*)hdr_end, hdr + sizeof(Trace) - hdr_end); | |
| 97 | if (hdr_end < hdr + sizeof(Trace)) { | |
| 98 | ReleaseMemoryPagesToOS(hdr_end, hdr + sizeof(Trace)); | |
| 99 | uptr unused = hdr + sizeof(Trace) - hdr_end; | |
| 100 | if (hdr_end != (uptr)MmapFixedNoAccess(hdr_end, unused)) { | |
| 101 | Report("ThreadSanitizer: failed to mprotect(%p, %p)\n", | |
| 102 | hdr_end, unused); | |
| 103 | CHECK("unable to mprotect" && 0); | |
| 104 | } | |
| 105 | } | |
| 86 | 106 | void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext)); |
| 87 | 107 | return new(mem) ThreadContext(tid); |
| 88 | 108 | } |
| ... | ... | @@ -94,42 +114,45 @@ static const u32 kThreadQuarantineSize = 64; |
| 94 | 114 | #endif |
| 95 | 115 | |
| 96 | 116 | Context::Context() |
| 97 | : initialized() | |
| 98 | , report_mtx(MutexTypeReport, StatMtxReport) | |
| 99 | , nreported() | |
| 100 | , nmissed_expected() | |
| 101 | , thread_registry(new(thread_registry_placeholder) ThreadRegistry( | |
| 102 | CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse)) | |
| 103 | , racy_mtx(MutexTypeRacy, StatMtxRacy) | |
| 104 | , racy_stacks() | |
| 105 | , racy_addresses() | |
| 106 | , fired_suppressions_mtx(MutexTypeFired, StatMtxFired) | |
| 107 | , clock_alloc("clock allocator") { | |
| 117 | : initialized(), | |
| 118 | report_mtx(MutexTypeReport), | |
| 119 | nreported(), | |
| 120 | nmissed_expected(), | |
| 121 | thread_registry(new (thread_registry_placeholder) ThreadRegistry( | |
| 122 | CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse)), | |
| 123 | racy_mtx(MutexTypeRacy), | |
| 124 | racy_stacks(), | |
| 125 | racy_addresses(), | |
| 126 | fired_suppressions_mtx(MutexTypeFired), | |
| 127 | clock_alloc(LINKER_INITIALIZED, "clock allocator") { | |
| 108 | 128 | fired_suppressions.reserve(8); |
| 109 | 129 | } |
| 110 | 130 | |
| 111 | 131 | // The objects are allocated in TLS, so one may rely on zero-initialization. |
| 112 | ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, | |
| 113 | unsigned reuse_count, | |
| 114 | uptr stk_addr, uptr stk_size, | |
| 132 | ThreadState::ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch, | |
| 133 | unsigned reuse_count, uptr stk_addr, uptr stk_size, | |
| 115 | 134 | uptr tls_addr, uptr tls_size) |
| 116 | : fast_state(tid, epoch) | |
| 117 | // Do not touch these, rely on zero initialization, | |
| 118 | // they may be accessed before the ctor. | |
| 119 | // , ignore_reads_and_writes() | |
| 120 | // , ignore_interceptors() | |
| 121 | , clock(tid, reuse_count) | |
| 135 | : fast_state(tid, epoch) | |
| 136 | // Do not touch these, rely on zero initialization, | |
| 137 | // they may be accessed before the ctor. | |
| 138 | // , ignore_reads_and_writes() | |
| 139 | // , ignore_interceptors() | |
| 140 | , | |
| 141 | clock(tid, reuse_count) | |
| 122 | 142 | #if !SANITIZER_GO |
| 123 | , jmp_bufs() | |
| 143 | , | |
| 144 | jmp_bufs() | |
| 124 | 145 | #endif |
| 125 | , tid(tid) | |
| 126 | , unique_id(unique_id) | |
| 127 | , stk_addr(stk_addr) | |
| 128 | , stk_size(stk_size) | |
| 129 | , tls_addr(tls_addr) | |
| 130 | , tls_size(tls_size) | |
| 146 | , | |
| 147 | tid(tid), | |
| 148 | unique_id(unique_id), | |
| 149 | stk_addr(stk_addr), | |
| 150 | stk_size(stk_size), | |
| 151 | tls_addr(tls_addr), | |
| 152 | tls_size(tls_size) | |
| 131 | 153 | #if !SANITIZER_GO |
| 132 | , last_sleep_clock(tid) | |
| 154 | , | |
| 155 | last_sleep_clock(tid) | |
| 133 | 156 | #endif |
| 134 | 157 | { |
| 135 | 158 | } |
| ... | ... | @@ -160,12 +183,12 @@ static void *BackgroundThread(void *arg) { |
| 160 | 183 | } else if (internal_strcmp(flags()->profile_memory, "stderr") == 0) { |
| 161 | 184 | mprof_fd = 2; |
| 162 | 185 | } else { |
| 163 | InternalScopedString filename(kMaxPathLength); | |
| 186 | InternalScopedString filename; | |
| 164 | 187 | filename.append("%s.%d", flags()->profile_memory, (int)internal_getpid()); |
| 165 | 188 | fd_t fd = OpenFile(filename.data(), WrOnly); |
| 166 | 189 | if (fd == kInvalidFd) { |
| 167 | 190 | Printf("ThreadSanitizer: failed to open memory profile file '%s'\n", |
| 168 | &filename[0]); | |
| 191 | filename.data()); | |
| 169 | 192 | } else { |
| 170 | 193 | mprof_fd = fd; |
| 171 | 194 | } |
| ... | ... | @@ -256,7 +279,8 @@ void MapShadow(uptr addr, uptr size) { |
| 256 | 279 | const uptr kPageSize = GetPageSizeCached(); |
| 257 | 280 | uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), kPageSize); |
| 258 | 281 | uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), kPageSize); |
| 259 | if (!MmapFixedNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow")) | |
| 282 | if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, | |
| 283 | "shadow")) | |
| 260 | 284 | Die(); |
| 261 | 285 | |
| 262 | 286 | // Meta shadow is 2:1, so tread carefully. |
| ... | ... | @@ -269,7 +293,8 @@ void MapShadow(uptr addr, uptr size) { |
| 269 | 293 | if (!data_mapped) { |
| 270 | 294 | // First call maps data+bss. |
| 271 | 295 | data_mapped = true; |
| 272 | if (!MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow")) | |
| 296 | if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin, | |
| 297 | "meta shadow")) | |
| 273 | 298 | Die(); |
| 274 | 299 | } else { |
| 275 | 300 | // Mapping continous heap. |
| ... | ... | @@ -280,7 +305,8 @@ void MapShadow(uptr addr, uptr size) { |
| 280 | 305 | return; |
| 281 | 306 | if (meta_begin < mapped_meta_end) |
| 282 | 307 | meta_begin = mapped_meta_end; |
| 283 | if (!MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow")) | |
| 308 | if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin, | |
| 309 | "meta shadow")) | |
| 284 | 310 | Die(); |
| 285 | 311 | mapped_meta_end = meta_end; |
| 286 | 312 | } |
| ... | ... | @@ -293,7 +319,7 @@ void MapThreadTrace(uptr addr, uptr size, const char *name) { |
| 293 | 319 | CHECK_GE(addr, TraceMemBeg()); |
| 294 | 320 | CHECK_LE(addr + size, TraceMemEnd()); |
| 295 | 321 | CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment |
| 296 | if (!MmapFixedNoReserve(addr, size, name)) { | |
| 322 | if (!MmapFixedSuperNoReserve(addr, size, name)) { | |
| 297 | 323 | Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p)\n", |
| 298 | 324 | addr, size); |
| 299 | 325 | Die(); |
| ... | ... | @@ -348,6 +374,18 @@ static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) { |
| 348 | 374 | } |
| 349 | 375 | #endif |
| 350 | 376 | |
| 377 | void CheckUnwind() { | |
| 378 | // There is high probability that interceptors will check-fail as well, | |
| 379 | // on the other hand there is no sense in processing interceptors | |
| 380 | // since we are going to die soon. | |
| 381 | ScopedIgnoreInterceptors ignore; | |
| 382 | #if !SANITIZER_GO | |
| 383 | cur_thread()->ignore_sync++; | |
| 384 | cur_thread()->ignore_reads_and_writes++; | |
| 385 | #endif | |
| 386 | PrintCurrentStackSlow(StackTrace::GetCurrentPc()); | |
| 387 | } | |
| 388 | ||
| 351 | 389 | void Initialize(ThreadState *thr) { |
| 352 | 390 | // Thread safe because done before all threads exist. |
| 353 | 391 | static bool is_initialized = false; |
| ... | ... | @@ -358,7 +396,7 @@ void Initialize(ThreadState *thr) { |
| 358 | 396 | ScopedIgnoreInterceptors ignore; |
| 359 | 397 | SanitizerToolName = "ThreadSanitizer"; |
| 360 | 398 | // Install tool-specific callbacks in sanitizer_common. |
| 361 | SetCheckFailedCallback(TsanCheckFailed); | |
| 399 | SetCheckUnwindCallback(CheckUnwind); | |
| 362 | 400 | |
| 363 | 401 | ctx = new(ctx_placeholder) Context; |
| 364 | 402 | const char *env_name = SANITIZER_GO ? "GORACE" : "TSAN_OPTIONS"; |
| ... | ... | @@ -384,7 +422,6 @@ void Initialize(ThreadState *thr) { |
| 384 | 422 | InitializeInterceptors(); |
| 385 | 423 | CheckShadowMapping(); |
| 386 | 424 | InitializePlatform(); |
| 387 | InitializeMutex(); | |
| 388 | 425 | InitializeDynamicAnnotations(); |
| 389 | 426 | #if !SANITIZER_GO |
| 390 | 427 | InitializeShadowMemory(); |
| ... | ... | @@ -443,7 +480,8 @@ void MaybeSpawnBackgroundThread() { |
| 443 | 480 | int Finalize(ThreadState *thr) { |
| 444 | 481 | bool failed = false; |
| 445 | 482 | |
| 446 | if (common_flags()->print_module_map == 1) PrintModuleMap(); | |
| 483 | if (common_flags()->print_module_map == 1) | |
| 484 | DumpProcessMap(); | |
| 447 | 485 | |
| 448 | 486 | if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1) |
| 449 | 487 | SleepForMillis(flags()->atexit_sleep_ms); |
| ... | ... | @@ -483,35 +521,37 @@ int Finalize(ThreadState *thr) { |
| 483 | 521 | |
| 484 | 522 | failed = OnFinalize(failed); |
| 485 | 523 | |
| 486 | #if TSAN_COLLECT_STATS | |
| 487 | StatAggregate(ctx->stat, thr->stat); | |
| 488 | StatOutput(ctx->stat); | |
| 489 | #endif | |
| 490 | ||
| 491 | 524 | return failed ? common_flags()->exitcode : 0; |
| 492 | 525 | } |
| 493 | 526 | |
| 494 | 527 | #if !SANITIZER_GO |
| 495 | void ForkBefore(ThreadState *thr, uptr pc) { | |
| 528 | void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { | |
| 496 | 529 | ctx->thread_registry->Lock(); |
| 497 | 530 | ctx->report_mtx.Lock(); |
| 498 | // Ignore memory accesses in the pthread_atfork callbacks. | |
| 499 | // If any of them triggers a data race we will deadlock | |
| 500 | // on the report_mtx. | |
| 501 | // We could ignore interceptors and sync operations as well, | |
| 531 | ScopedErrorReportLock::Lock(); | |
| 532 | // Suppress all reports in the pthread_atfork callbacks. | |
| 533 | // Reports will deadlock on the report_mtx. | |
| 534 | // We could ignore sync operations as well, | |
| 502 | 535 | // but so far it's unclear if it will do more good or harm. |
| 503 | 536 | // Unnecessarily ignoring things can lead to false positives later. |
| 504 | ThreadIgnoreBegin(thr, pc); | |
| 537 | thr->suppress_reports++; | |
| 538 | // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and | |
| 539 | // we'll assert in CheckNoLocks() unless we ignore interceptors. | |
| 540 | thr->ignore_interceptors++; | |
| 505 | 541 | } |
| 506 | 542 | |
| 507 | void ForkParentAfter(ThreadState *thr, uptr pc) { | |
| 508 | ThreadIgnoreEnd(thr, pc); // Begin is in ForkBefore. | |
| 543 | void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { | |
| 544 | thr->suppress_reports--; // Enabled in ForkBefore. | |
| 545 | thr->ignore_interceptors--; | |
| 546 | ScopedErrorReportLock::Unlock(); | |
| 509 | 547 | ctx->report_mtx.Unlock(); |
| 510 | 548 | ctx->thread_registry->Unlock(); |
| 511 | 549 | } |
| 512 | 550 | |
| 513 | void ForkChildAfter(ThreadState *thr, uptr pc) { | |
| 514 | ThreadIgnoreEnd(thr, pc); // Begin is in ForkBefore. | |
| 551 | void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { | |
| 552 | thr->suppress_reports--; // Enabled in ForkBefore. | |
| 553 | thr->ignore_interceptors--; | |
| 554 | ScopedErrorReportLock::Unlock(); | |
| 515 | 555 | ctx->report_mtx.Unlock(); |
| 516 | 556 | ctx->thread_registry->Unlock(); |
| 517 | 557 | |
| ... | ... | @@ -650,9 +690,6 @@ ALWAYS_INLINE |
| 650 | 690 | void MemoryAccessImpl1(ThreadState *thr, uptr addr, |
| 651 | 691 | int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic, |
| 652 | 692 | u64 *shadow_mem, Shadow cur) { |
| 653 | StatInc(thr, StatMop); | |
| 654 | StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); | |
| 655 | StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); | |
| 656 | 693 | |
| 657 | 694 | // This potentially can live in an MMX/SSE scratch register. |
| 658 | 695 | // The required intrinsics are: |
| ... | ... | @@ -709,7 +746,6 @@ void MemoryAccessImpl1(ThreadState *thr, uptr addr, |
| 709 | 746 | return; |
| 710 | 747 | // choose a random candidate slot and replace it |
| 711 | 748 | StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word); |
| 712 | StatInc(thr, StatShadowReplace); | |
| 713 | 749 | return; |
| 714 | 750 | RACE: |
| 715 | 751 | HandleRace(thr, shadow_mem, cur, old); |
| ... | ... | @@ -848,19 +884,11 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, |
| 848 | 884 | if (!SANITIZER_GO && !kAccessIsWrite && *shadow_mem == kShadowRodata) { |
| 849 | 885 | // Access to .rodata section, no races here. |
| 850 | 886 | // Measurements show that it can be 10-20% of all memory accesses. |
| 851 | StatInc(thr, StatMop); | |
| 852 | StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); | |
| 853 | StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); | |
| 854 | StatInc(thr, StatMopRodata); | |
| 855 | 887 | return; |
| 856 | 888 | } |
| 857 | 889 | |
| 858 | 890 | FastState fast_state = thr->fast_state; |
| 859 | 891 | if (UNLIKELY(fast_state.GetIgnoreBit())) { |
| 860 | StatInc(thr, StatMop); | |
| 861 | StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); | |
| 862 | StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); | |
| 863 | StatInc(thr, StatMopIgnored); | |
| 864 | 892 | return; |
| 865 | 893 | } |
| 866 | 894 | |
| ... | ... | @@ -871,10 +899,6 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, |
| 871 | 899 | |
| 872 | 900 | if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(), |
| 873 | 901 | thr->fast_synch_epoch, kAccessIsWrite))) { |
| 874 | StatInc(thr, StatMop); | |
| 875 | StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); | |
| 876 | StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); | |
| 877 | StatInc(thr, StatMopSame); | |
| 878 | 902 | return; |
| 879 | 903 | } |
| 880 | 904 | |
| ... | ... | @@ -896,10 +920,6 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr, |
| 896 | 920 | u64 *shadow_mem, Shadow cur) { |
| 897 | 921 | if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(), |
| 898 | 922 | thr->fast_synch_epoch, kAccessIsWrite))) { |
| 899 | StatInc(thr, StatMop); | |
| 900 | StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); | |
| 901 | StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); | |
| 902 | StatInc(thr, StatMopSame); | |
| 903 | 923 | return; |
| 904 | 924 | } |
| 905 | 925 | |
| ... | ... | @@ -956,8 +976,7 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, |
| 956 | 976 | // Reset middle part. |
| 957 | 977 | u64 *p1 = p; |
| 958 | 978 | p = RoundDown(end, kPageSize); |
| 959 | UnmapOrDie((void*)p1, (uptr)p - (uptr)p1); | |
| 960 | if (!MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1)) | |
| 979 | if (!MmapFixedSuperNoReserve((uptr)p1, (uptr)p - (uptr)p1)) | |
| 961 | 980 | Die(); |
| 962 | 981 | // Set the ending. |
| 963 | 982 | while (p < end) { |
| ... | ... | @@ -1016,7 +1035,6 @@ void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr, |
| 1016 | 1035 | |
| 1017 | 1036 | ALWAYS_INLINE USED |
| 1018 | 1037 | void FuncEntry(ThreadState *thr, uptr pc) { |
| 1019 | StatInc(thr, StatFuncEnter); | |
| 1020 | 1038 | DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc); |
| 1021 | 1039 | if (kCollectHistory) { |
| 1022 | 1040 | thr->fast_state.IncrementEpoch(); |
| ... | ... | @@ -1038,7 +1056,6 @@ void FuncEntry(ThreadState *thr, uptr pc) { |
| 1038 | 1056 | |
| 1039 | 1057 | ALWAYS_INLINE USED |
| 1040 | 1058 | void FuncExit(ThreadState *thr) { |
| 1041 | StatInc(thr, StatFuncExit); | |
| 1042 | 1059 | DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid()); |
| 1043 | 1060 | if (kCollectHistory) { |
| 1044 | 1061 | thr->fast_state.IncrementEpoch(); |
| ... | ... | @@ -1113,15 +1130,30 @@ void build_consistency_debug() {} |
| 1113 | 1130 | void build_consistency_release() {} |
| 1114 | 1131 | #endif |
| 1115 | 1132 | |
| 1116 | #if TSAN_COLLECT_STATS | |
| 1117 | void build_consistency_stats() {} | |
| 1118 | #else | |
| 1119 | void build_consistency_nostats() {} | |
| 1120 | #endif | |
| 1121 | ||
| 1122 | 1133 | } // namespace __tsan |
| 1123 | 1134 | |
| 1135 | #if SANITIZER_CHECK_DEADLOCKS | |
| 1136 | namespace __sanitizer { | |
| 1137 | using namespace __tsan; | |
| 1138 | MutexMeta mutex_meta[] = { | |
| 1139 | {MutexInvalid, "Invalid", {}}, | |
| 1140 | {MutexThreadRegistry, "ThreadRegistry", {}}, | |
| 1141 | {MutexTypeTrace, "Trace", {MutexLeaf}}, | |
| 1142 | {MutexTypeReport, "Report", {MutexTypeSyncVar}}, | |
| 1143 | {MutexTypeSyncVar, "SyncVar", {}}, | |
| 1144 | {MutexTypeAnnotations, "Annotations", {}}, | |
| 1145 | {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}}, | |
| 1146 | {MutexTypeFired, "Fired", {MutexLeaf}}, | |
| 1147 | {MutexTypeRacy, "Racy", {MutexLeaf}}, | |
| 1148 | {MutexTypeGlobalProc, "GlobalProc", {}}, | |
| 1149 | {}, | |
| 1150 | }; | |
| 1151 | ||
| 1152 | void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); } | |
| 1153 | } // namespace __sanitizer | |
| 1154 | #endif | |
| 1155 | ||
| 1124 | 1156 | #if !SANITIZER_GO |
| 1125 | 1157 | // Must be included in this file to make sure everything is inlined. |
| 1126 | #include "tsan_interface_inl.h" | |
| 1158 | # include "tsan_interface_inl.h" | |
| 1127 | 1159 | #endif |
lib/tsan/tsan_rtl.h+10-37| ... | ... | @@ -84,9 +84,6 @@ typedef Allocator::AllocatorCache AllocatorCache; |
| 84 | 84 | Allocator *allocator(); |
| 85 | 85 | #endif |
| 86 | 86 | |
| 87 | void TsanCheckFailed(const char *file, int line, const char *cond, | |
| 88 | u64 v1, u64 v2); | |
| 89 | ||
| 90 | 87 | const u64 kShadowRodata = (u64)-1; // .rodata shadow marker |
| 91 | 88 | |
| 92 | 89 | // FastState (from most significant bit): |
| ... | ... | @@ -403,10 +400,7 @@ struct ThreadState { |
| 403 | 400 | Vector<JmpBuf> jmp_bufs; |
| 404 | 401 | int ignore_interceptors; |
| 405 | 402 | #endif |
| 406 | #if TSAN_COLLECT_STATS | |
| 407 | u64 stat[StatCnt]; | |
| 408 | #endif | |
| 409 | const int tid; | |
| 403 | const u32 tid; | |
| 410 | 404 | const int unique_id; |
| 411 | 405 | bool in_symbolizer; |
| 412 | 406 | bool in_ignored_lib; |
| ... | ... | @@ -420,9 +414,6 @@ struct ThreadState { |
| 420 | 414 | const uptr tls_size; |
| 421 | 415 | ThreadContext *tctx; |
| 422 | 416 | |
| 423 | #if SANITIZER_DEBUG && !SANITIZER_GO | |
| 424 | InternalDeadlockDetector internal_deadlock_detector; | |
| 425 | #endif | |
| 426 | 417 | DDLogicalThread *dd_lt; |
| 427 | 418 | |
| 428 | 419 | // Current wired Processor, or nullptr. Required to handle any events. |
| ... | ... | @@ -447,9 +438,8 @@ struct ThreadState { |
| 447 | 438 | |
| 448 | 439 | const ReportDesc *current_report; |
| 449 | 440 | |
| 450 | explicit ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, | |
| 451 | unsigned reuse_count, | |
| 452 | uptr stk_addr, uptr stk_size, | |
| 441 | explicit ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch, | |
| 442 | unsigned reuse_count, uptr stk_addr, uptr stk_size, | |
| 453 | 443 | uptr tls_addr, uptr tls_size); |
| 454 | 444 | }; |
| 455 | 445 | |
| ... | ... | @@ -458,26 +448,26 @@ struct ThreadState { |
| 458 | 448 | ThreadState *cur_thread(); |
| 459 | 449 | void set_cur_thread(ThreadState *thr); |
| 460 | 450 | void cur_thread_finalize(); |
| 461 | INLINE void cur_thread_init() { } | |
| 451 | inline void cur_thread_init() { } | |
| 462 | 452 | #else |
| 463 | 453 | __attribute__((tls_model("initial-exec"))) |
| 464 | 454 | extern THREADLOCAL char cur_thread_placeholder[]; |
| 465 | INLINE ThreadState *cur_thread() { | |
| 455 | inline ThreadState *cur_thread() { | |
| 466 | 456 | return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current; |
| 467 | 457 | } |
| 468 | INLINE void cur_thread_init() { | |
| 458 | inline void cur_thread_init() { | |
| 469 | 459 | ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder); |
| 470 | 460 | if (UNLIKELY(!thr->current)) |
| 471 | 461 | thr->current = thr; |
| 472 | 462 | } |
| 473 | INLINE void set_cur_thread(ThreadState *thr) { | |
| 463 | inline void set_cur_thread(ThreadState *thr) { | |
| 474 | 464 | reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr; |
| 475 | 465 | } |
| 476 | INLINE void cur_thread_finalize() { } | |
| 466 | inline void cur_thread_finalize() { } | |
| 477 | 467 | #endif // SANITIZER_MAC || SANITIZER_ANDROID |
| 478 | 468 | #endif // SANITIZER_GO |
| 479 | 469 | |
| 480 | class ThreadContext : public ThreadContextBase { | |
| 470 | class ThreadContext final : public ThreadContextBase { | |
| 481 | 471 | public: |
| 482 | 472 | explicit ThreadContext(int tid); |
| 483 | 473 | ~ThreadContext(); |
| ... | ... | @@ -554,7 +544,6 @@ struct Context { |
| 554 | 544 | |
| 555 | 545 | Flags flags; |
| 556 | 546 | |
| 557 | u64 stat[StatCnt]; | |
| 558 | 547 | u64 int_alloc_cnt[MBlockTypeCount]; |
| 559 | 548 | u64 int_alloc_siz[MBlockTypeCount]; |
| 560 | 549 | }; |
| ... | ... | @@ -624,6 +613,7 @@ class ScopedReport : public ScopedReportBase { |
| 624 | 613 | ScopedErrorReportLock lock_; |
| 625 | 614 | }; |
| 626 | 615 | |
| 616 | bool ShouldReport(ThreadState *thr, ReportType typ); | |
| 627 | 617 | ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack); |
| 628 | 618 | void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk, |
| 629 | 619 | MutexSet *mset, uptr *tag = nullptr); |
| ... | ... | @@ -661,22 +651,6 @@ void ObtainCurrentStack(ThreadState *thr, uptr toppc, StackTraceTy *stack, |
| 661 | 651 | ObtainCurrentStack(thr, pc, &stack); \ |
| 662 | 652 | stack.ReverseOrder(); |
| 663 | 653 | |
| 664 | #if TSAN_COLLECT_STATS | |
| 665 | void StatAggregate(u64 *dst, u64 *src); | |
| 666 | void StatOutput(u64 *stat); | |
| 667 | #endif | |
| 668 | ||
| 669 | void ALWAYS_INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) { | |
| 670 | #if TSAN_COLLECT_STATS | |
| 671 | thr->stat[typ] += n; | |
| 672 | #endif | |
| 673 | } | |
| 674 | void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) { | |
| 675 | #if TSAN_COLLECT_STATS | |
| 676 | thr->stat[typ] = n; | |
| 677 | #endif | |
| 678 | } | |
| 679 | ||
| 680 | 654 | void MapShadow(uptr addr, uptr size); |
| 681 | 655 | void MapThreadTrace(uptr addr, uptr size, const char *name); |
| 682 | 656 | void DontNeedShadowFor(uptr addr, uptr size); |
| ... | ... | @@ -857,7 +831,6 @@ void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs, |
| 857 | 831 | DCHECK_GE((int)typ, 0); |
| 858 | 832 | DCHECK_LE((int)typ, 7); |
| 859 | 833 | DCHECK_EQ(GetLsb(addr, kEventPCBits), addr); |
| 860 | StatInc(thr, StatEvents); | |
| 861 | 834 | u64 pos = fs.GetTracePos(); |
| 862 | 835 | if (UNLIKELY((pos % kTracePartSize) == 0)) { |
| 863 | 836 | #if !SANITIZER_GO |
lib/tsan/tsan_rtl_mutex.cpp+30-45| ... | ... | @@ -24,7 +24,7 @@ namespace __tsan { |
| 24 | 24 | |
| 25 | 25 | void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r); |
| 26 | 26 | |
| 27 | struct Callback : DDCallback { | |
| 27 | struct Callback final : public DDCallback { | |
| 28 | 28 | ThreadState *thr; |
| 29 | 29 | uptr pc; |
| 30 | 30 | |
| ... | ... | @@ -51,6 +51,8 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ, |
| 51 | 51 | // or false positives (e.g. unlock in a different thread). |
| 52 | 52 | if (SANITIZER_GO) |
| 53 | 53 | return; |
| 54 | if (!ShouldReport(thr, typ)) | |
| 55 | return; | |
| 54 | 56 | ThreadRegistryLock l(ctx->thread_registry); |
| 55 | 57 | ScopedReport rep(typ); |
| 56 | 58 | rep.AddMutex(mid); |
| ... | ... | @@ -61,9 +63,8 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ, |
| 61 | 63 | OutputReport(thr, rep); |
| 62 | 64 | } |
| 63 | 65 | |
| 64 | void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { | |
| 66 | void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS { | |
| 65 | 67 | DPrintf("#%d: MutexCreate %zx flagz=0x%x\n", thr->tid, addr, flagz); |
| 66 | StatInc(thr, StatMutexCreate); | |
| 67 | 68 | if (!(flagz & MutexFlagLinkerInit) && IsAppMem(addr)) { |
| 68 | 69 | CHECK(!thr->is_freeing); |
| 69 | 70 | thr->is_freeing = true; |
| ... | ... | @@ -77,9 +78,8 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 77 | 78 | s->mtx.Unlock(); |
| 78 | 79 | } |
| 79 | 80 | |
| 80 | void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { | |
| 81 | void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS { | |
| 81 | 82 | DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr); |
| 82 | StatInc(thr, StatMutexDestroy); | |
| 83 | 83 | SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true); |
| 84 | 84 | if (s == 0) |
| 85 | 85 | return; |
| ... | ... | @@ -96,9 +96,8 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 96 | 96 | ctx->dd->MutexInit(&cb, &s->dd); |
| 97 | 97 | } |
| 98 | 98 | bool unlock_locked = false; |
| 99 | if (flags()->report_destroy_locked | |
| 100 | && s->owner_tid != SyncVar::kInvalidTid | |
| 101 | && !s->IsFlagSet(MutexFlagBroken)) { | |
| 99 | if (flags()->report_destroy_locked && s->owner_tid != kInvalidTid && | |
| 100 | !s->IsFlagSet(MutexFlagBroken)) { | |
| 102 | 101 | s->SetFlags(MutexFlagBroken); |
| 103 | 102 | unlock_locked = true; |
| 104 | 103 | } |
| ... | ... | @@ -107,7 +106,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 107 | 106 | if (!unlock_locked) |
| 108 | 107 | s->Reset(thr->proc()); // must not reset it before the report is printed |
| 109 | 108 | s->mtx.Unlock(); |
| 110 | if (unlock_locked) { | |
| 109 | if (unlock_locked && ShouldReport(thr, ReportTypeMutexDestroyLocked)) { | |
| 111 | 110 | ThreadRegistryLock l(ctx->thread_registry); |
| 112 | 111 | ScopedReport rep(ReportTypeMutexDestroyLocked); |
| 113 | 112 | rep.AddMutex(mid); |
| ... | ... | @@ -139,7 +138,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 139 | 138 | // s will be destroyed and freed in MetaMap::FreeBlock. |
| 140 | 139 | } |
| 141 | 140 | |
| 142 | void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { | |
| 141 | void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS { | |
| 143 | 142 | DPrintf("#%d: MutexPreLock %zx flagz=0x%x\n", thr->tid, addr, flagz); |
| 144 | 143 | if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) { |
| 145 | 144 | SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false); |
| ... | ... | @@ -155,7 +154,8 @@ void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 155 | 154 | } |
| 156 | 155 | } |
| 157 | 156 | |
| 158 | void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) { | |
| 157 | void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, | |
| 158 | int rec) NO_THREAD_SAFETY_ANALYSIS { | |
| 159 | 159 | DPrintf("#%d: MutexPostLock %zx flag=0x%x rec=%d\n", |
| 160 | 160 | thr->tid, addr, flagz, rec); |
| 161 | 161 | if (flagz & MutexFlagRecursiveLock) |
| ... | ... | @@ -169,7 +169,7 @@ void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) { |
| 169 | 169 | thr->fast_state.IncrementEpoch(); |
| 170 | 170 | TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId()); |
| 171 | 171 | bool report_double_lock = false; |
| 172 | if (s->owner_tid == SyncVar::kInvalidTid) { | |
| 172 | if (s->owner_tid == kInvalidTid) { | |
| 173 | 173 | CHECK_EQ(s->recursion, 0); |
| 174 | 174 | s->owner_tid = thr->tid; |
| 175 | 175 | s->last_lock = thr->fast_state.raw(); |
| ... | ... | @@ -182,11 +182,9 @@ void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) { |
| 182 | 182 | const bool first = s->recursion == 0; |
| 183 | 183 | s->recursion += rec; |
| 184 | 184 | if (first) { |
| 185 | StatInc(thr, StatMutexLock); | |
| 186 | 185 | AcquireImpl(thr, pc, &s->clock); |
| 187 | 186 | AcquireImpl(thr, pc, &s->read_clock); |
| 188 | 187 | } else if (!s->IsFlagSet(MutexFlagWriteReentrant)) { |
| 189 | StatInc(thr, StatMutexRecLock); | |
| 190 | 188 | } |
| 191 | 189 | thr->mset.Add(s->GetId(), true, thr->fast_state.epoch()); |
| 192 | 190 | bool pre_lock = false; |
| ... | ... | @@ -210,7 +208,7 @@ void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) { |
| 210 | 208 | } |
| 211 | 209 | } |
| 212 | 210 | |
| 213 | int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { | |
| 211 | int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS { | |
| 214 | 212 | DPrintf("#%d: MutexUnlock %zx flagz=0x%x\n", thr->tid, addr, flagz); |
| 215 | 213 | if (IsAppMem(addr)) |
| 216 | 214 | MemoryReadAtomic(thr, pc, addr, kSizeLog1); |
| ... | ... | @@ -228,11 +226,9 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 228 | 226 | rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1; |
| 229 | 227 | s->recursion -= rec; |
| 230 | 228 | if (s->recursion == 0) { |
| 231 | StatInc(thr, StatMutexUnlock); | |
| 232 | s->owner_tid = SyncVar::kInvalidTid; | |
| 229 | s->owner_tid = kInvalidTid; | |
| 233 | 230 | ReleaseStoreImpl(thr, pc, &s->clock); |
| 234 | 231 | } else { |
| 235 | StatInc(thr, StatMutexRecUnlock); | |
| 236 | 232 | } |
| 237 | 233 | } |
| 238 | 234 | thr->mset.Del(s->GetId(), true); |
| ... | ... | @@ -253,7 +249,7 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 253 | 249 | return rec; |
| 254 | 250 | } |
| 255 | 251 | |
| 256 | void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { | |
| 252 | void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS { | |
| 257 | 253 | DPrintf("#%d: MutexPreReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz); |
| 258 | 254 | if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) { |
| 259 | 255 | SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false); |
| ... | ... | @@ -265,9 +261,8 @@ void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 265 | 261 | } |
| 266 | 262 | } |
| 267 | 263 | |
| 268 | void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { | |
| 264 | void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAFETY_ANALYSIS { | |
| 269 | 265 | DPrintf("#%d: MutexPostReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz); |
| 270 | StatInc(thr, StatMutexReadLock); | |
| 271 | 266 | if (IsAppMem(addr)) |
| 272 | 267 | MemoryReadAtomic(thr, pc, addr, kSizeLog1); |
| 273 | 268 | SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false); |
| ... | ... | @@ -275,7 +270,7 @@ void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 275 | 270 | thr->fast_state.IncrementEpoch(); |
| 276 | 271 | TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId()); |
| 277 | 272 | bool report_bad_lock = false; |
| 278 | if (s->owner_tid != SyncVar::kInvalidTid) { | |
| 273 | if (s->owner_tid != kInvalidTid) { | |
| 279 | 274 | if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) { |
| 280 | 275 | s->SetFlags(MutexFlagBroken); |
| 281 | 276 | report_bad_lock = true; |
| ... | ... | @@ -305,16 +300,15 @@ void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { |
| 305 | 300 | } |
| 306 | 301 | } |
| 307 | 302 | |
| 308 | void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) { | |
| 303 | void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 309 | 304 | DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr); |
| 310 | StatInc(thr, StatMutexReadUnlock); | |
| 311 | 305 | if (IsAppMem(addr)) |
| 312 | 306 | MemoryReadAtomic(thr, pc, addr, kSizeLog1); |
| 313 | 307 | SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true); |
| 314 | 308 | thr->fast_state.IncrementEpoch(); |
| 315 | 309 | TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId()); |
| 316 | 310 | bool report_bad_unlock = false; |
| 317 | if (s->owner_tid != SyncVar::kInvalidTid) { | |
| 311 | if (s->owner_tid != kInvalidTid) { | |
| 318 | 312 | if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) { |
| 319 | 313 | s->SetFlags(MutexFlagBroken); |
| 320 | 314 | report_bad_unlock = true; |
| ... | ... | @@ -337,17 +331,16 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) { |
| 337 | 331 | } |
| 338 | 332 | } |
| 339 | 333 | |
| 340 | void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) { | |
| 334 | void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 341 | 335 | DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr); |
| 342 | 336 | if (IsAppMem(addr)) |
| 343 | 337 | MemoryReadAtomic(thr, pc, addr, kSizeLog1); |
| 344 | 338 | SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true); |
| 345 | 339 | bool write = true; |
| 346 | 340 | bool report_bad_unlock = false; |
| 347 | if (s->owner_tid == SyncVar::kInvalidTid) { | |
| 341 | if (s->owner_tid == kInvalidTid) { | |
| 348 | 342 | // Seems to be read unlock. |
| 349 | 343 | write = false; |
| 350 | StatInc(thr, StatMutexReadUnlock); | |
| 351 | 344 | thr->fast_state.IncrementEpoch(); |
| 352 | 345 | TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId()); |
| 353 | 346 | ReleaseImpl(thr, pc, &s->read_clock); |
| ... | ... | @@ -358,11 +351,9 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) { |
| 358 | 351 | CHECK_GT(s->recursion, 0); |
| 359 | 352 | s->recursion--; |
| 360 | 353 | if (s->recursion == 0) { |
| 361 | StatInc(thr, StatMutexUnlock); | |
| 362 | s->owner_tid = SyncVar::kInvalidTid; | |
| 354 | s->owner_tid = kInvalidTid; | |
| 363 | 355 | ReleaseStoreImpl(thr, pc, &s->clock); |
| 364 | 356 | } else { |
| 365 | StatInc(thr, StatMutexRecUnlock); | |
| 366 | 357 | } |
| 367 | 358 | } else if (!s->IsFlagSet(MutexFlagBroken)) { |
| 368 | 359 | s->SetFlags(MutexFlagBroken); |
| ... | ... | @@ -384,15 +375,15 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) { |
| 384 | 375 | } |
| 385 | 376 | } |
| 386 | 377 | |
| 387 | void MutexRepair(ThreadState *thr, uptr pc, uptr addr) { | |
| 378 | void MutexRepair(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 388 | 379 | DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr); |
| 389 | 380 | SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true); |
| 390 | s->owner_tid = SyncVar::kInvalidTid; | |
| 381 | s->owner_tid = kInvalidTid; | |
| 391 | 382 | s->recursion = 0; |
| 392 | 383 | s->mtx.Unlock(); |
| 393 | 384 | } |
| 394 | 385 | |
| 395 | void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) { | |
| 386 | void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 396 | 387 | DPrintf("#%d: MutexInvalidAccess %zx\n", thr->tid, addr); |
| 397 | 388 | SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true); |
| 398 | 389 | u64 mid = s->GetId(); |
| ... | ... | @@ -400,7 +391,7 @@ void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) { |
| 400 | 391 | ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr, mid); |
| 401 | 392 | } |
| 402 | 393 | |
| 403 | void Acquire(ThreadState *thr, uptr pc, uptr addr) { | |
| 394 | void Acquire(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 404 | 395 | DPrintf("#%d: Acquire %zx\n", thr->tid, addr); |
| 405 | 396 | if (thr->ignore_sync) |
| 406 | 397 | return; |
| ... | ... | @@ -431,7 +422,7 @@ void AcquireGlobal(ThreadState *thr, uptr pc) { |
| 431 | 422 | UpdateClockCallback, thr); |
| 432 | 423 | } |
| 433 | 424 | |
| 434 | void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) { | |
| 425 | void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 435 | 426 | DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr); |
| 436 | 427 | if (thr->ignore_sync) |
| 437 | 428 | return; |
| ... | ... | @@ -443,7 +434,7 @@ void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) { |
| 443 | 434 | s->mtx.Unlock(); |
| 444 | 435 | } |
| 445 | 436 | |
| 446 | void Release(ThreadState *thr, uptr pc, uptr addr) { | |
| 437 | void Release(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 447 | 438 | DPrintf("#%d: Release %zx\n", thr->tid, addr); |
| 448 | 439 | if (thr->ignore_sync) |
| 449 | 440 | return; |
| ... | ... | @@ -455,7 +446,7 @@ void Release(ThreadState *thr, uptr pc, uptr addr) { |
| 455 | 446 | s->mtx.Unlock(); |
| 456 | 447 | } |
| 457 | 448 | |
| 458 | void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) { | |
| 449 | void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS { | |
| 459 | 450 | DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr); |
| 460 | 451 | if (thr->ignore_sync) |
| 461 | 452 | return; |
| ... | ... | @@ -493,7 +484,6 @@ void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| 493 | 484 | return; |
| 494 | 485 | thr->clock.set(thr->fast_state.epoch()); |
| 495 | 486 | thr->clock.acquire(&thr->proc()->clock_cache, c); |
| 496 | StatInc(thr, StatSyncAcquire); | |
| 497 | 487 | } |
| 498 | 488 | |
| 499 | 489 | void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| ... | ... | @@ -502,7 +492,6 @@ void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| 502 | 492 | thr->clock.set(thr->fast_state.epoch()); |
| 503 | 493 | thr->fast_synch_epoch = thr->fast_state.epoch(); |
| 504 | 494 | thr->clock.releaseStoreAcquire(&thr->proc()->clock_cache, c); |
| 505 | StatInc(thr, StatSyncReleaseStoreAcquire); | |
| 506 | 495 | } |
| 507 | 496 | |
| 508 | 497 | void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| ... | ... | @@ -511,7 +500,6 @@ void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| 511 | 500 | thr->clock.set(thr->fast_state.epoch()); |
| 512 | 501 | thr->fast_synch_epoch = thr->fast_state.epoch(); |
| 513 | 502 | thr->clock.release(&thr->proc()->clock_cache, c); |
| 514 | StatInc(thr, StatSyncRelease); | |
| 515 | 503 | } |
| 516 | 504 | |
| 517 | 505 | void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| ... | ... | @@ -520,7 +508,6 @@ void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| 520 | 508 | thr->clock.set(thr->fast_state.epoch()); |
| 521 | 509 | thr->fast_synch_epoch = thr->fast_state.epoch(); |
| 522 | 510 | thr->clock.ReleaseStore(&thr->proc()->clock_cache, c); |
| 523 | StatInc(thr, StatSyncRelease); | |
| 524 | 511 | } |
| 525 | 512 | |
| 526 | 513 | void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| ... | ... | @@ -529,12 +516,10 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { |
| 529 | 516 | thr->clock.set(thr->fast_state.epoch()); |
| 530 | 517 | thr->fast_synch_epoch = thr->fast_state.epoch(); |
| 531 | 518 | thr->clock.acq_rel(&thr->proc()->clock_cache, c); |
| 532 | StatInc(thr, StatSyncAcquire); | |
| 533 | StatInc(thr, StatSyncRelease); | |
| 534 | 519 | } |
| 535 | 520 | |
| 536 | 521 | void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) { |
| 537 | if (r == 0) | |
| 522 | if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock)) | |
| 538 | 523 | return; |
| 539 | 524 | ThreadRegistryLock l(ctx->thread_registry); |
| 540 | 525 | ScopedReport rep(ReportTypeDeadlock); |
lib/tsan/tsan_rtl_report.cpp+37-27| ... | ... | @@ -31,23 +31,6 @@ using namespace __sanitizer; |
| 31 | 31 | |
| 32 | 32 | static ReportStack *SymbolizeStack(StackTrace trace); |
| 33 | 33 | |
| 34 | void TsanCheckFailed(const char *file, int line, const char *cond, | |
| 35 | u64 v1, u64 v2) { | |
| 36 | // There is high probability that interceptors will check-fail as well, | |
| 37 | // on the other hand there is no sense in processing interceptors | |
| 38 | // since we are going to die soon. | |
| 39 | ScopedIgnoreInterceptors ignore; | |
| 40 | #if !SANITIZER_GO | |
| 41 | cur_thread()->ignore_sync++; | |
| 42 | cur_thread()->ignore_reads_and_writes++; | |
| 43 | #endif | |
| 44 | Printf("FATAL: ThreadSanitizer CHECK failed: " | |
| 45 | "%s:%d \"%s\" (0x%zx, 0x%zx)\n", | |
| 46 | file, line, cond, (uptr)v1, (uptr)v2); | |
| 47 | PrintCurrentStackSlow(StackTrace::GetCurrentPc()); | |
| 48 | Die(); | |
| 49 | } | |
| 50 | ||
| 51 | 34 | // Can be overriden by an application/test to intercept reports. |
| 52 | 35 | #ifdef TSAN_EXTERNAL_HOOKS |
| 53 | 36 | bool OnReport(const ReportDesc *rep, bool suppressed); |
| ... | ... | @@ -142,6 +125,34 @@ static ReportStack *SymbolizeStack(StackTrace trace) { |
| 142 | 125 | return stack; |
| 143 | 126 | } |
| 144 | 127 | |
| 128 | bool ShouldReport(ThreadState *thr, ReportType typ) { | |
| 129 | // We set thr->suppress_reports in the fork context. | |
| 130 | // Taking any locking in the fork context can lead to deadlocks. | |
| 131 | // If any locks are already taken, it's too late to do this check. | |
| 132 | CheckedMutex::CheckNoLocks(); | |
| 133 | // For the same reason check we didn't lock thread_registry yet. | |
| 134 | if (SANITIZER_DEBUG) | |
| 135 | ThreadRegistryLock l(ctx->thread_registry); | |
| 136 | if (!flags()->report_bugs || thr->suppress_reports) | |
| 137 | return false; | |
| 138 | switch (typ) { | |
| 139 | case ReportTypeSignalUnsafe: | |
| 140 | return flags()->report_signal_unsafe; | |
| 141 | case ReportTypeThreadLeak: | |
| 142 | #if !SANITIZER_GO | |
| 143 | // It's impossible to join phantom threads | |
| 144 | // in the child after fork. | |
| 145 | if (ctx->after_multithreaded_fork) | |
| 146 | return false; | |
| 147 | #endif | |
| 148 | return flags()->report_thread_leaks; | |
| 149 | case ReportTypeMutexDestroyLocked: | |
| 150 | return flags()->report_destroy_locked; | |
| 151 | default: | |
| 152 | return true; | |
| 153 | } | |
| 154 | } | |
| 155 | ||
| 145 | 156 | ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) { |
| 146 | 157 | ctx->thread_registry->CheckLocked(); |
| 147 | 158 | void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc)); |
| ... | ... | @@ -274,7 +285,7 @@ void ScopedReportBase::AddMutex(const SyncVar *s) { |
| 274 | 285 | rm->stack = SymbolizeStackId(s->creation_stack_id); |
| 275 | 286 | } |
| 276 | 287 | |
| 277 | u64 ScopedReportBase::AddMutex(u64 id) { | |
| 288 | u64 ScopedReportBase::AddMutex(u64 id) NO_THREAD_SAFETY_ANALYSIS { | |
| 278 | 289 | u64 uid = 0; |
| 279 | 290 | u64 mid = id; |
| 280 | 291 | uptr addr = SyncVar::SplitId(id, &uid); |
| ... | ... | @@ -497,8 +508,10 @@ static bool HandleRacyAddress(ThreadState *thr, uptr addr_min, uptr addr_max) { |
| 497 | 508 | } |
| 498 | 509 | |
| 499 | 510 | bool OutputReport(ThreadState *thr, const ScopedReport &srep) { |
| 500 | if (!flags()->report_bugs || thr->suppress_reports) | |
| 501 | return false; | |
| 511 | // These should have been checked in ShouldReport. | |
| 512 | // It's too late to check them here, we have already taken locks. | |
| 513 | CHECK(flags()->report_bugs); | |
| 514 | CHECK(!thr->suppress_reports); | |
| 502 | 515 | atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime()); |
| 503 | 516 | const ReportDesc *rep = srep.GetReport(); |
| 504 | 517 | CHECK_EQ(thr->current_report, nullptr); |
| ... | ... | @@ -583,13 +596,13 @@ static bool RaceBetweenAtomicAndFree(ThreadState *thr) { |
| 583 | 596 | } |
| 584 | 597 | |
| 585 | 598 | void ReportRace(ThreadState *thr) { |
| 586 | CheckNoLocks(thr); | |
| 599 | CheckedMutex::CheckNoLocks(); | |
| 587 | 600 | |
| 588 | 601 | // Symbolizer makes lots of intercepted calls. If we try to process them, |
| 589 | 602 | // at best it will cause deadlocks on internal mutexes. |
| 590 | 603 | ScopedIgnoreInterceptors ignore; |
| 591 | 604 | |
| 592 | if (!flags()->report_bugs) | |
| 605 | if (!ShouldReport(thr, ReportTypeRace)) | |
| 593 | 606 | return; |
| 594 | 607 | if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr)) |
| 595 | 608 | return; |
| ... | ... | @@ -706,9 +719,7 @@ void ReportRace(ThreadState *thr) { |
| 706 | 719 | } |
| 707 | 720 | #endif |
| 708 | 721 | |
| 709 | if (!OutputReport(thr, rep)) | |
| 710 | return; | |
| 711 | ||
| 722 | OutputReport(thr, rep); | |
| 712 | 723 | } |
| 713 | 724 | |
| 714 | 725 | void PrintCurrentStack(ThreadState *thr, uptr pc) { |
| ... | ... | @@ -724,8 +735,7 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) { |
| 724 | 735 | // However, this solution is not reliable enough, please see dvyukov's comment |
| 725 | 736 | // http://reviews.llvm.org/D19148#406208 |
| 726 | 737 | // Also see PR27280 comment 2 and 3 for breaking examples and analysis. |
| 727 | ALWAYS_INLINE | |
| 728 | void PrintCurrentStackSlow(uptr pc) { | |
| 738 | ALWAYS_INLINE USED void PrintCurrentStackSlow(uptr pc) { | |
| 729 | 739 | #if !SANITIZER_GO |
| 730 | 740 | uptr bp = GET_CURRENT_FRAME(); |
| 731 | 741 | BufferedStackTrace *ptrace = |
lib/tsan/tsan_rtl_thread.cpp+7-18| ... | ... | @@ -51,7 +51,7 @@ struct OnCreatedArgs { |
| 51 | 51 | |
| 52 | 52 | void ThreadContext::OnCreated(void *arg) { |
| 53 | 53 | thr = 0; |
| 54 | if (tid == 0) | |
| 54 | if (tid == kMainTid) | |
| 55 | 55 | return; |
| 56 | 56 | OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg); |
| 57 | 57 | if (!args->thr) // GCD workers don't have a parent thread. |
| ... | ... | @@ -61,8 +61,6 @@ void ThreadContext::OnCreated(void *arg) { |
| 61 | 61 | TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0); |
| 62 | 62 | ReleaseImpl(args->thr, 0, &sync); |
| 63 | 63 | creation_stack_id = CurrentStackId(args->thr, args->pc); |
| 64 | if (reuse_count == 0) | |
| 65 | StatInc(args->thr, StatThreadMaxTid); | |
| 66 | 64 | } |
| 67 | 65 | |
| 68 | 66 | void ThreadContext::OnReset() { |
| ... | ... | @@ -115,7 +113,6 @@ void ThreadContext::OnStarted(void *arg) { |
| 115 | 113 | |
| 116 | 114 | thr->fast_synch_epoch = epoch0; |
| 117 | 115 | AcquireImpl(thr, 0, &sync); |
| 118 | StatInc(thr, StatSyncAcquire); | |
| 119 | 116 | sync.Reset(&thr->proc()->clock_cache); |
| 120 | 117 | thr->is_inited = true; |
| 121 | 118 | DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx " |
| ... | ... | @@ -149,9 +146,6 @@ void ThreadContext::OnFinished() { |
| 149 | 146 | PlatformCleanUpThreadState(thr); |
| 150 | 147 | #endif |
| 151 | 148 | thr->~ThreadState(); |
| 152 | #if TSAN_COLLECT_STATS | |
| 153 | StatAggregate(ctx->stat, thr->stat); | |
| 154 | #endif | |
| 155 | 149 | thr = 0; |
| 156 | 150 | } |
| 157 | 151 | |
| ... | ... | @@ -179,7 +173,7 @@ static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) { |
| 179 | 173 | |
| 180 | 174 | #if !SANITIZER_GO |
| 181 | 175 | static void ReportIgnoresEnabled(ThreadContext *tctx, IgnoreSet *set) { |
| 182 | if (tctx->tid == 0) { | |
| 176 | if (tctx->tid == kMainTid) { | |
| 183 | 177 | Printf("ThreadSanitizer: main thread finished with ignores enabled\n"); |
| 184 | 178 | } else { |
| 185 | 179 | Printf("ThreadSanitizer: thread T%d %s finished with ignores enabled," |
| ... | ... | @@ -210,7 +204,7 @@ static void ThreadCheckIgnore(ThreadState *thr) {} |
| 210 | 204 | void ThreadFinalize(ThreadState *thr) { |
| 211 | 205 | ThreadCheckIgnore(thr); |
| 212 | 206 | #if !SANITIZER_GO |
| 213 | if (!flags()->report_thread_leaks) | |
| 207 | if (!ShouldReport(thr, ReportTypeThreadLeak)) | |
| 214 | 208 | return; |
| 215 | 209 | ThreadRegistryLock l(ctx->thread_registry); |
| 216 | 210 | Vector<ThreadLeak> leaks; |
| ... | ... | @@ -232,13 +226,11 @@ int ThreadCount(ThreadState *thr) { |
| 232 | 226 | } |
| 233 | 227 | |
| 234 | 228 | int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) { |
| 235 | StatInc(thr, StatThreadCreate); | |
| 236 | 229 | OnCreatedArgs args = { thr, pc }; |
| 237 | 230 | u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers. |
| 238 | 231 | int tid = |
| 239 | 232 | ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args); |
| 240 | 233 | DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid); |
| 241 | StatSet(thr, StatThreadMaxAlive, ctx->thread_registry->GetMaxAliveThreads()); | |
| 242 | 234 | return tid; |
| 243 | 235 | } |
| 244 | 236 | |
| ... | ... | @@ -250,9 +242,10 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id, |
| 250 | 242 | uptr tls_size = 0; |
| 251 | 243 | #if !SANITIZER_GO |
| 252 | 244 | if (thread_type != ThreadType::Fiber) |
| 253 | GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size); | |
| 245 | GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_size, &tls_addr, | |
| 246 | &tls_size); | |
| 254 | 247 | |
| 255 | if (tid) { | |
| 248 | if (tid != kMainTid) { | |
| 256 | 249 | if (stk_addr && stk_size) |
| 257 | 250 | MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size); |
| 258 | 251 | |
| ... | ... | @@ -279,7 +272,6 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id, |
| 279 | 272 | |
| 280 | 273 | void ThreadFinish(ThreadState *thr) { |
| 281 | 274 | ThreadCheckIgnore(thr); |
| 282 | StatInc(thr, StatThreadFinish); | |
| 283 | 275 | if (thr->stk_addr && thr->stk_size) |
| 284 | 276 | DontNeedShadowFor(thr->stk_addr, thr->stk_size); |
| 285 | 277 | if (thr->tls_addr && thr->tls_size) |
| ... | ... | @@ -313,7 +305,7 @@ static bool ConsumeThreadByUid(ThreadContextBase *tctx, void *arg) { |
| 313 | 305 | int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) { |
| 314 | 306 | ConsumeThreadContext findCtx = {uid, nullptr}; |
| 315 | 307 | ctx->thread_registry->FindThread(ConsumeThreadByUid, &findCtx); |
| 316 | int tid = findCtx.tctx ? findCtx.tctx->tid : ThreadRegistry::kUnknownTid; | |
| 308 | int tid = findCtx.tctx ? findCtx.tctx->tid : kInvalidTid; | |
| 317 | 309 | DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, tid); |
| 318 | 310 | return tid; |
| 319 | 311 | } |
| ... | ... | @@ -371,13 +363,10 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, |
| 371 | 363 | } |
| 372 | 364 | #endif |
| 373 | 365 | |
| 374 | StatInc(thr, StatMopRange); | |
| 375 | ||
| 376 | 366 | if (*shadow_mem == kShadowRodata) { |
| 377 | 367 | DCHECK(!is_write); |
| 378 | 368 | // Access to .rodata section, no races here. |
| 379 | 369 | // Measurements show that it can be 10-20% of all memory accesses. |
| 380 | StatInc(thr, StatMopRangeRodata); | |
| 381 | 370 | return; |
| 382 | 371 | } |
| 383 | 372 |
lib/tsan/tsan_stack_trace.cpp+3-5| ... | ... | @@ -54,10 +54,8 @@ void __sanitizer::BufferedStackTrace::UnwindImpl( |
| 54 | 54 | uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { |
| 55 | 55 | uptr top = 0; |
| 56 | 56 | uptr bottom = 0; |
| 57 | if (StackTrace::WillUseFastUnwind(request_fast)) { | |
| 58 | GetThreadStackTopAndBottom(false, &top, &bottom); | |
| 59 | Unwind(max_depth, pc, bp, nullptr, top, bottom, true); | |
| 60 | } else | |
| 61 | Unwind(max_depth, pc, 0, context, 0, 0, false); | |
| 57 | GetThreadStackTopAndBottom(false, &top, &bottom); | |
| 58 | bool fast = StackTrace::WillUseFastUnwind(request_fast); | |
| 59 | Unwind(max_depth, pc, bp, context, top, bottom, fast); | |
| 62 | 60 | } |
| 63 | 61 | #endif // SANITIZER_GO |
lib/tsan/tsan_stat.cpp deleted-186| ... | ... | @@ -1,186 +0,0 @@ |
| 1 | //===-- tsan_stat.cpp -----------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is a part of ThreadSanitizer (TSan), a race detector. | |
| 10 | // | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | #include "tsan_stat.h" | |
| 13 | #include "tsan_rtl.h" | |
| 14 | ||
| 15 | namespace __tsan { | |
| 16 | ||
| 17 | #if TSAN_COLLECT_STATS | |
| 18 | ||
| 19 | void StatAggregate(u64 *dst, u64 *src) { | |
| 20 | for (int i = 0; i < StatCnt; i++) | |
| 21 | dst[i] += src[i]; | |
| 22 | } | |
| 23 | ||
| 24 | void StatOutput(u64 *stat) { | |
| 25 | stat[StatShadowNonZero] = stat[StatShadowProcessed] - stat[StatShadowZero]; | |
| 26 | ||
| 27 | static const char *name[StatCnt] = {}; | |
| 28 | name[StatMop] = "Memory accesses "; | |
| 29 | name[StatMopRead] = " Including reads "; | |
| 30 | name[StatMopWrite] = " writes "; | |
| 31 | name[StatMop1] = " Including size 1 "; | |
| 32 | name[StatMop2] = " size 2 "; | |
| 33 | name[StatMop4] = " size 4 "; | |
| 34 | name[StatMop8] = " size 8 "; | |
| 35 | name[StatMopSame] = " Including same "; | |
| 36 | name[StatMopIgnored] = " Including ignored "; | |
| 37 | name[StatMopRange] = " Including range "; | |
| 38 | name[StatMopRodata] = " Including .rodata "; | |
| 39 | name[StatMopRangeRodata] = " Including .rodata range "; | |
| 40 | name[StatShadowProcessed] = "Shadow processed "; | |
| 41 | name[StatShadowZero] = " Including empty "; | |
| 42 | name[StatShadowNonZero] = " Including non empty "; | |
| 43 | name[StatShadowSameSize] = " Including same size "; | |
| 44 | name[StatShadowIntersect] = " intersect "; | |
| 45 | name[StatShadowNotIntersect] = " not intersect "; | |
| 46 | name[StatShadowSameThread] = " Including same thread "; | |
| 47 | name[StatShadowAnotherThread] = " another thread "; | |
| 48 | name[StatShadowReplace] = " Including evicted "; | |
| 49 | ||
| 50 | name[StatFuncEnter] = "Function entries "; | |
| 51 | name[StatFuncExit] = "Function exits "; | |
| 52 | name[StatEvents] = "Events collected "; | |
| 53 | ||
| 54 | name[StatThreadCreate] = "Total threads created "; | |
| 55 | name[StatThreadFinish] = " threads finished "; | |
| 56 | name[StatThreadReuse] = " threads reused "; | |
| 57 | name[StatThreadMaxTid] = " max tid "; | |
| 58 | name[StatThreadMaxAlive] = " max alive threads "; | |
| 59 | ||
| 60 | name[StatMutexCreate] = "Mutexes created "; | |
| 61 | name[StatMutexDestroy] = " destroyed "; | |
| 62 | name[StatMutexLock] = " lock "; | |
| 63 | name[StatMutexUnlock] = " unlock "; | |
| 64 | name[StatMutexRecLock] = " recursive lock "; | |
| 65 | name[StatMutexRecUnlock] = " recursive unlock "; | |
| 66 | name[StatMutexReadLock] = " read lock "; | |
| 67 | name[StatMutexReadUnlock] = " read unlock "; | |
| 68 | ||
| 69 | name[StatSyncCreated] = "Sync objects created "; | |
| 70 | name[StatSyncDestroyed] = " destroyed "; | |
| 71 | name[StatSyncAcquire] = " acquired "; | |
| 72 | name[StatSyncRelease] = " released "; | |
| 73 | ||
| 74 | name[StatClockAcquire] = "Clock acquire "; | |
| 75 | name[StatClockAcquireEmpty] = " empty clock "; | |
| 76 | name[StatClockAcquireFastRelease] = " fast from release-store "; | |
| 77 | name[StatClockAcquireFull] = " full (slow) "; | |
| 78 | name[StatClockAcquiredSomething] = " acquired something "; | |
| 79 | name[StatClockRelease] = "Clock release "; | |
| 80 | name[StatClockReleaseResize] = " resize "; | |
| 81 | name[StatClockReleaseFast] = " fast "; | |
| 82 | name[StatClockReleaseSlow] = " dirty overflow (slow) "; | |
| 83 | name[StatClockReleaseFull] = " full (slow) "; | |
| 84 | name[StatClockReleaseAcquired] = " was acquired "; | |
| 85 | name[StatClockReleaseClearTail] = " clear tail "; | |
| 86 | name[StatClockStore] = "Clock release store "; | |
| 87 | name[StatClockStoreResize] = " resize "; | |
| 88 | name[StatClockStoreFast] = " fast "; | |
| 89 | name[StatClockStoreFull] = " slow "; | |
| 90 | name[StatClockStoreTail] = " clear tail "; | |
| 91 | name[StatClockAcquireRelease] = "Clock acquire-release "; | |
| 92 | ||
| 93 | name[StatAtomic] = "Atomic operations "; | |
| 94 | name[StatAtomicLoad] = " Including load "; | |
| 95 | name[StatAtomicStore] = " store "; | |
| 96 | name[StatAtomicExchange] = " exchange "; | |
| 97 | name[StatAtomicFetchAdd] = " fetch_add "; | |
| 98 | name[StatAtomicFetchSub] = " fetch_sub "; | |
| 99 | name[StatAtomicFetchAnd] = " fetch_and "; | |
| 100 | name[StatAtomicFetchOr] = " fetch_or "; | |
| 101 | name[StatAtomicFetchXor] = " fetch_xor "; | |
| 102 | name[StatAtomicFetchNand] = " fetch_nand "; | |
| 103 | name[StatAtomicCAS] = " compare_exchange "; | |
| 104 | name[StatAtomicFence] = " fence "; | |
| 105 | name[StatAtomicRelaxed] = " Including relaxed "; | |
| 106 | name[StatAtomicConsume] = " consume "; | |
| 107 | name[StatAtomicAcquire] = " acquire "; | |
| 108 | name[StatAtomicRelease] = " release "; | |
| 109 | name[StatAtomicAcq_Rel] = " acq_rel "; | |
| 110 | name[StatAtomicSeq_Cst] = " seq_cst "; | |
| 111 | name[StatAtomic1] = " Including size 1 "; | |
| 112 | name[StatAtomic2] = " size 2 "; | |
| 113 | name[StatAtomic4] = " size 4 "; | |
| 114 | name[StatAtomic8] = " size 8 "; | |
| 115 | name[StatAtomic16] = " size 16 "; | |
| 116 | ||
| 117 | name[StatAnnotation] = "Dynamic annotations "; | |
| 118 | name[StatAnnotateHappensBefore] = " HappensBefore "; | |
| 119 | name[StatAnnotateHappensAfter] = " HappensAfter "; | |
| 120 | name[StatAnnotateCondVarSignal] = " CondVarSignal "; | |
| 121 | name[StatAnnotateCondVarSignalAll] = " CondVarSignalAll "; | |
| 122 | name[StatAnnotateMutexIsNotPHB] = " MutexIsNotPHB "; | |
| 123 | name[StatAnnotateCondVarWait] = " CondVarWait "; | |
| 124 | name[StatAnnotateRWLockCreate] = " RWLockCreate "; | |
| 125 | name[StatAnnotateRWLockCreateStatic] = " StatAnnotateRWLockCreateStatic "; | |
| 126 | name[StatAnnotateRWLockDestroy] = " RWLockDestroy "; | |
| 127 | name[StatAnnotateRWLockAcquired] = " RWLockAcquired "; | |
| 128 | name[StatAnnotateRWLockReleased] = " RWLockReleased "; | |
| 129 | name[StatAnnotateTraceMemory] = " TraceMemory "; | |
| 130 | name[StatAnnotateFlushState] = " FlushState "; | |
| 131 | name[StatAnnotateNewMemory] = " NewMemory "; | |
| 132 | name[StatAnnotateNoOp] = " NoOp "; | |
| 133 | name[StatAnnotateFlushExpectedRaces] = " FlushExpectedRaces "; | |
| 134 | name[StatAnnotateEnableRaceDetection] = " EnableRaceDetection "; | |
| 135 | name[StatAnnotateMutexIsUsedAsCondVar] = " MutexIsUsedAsCondVar "; | |
| 136 | name[StatAnnotatePCQGet] = " PCQGet "; | |
| 137 | name[StatAnnotatePCQPut] = " PCQPut "; | |
| 138 | name[StatAnnotatePCQDestroy] = " PCQDestroy "; | |
| 139 | name[StatAnnotatePCQCreate] = " PCQCreate "; | |
| 140 | name[StatAnnotateExpectRace] = " ExpectRace "; | |
| 141 | name[StatAnnotateBenignRaceSized] = " BenignRaceSized "; | |
| 142 | name[StatAnnotateBenignRace] = " BenignRace "; | |
| 143 | name[StatAnnotateIgnoreReadsBegin] = " IgnoreReadsBegin "; | |
| 144 | name[StatAnnotateIgnoreReadsEnd] = " IgnoreReadsEnd "; | |
| 145 | name[StatAnnotateIgnoreWritesBegin] = " IgnoreWritesBegin "; | |
| 146 | name[StatAnnotateIgnoreWritesEnd] = " IgnoreWritesEnd "; | |
| 147 | name[StatAnnotateIgnoreSyncBegin] = " IgnoreSyncBegin "; | |
| 148 | name[StatAnnotateIgnoreSyncEnd] = " IgnoreSyncEnd "; | |
| 149 | name[StatAnnotatePublishMemoryRange] = " PublishMemoryRange "; | |
| 150 | name[StatAnnotateUnpublishMemoryRange] = " UnpublishMemoryRange "; | |
| 151 | name[StatAnnotateThreadName] = " ThreadName "; | |
| 152 | name[Stat__tsan_mutex_create] = " __tsan_mutex_create "; | |
| 153 | name[Stat__tsan_mutex_destroy] = " __tsan_mutex_destroy "; | |
| 154 | name[Stat__tsan_mutex_pre_lock] = " __tsan_mutex_pre_lock "; | |
| 155 | name[Stat__tsan_mutex_post_lock] = " __tsan_mutex_post_lock "; | |
| 156 | name[Stat__tsan_mutex_pre_unlock] = " __tsan_mutex_pre_unlock "; | |
| 157 | name[Stat__tsan_mutex_post_unlock] = " __tsan_mutex_post_unlock "; | |
| 158 | name[Stat__tsan_mutex_pre_signal] = " __tsan_mutex_pre_signal "; | |
| 159 | name[Stat__tsan_mutex_post_signal] = " __tsan_mutex_post_signal "; | |
| 160 | name[Stat__tsan_mutex_pre_divert] = " __tsan_mutex_pre_divert "; | |
| 161 | name[Stat__tsan_mutex_post_divert] = " __tsan_mutex_post_divert "; | |
| 162 | ||
| 163 | name[StatMtxTotal] = "Contentionz "; | |
| 164 | name[StatMtxTrace] = " Trace "; | |
| 165 | name[StatMtxThreads] = " Threads "; | |
| 166 | name[StatMtxReport] = " Report "; | |
| 167 | name[StatMtxSyncVar] = " SyncVar "; | |
| 168 | name[StatMtxSyncTab] = " SyncTab "; | |
| 169 | name[StatMtxSlab] = " Slab "; | |
| 170 | name[StatMtxAtExit] = " Atexit "; | |
| 171 | name[StatMtxAnnotations] = " Annotations "; | |
| 172 | name[StatMtxMBlock] = " MBlock "; | |
| 173 | name[StatMtxDeadlockDetector] = " DeadlockDetector "; | |
| 174 | name[StatMtxFired] = " FiredSuppressions "; | |
| 175 | name[StatMtxRacy] = " RacyStacks "; | |
| 176 | name[StatMtxFD] = " FD "; | |
| 177 | name[StatMtxGlobalProc] = " GlobalProc "; | |
| 178 | ||
| 179 | Printf("Statistics:\n"); | |
| 180 | for (int i = 0; i < StatCnt; i++) | |
| 181 | Printf("%s: %16zu\n", name[i], (uptr)stat[i]); | |
| 182 | } | |
| 183 | ||
| 184 | #endif | |
| 185 | ||
| 186 | } // namespace __tsan |
lib/tsan/tsan_stat.h deleted-191| ... | ... | @@ -1,191 +0,0 @@ |
| 1 | //===-- tsan_stat.h ---------------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // This file is a part of ThreadSanitizer (TSan), a race detector. | |
| 10 | // | |
| 11 | //===----------------------------------------------------------------------===// | |
| 12 | ||
| 13 | #ifndef TSAN_STAT_H | |
| 14 | #define TSAN_STAT_H | |
| 15 | ||
| 16 | namespace __tsan { | |
| 17 | ||
| 18 | enum StatType { | |
| 19 | // Memory access processing related stuff. | |
| 20 | StatMop, | |
| 21 | StatMopRead, | |
| 22 | StatMopWrite, | |
| 23 | StatMop1, // These must be consequtive. | |
| 24 | StatMop2, | |
| 25 | StatMop4, | |
| 26 | StatMop8, | |
| 27 | StatMopSame, | |
| 28 | StatMopIgnored, | |
| 29 | StatMopRange, | |
| 30 | StatMopRodata, | |
| 31 | StatMopRangeRodata, | |
| 32 | StatShadowProcessed, | |
| 33 | StatShadowZero, | |
| 34 | StatShadowNonZero, // Derived. | |
| 35 | StatShadowSameSize, | |
| 36 | StatShadowIntersect, | |
| 37 | StatShadowNotIntersect, | |
| 38 | StatShadowSameThread, | |
| 39 | StatShadowAnotherThread, | |
| 40 | StatShadowReplace, | |
| 41 | ||
| 42 | // Func processing. | |
| 43 | StatFuncEnter, | |
| 44 | StatFuncExit, | |
| 45 | ||
| 46 | // Trace processing. | |
| 47 | StatEvents, | |
| 48 | ||
| 49 | // Threads. | |
| 50 | StatThreadCreate, | |
| 51 | StatThreadFinish, | |
| 52 | StatThreadReuse, | |
| 53 | StatThreadMaxTid, | |
| 54 | StatThreadMaxAlive, | |
| 55 | ||
| 56 | // Mutexes. | |
| 57 | StatMutexCreate, | |
| 58 | StatMutexDestroy, | |
| 59 | StatMutexLock, | |
| 60 | StatMutexUnlock, | |
| 61 | StatMutexRecLock, | |
| 62 | StatMutexRecUnlock, | |
| 63 | StatMutexReadLock, | |
| 64 | StatMutexReadUnlock, | |
| 65 | ||
| 66 | // Synchronization. | |
| 67 | StatSyncCreated, | |
| 68 | StatSyncDestroyed, | |
| 69 | StatSyncAcquire, | |
| 70 | StatSyncRelease, | |
| 71 | StatSyncReleaseStoreAcquire, | |
| 72 | ||
| 73 | // Clocks - acquire. | |
| 74 | StatClockAcquire, | |
| 75 | StatClockAcquireEmpty, | |
| 76 | StatClockAcquireFastRelease, | |
| 77 | StatClockAcquireFull, | |
| 78 | StatClockAcquiredSomething, | |
| 79 | // Clocks - release. | |
| 80 | StatClockRelease, | |
| 81 | StatClockReleaseResize, | |
| 82 | StatClockReleaseFast, | |
| 83 | StatClockReleaseSlow, | |
| 84 | StatClockReleaseFull, | |
| 85 | StatClockReleaseAcquired, | |
| 86 | StatClockReleaseClearTail, | |
| 87 | // Clocks - release store. | |
| 88 | StatClockStore, | |
| 89 | StatClockStoreResize, | |
| 90 | StatClockStoreFast, | |
| 91 | StatClockStoreFull, | |
| 92 | StatClockStoreTail, | |
| 93 | // Clocks - acquire-release. | |
| 94 | StatClockAcquireRelease, | |
| 95 | ||
| 96 | // Atomics. | |
| 97 | StatAtomic, | |
| 98 | StatAtomicLoad, | |
| 99 | StatAtomicStore, | |
| 100 | StatAtomicExchange, | |
| 101 | StatAtomicFetchAdd, | |
| 102 | StatAtomicFetchSub, | |
| 103 | StatAtomicFetchAnd, | |
| 104 | StatAtomicFetchOr, | |
| 105 | StatAtomicFetchXor, | |
| 106 | StatAtomicFetchNand, | |
| 107 | StatAtomicCAS, | |
| 108 | StatAtomicFence, | |
| 109 | StatAtomicRelaxed, | |
| 110 | StatAtomicConsume, | |
| 111 | StatAtomicAcquire, | |
| 112 | StatAtomicRelease, | |
| 113 | StatAtomicAcq_Rel, | |
| 114 | StatAtomicSeq_Cst, | |
| 115 | StatAtomic1, | |
| 116 | StatAtomic2, | |
| 117 | StatAtomic4, | |
| 118 | StatAtomic8, | |
| 119 | StatAtomic16, | |
| 120 | ||
| 121 | // Dynamic annotations. | |
| 122 | StatAnnotation, | |
| 123 | StatAnnotateHappensBefore, | |
| 124 | StatAnnotateHappensAfter, | |
| 125 | StatAnnotateCondVarSignal, | |
| 126 | StatAnnotateCondVarSignalAll, | |
| 127 | StatAnnotateMutexIsNotPHB, | |
| 128 | StatAnnotateCondVarWait, | |
| 129 | StatAnnotateRWLockCreate, | |
| 130 | StatAnnotateRWLockCreateStatic, | |
| 131 | StatAnnotateRWLockDestroy, | |
| 132 | StatAnnotateRWLockAcquired, | |
| 133 | StatAnnotateRWLockReleased, | |
| 134 | StatAnnotateTraceMemory, | |
| 135 | StatAnnotateFlushState, | |
| 136 | StatAnnotateNewMemory, | |
| 137 | StatAnnotateNoOp, | |
| 138 | StatAnnotateFlushExpectedRaces, | |
| 139 | StatAnnotateEnableRaceDetection, | |
| 140 | StatAnnotateMutexIsUsedAsCondVar, | |
| 141 | StatAnnotatePCQGet, | |
| 142 | StatAnnotatePCQPut, | |
| 143 | StatAnnotatePCQDestroy, | |
| 144 | StatAnnotatePCQCreate, | |
| 145 | StatAnnotateExpectRace, | |
| 146 | StatAnnotateBenignRaceSized, | |
| 147 | StatAnnotateBenignRace, | |
| 148 | StatAnnotateIgnoreReadsBegin, | |
| 149 | StatAnnotateIgnoreReadsEnd, | |
| 150 | StatAnnotateIgnoreWritesBegin, | |
| 151 | StatAnnotateIgnoreWritesEnd, | |
| 152 | StatAnnotateIgnoreSyncBegin, | |
| 153 | StatAnnotateIgnoreSyncEnd, | |
| 154 | StatAnnotatePublishMemoryRange, | |
| 155 | StatAnnotateUnpublishMemoryRange, | |
| 156 | StatAnnotateThreadName, | |
| 157 | Stat__tsan_mutex_create, | |
| 158 | Stat__tsan_mutex_destroy, | |
| 159 | Stat__tsan_mutex_pre_lock, | |
| 160 | Stat__tsan_mutex_post_lock, | |
| 161 | Stat__tsan_mutex_pre_unlock, | |
| 162 | Stat__tsan_mutex_post_unlock, | |
| 163 | Stat__tsan_mutex_pre_signal, | |
| 164 | Stat__tsan_mutex_post_signal, | |
| 165 | Stat__tsan_mutex_pre_divert, | |
| 166 | Stat__tsan_mutex_post_divert, | |
| 167 | ||
| 168 | // Internal mutex contentionz. | |
| 169 | StatMtxTotal, | |
| 170 | StatMtxTrace, | |
| 171 | StatMtxThreads, | |
| 172 | StatMtxReport, | |
| 173 | StatMtxSyncVar, | |
| 174 | StatMtxSyncTab, | |
| 175 | StatMtxSlab, | |
| 176 | StatMtxAnnotations, | |
| 177 | StatMtxAtExit, | |
| 178 | StatMtxMBlock, | |
| 179 | StatMtxDeadlockDetector, | |
| 180 | StatMtxFired, | |
| 181 | StatMtxRacy, | |
| 182 | StatMtxFD, | |
| 183 | StatMtxGlobalProc, | |
| 184 | ||
| 185 | // This must be the last. | |
| 186 | StatCnt | |
| 187 | }; | |
| 188 | ||
| 189 | } // namespace __tsan | |
| 190 | ||
| 191 | #endif // TSAN_STAT_H |
lib/tsan/tsan_sync.cpp+6-9| ... | ... | @@ -18,10 +18,7 @@ namespace __tsan { |
| 18 | 18 | |
| 19 | 19 | void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s); |
| 20 | 20 | |
| 21 | SyncVar::SyncVar() | |
| 22 | : mtx(MutexTypeSyncVar, StatMtxSyncVar) { | |
| 23 | Reset(0); | |
| 24 | } | |
| 21 | SyncVar::SyncVar() : mtx(MutexTypeSyncVar) { Reset(0); } | |
| 25 | 22 | |
| 26 | 23 | void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid) { |
| 27 | 24 | this->addr = addr; |
| ... | ... | @@ -53,8 +50,8 @@ void SyncVar::Reset(Processor *proc) { |
| 53 | 50 | } |
| 54 | 51 | |
| 55 | 52 | MetaMap::MetaMap() |
| 56 | : block_alloc_("heap block allocator") | |
| 57 | , sync_alloc_("sync allocator") { | |
| 53 | : block_alloc_(LINKER_INITIALIZED, "heap block allocator"), | |
| 54 | sync_alloc_(LINKER_INITIALIZED, "sync allocator") { | |
| 58 | 55 | atomic_store(&uid_gen_, 0, memory_order_relaxed); |
| 59 | 56 | } |
| 60 | 57 | |
| ... | ... | @@ -175,7 +172,7 @@ void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz) { |
| 175 | 172 | uptr metap = (uptr)MemToMeta(p0); |
| 176 | 173 | uptr metasz = sz0 / kMetaRatio; |
| 177 | 174 | UnmapOrDie((void*)metap, metasz); |
| 178 | if (!MmapFixedNoReserve(metap, metasz)) | |
| 175 | if (!MmapFixedSuperNoReserve(metap, metasz)) | |
| 179 | 176 | Die(); |
| 180 | 177 | } |
| 181 | 178 | |
| ... | ... | @@ -202,8 +199,8 @@ SyncVar* MetaMap::GetIfExistsAndLock(uptr addr, bool write_lock) { |
| 202 | 199 | return GetAndLock(0, 0, addr, write_lock, false); |
| 203 | 200 | } |
| 204 | 201 | |
| 205 | SyncVar* MetaMap::GetAndLock(ThreadState *thr, uptr pc, | |
| 206 | uptr addr, bool write_lock, bool create) { | |
| 202 | SyncVar *MetaMap::GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock, | |
| 203 | bool create) NO_THREAD_SAFETY_ANALYSIS { | |
| 207 | 204 | u32 *meta = MemToMeta(addr); |
| 208 | 205 | u32 idx0 = *meta; |
| 209 | 206 | u32 myidx = 0; |
lib/tsan/tsan_sync.h+3-6| ... | ... | @@ -17,7 +17,6 @@ |
| 17 | 17 | #include "sanitizer_common/sanitizer_deadlock_detector_interface.h" |
| 18 | 18 | #include "tsan_defs.h" |
| 19 | 19 | #include "tsan_clock.h" |
| 20 | #include "tsan_mutex.h" | |
| 21 | 20 | #include "tsan_dense_alloc.h" |
| 22 | 21 | |
| 23 | 22 | namespace __tsan { |
| ... | ... | @@ -50,13 +49,11 @@ enum MutexFlags { |
| 50 | 49 | struct SyncVar { |
| 51 | 50 | SyncVar(); |
| 52 | 51 | |
| 53 | static const int kInvalidTid = -1; | |
| 54 | ||
| 55 | 52 | uptr addr; // overwritten by DenseSlabAlloc freelist |
| 56 | 53 | Mutex mtx; |
| 57 | 54 | u64 uid; // Globally unique id. |
| 58 | 55 | u32 creation_stack_id; |
| 59 | int owner_tid; // Set only by exclusive owners. | |
| 56 | u32 owner_tid; // Set only by exclusive owners. | |
| 60 | 57 | u64 last_lock; |
| 61 | 58 | int recursion; |
| 62 | 59 | atomic_uint32_t flags; |
| ... | ... | @@ -130,8 +127,8 @@ class MetaMap { |
| 130 | 127 | static const u32 kFlagMask = 3u << 30; |
| 131 | 128 | static const u32 kFlagBlock = 1u << 30; |
| 132 | 129 | static const u32 kFlagSync = 2u << 30; |
| 133 | typedef DenseSlabAlloc<MBlock, 1<<16, 1<<12> BlockAlloc; | |
| 134 | typedef DenseSlabAlloc<SyncVar, 1<<16, 1<<10> SyncAlloc; | |
| 130 | typedef DenseSlabAlloc<MBlock, 1 << 18, 1 << 12, kFlagMask> BlockAlloc; | |
| 131 | typedef DenseSlabAlloc<SyncVar, 1 << 20, 1 << 10, kFlagMask> SyncAlloc; | |
| 135 | 132 | BlockAlloc block_alloc_; |
| 136 | 133 | SyncAlloc sync_alloc_; |
| 137 | 134 | atomic_uint64_t uid_gen_; |
lib/tsan/tsan_trace.h+1-4| ... | ... | @@ -13,7 +13,6 @@ |
| 13 | 13 | #define TSAN_TRACE_H |
| 14 | 14 | |
| 15 | 15 | #include "tsan_defs.h" |
| 16 | #include "tsan_mutex.h" | |
| 17 | 16 | #include "tsan_stack_trace.h" |
| 18 | 17 | #include "tsan_mutexset.h" |
| 19 | 18 | |
| ... | ... | @@ -65,9 +64,7 @@ struct Trace { |
| 65 | 64 | // CreateThreadContext. |
| 66 | 65 | TraceHeader headers[kTraceParts]; |
| 67 | 66 | |
| 68 | Trace() | |
| 69 | : mtx(MutexTypeTrace, StatMtxTrace) { | |
| 70 | } | |
| 67 | Trace() : mtx(MutexTypeTrace) {} | |
| 71 | 68 | }; |
| 72 | 69 | |
| 73 | 70 | } // namespace __tsan |
lib/tsan/tsan_update_shadow_word_inl.h+1-11| ... | ... | @@ -13,12 +13,10 @@ |
| 13 | 13 | // produce sligtly less efficient code. |
| 14 | 14 | //===----------------------------------------------------------------------===// |
| 15 | 15 | do { |
| 16 | StatInc(thr, StatShadowProcessed); | |
| 17 | 16 | const unsigned kAccessSize = 1 << kAccessSizeLog; |
| 18 | 17 | u64 *sp = &shadow_mem[idx]; |
| 19 | 18 | old = LoadShadow(sp); |
| 20 | 19 | if (LIKELY(old.IsZero())) { |
| 21 | StatInc(thr, StatShadowZero); | |
| 22 | 20 | if (!stored) { |
| 23 | 21 | StoreIfNotYetStored(sp, &store_word); |
| 24 | 22 | stored = true; |
| ... | ... | @@ -27,17 +25,14 @@ do { |
| 27 | 25 | } |
| 28 | 26 | // is the memory access equal to the previous? |
| 29 | 27 | if (LIKELY(Shadow::Addr0AndSizeAreEqual(cur, old))) { |
| 30 | StatInc(thr, StatShadowSameSize); | |
| 31 | 28 | // same thread? |
| 32 | 29 | if (LIKELY(Shadow::TidsAreEqual(old, cur))) { |
| 33 | StatInc(thr, StatShadowSameThread); | |
| 34 | 30 | if (LIKELY(old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic))) { |
| 35 | 31 | StoreIfNotYetStored(sp, &store_word); |
| 36 | 32 | stored = true; |
| 37 | 33 | } |
| 38 | 34 | break; |
| 39 | 35 | } |
| 40 | StatInc(thr, StatShadowAnotherThread); | |
| 41 | 36 | if (HappensBefore(old, thr)) { |
| 42 | 37 | if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic)) { |
| 43 | 38 | StoreIfNotYetStored(sp, &store_word); |
| ... | ... | @@ -51,12 +46,8 @@ do { |
| 51 | 46 | } |
| 52 | 47 | // Do the memory access intersect? |
| 53 | 48 | if (Shadow::TwoRangesIntersect(old, cur, kAccessSize)) { |
| 54 | StatInc(thr, StatShadowIntersect); | |
| 55 | if (Shadow::TidsAreEqual(old, cur)) { | |
| 56 | StatInc(thr, StatShadowSameThread); | |
| 49 | if (Shadow::TidsAreEqual(old, cur)) | |
| 57 | 50 | break; |
| 58 | } | |
| 59 | StatInc(thr, StatShadowAnotherThread); | |
| 60 | 51 | if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic)) |
| 61 | 52 | break; |
| 62 | 53 | if (LIKELY(HappensBefore(old, thr))) |
| ... | ... | @@ -64,6 +55,5 @@ do { |
| 64 | 55 | goto RACE; |
| 65 | 56 | } |
| 66 | 57 | // The accesses do not intersect. |
| 67 | StatInc(thr, StatShadowNotIntersect); | |
| 68 | 58 | break; |
| 69 | 59 | } while (0); |
lib/tsan/ubsan/ubsan_flags.h-2| ... | ... | @@ -34,8 +34,6 @@ inline Flags *flags() { return &ubsan_flags; } |
| 34 | 34 | void InitializeFlags(); |
| 35 | 35 | void RegisterUbsanFlags(FlagParser *parser, Flags *f); |
| 36 | 36 | |
| 37 | const char *MaybeCallUbsanDefaultOptions(); | |
| 38 | ||
| 39 | 37 | } // namespace __ubsan |
| 40 | 38 | |
| 41 | 39 | extern "C" { |
lib/tsan/ubsan/ubsan_platform.h+4-4| ... | ... | @@ -14,10 +14,10 @@ |
| 14 | 14 | |
| 15 | 15 | // Other platforms should be easy to add, and probably work as-is. |
| 16 | 16 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ |
| 17 | defined(__NetBSD__) || defined(__OpenBSD__) || \ | |
| 18 | (defined(__sun__) && defined(__svr4__)) || \ | |
| 19 | defined(_WIN32) || defined(__Fuchsia__) || defined(__rtems__) | |
| 20 | # define CAN_SANITIZE_UB 1 | |
| 17 | defined(__NetBSD__) || defined(__DragonFly__) || \ | |
| 18 | (defined(__sun__) && defined(__svr4__)) || defined(_WIN32) || \ | |
| 19 | defined(__Fuchsia__) | |
| 20 | #define CAN_SANITIZE_UB 1 | |
| 21 | 21 | #else |
| 22 | 22 | # define CAN_SANITIZE_UB 0 |
| 23 | 23 | #endif |
src/Cache.zig+1-1| ... | ... | @@ -210,7 +210,7 @@ pub const Manifest = struct { |
| 210 | 210 | pub fn addFile(self: *Manifest, file_path: []const u8, max_file_size: ?usize) !usize { |
| 211 | 211 | assert(self.manifest_file == null); |
| 212 | 212 | |
| 213 | try self.files.ensureCapacity(self.cache.gpa, self.files.items.len + 1); | |
| 213 | try self.files.ensureUnusedCapacity(self.cache.gpa, 1); | |
| 214 | 214 | const resolved_path = try fs.path.resolve(self.cache.gpa, &[_][]const u8{file_path}); |
| 215 | 215 | |
| 216 | 216 | const idx = self.files.items.len; |
src/Compilation.zig+4-2| ... | ... | @@ -2666,7 +2666,7 @@ fn reportRetryableCObjectError( |
| 2666 | 2666 | |
| 2667 | 2667 | const c_obj_err_msg = try comp.gpa.create(CObject.ErrorMsg); |
| 2668 | 2668 | errdefer comp.gpa.destroy(c_obj_err_msg); |
| 2669 | const msg = try std.fmt.allocPrint(comp.gpa, "unable to build C object: {s}", .{@errorName(err)}); | |
| 2669 | const msg = try std.fmt.allocPrint(comp.gpa, "{s}", .{@errorName(err)}); | |
| 2670 | 2670 | errdefer comp.gpa.free(msg); |
| 2671 | 2671 | c_obj_err_msg.* = .{ |
| 2672 | 2672 | .msg = msg, |
| ... | ... | @@ -2742,6 +2742,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 2742 | 2742 | const tracy = trace(@src()); |
| 2743 | 2743 | defer tracy.end(); |
| 2744 | 2744 | |
| 2745 | log.debug("updating C object: {s}", .{c_object.src.src_path}); | |
| 2746 | ||
| 2745 | 2747 | if (c_object.clearStatus(comp.gpa)) { |
| 2746 | 2748 | // There was previous failure. |
| 2747 | 2749 | const lock = comp.mutex.acquire(); |
| ... | ... | @@ -3271,7 +3273,7 @@ fn failCObjWithOwnedErrorMsg( |
| 3271 | 3273 | defer lock.release(); |
| 3272 | 3274 | { |
| 3273 | 3275 | errdefer err_msg.destroy(comp.gpa); |
| 3274 | try comp.failed_c_objects.ensureCapacity(comp.gpa, comp.failed_c_objects.count() + 1); | |
| 3276 | try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1); | |
| 3275 | 3277 | } |
| 3276 | 3278 | comp.failed_c_objects.putAssumeCapacityNoClobber(c_object, err_msg); |
| 3277 | 3279 | } |
src/libcxx.zig+2| ... | ... | @@ -45,6 +45,7 @@ const libcxx_files = [_][]const u8{ |
| 45 | 45 | "src/filesystem/directory_iterator.cpp", |
| 46 | 46 | "src/filesystem/int128_builtins.cpp", |
| 47 | 47 | "src/filesystem/operations.cpp", |
| 48 | "src/format.cpp", | |
| 48 | 49 | "src/functional.cpp", |
| 49 | 50 | "src/future.cpp", |
| 50 | 51 | "src/hash.cpp", |
| ... | ... | @@ -64,6 +65,7 @@ const libcxx_files = [_][]const u8{ |
| 64 | 65 | "src/stdexcept.cpp", |
| 65 | 66 | "src/string.cpp", |
| 66 | 67 | "src/strstream.cpp", |
| 68 | "src/support/ibm/xlocale_zos.cpp", | |
| 67 | 69 | "src/support/solaris/xlocale.cpp", |
| 68 | 70 | "src/support/win32/locale_win32.cpp", |
| 69 | 71 | "src/support/win32/support.cpp", |
src/libtsan.zig+4-6| ... | ... | @@ -260,7 +260,6 @@ const tsan_sources = [_][]const u8{ |
| 260 | 260 | "tsan_malloc_mac.cpp", |
| 261 | 261 | "tsan_md5.cpp", |
| 262 | 262 | "tsan_mman.cpp", |
| 263 | "tsan_mutex.cpp", | |
| 264 | 263 | "tsan_mutexset.cpp", |
| 265 | 264 | "tsan_preinit.cpp", |
| 266 | 265 | "tsan_report.cpp", |
| ... | ... | @@ -270,7 +269,6 @@ const tsan_sources = [_][]const u8{ |
| 270 | 269 | "tsan_rtl_report.cpp", |
| 271 | 270 | "tsan_rtl_thread.cpp", |
| 272 | 271 | "tsan_stack_trace.cpp", |
| 273 | "tsan_stat.cpp", | |
| 274 | 272 | "tsan_suppressions.cpp", |
| 275 | 273 | "tsan_symbolize.cpp", |
| 276 | 274 | "tsan_sync.cpp", |
| ... | ... | @@ -295,14 +293,15 @@ const sanitizer_common_sources = [_][]const u8{ |
| 295 | 293 | "sanitizer_deadlock_detector2.cpp", |
| 296 | 294 | "sanitizer_errno.cpp", |
| 297 | 295 | "sanitizer_file.cpp", |
| 298 | "sanitizer_flags.cpp", | |
| 299 | 296 | "sanitizer_flag_parser.cpp", |
| 297 | "sanitizer_flags.cpp", | |
| 300 | 298 | "sanitizer_fuchsia.cpp", |
| 301 | 299 | "sanitizer_libc.cpp", |
| 302 | 300 | "sanitizer_libignore.cpp", |
| 303 | 301 | "sanitizer_linux.cpp", |
| 304 | 302 | "sanitizer_linux_s390.cpp", |
| 305 | 303 | "sanitizer_mac.cpp", |
| 304 | "sanitizer_mutex.cpp", | |
| 306 | 305 | "sanitizer_netbsd.cpp", |
| 307 | 306 | "sanitizer_openbsd.cpp", |
| 308 | 307 | "sanitizer_persistent_allocator.cpp", |
| ... | ... | @@ -314,20 +313,19 @@ const sanitizer_common_sources = [_][]const u8{ |
| 314 | 313 | "sanitizer_platform_limits_solaris.cpp", |
| 315 | 314 | "sanitizer_posix.cpp", |
| 316 | 315 | "sanitizer_printf.cpp", |
| 317 | "sanitizer_procmaps_common.cpp", | |
| 318 | 316 | "sanitizer_procmaps_bsd.cpp", |
| 317 | "sanitizer_procmaps_common.cpp", | |
| 319 | 318 | "sanitizer_procmaps_fuchsia.cpp", |
| 320 | 319 | "sanitizer_procmaps_linux.cpp", |
| 321 | 320 | "sanitizer_procmaps_mac.cpp", |
| 322 | 321 | "sanitizer_procmaps_solaris.cpp", |
| 323 | "sanitizer_rtems.cpp", | |
| 324 | 322 | "sanitizer_solaris.cpp", |
| 325 | 323 | "sanitizer_stoptheworld_fuchsia.cpp", |
| 326 | 324 | "sanitizer_stoptheworld_mac.cpp", |
| 327 | 325 | "sanitizer_suppressions.cpp", |
| 328 | 326 | "sanitizer_termination.cpp", |
| 329 | "sanitizer_tls_get_addr.cpp", | |
| 330 | 327 | "sanitizer_thread_registry.cpp", |
| 328 | "sanitizer_tls_get_addr.cpp", | |
| 331 | 329 | "sanitizer_type_traits.cpp", |
| 332 | 330 | "sanitizer_win.cpp", |
| 333 | 331 | }; |