I think I have essentially gotten to the bottom of this bug. And it is
pretty subtle indeed!

The issue is nominative versus structural typing. Consider the
following two structs:

struct mystruct1
{
   int d;
   double t;
}

struct mystruct2
{
   int d;
   double t;
}

Structurally, these are the same type as they contain the same fields
(in the same order -- this is important for C). But the names of the
structs are different. Thus nominatively they are different.

Now C/C++ are by and large nominatively typed. Structs with different
names are different for the purpose of type checking.

However, there are some exceptions. The template system in C++ is
structurally typed. You can instantiate templates with differently
named, but structurally identical types without issue, so long as the
implementations don't conflict.

And then there is typedef. This actually doesn't create a new type for
the purposes of type checking. It in fact only creates a type name
alias. The type is still considered to be the same for type checking
purposes.

Now if you look in stdint.h you find that on the system in question,
intmax_t is typedef'd to be a long. Thus intmax_t and long are the
*same* type on that system. Thus it is invalid to define the function
for intmax_t and for long with different implementations. So the
compiler is correct to reject this code.

Unfortunately, I don't know of a way of comparing two types with
preprocessor macros to see if they are the same. But we can compare
their sizes with sizeof. It turns out that sizeof is actually a macro,
not a function, and so can be compared at compile time. If
sizeof(intmax_t) == sizeof(long) then we shouldn't define the second
version of the function. The function will still accept an intmax_t
because that is the same type as a long.

I also found at least one reference which says that intmax_t is
*always* a typedef to an existing integral type. At least in C90 the
type must be an ordinary integer type, but from C99 onwards it can be
an extended integer type (so could conceivably be a uint128_t on a 64
bit machine). I'm not sure if we are still using C90 or whether we are
using gnu99. And I've no idea what the gnu "standard" says anyway. But
at least the fix I suggest should work for quite a few machines. We
might have to make further changes if we start running into problems
with extended types. I know the Apple GCC does all sorts of unusual
things when it comes to standards, so who knows.

I will check in this fix to the repo momentarily.

Bill.

On 11 October 2012 16:01, Bill Hart <[email protected]> wrote:
> On 7 October 2012 04:10, leif <[email protected]> wrote:
>
> <SNIP>
>
>> On Linux IA64 (SLES 10, Itanium) in contrast, I got the following failures:
>>
>> With the (fairly old) "native" GCC 4.1.2, building the testsuite fails:
>>
>> make[4]: Entering directory
>> `/home/leif/src/mpir-2.6.0-alpha1-build.iras-gcc-4.1.2/tests/cxx'
>> g++ -DHAVE_CONFIG_H -I. -I../../../mpir-2.6.0-alpha1/tests/cxx -I../..
>> -I../../../mpir-2.6.0-alpha1 -I../../../mpir-2.6.0-alpha1/tests    -O2 -c -o
>> t-assign.o ../../../mpir-2.6.0-alpha1/tests/cxx/t-assign.cc
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1587: error: ‘__gmp_expr<__mpz_struct
>> [1], __mpz_struct [1]>::__gmp_expr(intmax_t)’ cannot be overloaded
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1578: error: with
>> ‘__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(long int)’
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1588: error: ‘__gmp_expr<__mpz_struct
>> [1], __mpz_struct [1]>::__gmp_expr(uintmax_t)’ cannot be overloaded
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1579: error: with
>> ‘__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(long unsigned
>> int)’
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1656: error: ‘__gmp_expr<__mpz_struct
>> [1], __mpz_struct [1]>& __gmp_expr<__mpz_struct [1], __mpz_struct
>> [1]>::operator=(intmax_t)’ cannot be overloaded
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1647: error: with
>> ‘__gmp_expr<__mpz_struct [1], __mpz_struct [1]>& __gmp_expr<__mpz_struct
>> [1], __mpz_struct [1]>::operator=(long int)’
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1657: error: ‘__gmp_expr<__mpz_struct
>> [1], __mpz_struct [1]>& __gmp_expr<__mpz_struct [1], __mpz_struct
>> [1]>::operator=(uintmax_t)’ cannot be overloaded
>> ../../../mpir-2.6.0-alpha1/mpirxx.h:1648: error: with
>> ‘__gmp_expr<__mpz_struct [1], __mpz_struct [1]>& __gmp_expr<__mpz_struct
>> [1], __mpz_struct [1]>::operator=(long unsigned int)’
>
> <SNIP>
>
> OK, I took a look at this and basically an intmax_t and long int are
> the same thing on this machine (as are a uintmax_t and unsigned long
> int). Thus it is effectively trying to overload the __gmp_exp function
> twice with the same type but different implementations (one calls the
> si function, the other calls the sx function).
>
> This is a problem for which I don't personally know the solution at
> present. Any suggestions would be very helpful.
>
> Bill.

-- 
You received this message because you are subscribed to the Google Groups 
"mpir-devel" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/mpir-devel?hl=en.

Reply via email to