Boost logo

Boost-Commit :

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();


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