Message ID | 20200209135626.GA1239883@redhat.com |
---|---|
State | New |
Headers | show |
Series | [committed] libstdc++: Fix BUILTIN-PTR-CMP helpers | expand |
On 09/02/20 13:56 +0000, Jonathan Wakely wrote: >The helpers that implement BUILTIN-PTR-CMP do not currently check if the >arguments are actually comparable, so the concept is true when it >shouldn't be. > >Since we're trying to test for an unambiguous conversion to pointers, we >can also require that it returns bool, because the built-in comparisons >for pointers do return bool. > > * include/bits/range_cmp.h (__detail::__eq_builtin_ptr_cmp): Require > equality comparison to be valid and return bool. > (__detail::__less_builtin_ptr_cmp): Likewise for less-than comparison. > * testsuite/20_util/function_objects/range.cmp/equal_to.cc: Check > type with ambiguous conversion to fundamental types. > * testsuite/20_util/function_objects/range.cmp/less.cc: Likewise. This fixes the new comments I added to those tests. Tested x86_64-linux, committed to master.
diff --git a/libstdc++-v3/include/bits/range_cmp.h b/libstdc++-v3/include/bits/range_cmp.h index e0385035543..571ba7f9555 100644 --- a/libstdc++-v3/include/bits/range_cmp.h +++ b/libstdc++-v3/include/bits/range_cmp.h @@ -62,7 +62,8 @@ namespace ranges // BUILTIN-PTR-CMP(T, ==, U) template<typename _Tp, typename _Up> concept __eq_builtin_ptr_cmp - = convertible_to<_Tp, const volatile void*> + = requires (_Tp&& __t, _Up&& __u) { { __t == __u } -> same_as<bool>; } + && convertible_to<_Tp, const volatile void*> && convertible_to<_Up, const volatile void*> && (! requires(_Tp&& __t, _Up&& __u) { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } @@ -73,7 +74,8 @@ namespace ranges // BUILTIN-PTR-CMP(T, <, U) template<typename _Tp, typename _Up> concept __less_builtin_ptr_cmp - = convertible_to<_Tp, const volatile void*> + = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as<bool>; } + && convertible_to<_Tp, const volatile void*> && convertible_to<_Up, const volatile void*> && (! requires(_Tp&& __t, _Up&& __u) { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc index 39bc984c508..34f8ee5aca4 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc @@ -69,6 +69,15 @@ test02() VERIFY( f(x, x) ); } +struct Y +{ + operator void*() const; + operator int() const; +}; + +// X{} == X{} is ambiguous so ranges::equal_to{}(X{}, X{}) should be invalid +static_assert( !std::is_invocable_v<F&, Y, Y> ); + int main() { diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc index 978894d5fc0..bf7d600e7fe 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc @@ -74,6 +74,15 @@ test02() VERIFY( ! f(x, x) ); } +struct Y +{ + operator void*() const; + operator int() const; +}; + +// X{} == X{} is ambiguous so ranges::less{}(X{}, X{}) should be invalid +static_assert( !std::is_invocable_v<F&, Y, Y> ); + int main() {