[libcxx-commits] [libcxx] 451bba6 - [libc++] Revert "Check correctly ref-qualified __is_callable in algorithms (#73451)"

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 1 12:57:07 PDT 2024


Author: Louis Dionne
Date: 2024-08-01T15:56:06-04:00
New Revision: 451bba6fbf0bc9a2bfff9253ac45caf7c57d38b9

URL: https://github.com/llvm/llvm-project/commit/451bba6fbf0bc9a2bfff9253ac45caf7c57d38b9
DIFF: https://github.com/llvm/llvm-project/commit/451bba6fbf0bc9a2bfff9253ac45caf7c57d38b9.diff

LOG: [libc++] Revert "Check correctly ref-qualified __is_callable in algorithms (#73451)"

This reverts commit 8d151f804ff43aaed1edf810bb2a07607b8bba14, which
broke some build bots. I think that is caused by an invalid argument
order when checking __is_comparable in upper_bound.

Added: 
    libcxx/test/libcxx/algorithms/callable.verify.cpp

Modified: 
    libcxx/include/__algorithm/equal_range.h
    libcxx/include/__algorithm/includes.h
    libcxx/include/__algorithm/is_permutation.h
    libcxx/include/__algorithm/lower_bound.h
    libcxx/include/__algorithm/max_element.h
    libcxx/include/__algorithm/min_element.h
    libcxx/include/__algorithm/minmax.h
    libcxx/include/__algorithm/minmax_element.h
    libcxx/include/__algorithm/partial_sort_copy.h
    libcxx/include/__algorithm/search.h
    libcxx/include/__algorithm/search_n.h
    libcxx/include/__algorithm/upper_bound.h
    libcxx/src/regex.cpp
    libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
    libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
    libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp
    libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
    libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp
    libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
    libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp

Removed: 
    libcxx/test/libcxx/algorithms/callable-requirements-rvalue.compile.pass.cpp
    libcxx/test/libcxx/algorithms/callable-requirements.verify.cpp


################################################################################
diff  --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h
index 676e4366f3db7..09bbf8f006021 100644
--- a/libcxx/include/__algorithm/equal_range.h
+++ b/libcxx/include/__algorithm/equal_range.h
@@ -62,7 +62,7 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp
 template <class _ForwardIterator, class _Tp, class _Compare>
 _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
 equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
   static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible");
   return std::__equal_range<_ClassicAlgPolicy>(
       std::move(__first),

diff  --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h
index 0ad09a94baf13..62af03c374260 100644
--- a/libcxx/include/__algorithm/includes.h
+++ b/libcxx/include/__algorithm/includes.h
@@ -54,7 +54,7 @@ includes(_InputIterator1 __first1,
          _InputIterator2 __last2,
          _Compare __comp) {
   static_assert(
-      __is_callable<_Compare&, decltype(*__first1), decltype(*__first2)>::value, "The comparator has to be callable");
+      __is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value, "Comparator has to be callable");
 
   return std::__includes(
       std::move(__first1),

diff  --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h
index 9dcfcf1810e7c..2ddfb32a212bb 100644
--- a/libcxx/include/__algorithm/is_permutation.h
+++ b/libcxx/include/__algorithm/is_permutation.h
@@ -249,8 +249,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation(
 template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
     _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __pred) {
-  static_assert(__is_callable<_BinaryPredicate&, decltype(*__first1), decltype(*__first2)>::value,
-                "The comparator has to be callable");
+  static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
+                "The predicate has to be callable");
 
   return std::__is_permutation<_ClassicAlgPolicy>(std::move(__first1), std::move(__last1), std::move(__first2), __pred);
 }
@@ -286,8 +286,8 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 boo
     _ForwardIterator2 __first2,
     _ForwardIterator2 __last2,
     _BinaryPredicate __pred) {
-  static_assert(__is_callable<_BinaryPredicate&, decltype(*__first1), decltype(*__first2)>::value,
-                "The comparator has to be callable");
+  static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
+                "The predicate has to be callable");
 
   return std::__is_permutation<_ClassicAlgPolicy>(
       std::move(__first1),

diff  --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h
index d18ab83ae7078..c417d84835497 100644
--- a/libcxx/include/__algorithm/lower_bound.h
+++ b/libcxx/include/__algorithm/lower_bound.h
@@ -93,7 +93,7 @@ __lower_bound(_ForwardIterator __first, _Sent __last, const _Type& __value, _Com
 template <class _ForwardIterator, class _Tp, class _Compare>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
 lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
   auto __proj = std::__identity();
   return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj);
 }

diff  --git a/libcxx/include/__algorithm/max_element.h b/libcxx/include/__algorithm/max_element.h
index 3e58c40052c93..c036726cbccd8 100644
--- a/libcxx/include/__algorithm/max_element.h
+++ b/libcxx/include/__algorithm/max_element.h
@@ -13,7 +13,6 @@
 #include <__algorithm/comp_ref_type.h>
 #include <__config>
 #include <__iterator/iterator_traits.h>
-#include <__type_traits/is_callable.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -38,8 +37,6 @@ __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp
 template <class _ForwardIterator, class _Compare>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
 max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
-  static_assert(
-      __is_callable<_Compare&, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
   return std::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp);
 }
 

diff  --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h
index 9a360f94ce109..65f3594d630ce 100644
--- a/libcxx/include/__algorithm/min_element.h
+++ b/libcxx/include/__algorithm/min_element.h
@@ -53,7 +53,7 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
   static_assert(
       __has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator");
   static_assert(
-      __is_callable<_Compare&, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
+      __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
 
   return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp);
 }

diff  --git a/libcxx/include/__algorithm/minmax.h b/libcxx/include/__algorithm/minmax.h
index bb7a379be125b..9feda2b4c0da9 100644
--- a/libcxx/include/__algorithm/minmax.h
+++ b/libcxx/include/__algorithm/minmax.h
@@ -40,7 +40,7 @@ minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __
 template <class _Tp, class _Compare>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp>
 minmax(initializer_list<_Tp> __t, _Compare __comp) {
-  static_assert(__is_callable<_Compare&, _Tp, _Tp>::value, "The comparator has to be callable");
+  static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable");
   __identity __proj;
   auto __ret = std::__minmax_element_impl(__t.begin(), __t.end(), __comp, __proj);
   return pair<_Tp, _Tp>(*__ret.first, *__ret.second);

diff  --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h
index 23929c96d987f..43cb23347c346 100644
--- a/libcxx/include/__algorithm/minmax_element.h
+++ b/libcxx/include/__algorithm/minmax_element.h
@@ -84,7 +84,7 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __com
   static_assert(
       __has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator");
   static_assert(
-      __is_callable<_Compare&, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
+      __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
   auto __proj = __identity();
   return std::__minmax_element_impl(__first, __last, __comp, __proj);
 }

diff  --git a/libcxx/include/__algorithm/partial_sort_copy.h b/libcxx/include/__algorithm/partial_sort_copy.h
index 6d44b4f8f928a..ef7c9d34d9498 100644
--- a/libcxx/include/__algorithm/partial_sort_copy.h
+++ b/libcxx/include/__algorithm/partial_sort_copy.h
@@ -76,8 +76,8 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
     _RandomAccessIterator __result_first,
     _RandomAccessIterator __result_last,
     _Compare __comp) {
-  static_assert(__is_callable<_Compare&, decltype(*__first), decltype(*__result_first)>::value,
-                "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value, "Comparator has to be callable");
 
   auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(
       __first,

diff  --git a/libcxx/include/__algorithm/search.h b/libcxx/include/__algorithm/search.h
index 7316e5e4e1d98..b82ca78095354 100644
--- a/libcxx/include/__algorithm/search.h
+++ b/libcxx/include/__algorithm/search.h
@@ -166,8 +166,8 @@ search(_ForwardIterator1 __first1,
        _ForwardIterator2 __first2,
        _ForwardIterator2 __last2,
        _BinaryPredicate __pred) {
-  static_assert(__is_callable<_BinaryPredicate&, decltype(*__first1), decltype(*__first2)>::value,
-                "The comparator has to be callable");
+  static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
+                "BinaryPredicate has to be callable");
   auto __proj = __identity();
   return std::__search_impl(__first1, __last1, __first2, __last2, __pred, __proj, __proj).first;
 }

diff  --git a/libcxx/include/__algorithm/search_n.h b/libcxx/include/__algorithm/search_n.h
index f9806385656bf..771647d3168a4 100644
--- a/libcxx/include/__algorithm/search_n.h
+++ b/libcxx/include/__algorithm/search_n.h
@@ -139,7 +139,7 @@ template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n(
     _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) {
   static_assert(
-      __is_callable<_BinaryPredicate&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+      __is_callable<_BinaryPredicate, decltype(*__first), const _Tp&>::value, "BinaryPredicate has to be callable");
   auto __proj = __identity();
   return std::__search_n_impl(__first, __last, std::__convert_to_integral(__count), __value, __pred, __proj).first;
 }

diff  --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h
index 43d1c510821ee..c39dec2e89698 100644
--- a/libcxx/include/__algorithm/upper_bound.h
+++ b/libcxx/include/__algorithm/upper_bound.h
@@ -18,7 +18,6 @@
 #include <__iterator/advance.h>
 #include <__iterator/distance.h>
 #include <__iterator/iterator_traits.h>
-#include <__type_traits/is_callable.h>
 #include <__type_traits/is_constructible.h>
 #include <__utility/move.h>
 
@@ -51,7 +50,6 @@ __upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp
 template <class _ForwardIterator, class _Tp, class _Compare>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
 upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
   static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible");
   return std::__upper_bound<_ClassicAlgPolicy>(
       std::move(__first), std::move(__last), __value, std::move(__comp), std::__identity());

diff  --git a/libcxx/src/regex.cpp b/libcxx/src/regex.cpp
index 6d9f06e213466..9dc0c698541c8 100644
--- a/libcxx/src/regex.cpp
+++ b/libcxx/src/regex.cpp
@@ -323,8 +323,8 @@ const classnames ClassNames[] = {
     {"xdigit", ctype_base::xdigit}};
 
 struct use_strcmp {
-  bool operator()(const collationnames& x, const char* y) const { return strcmp(x.elem_, y) < 0; }
-  bool operator()(const classnames& x, const char* y) const { return strcmp(x.elem_, y) < 0; }
+  bool operator()(const collationnames& x, const char* y) { return strcmp(x.elem_, y) < 0; }
+  bool operator()(const classnames& x, const char* y) { return strcmp(x.elem_, y) < 0; }
 };
 
 } // namespace

diff  --git a/libcxx/test/libcxx/algorithms/callable-requirements-rvalue.compile.pass.cpp b/libcxx/test/libcxx/algorithms/callable-requirements-rvalue.compile.pass.cpp
deleted file mode 100644
index 4a5535e71ab96..0000000000000
--- a/libcxx/test/libcxx/algorithms/callable-requirements-rvalue.compile.pass.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-// <algorithm>
-
-// Make sure that we don't error out when passing a comparator that is lvalue callable
-// but not rvalue callable to algorithms. While it is technically ill-formed for users
-// to provide us such predicates, this test is useful for libc++ to ensure that we check
-// predicate requirements correctly (i.e. that we check them on lvalues and not on
-// rvalues). See https://github.com/llvm/llvm-project/issues/69554 for additional
-// context.
-
-#include <algorithm>
-
-#include "test_macros.h"
-
-struct NotRvalueCallable {
-  bool operator()(int a, int b) const& { return a < b; }
-  bool operator()(int, int) && = delete;
-};
-
-void f() {
-  int a[] = {1, 2, 3, 4};
-  (void)std::lower_bound(a, a + 4, 0, NotRvalueCallable{});
-  (void)std::upper_bound(a, a + 4, 0, NotRvalueCallable{});
-  (void)std::minmax({1, 2, 3}, NotRvalueCallable{});
-  (void)std::minmax_element(a, a + 4, NotRvalueCallable{});
-  (void)std::min_element(a, a + 4, NotRvalueCallable{});
-  (void)std::max_element(a, a + 4, NotRvalueCallable{});
-  (void)std::is_permutation(a, a + 4, a, NotRvalueCallable{});
-#if TEST_STD_VER >= 14
-  (void)std::is_permutation(a, a + 4, a, a + 4, NotRvalueCallable{});
-#endif
-  (void)std::includes(a, a + 4, a, a + 4, NotRvalueCallable{});
-  (void)std::equal_range(a, a + 4, 0, NotRvalueCallable{});
-  (void)std::partial_sort_copy(a, a + 4, a, a + 4, NotRvalueCallable{});
-  (void)std::search(a, a + 4, a, a + 4, NotRvalueCallable{});
-  (void)std::search_n(a, a + 4, 4, 0, NotRvalueCallable{});
-}

diff  --git a/libcxx/test/libcxx/algorithms/callable-requirements.verify.cpp b/libcxx/test/libcxx/algorithms/callable-requirements.verify.cpp
deleted file mode 100644
index 7555d9815c60b..0000000000000
--- a/libcxx/test/libcxx/algorithms/callable-requirements.verify.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-// Ignore spurious errors after the initial static_assert failure.
-// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
-
-// <algorithm>
-
-// Check that calling a classic STL algorithm with various non-callable comparators is diagnosed.
-
-#include <algorithm>
-
-#include "test_macros.h"
-
-struct NotCallable {
-  bool compare(int a, int b) const { return a < b; }
-};
-
-struct NotMutableCallable {
-  bool operator()(int a, int b) = delete;
-  bool operator()(int a, int b) const { return a < b; }
-};
-
-void f() {
-  int a[] = {1, 2, 3, 4};
-  {
-    (void)std::lower_bound(a, a + 4, 0, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::upper_bound(a, a + 4, 0, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::minmax({1, 2, 3}, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::minmax_element(a, a + 4, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::min_element(a, a + 4, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::max_element(a, a + 4, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::is_permutation(a, a + 4, a, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-#if TEST_STD_VER >= 14
-    (void)std::is_permutation(a, a + 4, a, a + 4, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-#endif
-
-    (void)std::includes(a, a + 4, a, a + 4, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::equal_range(a, a + 4, 0, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::partial_sort_copy(a, a + 4, a, a + 4, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::search(a, a + 4, a, a + 4, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::search_n(a, a + 4, 4, 0, &NotCallable::compare);
-    // expected-error@*:* {{The comparator has to be callable}}
-  }
-
-  {
-    (void)std::lower_bound(a, a + 4, 0, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::upper_bound(a, a + 4, 0, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::minmax({1, 2, 3}, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::minmax_element(a, a + 4, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::min_element(a, a + 4, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::max_element(a, a + 4, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::is_permutation(a, a + 4, a, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-#if TEST_STD_VER >= 14
-    (void)std::is_permutation(a, a + 4, a, a + 4, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-#endif
-
-    (void)std::includes(a, a + 4, a, a + 4, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::equal_range(a, a + 4, 0, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::partial_sort_copy(a, a + 4, a, a + 4, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::search(a, a + 4, a, a + 4, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-
-    (void)std::search_n(a, a + 4, 4, 0, NotMutableCallable{});
-    // expected-error@*:* {{The comparator has to be callable}}
-  }
-}

diff  --git a/libcxx/test/libcxx/algorithms/callable.verify.cpp b/libcxx/test/libcxx/algorithms/callable.verify.cpp
new file mode 100644
index 0000000000000..da87ecd0971d2
--- /dev/null
+++ b/libcxx/test/libcxx/algorithms/callable.verify.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <algorithm>
+
+// check that the classical algorithms with non-callable comparators fail
+
+#include <algorithm>
+
+void f() {
+  struct S {
+    int i;
+
+    S(int i_) : i(i_) {}
+
+    bool compare(const S&) const;
+  };
+
+  S a[] = {1, 2, 3, 4};
+  (void) std::lower_bound(a, a + 4, 0, &S::compare); // expected-error@*:* {{The comparator has to be callable}}
+  (void) std::minmax({S{1}}, &S::compare); // expected-error@*:* {{The comparator has to be callable}}
+  (void) std::minmax_element(a, a + 4, &S::compare); // expected-error@*:* {{The comparator has to be callable}}
+}

diff  --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
index d20abf3ffc278..bc71150c9e2d8 100644
--- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
@@ -26,35 +26,35 @@ struct Proj {
     constexpr explicit Proj(int *copies) : copies_(copies) {}
     constexpr Proj(const Proj& rhs) : copies_(rhs.copies_) { *copies_ += 1; }
     constexpr Proj& operator=(const Proj&) = default;
-    constexpr void* operator()(T) const { return nullptr; }
+    constexpr void *operator()(T) const { return nullptr; }
 };
 
 struct Less {
-  constexpr bool operator()(void*, void*) const { return false; }
+    constexpr bool operator()(void*, void*) const { return false; }
 };
 
 struct Equal {
-  constexpr bool operator()(void*, void*) const { return true; }
+    constexpr bool operator()(void*, void*) const { return true; }
 };
 
 struct UnaryVoid {
-  constexpr void operator()(void*) const {}
+    constexpr void operator()(void*) const {}
 };
 
 struct UnaryTrue {
-  constexpr bool operator()(void*) const { return true; }
+    constexpr bool operator()(void*) const { return true; }
 };
 
 struct NullaryValue {
-  constexpr std::nullptr_t operator()() const { return nullptr; }
+    constexpr std::nullptr_t operator()() const { return nullptr; }
 };
 
 struct UnaryTransform {
-  constexpr T operator()(void*) const { return T(); }
+    constexpr T operator()(void*) const { return T(); }
 };
 
 struct BinaryTransform {
-  constexpr T operator()(void*, void*) const { return T(); }
+    constexpr T operator()(void*, void*) const { return T(); }
 };
 
 constexpr bool all_the_algorithms()

diff  --git a/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp b/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
index f5ad5a8d3d3ee..78a58634bc216 100644
--- a/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
@@ -72,9 +72,9 @@ struct Cpp20HostileIterator
 };
 
 struct Pred {
-  bool operator()(int, int) const { return false; }
-  bool operator()(int) const { return false; }
-  int operator()() const { return 0; }
+  bool operator()(int, int) { return false; }
+  bool operator()(int) { return false; }
+  int operator()() { return 0; }
 };
 
 void test() {

diff  --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp
index 4e4f889a45e74..ea4270ec4095b 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp
@@ -51,7 +51,7 @@ struct S {
 };
 
 struct eq {
-  bool operator()(const S& a, const S& b) const { return a.i_ == b.i_; }
+  bool operator()(const S& a, const S&b) { return a.i_ == b.i_; }
 };
 
 

diff  --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
index 2fa3e9ffac1bc..3bf72e3fbf57b 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
@@ -32,13 +32,12 @@ TEST_CONSTEXPR bool test_constexpr() {
     }
 #endif
 
-struct count_equal {
-  static unsigned count;
-  template <class T>
-  bool operator()(const T& x, const T& y) const {
-    ++count;
-    return x == y;
-  }
+struct count_equal
+{
+    static unsigned count;
+    template <class T>
+    bool operator()(const T& x, const T& y)
+        {++count; return x == y;}
 };
 
 unsigned count_equal::count = 0;

diff  --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp
index cfb82f3d4084c..f835d2f094581 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp
@@ -36,15 +36,8 @@ struct count_equal
 {
     static unsigned count;
     template <class T>
-    bool operator()(const T& x, const T& y) & {
-      ++count;
-      return x == y;
-    };
-    template <class T>
-    bool operator()(const T& x, const T& y) const& {
-      ++count;
-      return x == y;
-    };
+    bool operator()(const T& x, const T& y)
+        {++count; return x == y;}
 };
 
 unsigned count_equal::count = 0;

diff  --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
index ebff401cac297..d103e8c2ddb33 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
@@ -24,11 +24,11 @@
 #if TEST_STD_VER >= 11
 #include <memory>
 
-struct indirect_less {
-  template <class P>
-  bool operator()(const P& x, const P& y) const {
-    return *x < *y;
-  }
+struct indirect_less
+{
+    template <class P>
+    bool operator()(const P& x, const P& y)
+        {return *x < *y;}
 };
 
 struct S {
@@ -119,7 +119,7 @@ test()
 
 struct less_by_first {
   template <typename Pair>
-  bool operator()(const Pair& lhs, const Pair& rhs) const {
+  bool operator()(const Pair& lhs, const Pair& rhs) {
     return std::less<typename Pair::first_type>()(lhs.first, rhs.first);
   }
 };

diff  --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp
index 5ee6d89064941..46c2a42349df7 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp
@@ -25,17 +25,21 @@
 
 #include "test_macros.h"
 
-struct indirect_less {
-  template <class P>
-  bool operator()(const P& x, const P& y) const {
-    return *x < *y;
-  }
+struct indirect_less
+{
+    template <class P>
+    bool operator()(const P& x, const P& y)
+        {return *x < *y;}
 };
 
 std::mt19937 randomness;
 
-struct first_only {
-  bool operator()(const std::pair<int, int>& x, const std::pair<int, int>& y) const { return x.first < y.first; }
+struct first_only
+{
+    bool operator()(const std::pair<int, int>& x, const std::pair<int, int>& y)
+    {
+        return x.first < y.first;
+    }
 };
 
 void test()


        


More information about the libcxx-commits mailing list