Обсуждение: AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

Поиск
Список
Период
Сортировка

AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
Zeugswetter Andreas SB
Дата:
> >> I'm aware that some compilers will produce warnings about these
> >> constants, but there should not be any that fail completely, since
> >> (a) we won't be compiling this code unless we've proven that the
> >> compiler supports a 64-bit-int datatype, and 
> 
> > Unfortunately configure does not check the use of 64 bit integer 
> > constants. A little check on AIX shows, that it indeed DOES 
> NOT work !!!!!
> 
> Grumble...
> 
> >> (b) the C standard
> >> forbids a compiler from requiring width suffixes (cf. 
> 6.4.4.1 in C99).
> 
> > Maybe that standard is somewhat too recent to rely upon 100%.
> 
> ANSI C says the same thing, although of course it only discusses int and
> long.  But the spec has always been clear that the implied type of an
> integer constant is whatever it takes to hold it; you do not need an
> explicit "L" suffix to make a valid constant.  AIX's compiler 
> is broken.

Reading your above note I do not see, how you map this statement
to a long long int (64 bits) on a platform where int is 32 bits. On this platform
we are definitely not talking about an integer constant.

> > Do you want me to supply an AIX specific patch with #if defined (_AIX) ?
> 
> I'll do something about it.  Would you check to see whether a > macro like
> #define SIXTYFOUR(x)  x##LL works?

Yes, that works. Unfortunately I will only be able to test on Monday.

Could you use something like the following in configure, to test it ?

#define SIXTYFOUR(x)  x
if (sizeof(SIXTYFOUR(0x0)) == 8)               printf ("0x0 is 64 bits\n");
else return(-1);

#define SIXTYFOUR(x)  x##LL
if (sizeof(SIXTYFOUR(0x0)) == 8)               printf ("0x0LL is 64 bits\n");
else return (-1);

Andreas


Re: AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
Tom Lane
Дата:
Zeugswetter Andreas SB  <ZeugswetterA@wien.spardat.at> writes:
>> ANSI C says the same thing, although of course it only discusses int and
>> long.  But the spec has always been clear that the implied type of an
>> integer constant is whatever it takes to hold it; you do not need an
>> explicit "L" suffix to make a valid constant.  AIX's compiler 
>> is broken.

> Reading your above note I do not see, how you map this statement to a
> long long int (64 bits) on a platform where int is 32 bits. On this
> platform we are definitely not talking about an integer constant.

Sorry, perhaps I should have said "integral" constant, or something like
that.  But if you read the spec you will find it calls all these things
integer constants.  The relevant part of C99 says
      [#5] The type of an integer constant is  the  first  of  the      corresponding list in which its value can be
represented.
                   ||                       |                   ||                       |  Octal or Hexadecimal
Suffix      ||   Decimal Constant    |        Constant
-------------++-----------------------+------------------------     none         ||int                    | int
         ||long int               | unsigned int                   ||long long int          | long int
||                       | unsigned long int                   ||                       | long long int
 ||                       | unsigned long long int
 

and I'm quite sure that ANSI C says exactly the same thing except for
not listing the long long types.  This behavior is not some weird new
invention of C99 --- it has been part of the language definition since
K&R's first edition (see K&R ref section 2.4.1, if you have a copy).
Apparently the AIX compiler writers' memories do not go back to times
when int was commonly narrower than long and so this part of the spec
was really significant.  Otherwise they'd not have had any difficulty
in extrapolating the correct handling of long long constants.

>>>> Do you want me to supply an AIX specific patch with #if defined (_AIX) ?
>> 
>> I'll do something about it.  Would you check to see whether a macro like
>> #define SIXTYFOUR(x)  x##LL works?

> Yes, that works.

Okay.  I've committed a configure check that tests to see whether a
macro defined as above compiles, and if so it will be used (if we are
using "long long" for int64).  Hopefully the check will prevent breakage
on machines where LL is not appropriate.
        regards, tom lane


Re: AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
Peter Eisentraut
Дата:
Tom Lane writes:

> Okay.  I've committed a configure check that tests to see whether a
> macro defined as above compiles, and if so it will be used (if we are
> using "long long" for int64).  Hopefully the check will prevent breakage
> on machines where LL is not appropriate.

I don't see what this configure check buys us, since it does not check for
anything that's ever been reported not working.  Do you think there are
platforms that have 'long long int' but no 'LL' suffix?  That seems more
than unlikely.

-- 
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/



Re: AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
Tom Lane
Дата:
Peter Eisentraut <peter_e@gmx.net> writes:
> I don't see what this configure check buys us, since it does not check for
> anything that's ever been reported not working.  Do you think there are
> platforms that have 'long long int' but no 'LL' suffix?  That seems more
> than unlikely.

Well, I don't know.  Up till yesterday I would have said that there were
no compilers that violated the C specification (not to mention twenty
years of traditional practice) in the handling of integral constants
of varying widths.

If you look closely, the configure test is not simply checking whether
LL is accepted, it is checking whether we can construct an acceptable
constant by macroized token-pasting.  That's a slightly larger
assumption, but it's the one the code must actually make to cover
AIX's problem.  As I remarked before, I think that ## is more typically
used to paste identifiers and strings together; I don't really want to
bet that pasting 0xNNN ## LL will work on every compiler.

Mainly it's a schedule-driven thing.  I don't want to take any risk that
a last-minute patch to work around AIX's broken compiler will break any
other platforms.  If we had found this problem before beta cycle
started, I would be more willing to say "let's try it and find out
whether it works everywhere".

Yeah, it's paranoia, but considering that the whole thing is an exercise
in covering up a "shouldn't happen" compiler bug, I think paranoia is
not so unreasonable.
        regards, tom lane


Re: AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
Ian Lance Taylor
Дата:
Tom Lane <tgl@sss.pgh.pa.us> writes:

> If you look closely, the configure test is not simply checking whether
> LL is accepted, it is checking whether we can construct an acceptable
> constant by macroized token-pasting.  That's a slightly larger
> assumption, but it's the one the code must actually make to cover
> AIX's problem.  As I remarked before, I think that ## is more typically
> used to paste identifiers and strings together; I don't really want to
> bet that pasting 0xNNN ## LL will work on every compiler.
> 
> Mainly it's a schedule-driven thing.  I don't want to take any risk that
> a last-minute patch to work around AIX's broken compiler will break any
> other platforms.  If we had found this problem before beta cycle
> started, I would be more willing to say "let's try it and find out
> whether it works everywhere".

A safe way to construct a long long constant is to do it using an
expression:   ((((uint64) 0xdeadbeef) << 32) | (uint64) 0xfeedface)
It's awkward, obviously, but it works with any compiler.

Ian


Re: AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
Tom Lane
Дата:
Ian Lance Taylor <ian@airs.com> writes:
> A safe way to construct a long long constant is to do it using an
> expression:
>     ((((uint64) 0xdeadbeef) << 32) | (uint64) 0xfeedface)
> It's awkward, obviously, but it works with any compiler.

An interesting example.  That will work as intended if and only if the
compiler regards 0xfeedface as unsigned --- if the constant is initially
treated as a signed int, then extension to 64 bits will propagate the
wrong bit value into the high-order bits.

Indeed, according to the ANSI C spec, 0xfeedface *should* be regarded as
unsigned in a machine whose ints are 32 bits.  However, this conclusion
comes from the exact same paragraph that AIX got wrong to begin with.
I'm not sure that doing it this way actually affords any extra protection
against compilers that can't be trusted to handle integral constants
per-spec...
        regards, tom lane


Re: AW: AW: Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
Ian Lance Taylor
Дата:
Tom Lane <tgl@sss.pgh.pa.us> writes:

> Ian Lance Taylor <ian@airs.com> writes:
> > A safe way to construct a long long constant is to do it using an
> > expression:
> >     ((((uint64) 0xdeadbeef) << 32) | (uint64) 0xfeedface)
> > It's awkward, obviously, but it works with any compiler.
> 
> An interesting example.  That will work as intended if and only if the
> compiler regards 0xfeedface as unsigned --- if the constant is initially
> treated as a signed int, then extension to 64 bits will propagate the
> wrong bit value into the high-order bits.
> 
> Indeed, according to the ANSI C spec, 0xfeedface *should* be regarded as
> unsigned in a machine whose ints are 32 bits.  However, this conclusion
> comes from the exact same paragraph that AIX got wrong to begin with.
> I'm not sure that doing it this way actually affords any extra protection
> against compilers that can't be trusted to handle integral constants
> per-spec...

True, for additional safety, do this:   ((((uint64) (unsigned long) 0xdeadbeef) << 32) | (uint64) (unsigned long)
0xfeedface)

Of course, this won't work if long is 64 bits and int is 32 bits and
the compiler erroneously makes a hexidecimal constant signed int
rather than unsigned int, signed long (incorrect but possible), or
unsigned long.

I seem to recall that even K&R compilers support an L suffix to
indicate a long value.  If that is the case, then I think this is
always safe for any compiler:   ((((uint64) (unsigned long) 0xdeadbeefL) << 32) | (uint64) (unsigned long)
0xfeedfaceL)

(In reality that should certainly be safe, because there are no K&R
compilers which support a 64 bit integer type.)

Ian


Re: RELEASE STOPPER? nonportable int64 constant s in pg_crc.c

От
ncm@zembu.com (Nathan Myers)
Дата:
On Sat, Mar 24, 2001 at 02:05:05PM -0800, Ian Lance Taylor wrote:
> Tom Lane <tgl@sss.pgh.pa.us> writes:
> > Ian Lance Taylor <ian@airs.com> writes:
> > > A safe way to construct a long long constant is to do it using an
> > > expression:
> > >     ((((uint64) 0xdeadbeef) << 32) | (uint64) 0xfeedface)
> > > It's awkward, obviously, but it works with any compiler.
> > 
> > An interesting example.  That will work as intended if and only if the
> > compiler regards 0xfeedface as unsigned ...
> 
> True, for additional safety, do this:
>     ((((uint64) (unsigned long) 0xdeadbeef) << 32) |
>       (uint64) (unsigned long) 0xfeedface)

For the paranoid,
  ((((uint64) 0xdead) << 48) | (((uint64) 0xbeef) << 32) | \   (((uint64) 0xfeed) << 16) | ((uint64) 0xface))

Or, better
  #define FRAG64(bits,shift) (((uint64)(bits)) << (shift))  #define LITERAL64(a,b,c,d) \    FRAG64(a,48) | FRAG64(b,32)
|FRAG64(c,16) | FRAG64(d,0)  LITERAL64(0xdead,0xbeef,0xfeed,0xface)
 

That might be overkill for just a single literal...

Nathan Myers
ncm