Created attachment 27027 [details] Preprocessed source from g++ -v -save-temps -std=c++0x gcc-stdint.cpp Both <cstdint> and <tr1/cstdint> are implemented by defining __STDC_LIMIT_MACROS, including <stdint.h> and then undefining the macro again. However, if <stdint.h> has already been included (which may occur indirectly via some third-party C library header) then the limit macros do not get defined. I'm not 100% sure this is a bug because the C and C++ standards seem to contradict each other, but here's my reasoning: Both TR1 and C++11 are explicit that <cstdint> will define the limit macros, and C++11 also says "The macros defined by <cstdint> are provided unconditionally. In particular, the symbols __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS (mentioned in footnotes 219, 220, and 222 in the C standard) play no role in C++." TR1 also says that "[<stdint.h>] behaves as if it includes the header <cstdint>, and provides sufficient using declarations to declare in the global namespace all type names defined in the header <cstdint>." I've run into this on GCC 4.6.1, but from a quick look at http://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/include/c_global/cstdint@185951 it looks like this hasn't changed. Command line: g++ -c -std=c++0x gcc-stdint.cpp Output: gcc-stdint.cpp:4:26: error: ‘UINT32_MAX’ was not declared in this scope Output of g++ -v: Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.1-9ubuntu3' --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-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --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 (Ubuntu/Linaro 4.6.1-9ubuntu3)
Including <stdint.h> alone should declare the macros, <cstdint> isn't needed to demonstrate the bug. The problem is that <stdint.h> has this: /* The ISO C99 standard specifies that in C++ implementations these macros should only be defined if explicitly requested. */ #if !defined __cplusplus || defined __STDC_LIMIT_MACROS Which is indeed what C99 says, but C99 doesn't get to dictate rules to C++, and C11 doesn't include that useless footnote. GCC's own <stdint-gcc.h> should be fixed and glibc's <stdint.h> should be fixed, and GCC's <stdint.h> should probably include #ifdef __cplusplus # define __STDC_LIMIT_MACROS #endif if GCC detects that glibc requires it in order to function correctly. In short: not a libstdc++ bug!
Let's add Joseph in CC: he spent a lot of time on GCC's own stdint.h (which by now, afaik, is supported on most widespread targets) and I'm sure he can help with it (and with glibc too, in case)
Joseph, I was just about to file a glibc bug, let me know if you want that done. Glibc's stdint.h (and GCC's stdint-gcc.h) must unconditionally define the macros for C++11. It's debatable whether they should be defined for C++03. The __STDC_xxx_MACROS macros make sense there to avoid macro pollution, but arguably no strict C++03 program will include <stdint.h> anyway, so defining them unconditionally would also be reasonable, and consistent with C++11. GCC also needs to workaround the problem for "older" (i.e. all existing) glibc versions.
My previous suggestion stands of having the compiler predefine __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS, whether for C++11 or generally for C++, to make all existing stdint.h headers work as desired. You could predefine in the compiler, or you could predefine in stdint-wrap.h when it includes a system stdint.h and remove the conditionals in stdint-gcc.h. (In the header might be better because then you can use #ifndef to avoid any conflict with a user's definition of those macros.) If the libstdc++ people conclude that these definitions should be present for all C++ versions, not just C++11, then the conditionals in glibc's stdint.h can be removed at leisure (the predefines in GCC will make the conditionals useless but harmless).
Jakub, any chance you could help for this?
I guess we should simply implement in stdint-wrap.h and stdint-gcc.h what Joseph recommended. It seems safer to me to conditionalize the change on C++11.
On it.
Author: paolo Date: Sat Oct 6 23:06:04 2012 New Revision: 192174 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=192174 Log: 2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/52764 * ginclude/stdint-wrap.h: In C++11 if __STDC_HOSTED__ define __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS. * ginclude/stdint-gcc.h: In C++11 unconditionally define limit and constant macros. /testsuite 2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/52764 * g++.dg/cpp0x/stdint.C: New. /libstdc++-v3 2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/52764 * include/c_global/cstdint: Remove __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS related macros. Added: trunk/gcc/testsuite/g++.dg/cpp0x/stdint.C Modified: trunk/gcc/ChangeLog trunk/gcc/ginclude/stdint-gcc.h trunk/gcc/ginclude/stdint-wrap.h trunk/gcc/testsuite/ChangeLog trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/c_global/cstdint
Fixed.