From 5f43b228612f45a68705d691b482aeca7cf3f68c Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 18 Feb 2023 19:58:36 +0300 Subject: [PATCH] Reuse is_swappable implementation in is_nothrow_swappable for gcc < 4.7. This avoids applying noexcept operator to a potentially invalid swap expression, which should resolve ICE with gcc 4.6. --- doc/history.qbk | 1 + .../detail/is_swappable_cxx_11.hpp | 21 +++++++++++++++++-- .../type_traits/is_nothrow_swappable.hpp | 3 +-- test/is_nothrow_swappable_test.cpp | 1 - 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/doc/history.qbk b/doc/history.qbk index d2b277f..ca412ba 100644 --- a/doc/history.qbk +++ b/doc/history.qbk @@ -10,6 +10,7 @@ [h4 Boost-1.82.0] * Added __is_swappable trait. +* Added a workaround for gcc 4.6 that allows __is_nothrow_swappable to work. [h4 Boost-1.70.0] diff --git a/include/boost/type_traits/detail/is_swappable_cxx_11.hpp b/include/boost/type_traits/detail/is_swappable_cxx_11.hpp index 293210a..390253c 100644 --- a/include/boost/type_traits/detail/is_swappable_cxx_11.hpp +++ b/include/boost/type_traits/detail/is_swappable_cxx_11.hpp @@ -34,7 +34,22 @@ template boost::false_type is_swappable_impl( ... ); template struct is_swappable_helper { typedef decltype( boost_type_traits_swappable_detail::is_swappable_impl(0) ) type; }; -#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !BOOST_WORKAROUND(BOOST_GCC, < 40700) +#if !defined(BOOST_NO_CXX11_NOEXCEPT) + +#if BOOST_WORKAROUND(BOOST_GCC, < 40700) + +// gcc 4.6 ICEs when noexcept operator is used on an invalid expression +template::type::value> +struct is_nothrow_swappable_with_helper { typedef boost::false_type type; }; +template +struct is_nothrow_swappable_with_helper { typedef boost::integral_constant(), boost::declval()))> type; }; + +template::type::value> +struct is_nothrow_swappable_helper { typedef boost::false_type type; }; +template +struct is_nothrow_swappable_helper { typedef boost::integral_constant(), boost::declval()))> type; }; + +#else // BOOST_WORKAROUND(BOOST_GCC, < 40700) template(), boost::declval()))> boost::integral_constant is_nothrow_swappable_with_impl( int ); template boost::false_type is_nothrow_swappable_with_impl( ... ); @@ -46,7 +61,9 @@ template boost::false_type is_nothrow_swappable_impl( ... ); template struct is_nothrow_swappable_helper { typedef decltype( boost_type_traits_swappable_detail::is_nothrow_swappable_impl(0) ) type; }; -#endif // !defined(BOOST_NO_CXX11_NOEXCEPT) && !BOOST_WORKAROUND(BOOST_GCC, < 40700) +#endif // BOOST_WORKAROUND(BOOST_GCC, < 40700) + +#endif // !defined(BOOST_NO_CXX11_NOEXCEPT) } // namespace boost_type_traits_swappable_detail diff --git a/include/boost/type_traits/is_nothrow_swappable.hpp b/include/boost/type_traits/is_nothrow_swappable.hpp index fc319f7..1ab3dcd 100644 --- a/include/boost/type_traits/is_nothrow_swappable.hpp +++ b/include/boost/type_traits/is_nothrow_swappable.hpp @@ -8,10 +8,9 @@ // http://www.boost.org/LICENSE_1_0.txt #include -#include #if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) \ - || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) || BOOST_WORKAROUND(BOOST_GCC, < 40700) + || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) #include #include diff --git a/test/is_nothrow_swappable_test.cpp b/test/is_nothrow_swappable_test.cpp index fafa526..ad49f95 100644 --- a/test/is_nothrow_swappable_test.cpp +++ b/test/is_nothrow_swappable_test.cpp @@ -18,7 +18,6 @@ // These conditions should be similar to those in is_nothrow_swappable.hpp #if defined(BOOST_NO_SFINAE_EXPR) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ - || BOOST_WORKAROUND(BOOST_GCC, < 40700) \ || (defined(__GLIBCXX__) && __GLIBCXX__ <= 20120301) // built-in clang++ -std=c++11 on Travis, w/ libstdc++ 4.6 #define BOOST_TYPE_TRAITS_IS_NOTHROW_SWAPPABLE_EMULATED #endif