[libcxx-commits] [libcxx] ff84c63 - [libc++] [ranges] Fix LWG3470 "convertible-to-non-slicing seems to reject valid case"

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jan 26 16:37:43 PST 2022


Author: Arthur O'Dwyer
Date: 2022-01-26T19:30:12-05:00
New Revision: ff84c635b77e3b9ac62116e6e2a85bc6a556fc78

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

LOG: [libc++] [ranges] Fix LWG3470 "convertible-to-non-slicing seems to reject valid case"

Differential Revision: https://reviews.llvm.org/D117941

Added: 
    libcxx/test/std/ranges/range.utility/range.subrange/lwg3470.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx2bIssues.csv
    libcxx/include/__ranges/subrange.h

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index b151393e0a50d..855a1f43a2a99 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -109,7 +109,7 @@
 `3392 <https://wg21.link/LWG3392>`__,"``ranges::distance()`` cannot be used on a move-only iterator with a sized sentinel","October 2021","","","|ranges|"
 `3407 <https://wg21.link/LWG3407>`__,"Some problems with the wording changes of P1739R4","October 2021","","","|ranges|"
 `3422 <https://wg21.link/LWG3422>`__,"Issues of ``seed_seq``'s constructors","October 2021","|Complete|","14.0"
-`3470 <https://wg21.link/LWG3470>`__,"``convertible-to-non-slicing`` seems to reject valid case","October 2021","","","|ranges|"
+`3470 <https://wg21.link/LWG3470>`__,"``convertible-to-non-slicing`` seems to reject valid case","October 2021","|Complete|","14.0","|ranges|"
 `3480 <https://wg21.link/LWG3480>`__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","October 2021","|Complete|","14.0","|ranges|"
 `3498 <https://wg21.link/LWG3498>`__,"Inconsistent ``noexcept``-specifiers for ``basic_syncbuf``","October 2021","",""
 `3535 <https://wg21.link/LWG3535>`__,"``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie","October 2021","","","|ranges|"

diff  --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h
index 8e984f2bf06cc..14716d1fb0fff 100644
--- a/libcxx/include/__ranges/subrange.h
+++ b/libcxx/include/__ranges/subrange.h
@@ -39,13 +39,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #if !defined(_LIBCPP_HAS_NO_RANGES)
 
 namespace ranges {
+  template<class _From, class _To>
+  concept __uses_nonqualification_pointer_conversion =
+    is_pointer_v<_From> && is_pointer_v<_To> &&
+    !convertible_to<remove_pointer_t<_From>(*)[], remove_pointer_t<_To>(*)[]>;
+
   template<class _From, class _To>
   concept __convertible_to_non_slicing =
     convertible_to<_From, _To> &&
-    // If they're both pointers, they must have the same element type.
-    !(is_pointer_v<decay_t<_From>> &&
-      is_pointer_v<decay_t<_To>> &&
-      __
diff erent_from<remove_pointer_t<decay_t<_From>>, remove_pointer_t<decay_t<_To>>>);
+    !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;
 
   template<class _Tp>
   concept __pair_like =

diff  --git a/libcxx/test/std/ranges/range.utility/range.subrange/lwg3470.pass.cpp b/libcxx/test/std/ranges/range.utility/range.subrange/lwg3470.pass.cpp
new file mode 100644
index 0000000000000..d174d09d4eb64
--- /dev/null
+++ b/libcxx/test/std/ranges/range.utility/range.subrange/lwg3470.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// class std::ranges::subrange;
+//   Test the example from LWG 3470,
+//   qualification conversions in __convertible_to_non_slicing
+
+#include <ranges>
+
+#include <cassert>
+
+#include "test_macros.h"
+
+constexpr bool test()
+{
+  // The example from LWG3470, using implicit conversion.
+  int a[3] = { 1, 2, 3 };
+  int* b[3] = { &a[2], &a[0], &a[1] };
+  std::ranges::subrange<const int* const*> c = b;
+  assert(c.begin() == b + 0);
+  assert(c.end() == b + 3);
+
+  // Also test CTAD and a subrange-to-subrange conversion.
+  std::same_as<std::ranges::subrange<int**>> auto d = std::ranges::subrange(b);
+  assert(d.begin() == b + 0);
+  assert(d.end() == b + 3);
+
+  std::ranges::subrange<const int* const*> e = d;
+  assert(e.begin() == b + 0);
+  assert(e.end() == b + 3);
+
+  return true;
+}
+
+int main(int, char**)
+{
+  test();
+  static_assert(test());
+
+  return 0;
+}


        


More information about the libcxx-commits mailing list