Index: include/__bit_reference =================================================================== --- include/__bit_reference +++ include/__bit_reference @@ -1081,9 +1081,17 @@ return __equal_unaligned(__first1, __last1, __first2); } +template +struct __bit_iterator_is_trivially_relocatable { + typedef typename conditional<_IsConst, typename _Cp::__const_storage_pointer, + typename _Cp::__storage_pointer>::type __storage_pointer; + + typedef __libcpp_is_trivially_relocatable<__storage_pointer> type; +}; + template -class __bit_iterator +class _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__bit_iterator_is_trivially_relocatable<_Cp, _IsConst>::type::value)) __bit_iterator { public: typedef typename _Cp::difference_type difference_type; Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -1309,6 +1309,14 @@ #define _LIBCPP_HAS_NO_IS_AGGREGATE #endif +#if __has_extension(trivially_relocatable) +#define _LIBCPP_TRIVIALLY_RELOCATABLE [[clang::trivially_relocatable]] +#define _LIBCPP_TRIVIALLY_RELOCATABLE_IF(x) [[clang::trivially_relocatable(x)]] +#else +#define _LIBCPP_TRIVIALLY_RELOCATABLE +#define _LIBCPP_TRIVIALLY_RELOCATABLE_IF(x) +#endif + #if !defined(__cpp_coroutines) || __cpp_coroutines < 201703L #define _LIBCPP_HAS_NO_COROUTINES #endif Index: include/__hash_table =================================================================== --- include/__hash_table +++ include/__hash_table @@ -763,7 +763,8 @@ }; template -class __bucket_list_deallocator +class _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__libcpp_is_trivially_relocatable<__compressed_pair::size_type, _Alloc>>::value)) + __bucket_list_deallocator { typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; @@ -1403,6 +1404,19 @@ void __deallocate_node(__next_pointer __np) _NOEXCEPT; __next_pointer __detach() _NOEXCEPT; +public: + typedef integral_constant= 2 + false +#else + __libcpp_is_trivially_relocatable<__bucket_list>::value && + __libcpp_is_trivially_relocatable<__first_node>::value && + __libcpp_is_trivially_relocatable<__node_allocator>::value && + __libcpp_is_trivially_relocatable::value && + __libcpp_is_trivially_relocatable::value +#endif + > __allow_trivial_relocation; + template friend class _LIBCPP_TEMPLATE_VIS unordered_map; template friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; }; Index: include/__locale =================================================================== --- include/__locale +++ include/__locale @@ -118,7 +118,7 @@ const _Facet& use_facet(const locale&); -class _LIBCPP_TYPE_VIS locale +class _LIBCPP_TYPE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE locale { public: // types: Index: include/__mutex_base =================================================================== --- include/__mutex_base +++ include/__mutex_base @@ -111,7 +111,7 @@ }; template -class _LIBCPP_TEMPLATE_VIS unique_lock +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE unique_lock { public: typedef _Mutex mutex_type; Index: include/bitset =================================================================== --- include/bitset +++ include/bitset @@ -147,12 +147,12 @@ typedef ptrdiff_t difference_type; typedef size_t size_type; typedef size_type __storage_type; -protected: typedef __bitset __self; typedef __storage_type* __storage_pointer; typedef const __storage_type* __const_storage_pointer; static const unsigned __bits_per_word = static_cast(sizeof(__storage_type) * CHAR_BIT); +protected: friend class __bit_reference<__bitset>; friend class __bit_const_reference<__bitset>; friend class __bit_iterator<__bitset, false>; @@ -443,12 +443,12 @@ typedef ptrdiff_t difference_type; typedef size_t size_type; typedef size_type __storage_type; -protected: typedef __bitset __self; typedef __storage_type* __storage_pointer; typedef const __storage_type* __const_storage_pointer; static const unsigned __bits_per_word = static_cast(sizeof(__storage_type) * CHAR_BIT); +protected: friend class __bit_reference<__bitset>; friend class __bit_const_reference<__bitset>; friend class __bit_iterator<__bitset, false>; @@ -602,12 +602,12 @@ typedef ptrdiff_t difference_type; typedef size_t size_type; typedef size_type __storage_type; -protected: typedef __bitset __self; typedef __storage_type* __storage_pointer; typedef const __storage_type* __const_storage_pointer; static const unsigned __bits_per_word = static_cast(sizeof(__storage_type) * CHAR_BIT); +protected: friend class __bit_reference<__bitset>; friend class __bit_const_reference<__bitset>; friend class __bit_iterator<__bitset, false>; Index: include/deque =================================================================== --- include/deque +++ include/deque @@ -1024,6 +1024,14 @@ __deque_base * const __base_; }; +public: + typedef integral_constant::value && + __libcpp_is_trivially_relocatable<__pointer_allocator>::value && + __libcpp_is_trivially_relocatable::value && + __libcpp_is_trivially_relocatable::value + > __allow_trivial_relocation; + protected: __map __map_; size_type __start_; @@ -1263,7 +1271,7 @@ } template */> -class _LIBCPP_TEMPLATE_VIS deque +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__deque_base<_Tp, _Allocator>::__allow_trivial_relocation::value)) deque : private __deque_base<_Tp, _Allocator> { public: Index: include/exception =================================================================== --- include/exception +++ include/exception @@ -136,7 +136,7 @@ #ifndef _LIBCPP_ABI_MICROSOFT -class _LIBCPP_TYPE_VIS exception_ptr +class _LIBCPP_TYPE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE exception_ptr { void* __ptr_; public: Index: include/forward_list =================================================================== --- include/forward_list +++ include/forward_list @@ -556,6 +556,9 @@ void __move_assign_alloc(__forward_list_base& __x, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {__alloc() = _VSTD::move(__x.__alloc());} + +public: + typedef __libcpp_is_trivially_relocatable<__compressed_pair<__begin_node, __node_allocator> > __allow_trivial_relocation; }; #ifndef _LIBCPP_CXX03_LANG @@ -623,7 +626,9 @@ } template */> -class _LIBCPP_TEMPLATE_VIS forward_list +class _LIBCPP_TEMPLATE_VIS + _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__forward_list_base<_Tp, _Alloc>::__allow_trivial_relocation::value)) + forward_list : private __forward_list_base<_Tp, _Alloc> { typedef __forward_list_base<_Tp, _Alloc> base; Index: include/future =================================================================== --- include/future +++ include/future @@ -1076,7 +1076,7 @@ #endif template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_TRIVIALLY_RELOCATABLE future { __assoc_state<_Rp>* __state_; @@ -1176,7 +1176,7 @@ } template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future<_Rp&> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_TRIVIALLY_RELOCATABLE future<_Rp&> { __assoc_state<_Rp&>* __state_; @@ -1271,7 +1271,7 @@ } template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE future +class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_TRIVIALLY_RELOCATABLE future { __assoc_sub_state* __state_; @@ -1354,7 +1354,7 @@ template class packaged_task; template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_TRIVIALLY_RELOCATABLE promise { __assoc_state<_Rp>* __state_; @@ -1521,7 +1521,7 @@ // promise template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<_Rp&> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_TRIVIALLY_RELOCATABLE promise<_Rp&> { __assoc_state<_Rp&>* __state_; @@ -1657,7 +1657,7 @@ // promise template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE promise +class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_TRIVIALLY_RELOCATABLE promise { __assoc_sub_state* __state_; @@ -2364,7 +2364,7 @@ // shared_future template -class _LIBCPP_TEMPLATE_VIS shared_future +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE shared_future { __assoc_state<_Rp>* __state_; @@ -2438,7 +2438,7 @@ } template -class _LIBCPP_TEMPLATE_VIS shared_future<_Rp&> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE shared_future<_Rp&> { __assoc_state<_Rp&>* __state_; @@ -2512,7 +2512,7 @@ } template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE shared_future +class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_TRIVIALLY_RELOCATABLE shared_future { __assoc_sub_state* __state_; Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -2432,8 +2432,16 @@ typedef false_type __enable_rval_overload; }; +template +struct __unique_ptr_is_trivially_relocatable { + typedef _Tp element_type; + typedef _Dp deleter_type; + typedef typename __pointer_type<_Tp, deleter_type>::type pointer; + typedef __libcpp_is_trivially_relocatable<__compressed_pair > type; +}; + template > -class _LIBCPP_TEMPLATE_VIS unique_ptr { +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__unique_ptr_is_trivially_relocatable<_Tp, _Dp>::type::value)) unique_ptr { public: typedef _Tp element_type; typedef _Dp deleter_type; @@ -2641,7 +2649,7 @@ template -class _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> { +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__unique_ptr_is_trivially_relocatable<_Tp, _Dp>::type::value)) unique_ptr<_Tp[], _Dp> { public: typedef _Tp element_type; typedef _Dp deleter_type; @@ -3812,7 +3820,7 @@ template class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; template -class _LIBCPP_TEMPLATE_VIS shared_ptr +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE shared_ptr { public: typedef _Tp element_type; @@ -4806,7 +4814,7 @@ #endif // _LIBCPP_NO_RTTI template -class _LIBCPP_TEMPLATE_VIS weak_ptr +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE weak_ptr { public: typedef _Tp element_type; Index: include/optional =================================================================== --- include/optional +++ include/optional @@ -581,7 +581,7 @@ >; template -class optional +class _LIBCPP_TRIVIALLY_RELOCATABLE_IF(__libcpp_is_trivially_relocatable<_Tp>::value) optional : private __optional_move_assign_base<_Tp> , private __optional_sfinae_ctor_base_t<_Tp> , private __optional_sfinae_assign_base_t<_Tp> Index: include/queue =================================================================== --- include/queue +++ include/queue @@ -210,7 +210,7 @@ operator< (const queue<_Tp, _Container>& __x,const queue<_Tp, _Container>& __y); template */> -class _LIBCPP_TEMPLATE_VIS queue +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__libcpp_is_trivially_relocatable<_Container>::value)) queue { public: typedef _Container container_type; @@ -424,7 +424,7 @@ template , class _Compare = less > -class _LIBCPP_TEMPLATE_VIS priority_queue +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__libcpp_is_trivially_relocatable<_Container>::value && __libcpp_is_trivially_relocatable<_Compare>::value)) priority_queue { public: typedef _Container container_type; Index: include/shared_mutex =================================================================== --- include/shared_mutex +++ include/shared_mutex @@ -306,7 +306,7 @@ } template -class shared_lock +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE shared_lock { public: typedef _Mutex mutex_type; Index: include/stack =================================================================== --- include/stack +++ include/stack @@ -109,7 +109,7 @@ operator< (const stack<_Tp, _Container>& __x, const stack<_Tp, _Container>& __y); template */> -class _LIBCPP_TEMPLATE_VIS stack +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__libcpp_is_trivially_relocatable<_Container>::value)) stack { public: typedef _Container container_type; Index: include/string =================================================================== --- include/string +++ include/string @@ -662,8 +662,21 @@ #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +template +struct __basic_string_is_trivially_relocatable { +#if _LIBCPP_DEBUG_LEVEL >= 2 + typedef false_type type; +#else + typedef typename allocator_traits<_Allocator>::pointer pointer; + typedef integral_constant::value && + __libcpp_is_trivially_relocatable<_Allocator>::value + > type; +#endif +}; + template -class _LIBCPP_TEMPLATE_VIS basic_string +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF(__basic_string_is_trivially_relocatable<_Allocator>::type::value) basic_string : private __basic_string_common { public: Index: include/thread =================================================================== --- include/thread +++ include/thread @@ -213,7 +213,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) {return __os << __id.__id_;} -class _LIBCPP_TYPE_VIS thread +class _LIBCPP_TYPE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE thread { __libcpp_thread_t __t_; Index: include/unordered_map =================================================================== --- include/unordered_map +++ include/unordered_map @@ -840,7 +840,9 @@ template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > -class _LIBCPP_TEMPLATE_VIS unordered_map +class _LIBCPP_TEMPLATE_VIS + _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__hash_table, _Hash, _Pred, _Alloc>::__allow_trivial_relocation::value)) + unordered_map { public: // types @@ -1740,7 +1742,9 @@ template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > -class _LIBCPP_TEMPLATE_VIS unordered_multimap +class _LIBCPP_TEMPLATE_VIS + _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__hash_table, _Hash, _Pred, _Alloc>::__allow_trivial_relocation::value)) + unordered_multimap { public: // types Index: include/unordered_set =================================================================== --- include/unordered_set +++ include/unordered_set @@ -379,7 +379,9 @@ template , class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> > -class _LIBCPP_TEMPLATE_VIS unordered_set +class _LIBCPP_TEMPLATE_VIS + _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__hash_table<_Value, _Hash, _Pred, _Alloc>::__allow_trivial_relocation::value)) + unordered_set { public: // types @@ -1042,7 +1044,9 @@ template , class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> > -class _LIBCPP_TEMPLATE_VIS unordered_multiset +class _LIBCPP_TEMPLATE_VIS + _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__hash_table<_Value, _Hash, _Pred, _Alloc>::__allow_trivial_relocation::value)) + unordered_multiset { public: // types Index: include/variant =================================================================== --- include/variant +++ include/variant @@ -1160,7 +1160,7 @@ } // __variant_detail template -class _LIBCPP_TEMPLATE_VIS variant +class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF(__all<__libcpp_is_trivially_relocatable_v<_Types>...>::value) variant : private __sfinae_ctor_base< __all...>::value, __all...>::value>, Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -414,6 +414,13 @@ void __move_assign_alloc(__vector_base&, false_type) _NOEXCEPT {} + +public: +#if _LIBCPP_DEBUG_LEVEL >= 2 + typedef false_type __allow_trivial_relocation; +#else + typedef __libcpp_is_trivially_relocatable<__compressed_pair > __allow_trivial_relocation; +#endif }; template @@ -466,7 +473,9 @@ } template */> -class _LIBCPP_TEMPLATE_VIS vector +class _LIBCPP_TEMPLATE_VIS + _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__vector_base<_Tp, _Allocator>::__allow_trivial_relocation::value)) + vector : private __vector_base<_Tp, _Allocator> { private: @@ -2159,7 +2168,26 @@ }; template -class _LIBCPP_TEMPLATE_VIS vector +struct __vector_bool_is_trivially_relocatable { + typedef _Allocator allocator_type; + typedef allocator_traits __alloc_traits; + typedef typename __alloc_traits::size_type size_type; + typedef size_type __storage_type; + typedef typename __rebind_alloc_helper<__alloc_traits, __storage_type>::type __storage_allocator; + typedef allocator_traits<__storage_allocator> __storage_traits; + typedef typename __storage_traits::pointer __storage_pointer; + + typedef integral_constant::value && + __libcpp_is_trivially_relocatable::value && + __libcpp_is_trivially_relocatable<__compressed_pair >::value + > type; +}; + +template +class _LIBCPP_TEMPLATE_VIS + _LIBCPP_TRIVIALLY_RELOCATABLE_IF(__vector_bool_is_trivially_relocatable<_Allocator>::type::value) + vector : private __vector_base_common { public: @@ -2169,7 +2197,7 @@ typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; - typedef size_type __storage_type; + typedef size_type __storage_type; typedef __bit_iterator pointer; typedef __bit_iterator const_pointer; typedef pointer iterator; @@ -2177,12 +2205,12 @@ typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; -private: typedef typename __rebind_alloc_helper<__alloc_traits, __storage_type>::type __storage_allocator; typedef allocator_traits<__storage_allocator> __storage_traits; typedef typename __storage_traits::pointer __storage_pointer; typedef typename __storage_traits::const_pointer __const_storage_pointer; +private: __storage_pointer __begin_; size_type __size_; __compressed_pair __cap_alloc_; Index: test/libcxx/containers/sequences/deque/trivially_relocatable.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/sequences/deque/trivially_relocatable.pass.cpp @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template class deque; + +#include +#include +#include + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +struct NonTriv { ~NonTriv(); }; + +namespace fa { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + // The defaulted (trivial) copy constructor is still present here! + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template using deque = std::deque>; +} + +namespace fa2 { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + FakeAllocator(const FakeAllocator&); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using deque = std::deque>; +} + +namespace fa3 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&) = default; + FakePointer& operator=(const FakePointer&) = default; + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using deque = std::deque>; +} + +namespace fa4 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&); + FakePointer& operator=(const FakePointer&); + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using deque = std::deque>; +} + + +static_assert(std::is_trivially_relocatable< std::allocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa2::FakeAllocator >::value, ""); +static_assert(std::is_trivially_relocatable< fa4::FakeAllocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa4::FakePointer >::value, ""); + +template +void check_trivial_relocatability() +{ +#if !__has_extension(trivially_relocatable) + // Making deque trivially relocatable requires using the attribute. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#else + static_assert(std::is_trivially_relocatable< VT >::value == Expected, ""); +#endif +} + +int main() +{ + check_trivial_relocatability< std::deque, true >(); + check_trivial_relocatability< std::deque, true >(); + + check_trivial_relocatability< fa::deque, true >(); + check_trivial_relocatability< fa::deque, true >(); + + check_trivial_relocatability< fa2::deque, false >(); + check_trivial_relocatability< fa2::deque, false >(); + + check_trivial_relocatability< fa3::deque, true >(); + check_trivial_relocatability< fa3::deque, true >(); + + check_trivial_relocatability< fa4::deque, false >(); + check_trivial_relocatability< fa4::deque, false >(); +} Index: test/libcxx/containers/sequences/vector/trivially_relocatable.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/sequences/vector/trivially_relocatable.pass.cpp @@ -0,0 +1,159 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template class vector; + +#include +#include +#include + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + +struct Incomplete; +struct NonTriv { ~NonTriv(); }; + +namespace fa { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + // The defaulted (trivial) copy constructor is still present here! + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template using vector = std::vector>; +} + +namespace fa2 { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + FakeAllocator(const FakeAllocator&); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using vector = std::vector>; +} + +namespace fa3 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&) = default; + FakePointer& operator=(const FakePointer&) = default; + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using vector = std::vector>; +} + +namespace fa4 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&); + FakePointer& operator=(const FakePointer&); + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using vector = std::vector>; +} + + +static_assert(std::is_trivially_relocatable< std::allocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa2::FakeAllocator >::value, ""); +static_assert(std::is_trivially_relocatable< fa4::FakeAllocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa4::FakePointer >::value, ""); + +template +void check_trivial_relocatability() +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + // Debugging adds significant operations to vector's move-constructor and destructor. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#elif !__has_extension(trivially_relocatable) + // Making vector trivially relocatable requires using the attribute. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#else + static_assert(std::is_trivially_relocatable< VT >::value == Expected, ""); +#endif +} + +int main() +{ + check_trivial_relocatability< std::vector, true >(); + check_trivial_relocatability< std::vector, true >(); + check_trivial_relocatability< std::vector, true >(); + + check_trivial_relocatability< fa::vector, true >(); + check_trivial_relocatability< fa::vector, true >(); + check_trivial_relocatability< fa::vector, true >(); + + check_trivial_relocatability< fa2::vector, false >(); + check_trivial_relocatability< fa2::vector, false >(); + check_trivial_relocatability< fa2::vector, false >(); + + check_trivial_relocatability< fa3::vector, true >(); + check_trivial_relocatability< fa3::vector, true >(); + check_trivial_relocatability< fa3::vector, true >(); + + check_trivial_relocatability< fa4::vector, false >(); + check_trivial_relocatability< fa4::vector, false >(); + check_trivial_relocatability< fa4::vector, false >(); +} Index: test/libcxx/containers/unord/unord.map/trivially_relocatable.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/unord/unord.map/trivially_relocatable.pass.cpp @@ -0,0 +1,183 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +#include +#include +#include + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +struct NonTriv { ~NonTriv(); }; +template <> struct std::hash { size_t operator()(const NonTriv&) const; }; +bool operator==(const NonTriv&, const NonTriv&); + +namespace fa { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + // The defaulted (trivial) copy constructor is still present here! + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template using alloc = FakeAllocator>; + template using unordered_map = std::unordered_map, std::equal_to, alloc>; +} + +namespace fa2 { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + FakeAllocator(const FakeAllocator&); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using alloc = FakeAllocator>; + template using unordered_map = std::unordered_map, std::equal_to, alloc>; +} + +namespace fa3 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&) = default; + FakePointer& operator=(const FakePointer&) = default; + std::conditional_t::value, char, T>& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using alloc = FakeAllocator>; + template using unordered_map = std::unordered_map, std::equal_to, alloc>; +} + +namespace fa4 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&); + FakePointer& operator=(const FakePointer&); + std::conditional_t::value, char, T>& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using alloc = FakeAllocator>; + template using unordered_map = std::unordered_map, std::equal_to, alloc>; +} + +namespace fa5 { + template + struct FakeHasher : std::hash { + ~FakeHasher(); + }; + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using unordered_map = std::unordered_map, std::equal_to>; +} + +namespace fa6 { + template + struct FakeEqualTo : std::equal_to { + ~FakeEqualTo(); + }; + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using unordered_map = std::unordered_map, FakeEqualTo>; +} + +static_assert(std::is_trivially_relocatable< std::allocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa2::FakeAllocator >::value, ""); +static_assert(std::is_trivially_relocatable< fa4::FakeAllocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa4::FakePointer >::value, ""); + +template +void check_trivial_relocatability() +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + // Debugging adds significant operations to unordered_set's move-constructor and destructor. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#elif !__has_extension(trivially_relocatable) + // Making unordered_set trivially relocatable requires using the attribute. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#else + static_assert(std::is_trivially_relocatable< VT >::value == Expected, ""); +#endif +} + +int main() +{ + check_trivial_relocatability< std::unordered_map, true >(); + check_trivial_relocatability< std::unordered_map, true >(); + + check_trivial_relocatability< fa::unordered_map, true >(); + check_trivial_relocatability< fa::unordered_map, true >(); + + check_trivial_relocatability< fa2::unordered_map, false >(); + check_trivial_relocatability< fa2::unordered_map, false >(); + + check_trivial_relocatability< fa3::unordered_map, true >(); + check_trivial_relocatability< fa3::unordered_map, true >(); + + check_trivial_relocatability< fa4::unordered_map, false >(); + check_trivial_relocatability< fa4::unordered_map, false >(); + + check_trivial_relocatability< fa5::unordered_map, false >(); + check_trivial_relocatability< fa5::unordered_map, false >(); + + check_trivial_relocatability< fa6::unordered_map, false >(); + check_trivial_relocatability< fa6::unordered_map, false >(); +} Index: test/libcxx/containers/unord/unord.set/trivially_relocatable.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/containers/unord/unord.set/trivially_relocatable.pass.cpp @@ -0,0 +1,179 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +#include +#include +#include + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +struct NonTriv { ~NonTriv(); }; +template <> struct std::hash { size_t operator()(const NonTriv&) const; }; +bool operator==(const NonTriv&, const NonTriv&); + +namespace fa { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + // The defaulted (trivial) copy constructor is still present here! + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template using unordered_set = std::unordered_set, std::equal_to, FakeAllocator>; +} + +namespace fa2 { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + FakeAllocator(const FakeAllocator&); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using unordered_set = std::unordered_set, std::equal_to, FakeAllocator>; +} + +namespace fa3 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&) = default; + FakePointer& operator=(const FakePointer&) = default; + std::conditional_t::value, char, T>& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using unordered_set = std::unordered_set, std::equal_to, FakeAllocator>; +} + +namespace fa4 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&); + FakePointer& operator=(const FakePointer&); + std::conditional_t::value, char, T>& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + template using unordered_set = std::unordered_set, std::equal_to, FakeAllocator>; +} + +namespace fa5 { + template + struct FakeHasher : std::hash { + ~FakeHasher(); + }; + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using unordered_set = std::unordered_set, std::equal_to, std::allocator>; +} + +namespace fa6 { + template + struct FakeEqualTo : std::equal_to { + ~FakeEqualTo(); + }; + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using unordered_set = std::unordered_set, FakeEqualTo, std::allocator>; +} + +static_assert(std::is_trivially_relocatable< std::allocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa2::FakeAllocator >::value, ""); +static_assert(std::is_trivially_relocatable< fa4::FakeAllocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa4::FakePointer >::value, ""); + +template +void check_trivial_relocatability() +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + // Debugging adds significant operations to unordered_set's move-constructor and destructor. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#elif !__has_extension(trivially_relocatable) + // Making unordered_set trivially relocatable requires using the attribute. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#else + static_assert(std::is_trivially_relocatable< VT >::value == Expected, ""); +#endif +} + +int main() +{ + check_trivial_relocatability< std::unordered_set, true >(); + check_trivial_relocatability< std::unordered_set, true >(); + + check_trivial_relocatability< fa::unordered_set, true >(); + check_trivial_relocatability< fa::unordered_set, true >(); + + check_trivial_relocatability< fa2::unordered_set, false >(); + check_trivial_relocatability< fa2::unordered_set, false >(); + + check_trivial_relocatability< fa3::unordered_set, true >(); + check_trivial_relocatability< fa3::unordered_set, true >(); + + check_trivial_relocatability< fa4::unordered_set, false >(); + check_trivial_relocatability< fa4::unordered_set, false >(); + + check_trivial_relocatability< fa5::unordered_set, false >(); + check_trivial_relocatability< fa5::unordered_set, false >(); + + check_trivial_relocatability< fa6::unordered_set, false >(); + check_trivial_relocatability< fa6::unordered_set, false >(); +} Index: test/libcxx/strings/basic.string/trivially_relocatable.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/strings/basic.string/trivially_relocatable.pass.cpp @@ -0,0 +1,154 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +#include +#include +#include + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +namespace fa { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + // The defaulted (trivial) copy constructor is still present here! + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + using string = std::basic_string, FakeAllocator>; + using wstring = std::basic_string, FakeAllocator>; +} + +namespace fa2 { + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + template + FakeAllocator(const FakeAllocator&); + FakeAllocator(const FakeAllocator&); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + using string = std::basic_string, FakeAllocator>; + using wstring = std::basic_string, FakeAllocator>; +} + +namespace fa3 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&) = default; + FakePointer& operator=(const FakePointer&) = default; + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + using string = std::basic_string, FakeAllocator>; + using wstring = std::basic_string, FakeAllocator>; +} + +namespace fa4 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&); + FakePointer& operator=(const FakePointer&); + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template + struct FakeAllocator : std::allocator { + template struct rebind { + using other = FakeAllocator; + }; + using pointer = FakePointer; + }; + + using string = std::basic_string, FakeAllocator>; + using wstring = std::basic_string, FakeAllocator>; +} + + +static_assert(std::is_trivially_relocatable< std::allocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa2::FakeAllocator >::value, ""); +static_assert(std::is_trivially_relocatable< fa4::FakeAllocator >::value, ""); +static_assert(!std::is_trivially_relocatable< fa4::FakePointer >::value, ""); + +template +void check_trivial_relocatability() +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + // Debugging adds significant operations to string's move-constructor and destructor. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#elif !__has_extension(trivially_relocatable) + // Making string trivially relocatable requires using the attribute. + static_assert(std::is_trivially_relocatable< VT >::value == false, ""); +#else + static_assert(std::is_trivially_relocatable< VT >::value == Expected, ""); +#endif +} + +int main() +{ + check_trivial_relocatability< std::string, true >(); + check_trivial_relocatability< std::wstring, true >(); + + check_trivial_relocatability< fa::string, true >(); + check_trivial_relocatability< fa::wstring, true >(); + + check_trivial_relocatability< fa2::string, false >(); + check_trivial_relocatability< fa2::wstring, false >(); + + check_trivial_relocatability< fa3::string, true >(); + check_trivial_relocatability< fa3::wstring, true >(); + + check_trivial_relocatability< fa4::string, false >(); + check_trivial_relocatability< fa4::wstring, false >(); +} Index: test/libcxx/type_traits/is_trivially_relocatable.pass.cpp =================================================================== --- test/libcxx/type_traits/is_trivially_relocatable.pass.cpp +++ test/libcxx/type_traits/is_trivially_relocatable.pass.cpp @@ -62,6 +62,10 @@ T t; bool operator==(const K&) const; bool operator< (const K&) const; + struct Cmp { + Cmp(); Cmp(const Cmp&); ~Cmp(); + bool operator()(const K&, const K&) const; + }; }; template<> struct std::hash { size_t operator()(const K&) const; }; @@ -72,7 +76,7 @@ true; #endif -// Define this name for convenience. +// Define the P1144 name for convenience. #define is_trivially_relocatable __libcpp_is_trivially_relocatable static_assert(std::is_trivially_relocatable::value, ""); @@ -81,14 +85,15 @@ static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); +//static_assert(!std::is_trivially_relocatable::value, ""); // virtual destructor //static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); @@ -98,9 +103,9 @@ static_assert(std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable::value, ""); -static_assert(!std::is_trivially_relocatable::value, ""); -static_assert(!std::is_trivially_relocatable::value, ""); -static_assert(!std::is_trivially_relocatable::value, ""); +static_assert(std::is_trivially_relocatable::value, ""); +static_assert(std::is_trivially_relocatable::value, ""); +static_assert(!std::is_trivially_relocatable::value, ""); // virtual destructor static_assert(!std::is_trivially_relocatable::value, ""); static_assert(std::is_trivially_relocatable::value, ""); static_assert(std::is_trivially_relocatable::value, ""); @@ -108,22 +113,26 @@ static_assert(std::is_trivially_relocatable::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value == NotDebug, ""); +static_assert(std::is_trivially_relocatable>::value == NotDebug, ""); +static_assert(std::is_trivially_relocatable>::value == NotDebug, ""); +static_assert(std::is_trivially_relocatable>::value == NotDebug, ""); +static_assert(std::is_trivially_relocatable>::value == NotDebug, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value == NotDebug, ""); +static_assert(!std::is_trivially_relocatable>>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(!std::is_trivially_relocatable>>::value, ""); +static_assert(std::is_trivially_relocatable>::value == NotDebug, ""); +static_assert(std::is_trivially_relocatable>>::value, ""); +static_assert(!std::is_trivially_relocatable, K::Cmp>>::value, ""); //static_assert(std::is_trivially_relocatable>::value, ""); //static_assert(std::is_trivially_relocatable>::value, ""); //static_assert(!std::is_trivially_relocatable>::value, ""); @@ -156,28 +165,28 @@ static_assert(std::is_trivially_relocatable::local_iterator>::value == NotDebug, ""); static_assert(std::is_trivially_relocatable::iterator>::value == NotDebug, ""); static_assert(std::is_trivially_relocatable::const_iterator>::value == NotDebug, ""); -static_assert(!std::is_trivially_relocatable::iterator>::value, ""); +static_assert(std::is_trivially_relocatable::iterator>::value, ""); static_assert(std::is_trivially_relocatable::const_iterator>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>>::value, ""); static_assert(std::is_trivially_relocatable>>::value, ""); static_assert(std::is_trivially_relocatable>>::value == NotDebug, ""); -static_assert(!std::is_trivially_relocatable>>::value, ""); +static_assert(std::is_trivially_relocatable>>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable::value, ""); -static_assert(!std::is_trivially_relocatable::value, ""); // because it uses vector internally -static_assert(!std::is_trivially_relocatable::value, ""); // because it uses vector internally -static_assert(!std::is_trivially_relocatable::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); // contains a locale +static_assert(std::is_trivially_relocatable::value, ""); // contains a regex_traits +static_assert(std::is_trivially_relocatable::value == NotDebug, ""); // contains a vector +static_assert(std::is_trivially_relocatable::value == NotDebug, ""); // contains a vector +static_assert(std::is_trivially_relocatable::value == NotDebug, ""); static_assert(std::is_trivially_relocatable::value == NotDebug, ""); -static_assert(!std::is_trivially_relocatable::value, ""); +static_assert(std::is_trivially_relocatable::value == NotDebug, ""); static_assert(std::is_trivially_relocatable::value == NotDebug, ""); -//static_assert(std::is_trivially_relocatable::value == NotDebug, ""); // because it uses vector internally -//static_assert(std::is_trivially_relocatable::value == NotDebug, ""); // because it uses vector internally +//static_assert(std::is_trivially_relocatable::value == NotDebug, ""); // contains a vector +//static_assert(std::is_trivially_relocatable::value == NotDebug, ""); // contains a vector //static_assert(std::is_trivially_relocatable::value == NotDebug, ""); //static_assert(std::is_trivially_relocatable::value == NotDebug, ""); //static_assert(std::is_trivially_relocatable::value == NotDebug, ""); @@ -190,19 +199,19 @@ static_assert(std::is_trivially_relocatable::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); static_assert(std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable::value, ""); static_assert(std::is_trivially_relocatable::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); -static_assert(!std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); +static_assert(std::is_trivially_relocatable>::value, ""); static_assert(!std::is_trivially_relocatable>::value, ""); // contains pointer into self static_assert(!std::is_trivially_relocatable>::value, ""); // contains pointer into self static_assert(!std::is_trivially_relocatable>::value, ""); // contains pointer into self Index: test/libcxx/utilities/memory/util.smartptr/trivially_relocatable.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/memory/util.smartptr/trivially_relocatable.pass.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++03 +// +// +// +// class shared_ptr +// class unique_ptr +// class weak_ptr + +#include + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +class Incomplete; +class NonTriv { ~NonTriv(); }; +class _LIBCPP_TRIVIALLY_RELOCATABLE Reloc { ~Reloc(); }; + +static_assert(std::is_trivially_relocatable::value, ""); +static_assert(!std::is_trivially_relocatable::value, ""); +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable< std::shared_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::shared_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::shared_ptr >::value, ""); + +static_assert(std::is_trivially_relocatable< std::weak_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::weak_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::weak_ptr >::value, ""); + +static_assert(std::is_trivially_relocatable< std::default_delete >::value, ""); +static_assert(std::is_trivially_relocatable< std::unique_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::unique_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::unique_ptr >::value, ""); + +static_assert(std::is_trivially_relocatable< std::default_delete >::value, ""); +static_assert(std::is_trivially_relocatable< std::unique_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::unique_ptr >::value, ""); +static_assert(std::is_trivially_relocatable< std::unique_ptr >::value, ""); +#endif + +int main() {} Index: test/libcxx/utilities/memory/util.smartptr/trivially_relocatable_with_deleter.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/memory/util.smartptr/trivially_relocatable_with_deleter.pass.cpp @@ -0,0 +1,162 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template class unique_ptr; + +#include +#include + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +struct Incomplete; +struct NonTriv { ~NonTriv(); }; + +namespace fa { + template + struct FakeDeleter { + using pointer = T*; + void operator()(pointer p) const; + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template using unique_ptr = std::unique_ptr>; +} + +namespace fa2 { + template + struct FakeDeleter { + using pointer = T*; + ~FakeDeleter(); + void operator()(pointer p) const; + }; + static_assert(!std::is_trivially_destructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template using unique_ptr = std::unique_ptr>; +} + +namespace fa3 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&) = default; + FakePointer& operator=(const FakePointer&) = default; + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(std::is_trivially_copy_constructible>::value, ""); + static_assert(std::is_trivially_relocatable>::value, ""); + + template + struct FakeDeleter { + using pointer = FakePointer; + void operator()(pointer p) const; + }; + + template using unique_ptr = std::unique_ptr>; +} + +namespace fa4 { + template + struct FakePointer { + int offset; + FakePointer(); + FakePointer(const FakePointer&); + FakePointer& operator=(const FakePointer&); + T& operator*() const; + T* operator->() const; + FakePointer operator + (unsigned int) const; + FakePointer& operator += (unsigned int); + FakePointer operator ++(int); + FakePointer& operator ++(); + FakePointer operator --(int); + FakePointer& operator --(); + }; + static_assert(!std::is_trivially_copy_constructible>::value, ""); + static_assert(!std::is_trivially_relocatable>::value, ""); + + template + struct FakeDeleter { + using pointer = FakePointer; + void operator()(pointer p) const; + }; + + template using unique_ptr = std::unique_ptr>; +} + + +static_assert(std::is_trivially_relocatable< std::default_delete >::value, ""); +static_assert(std::is_trivially_relocatable< std::default_delete >::value, ""); +static_assert(!std::is_trivially_relocatable< fa2::FakeDeleter >::value, ""); +static_assert(std::is_trivially_relocatable< typename fa2::FakeDeleter::pointer >::value, ""); +static_assert(std::is_trivially_relocatable< fa4::FakeDeleter >::value, ""); +static_assert(!std::is_trivially_relocatable< typename fa4::FakeDeleter::pointer >::value, ""); + +template +void check_trivial_relocatability() +{ +#if __has_extension(trivially_relocatable) + static_assert(std::is_trivially_relocatable< T >::value == Expected, ""); +#else + // Making unique_ptr trivially relocatable requires using the attribute. + static_assert(std::is_trivially_relocatable< T >::value == false, ""); +#endif +} + +int main() +{ + check_trivial_relocatability< std::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + + check_trivial_relocatability< fa::unique_ptr, true >(); + check_trivial_relocatability< fa::unique_ptr, true >(); + check_trivial_relocatability< fa::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + check_trivial_relocatability< std::unique_ptr, true >(); + + check_trivial_relocatability< fa2::unique_ptr, false >(); + check_trivial_relocatability< fa2::unique_ptr, false >(); + check_trivial_relocatability< fa2::unique_ptr, false >(); + check_trivial_relocatability< fa2::unique_ptr, false >(); + check_trivial_relocatability< fa2::unique_ptr, false >(); + check_trivial_relocatability< fa2::unique_ptr, false >(); + + check_trivial_relocatability< fa3::unique_ptr, true >(); + check_trivial_relocatability< fa3::unique_ptr, true >(); + check_trivial_relocatability< fa3::unique_ptr, true >(); + check_trivial_relocatability< fa3::unique_ptr, true >(); + check_trivial_relocatability< fa3::unique_ptr, true >(); + check_trivial_relocatability< fa3::unique_ptr, true >(); + + check_trivial_relocatability< fa4::unique_ptr, false >(); + check_trivial_relocatability< fa4::unique_ptr, false >(); + check_trivial_relocatability< fa4::unique_ptr, false >(); + check_trivial_relocatability< fa4::unique_ptr, false >(); + check_trivial_relocatability< fa4::unique_ptr, false >(); + check_trivial_relocatability< fa4::unique_ptr, false >(); +} Index: test/libcxx/utilities/optional/optional.object/trivial_copy_move_ABI.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/optional/optional.object/trivial_copy_move_ABI.pass.cpp @@ -0,0 +1,199 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// The test fails due to the missing is_trivially_constructible intrinsic. +// XFAIL: gcc-4.9 +// UNSUPPORTED: c++03, c++11, c++14 + +// + +// template class optional + +// Test that we properly provide the trivial copy operations by default. + +// FreeBSD provides the old ABI. This test checks the new ABI so we need +// to manually turn it on. +#if defined(__FreeBSD__) +#define _LIBCPP_ABI_UNSTABLE +#endif + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) +#error Non-trivial ctor ABI macro defined +#endif + +template +struct HasTrivialABI : std::integral_constant::value + && (!std::is_copy_constructible::value || std::is_trivially_copy_constructible::value) +#if TEST_STD_VER >= 11 + && (!std::is_move_constructible::value || std::is_trivially_move_constructible::value) +#endif +> {}; + +#if TEST_STD_VER >= 11 +struct NonTrivialDtor { + NonTrivialDtor(NonTrivialDtor const&) = default; + ~NonTrivialDtor(); +}; +NonTrivialDtor::~NonTrivialDtor() {} +static_assert(!HasTrivialABI::value, ""); + +struct NonTrivialCopy { + NonTrivialCopy(NonTrivialCopy const&); +}; +NonTrivialCopy::NonTrivialCopy(NonTrivialCopy const&) {} +static_assert(!HasTrivialABI::value, ""); + +struct NonTrivialMove { + NonTrivialMove(NonTrivialMove const&) = default; + NonTrivialMove(NonTrivialMove&&); +}; +NonTrivialMove::NonTrivialMove(NonTrivialMove&&) {} +static_assert(!HasTrivialABI::value, ""); + +struct DeletedCopy { + DeletedCopy(DeletedCopy const&) = delete; + DeletedCopy(DeletedCopy&&) = default; +}; +static_assert(HasTrivialABI::value, ""); + +struct TrivialMove { + TrivialMove(TrivialMove &&) = default; +}; +static_assert(HasTrivialABI::value, ""); + +struct Trivial { + Trivial(Trivial const&) = default; +}; +static_assert(HasTrivialABI::value, ""); +#endif + +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialRelocEmpty { + TrivialRelocEmpty(const TrivialRelocEmpty&); + TrivialRelocEmpty(TrivialRelocEmpty&&); + ~TrivialRelocEmpty(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialReloc { + int i; + TrivialReloc(const TrivialReloc&); + TrivialReloc(TrivialReloc&&); + ~TrivialReloc(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +int main() +{ + { + typedef std::optional P; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#if TEST_STD_VER >= 11 + { + typedef std::optional P; + static_assert(std::is_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::optional; + static_assert(!std::is_trivially_destructible

::value, ""); + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::optional; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::optional; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::optional; + static_assert(!std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::optional; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::optional; + static_assert(!std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#if __has_extension(trivially_relocatable) + { + using P = std::optional; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::optional; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#endif +#endif +} Index: test/libcxx/utilities/tuple/tuple.tuple/trivial_copy_move_ABI.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/tuple/tuple.tuple/trivial_copy_move_ABI.pass.cpp @@ -0,0 +1,199 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// The test fails due to the missing is_trivially_constructible intrinsic. +// XFAIL: gcc-4.9 +// UNSUPPORTED: c++03 + +// + +// template struct tuple + +// Test that we properly provide the trivial copy operations by default. + +// FreeBSD provides the old ABI. This test checks the new ABI so we need +// to manually turn it on. +#if defined(__FreeBSD__) +#define _LIBCPP_ABI_UNSTABLE +#endif + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) +#error Non-trivial ctor ABI macro defined +#endif + +template +struct HasTrivialABI : std::integral_constant::value + && (!std::is_copy_constructible::value || std::is_trivially_copy_constructible::value) +#if TEST_STD_VER >= 11 + && (!std::is_move_constructible::value || std::is_trivially_move_constructible::value) +#endif +> {}; + +#if TEST_STD_VER >= 11 +struct NonTrivialDtor { + NonTrivialDtor(NonTrivialDtor const&) = default; + ~NonTrivialDtor(); +}; +NonTrivialDtor::~NonTrivialDtor() {} +static_assert(!HasTrivialABI::value, ""); + +struct NonTrivialCopy { + NonTrivialCopy(NonTrivialCopy const&); +}; +NonTrivialCopy::NonTrivialCopy(NonTrivialCopy const&) {} +static_assert(!HasTrivialABI::value, ""); + +struct NonTrivialMove { + NonTrivialMove(NonTrivialMove const&) = default; + NonTrivialMove(NonTrivialMove&&); +}; +NonTrivialMove::NonTrivialMove(NonTrivialMove&&) {} +static_assert(!HasTrivialABI::value, ""); + +struct DeletedCopy { + DeletedCopy(DeletedCopy const&) = delete; + DeletedCopy(DeletedCopy&&) = default; +}; +static_assert(HasTrivialABI::value, ""); + +struct TrivialMove { + TrivialMove(TrivialMove &&) = default; +}; +static_assert(HasTrivialABI::value, ""); + +struct Trivial { + Trivial(Trivial const&) = default; +}; +static_assert(HasTrivialABI::value, ""); +#endif + +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialRelocEmpty { + TrivialRelocEmpty(const TrivialRelocEmpty&); + TrivialRelocEmpty(TrivialRelocEmpty&&); + ~TrivialRelocEmpty(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialReloc { + int i; + TrivialReloc(const TrivialReloc&); + TrivialReloc(TrivialReloc&&); + ~TrivialReloc(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +int main() +{ + { + typedef std::tuple P; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#if TEST_STD_VER >= 11 + { + typedef std::tuple P; + static_assert(std::is_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::tuple; + static_assert(!std::is_trivially_destructible

::value, ""); + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::tuple; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::tuple; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::tuple; + static_assert(!std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::tuple; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::tuple; + static_assert(!std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#if __has_extension(trivially_relocatable) + { + using P = std::tuple; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::tuple; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#endif +#endif +} Index: test/libcxx/utilities/utility/pairs/pairs.pair/trivial_copy_move_ABI.pass.cpp =================================================================== --- test/libcxx/utilities/utility/pairs/pairs.pair/trivial_copy_move_ABI.pass.cpp +++ test/libcxx/utilities/utility/pairs/pairs.pair/trivial_copy_move_ABI.pass.cpp @@ -26,6 +26,10 @@ #include "test_macros.h" +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) #error Non-trivial ctor ABI macro defined #endif @@ -77,6 +81,24 @@ static_assert(HasTrivialABI::value, ""); #endif +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialRelocEmpty { + TrivialRelocEmpty(const TrivialRelocEmpty&); + TrivialRelocEmpty(TrivialRelocEmpty&&); + ~TrivialRelocEmpty(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialReloc { + int i; + TrivialReloc(const TrivialReloc&); + TrivialReloc(TrivialReloc&&); + ~TrivialReloc(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif void test_trivial() { @@ -84,12 +106,14 @@ typedef std::pair P; static_assert(std::is_copy_constructible

::value, ""); static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); } #if TEST_STD_VER >= 11 { typedef std::pair P; static_assert(std::is_move_constructible

::value, ""); static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); } { using P = std::pair; @@ -99,6 +123,7 @@ static_assert(std::is_move_constructible

::value, ""); static_assert(!std::is_trivially_move_constructible

::value, ""); static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); } { using P = std::pair; @@ -107,6 +132,7 @@ static_assert(std::is_move_constructible

::value, ""); static_assert(!std::is_trivially_move_constructible

::value, ""); static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); } { using P = std::pair; @@ -115,6 +141,7 @@ static_assert(std::is_move_constructible

::value, ""); static_assert(!std::is_trivially_move_constructible

::value, ""); static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); } { using P = std::pair; @@ -123,6 +150,7 @@ static_assert(std::is_move_constructible

::value, ""); static_assert(std::is_trivially_move_constructible

::value, ""); static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); } { using P = std::pair; @@ -131,6 +159,7 @@ static_assert(std::is_move_constructible

::value, ""); static_assert(std::is_trivially_move_constructible

::value, ""); static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); } { using P = std::pair; @@ -139,7 +168,28 @@ static_assert(std::is_move_constructible

::value, ""); static_assert(std::is_trivially_move_constructible

::value, ""); static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#if __has_extension(trivially_relocatable) + { + using P = std::pair; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); } + { + using P = std::pair; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#endif #endif } Index: test/libcxx/utilities/variant/variant.variant/trivial_copy_move_ABI.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/variant/variant.variant/trivial_copy_move_ABI.pass.cpp @@ -0,0 +1,199 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// The test fails due to the missing is_trivially_constructible intrinsic. +// XFAIL: gcc-4.9 +// UNSUPPORTED: c++03, c++11, c++14 + +// + +// template class variant + +// Test that we properly provide the trivial copy operations by default. + +// FreeBSD provides the old ABI. This test checks the new ABI so we need +// to manually turn it on. +#if defined(__FreeBSD__) +#define _LIBCPP_ABI_UNSTABLE +#endif + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Define the P1144 name for convenience. +#define is_trivially_relocatable __libcpp_is_trivially_relocatable + + +#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) +#error Non-trivial ctor ABI macro defined +#endif + +template +struct HasTrivialABI : std::integral_constant::value + && (!std::is_copy_constructible::value || std::is_trivially_copy_constructible::value) +#if TEST_STD_VER >= 11 + && (!std::is_move_constructible::value || std::is_trivially_move_constructible::value) +#endif +> {}; + +#if TEST_STD_VER >= 11 +struct NonTrivialDtor { + NonTrivialDtor(NonTrivialDtor const&) = default; + ~NonTrivialDtor(); +}; +NonTrivialDtor::~NonTrivialDtor() {} +static_assert(!HasTrivialABI::value, ""); + +struct NonTrivialCopy { + NonTrivialCopy(NonTrivialCopy const&); +}; +NonTrivialCopy::NonTrivialCopy(NonTrivialCopy const&) {} +static_assert(!HasTrivialABI::value, ""); + +struct NonTrivialMove { + NonTrivialMove(NonTrivialMove const&) = default; + NonTrivialMove(NonTrivialMove&&); +}; +NonTrivialMove::NonTrivialMove(NonTrivialMove&&) {} +static_assert(!HasTrivialABI::value, ""); + +struct DeletedCopy { + DeletedCopy(DeletedCopy const&) = delete; + DeletedCopy(DeletedCopy&&) = default; +}; +static_assert(HasTrivialABI::value, ""); + +struct TrivialMove { + TrivialMove(TrivialMove &&) = default; +}; +static_assert(HasTrivialABI::value, ""); + +struct Trivial { + Trivial(Trivial const&) = default; +}; +static_assert(HasTrivialABI::value, ""); +#endif + +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialRelocEmpty { + TrivialRelocEmpty(const TrivialRelocEmpty&); + TrivialRelocEmpty(TrivialRelocEmpty&&); + ~TrivialRelocEmpty(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +struct _LIBCPP_TRIVIALLY_RELOCATABLE TrivialReloc { + int i; + TrivialReloc(const TrivialReloc&); + TrivialReloc(TrivialReloc&&); + ~TrivialReloc(); +}; +#if __has_extension(trivially_relocatable) +static_assert(std::is_trivially_relocatable::value, ""); +#endif + +int main() +{ + { + typedef std::variant P; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#if TEST_STD_VER >= 11 + { + typedef std::variant P; + static_assert(std::is_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::variant; + static_assert(!std::is_trivially_destructible

::value, ""); + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::variant; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::variant; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(!std::is_trivially_relocatable

::value, ""); + } + { + using P = std::variant; + static_assert(!std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::variant; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::variant; + static_assert(!std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(std::is_trivially_move_constructible

::value, ""); + static_assert(HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#if __has_extension(trivially_relocatable) + { + using P = std::variant; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } + { + using P = std::variant; + static_assert(std::is_copy_constructible

::value, ""); + static_assert(!std::is_trivially_copy_constructible

::value, ""); + static_assert(std::is_move_constructible

::value, ""); + static_assert(!std::is_trivially_move_constructible

::value, ""); + static_assert(!HasTrivialABI

::value, ""); + static_assert(std::is_trivially_relocatable

::value, ""); + } +#endif +#endif +}