[libcxx-commits] [libcxx] 4163f61 - [libc++] [ranges] Fix a missing auto(x) cast in ranges::data.

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jan 12 15:18:23 PST 2022


Author: Arthur O'Dwyer
Date: 2022-01-12T18:16:15-05:00
New Revision: 4163f61f29f47d3e0d82cec2ba4cf8997d4b6820

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

LOG: [libc++] [ranges] Fix a missing auto(x) cast in ranges::data.

Also remove some bogus `std::forward`s. My impression is that these
forwards were actually harmless, because `ranges::begin(FWD(t))` is
always identical to `ranges::begin(t)` (except when it's ill-formed,
and that can't happen in this case). However, they're also superfluous
and don't reflect the wording in the standard, so let's eliminate them.

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

Added: 
    

Modified: 
    libcxx/include/__ranges/data.h
    libcxx/test/std/ranges/range.access/data.pass.cpp
    libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__ranges/data.h b/libcxx/include/__ranges/data.h
index cc151c59f3d78..de39312b49cda 100644
--- a/libcxx/include/__ranges/data.h
+++ b/libcxx/include/__ranges/data.h
@@ -14,8 +14,7 @@
 #include <__iterator/iterator_traits.h>
 #include <__memory/pointer_traits.h>
 #include <__ranges/access.h>
-#include <__utility/forward.h>
-#include <concepts>
+#include <__utility/auto_cast.h>
 #include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -35,34 +34,32 @@ namespace __data {
 
   template <class _Tp>
   concept __member_data =
+    __can_borrow<_Tp> &&
     requires(_Tp&& __t) {
-      { _VSTD::forward<_Tp>(__t) } -> __can_borrow;
-      { __t.data() } -> __ptr_to_object;
+      { _LIBCPP_AUTO_CAST(__t.data()) } -> __ptr_to_object;
     };
 
   template <class _Tp>
   concept __ranges_begin_invocable =
     !__member_data<_Tp> &&
+    __can_borrow<_Tp> &&
     requires(_Tp&& __t) {
-      { _VSTD::forward<_Tp>(__t) } -> __can_borrow;
-      { ranges::begin(_VSTD::forward<_Tp>(__t)) } -> contiguous_iterator;
+      { ranges::begin(__t) } -> contiguous_iterator;
     };
 
   struct __fn {
     template <__member_data _Tp>
-      requires __can_borrow<_Tp>
     _LIBCPP_HIDE_FROM_ABI
-    constexpr __ptr_to_object auto operator()(_Tp&& __t) const
+    constexpr auto operator()(_Tp&& __t) const
         noexcept(noexcept(__t.data())) {
       return __t.data();
     }
 
     template<__ranges_begin_invocable _Tp>
-      requires __can_borrow<_Tp>
     _LIBCPP_HIDE_FROM_ABI
-    constexpr __ptr_to_object auto operator()(_Tp&& __t) const
-        noexcept(noexcept(_VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t))))) {
-      return _VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t)));
+    constexpr auto operator()(_Tp&& __t) const
+        noexcept(noexcept(_VSTD::to_address(ranges::begin(__t)))) {
+      return _VSTD::to_address(ranges::begin(__t));
     }
   };
 }

diff  --git a/libcxx/test/std/ranges/range.access/data.pass.cpp b/libcxx/test/std/ranges/range.access/data.pass.cpp
index 6d0b718f6b040..da4d79d724f3b 100644
--- a/libcxx/test/std/ranges/range.access/data.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/data.pass.cpp
@@ -36,9 +36,45 @@ struct DataMember {
   int x;
   constexpr const int *data() const { return &x; }
 };
-
 static_assert( std::is_invocable_v<RangeDataT, DataMember &>);
 static_assert(!std::is_invocable_v<RangeDataT, DataMember &&>);
+static_assert( std::is_invocable_v<RangeDataT, DataMember const&>);
+static_assert(!std::is_invocable_v<RangeDataT, DataMember const&&>);
+
+constexpr bool testReturnTypes() {
+  {
+    int *x[2];
+    ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int**);
+  }
+  {
+    int x[2][2];
+    ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int(*)[2]);
+  }
+  {
+    struct D {
+      char*& data();
+      short*& data() const;
+    };
+    ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<D&>())), char*);
+    static_assert(!std::is_invocable_v<RangeDataT, D&&>);
+    ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const D&>())), short*);
+    static_assert(!std::is_invocable_v<RangeDataT, const D&&>);
+  }
+  {
+    struct NC {
+      char *begin() const;
+      char *end() const;
+      int *data();
+    };
+    static_assert(!std::ranges::contiguous_range<NC>);
+    static_assert( std::ranges::contiguous_range<const NC>);
+    ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<NC&>())), int*);
+    static_assert(!std::is_invocable_v<RangeDataT, NC&&>);
+    ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const NC&>())), char*);
+    static_assert(!std::is_invocable_v<RangeDataT, const NC&&>);
+  }
+  return true;
+}
 
 struct VoidDataMember {
   void *data() const;
@@ -49,21 +85,14 @@ struct Empty { };
 struct EmptyDataMember {
   Empty data() const;
 };
-
 static_assert(!std::is_invocable_v<RangeDataT, EmptyDataMember const&>);
 
-struct EmptyPtrDataMember {
-  Empty x;
-  constexpr const Empty *data() const { return &x; }
-};
-
-struct PtrConvertible {
-  operator int*() const;
-};
 struct PtrConvertibleDataMember {
-  PtrConvertible data() const;
+  struct Ptr {
+    operator int*() const;
+  };
+  Ptr data() const;
 };
-
 static_assert(!std::is_invocable_v<RangeDataT, PtrConvertibleDataMember const&>);
 
 struct NonConstDataMember {
@@ -74,14 +103,13 @@ struct NonConstDataMember {
 struct EnabledBorrowingDataMember {
   constexpr int *data() { return &globalBuff[0]; }
 };
-
 template<>
 inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingDataMember> = true;
 
 struct DataMemberAndBegin {
   int x;
   constexpr const int *data() const { return &x; }
-  constexpr const int *begin() const { return &x; }
+  const int *begin() const;
 };
 
 constexpr bool testDataMember() {
@@ -147,8 +175,10 @@ struct BeginMemberRvalue {
 
   ContiguousIter begin() &&;
 };
+static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&>);
 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&&>);
 static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&>);
+static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&&>);
 
 struct BeginMemberBorrowingEnabled {
   constexpr contiguous_iterator<int*> begin() { return contiguous_iterator<int*>{&globalBuff[1]}; }
@@ -188,6 +218,8 @@ struct RandomButNotContiguous {
 static_assert(!std::is_invocable_v<RangeDataT, RandomButNotContiguous>);
 
 int main(int, char**) {
+  static_assert(testReturnTypes());
+
   testDataMember();
   static_assert(testDataMember());
 

diff  --git a/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp
index 228c27774b8cc..1b5aa353d9364 100644
--- a/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp
@@ -46,8 +46,8 @@ struct ContiguousWhenNonConst {
     int *end();
     int *data() const;
 };
-static_assert( std::ranges::random_access_range<ContiguousWhenNonConst>);
 static_assert( std::ranges::contiguous_range<ContiguousWhenNonConst>);
+static_assert( std::ranges::random_access_range<const ContiguousWhenNonConst>);
 static_assert(!std::ranges::contiguous_range<const ContiguousWhenNonConst>);
 
 struct ContiguousWhenConst {
@@ -57,9 +57,9 @@ struct ContiguousWhenConst {
     int *end();
     const int *data() const;
 };
+static_assert( std::ranges::contiguous_range<const ContiguousWhenConst>);
 static_assert( std::ranges::random_access_range<ContiguousWhenConst>);
 static_assert(!std::ranges::contiguous_range<ContiguousWhenConst>);
-static_assert( std::ranges::contiguous_range<const ContiguousWhenConst>);
 
 struct DataFunctionWrongReturnType {
     const int *begin() const;
@@ -67,7 +67,7 @@ struct DataFunctionWrongReturnType {
     const char *data() const;
 };
 static_assert( std::ranges::random_access_range<DataFunctionWrongReturnType>);
-static_assert(!std::ranges::contiguous_range<const DataFunctionWrongReturnType>);
+static_assert(!std::ranges::contiguous_range<DataFunctionWrongReturnType>);
 
 struct WrongObjectness {
     const int *begin() const;


        


More information about the libcxx-commits mailing list