[libcxx] r194536 - This fixes a very subtle ABI problem concerning the copy constructor of

Howard Hinnant hhinnant at apple.com
Tue Nov 12 16:39:22 PST 2013


Author: hhinnant
Date: Tue Nov 12 18:39:22 2013
New Revision: 194536

URL: http://llvm.org/viewvc/llvm-project?rev=194536&view=rev
Log:
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<int, int> 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<int, int> is ABI
incompatible with the C++11 libc++ copy constructor for pair<int, int>.
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<int, int>
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.

Modified:
    libcxx/trunk/include/__config
    libcxx/trunk/include/memory
    libcxx/trunk/include/type_traits
    libcxx/trunk/include/utility
    libcxx/trunk/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp

Modified: libcxx/trunk/include/__config
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=194536&r1=194535&r2=194536&view=diff
==============================================================================
--- libcxx/trunk/include/__config (original)
+++ libcxx/trunk/include/__config Tue Nov 12 18:39:22 2013
@@ -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")))

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=194536&r1=194535&r2=194536&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Tue Nov 12 18:39:22 2013
@@ -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
 

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=194536&r1=194535&r2=194536&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Tue Nov 12 18:39:22 2013
@@ -2437,7 +2437,7 @@ template <class _Tp> struct _LIBCPP_TYPE
 // is_trivially_copy_constructible
 
 template <class _Tp> 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<const _Tp>::type>
     {};
 
 // is_trivially_move_constructible

Modified: libcxx/trunk/include/utility
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?rev=194536&r1=194535&r2=194536&view=diff
==============================================================================
--- libcxx/trunk/include/utility (original)
+++ libcxx/trunk/include/utility Tue Nov 12 18:39:22 2013
@@ -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<first_type>::value &&

Modified: libcxx/trunk/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp?rev=194536&r1=194535&r2=194536&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp (original)
+++ libcxx/trunk/test/utilities/utility/pairs/pairs.pair/copy_ctor.pass.cpp Tue Nov 12 18:39:22 2013
@@ -26,6 +26,8 @@ int main()
         assert(p2.second == 4);
     }
 
+    static_assert((std::is_trivially_copy_constructible<std::pair<int, int> >::value), "");
+
 #if _LIBCPP_STD_VER > 11
     {
         typedef std::pair<int, short> P1;





More information about the cfe-commits mailing list