[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