Bug 52538 - Extend C++11 UDLs to be compatible with inttypes.h macros
Summary: Extend C++11 UDLs to be compatible with inttypes.h macros
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P3 enhancement
Target Milestone: 4.8.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-09 09:00 UTC by Jeffrey Yasskin
Modified: 2012-11-12 14:57 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-05-01 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jeffrey Yasskin 2012-03-09 09:00:41 UTC
C++11 defines user-defined literals in a way that breaks compatibility with some code that uses the formatting macros from <inttypes.h>:

$ cat test.cc
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>

int main() {
  int64_t i64 = 123;
  printf("My int64: %"PRId64"\n", i64);
}
$ install_gcc46/bin/g++ -Wall test.cc -o test && ./test
My int64: 123
$ install_gcc46/bin/g++ -std=c++0x -Wall test.cc -o test && ./test
My int64: 123
$ install_gcc47/bin/g++-4.7pre -Wall test.cc -o test && ./test
My int64: 123
$ install_gcc47/bin/g++-4.7pre -Wall -Wc++11-compat test.cc -o test && ./test
My int64: 123
$ install_gcc47/bin/g++-4.7pre -std=c++0x -Wall test.cc -o test && ./test
test.cc: In function ‘int main()’:
test.cc:7:29: error: unable to find string literal operator ‘operator"" PRId64’


Clang is working around this by interpreting literal suffixes that don't start with underscores as separate tokens, which allows them to expand as macros: http://llvm.org/viewvc/llvm-project?view=rev&revision=152287

According to [lex.ext]p10 and [usrlit.suffix], these suffixes are ill-formed, no diagnostic required, so allowing them to expand as macros is a conforming extension.

It would also be possible to fix the code by inserting a space between the " and the macro name, but in Google's codebase, this cleanup would be 3-4x as large as the narrowing conversion cleanup, which you have already made optional.
Comment 1 Andrew Pinski 2012-03-09 09:07:10 UTC
If you want to use C++11, then you have to write C++11 code.  That is the way forward I think we have discussed this before.
Comment 2 Jonathan Wakely 2012-03-09 09:51:34 UTC
(In reply to comment #1)
> If you want to use C++11, then you have to write C++11 code.  That is the way
> forward I think we have discussed this before.

Yes, in PR 52485, and see also PR 51282 and PR 50917 - this is affecting a lot of large codebases. The committee are discussing whether this is a defect worth addressing in the standard, as the scope of the problems is larger than previously realised.

(In reply to comment #0)
> It would also be possible to fix the code by inserting a space between the "
> and the macro name, but in Google's codebase, this cleanup would be 3-4x as
> large as the narrowing conversion cleanup, which you have already made
> optional.

Ack. When UDL support was added to G++ I also found more problems due to "PRId64" than I had found when narrowing errors where added (in a much smaller codebase, obviously.)
Comment 3 Ollie Wild 2012-04-27 14:29:39 UTC
Author: aaw
Date: Fri Apr 27 14:29:32 2012
New Revision: 186909

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=186909
Log:
Add new option, -Wliteral-suffix.

This option, which is enabled by default, causes the preprocessor to warn
when a string or character literal is followed by a ud-suffix which does
not begin with an underscore.  According to [lex.ext]p10, this is
ill-formed.

Also modifies the preprocessor to treat such ill-formed suffixes as separate
preprocessing tokens.  This is consistent with the Clang front end (see
http://llvm.org/viewvc/llvm-project?view=rev&revision=152287), and enables
backwards compatibility with code that uses formatting macros from
<inttypes.h>, as in the following code block:

  int main() {
    int64_t i64 = 123;
    printf("My int64: %"PRId64"\n", i64);
  }

Google ref b/6377711.

2012-04-27   Ollie Wild  <aaw@google.com>

	PR c++/52538
	* gcc/c-family/c-common.c: Add CPP_W_LITERAL_SUFFIX mapping.
	* gcc/c-family/c-opts.c (c_common_handle_option): Handle
	OPT_Wliteral_suffix.
	* gcc/c-family/c.opt: Add Wliteral-suffix.
	* gcc/doc/invoke.texi (Wliteral-suffix): Document new option.
	* gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.c: New test.
	* libcpp/include/cpplib.h (struct cpp_options): Add new field,
	warn_literal_suffix.
	(CPP_W_LITERAL_SUFFIX): New enum.
	* libcpp/init.c (cpp_create_reader): Default initialization of
	warn_literal_suffix.
	* libcpp/lex.c (lex_raw_string): Treat user-defined literals which
	don't begin with '_' as separate tokens and produce a warning.
	(lex_string): Ditto.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/c-family/ChangeLog
    trunk/gcc/c-family/c-common.c
    trunk/gcc/c-family/c-opts.c
    trunk/gcc/c-family/c.opt
    trunk/gcc/doc/invoke.texi
    trunk/gcc/testsuite/ChangeLog
    trunk/libcpp/ChangeLog
    trunk/libcpp/include/cpplib.h
    trunk/libcpp/init.c
    trunk/libcpp/lex.c
Comment 4 Jeffrey Yasskin 2012-04-27 17:47:30 UTC
Is this ok for gcc-4_7-branch too? The other bug reports Jonathan mentioned won't be helped by a fix that skips 4.7.
Comment 5 Jonathan Wakely 2012-05-01 10:37:59 UTC
let's confirm this :)
Comment 6 Paolo Carlini 2012-11-12 14:57:22 UTC
Fixed for 4.8.0.