Thread: 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
From
Zeugswetter Andreas SB
Date:
> >> 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
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
From
Peter Eisentraut
Date:
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/
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
From
Ian Lance Taylor
Date:
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
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
From
Ian Lance Taylor
Date:
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
From
ncm@zembu.com (Nathan Myers)
Date:
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