diff options
author | Marc Glisse <marc.glisse@inria.fr> | 2022-04-18 16:19:20 +0200 |
---|---|---|
committer | Marc Glisse <marc.glisse@inria.fr> | 2022-04-18 16:19:20 +0200 |
commit | 15c99df7bca51d33d6d7d7fe26ad7ce66ebb7ac4 (patch) | |
tree | 880d54f86627e4b1b45a66848e31c5af0da037e8 | |
parent | d5140b0ec81a64f53f5c3f223fdf215b324675eb (diff) | |
download | gmp-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-- | ChangeLog | 4 | ||||
-rw-r--r-- | gmpxx.h | 17 |
2 files changed, 14 insertions, 7 deletions
@@ -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. @@ -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() |