Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85157 - in branches/release: boost/variant libs/variant/test
From: antoshkka_at_[hidden]
Date: 2013-07-25 04:42:44


Author: apolukhin
Date: 2013-07-25 04:42:44 EDT (Thu, 25 Jul 2013)
New Revision: 85157
URL: http://svn.boost.org/trac/boost/changeset/85157

Log:
Merge from trunk:
* make the library work on exception-disabled environments (fixes #8717)
* fix compilation of Boost.Variants move assignment for situations when one of the variant template classes has nothrow copy constructor and throwing move constructor (fixes #8772)
* mark move constructor of variant with BOOST_NOEXCEPT_IF (refs #7911)

Text files modified:
   branches/release/boost/variant/get.hpp | 7 ++-
   branches/release/boost/variant/variant.hpp | 68 +++++++++++++++++++++++++++++----------
   branches/release/boost/variant/visitor_ptr.hpp | 3 +
   branches/release/libs/variant/test/Jamfile.v2 | 11 ++++++
   branches/release/libs/variant/test/recursive_variant_test.cpp | 35 ++++++++++++++++++-
   branches/release/libs/variant/test/rvalue_test.cpp | 42 ++++++++++++++++++++++-
   6 files changed, 138 insertions(+), 28 deletions(-)

Modified: branches/release/boost/variant/get.hpp
==============================================================================
--- branches/release/boost/variant/get.hpp Thu Jul 25 03:21:21 2013 (r85156)
+++ branches/release/boost/variant/get.hpp 2013-07-25 04:42:44 EDT (Thu, 25 Jul 2013) (r85157)
@@ -17,6 +17,7 @@
 
 #include "boost/config.hpp"
 #include "boost/detail/workaround.hpp"
+#include "boost/throw_exception.hpp"
 #include "boost/utility/addressof.hpp"
 #include "boost/variant/variant_fwd.hpp"
 
@@ -41,7 +42,7 @@
 {
 public: // std::exception implementation
 
- virtual const char * what() const throw()
+ virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
     {
         return "boost::bad_get: "
                "failed value get using boost::get";
@@ -177,7 +178,7 @@
     U_ptr result = get<U>(&operand);
 
     if (!result)
- throw bad_get();
+ boost::throw_exception(bad_get());
     return *result;
 }
 
@@ -193,7 +194,7 @@
     U_ptr result = get<const U>(&operand);
 
     if (!result)
- throw bad_get();
+ boost::throw_exception(bad_get());
     return *result;
 }
 

Modified: branches/release/boost/variant/variant.hpp
==============================================================================
--- branches/release/boost/variant/variant.hpp Thu Jul 25 03:21:21 2013 (r85156)
+++ branches/release/boost/variant/variant.hpp 2013-07-25 04:42:44 EDT (Thu, 25 Jul 2013) (r85157)
@@ -3,13 +3,15 @@
 // See http://www.boost.org for updates, documentation, and revision history.
 //-----------------------------------------------------------------------------
 //
-// Copyright (c) 2002-2003
-// Eric Friedman, Itay Maman
+// Copyright (c) 2002-2003 Eric Friedman, Itay Maman
+// Copyright (c) 2012-2013 Antony Polukhin
 //
 // Distributed under the Boost Software License, Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
+// Thanks to Adam Romanek for providing patches for exception-disabled env.
+
 #ifndef BOOST_VARIANT_VARIANT_HPP
 #define BOOST_VARIANT_VARIANT_HPP
 
@@ -37,6 +39,7 @@
 #include "boost/variant/detail/generic_result_type.hpp"
 #include "boost/variant/detail/move.hpp"
 
+#include "boost/detail/no_exceptions_support.hpp"
 #include "boost/detail/reference_content.hpp"
 #include "boost/aligned_storage.hpp"
 #include "boost/blank.hpp"
@@ -226,6 +229,25 @@
 
 #endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
 
+#ifndef BOOST_NO_CXX11_NOEXCEPT
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction is_variant_move_noexcept
+//
+// Returns true_type if all the types are nothrow move constructible.
+//
+template <class Types>
+struct is_variant_move_noexcept {
+ typedef typename boost::mpl::find_if<
+ Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
+ >::type iterator_t;
+
+ typedef typename boost::mpl::end<Types>::type end_t;
+ typedef typename boost::is_same<
+ iterator_t, end_t
+ >::type type;
+};
+#endif // BOOST_NO_CXX11_NOEXCEPT
+
 ///////////////////////////////////////////////////////////////////////////////
 // (detail) metafunction make_storage
 //
@@ -770,12 +792,12 @@
         // ...destroy lhs content...
         lhs_content.~LhsT(); // nothrow
 
- try
+ BOOST_TRY
         {
             // ...and attempt to copy rhs content into lhs storage:
             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
         }
- catch (...)
+ BOOST_CATCH (...)
         {
             // In case of failure, restore backup content to lhs storage...
             new(lhs_.storage_.address())
@@ -784,8 +806,9 @@
                     ); // nothrow
 
             // ...and rethrow:
- throw;
+ BOOST_RETHROW;
         }
+ BOOST_CATCH_END
 
         // In case of success, indicate new content type:
         lhs_.indicate_which(rhs_which_); // nothrow
@@ -803,12 +826,12 @@
         // ...destroy lhs content...
         lhs_content.~LhsT(); // nothrow
 
- try
+ BOOST_TRY
         {
             // ...and attempt to copy rhs content into lhs storage:
             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
         }
- catch (...)
+ BOOST_CATCH (...)
         {
             // In case of failure, copy backup pointer to lhs storage...
             new(lhs_.storage_.address())
@@ -818,8 +841,9 @@
             lhs_.indicate_backup_which( lhs_.which() ); // nothrow
 
             // ...and rethrow:
- throw;
+ BOOST_RETHROW;
         }
+ BOOST_CATCH_END
 
         // In case of success, indicate new content type...
         lhs_.indicate_which(rhs_which_); // nothrow
@@ -1289,6 +1313,12 @@
           internal_types, never_uses_backup_flag
>::type storage_t;
 
+#ifndef BOOST_NO_CXX11_NOEXCEPT
+ typedef typename detail::variant::is_variant_move_noexcept<
+ internal_types
+ > variant_move_noexcept;
+#endif
+
 private: // helpers, for representation (below)
 
     // which_ on:
@@ -1375,7 +1405,7 @@
 
 public: // structors
 
- ~variant()
+ ~variant() BOOST_NOEXCEPT
     {
         destroy_content();
     }
@@ -1766,7 +1796,7 @@
     }
     
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- variant(variant&& operand)
+ variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept::type::value)
     {
         // Move the value of operand into *this...
         detail::variant::move_into visitor( storage_.address() );
@@ -1860,13 +1890,13 @@
             // Destroy lhs's content...
             lhs_.destroy_content(); // nothrow
 
- try
+ BOOST_TRY
             {
                 // ...and attempt to copy rhs's content into lhs's storage:
                 new(lhs_.storage_.address())
                     RhsT( rhs_content );
             }
- catch (...)
+ BOOST_CATCH (...)
             {
                 // In case of failure, default-construct fallback type in lhs's storage...
                 new (lhs_.storage_.address())
@@ -1878,8 +1908,9 @@
                     ); // nothrow
 
                 // ...and rethrow:
- throw;
+ BOOST_RETHROW;
             }
+ BOOST_CATCH_END
 
             // In the event of success, indicate new content type:
             lhs_.indicate_which(rhs_which_); // nothrow
@@ -1955,7 +1986,7 @@
 
     private: // helpers, for internal visitor interface (below)
 
- template <typename RhsT, typename B1, typename B2>
+ template <typename RhsT, typename B2>
         void assign_impl(
               RhsT& rhs_content
             , mpl::true_ // has_nothrow_copy
@@ -2004,13 +2035,13 @@
             // Destroy lhs's content...
             lhs_.destroy_content(); // nothrow
 
- try
+ BOOST_TRY
             {
                 // ...and attempt to copy rhs's content into lhs's storage:
                 new(lhs_.storage_.address())
                     RhsT( detail::variant::move(rhs_content) );
             }
- catch (...)
+ BOOST_CATCH (...)
             {
                 // In case of failure, default-construct fallback type in lhs's storage...
                 new (lhs_.storage_.address())
@@ -2022,8 +2053,9 @@
                     ); // nothrow
 
                 // ...and rethrow:
- throw;
+ BOOST_RETHROW;
             }
+ BOOST_CATCH_END
 
             // In the event of success, indicate new content type:
             lhs_.indicate_which(rhs_which_); // nothrow
@@ -2177,7 +2209,7 @@
     }
 
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- variant& operator=(variant&& rhs)
+ variant& operator=(variant&& rhs) // BOOST_NOEXCEPT_IF(variant_move_noexcept::type::value && all move assign operators are noexcept)
     {
         variant_assign( detail::variant::move(rhs) );
         return *this;

Modified: branches/release/boost/variant/visitor_ptr.hpp
==============================================================================
--- branches/release/boost/variant/visitor_ptr.hpp Thu Jul 25 03:21:21 2013 (r85156)
+++ branches/release/boost/variant/visitor_ptr.hpp 2013-07-25 04:42:44 EDT (Thu, 25 Jul 2013) (r85157)
@@ -18,6 +18,7 @@
 
 #include "boost/mpl/eval_if.hpp"
 #include "boost/mpl/identity.hpp"
+#include "boost/throw_exception.hpp"
 #include "boost/type_traits/add_reference.hpp"
 #include "boost/type_traits/is_reference.hpp"
 #include "boost/type_traits/is_void.hpp"
@@ -64,7 +65,7 @@
     template <typename U>
     result_type operator()(const U&) const
     {
- throw bad_visit();
+ boost::throw_exception(bad_visit());
     }
 
 #if !defined(BOOST_NO_VOID_RETURNS)

Modified: branches/release/libs/variant/test/Jamfile.v2
==============================================================================
--- branches/release/libs/variant/test/Jamfile.v2 Thu Jul 25 03:21:21 2013 (r85156)
+++ branches/release/libs/variant/test/Jamfile.v2 2013-07-25 04:42:44 EDT (Thu, 25 Jul 2013) (r85157)
@@ -1,6 +1,7 @@
 # Boost.Variant Library test Jamfile
 #
 # Copyright (C) 2003, Eric Friedman, Itay Maman.
+# Copyright (C) 2013, Antony Polukhin.
 #
 # This material is provided "as is", with absolutely no warranty expressed
 # or implied. Any use is at your own risk.
@@ -35,6 +36,16 @@
     [ run variant_multivisit_test.cpp ]
     [ run hash_variant_test.cpp ]
     [ run rvalue_test.cpp ]
+ [ run recursive_variant_test.cpp : : : <define>BOOST_NO_EXCEPTIONS
+ <toolset>gcc-4.3:<cxxflags>-fno-exceptions
+ <toolset>gcc-4.4:<cxxflags>-fno-exceptions
+ <toolset>gcc-4.5:<cxxflags>-fno-exceptions
+ <toolset>gcc-4.6:<cxxflags>-fno-exceptions
+ <toolset>gcc-4.7:<cxxflags>-fno-exceptions
+ <toolset>gcc-4.8:<cxxflags>-fno-exceptions
+ <toolset>clang:<cxxflags>-fno-exceptions
+ : variant_noexcept_test
+ ]
    ;
 
 

Modified: branches/release/libs/variant/test/recursive_variant_test.cpp
==============================================================================
--- branches/release/libs/variant/test/recursive_variant_test.cpp Thu Jul 25 03:21:21 2013 (r85156)
+++ branches/release/libs/variant/test/recursive_variant_test.cpp 2013-07-25 04:42:44 EDT (Thu, 25 Jul 2013) (r85157)
@@ -3,14 +3,43 @@
 // See http://www.boost.org for updates, documentation, and revision history.
 //-----------------------------------------------------------------------------
 //
-// Copyright (c) 2003
-// Eric Friedman, Itay Maman
+// Copyright (c) 2003 Eric Friedman, Itay Maman
+// Copyright (c) 2013 Antony Polukhin
 //
 // Distributed under the Boost Software License, Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#include "boost/test/minimal.hpp"
+
+// This file is used in two test cases:
+//
+// 1) recursive_variant_test.cpp that tests recursive usage of variant
+//
+// 2) variant_noexcept_test that tests Boost.Variant ability to compile
+// and work with disabled exceptions
+
+#ifdef BOOST_NO_EXCEPTIONS
+// `boost/test/minimal.hpp` cannot work with exceptions disabled,
+// so we need the following workarounds for that case:
+namespace boost {
+ int exit_success = 0;
+}
+
+int test_main(int , char* []);
+
+int main( int argc, char* argv[] )
+{
+ return test_main(argc, argv);
+}
+
+#include <stdlib.h>
+#define BOOST_CHECK(exp) if (!(exp)) exit(EXIT_FAILURE)
+
+#else // BOOST_NO_EXCEPTIONS
+# include "boost/test/minimal.hpp"
+#endif // BOOST_NO_EXCEPTIONS
+
+
 #include "boost/variant.hpp"
 #include "boost/mpl/vector.hpp"
 #include "boost/mpl/copy.hpp"

Modified: branches/release/libs/variant/test/rvalue_test.cpp
==============================================================================
--- branches/release/libs/variant/test/rvalue_test.cpp Thu Jul 25 03:21:21 2013 (r85156)
+++ branches/release/libs/variant/test/rvalue_test.cpp 2013-07-25 04:42:44 EDT (Thu, 25 Jul 2013) (r85157)
@@ -3,8 +3,7 @@
 // See http://www.boost.org for updates, documentation, and revision history.
 //-----------------------------------------------------------------------------
 //
-// Copyright (c) 2012
-// Antony Polukhin
+// Copyright (c) 2012-2013 Antony Polukhin
 //
 // Distributed under the Boost Software License, Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at
@@ -14,6 +13,7 @@
 
 #include "boost/test/minimal.hpp"
 #include "boost/variant.hpp"
+#include "boost/type_traits/is_nothrow_move_assignable.hpp"
 
 // This test requires rvalue references support
 
@@ -34,6 +34,11 @@
     BOOST_CHECK(true);
 }
 
+void run_moves_are_noexcept()
+{
+ BOOST_CHECK(true);
+}
+
 #else
 
 class move_copy_conting_class {
@@ -177,13 +182,44 @@
     BOOST_CHECK(vi.which() == 1);
 }
 
+void run_moves_are_noexcept() {
+#ifndef BOOST_NO_CXX11_NOEXCEPT
+ typedef boost::variant<int, short, double> variant_noexcept_t;
+ //BOOST_CHECK(boost::is_nothrow_move_assignable<variant_noexcept_t>::value);
+ BOOST_CHECK(boost::is_nothrow_move_constructible<variant_noexcept_t>::value);
+
+ typedef boost::variant<int, short, double, move_only_structure> variant_except_t;
+ //BOOST_CHECK(!boost::is_nothrow_move_assignable<variant_except_t>::value);
+ BOOST_CHECK(!boost::is_nothrow_move_constructible<variant_except_t>::value);
 #endif
+}
 
+#endif
+
+struct nothrow_copyable_throw_movable {
+ nothrow_copyable_throw_movable(){}
+ nothrow_copyable_throw_movable(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT {}
+ nothrow_copyable_throw_movable& operator=(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT { return *this; }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ nothrow_copyable_throw_movable(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) {}
+ nothrow_copyable_throw_movable& operator=(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) { return *this; }
+#endif
+};
+
+// This test is created to cover the following situation:
+// https://svn.boost.org/trac/boost/ticket/8772
+void run_tricky_compilation_test()
+{
+ boost::variant<int, nothrow_copyable_throw_movable> v;
+ v = nothrow_copyable_throw_movable();
+}
 
 int test_main(int , char* [])
 {
    run();
    run1();
    run_move_only();
+ run_moves_are_noexcept();
+ run_tricky_compilation_test();
    return 0;
-}
\ No newline at end of file
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk