diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h --- a/libcxx/include/__ranges/access.h +++ b/libcxx/include/__ranges/access.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___RANGES_ACCESS_H #define _LIBCPP___RANGES_ACCESS_H +#include <__concepts/class_or_enum.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/readable_traits.h> @@ -39,6 +40,7 @@ template concept __member_begin = __can_borrow<_Tp> && + __class_or_enum> && requires(_Tp&& __t) { { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator; }; @@ -102,6 +104,7 @@ template concept __member_end = __can_borrow<_Tp> && + __class_or_enum> && requires(_Tp&& __t) { typename iterator_t<_Tp>; { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for>; diff --git a/libcxx/include/__ranges/empty.h b/libcxx/include/__ranges/empty.h --- a/libcxx/include/__ranges/empty.h +++ b/libcxx/include/__ranges/empty.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___RANGES_EMPTY_H #define _LIBCPP___RANGES_EMPTY_H +#include <__concepts/class_or_enum.h> #include <__config> #include <__iterator/concepts.h> #include <__ranges/access.h> @@ -28,9 +29,11 @@ namespace ranges { namespace __empty { template - concept __member_empty = requires(_Tp&& __t) { - bool(__t.empty()); - }; + concept __member_empty = + __class_or_enum> && + requires(_Tp&& __t) { + bool(__t.empty()); + }; template concept __can_invoke_size = diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h --- a/libcxx/include/__ranges/size.h +++ b/libcxx/include/__ranges/size.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___RANGES_SIZE_H #define _LIBCPP___RANGES_SIZE_H +#include <__concepts/class_or_enum.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> @@ -41,9 +42,12 @@ concept __size_enabled = !disable_sized_range>; template - concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) { - { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like; - }; + concept __member_size = + __size_enabled<_Tp> && + __class_or_enum> && + requires(_Tp&& __t) { + { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like; + }; template concept __unqualified_size = diff --git a/libcxx/test/std/ranges/range.access/begin.pass.cpp b/libcxx/test/std/ranges/range.access/begin.pass.cpp --- a/libcxx/test/std/ranges/range.access/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.access/begin.pass.cpp @@ -281,6 +281,12 @@ static_assert(noexcept(std::ranges::begin(brar))); static_assert(noexcept(std::ranges::cbegin(brar))); +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(!std::is_invocable_v*>); +static_assert(!std::is_invocable_v*>); + int main(int, char**) { testArray(); static_assert(testArray()); diff --git a/libcxx/test/std/ranges/range.access/empty.pass.cpp b/libcxx/test/std/ranges/range.access/empty.pass.cpp --- a/libcxx/test/std/ranges/range.access/empty.pass.cpp +++ b/libcxx/test/std/ranges/range.access/empty.pass.cpp @@ -168,6 +168,11 @@ return true; } +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(!std::is_invocable_v*>); + int main(int, char**) { testEmptyMember(); static_assert(testEmptyMember()); diff --git a/libcxx/test/std/ranges/range.access/end.pass.cpp b/libcxx/test/std/ranges/range.access/end.pass.cpp --- a/libcxx/test/std/ranges/range.access/end.pass.cpp +++ b/libcxx/test/std/ranges/range.access/end.pass.cpp @@ -326,6 +326,12 @@ static_assert(noexcept(std::ranges::end(erar))); static_assert(noexcept(std::ranges::cend(erar))); +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(!std::is_invocable_v*>); +static_assert(!std::is_invocable_v*>); + int main(int, char**) { testArray(); static_assert(testArray()); diff --git a/libcxx/test/std/ranges/range.access/size.pass.cpp b/libcxx/test/std/ranges/range.access/size.pass.cpp --- a/libcxx/test/std/ranges/range.access/size.pass.cpp +++ b/libcxx/test/std/ranges/range.access/size.pass.cpp @@ -316,6 +316,11 @@ return true; } +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(!std::is_invocable_v*>); + int main(int, char**) { testArrayType(); static_assert(testArrayType()); diff --git a/libcxx/test/std/ranges/range.access/ssize.pass.cpp b/libcxx/test/std/ranges/range.access/ssize.pass.cpp --- a/libcxx/test/std/ranges/range.access/ssize.pass.cpp +++ b/libcxx/test/std/ranges/range.access/ssize.pass.cpp @@ -80,6 +80,11 @@ return true; } +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(!std::is_invocable_v*>); + int main(int, char**) { test(); static_assert(test()); diff --git a/libcxx/test/std/ranges/range.req/range.range/range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.range/range.compile.pass.cpp --- a/libcxx/test/std/ranges/range.req/range.range/range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.range/range.compile.pass.cpp @@ -46,3 +46,8 @@ int* end(); }; static_assert(!std::ranges::range); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(!std::ranges::range*>);