diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index a672f8b2b39..f25b8b76df6 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -5054,8 +5054,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO * @param __last1 Another iterator. * @param __last2 Another iterator. * @param __result An iterator pointing to the end of the merged range. - * @return An iterator pointing to the first element not less - * than @e val. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). * * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into * the sorted range @p [__result, __result + (__last1-__first1) + @@ -5102,8 +5102,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO * @param __last2 Another iterator. * @param __result An iterator pointing to the end of the merged range. * @param __comp A functor to use for comparisons. - * @return An iterator pointing to the first element "not less - * than" @e val. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). * * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into * the sorted range @p [__result, __result + (__last1-__first1) + diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h index f87838692c6..8c385b87244 100644 --- a/libstdc++-v3/include/debug/functions.h +++ b/libstdc++-v3/include/debug/functions.h @@ -219,6 +219,7 @@ namespace __gnu_debug // Can't check if an input iterator sequence is sorted, because we // can't step through the sequence. template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_aux(const _InputIterator&, const _InputIterator&, std::input_iterator_tag) @@ -227,6 +228,7 @@ namespace __gnu_debug // Can verify if a forward iterator sequence is in fact sorted using // std::__is_sorted template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag) @@ -245,6 +247,7 @@ namespace __gnu_debug // Can't check if an input iterator sequence is sorted, because we can't step // through the sequence. template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_aux(const _InputIterator&, const _InputIterator&, _Predicate, std::input_iterator_tag) @@ -253,6 +256,7 @@ namespace __gnu_debug // Can verify if a forward iterator sequence is in fact sorted using // std::__is_sorted template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, std::forward_iterator_tag) @@ -270,31 +274,26 @@ namespace __gnu_debug // Determine if a sequence is sorted. template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted(const _InputIterator& __first, const _InputIterator& __last) { - // Verify that the < operator for elements in the sequence is a - // StrictWeakOrdering by checking that it is irreflexive. - __glibcxx_assert(__first == __last || !(*__first < *__first)); - return __check_sorted_aux(__first, __last, std::__iterator_category(__first)); } template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted(const _InputIterator& __first, const _InputIterator& __last, _Predicate __pred) { - // Verify that the predicate is StrictWeakOrdering by checking that it - // is irreflexive. - __glibcxx_assert(__first == __last || !__pred(*__first, *__first)); - return __check_sorted_aux(__first, __last, __pred, std::__iterator_category(__first)); } template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_set_aux(const _InputIterator& __first, const _InputIterator& __last, @@ -302,6 +301,7 @@ namespace __gnu_debug { return __check_sorted(__first, __last); } template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_set_aux(const _InputIterator&, const _InputIterator&, @@ -309,6 +309,7 @@ namespace __gnu_debug { return true; } template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_set_aux(const _InputIterator& __first, const _InputIterator& __last, @@ -316,6 +317,7 @@ namespace __gnu_debug { return __check_sorted(__first, __last, __pred); } template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_set_aux(const _InputIterator&, const _InputIterator&, _Predicate, @@ -324,6 +326,7 @@ namespace __gnu_debug // ... special variant used in std::merge, std::includes, std::set_*. template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_set(const _InputIterator1& __first, const _InputIterator1& __last, @@ -341,6 +344,7 @@ namespace __gnu_debug template + _GLIBCXX20_CONSTEXPR inline bool __check_sorted_set(const _InputIterator1& __first, const _InputIterator1& __last, @@ -360,6 +364,7 @@ namespace __gnu_debug // 270. Binary search requirements overly strict // Determine if a sequence is partitioned w.r.t. this element. template + _GLIBCXX20_CONSTEXPR inline bool __check_partitioned_lower(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) @@ -376,6 +381,7 @@ namespace __gnu_debug } template + _GLIBCXX20_CONSTEXPR inline bool __check_partitioned_upper(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) @@ -393,6 +399,7 @@ namespace __gnu_debug // Determine if a sequence is partitioned w.r.t. this element. template + _GLIBCXX20_CONSTEXPR inline bool __check_partitioned_lower(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, @@ -410,6 +417,7 @@ namespace __gnu_debug } template + _GLIBCXX20_CONSTEXPR inline bool __check_partitioned_upper(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, @@ -435,35 +443,41 @@ namespace __gnu_debug template() < __deref<_It>())> + _GLIBCXX20_CONSTEXPR static bool _S_is_valid(_It __it) { return !(*__it < *__it); } // Fallback method if operator doesn't exist. template + _GLIBCXX20_CONSTEXPR static bool _S_is_valid(_Args...) { return true; } template()(__deref<_It>(), __deref<_It>()))> + _GLIBCXX20_CONSTEXPR static bool _S_is_valid_pred(_It __it, _Pred __pred) { return !__pred(*__it, *__it); } // Fallback method if predicate can't be invoked. template + _GLIBCXX20_CONSTEXPR static bool _S_is_valid_pred(_Args...) { return true; } }; template + _GLIBCXX20_CONSTEXPR inline bool __is_irreflexive(_Iterator __it) { return _Irreflexive_checker::_S_is_valid(__it); } template + _GLIBCXX20_CONSTEXPR inline bool __is_irreflexive_pred(_Iterator __it, _Pred __pred) { return _Irreflexive_checker::_S_is_valid_pred(__it, __pred); } diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h index 9429bb90a55..16d871e68f4 100644 --- a/libstdc++-v3/include/debug/helper_functions.h +++ b/libstdc++-v3/include/debug/helper_functions.h @@ -88,12 +88,14 @@ namespace __gnu_debug * precision. */ template + _GLIBCXX_CONSTEXPR inline typename _Distance_traits<_Iterator>::__type __get_distance(_Iterator __lhs, _Iterator __rhs, std::random_access_iterator_tag) { return std::make_pair(__rhs - __lhs, __dp_exact); } template + _GLIBCXX_CONSTEXPR inline typename _Distance_traits<_Iterator>::__type __get_distance(_Iterator __lhs, _Iterator __rhs, std::input_iterator_tag) @@ -105,6 +107,7 @@ namespace __gnu_debug } template + _GLIBCXX_CONSTEXPR inline typename _Distance_traits<_Iterator>::__type __get_distance(_Iterator __lhs, _Iterator __rhs) { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } @@ -114,6 +117,13 @@ namespace __gnu_debug * iterators. */ template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_Integral, _Integral, std::__true_type) + { return true; } + + template + _GLIBCXX20_CONSTEXPR inline bool __valid_range_aux(_Integral, _Integral, typename _Distance_traits<_Integral>::__type& __dist, @@ -123,10 +133,35 @@ namespace __gnu_debug return true; } + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { return true; } + + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::random_access_iterator_tag) + { return __first <= __last; } + /** We have iterators, so figure out what kind of iterators they are * to see if we can check the range ahead of time. */ template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::__false_type) + { + return __valid_range_aux(__first, __last, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR inline bool __valid_range_aux(_InputIterator __first, _InputIterator __last, typename _Distance_traits<_InputIterator>::__type& __dist, @@ -157,10 +192,16 @@ namespace __gnu_debug * otherwise. */ template + _GLIBCXX20_CONSTEXPR inline bool __valid_range(_InputIterator __first, _InputIterator __last, typename _Distance_traits<_InputIterator>::__type& __dist) { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + // Detected by the compiler directly. + return true; +#endif typedef typename std::__is_integer<_InputIterator>::__type _Integral; return __valid_range_aux(__first, __last, __dist, _Integral()); } @@ -180,11 +221,17 @@ namespace __gnu_debug #endif template + _GLIBCXX_CONSTEXPR inline bool __valid_range(_InputIterator __first, _InputIterator __last) { - typename _Distance_traits<_InputIterator>::__type __dist; - return __valid_range(__first, __last, __dist); +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + // Detected by the compiler directly. + return true; +#endif + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __valid_range_aux(__first, __last, _Integral()); } template @@ -201,6 +248,7 @@ namespace __gnu_debug // Fallback method, always ok. template + _GLIBCXX_CONSTEXPR inline bool __can_advance(_InputIterator, _Size) { return true; } @@ -218,6 +266,7 @@ namespace __gnu_debug * thanks to the < operator. */ template + _GLIBCXX_CONSTEXPR inline _Iterator __base(_Iterator __it) { return __it; } diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h index b598192cb3e..a6384b21fa4 100644 --- a/libstdc++-v3/include/debug/macros.h +++ b/libstdc++-v3/include/debug/macros.h @@ -38,10 +38,20 @@ * the user error and where the error is reported. * */ -#define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ +#if 0 /* defined __cpp_lib_is_constant_evaluated */ +# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ + if (std::is_constant_evaluated()) \ + /* FIXME: Compilation error here when !_Cond. */ \ + break; \ if (! (_Cond)) \ __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ ._ErrMsg._M_error() +#else +# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ + if (! (_Cond)) \ + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ + ._ErrMsg._M_error() +#endif #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ do \ @@ -291,9 +301,43 @@ _GLIBCXX_DEBUG_VERIFY(! this->empty(), \ _M_message(__gnu_debug::__msg_empty) \ ._M_sequence(*this, "this")) +// Verify that a predicate is irreflexive +#define __glibcxx_check_irreflexive(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last || !(*_First < *_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_iterator_value_type(_First, "< operator type")) + +#if __cplusplus >= 201103L +# define __glibcxx_check_irreflexive2(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last \ + || __gnu_debug::__is_irreflexive(_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_iterator_value_type(_First, "< operator type")) +#else +# define __glibcxx_check_irreflexive2(_First,_Last) +#endif + +#define __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last || !_Pred(*_First, *_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_instance(_Pred, "functor") \ + ._M_iterator_value_type(_First, "ordered type")) + +#if __cplusplus >= 201103L +# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last \ + ||__gnu_debug::__is_irreflexive_pred(_First, _Pred), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_instance(_Pred, "functor") \ + ._M_iterator_value_type(_First, "ordered type")) +#else +# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) +#endif + // Verify that the iterator range [_First, _Last) is sorted #define __glibcxx_check_sorted(_First,_Last) \ __glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_irreflexive(_First,_Last); \ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ __gnu_debug::__base(_First), \ __gnu_debug::__base(_Last)), \ @@ -305,6 +349,7 @@ __glibcxx_check_valid_range(_First,_Last); \ predicate _Pred. */ #define __glibcxx_check_sorted_pred(_First,_Last,_Pred) \ __glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_irreflexive_pred(_First,_Last,_Pred); \ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ __gnu_debug::__base(_First), \ __gnu_debug::__base(_Last), _Pred), \ @@ -423,37 +468,4 @@ _GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \ #define __glibcxx_check_string_len(_String,_Len) \ _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0) -// Verify that a predicate is irreflexive -#define __glibcxx_check_irreflexive(_First,_Last) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last || !(*_First < *_First), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_iterator_value_type(_First, "< operator type")) - -#if __cplusplus >= 201103L -# define __glibcxx_check_irreflexive2(_First,_Last) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last \ - || __gnu_debug::__is_irreflexive(_First), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_iterator_value_type(_First, "< operator type")) -#else -# define __glibcxx_check_irreflexive2(_First,_Last) -#endif - -#define __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last || !_Pred(*_First, *_First), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_instance(_Pred, "functor") \ - ._M_iterator_value_type(_First, "ordered type")) - -#if __cplusplus >= 201103L -# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last \ - ||__gnu_debug::__is_irreflexive_pred(_First, _Pred), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_instance(_Pred, "functor") \ - ._M_iterator_value_type(_First, "ordered type")) -#else -# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) -#endif - #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/binary_search/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/binary_search/constexpr.cc index 8406b3d147f..205a96a223b 100644 --- a/libstdc++-v3/testsuite/25_algorithms/binary_search/constexpr.cc +++ b/libstdc++-v3/testsuite/25_algorithms/binary_search/constexpr.cc @@ -29,7 +29,7 @@ test() const auto out4 = std::binary_search(ca0.begin(), ca0.end(), 5); const auto out5 = std::binary_search(ca0.begin(), ca0.end(), 5, - std::equal_to()); + std::less()); return true; } diff --git a/libstdc++-v3/testsuite/25_algorithms/is_sorted/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/is_sorted/constexpr.cc index 0be2f5fed62..f549b3d9307 100644 --- a/libstdc++-v3/testsuite/25_algorithms/is_sorted/constexpr.cc +++ b/libstdc++-v3/testsuite/25_algorithms/is_sorted/constexpr.cc @@ -26,7 +26,7 @@ constexpr std::array ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}; constexpr auto outv = std::is_sorted(ca0.begin(), ca0.end()); constexpr auto outw = std::is_sorted(ca0.begin(), ca0.end(), - std::equal_to()); + std::less()); constexpr bool test() diff --git a/libstdc++-v3/testsuite/25_algorithms/merge/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/merge/constexpr.cc index cc8d3755da4..794453dd50c 100644 --- a/libstdc++-v3/testsuite/25_algorithms/merge/constexpr.cc +++ b/libstdc++-v3/testsuite/25_algorithms/merge/constexpr.cc @@ -26,7 +26,7 @@ test() { constexpr std::array ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}; constexpr std::array cas{{3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}; - constexpr std::array camm{{-4, -5, -6}}; + constexpr std::array camm{{-6, -5, -4}}; std::array out0{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; const auto outdd = std::merge(ca0.begin(), ca0.end(), @@ -34,7 +34,7 @@ test() const auto outee = std::merge(ca0.begin(), ca0.end(), camm.begin(), camm.end(), out0.begin(), - [](int i, int j){ return i < -j; }); + [](int i, int j){ return i < j; }); return true; }