From 3f81e9eebaf662f230d3dff7329098df6ee7e36d Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Wed, 13 Nov 2013 00:39:22 +0000 Subject: [PATCH] This fixes a very subtle ABI problem concerning the copy constructor of pair, and a couple of pair-like implementation detail types. The C++98/03 and 11 standards all specify that the copy constructor of pair is trivial. However as libc++ tracked the draft C++11 standard over the years, this copy constructor became non-trivial, and then just recently was corrected back to trivial for C++11. Unfortunately (for libc++1) the Itanium ABI specifies different calling conventions for trivial and non-trivial copy constructors. Therefore currently the C++03 libc++ copy constructor for pair is ABI incompatible with the C++11 libc++ copy constructor for pair. This is Bad(tm). This patch corrects the situation by making this copy constructor trivial in C++03 mode as well. Just in case it is needed for an incomplete C++11 compiler, libc++ retains the ability to support pair with rvalue references, but without defaulted special members. However the pair needs non-trivial special members to implement this special case, (as it did when clang was in this place a couple of years ago). During this work a bug was also found and fixed in is_trivially_constructible. And there is a minor drive-by fix in <__config> regarding __type_visibility__. A test is updated to ensure that the copy constructor of pair is trivial in both C++03 and C++11. This test will necessarily fail for a compiler that implements rvalue references but not defaulted special members. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@194536 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 2 +- include/memory | 39 +++++-------------- include/type_traits | 2 +- include/utility | 2 +- .../pairs/pairs.pair/copy_ctor.pass.cpp | 2 + 5 files changed, 15 insertions(+), 32 deletions(-) diff --git a/include/__config b/include/__config index a45b02de..43fbf87d 100644 --- a/include/__config +++ b/include/__config @@ -174,7 +174,7 @@ #endif #ifndef _LIBCPP_TYPE_VIS -# if __has_attribute(type_visibility) +# if __has_attribute(__type_visibility__) # define _LIBCPP_TYPE_VIS __attribute__ ((__type_visibility__("default"))) # else # define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default"))) diff --git a/include/memory b/include/memory index bf44837f..b382f70b 100644 --- a/include/memory +++ b/include/memory @@ -1954,7 +1954,7 @@ public: _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2) : __first_(_VSTD::forward<_T1_param>(__t1)), __second_(_VSTD::forward<_T2_param>(__t2)) {} -#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(const __libcpp_compressed_pair_imp& __p) @@ -1973,8 +1973,6 @@ public: return *this; } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(__libcpp_compressed_pair_imp&& __p) _NOEXCEPT_(is_nothrow_move_constructible<_T1>::value && @@ -1992,9 +1990,7 @@ public: return *this; } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) #ifndef _LIBCPP_HAS_NO_VARIADICS @@ -2051,7 +2047,7 @@ public: _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2) : _T1(_VSTD::forward<_T1_param>(__t1)), __second_(_VSTD::forward<_T2_param>(__t2)) {} -#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(const __libcpp_compressed_pair_imp& __p) @@ -2069,8 +2065,6 @@ public: return *this; } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(__libcpp_compressed_pair_imp&& __p) _NOEXCEPT_(is_nothrow_move_constructible<_T1>::value && @@ -2087,9 +2081,7 @@ public: return *this; } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) #ifndef _LIBCPP_HAS_NO_VARIADICS @@ -2147,7 +2139,7 @@ public: is_nothrow_move_constructible<_T2>::value) : _T2(_VSTD::forward<_T2_param>(__t2)), __first_(_VSTD::forward<_T1_param>(__t1)) {} -#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(const __libcpp_compressed_pair_imp& __p) @@ -2165,8 +2157,6 @@ public: return *this; } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(__libcpp_compressed_pair_imp&& __p) _NOEXCEPT_(is_nothrow_move_constructible<_T1>::value && @@ -2183,9 +2173,7 @@ public: return *this; } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) #ifndef _LIBCPP_HAS_NO_VARIADICS @@ -2241,7 +2229,7 @@ public: _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2) : _T1(_VSTD::forward<_T1_param>(__t1)), _T2(_VSTD::forward<_T2_param>(__t2)) {} -#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(const __libcpp_compressed_pair_imp& __p) @@ -2259,8 +2247,6 @@ public: return *this; } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - _LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(__libcpp_compressed_pair_imp&& __p) _NOEXCEPT_(is_nothrow_move_constructible<_T1>::value && @@ -2277,9 +2263,7 @@ public: return *this; } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) #ifndef _LIBCPP_HAS_NO_VARIADICS @@ -2332,7 +2316,7 @@ public: _LIBCPP_INLINE_VISIBILITY __compressed_pair(_T1_param __t1, _T2_param __t2) : base(_VSTD::forward<_T1_param>(__t1), _VSTD::forward<_T2_param>(__t2)) {} -#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) _LIBCPP_INLINE_VISIBILITY __compressed_pair(const __compressed_pair& __p) @@ -2349,7 +2333,6 @@ public: return *this; } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __compressed_pair(__compressed_pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<_T1>::value && @@ -2365,9 +2348,7 @@ public: return *this; } -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) #ifndef _LIBCPP_HAS_NO_VARIADICS diff --git a/include/type_traits b/include/type_traits index b6430fbb..c4afe5e1 100644 --- a/include/type_traits +++ b/include/type_traits @@ -2437,7 +2437,7 @@ template struct _LIBCPP_TYPE_VIS_ONLY is_trivially_default_construct // is_trivially_copy_constructible template struct _LIBCPP_TYPE_VIS_ONLY is_trivially_copy_constructible - : public is_trivially_constructible<_Tp, const typename add_lvalue_reference<_Tp>::type> + : public is_trivially_constructible<_Tp, typename add_lvalue_reference::type> {}; // is_trivially_move_constructible diff --git a/include/utility b/include/utility index 5fc2cf20..303dd4e1 100644 --- a/include/utility +++ b/include/utility @@ -275,7 +275,7 @@ struct _LIBCPP_TYPE_VIS_ONLY pair #ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS _LIBCPP_INLINE_VISIBILITY pair(const pair& __p) = default; -#else +#elif !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) // default the copy ctor in C++03 _LIBCPP_INLINE_VISIBILITY pair(const pair& __p) _NOEXCEPT_(is_nothrow_copy_constructible::value && diff --git a/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp b/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp index b163f246..4b54f717 100644 --- a/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp +++ b/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp @@ -26,6 +26,8 @@ int main() assert(p2.second == 4); } + static_assert((std::is_trivially_copy_constructible >::value), ""); + #if _LIBCPP_STD_VER > 11 { typedef std::pair P1;