[clang] [libcxx] [clang-tools-extra] [llvm] [libc++] P2602R2 Poison Pills are Too Toxic (PR #74534)
Jakub Mazurkiewicz via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 10 14:54:51 PST 2024
https://github.com/JMazurkiewicz updated https://github.com/llvm/llvm-project/pull/74534
>From aaccb9e13618517803df1230741b02b4c5ee08c7 Mon Sep 17 00:00:00 2001
From: Jakub Mazurkiewicz <mazkuba3 at gmail.com>
Date: Tue, 5 Dec 2023 23:36:57 +0100
Subject: [PATCH 1/3] [libc++] P2602R2 Poison Pills are Too Toxic
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +-
libcxx/docs/Status/Cxx23Papers.csv | 2 +-
libcxx/include/__compare/partial_order.h | 2 ++
libcxx/include/__compare/strong_order.h | 2 ++
libcxx/include/__compare/weak_order.h | 2 ++
libcxx/include/__iterator/iter_move.h | 2 +-
libcxx/include/__ranges/access.h | 6 ++--
libcxx/include/__ranges/rbegin.h | 3 +-
libcxx/include/__ranges/rend.h | 3 +-
libcxx/include/__ranges/size.h | 3 +-
libcxx/include/version | 4 +--
.../iterator.cust.move/iter_move.pass.cpp | 11 +++++++
.../iterator.cust.swap/iter_swap.pass.cpp | 6 ++++
.../ordinary_unqualified_lookup_helpers.h | 33 +++++++++++++++++++
.../cmp/cmp.alg/partial_order.pass.cpp | 9 +++++
.../cmp/cmp.alg/strong_order.pass.cpp | 9 +++++
.../cmp/cmp.alg/weak_order.pass.cpp | 9 +++++
.../algorithm.version.compile.pass.cpp | 14 ++++----
.../functional.version.compile.pass.cpp | 14 ++++----
.../iterator.version.compile.pass.cpp | 14 ++++----
.../memory.version.compile.pass.cpp | 14 ++++----
.../ranges.version.compile.pass.cpp | 14 ++++----
.../version.version.compile.pass.cpp | 14 ++++----
.../std/ranges/range.access/begin.pass.cpp | 18 +++++++---
.../test/std/ranges/range.access/end.pass.cpp | 20 +++++++----
.../ordinary_unqualified_lookup_helpers.h | 25 ++++++++++++++
.../std/ranges/range.access/rbegin.pass.cpp | 18 +++++++---
.../std/ranges/range.access/rend.pass.cpp | 20 +++++++----
.../std/ranges/range.access/size.pass.cpp | 9 ++++-
.../generate_feature_test_macro_components.py | 2 +-
30 files changed, 223 insertions(+), 81 deletions(-)
create mode 100644 libcxx/test/std/language.support/cmp/cmp.alg/ordinary_unqualified_lookup_helpers.h
create mode 100644 libcxx/test/std/ranges/range.access/ordinary_unqualified_lookup_helpers.h
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index d09f65b7cadc0e..f4788aa5747882 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -266,7 +266,7 @@ Status
--------------------------------------------------- -----------------
``__cpp_lib_polymorphic_allocator`` ``201902L``
--------------------------------------------------- -----------------
- ``__cpp_lib_ranges`` ``202207L``
+ ``__cpp_lib_ranges`` ``202211L``
--------------------------------------------------- -----------------
``__cpp_lib_remove_cvref`` ``201711L``
--------------------------------------------------- -----------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index e03cbff2a08bbf..7dc6f36ba1e63f 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","|In Progress|","","|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|","18.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 36a11dfaa2881b..b422bdd4ef8415 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 cbfcf7316de9e0..ba59cb51b86d99 100644
--- a/libcxx/include/__compare/strong_order.h
+++ b/libcxx/include/__compare/strong_order.h
@@ -34,6 +34,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 e6a42ac4c92352..8d7f9390923030 100644
--- a/libcxx/include/__compare/weak_order.h
+++ b/libcxx/include/__compare/weak_order.h
@@ -28,6 +28,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 d9ff90bf654566..79dcac8f50b9f4 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 =
diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h
index 502bd5e951c4a6..01bf8cc2f544f3 100644
--- a/libcxx/include/__ranges/access.h
+++ b/libcxx/include/__ranges/access.h
@@ -49,8 +49,7 @@ namespace __begin {
{ _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 =
@@ -121,8 +120,7 @@ namespace __end {
{ _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 1ceb1116d695fc..8fd17a3c016a23 100644
--- a/libcxx/include/__ranges/rbegin.h
+++ b/libcxx/include/__ranges/rbegin.h
@@ -43,8 +43,7 @@ concept __member_rbegin =
{ _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 7ee574ccfa6745..1f482963ac749f 100644
--- a/libcxx/include/__ranges/rend.h
+++ b/libcxx/include/__ranges/rend.h
@@ -45,8 +45,7 @@ concept __member_rend =
{ _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 f22dd1ff7b79f3..0ed939e0bd4f9c 100644
--- a/libcxx/include/__ranges/size.h
+++ b/libcxx/include/__ranges/size.h
@@ -41,8 +41,7 @@ namespace ranges {
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/include/version b/libcxx/include/version
index e84790b888d333..71937c3a3d1c22 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -164,7 +164,7 @@ __cpp_lib_parallel_algorithm 201603L <algorithm> <num
__cpp_lib_polymorphic_allocator 201902L <memory_resource>
__cpp_lib_print 202207L <ostream> <print>
__cpp_lib_quoted_string_io 201304L <iomanip>
-__cpp_lib_ranges 202207L <algorithm> <functional> <iterator>
+__cpp_lib_ranges 202211L <algorithm> <functional> <iterator>
<memory> <ranges>
__cpp_lib_ranges_as_const 202207L <ranges>
__cpp_lib_ranges_as_rvalue 202207L <ranges>
@@ -405,7 +405,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
# if _LIBCPP_AVAILABILITY_HAS_PMR
# define __cpp_lib_polymorphic_allocator 201902L
# endif
-# define __cpp_lib_ranges 202207L
+# define __cpp_lib_ranges 202211L
# define __cpp_lib_remove_cvref 201711L
# if !defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC
# define __cpp_lib_semaphore 201907L
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
index 566638263e8875..8cd515d8e7fb47 100644
--- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
@@ -11,6 +11,14 @@
// template<class I>
// unspecified iter_move;
+// Note: this struct is intentionally defined before any other header is included.
+// Custom `iter_move` must be visible to `std::ranges::iter_move` CPO from `<iterator>` header.
+namespace nest {
+struct StructWithGlobalIterMove {};
+} // namespace nest
+
+int&& iter_move(nest::StructWithGlobalIterMove);
+
#include <algorithm>
#include <array>
#include <cassert>
@@ -186,6 +194,9 @@ template<class T> struct Holder { T t; };
static_assert(std::is_invocable_v<IterMoveT, Holder<Incomplete>**>);
static_assert(std::is_invocable_v<IterMoveT, Holder<Incomplete>**&>);
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<IterMoveT, nest::StructWithGlobalIterMove&>);
+
int main(int, char**)
{
test();
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..692ddef195d2c2 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,12 @@ 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 NotMoreSpecializedIterSwap {
+ friend void iter_swap(auto&, auto&);
+};
+
+static_assert(!std::is_invocable_v<IterSwapT, NotMoreSpecializedIterSwap&, NotMoreSpecializedIterSwap&>);
+
struct NodiscardIterSwap {
[[nodiscard]] friend int iter_swap(NodiscardIterSwap&, NodiscardIterSwap&) { return 0; }
};
diff --git a/libcxx/test/std/language.support/cmp/cmp.alg/ordinary_unqualified_lookup_helpers.h b/libcxx/test/std/language.support/cmp/cmp.alg/ordinary_unqualified_lookup_helpers.h
new file mode 100644
index 00000000000000..4cbe163c312f4b
--- /dev/null
+++ b/libcxx/test/std/language.support/cmp/cmp.alg/ordinary_unqualified_lookup_helpers.h
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_LANGUAGE_SUPPORT_CMP_CMP_ALG_ORDINARY_UNQUALIFIED_LOOKUP_HELPERS_H
+#define TEST_STD_LANGUAGE_SUPPORT_CMP_CMP_ALG_ORDINARY_UNQUALIFIED_LOOKUP_HELPERS_H
+
+// Note: this header should be included before any other header.
+// Comparison functions defined here must be visible to CPOs from `<compare>` header.
+
+namespace nest {
+struct StructWithGlobalCmpFunctions {};
+} // namespace nest
+
+struct ConvertibleToComparisonType;
+
+ConvertibleToComparisonType strong_order(nest::StructWithGlobalCmpFunctions, nest::StructWithGlobalCmpFunctions);
+ConvertibleToComparisonType weak_order(nest::StructWithGlobalCmpFunctions, nest::StructWithGlobalCmpFunctions);
+ConvertibleToComparisonType partial_order(nest::StructWithGlobalCmpFunctions, nest::StructWithGlobalCmpFunctions);
+
+#include <compare> // Intentionally included here, so we can define `ConvertibleToComparisonType` later.
+
+struct ConvertibleToComparisonType {
+ operator std::strong_ordering() const;
+ operator std::weak_ordering() const;
+ operator std::partial_ordering() const;
+};
+
+#endif // TEST_STD_LANGUAGE_SUPPORT_CMP_CMP_ALG_ORDINARY_UNQUALIFIED_LOOKUP_HELPERS_H
diff --git a/libcxx/test/std/language.support/cmp/cmp.alg/partial_order.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.alg/partial_order.pass.cpp
index bd313889b1a4e3..d6376f0a5cb2a0 100644
--- a/libcxx/test/std/language.support/cmp/cmp.alg/partial_order.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.alg/partial_order.pass.cpp
@@ -12,6 +12,10 @@
// template<class T> constexpr partial_ordering partial_order(const T& a, const T& b);
+// Note: this header is intentionally included before any other header.
+// Comparison functions defined there must be visible to CPOs from `<compare>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <compare>
#include <cassert>
@@ -240,6 +244,11 @@ constexpr bool test_1_4()
return true;
}
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<decltype(std::partial_order),
+ nest::StructWithGlobalCmpFunctions,
+ nest::StructWithGlobalCmpFunctions>);
+
int main(int, char**)
{
test_1_1();
diff --git a/libcxx/test/std/language.support/cmp/cmp.alg/strong_order.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.alg/strong_order.pass.cpp
index ac6b6879f77309..5c26a0be23f0ac 100644
--- a/libcxx/test/std/language.support/cmp/cmp.alg/strong_order.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.alg/strong_order.pass.cpp
@@ -12,6 +12,10 @@
// template<class T> constexpr strong_ordering strong_order(const T& a, const T& b);
+// Note: this header is intentionally included before any other header.
+// Comparison functions defined there must be visible to CPOs from `<compare>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <compare>
#include <cassert>
@@ -448,6 +452,11 @@ constexpr bool test_1_4()
return true;
}
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<decltype(std::strong_order),
+ nest::StructWithGlobalCmpFunctions,
+ nest::StructWithGlobalCmpFunctions>);
+
int main(int, char**)
{
test_1_1();
diff --git a/libcxx/test/std/language.support/cmp/cmp.alg/weak_order.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.alg/weak_order.pass.cpp
index 09d720196e0b2b..0dc79acc99ed97 100644
--- a/libcxx/test/std/language.support/cmp/cmp.alg/weak_order.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.alg/weak_order.pass.cpp
@@ -12,6 +12,10 @@
// template<class T> constexpr weak_ordering weak_order(const T& a, const T& b);
+// Note: this header is intentionally included before any other header.
+// Comparison functions defined there must be visible to CPOs from `<compare>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <compare>
#include <cassert>
@@ -493,6 +497,11 @@ constexpr bool test_1_5()
return true;
}
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<decltype(std::weak_order),
+ nest::StructWithGlobalCmpFunctions,
+ nest::StructWithGlobalCmpFunctions>);
+
int main(int, char**)
{
test_1_1();
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp
index ec6503ec237554..918c6d35f730dc 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp
@@ -20,7 +20,7 @@
__cpp_lib_constexpr_algorithms 201806L [C++20]
__cpp_lib_freestanding_algorithm 202311L [C++26]
__cpp_lib_parallel_algorithm 201603L [C++17]
- __cpp_lib_ranges 202207L [C++20]
+ __cpp_lib_ranges 202211L [C++20]
__cpp_lib_ranges_starts_ends_with 202106L [C++23]
__cpp_lib_robust_nonmodifying_seq_ops 201304L [C++14]
__cpp_lib_sample 201603L [C++17]
@@ -201,8 +201,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++20"
# endif
# ifdef __cpp_lib_ranges_starts_ends_with
@@ -266,8 +266,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++23"
# endif
# if !defined(_LIBCPP_VERSION)
@@ -349,8 +349,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
index 72c96c62b64c45..55674d104fab90 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
@@ -28,7 +28,7 @@
__cpp_lib_invoke_r 202106L [C++23]
__cpp_lib_move_only_function 202110L [C++23]
__cpp_lib_not_fn 201603L [C++17]
- __cpp_lib_ranges 202207L [C++20]
+ __cpp_lib_ranges 202211L [C++20]
__cpp_lib_result_of_sfinae 201210L [C++14]
__cpp_lib_transparent_operators 201210L [C++14]
201510L [C++17]
@@ -293,8 +293,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++20"
# endif
# ifndef __cpp_lib_result_of_sfinae
@@ -399,8 +399,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++23"
# endif
# ifndef __cpp_lib_result_of_sfinae
@@ -523,8 +523,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++26"
# endif
# ifndef __cpp_lib_result_of_sfinae
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp
index 700907ce9bb071..6c652e694f6ddf 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp
@@ -23,7 +23,7 @@
__cpp_lib_move_iterator_concept 202207L [C++20]
__cpp_lib_nonmember_container_access 201411L [C++17]
__cpp_lib_null_iterators 201304L [C++14]
- __cpp_lib_ranges 202207L [C++20]
+ __cpp_lib_ranges 202211L [C++20]
__cpp_lib_ssize 201902L [C++20]
*/
@@ -197,8 +197,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++20"
# endif
# ifndef __cpp_lib_ssize
@@ -255,8 +255,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++23"
# endif
# ifndef __cpp_lib_ssize
@@ -313,8 +313,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++26"
# endif
# ifndef __cpp_lib_ssize
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
index b1f6c76d847398..8ea1173309432f 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
@@ -28,7 +28,7 @@
__cpp_lib_make_unique 201304L [C++14]
__cpp_lib_out_ptr 202106L [C++23]
202311L [C++26]
- __cpp_lib_ranges 202207L [C++20]
+ __cpp_lib_ranges 202211L [C++20]
__cpp_lib_raw_memory_algorithms 201606L [C++17]
__cpp_lib_shared_ptr_arrays 201611L [C++17]
201707L [C++20]
@@ -364,8 +364,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++20"
# endif
# ifndef __cpp_lib_raw_memory_algorithms
@@ -501,8 +501,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++23"
# endif
# ifndef __cpp_lib_raw_memory_algorithms
@@ -638,8 +638,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++26"
# endif
# ifndef __cpp_lib_raw_memory_algorithms
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index aa3a4964ad492e..0ea59178e68787 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -16,7 +16,7 @@
// Test the feature test macros defined by <ranges>
/* Constant Value
- __cpp_lib_ranges 202207L [C++20]
+ __cpp_lib_ranges 202211L [C++20]
__cpp_lib_ranges_as_const 202207L [C++23]
__cpp_lib_ranges_as_rvalue 202207L [C++23]
__cpp_lib_ranges_chunk 202202L [C++23]
@@ -162,8 +162,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++20"
# endif
# ifdef __cpp_lib_ranges_as_const
@@ -207,8 +207,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++23"
# endif
# if !defined(_LIBCPP_VERSION)
@@ -309,8 +309,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 0b00469892f607..9572fac59d79f1 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -153,7 +153,7 @@
__cpp_lib_polymorphic_allocator 201902L [C++20]
__cpp_lib_print 202207L [C++23]
__cpp_lib_quoted_string_io 201304L [C++14]
- __cpp_lib_ranges 202207L [C++20]
+ __cpp_lib_ranges 202211L [C++20]
__cpp_lib_ranges_as_const 202207L [C++23]
__cpp_lib_ranges_as_rvalue 202207L [C++23]
__cpp_lib_ranges_chunk 202202L [C++23]
@@ -3832,8 +3832,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++20"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++20"
# endif
# ifdef __cpp_lib_ranges_as_const
@@ -5272,8 +5272,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++23"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++23"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++23"
# endif
# if !defined(_LIBCPP_VERSION)
@@ -6985,8 +6985,8 @@
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++26"
# endif
-# if __cpp_lib_ranges != 202207L
-# error "__cpp_lib_ranges should have the value 202207L in c++26"
+# if __cpp_lib_ranges != 202211L
+# error "__cpp_lib_ranges should have the value 202211L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/ranges/range.access/begin.pass.cpp b/libcxx/test/std/ranges/range.access/begin.pass.cpp
index ca25fc297a0119..89e1e130c2dfbf 100644
--- a/libcxx/test/std/ranges/range.access/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/begin.pass.cpp
@@ -11,6 +11,10 @@
// std::ranges::begin
// std::ranges::cbegin
+// Note: this header is intentionally included before any other header.
+// Access functions defined here must be visible to accessors from `<ranges>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <ranges>
#include <cassert>
@@ -192,7 +196,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 +249,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 +270,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);
@@ -325,6 +329,10 @@ static_assert(!std::is_invocable_v<RangeBeginT, Holder<Incomplete>*&>);
static_assert(!std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*>);
static_assert(!std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*&>);
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<RangeBeginT, nest::StructWithGlobalAccess&>);
+static_assert(!std::is_invocable_v<RangeCBeginT, nest::StructWithGlobalAccess&>);
+
int main(int, char**) {
static_assert(testReturnTypes());
diff --git a/libcxx/test/std/ranges/range.access/end.pass.cpp b/libcxx/test/std/ranges/range.access/end.pass.cpp
index 21d97354ef08d0..749c20fe4c1602 100644
--- a/libcxx/test/std/ranges/range.access/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/end.pass.cpp
@@ -11,6 +11,10 @@
// std::ranges::end
// std::ranges::cend
+// Note: this header is intentionally included before any other header.
+// Access functions defined here must be visible to accessors from `<ranges>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <ranges>
#include <cassert>
@@ -193,7 +197,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 +275,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 +290,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;
@@ -354,6 +358,10 @@ static_assert(!std::is_invocable_v<RangeEndT, Holder<Incomplete>*&>);
static_assert(!std::is_invocable_v<RangeCEndT, Holder<Incomplete>*>);
static_assert(!std::is_invocable_v<RangeCEndT, Holder<Incomplete>*&>);
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<RangeEndT, nest::StructWithGlobalAccess&>);
+static_assert(!std::is_invocable_v<RangeCEndT, nest::StructWithGlobalAccess&>);
+
int main(int, char**) {
static_assert(testReturnTypes());
diff --git a/libcxx/test/std/ranges/range.access/ordinary_unqualified_lookup_helpers.h b/libcxx/test/std/ranges/range.access/ordinary_unqualified_lookup_helpers.h
new file mode 100644
index 00000000000000..34be68aef1f4f8
--- /dev/null
+++ b/libcxx/test/std/ranges/range.access/ordinary_unqualified_lookup_helpers.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_RANGES_RANGE_ACCESS_ORDINARY_UNQUALIFIED_LOOKUP_HELPERS_H
+#define TEST_STD_RANGES_RANGE_ACCESS_ORDINARY_UNQUALIFIED_LOOKUP_HELPERS_H
+
+// Note: this header should be included before any other header.
+// Access functions defined here must be visible to accessors from `<ranges>` header.
+
+namespace nest {
+struct StructWithGlobalAccess {};
+} // namespace nest
+
+int* begin(nest::StructWithGlobalAccess);
+int* end(nest::StructWithGlobalAccess);
+int* rbegin(nest::StructWithGlobalAccess);
+int* rend(nest::StructWithGlobalAccess);
+unsigned int size(nest::StructWithGlobalAccess);
+
+#endif // TEST_STD_RANGES_RANGE_ACCESS_ORDINARY_UNQUALIFIED_LOOKUP_HELPERS_H
diff --git a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
index e1a564c94ed948..9bd804b59d3b1d 100644
--- a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
@@ -11,6 +11,10 @@
// std::ranges::rbegin
// std::ranges::crbegin
+// Note: this header is intentionally included before any other header.
+// Access functions defined here must be visible to accessors from `<ranges>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <ranges>
#include <cassert>
@@ -187,7 +191,7 @@ 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 +250,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 +271,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);
@@ -501,6 +505,10 @@ static_assert(!std::is_invocable_v<RangeRBeginT, Holder<Incomplete>*&>);
static_assert(!std::is_invocable_v<RangeCRBeginT, Holder<Incomplete>*>);
static_assert(!std::is_invocable_v<RangeCRBeginT, Holder<Incomplete>*&>);
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<RangeRBeginT, nest::StructWithGlobalAccess&>);
+static_assert(!std::is_invocable_v<RangeCRBeginT, nest::StructWithGlobalAccess&>);
+
int main(int, char**) {
static_assert(testReturnTypes());
diff --git a/libcxx/test/std/ranges/range.access/rend.pass.cpp b/libcxx/test/std/ranges/range.access/rend.pass.cpp
index 5ba244b6b18cfe..eb45889ca70f87 100644
--- a/libcxx/test/std/ranges/range.access/rend.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/rend.pass.cpp
@@ -11,6 +11,10 @@
// std::ranges::rend
// std::ranges::crend
+// Note: this header is intentionally included before any other header.
+// Access functions defined here must be visible to accessors from `<ranges>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <ranges>
#include <cassert>
@@ -196,7 +200,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 +276,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 +291,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;
@@ -530,6 +534,10 @@ static_assert(!std::is_invocable_v<RangeREndT, Holder<Incomplete>*&>);
static_assert(!std::is_invocable_v<RangeCREndT, Holder<Incomplete>*>);
static_assert(!std::is_invocable_v<RangeCREndT, Holder<Incomplete>*&>);
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<RangeREndT, nest::StructWithGlobalAccess&>);
+static_assert(!std::is_invocable_v<RangeCREndT, nest::StructWithGlobalAccess&>);
+
int main(int, char**) {
static_assert(testReturnTypes());
diff --git a/libcxx/test/std/ranges/range.access/size.pass.cpp b/libcxx/test/std/ranges/range.access/size.pass.cpp
index fd7d0a8b997522..36bd19ba8c5791 100644
--- a/libcxx/test/std/ranges/range.access/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/size.pass.cpp
@@ -10,6 +10,10 @@
// std::ranges::size
+// Note: this header is intentionally included before any other header.
+// Access functions defined here must be visible to accessors from `<ranges>` header.
+#include "ordinary_unqualified_lookup_helpers.h"
+
#include <ranges>
#include <cassert>
@@ -219,7 +223,7 @@ 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.
@@ -318,6 +322,9 @@ template<class T> struct Holder { T t; };
static_assert(!std::is_invocable_v<RangeSizeT, Holder<Incomplete>*>);
static_assert(!std::is_invocable_v<RangeSizeT, Holder<Incomplete>*&>);
+// Ordinary unqualified lookup should not be performed.
+static_assert(!std::is_invocable_v<RangeSizeT, nest::StructWithGlobalAccess&>);
+
int main(int, char**) {
testArrayType();
static_assert(testArrayType());
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 8943ad2557433c..153b7d54a70595 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -882,7 +882,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_ranges",
- "values": {"c++20": 202207},
+ "values": {"c++20": 202211}, # DR P2602R2 Poison Pills are Too Toxic
"headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
},
{
>From 912bc3e26f810214f57631f36b9d7899d2360313 Mon Sep 17 00:00:00 2001
From: Jakub Mazurkiewicz <mazkuba3 at gmail.com>
Date: Wed, 6 Dec 2023 00:18:46 +0100
Subject: [PATCH 2/3] =?UTF-8?q?Make=20=F0=9F=90=8D=20formatter=20happy?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
libcxx/utils/generate_feature_test_macro_components.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 153b7d54a70595..531b8f0863e7a5 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -882,7 +882,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_ranges",
- "values": {"c++20": 202211}, # DR P2602R2 Poison Pills are Too Toxic
+ "values": {"c++20": 202211}, # DR P2602R2 Poison Pills are Too Toxic
"headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
},
{
>From aabffddfe5b976c681315ca0b72c2a0e6dcb06c1 Mon Sep 17 00:00:00 2001
From: Jakub Mazurkiewicz <mazkuba3 at gmail.com>
Date: Wed, 10 Jan 2024 23:54:18 +0100
Subject: [PATCH 3/3] Formatting
---
libcxx/test/std/ranges/range.access/begin.pass.cpp | 2 +-
libcxx/test/std/ranges/range.access/end.pass.cpp | 2 +-
libcxx/test/std/ranges/range.access/rbegin.pass.cpp | 3 ++-
libcxx/test/std/ranges/range.access/rend.pass.cpp | 2 +-
libcxx/test/std/ranges/range.access/size.pass.cpp | 3 ++-
5 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/libcxx/test/std/ranges/range.access/begin.pass.cpp b/libcxx/test/std/ranges/range.access/begin.pass.cpp
index 89e1e130c2dfbf..c667fcfdce81dc 100644
--- a/libcxx/test/std/ranges/range.access/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/begin.pass.cpp
@@ -196,7 +196,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 &>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
+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 &>);
diff --git a/libcxx/test/std/ranges/range.access/end.pass.cpp b/libcxx/test/std/ranges/range.access/end.pass.cpp
index 749c20fe4c1602..3047827dd8bcb2 100644
--- a/libcxx/test/std/ranges/range.access/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/end.pass.cpp
@@ -197,7 +197,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 &>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
+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 &>);
diff --git a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
index 9bd804b59d3b1d..dee0445f20eb64 100644
--- a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
@@ -191,7 +191,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 &>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
+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 &>);
diff --git a/libcxx/test/std/ranges/range.access/rend.pass.cpp b/libcxx/test/std/ranges/range.access/rend.pass.cpp
index eb45889ca70f87..4ec72cd80b7431 100644
--- a/libcxx/test/std/ranges/range.access/rend.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/rend.pass.cpp
@@ -200,7 +200,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 &>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
+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 &>);
diff --git a/libcxx/test/std/ranges/range.access/size.pass.cpp b/libcxx/test/std/ranges/range.access/size.pass.cpp
index 36bd19ba8c5791..f35b2d659c0cf8 100644
--- a/libcxx/test/std/ranges/range.access/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/size.pass.cpp
@@ -223,7 +223,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&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
+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.
More information about the llvm-commits
mailing list