$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r84687 - in trunk: boost/multiprecision libs/multiprecision/test
From: john_at_[hidden]
Date: 2013-06-08 10:07:21
Author: johnmaddock
Date: 2013-06-08 10:07:21 EDT (Sat, 08 Jun 2013)
New Revision: 84687
URL: http://svn.boost.org/trac/boost/changeset/84687
Log:
Fix assignment operations to be safe after a move.
Added test cases to catch bug case.
Refs #8667.
Text files modified: 
   trunk/boost/multiprecision/gmp.hpp           |    10 ++++---                                 
   trunk/boost/multiprecision/mpfr.hpp          |    49 +++++++++++++++++++++++++++++++++++---- 
   trunk/libs/multiprecision/test/test_move.cpp |    45 ++++++++++++++++++++++++++++++++++++    
   3 files changed, 95 insertions(+), 9 deletions(-)
Modified: trunk/boost/multiprecision/gmp.hpp
==============================================================================
--- trunk/boost/multiprecision/gmp.hpp	Sat Jun  8 06:58:41 2013	(r84686)
+++ trunk/boost/multiprecision/gmp.hpp	2013-06-08 10:07:21 EDT (Sat, 08 Jun 2013)	(r84687)
@@ -1015,8 +1015,9 @@
    explicit gmp_int(const gmp_rational& o);
    gmp_int& operator = (const gmp_int& o)
    {
-      if(o.m_data[0]._mp_d)
-         mpz_set(m_data, o.m_data);
+      if(m_data[0]._mp_d == 0)
+         mpz_init(this->m_data);
+      mpz_set(m_data, o.m_data);
       return *this;
    }
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
@@ -1728,8 +1729,9 @@
    }
    gmp_rational& operator = (const gmp_rational& o)
    {
-      if(o.m_data[0]._mp_num._mp_d)
-         mpq_set(m_data, o.m_data);
+      if(m_data[0]._mp_den._mp_d == 0)
+         mpq_init(m_data);
+      mpq_set(m_data, o.m_data);
       return *this;
    }
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
Modified: trunk/boost/multiprecision/mpfr.hpp
==============================================================================
--- trunk/boost/multiprecision/mpfr.hpp	Sat Jun  8 06:58:41 2013	(r84686)
+++ trunk/boost/multiprecision/mpfr.hpp	2013-06-08 10:07:21 EDT (Sat, 08 Jun 2013)	(r84687)
@@ -702,21 +702,29 @@
    }
    mpfr_float_backend& operator=(const mpfr_t val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set(this->m_data, val, GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const mpf_t val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set_f(this->m_data, val, GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const mpz_t val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set_z(this->m_data, val, GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const mpq_t val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set_q(this->m_data, val, GMP_RNDN);
       return *this;
    }
@@ -724,22 +732,30 @@
    template <unsigned D, mpfr_allocation_type AT>
    mpfr_float_backend& operator=(const mpfr_float_backend<D, AT>& val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
    template <unsigned D>
    mpfr_float_backend& operator=(const gmp_float<D>& val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const gmp_int& val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const gmp_rational& val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
@@ -803,7 +819,10 @@
 
    mpfr_float_backend& operator=(const mpfr_float_backend& o)
    {
-      mpfr_set_prec(this->m_data, mpfr_get_prec(o.data()));
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, mpfr_get_prec(o.data()));
+      else
+         mpfr_set_prec(this->m_data, mpfr_get_prec(o.data()));
       mpfr_set(this->m_data, o.data(), GMP_RNDN);
       return *this;
    }
@@ -822,47 +841,67 @@
    }
    mpfr_float_backend& operator=(const mpfr_t val)
    {
-      mpfr_set_prec(this->m_data, mpfr_get_prec(val));
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, mpfr_get_prec(val));
+      else
+         mpfr_set_prec(this->m_data, mpfr_get_prec(val));
       mpfr_set(this->m_data, val, GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const mpf_t val)
    {
-      mpfr_set_prec(this->m_data, mpf_get_prec(val));
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, mpf_get_prec(val));
+      else
+         mpfr_set_prec(this->m_data, mpf_get_prec(val));
       mpfr_set_f(this->m_data, val, GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const mpz_t val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
       mpfr_set_z(this->m_data, val, GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const mpq_t val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
       mpfr_set_q(this->m_data, val, GMP_RNDN);
       return *this;
    }
    template <unsigned D>
    mpfr_float_backend& operator=(const mpfr_float_backend<D>& val)
    {
-      mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, mpfr_get_prec(val.data()));
+      else
+         mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
       mpfr_set(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
    template <unsigned D>
    mpfr_float_backend& operator=(const gmp_float<D>& val)
    {
-      mpfr_set_prec(this->m_data, mpf_get_prec(val.data()));
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, mpf_get_prec(val.data()));
+      else
+         mpfr_set_prec(this->m_data, mpf_get_prec(val.data()));
       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const gmp_int& val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
    mpfr_float_backend& operator=(const gmp_rational& val)
    {
+      if(this->m_data[0]._mpfr_d == 0)
+         mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
       return *this;
    }
Modified: trunk/libs/multiprecision/test/test_move.cpp
==============================================================================
--- trunk/libs/multiprecision/test/test_move.cpp	Sat Jun  8 06:58:41 2013	(r84686)
+++ trunk/libs/multiprecision/test/test_move.cpp	2013-06-08 10:07:21 EDT (Sat, 08 Jun 2013)	(r84687)
@@ -84,6 +84,36 @@
    BOOST_TEST(b == 2);
 }
 
+template <class T, class A>
+void test_move_and_assign(T x, A val)
+{
+   // move away from x, then assign val to x.
+   T z(x);
+   T y(std::move(x));
+   x.assign(val);
+   BOOST_CHECK_EQUAL(x, T(val));
+   BOOST_CHECK_EQUAL(z, y);
+}
+
+template <class T>
+void test_move_and_assign()
+{
+   T x(23);
+   test_move_and_assign(x, static_cast<short>(2));
+   test_move_and_assign(x, static_cast<int>(2));
+   test_move_and_assign(x, static_cast<long>(2));
+   test_move_and_assign(x, static_cast<long long>(2));
+   test_move_and_assign(x, static_cast<unsigned short>(2));
+   test_move_and_assign(x, static_cast<unsigned int>(2));
+   test_move_and_assign(x, static_cast<unsigned long>(2));
+   test_move_and_assign(x, static_cast<unsigned long long>(2));
+   test_move_and_assign(x, static_cast<float>(2));
+   test_move_and_assign(x, static_cast<double>(2));
+   test_move_and_assign(x, static_cast<long double>(2));
+   test_move_and_assign(x, x);
+   test_move_and_assign(x, "23");
+}
+
 
 int main()
 {
@@ -131,6 +161,9 @@
       d = std::move(e);
       e = d;
       BOOST_TEST(e == d);
+
+      test_move_and_assign<mpfr_float>();
+      test_move_and_assign<mpfr_float_50>();
    }
 #endif
 #ifdef TEST_GMP
@@ -170,6 +203,9 @@
       d = std::move(e);
       e = d;
       BOOST_TEST(e == d);
+
+      test_move_and_assign<mpf_float>();
+      test_move_and_assign<mpf_float_50>();
    }
    {
       test_std_lib<mpz_int>();
@@ -194,6 +230,8 @@
       d = std::move(e);
       e = d;
       BOOST_TEST(e == d);
+
+      test_move_and_assign<mpz_int>();
    }
    {
       test_std_lib<mpq_rational>();
@@ -217,6 +255,8 @@
       d = std::move(e);
       e = d;
       BOOST_TEST(e == d);
+
+      test_move_and_assign<mpq_rational>();
    }
 #endif
 #ifdef TEST_TOMMATH
@@ -245,6 +285,8 @@
       d = std::move(e);
       e = d;
       BOOST_TEST(e == d);
+
+      test_move_and_assign<tom_int>();
    }
 #endif
 #ifdef TEST_CPP_INT
@@ -273,6 +315,9 @@
       d = std::move(e);
       e = d;
       BOOST_TEST(e == d);
+
+      test_move_and_assign<cpp_int>();
+      test_move_and_assign<int512_t>();
    }
 #endif
    return boost::report_errors();