Most of the ctype.h
items are declared as inline definitions, so they get expanded at compile time. When you compile without -std=c++11
, it expands to:
extern inline int
toupper(int _c)
{
return (__toupper(_c));
}
When you compile with -std=c++11
, it expands to:
extern inline __attribute__((__gnu_inline__)) int
toupper(int _c)
{
return (__toupper(_c));
}
For some reason, g++ is then choosing to ignore the perfectly good definition that is presented there.
Based on the commentary on this invalid bug, it's gcc choosing to not optimize the code and looking for the definition in one of the linked libraries.
A workaround seems to be to compile with at least -O1
optimization, which avoids the issue, but it's a real pain in the ass.
Now when we look at the differences in the #defines between non-C++11 and C++11, we see that we have an extra #define:
$ touch x.cc
$ g++-4.9 -dM -E x.cc | grep STD
#define __STDC_HOSTED__ 1
#define __STDC__ 1
$ g++-4.9 -std=c++11 -dM -E x.cc | grep STD
#define __STDC_HOSTED__ 1
#define __GNUC_STDC_INLINE__ 1
#define __STDC__ 1
and because of a piece of code in the 10.9 SDK (usr/include/sys/cdefs.h
), all those __DARWIN_CTYPE_TOP_inline
in cytpe.h
get turned into __header_inline
which get turned into extern __inline __attribute__((__gnu_inline__))
thanks to this little bit of additional code:
#elif defined(__GNUC__) && defined(__GNUC_STDC_INLINE__)
# define __header_inline extern __inline __attribute__((__gnu_inline__))
It looks like apple's header is trying to do the right thing, but they've not covered all their bases. There is another issue, which mentions a similar bug.