summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2022-04-18 16:19:20 +0200
committerMarc Glisse <marc.glisse@inria.fr>2022-04-18 16:19:20 +0200
commit15c99df7bca51d33d6d7d7fe26ad7ce66ebb7ac4 (patch)
tree880d54f86627e4b1b45a66848e31c5af0da037e8
parentd5140b0ec81a64f53f5c3f223fdf215b324675eb (diff)
downloadgmp-15c99df7bca51d33d6d7d7fe26ad7ce66ebb7ac4.tar.gz
Do not use mp directly in mpz_class
This is the difference between f and g in the following, where gcc generates "return 1;" for f and not for g. The aliasing is caused by the functions get_num and get_den in mpq_class. struct mpz_struct { int i; }; typedef mpz_struct mpz_t[1]; struct mpq_struct { mpz_struct num, den; }; typedef mpq_struct mpq_t[1]; struct mpz_class { mpz_t mp; }; struct mpq_class { mpq_t mp; }; int f(mpq_class*q, mpz_class*z){ q->mp->num.i = 1; z->mp->i = 2; return q->mp->num.i; } int g(mpq_class*q, mpz_class*z){ q->mp->num.i = 1; int*p=&z->mp->i; *p = 2; return q->mp->num.i; }
-rw-r--r--ChangeLog4
-rw-r--r--gmpxx.h17
2 files changed, 14 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index a38896524..3dc9640c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2022-04-18 Marc Glisse <marc.glisse@inria.fr>
+
+ * gmpxx.h (mpz_class): Do not use mp directly.
+
2022-03-18 Marco Bodrato <bodrato@mail.dm.unipi.it>
* tests/mpz/t-lucm.c: Remove an unused var.
diff --git a/gmpxx.h b/gmpxx.h
index 0d5c6e374..b7ed06a4d 100644
--- a/gmpxx.h
+++ b/gmpxx.h
@@ -1580,7 +1580,7 @@ private:
void assign_ui(unsigned long l)
{
if (__GMPXX_CONSTANT_TRUE(l == 0))
- mp->_mp_size = 0;
+ __get_mp()->_mp_size = 0;
else
mpz_set_ui(mp, l);
}
@@ -1634,7 +1634,7 @@ public:
__gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
#if __GMPXX_USE_CXX11
__gmp_expr(__gmp_expr &&z) noexcept
- { *mp = *z.mp; mpz_init(z.mp); }
+ { *__get_mp() = *z.__get_mp(); mpz_init(z.mp); }
#endif
template <class T>
__gmp_expr(const __gmp_expr<mpz_t, T> &expr)
@@ -1666,7 +1666,8 @@ public:
~__gmp_expr() { mpz_clear(mp); }
- void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); }
+ void swap(__gmp_expr& z) __GMPXX_NOEXCEPT
+ { std::swap(*__get_mp(), *z.__get_mp()); }
// assignment operators
__gmp_expr & operator=(const __gmp_expr &z)
@@ -1728,7 +1729,7 @@ public:
// bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); }
#if __GMPXX_USE_CXX11
- explicit operator bool() const { return mp->_mp_size != 0; }
+ explicit operator bool() const { return __get_mp()->_mp_size != 0; }
#endif
// member operators
@@ -1896,9 +1897,11 @@ public:
// conversion functions
- // casting a reference to an mpz_t to mpz_class & is a dirty hack,
- // but works because the internal representation of mpz_class is
- // exactly an mpz_t
+ // casting a reference to an mpz_t to mpz_class & is a dirty hack.
+ // It kind of works because the internal representation of mpz_class is
+ // exactly an mpz_t, but compilers are allowed to assume that mpq_class
+ // and mpz_class do not alias... In mpz_class, we avoid using mp directly,
+ // to reduce the risks of such problematic optimizations.
const mpz_class & get_num() const
{ return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); }
mpz_class & get_num()