Warnings in GMP.H, and potentially more serious problem

delta trinity deltatrinity at hotmail.com
Sat May 15 15:24:32 CEST 2004


Hello

Well, this is to follow the issue with warnings in GMP.H 4.1.3
Note that looking at the code, I found a possible serious problem which 
could result in wrong value returned to mpz_get_ui.

Setup
-----
x86 platform (P4)
Borland C++ Builder 6.0
GMP 4.1.3 shared library compiled with MinGW (gcc version 3.2.3).
./configure --disable-static --enable-shared -host=i386-pc-mingw32  (if I 
compile for other x86 platforms, the problem is the same, the generated 
gmp.h is the same).

Problem
-----
When compiling C++ applications (standard 'c' applications doesn't seem to 
cause the warnings) using GMP.H 4.1.3 in Borland C++ Builder 6, I get

[C++ Warning] gmp.h(1595): W8008 Condition is always true
[C++ Warning] gmp.h(1596): W8041 Negating unsigned value

Those are only warnings, and does not cause the compilation to fail.

In the header, this is at (marked by ====HERE====):

unsigned long
mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW
{
mp_ptr __gmp_p = __gmp_z->_mp_d;
mp_size_t __gmp_n = __gmp_z->_mp_size;
mp_limb_t __gmp_l = __gmp_p[0];
if (__GMP_ULONG_MAX <= GMP_NUMB_MASK) ====HERE====
   return __gmp_l & (-(mp_limb_t) (__gmp_n != 0)); ====HERE====
#if GMP_NAIL_BITS != 0 /* redundant #if, shuts up compiler warnings */
else /* happens for nails, but not if LONG_LONG_LIMB */
   { /* assume two limbs are enough to fill an ulong */
     __gmp_n = __GMP_ABS (__gmp_n);
     if (__gmp_n <= 1)
return __gmp_l & (-(mp_limb_t) (__gmp_n != 0));
     else
return __gmp_l + (__gmp_p[1] << GMP_NUMB_BITS);
   }
#endif
}

The first warning is because two constants are used in the equation (in 
fact, 2 defines).  Equivalent to (in this case)
if (32 <= 32)

The second warning is due to negating an unsigned value.

Possible flaw
-----
Looking at the code, at the second warning, could (__gmp_n != 0) give 
problems if a compiler decide to evaluate the expression to anything other 
than 1.  Is 'true' defined as any non-zero value?  I'm not sure.  But if so, 
this could evaluate to 0xFFFFFFFF.  The expression would then evaluate to:

return __gmp_l & (-(mp_limb_t) (0xFFFFFFFF)); /* (-1) */
return __gmp_l & (1);

So, it is questionable if the current gmp.h work for every compilers in its 
current state.  Some tests should be made regarding that.

With my compiler though, this doesn't cause problems.  The (__gmp_n != 0) 
actually compile to

cmp dword ptr [ebp-0x2c],0x00
setnz al
and eax,0x01

Which set eax to either 0 or 1.

note
-----
The warnings themself are seen when I compile C++ console application.  I 
tried compiling a C console application and they didn't show.  Probably the 
compiler use two different core for C and C++.


Regards

Eric

_________________________________________________________________
Express yourself with the new version of MSN Messenger! Download today - 
it's FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/



More information about the gmp-bugs mailing list