libcxx: Platform independent printing using format constants

Hi,

I'm currently porting a program from g++/libstdc++ to clang/libcxx and
was quite surprised that the platform independent printing using format
constants, e.g. PRId64, produces errors with libcxx.

A simple example which compiles fine w/o libcxx or g++

#include <cstdio>
#include <cinttypes>

int main() {
  int64_t n = 1;

  printf("%" PRId64, n);
}

w/ -stdlib=libcxx

+7:14: error: expected ')'
  printf("%" PRId64, n);
             ^
+7:9: note: to match this '('
  printf("%" PRId64, n);
        ^

Although the cinttypes header comments lists them

Macros:
    ...
    PRId64

So, what am I missing here? Is this not yet supported? How am I supposed
to handle this?

The library name is libc++, not libcxx. Try -stdlib=libc++ instead.

…but if it's really not working, that's a bug.

libc++ does this to pick up the macro definitions:

#include <inttypes.h>

However, glibc’s inttypes.h only provides them in C++ mode if _STDC_FORMAT_MACROS is defined, and libc++ doesn’t define it.

libc++ does this to pick up the macro definitions:

#include <inttypes.h>

However, glibc’s inttypes.h only provides them in C++ mode if _STDC_FORMAT_MACROS is defined, and libc++ doesn’t define it.

Sorry, needs more underscore: __STDC_FORMAT_MACROS.

libc++ does this to pick up the macro definitions:

#include <inttypes.h>

However, glibc's inttypes.h only provides them in C++ mode if _STDC_FORMAT_MACROS is defined, and libc++ doesn't define it.

Sorry, needs more underscore: __STDC_FORMAT_MACROS.

Right. This is C++11-conforming. 27.9.2 [c.files]/p3:

Table 135 describes header <cinttypes>. [ Note: The macros defined by <cinttypes> are provided unconditionally. In particular, the symbol __STDC_FORMAT_MACROS, mentioned in footnote 182 of the C standard, plays no role in C++. — end note ]

Summary: <inttypes.h> should not be protecting anything in C++ based on __STDC_FORMAT_MACROS, despite the non-normative footnote in C99's 7.8.1. When the C++ committee looked at this issue, they told the C committee "thanks but no thanks.". See:

http://cplusplus.github.com/LWG/lwg-defects.html#593
http://cplusplus.github.com/LWG/lwg-defects.html#984

Howard

Right, but glibc follows the C99 standard, not the C++11 standard (nor the C11 standard, which removes this unwanted “protection”), so cinttypes needs to define __STDC_FORMAT_MACROS itself if it’s going to include a C99 <inttypes.h> header such as glibc’s.

That solution won't make a C++11 conforming std::lib. C++11 also defines <inttypes.h> that *always* provides these macros.

glibc could also follow the C99 standard by not guarding with __STDC_FORMAT_MACROS. C99 has no normative statements that say it shall guard with __STDC_FORMAT_MACROS. The only statements it has to such an effect are non-normative.

Additionally the #define __STDC_FORMAT_MACROS in <cinttypes> won't necessarily be effective. Consider the case that <inttypes.h> has traditional include guards:

#include <inttypes.h>
...
#include <cinttypes>
...
// PRId64 defined here?

PRId64 may or may not be defined here depending upon whether <inttypes.h> put it under an include guard.

<inttypes.h> is the right place to fix this bug.

Howard

OK, but where do we work around the bug? Perhaps Clang should always define __STDC_FORMAT_MACROS in C++ mode.

Another possibility is to define it for needy platforms in libc++'s <__config>.

Howard