Since the fix for PR c++/80955 any suffix on a string literal that
begins with an underscore is assumed to be a user-defined literal
suffix, not a macro. This assumption is invalid for a suffix beginning
with two underscores, because such names are reserved and can't be used
for UDLs anyway. Checking for exactly one underscore restores support
for macro expansion in cases like "File: "__FILE__ or "Date: "__DATE__
(which are formally ill-formed but accepted with a warning, as a
conforming extension).

gcc/testsuite:

        PR preprocessor/84517
        * g++.dg/cpp0x/udlit-macros.C: Expect a warning for ""__FILE__.

libcpp:

        PR preprocessor/84517
        * lex.c (is_macro_not_literal_suffix): New function.
        (lex_raw_string, lex_string): Use is_macro_not_literal_suffix to
        decide when to issue -Wliteral-suffix warnings.


Tested powerpc64le-linux, OK for trunk?
commit 9781a25354e07503690259d7fa95e9dd459c51b2
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Thu Feb 22 19:59:38 2018 +0000

    PR preprocessor/84517 allow double-underscore macros after string literals
    
    Since the fix for PR c++/80955 any suffix on a string literal that
    begins with an underscore is assumed to be a user-defined literal
    suffix, not a macro. This assumption is invalid for a suffix beginning
    with two underscores, because such names are reserved and can't be used
    for UDLs anyway. Checking for exactly one underscore restores support
    for macro expansion in cases like "File: "__FILE__ or "Date: "__DATE__
    (which are formally ill-formed but accepted with a warning, as a
    conforming extension).
    
    gcc/testsuite:
    
            PR preprocessor/84517
            * g++.dg/cpp0x/udlit-macros.C: Expect a warning for ""__FILE__.
    
    libcpp:
    
            PR preprocessor/84517
            * lex.c (is_macro_not_literal_suffix): New function.
            (lex_raw_string, lex_string): Use is_macro_not_literal_suffix to
            decide when to issue -Wliteral-suffix warnings.

diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-macros.C 
b/gcc/testsuite/g++.dg/cpp0x/udlit-macros.C
index fb518281811..7ef324b7e04 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-macros.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-macros.C
@@ -16,7 +16,7 @@ int operator""_ID(const char*, size_t) { return 0; }
 int main()
 {
   long i64 = 123;
-  char buf[100];
+  char buf[] = "xxxxxx"__FILE__;      // { dg-warning "invalid suffix on 
literal" }
   sprintf(buf, "%"PRId64"abc", i64);  // { dg-warning "invalid suffix on 
literal" }
   return strcmp(buf, "123abc")
         + ""_zero
diff --git a/libcpp/lex.c b/libcpp/lex.c
index 92c62517a4d..37c365a3560 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -1630,6 +1630,21 @@ is_macro(cpp_reader *pfile, const uchar *base)
   return !result ? false : (result->type == NT_MACRO);
 }
 
+/* Returns true if a literal suffix does not have the expected form
+   and is defined as a macro.  */
+
+static bool
+is_macro_not_literal_suffix(cpp_reader *pfile, const uchar *base)
+{
+  /* User-defined literals outside of namespace std must start with a single
+     underscore, so assume anything of that form really is a UDL suffix.
+     We don't need to worry about UDLs defined inside namespace std because
+     their names are reserved, so cannot be used as macro names in valid
+     programs.  */
+  if (base[0] == '_' && base[1] != '_')
+    return false;
+  return is_macro (pfile, base);
+}
 
 /* Lexes a raw string.  The stored string contains the spelling, including
    double quotes, delimiter string, '(' and ')', any leading
@@ -1900,10 +1915,8 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, 
const uchar *base,
     {
       /* If a string format macro, say from inttypes.h, is placed touching
         a string literal it could be parsed as a C++11 user-defined string
-        literal thus breaking the program.
-        Try to identify macros with is_macro. A warning is issued.
-        The macro name should not start with '_' for this warning. */
-      if ((*cur != '_') && is_macro (pfile, cur))
+        literal thus breaking the program.  */
+      if (is_macro_not_literal_suffix (pfile, cur))
        {
          /* Raise a warning, but do not consume subsequent tokens.  */
          if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping)
@@ -2031,10 +2044,8 @@ lex_string (cpp_reader *pfile, cpp_token *token, const 
uchar *base)
     {
       /* If a string format macro, say from inttypes.h, is placed touching
         a string literal it could be parsed as a C++11 user-defined string
-        literal thus breaking the program.
-        Try to identify macros with is_macro. A warning is issued.
-        The macro name should not start with '_' for this warning. */
-      if ((*cur != '_') && is_macro (pfile, cur))
+        literal thus breaking the program.  */
+      if (is_macro_not_literal_suffix (pfile, cur))
        {
          /* Raise a warning, but do not consume subsequent tokens.  */
          if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping)

Reply via email to