]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add new option, -Wliteral-suffix.
authorOllie Wild <aaw@google.com>
Fri, 27 Apr 2012 14:29:32 +0000 (14:29 +0000)
committerOllie Wild <aaw@gcc.gnu.org>
Fri, 27 Apr 2012 14:29:32 +0000 (14:29 +0000)
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.

From-SVN: r186909

12 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C [new file with mode: 0644]
libcpp/ChangeLog
libcpp/include/cpplib.h
libcpp/init.c
libcpp/lex.c

index aeda32c9791c0caeb451c0765af01c4a00a48b6a..7097f17befd7fd4ba12d106d7892cdf28a912c49 100644 (file)
@@ -1,3 +1,7 @@
+2012-04-27   Ollie Wild  <aaw@google.com>
+
+       * doc/invoke.texi (Wliteral-suffix): Document new option.
+
 2012-04-27  Tom Tromey  <tromey@redhat.com>
 
        * dwarf2out.c (dwarf_stack_op_name): Use get_DW_OP_name.
index fb895315d432339a257bdfab480a973421c3ea74..2082ff6c4af0278fda308311e18fee84f23b2f01 100644 (file)
@@ -1,3 +1,9 @@
+2012-04-27   Ollie Wild  <aaw@google.com>
+
+       * c-common.c: Add CPP_W_LITERAL_SUFFIX mapping.
+       * c-opts.c (c_common_handle_option): Handle OPT_Wliteral_suffix.
+       * c.opt: Add Wliteral-suffix.
+
 2012-04-22  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR c/44774
index 4eacd198d779753dc7c2ed3c547aacdaeb09543e..bf5b034ee2d07004b0187445872bca9f47fd7cbf 100644 (file)
@@ -8820,6 +8820,7 @@ static const struct reason_option_codes_t option_codes[] = {
   {CPP_W_NORMALIZE,                    OPT_Wnormalized_},
   {CPP_W_INVALID_PCH,                  OPT_Winvalid_pch},
   {CPP_W_WARNING_DIRECTIVE,            OPT_Wcpp},
+  {CPP_W_LITERAL_SUFFIX,               OPT_Wliteral_suffix},
   {CPP_W_NONE,                         0}
 };
 
index 17e1958ad58d63c16f6f49e21d70c8feee713670..2510747c40e53a10a501dcf3175fb862a2c228cc 100644 (file)
@@ -476,6 +476,10 @@ c_common_handle_option (size_t scode, const char *arg, int value,
       cpp_opts->warn_invalid_pch = value;
       break;
 
+    case OPT_Wliteral_suffix:
+      cpp_opts->warn_literal_suffix = value;
+      break;
+
     case OPT_Wlong_long:
       cpp_opts->cpp_warn_long_long = value;
       break;
index d8c944d7e13e7a4505f6aa1547acae41c6676b27..db8ca812ca55a8e2df2d07b9ae5663b75c8471f1 100644 (file)
@@ -449,6 +449,10 @@ Wjump-misses-init
 C ObjC Var(warn_jump_misses_init) Init(-1) Warning
 Warn when a jump misses a variable initialization
 
+Wliteral-suffix
+C++ ObjC++ Warning
+Warn when a string or character literal is followed by a ud-suffix which does not begin with an underscore.
+
 Wlogical-op
 C ObjC C++ ObjC++ Var(warn_logical_op) Init(0) Warning 
 Warn when a logical operator is suspiciously always evaluating to true or false
index c6bf20dd3d3fca57ad40b08bfc89b0d27a92b364..280fac3b04bc03e4b92fc3bbf0d3d1af74e597d8 100644 (file)
@@ -198,8 +198,8 @@ in the following sections.
 -fno-default-inline  -fvisibility-inlines-hidden @gol
 -fvisibility-ms-compat @gol
 -Wabi  -Wconversion-null  -Wctor-dtor-privacy @gol
--Wdelete-non-virtual-dtor -Wnarrowing -Wnoexcept @gol
--Wnon-virtual-dtor  -Wreorder @gol
+-Wdelete-non-virtual-dtor -Wliteral-suffix -Wnarrowing @gol
+-Wnoexcept -Wnon-virtual-dtor  -Wreorder @gol
 -Weffc++  -Wstrict-null-sentinel @gol
 -Wno-non-template-friend  -Wold-style-cast @gol
 -Woverloaded-virtual  -Wno-pmf-conversions @gol
@@ -2425,6 +2425,30 @@ an instance of a derived class through a pointer to a base class if the
 base class does not have a virtual destructor.  This warning is enabled
 by @option{-Wall}.
 
+@item -Wliteral-suffix @r{(C++ and Objective-C++ only)}
+@opindex Wliteral-suffix
+@opindex Wno-literal-suffix
+Warn when a string or character literal is followed by a ud-suffix which does
+not begin with an underscore.  As a conforming extension, GCC treats such
+suffixes as separate preprocessing tokens in order to maintain backwards
+compatibility with code that uses formatting macros from @code{<inttypes.h>}.
+For example:
+
+@smallexample
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <stdio.h>
+
+int main() @{
+  int64_t i64 = 123;
+  printf("My int64: %"PRId64"\n", i64);
+@}
+@end smallexample
+
+In this case, @code{PRId64} is treated as a separate preprocessing token.
+
+This warning is enabled by default.
+
 @item -Wnarrowing @r{(C++ and Objective-C++ only)}
 @opindex Wnarrowing
 @opindex Wno-narrowing
index 72f1f468456f433809902fa6ea24c3906ecf2c7c..54c616c441d04741b081cb5bb84fd6056115f8e3 100644 (file)
@@ -1,3 +1,7 @@
+2012-04-27   Ollie Wild  <aaw@google.com>
+
+       * g++.dg/cpp0x/Wliteral-suffix.c: New test.
+
 2012-04-27  Paolo Bonzini  <bonzini@gnu.org>
 
        * gcc.c-torture/execute/20120427-2.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C b/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C
new file mode 100644 (file)
index 0000000..39a8353
--- /dev/null
@@ -0,0 +1,29 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+// Make sure -Wliteral-suffix is enabled by default and
+// triggers as expected.
+
+#define BAR "bar"
+#define PLUS_ONE + 1
+
+#include <cstdint>
+#include <cassert>
+
+
+void
+test()
+{
+  char c = '3'PLUS_ONE;          // { dg-warning "invalid suffix on literal" }
+  char s[] = "foo"BAR;   // { dg-warning "invalid suffix on literal" }
+
+  assert(c == '4');
+  assert(s[3] != '\0');
+  assert(s[3] == 'b');
+}
+
+int
+main()
+{
+  test();
+}
index 08878b2781106dbc1c1f5d323041ca6c035f764e..f7c330c514393905f76444f8091263c5d5ea4cd8 100644 (file)
@@ -1,3 +1,14 @@
+2012-04-27   Ollie Wild  <aaw@google.com>
+
+       * include/cpplib.h (struct cpp_options): Add new field,
+       warn_literal_suffix.
+       (CPP_W_LITERAL_SUFFIX): New enum.
+       * init.c (cpp_create_reader): Default initialization of
+       warn_literal_suffix.
+       * lex.c (lex_raw_string): Treat user-defined literals which don't
+       begin with '_' as separate tokens and produce a warning.
+       (lex_string): Ditto.
+
 2012-04-26  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        * line-map.c (linemap_resolve_location): Synchronize comments with
index bf59d016231dc8f817c2516e85bdff263277f020..9dbc477b61e88cd220464847b33786f88b193c2a 100644 (file)
@@ -427,6 +427,10 @@ struct cpp_options
   /* Nonzero for C++ 2011 Standard user-defnied literals.  */
   unsigned char user_literals;
 
+  /* Nonzero means warn when a string or character literal is followed by a
+     ud-suffix which does not beging with an underscore.  */
+  unsigned char warn_literal_suffix;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
@@ -906,7 +910,8 @@ enum {
   CPP_W_CXX_OPERATOR_NAMES,
   CPP_W_NORMALIZE,
   CPP_W_INVALID_PCH,
-  CPP_W_WARNING_DIRECTIVE
+  CPP_W_WARNING_DIRECTIVE,
+  CPP_W_LITERAL_SUFFIX
 };
 
 /* Output a diagnostic of some kind.  */
index 5fa82ca9c3ec14d5eafd00bc6912537246a78e73..3262184c9c5e603636a4ff94c3a801ec998157d6 100644 (file)
@@ -175,6 +175,7 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
   CPP_OPTION (pfile, warn_variadic_macros) = 1;
   CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1;
   CPP_OPTION (pfile, warn_normalize) = normalized_C;
+  CPP_OPTION (pfile, warn_literal_suffix) = 1;
 
   /* Default CPP arithmetic to something sensible for the host for the
      benefit of dumb users like fix-header.  */
index 9d23002d84be19b2a19ff83a246cbbde5c0880af..7e2671ef026f526f061a40017340fdf04ba5707f 100644 (file)
@@ -1553,14 +1553,30 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
 
   if (CPP_OPTION (pfile, user_literals))
     {
+      /* According to C++11 [lex.ext]p10, a ud-suffix not starting with an
+        underscore is ill-formed.  Since this breaks programs using macros
+        from inttypes.h, we generate a warning and treat the ud-suffix as a
+        separate preprocessing token.  This approach is under discussion by
+        the standards committee, and has been adopted as a conforming
+        extension by other front ends such as clang. */
+      if (ISALPHA (*cur))
+       {
+         // Raise a warning, but do not consume subsequent tokens.
+         if (CPP_OPTION (pfile, warn_literal_suffix))
+           cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
+                                  token->src_loc, 0,
+                                  "invalid suffix on literal; C++11 requires "
+                                  "a space between literal and identifier");
+       }
       /* Grab user defined literal suffix.  */
-      if (ISIDST (*cur))
+      else if (*cur == '_')
        {
          type = cpp_userdef_string_add_type (type);
          ++cur;
+
+         while (ISIDNUM (*cur))
+           ++cur;
        }
-      while (ISIDNUM (*cur))
-       ++cur;
     }
 
   pfile->buffer->cur = cur;
@@ -1668,15 +1684,31 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
 
   if (CPP_OPTION (pfile, user_literals))
     {
+      /* According to C++11 [lex.ext]p10, a ud-suffix not starting with an
+        underscore is ill-formed.  Since this breaks programs using macros
+        from inttypes.h, we generate a warning and treat the ud-suffix as a
+        separate preprocessing token.  This approach is under discussion by
+        the standards committee, and has been adopted as a conforming
+        extension by other front ends such as clang. */
+      if (ISALPHA (*cur))
+       {
+         // Raise a warning, but do not consume subsequent tokens.
+         if (CPP_OPTION (pfile, warn_literal_suffix))
+           cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
+                                  token->src_loc, 0,
+                                  "invalid suffix on literal; C++11 requires "
+                                  "a space between literal and identifier");
+       }
       /* Grab user defined literal suffix.  */
-      if (ISIDST (*cur))
+      else if (*cur == '_')
        {
          type = cpp_userdef_char_add_type (type);
          type = cpp_userdef_string_add_type (type);
           ++cur;
+
+         while (ISIDNUM (*cur))
+           ++cur;
        }
-      while (ISIDNUM (*cur))
-       ++cur;
     }
 
   pfile->buffer->cur = cur;