Created attachment 24647 [details] Trivial testcase The C standard (as well as POSIX) requires that intmax_t "designates a signed integer type capable of representing any value of any signed integer type" and likewise for uintmax_t. However, on amd64, intmax_t is long, which is not big enough to hold a 128-bit quantity. A trivial preprocessed testcase is attached, not that you need one. I see this behavior on 4.6 and 4.7: lakeview ok % gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.6.1-1' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-multiarch --with-multiarch-defaults=x86_64-linux-gnu --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib/x86_64-linux-gnu --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib/x86_64-linux-gnu --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.1 (Debian 4.6.1-1) lakeview ok % /usr/lib/gcc-snapshot/bin/gcc -v Using built-in specs. COLLECT_GCC=/usr/lib/gcc-snapshot/bin/gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc-snapshot/libexec/gcc/x86_64-linux-gnu/4.7.0/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 20110624-1' --with-bugurl=file:///usr/share/doc/gcc-snapshot/README.Bugs --enable-languages=c,ada,c++,java,fortran,objc,obj-c++,go --prefix=/usr/lib/gcc-snapshot --enable-shared --enable-multiarch --with-multiarch-defaults=x86_64-linux-gnu --enable-linker-build-id --with-system-zlib --disable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.7-snap/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.7-snap --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.7-snap --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --with-arch-32=i586 --with-tune=generic --disable-werror --enable-checking=yes --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.7.0 20110624 (experimental) [trunk revision 175388] (Debian 20110624-1) This is Debian bug #629137.
Created attachment 24648 [details] Unpreprocessed testcase The preprocessed testcase hardcodes long int and so doesn't test the presence of the bug correctly. In this case, only an unpreprocessed testcase will demonstrate the problem.
sizeof(intmax_t) is fixed by various LP64 ABIs and cannot be changed I believe the stock answer is that __int128 is not a C99 extended integer type, so isn't one of the types that intmax_t can represent the value of
(In reply to comment #2) > sizeof(intmax_t) is fixed by various LP64 ABIs and cannot be changed That does sound potentially problematic. I don't see how that solves the standard conformance issue, though. If intmax_t cannot be changed, then I suppose the only appropriate behavior is not to provide any integer types larger than intmax_t with -std=c99. > I believe the stock answer is that __int128 is not a C99 extended integer type, > so isn't one of the types that intmax_t can represent the value of There are five *standard signed integer types*.... There may also be *implementation-defined extended signed integer types*. The standard and extended signed integer types are collectively called *signed integer types*. Since the standard specifies intmax_t in terms of a "signed integer type", it therefore includes any implementation-defined extended signed integer types, including __int128_t.
(In reply to comment #3) > Since the standard specifies intmax_t in terms of a "signed integer type", it > therefore includes any implementation-defined extended signed integer types, Yes. > including __int128_t. You're assuming __int128 is an implementation-defined extended integer type. If GCC chooses to call __int128 some other type that doesn't fall under the C99 definition of "implementation defined integer type" then intmax_t doesn't have to be able to represent its values. Of course this is cheating by playing wordgames, but sizeof(intmax_t) can't change and people want to be able to use __int128
(In reply to comment #3) > suppose the only appropriate behavior is not to provide any integer types > larger > than intmax_t with -std=c99. Use -pedantic-errors if you want to reject programs using __int128
By (directly) using an identifier starting with two underscores you are leaving the territory of the C standard.
(In reply to comment #5) > (In reply to comment #3) > > suppose the only appropriate behavior is not to provide any integer types > > larger > > than intmax_t with -std=c99. > > Use -pedantic-errors if you want to reject programs using __int128 I don't. I want to compile using C99 mode (I use scoped for) on a variety of different compilers, taking advantage of 128-bit integers whenever possible (for performance reasons). The portable way to do this with the preprocessor is to see if UINTMAX_MAX is set to the proper value. In fact, GCC as it is currently provides no way to determine whether 128-bit integers are in fact supported at all on the current hardware, which leads to compilation failures on, say, 32-bit SPARC. The conformance issue, while important, is secondary. I do expect GCC to comply with the standard in standards mode, and I do expect any deviation from the standards behavior in standards mode to be considered a bug worth fixing. But it isn't the primary goal here. I also see no mention of intmax_t in the SysV ABI for x86-64. Can you be more specific about what specifically would cause ABI breakage if intmax_t were to become 128-bit on x86_64-pc-linux-gnu? According to <http://gcc.gnu.org/ml/gcc/2011-03/msg00095.html>, as long as libc behaves appropriately, it shouldn't be a problem.
(In reply to comment #6) > By (directly) using an identifier starting with two underscores you are leaving > the territory of the C standard. I don't agree. The footnote to the text that I quoted states: "Implementation-defined keywords shall have the form of an identifier reserved for any use as described in 7.1.3." So the standard specifies that such implementation-defined signed integer types (which it has just instructed implementors must be implemented using double underscores) are part of the signed integer types. I don't see another legitimate interpretation here. As I said previously, I want to use 128-bit integers where possible. If intmax_t were correctly and appropriately defined as to use 128-bit integers, then the behavior would not only be standards-conforming with regard to C99, but it would also be practically useful and I wouldn't have to use double-underscored types at all.
(In reply to comment #7) > The conformance issue, while important, is secondary. I do expect GCC to > comply with the standard in standards mode, and I do expect any deviation from > the standards behavior in standards mode to be considered a bug worth fixing. What do you mean by standards mode? It's clearly documented in the manual that -std=c99 does NOT mean non-standard extensions are rejected, for that you need to use -pedantic-errors, and that rejects __int128.
(In reply to comment #9) > What do you mean by standards mode? > It's clearly documented in the manual that -std=c99 does NOT mean non-standard > extensions are rejected, for that you need to use -pedantic-errors, and that > rejects __int128. My complaint is not even about __int128. My complaint is about intmax_t. With -std=c99, intmax_t is not capable of representing all the values of all implementation-defined signed integer types. The C standard requires that it is so capable. If the implementation provides a type (however named (or unnamed) or specified) that is an implementation-defined signed integer type, intmax_t must be capable of expressing all the values that such a type may hold. I don't care how the type is specified or named. It exists. It happens to be named in the standard-specified manner; that is convenient, but ultimately irrelevant. It exists, therefore, intmax_t's behavior is specified in terms of that type. Period. Your only out here is if you claim that the type in question (however named, unnamed, or specified) is not an implementation-defined signed integer type, and in that case, you'll need to specify that in the documentation and specify what it *is*. You should probably document that it is a) not implementation-defined, b) not signed (or unsigned, as appropriate), c) not integral, or d) not a type.
On Thu, 30 Jun 2011, sandals at crustytoothpaste dot net wrote: > Your only out here is if you claim that the type in question (however named, > unnamed, or specified) is not an implementation-defined signed integer type, > and in that case, you'll need to specify that in the documentation and specify > what it *is*. You should probably document that it is a) not > implementation-defined, b) not signed (or unsigned, as appropriate), c) not > integral, or d) not a type. The implementation-defined extended integer types are documented alongside the other implementation-defined behavior in implement-c.texi: "GCC does not support any extended integer types.". Note that "char" is a standard integer type that is not a signed or unsigned integer type although it behaves like one or the other; you could think of it as a "sui generis integer type". And the right way to think of __int128 is as a "sui generis extended type", that is not an integer type although it shares some properties with them. Maybe the __fpreg type supported on IA64 is more obviously a "sui generis extended type" given the restrictions on how it can be used - but the same category contains both those types (and ARM __fp16, for another example).
Invalid then.