[libcxx-commits] [libcxx] 12978b3 - [libc++] P2602R2 Poison Pills are Too Toxic (#74534)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Mar 16 05:16:40 PDT 2024
Author: Jakub Mazurkiewicz
Date: 2024-03-16T12:16:36Z
New Revision: 12978b3e23a2766732595391c193e5631f40a3db
URL: https://github.com/llvm/llvm-project/commit/12978b3e23a2766732595391c193e5631f40a3db
DIFF: https://github.com/llvm/llvm-project/commit/12978b3e23a2766732595391c193e5631f40a3db.diff
LOG: [libc++] P2602R2 Poison Pills are Too Toxic (#74534)
Implements [P2602R2 Poison Pills are Too
Toxic](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2602r2.html)
as a DR in C++20 mode.
Added:
libcxx/test/std/ranges/robust_against_poison_pills.compile.pass.cpp
Modified:
libcxx/docs/Status/Cxx23Papers.csv
libcxx/include/__compare/partial_order.h
libcxx/include/__compare/strong_order.h
libcxx/include/__compare/weak_order.h
libcxx/include/__iterator/iter_move.h
libcxx/include/__ranges/access.h
libcxx/include/__ranges/rbegin.h
libcxx/include/__ranges/rend.h
libcxx/include/__ranges/size.h
libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp
libcxx/test/std/ranges/range.access/begin.pass.cpp
libcxx/test/std/ranges/range.access/end.pass.cpp
libcxx/test/std/ranges/range.access/rbegin.pass.cpp
libcxx/test/std/ranges/range.access/rend.pass.cpp
libcxx/test/std/ranges/range.access/size.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 56e1468b4ca1a3..80547c5c1f3f57 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -100,7 +100,7 @@
"`P2396R1 <https://wg21.link/P2396R1>`__","LWG", "Concurrency TS 2 fixes ", "November 2022","","","|concurrency TS|"
"`P2505R5 <https://wg21.link/P2505R5>`__","LWG", "Monadic Functions for ``std::expected``", "November 2022","|Complete|","17.0",""
"`P2539R4 <https://wg21.link/P2539R4>`__","LWG", "Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?", "November 2022","|Complete|","18.0","|format|"
-"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","","","|ranges|"
+"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","|Complete|","19.0","|ranges|"
"`P2708R1 <https://wg21.link/P2708R1>`__","LWG", "No Further Fundamentals TSes", "November 2022","|Nothing to do|","",""
"","","","","","",""
"`P0290R4 <https://wg21.link/P0290R4>`__","LWG", "``apply()`` for ``synchronized_value<T>``","February 2023","","","|concurrency TS|"
diff --git a/libcxx/include/__compare/partial_order.h b/libcxx/include/__compare/partial_order.h
index f3ed4900fbff25..1d2fae63e5f248 100644
--- a/libcxx/include/__compare/partial_order.h
+++ b/libcxx/include/__compare/partial_order.h
@@ -28,6 +28,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// [cmp.alg]
namespace __partial_order {
+void partial_order() = delete;
+
struct __fn {
// NOLINTBEGIN(libcpp-robust-against-adl) partial_order should use ADL, but only here
template <class _Tp, class _Up>
diff --git a/libcxx/include/__compare/strong_order.h b/libcxx/include/__compare/strong_order.h
index 3dc819e642515c..8c363b56382221 100644
--- a/libcxx/include/__compare/strong_order.h
+++ b/libcxx/include/__compare/strong_order.h
@@ -37,6 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// [cmp.alg]
namespace __strong_order {
+void strong_order() = delete;
+
struct __fn {
// NOLINTBEGIN(libcpp-robust-against-adl) strong_order should use ADL, but only here
template <class _Tp, class _Up>
diff --git a/libcxx/include/__compare/weak_order.h b/libcxx/include/__compare/weak_order.h
index b82a708c29a146..1a3e85feb233b3 100644
--- a/libcxx/include/__compare/weak_order.h
+++ b/libcxx/include/__compare/weak_order.h
@@ -30,6 +30,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// [cmp.alg]
namespace __weak_order {
+void weak_order() = delete;
+
struct __fn {
// NOLINTBEGIN(libcpp-robust-against-adl) weak_order should use ADL, but only here
template <class _Tp, class _Up>
diff --git a/libcxx/include/__iterator/iter_move.h b/libcxx/include/__iterator/iter_move.h
index 202b94cccc5ac6..ba8aed3c0ffbbd 100644
--- a/libcxx/include/__iterator/iter_move.h
+++ b/libcxx/include/__iterator/iter_move.h
@@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
namespace __iter_move {
-void iter_move();
+void iter_move() = delete;
template <class _Tp>
concept __unqualified_iter_move = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h
index 263fdd637fd965..218b3928ecdc5f 100644
--- a/libcxx/include/__ranges/access.h
+++ b/libcxx/include/__ranges/access.h
@@ -45,8 +45,7 @@ concept __member_begin = __can_borrow<_Tp> && __workaround_52970<_Tp> && require
{ _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
};
-void begin(auto&) = delete;
-void begin(const auto&) = delete;
+void begin() = delete;
template <class _Tp>
concept __unqualified_begin =
@@ -109,8 +108,7 @@ concept __member_end = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(
{ _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
};
-void end(auto&) = delete;
-void end(const auto&) = delete;
+void end() = delete;
template <class _Tp>
concept __unqualified_end =
diff --git a/libcxx/include/__ranges/rbegin.h b/libcxx/include/__ranges/rbegin.h
index 7111201ae7d6bb..947e428f00cd52 100644
--- a/libcxx/include/__ranges/rbegin.h
+++ b/libcxx/include/__ranges/rbegin.h
@@ -40,8 +40,7 @@ concept __member_rbegin = __can_borrow<_Tp> && __workaround_52970<_Tp> && requir
{ _LIBCPP_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator;
};
-void rbegin(auto&) = delete;
-void rbegin(const auto&) = delete;
+void rbegin() = delete;
template <class _Tp>
concept __unqualified_rbegin =
diff --git a/libcxx/include/__ranges/rend.h b/libcxx/include/__ranges/rend.h
index 58d98aafd264b8..1b6be58fea24b4 100644
--- a/libcxx/include/__ranges/rend.h
+++ b/libcxx/include/__ranges/rend.h
@@ -42,8 +42,7 @@ concept __member_rend = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires
{ _LIBCPP_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(ranges::rbegin(__t))>;
};
-void rend(auto&) = delete;
-void rend(const auto&) = delete;
+void rend() = delete;
template <class _Tp>
concept __unqualified_rend =
diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h
index 14e21aae6bf1d5..59ca2b11ee3890 100644
--- a/libcxx/include/__ranges/size.h
+++ b/libcxx/include/__ranges/size.h
@@ -41,8 +41,7 @@ inline constexpr bool disable_sized_range = false;
namespace ranges {
namespace __size {
-void size(auto&) = delete;
-void size(const auto&) = delete;
+void size() = delete;
template <class _Tp>
concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>;
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp
index dd78707f25409c..e6507f7e776735 100644
--- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp
@@ -47,6 +47,13 @@ static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, HasIterSwap&>);
static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, int&>);
static_assert(!std::is_invocable_v<IterSwapT&&, int&, HasIterSwap&>);
+struct StructWithNotMoreSpecializedIterSwap {
+ friend void iter_swap(auto&, auto&);
+};
+
+static_assert(
+ !std::is_invocable_v<IterSwapT, StructWithNotMoreSpecializedIterSwap&, StructWithNotMoreSpecializedIterSwap&>);
+
struct NodiscardIterSwap {
[[nodiscard]] friend int iter_swap(NodiscardIterSwap&, NodiscardIterSwap&) { return 0; }
};
diff --git a/libcxx/test/std/ranges/range.access/begin.pass.cpp b/libcxx/test/std/ranges/range.access/begin.pass.cpp
index ca25fc297a0119..5ca3d59abb1407 100644
--- a/libcxx/test/std/ranges/range.access/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/begin.pass.cpp
@@ -192,7 +192,7 @@ struct BeginFunction {
};
static_assert( std::is_invocable_v<RangeBeginT, BeginFunction const&>);
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &&>);
-static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &>);
+static_assert(std::is_invocable_v<RangeBeginT, BeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction const&>);
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction &>);
@@ -245,7 +245,7 @@ struct BeginFunctionWithPrivateBeginMember {
constexpr bool testBeginFunction() {
BeginFunction a{};
const BeginFunction aa{};
- static_assert(!std::invocable<RangeBeginT, decltype((a))>);
+ assert(std::ranges::begin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cbegin(a) == &a.x);
assert(std::ranges::begin(aa) == &aa.x);
assert(std::ranges::cbegin(aa) == &aa.x);
@@ -266,21 +266,21 @@ constexpr bool testBeginFunction() {
BeginFunctionReturnsEmptyPtr d{};
const BeginFunctionReturnsEmptyPtr dd{};
- static_assert(!std::invocable<RangeBeginT, decltype((d))>);
+ assert(std::ranges::begin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cbegin(d) == &d.x);
assert(std::ranges::begin(dd) == &dd.x);
assert(std::ranges::cbegin(dd) == &dd.x);
BeginFunctionWithDataMember e{};
const BeginFunctionWithDataMember ee{};
- static_assert(!std::invocable<RangeBeginT, decltype((e))>);
+ assert(std::ranges::begin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::begin(ee) == &ee.x);
assert(std::ranges::cbegin(e) == &e.x);
assert(std::ranges::cbegin(ee) == &ee.x);
BeginFunctionWithPrivateBeginMember f{};
const BeginFunctionWithPrivateBeginMember ff{};
- static_assert(!std::invocable<RangeBeginT, decltype((f))>);
+ assert(std::ranges::begin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cbegin(f) == &f.y);
assert(std::ranges::begin(ff) == &ff.y);
assert(std::ranges::cbegin(ff) == &ff.y);
diff --git a/libcxx/test/std/ranges/range.access/end.pass.cpp b/libcxx/test/std/ranges/range.access/end.pass.cpp
index 21d97354ef08d0..3e465b357e9851 100644
--- a/libcxx/test/std/ranges/range.access/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/end.pass.cpp
@@ -193,7 +193,7 @@ static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>);
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
-static_assert(!std::is_invocable_v<RangeEndT, EndFunction &>);
+static_assert(std::is_invocable_v<RangeEndT, EndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeCEndT, EndFunction const&>);
static_assert( std::is_invocable_v<RangeCEndT, EndFunction &>);
@@ -271,7 +271,7 @@ constexpr bool testEndFunction() {
assert(std::ranges::end(a) == &a.x);
assert(std::ranges::cend(a) == &a.x);
EndFunction aa{};
- static_assert(!std::is_invocable_v<RangeEndT, decltype((aa))>);
+ assert(std::ranges::end(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(aa) == &aa.x);
EndFunctionByValue b;
@@ -286,28 +286,28 @@ constexpr bool testEndFunction() {
assert(std::ranges::end(d) == &d.x);
assert(std::ranges::cend(d) == &d.x);
EndFunctionReturnsEmptyPtr dd{};
- static_assert(!std::is_invocable_v<RangeEndT, decltype((dd))>);
+ assert(std::ranges::end(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(dd) == &dd.x);
const EndFunctionWithDataMember e{};
assert(std::ranges::end(e) == &e.x);
assert(std::ranges::cend(e) == &e.x);
EndFunctionWithDataMember ee{};
- static_assert(!std::is_invocable_v<RangeEndT, decltype((ee))>);
+ assert(std::ranges::end(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(ee) == &ee.x);
const EndFunctionWithPrivateEndMember f{};
assert(std::ranges::end(f) == &f.y);
assert(std::ranges::cend(f) == &f.y);
EndFunctionWithPrivateEndMember ff{};
- static_assert(!std::is_invocable_v<RangeEndT, decltype((ff))>);
+ assert(std::ranges::end(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(ff) == &ff.y);
const BeginMemberEndFunction g{};
assert(std::ranges::end(g) == &g.x);
assert(std::ranges::cend(g) == &g.x);
BeginMemberEndFunction gg{};
- static_assert(!std::is_invocable_v<RangeEndT, decltype((gg))>);
+ assert(std::ranges::end(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(gg) == &gg.x);
return true;
diff --git a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
index e1a564c94ed948..3997f38efd0298 100644
--- a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
@@ -187,7 +187,8 @@ struct RBeginFunction {
};
static_assert( std::is_invocable_v<RangeRBeginT, RBeginFunction const&>);
static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &&>);
-static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &>);
+static_assert(
+ std::is_invocable_v<RangeRBeginT, RBeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction const&>);
static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction &>);
@@ -246,7 +247,7 @@ struct RBeginFunctionWithPrivateBeginMember {
constexpr bool testRBeginFunction() {
RBeginFunction a{};
const RBeginFunction aa{};
- static_assert(!std::invocable<RangeRBeginT, decltype((a))>);
+ assert(std::ranges::rbegin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crbegin(a) == &a.x);
assert(std::ranges::rbegin(aa) == &aa.x);
assert(std::ranges::crbegin(aa) == &aa.x);
@@ -267,21 +268,21 @@ constexpr bool testRBeginFunction() {
RBeginFunctionReturnsEmptyPtr d{};
const RBeginFunctionReturnsEmptyPtr dd{};
- static_assert(!std::invocable<RangeRBeginT, decltype((d))>);
+ assert(std::ranges::rbegin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crbegin(d) == &d.x);
assert(std::ranges::rbegin(dd) == &dd.x);
assert(std::ranges::crbegin(dd) == &dd.x);
RBeginFunctionWithDataMember e{};
const RBeginFunctionWithDataMember ee{};
- static_assert(!std::invocable<RangeRBeginT, decltype((e))>);
+ assert(std::ranges::rbegin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::rbegin(ee) == &ee.x);
assert(std::ranges::crbegin(e) == &e.x);
assert(std::ranges::crbegin(ee) == &ee.x);
RBeginFunctionWithPrivateBeginMember f{};
const RBeginFunctionWithPrivateBeginMember ff{};
- static_assert(!std::invocable<RangeRBeginT, decltype((f))>);
+ assert(std::ranges::rbegin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crbegin(f) == &f.y);
assert(std::ranges::rbegin(ff) == &ff.y);
assert(std::ranges::crbegin(ff) == &ff.y);
diff --git a/libcxx/test/std/ranges/range.access/rend.pass.cpp b/libcxx/test/std/ranges/range.access/rend.pass.cpp
index 5ba244b6b18cfe..f5f59edf19393f 100644
--- a/libcxx/test/std/ranges/range.access/rend.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/rend.pass.cpp
@@ -196,7 +196,7 @@ static_assert(!std::is_invocable_v<RangeREndT, REndFunction &&>);
static_assert( std::is_invocable_v<RangeREndT, REndFunction const&>);
static_assert(!std::is_invocable_v<RangeREndT, REndFunction &&>);
-static_assert(!std::is_invocable_v<RangeREndT, REndFunction &>);
+static_assert(std::is_invocable_v<RangeREndT, REndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeCREndT, REndFunction const&>);
static_assert( std::is_invocable_v<RangeCREndT, REndFunction &>);
@@ -272,7 +272,7 @@ constexpr bool testREndFunction() {
assert(std::ranges::rend(a) == &a.x);
assert(std::ranges::crend(a) == &a.x);
REndFunction aa{};
- static_assert(!std::is_invocable_v<RangeREndT, decltype((aa))>);
+ assert(std::ranges::rend(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crend(aa) == &aa.x);
REndFunctionByValue b;
@@ -287,28 +287,28 @@ constexpr bool testREndFunction() {
assert(std::ranges::rend(d) == &d.x);
assert(std::ranges::crend(d) == &d.x);
REndFunctionReturnsEmptyPtr dd{};
- static_assert(!std::is_invocable_v<RangeREndT, decltype((dd))>);
+ assert(std::ranges::rend(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crend(dd) == &dd.x);
const REndFunctionWithDataMember e{};
assert(std::ranges::rend(e) == &e.x);
assert(std::ranges::crend(e) == &e.x);
REndFunctionWithDataMember ee{};
- static_assert(!std::is_invocable_v<RangeREndT, decltype((ee))>);
+ assert(std::ranges::rend(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crend(ee) == &ee.x);
const REndFunctionWithPrivateEndMember f{};
assert(std::ranges::rend(f) == &f.y);
assert(std::ranges::crend(f) == &f.y);
REndFunctionWithPrivateEndMember ff{};
- static_assert(!std::is_invocable_v<RangeREndT, decltype((ff))>);
+ assert(std::ranges::rend(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crend(ff) == &ff.y);
const RBeginMemberEndFunction g{};
assert(std::ranges::rend(g) == &g.x);
assert(std::ranges::crend(g) == &g.x);
RBeginMemberEndFunction gg{};
- static_assert(!std::is_invocable_v<RangeREndT, decltype((gg))>);
+ assert(std::ranges::rend(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crend(gg) == &gg.x);
return true;
diff --git a/libcxx/test/std/ranges/range.access/size.pass.cpp b/libcxx/test/std/ranges/range.access/size.pass.cpp
index fd7d0a8b997522..ee44aa815ba993 100644
--- a/libcxx/test/std/ranges/range.access/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/size.pass.cpp
@@ -219,7 +219,8 @@ inline constexpr bool std::ranges::disable_sized_range<const ImproperlyDisabledF
static_assert( std::is_invocable_v<RangeSizeT, ImproperlyDisabledMember&>);
static_assert( std::is_invocable_v<RangeSizeT, const ImproperlyDisabledMember&>);
-static_assert(!std::is_invocable_v<RangeSizeT, ImproperlyDisabledFunction&>);
+static_assert(std::is_invocable_v<RangeSizeT,
+ ImproperlyDisabledFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeSizeT, const ImproperlyDisabledFunction&>);
// No begin end.
diff --git a/libcxx/test/std/ranges/robust_against_poison_pills.compile.pass.cpp b/libcxx/test/std/ranges/robust_against_poison_pills.compile.pass.cpp
new file mode 100644
index 00000000000000..1b3da814d08002
--- /dev/null
+++ b/libcxx/test/std/ranges/robust_against_poison_pills.compile.pass.cpp
@@ -0,0 +1,102 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+
+// <compare>, <iterator>, <ranges>
+
+// ADL should be performed. Ordinary unqualified lookup should not be performed.
+
+namespace ns {
+struct StructWithGlobalFunctions {};
+} // namespace ns
+
+struct ConvertibleToCmpType;
+ConvertibleToCmpType strong_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&);
+ConvertibleToCmpType weak_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&);
+ConvertibleToCmpType partial_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&);
+
+int&& iter_move(const ns::StructWithGlobalFunctions&);
+void iter_swap(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&);
+
+int* begin(const ns::StructWithGlobalFunctions&);
+int* end(const ns::StructWithGlobalFunctions&);
+int* rbegin(const ns::StructWithGlobalFunctions&);
+int* rend(const ns::StructWithGlobalFunctions&);
+unsigned int size(const ns::StructWithGlobalFunctions&);
+
+#include <compare>
+#include <ranges>
+#include <type_traits>
+
+struct ConvertibleToCmpType {
+ operator std::strong_ordering() const;
+ operator std::weak_ordering() const;
+ operator std::partial_ordering() const;
+};
+
+struct StructWithHiddenFriends {
+ friend ConvertibleToCmpType strong_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&);
+ friend ConvertibleToCmpType weak_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&);
+ friend ConvertibleToCmpType partial_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&);
+
+ friend int&& iter_move(const StructWithHiddenFriends&);
+ friend void iter_swap(const StructWithHiddenFriends&, const StructWithHiddenFriends&);
+
+ friend int* begin(const StructWithHiddenFriends&);
+ friend int* end(const StructWithHiddenFriends&);
+ friend int* rbegin(const StructWithHiddenFriends&);
+ friend int* rend(const StructWithHiddenFriends&);
+ friend unsigned int size(const StructWithHiddenFriends&);
+};
+
+// [cmp.alg] ADL should be performed.
+static_assert(std::is_invocable_v<decltype(std::strong_order), StructWithHiddenFriends&, StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::weak_order), StructWithHiddenFriends&, StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::partial_order), StructWithHiddenFriends&, StructWithHiddenFriends&>);
+
+// [cmp.alg] Ordinary unqualified lookup should not be performed.
+static_assert(
+ !std::is_invocable_v<decltype(std::strong_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>);
+static_assert(
+ !std::is_invocable_v<decltype(std::weak_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>);
+static_assert(
+ !std::is_invocable_v<decltype(std::partial_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>);
+
+// [iterator.cust] ADL should be performed.
+static_assert(std::is_invocable_v<decltype(std::ranges::iter_move), StructWithHiddenFriends&>);
+static_assert(
+ std::is_invocable_v<decltype(std::ranges::iter_swap), StructWithHiddenFriends&, StructWithHiddenFriends&>);
+
+// [iterator.cust] Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<decltype(std::ranges::iter_move), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::iter_swap),
+ ns::StructWithGlobalFunctions&,
+ ns::StructWithGlobalFunctions&>);
+
+// [range.access] ADL should be performed.
+static_assert(std::is_invocable_v<decltype(std::ranges::begin), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::cbegin), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::end), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::cend), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::rbegin), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::crbegin), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::rend), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::crend), StructWithHiddenFriends&>);
+static_assert(std::is_invocable_v<decltype(std::ranges::size), StructWithHiddenFriends&>);
+
+// [range.access] Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<decltype(std::ranges::begin), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::cbegin), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::end), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::cend), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::rbegin), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::crbegin), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::rend), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::crend), ns::StructWithGlobalFunctions&>);
+static_assert(!std::is_invocable_v<decltype(std::ranges::size), ns::StructWithGlobalFunctions&>);
More information about the libcxx-commits
mailing list