]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
lex.c (lex_raw_string(), [...]): Constrain suffixes treated as concatenated literal...
authorEd Smith-Rowland <3dw4rd@verizon.net>
Sat, 29 Jun 2013 03:41:58 +0000 (03:41 +0000)
committerEdward Smith-Rowland <emsr@gcc.gnu.org>
Sat, 29 Jun 2013 03:41:58 +0000 (03:41 +0000)
libcpp:

2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>

* lex.c (lex_raw_string(), lex_string()): Constrain suffixes treated
as concatenated literal and macro to just the patterns found in
inttypes.h; (is_macro()): New.

gcc/cp:

2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>

* cp-tree.h (UDLIT_OP_ANSI_PREFIX): Remove space.
* parser.c (cp_parser_operator()): Parse user-defined string
literal as literal operator.

gcc/testsuite:

2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>

* g++.dg/cpp0x/udlit-nospace-neg.C: Adjust.
* g++.dg/cpp1y/udlit-enc-prefix-neg.C: New.
* g++.dg/cpp1y/udlit-userdef-string.C: New.
* g++.dg/cpp1y/complex_literals.h: New.

From-SVN: r200563

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C
gcc/testsuite/g++.dg/cpp1y/complex_literals.h [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/udlit-enc-prefix-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/udlit-userdef-string.C [new file with mode: 0644]
libcpp/ChangeLog
libcpp/lex.c

index c00f24c7fd0975dd2a25d55650eb0e9f71746be1..2de63c0b8d87ef8cd9dbf0774541d33f3b5969a5 100644 (file)
@@ -1,3 +1,9 @@
+2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>
+
+       * cp-tree.h (UDLIT_OP_ANSI_PREFIX): Remove space.
+       * parser.c (cp_parser_operator()): Parse user-defined string
+       literal as literal operator.
+
 2013-06-28  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/57645
index d3dd494124268169865a6d6ec62f60e17c893f8e..3e8043a4162692600d4a3a0375232321859c897c 100644 (file)
@@ -4404,7 +4404,7 @@ extern GTY(()) vec<tree, va_gc> *local_classes;
 #define LAMBDANAME_PREFIX "__lambda"
 #define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d"
 
-#define UDLIT_OP_ANSI_PREFIX "operator\"\" "
+#define UDLIT_OP_ANSI_PREFIX "operator\"\""
 #define UDLIT_OP_ANSI_FORMAT UDLIT_OP_ANSI_PREFIX "%s"
 #define UDLIT_OP_MANGLED_PREFIX "li"
 #define UDLIT_OP_MANGLED_FORMAT UDLIT_OP_MANGLED_PREFIX "%s"
index 281e163b7df0a7f389944bc261c3a01dcdfac86e..6e8293b024e108a64d34b23d9894e92e0efcd79b 100644 (file)
@@ -12244,6 +12244,8 @@ cp_parser_operator (cp_parser* parser)
 {
   tree id = NULL_TREE;
   cp_token *token;
+  bool bad_encoding_prefix = false;
+  int string_len = 2;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -12443,10 +12445,20 @@ cp_parser_operator (cp_parser* parser)
       cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
       return ansi_opname (ARRAY_REF);
 
+    case CPP_WSTRING:
+      string_len = 3;
+    case CPP_STRING16:
+    case CPP_STRING32:
+      string_len = 5;
+    case CPP_UTF8STRING:
+      string_len = 4;
+      bad_encoding_prefix = true;
     case CPP_STRING:
       if (cxx_dialect == cxx98)
        maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
-      if (TREE_STRING_LENGTH (token->u.value) > 2)
+      if (bad_encoding_prefix)
+       error ("invalid encoding prefix in literal operator");
+      if (TREE_STRING_LENGTH (token->u.value) > string_len)
        {
          error ("expected empty string after %<operator%> keyword");
          return error_mark_node;
@@ -12464,15 +12476,49 @@ cp_parser_operator (cp_parser* parser)
              return cp_literal_operator_id (name);
            }
        }
+      else if (token->type == CPP_KEYWORD)
+       {
+         error ("unexpected keyword;"
+                " remove space between quotes and suffix identifier");
+         return error_mark_node;
+       }
       else
        {
          error ("expected suffix identifier");
          return error_mark_node;
        }
 
+    case CPP_WSTRING_USERDEF:
+      string_len = 3;
+    case CPP_STRING16_USERDEF:
+    case CPP_STRING32_USERDEF:
+      string_len = 5;
+    case CPP_UTF8STRING_USERDEF:
+      string_len = 4;
+      bad_encoding_prefix = true;
     case CPP_STRING_USERDEF:
-      error ("missing space between %<\"\"%> and suffix identifier");
-      return error_mark_node;
+      if (cxx_dialect == cxx98)
+       maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
+      if (bad_encoding_prefix)
+       error ("invalid encoding prefix in literal operator");
+      {
+       tree string_tree = USERDEF_LITERAL_VALUE (token->u.value);
+       if (TREE_STRING_LENGTH (string_tree) > string_len)
+         {
+           error ("expected empty string after %<operator%> keyword");
+           return error_mark_node;
+         }
+       id = USERDEF_LITERAL_SUFFIX_ID (token->u.value);
+       /* Consume the user-defined string literal.  */
+       cp_lexer_consume_token (parser->lexer);
+       if (id != error_mark_node)
+         {
+           const char *name = IDENTIFIER_POINTER (id);
+           return cp_literal_operator_id (name);
+         }
+       else
+         return error_mark_node;
+      }
 
     default:
       /* Anything else is an error.  */
index 1ab4a98eb10bec259c6c2b6d506fc73e2a80b240..5c09364a80a38b912746bee377b45697ad4d48c5 100644 (file)
@@ -1,3 +1,10 @@
+2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>
+
+       * g++.dg/cpp0x/udlit-nospace-neg.C: Adjust.
+       * g++.dg/cpp1y/udlit-enc-prefix-neg.C: New.
+       * g++.dg/cpp1y/udlit-userdef-string.C: New.
+       * g++.dg/cpp1y/complex_literals.h: New.
+
 2013-06-28  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/57645
index 2b57637a9168d176c21f3f06f43ea4245295e582..f06bd8bdf02b5d045cf89ec721da9a0cb1f39fcf 100644 (file)
@@ -1,3 +1,5 @@
 // { dg-options "-std=c++0x" }
 
-float operator ""_abc(const char*); // { dg-error "missing space between|and suffix identifier" }
+float operator ""_abc(const char*);
+
+int operator""_def(long double);
diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals.h b/gcc/testsuite/g++.dg/cpp1y/complex_literals.h
new file mode 100644 (file)
index 0000000..ea328e3
--- /dev/null
@@ -0,0 +1,12 @@
+
+#include <complex>
+
+#pragma GCC system_header
+
+std::complex<float>
+operator""if(long double ximag)
+{ return std::complex<float>(0.0F, static_cast<float>(ximag)); }
+
+std::complex<float>
+operator""if(unsigned long long nimag)
+{ return std::complex<float>(0.0F, static_cast<float>(nimag)); }
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-enc-prefix-neg.C b/gcc/testsuite/g++.dg/cpp1y/udlit-enc-prefix-neg.C
new file mode 100644 (file)
index 0000000..149fd0d
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-options -std=c++1y }
+
+int
+operator L""_Ls(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
+{ return 0; }
+
+int
+operator u""_s16(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
+{ return 0; }
+
+int
+operator U""_s32(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
+{ return 0; }
+
+int
+operator u8""_u8s(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
+{ return 0; }
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-userdef-string.C b/gcc/testsuite/g++.dg/cpp1y/udlit-userdef-string.C
new file mode 100644 (file)
index 0000000..e58a66b
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options -std=c++1y }
+
+#include "complex_literals.h"
+
+auto cx = 1.1if;
+
+auto cn = 123if;
index ca29119c953322a354497f3525e3738e35301bc6..0cf9100cf62f5f6a0f282bdae2b660a45d1c1e41 100644 (file)
@@ -1,3 +1,9 @@
+2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>
+
+       * lex.c (lex_raw_string(), lex_string()): Constrain suffixes treated
+       as concatenated literal and macro to just the patterns found in
+       inttypes.h; (is_macro()): New.
+
 2013-06-24  Dehao Chen  <dehao@google.com>
 
        * files.c (_cpp_stack_include): Fix the highest_location when header
index 3e59d40d32e3f1a4a1192276dec5f0b358651b17..022d31016e221ed3114b711d8a0edff77bbdb49c 100644 (file)
@@ -1334,6 +1334,33 @@ bufring_append (cpp_reader *pfile, const uchar *base, size_t len,
   *last_buff_p = last_buff;
 }
 
+
+/* Returns true if a macro has been defined.
+   This might not work if compile with -save-temps,
+   or preprocess separately from compilation.  */
+
+static bool
+is_macro(cpp_reader *pfile, const uchar *base)
+{
+  const uchar *cur = base;
+  if (! ISIDST (*cur))
+    return false;
+  unsigned int hash = HT_HASHSTEP (0, *cur);
+  ++cur;
+  while (ISIDNUM (*cur))
+    {
+      hash = HT_HASHSTEP (hash, *cur);
+      ++cur;
+    }
+  hash = HT_HASHFINISH (hash, cur - base);
+
+  cpp_hashnode *result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table,
+                                       base, cur - base, hash, HT_NO_INSERT));
+
+  return !result ? false : (result->type == NT_MACRO);
+}
+
+
 /* Lexes a raw string.  The stored string contains the spelling, including
    double quotes, delimiter string, '(' and ')', any leading
    'L', 'u', 'U' or 'u8' and 'R' modifier.  It returns the type of the
@@ -1556,22 +1583,18 @@ 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.
-         A special exception is made for the suffix 's' which will be
-        standardized as a user-defined literal suffix for strings.  */
-      if (ISALPHA (*cur) && *cur != 's')
+      /* 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. */
+      if (is_macro (pfile, 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");
+                                  "a space between literal and string macro");
        }
       /* Grab user defined literal suffix.  */
       else if (ISIDST (*cur))
@@ -1689,22 +1712,18 @@ 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.
-         A special exception is made for the suffix 's' which will be
-        standardized as a user-defined literal suffix for strings.  */
-      if (ISALPHA (*cur) && *cur != 's')
+      /* 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. */
+      if (is_macro (pfile, 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");
+                                  "a space between literal and string macro");
        }
       /* Grab user defined literal suffix.  */
       else if (ISIDST (*cur))