Fix assignment operations to be safe after a move.

Added test cases to catch bug case.
Refs #8667.

[SVN r84687]
This commit is contained in:
John Maddock
2013-06-08 14:07:21 +00:00
parent 3ee4005731
commit cdd63adfcd
3 changed files with 95 additions and 9 deletions

View File

@@ -1015,8 +1015,9 @@ struct gmp_int
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 @@ struct gmp_rational
}
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

View File

@@ -702,21 +702,29 @@ struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationTy
}
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 @@ struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationTy
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 @@ struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0
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 @@ struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0
}
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;
}

View File

@@ -84,6 +84,36 @@ void test_std_lib()
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 @@ int main()
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 @@ int main()
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 @@ int main()
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 @@ int main()
d = std::move(e);
e = d;
BOOST_TEST(e == d);
test_move_and_assign<mpq_rational>();
}
#endif
#ifdef TEST_TOMMATH
@@ -245,6 +285,8 @@ int main()
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 @@ int main()
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();