[libcxx-commits] [libcxx] r364063 - Make move and forward work in C++03.

Eric Fiselier via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jun 21 08:20:55 PDT 2019


Author: ericwf
Date: Fri Jun 21 08:20:55 2019
New Revision: 364063

URL: http://llvm.org/viewvc/llvm-project?rev=364063&view=rev
Log:
Make move and forward work in C++03.

These functions are key to allowing the use of rvalues and variadics
in C++03 mode. Everything works the same as in C++11, except for one
tangentially related case:

struct T {
  T(T &&) = default;
};

In C++11, T has a deleted copy constructor. But in C++03 Clang gives
it both a move and a copy constructor. This seems reasonable enough
given the extensions it's using.

The other changes in this patch were the minimal set required
to keep the tests passing after the move/forward change. Most notably
the removal of the `__rv<unique_ptr>` hack that was present
in an attempt to make unique_ptr move only without language support.

Removed:
    libcxx/trunk/test/std/utilities/utility/forward/forward_03.pass.cpp
Modified:
    libcxx/trunk/include/algorithm
    libcxx/trunk/include/exception
    libcxx/trunk/include/forward_list
    libcxx/trunk/include/memory
    libcxx/trunk/include/type_traits
    libcxx/trunk/test/libcxx/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
    libcxx/trunk/test/std/utilities/utility/forward/forward.fail.cpp
    libcxx/trunk/test/std/utilities/utility/forward/forward.pass.cpp
    libcxx/trunk/test/std/utilities/utility/forward/move.fail.cpp
    libcxx/trunk/test/std/utilities/utility/forward/move.pass.cpp
    libcxx/trunk/test/std/utilities/utility/forward/move_if_noexcept.pass.cpp

Modified: libcxx/trunk/include/algorithm
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/algorithm?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/include/algorithm (original)
+++ libcxx/trunk/include/algorithm Fri Jun 21 08:20:55 2019
@@ -3181,11 +3181,7 @@ _SampleIterator sample(_PopulationIterat
 
 template<class _RandomAccessIterator, class _UniformRandomNumberGenerator>
     void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
-#ifndef _LIBCPP_CXX03_LANG
                  _UniformRandomNumberGenerator&& __g)
-#else
-                 _UniformRandomNumberGenerator& __g)
-#endif
 {
     typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
     typedef uniform_int_distribution<ptrdiff_t> _Dp;

Modified: libcxx/trunk/include/exception
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/exception?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/include/exception (original)
+++ libcxx/trunk/include/exception Fri Jun 21 08:20:55 2019
@@ -260,11 +260,7 @@ struct __throw_with_nested;
 template <class _Tp, class _Up>
 struct __throw_with_nested<_Tp, _Up, true> {
     _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void
-#ifndef _LIBCPP_CXX03_LANG
     __do_throw(_Tp&& __t)
-#else
-    __do_throw (_Tp& __t)
-#endif  // _LIBCPP_CXX03_LANG
     {
         throw __nested<_Up>(_VSTD::forward<_Tp>(__t));
     }
@@ -287,11 +283,7 @@ struct __throw_with_nested<_Tp, _Up, fal
 template <class _Tp>
 _LIBCPP_NORETURN
 void
-#ifndef _LIBCPP_CXX03_LANG
 throw_with_nested(_Tp&& __t)
-#else
-throw_with_nested (_Tp& __t)
-#endif // _LIBCPP_CXX03_LANG
 {
 #ifndef _LIBCPP_NO_EXCEPTIONS
     typedef typename decay<_Tp>::type _Up;

Modified: libcxx/trunk/include/forward_list
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/forward_list?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/include/forward_list (original)
+++ libcxx/trunk/include/forward_list Fri Jun 21 08:20:55 2019
@@ -808,7 +808,6 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     void clear() _NOEXCEPT {base::clear();}
 
-#ifndef _LIBCPP_CXX03_LANG
     _LIBCPP_INLINE_VISIBILITY
     void splice_after(const_iterator __p, forward_list&& __x);
     _LIBCPP_INLINE_VISIBILITY
@@ -816,7 +815,6 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     void splice_after(const_iterator __p, forward_list&& __x,
                       const_iterator __f, const_iterator __l);
-#endif  // _LIBCPP_CXX03_LANG
     void splice_after(const_iterator __p, forward_list& __x);
     void splice_after(const_iterator __p, forward_list& __x, const_iterator __i);
     void splice_after(const_iterator __p, forward_list& __x,
@@ -1468,8 +1466,6 @@ forward_list<_Tp, _Alloc>::splice_after(
     }
 }
 
-#ifndef _LIBCPP_CXX03_LANG
-
 template <class _Tp, class _Alloc>
 inline _LIBCPP_INLINE_VISIBILITY
 void
@@ -1499,8 +1495,6 @@ forward_list<_Tp, _Alloc>::splice_after(
     splice_after(__p, __x, __f, __l);
 }
 
-#endif  // _LIBCPP_CXX03_LANG
-
 template <class _Tp, class _Alloc>
 void
 forward_list<_Tp, _Alloc>::remove(const value_type& __v)

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Fri Jun 21 08:20:55 2019
@@ -2561,14 +2561,9 @@ public:
   }
 
   _LIBCPP_INLINE_VISIBILITY
-  operator __rv<unique_ptr>() {
-    return __rv<unique_ptr>(*this);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  unique_ptr(__rv<unique_ptr> __u)
-      : __ptr_(__u->release(),
-               _VSTD::forward<deleter_type>(__u->get_deleter())) {}
+  unique_ptr(unique_ptr&& __u)
+      : __ptr_(__u.release(),
+               _VSTD::forward<deleter_type>(__u.get_deleter())) {}
 
   template <class _Up, class _Ep>
   _LIBCPP_INLINE_VISIBILITY
@@ -2586,7 +2581,7 @@ public:
 
   _LIBCPP_INLINE_VISIBILITY
   unique_ptr(pointer __p, deleter_type __d)
-      : __ptr_(_VSTD::move(__p), _VSTD::move(__d)) {}
+      : __ptr_(__p, _VSTD::forward<deleter_type>(__d)) {}
 #endif // _LIBCPP_CXX03_LANG
 
 #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
@@ -2863,19 +2858,14 @@ public:
       : __ptr_(pointer(), _VSTD::forward<deleter_type>(__d)) {}
 
   _LIBCPP_INLINE_VISIBILITY
-  operator __rv<unique_ptr>() {
-    return __rv<unique_ptr>(*this);
-  }
+  unique_ptr(unique_ptr&& __u)
+      : __ptr_(__u.release(),
+               _VSTD::forward<deleter_type>(__u.get_deleter())) {}
 
   _LIBCPP_INLINE_VISIBILITY
-  unique_ptr(__rv<unique_ptr> __u)
-      : __ptr_(__u->release(),
-               _VSTD::forward<deleter_type>(__u->get_deleter())) {}
-
-  _LIBCPP_INLINE_VISIBILITY
-  unique_ptr& operator=(__rv<unique_ptr> __u) {
-    reset(__u->release());
-    __ptr_.second() = _VSTD::forward<deleter_type>(__u->get_deleter());
+  unique_ptr& operator=(unique_ptr&& __u) {
+    reset(__u.release());
+    __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter());
     return *this;
   }
 
@@ -3091,18 +3081,6 @@ operator>=(nullptr_t, const unique_ptr<_
     return !(nullptr < __x);
 }
 
-#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-template <class _Tp, class _Dp>
-inline _LIBCPP_INLINE_VISIBILITY
-unique_ptr<_Tp, _Dp>
-move(unique_ptr<_Tp, _Dp>& __t)
-{
-    return unique_ptr<_Tp, _Dp>(__rv<unique_ptr<_Tp, _Dp> >(__t));
-}
-
-#endif
-
 #if _LIBCPP_STD_VER > 11
 
 template<class _Tp>

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Fri Jun 21 08:20:55 2019
@@ -2277,8 +2277,6 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR boo
 
 // move
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
 template <class _Tp>
 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 typename remove_reference<_Tp>::type&&
@@ -2306,47 +2304,6 @@ forward(typename remove_reference<_Tp>::
     return static_cast<_Tp&&>(__t);
 }
 
-#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
-template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
-_Tp&
-move(_Tp& __t)
-{
-    return __t;
-}
-
-template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
-const _Tp&
-move(const _Tp& __t)
-{
-    return __t;
-}
-
-template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
-_Tp&
-forward(typename remove_reference<_Tp>::type& __t) _NOEXCEPT
-{
-    return __t;
-}
-
-
-template <class _Tp>
-class __rv
-{
-    typedef typename remove_reference<_Tp>::type _Trr;
-    _Trr& t_;
-public:
-    _LIBCPP_INLINE_VISIBILITY
-    _Trr* operator->() {return &t_;}
-    _LIBCPP_INLINE_VISIBILITY
-    explicit __rv(_Trr& __t) : t_(__t) {}
-};
-
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 template <class _Tp>

Modified: libcxx/trunk/test/libcxx/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/test/libcxx/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp (original)
+++ libcxx/trunk/test/libcxx/utilities/function.objects/func.require/bullet_4_5_6.pass.cpp Fri Jun 21 08:20:55 2019
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+// FIXME(EricWF): Make this test pass in C++03 with Clang once the transition
+// has gotten far enough that __invoke works.
+// XFAIL: c++98 || c++03
+
 // <functional>
 
 // INVOKE (f, t1, t2, ..., tN)

Modified: libcxx/trunk/test/std/utilities/utility/forward/forward.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/forward/forward.fail.cpp?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/utility/forward/forward.fail.cpp (original)
+++ libcxx/trunk/test/std/utilities/utility/forward/forward.fail.cpp Fri Jun 21 08:20:55 2019
@@ -21,16 +21,10 @@ const A csource() {return A();}
 
 int main(int, char**)
 {
-#if TEST_STD_VER >= 11
     {
         std::forward<A&>(source());  // expected-note {{requested here}}
         // expected-error-re at type_traits:* 1 {{static_assert failed{{.*}} "can not forward an rvalue as an lvalue"}}
     }
-#else
-    {
-        std::forward<A&>(source()); // expected-error {{no matching function for call to 'forward'}}
-    }
-#endif
     {
         const A ca = A();
         std::forward<A&>(ca); // expected-error {{no matching function for call to 'forward'}}

Modified: libcxx/trunk/test/std/utilities/utility/forward/forward.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/forward/forward.pass.cpp?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/utility/forward/forward.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/utility/forward/forward.pass.cpp Fri Jun 21 08:20:55 2019
@@ -20,12 +20,12 @@ struct A
 {
 };
 
-A source() noexcept {return A();}
-const A csource() noexcept {return A();}
+A source() TEST_NOEXCEPT {return A();}
+const A csource() TEST_NOEXCEPT {return A();}
 
 
-constexpr bool test_constexpr_forward() {
 #if TEST_STD_VER > 11
+constexpr bool test_constexpr_forward() {
     int x = 42;
     const int cx = 101;
     return std::forward<int&>(x)        == 42
@@ -36,10 +36,8 @@ constexpr bool test_constexpr_forward()
         && std::forward<const int&&>(x) == 42
         && std::forward<const int&>(cx) == 101
         && std::forward<const int>(cx)  == 101;
-#else
-    return true;
-#endif
 }
+#endif
 
 int main(int, char**)
 {
@@ -52,23 +50,23 @@ int main(int, char**)
     static_assert(std::is_same<decltype(std::forward<A&>(a)), A&>::value, "");
     static_assert(std::is_same<decltype(std::forward<A>(a)), A&&>::value, "");
     static_assert(std::is_same<decltype(std::forward<A>(source())), A&&>::value, "");
-    static_assert(noexcept(std::forward<A&>(a)), "");
-    static_assert(noexcept(std::forward<A>(a)), "");
-    static_assert(noexcept(std::forward<A>(source())), "");
+    ASSERT_NOEXCEPT(std::forward<A&>(a));
+    ASSERT_NOEXCEPT(std::forward<A>(a));
+    ASSERT_NOEXCEPT(std::forward<A>(source()));
 
     static_assert(std::is_same<decltype(std::forward<const A&>(a)), const A&>::value, "");
     static_assert(std::is_same<decltype(std::forward<const A>(a)), const A&&>::value, "");
     static_assert(std::is_same<decltype(std::forward<const A>(source())), const A&&>::value, "");
-    static_assert(noexcept(std::forward<const A&>(a)), "");
-    static_assert(noexcept(std::forward<const A>(a)), "");
-    static_assert(noexcept(std::forward<const A>(source())), "");
+    ASSERT_NOEXCEPT(std::forward<const A&>(a));
+    ASSERT_NOEXCEPT(std::forward<const A>(a));
+    ASSERT_NOEXCEPT(std::forward<const A>(source()));
 
     static_assert(std::is_same<decltype(std::forward<const A&>(ca)), const A&>::value, "");
     static_assert(std::is_same<decltype(std::forward<const A>(ca)), const A&&>::value, "");
     static_assert(std::is_same<decltype(std::forward<const A>(csource())), const A&&>::value, "");
-    static_assert(noexcept(std::forward<const A&>(ca)), "");
-    static_assert(noexcept(std::forward<const A>(ca)), "");
-    static_assert(noexcept(std::forward<const A>(csource())), "");
+    ASSERT_NOEXCEPT(std::forward<const A&>(ca));
+    ASSERT_NOEXCEPT(std::forward<const A>(ca));
+    ASSERT_NOEXCEPT(std::forward<const A>(csource()));
 
 #if TEST_STD_VER > 11
     {

Removed: libcxx/trunk/test/std/utilities/utility/forward/forward_03.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/forward/forward_03.pass.cpp?rev=364062&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/utility/forward/forward_03.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/utility/forward/forward_03.pass.cpp (removed)
@@ -1,59 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// test forward
-
-#include <utility>
-#include <cassert>
-
-#include "test_macros.h"
-
-struct A
-{
-};
-
-A source() {return A();}
-const A csource() {return A();}
-
-typedef char one;
-struct two {one _[2];};
-struct four {one _[4];};
-struct eight {one _[8];};
-
-one test(A&);
-two test(const A&);
-
-int main(int, char**)
-{
-    A a;
-    const A ca = A();
-
-    ((void)a); // Prevent unused warning
-    ((void)ca); // Prevent unused warning
-
-#if TEST_STD_VER < 11
-    static_assert(sizeof(test(std::forward<A&>(a))) == 1, "");
-    static_assert(sizeof(test(std::forward<A>(a))) == 1, "");
-
-    // Libc++'s C++03 implementation of 'forward' cannot accept true non-const
-    // rvalues.
-    // static_assert(sizeof(test(std::forward<A>(source()))) == 2, "");
-
-    static_assert(sizeof(test(std::forward<const A&>(a))) == 2, "");
-    static_assert(sizeof(test(std::forward<const A&>(source()))) == 2, "");
-    static_assert(sizeof(test(std::forward<const A>(a))) == 2, "");
-    static_assert(sizeof(test(std::forward<const A>(source()))) == 2, "");
-
-    static_assert(sizeof(test(std::forward<const A&>(ca))) == 2, "");
-    static_assert(sizeof(test(std::forward<const A&>(csource()))) == 2, "");
-    static_assert(sizeof(test(std::forward<const A>(ca))) == 2, "");
-    static_assert(sizeof(test(std::forward<const A>(csource()))) == 2, "");
-#endif
-
-  return 0;
-}

Modified: libcxx/trunk/test/std/utilities/utility/forward/move.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/forward/move.fail.cpp?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/utility/forward/move.fail.cpp (original)
+++ libcxx/trunk/test/std/utilities/utility/forward/move.fail.cpp Fri Jun 21 08:20:55 2019
@@ -6,7 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++98, c++03
+// This test should pass in C++03 with Clang extensions because Clang does
+// not implicitly delete the copy constructor when move constructors are
+// defaulted using extensions.
+
+// XFAIL: c++98, c++03
 
 // test move
 
@@ -26,10 +30,9 @@ void test(move_only) {}
 
 int main(int, char**)
 {
-    move_only a;
-    const move_only ca = move_only();
-
-    test(std::move(ca)); // c
+  const move_only ca = move_only();
+  // expected-error at +1 {{call to implicitly-deleted copy constructor of 'move_only'}}
+  test(std::move(ca));
 
   return 0;
 }

Modified: libcxx/trunk/test/std/utilities/utility/forward/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/forward/move.pass.cpp?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/utility/forward/move.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/utility/forward/move.pass.cpp Fri Jun 21 08:20:55 2019
@@ -8,8 +8,6 @@
 
 // test move
 
-// UNSUPPORTED: c++98, c++03
-
 #include <utility>
 #include <type_traits>
 #include <cassert>
@@ -36,7 +34,7 @@ int x = 42;
 const int& cx = x;
 
 template <class QualInt>
-QualInt get() noexcept { return static_cast<QualInt>(x); }
+QualInt get() TEST_NOEXCEPT { return static_cast<QualInt>(x); }
 
 
 int copy_ctor = 0;
@@ -49,30 +47,27 @@ struct A {
     A& operator=(const A&) = delete;
 };
 
-constexpr bool test_constexpr_move() {
 #if TEST_STD_VER > 11
+constexpr bool test_constexpr_move() {
     int y = 42;
     const int cy = y;
     return std::move(y) == 42
         && std::move(cy) == 42
         && std::move(static_cast<int&&>(y)) == 42
         && std::move(static_cast<int const&&>(y)) == 42;
-#else
-    return true;
-#endif
 }
-
+#endif
 int main(int, char**)
 {
     { // Test return type and noexcept.
         static_assert(std::is_same<decltype(std::move(x)), int&&>::value, "");
-        static_assert(noexcept(std::move(x)), "");
+        ASSERT_NOEXCEPT(std::move(x));
         static_assert(std::is_same<decltype(std::move(cx)), const int&&>::value, "");
-        static_assert(noexcept(std::move(cx)), "");
+        ASSERT_NOEXCEPT(std::move(cx));
         static_assert(std::is_same<decltype(std::move(42)), int&&>::value, "");
-        static_assert(noexcept(std::move(42)), "");
+        ASSERT_NOEXCEPT(std::move(42));
         static_assert(std::is_same<decltype(std::move(get<const int&&>())), const int&&>::value, "");
-        static_assert(noexcept(std::move(get<int const&&>())), "");
+        ASSERT_NOEXCEPT(std::move(get<int const&&>()));
     }
     { // test copy and move semantics
         A a;

Modified: libcxx/trunk/test/std/utilities/utility/forward/move_if_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/utility/forward/move_if_noexcept.pass.cpp?rev=364063&r1=364062&r2=364063&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/utility/forward/move_if_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/utility/forward/move_if_noexcept.pass.cpp Fri Jun 21 08:20:55 2019
@@ -28,9 +28,7 @@ class A
 public:
 
     A() {}
-#if TEST_STD_VER >= 11
     A(A&&) {}
-#endif
 };
 
 struct legacy
@@ -55,9 +53,7 @@ int main(int, char**)
     static_assert((std::is_same<decltype(std::move_if_noexcept(ca)), const A&&>::value), "");
     static_assert((std::is_same<decltype(std::move_if_noexcept(l)), const legacy&>::value), "");
 #else  // C++ < 11
-    // In C++03 libc++ #define's decltype to be __decltype on clang and
-    // __typeof__ for other compilers. __typeof__ does not deduce the reference
-    // qualifiers and will cause this test to fail.
+    // In C++03 we don't have noexcept so we can never move :-(
     static_assert((std::is_same<decltype(std::move_if_noexcept(i)), const int&>::value), "");
     static_assert((std::is_same<decltype(std::move_if_noexcept(ci)), const int&>::value), "");
     static_assert((std::is_same<decltype(std::move_if_noexcept(a)), const A&>::value), "");




More information about the libcxx-commits mailing list