Bug 52764 - Including <cstdint> after <stdint.h> fails to define limit macros
Summary: Including <cstdint> after <stdint.h> fails to define limit macros
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.1
: P3 normal
Target Milestone: 4.8.0
Assignee: Paolo Carlini
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-29 09:04 UTC by Bruce Merry
Modified: 2012-10-06 23:10 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-03-29 00:00:00


Attachments
Preprocessed source from g++ -v -save-temps -std=c++0x gcc-stdint.cpp (754 bytes, application/octet-stream)
2012-03-29 09:04 UTC, Bruce Merry
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bruce Merry 2012-03-29 09:04:56 UTC
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)
Comment 1 Jonathan Wakely 2012-03-29 09:58:58 UTC
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!
Comment 2 Paolo Carlini 2012-03-29 10:02:25 UTC
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)
Comment 3 Jonathan Wakely 2012-03-29 10:25:22 UTC
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.
Comment 4 jsm-csl@polyomino.org.uk 2012-04-07 16:06:46 UTC
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).
Comment 5 Paolo Carlini 2012-09-27 12:04:00 UTC
Jakub, any chance you could help for this?
Comment 6 Paolo Carlini 2012-09-27 12:38:48 UTC
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.
Comment 7 Paolo Carlini 2012-09-27 15:10:09 UTC
On it.
Comment 8 paolo@gcc.gnu.org 2012-10-06 23:06:09 UTC
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
Comment 9 Paolo Carlini 2012-10-06 23:10:58 UTC
Fixed.