PING!

Support operator"" ""(...) per CWG 1473.
This brings full string parsing to literal operator declarations including 
string chunk concatenation and appropriate errors.

Bootstrapped and tested on x86_64-linux.

OK?

I'm less sure if this is appropriate for 4.9 even when it opens.

cp/
        
2014-07-12  Edward Smith-Rowland  <3dw...@verizon.net>

        PR C++/60209 - Declaration of user-defined literal operator cause error
        * cp/parser.c (cp_parser_operator()): Fold treatment of strings
        and user-defined string literals.  Use the full string parser.
        (cp_parser_string_literal()): Add flag to not look for literal operator.


testsuite/
        
2014-07-12  Edward Smith-Rowland  <3dw...@verizon.net>

        PR C++/60209 - Declaration of user-defined literal operator cause error
        * g++.dg/cpp0x/pr60209-neg.C: New.
        * g++.dg/cpp0x/pr60209.C: New.
        * g++.dg/cpp1y/udlit-empty-string-neg.C: Adjust messages.

Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 212479)
+++ cp/parser.c (working copy)
@@ -1895,7 +1895,7 @@
 static tree cp_parser_identifier
   (cp_parser *);
 static tree cp_parser_string_literal
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, bool);
 static tree cp_parser_userdef_char_literal
   (cp_parser *);
 static tree cp_parser_userdef_string_literal
@@ -3566,7 +3566,8 @@
 
    FUTURE: ObjC++ will need to handle @-strings here.  */
 static tree
-cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
+cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
+                         bool lookup_udlit = true)
 {
   tree value;
   size_t count;
@@ -3721,7 +3722,10 @@
        {
          tree literal = build_userdef_literal (suffix_id, value,
                                                OT_NONE, NULL_TREE);
-         value = cp_parser_userdef_string_literal (literal);
+         if (lookup_udlit)
+           value = cp_parser_userdef_string_literal (literal);
+         else
+           value = literal;
        }
     }
   else
@@ -12636,7 +12640,7 @@
 {
   tree id = NULL_TREE;
   cp_token *token;
-  bool bad_encoding_prefix = false;
+  bool utf8 = false;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -12836,83 +12840,73 @@
       cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
       return ansi_opname (ARRAY_REF);
 
+    case CPP_UTF8STRING:
+    case CPP_UTF8STRING_USERDEF:
+      utf8 = true;
+    case CPP_STRING:
     case CPP_WSTRING:
     case CPP_STRING16:
     case CPP_STRING32:
-    case CPP_UTF8STRING:
-     bad_encoding_prefix = true;
-      /* Fall through.  */
-
-    case CPP_STRING:
-      if (cxx_dialect == cxx98)
-       maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
-      if (bad_encoding_prefix)
-       {
-         error ("invalid encoding prefix in literal operator");
-         return error_mark_node;
-       }
-      if (TREE_STRING_LENGTH (token->u.value) > 2)
-       {
-         error ("expected empty string after %<operator%> keyword");
-         return error_mark_node;
-       }
-      /* Consume the string.  */
-      cp_lexer_consume_token (parser->lexer);
-      /* Look for the suffix identifier.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      if (token->type == CPP_NAME)
-       {
-         id = cp_parser_identifier (parser);
-         if (id != error_mark_node)
-           {
-             const char *name = IDENTIFIER_POINTER (id);
-             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_STRING_USERDEF:
     case CPP_WSTRING_USERDEF:
     case CPP_STRING16_USERDEF:
     case CPP_STRING32_USERDEF:
-    case CPP_UTF8STRING_USERDEF:
-      bad_encoding_prefix = true;
-      /* Fall through.  */
+      {
+       tree str, string_tree;
+       int sz, len;
 
-    case CPP_STRING_USERDEF:
-      if (cxx_dialect == cxx98)
-       maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
-      if (bad_encoding_prefix)
-       {
-         error ("invalid encoding prefix in literal operator");
+       if (cxx_dialect == cxx98)
+         maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
+
+       /* Consume the string.  */
+       str = cp_parser_string_literal (parser, /*translate=*/true,
+                                     /*wide_ok=*/true, /*lookup_udlit=*/false);
+       if (str == error_mark_node)
          return error_mark_node;
-       }
-      {
-       tree string_tree = USERDEF_LITERAL_VALUE (token->u.value);
-       if (TREE_STRING_LENGTH (string_tree) > 2)
+       else if (TREE_CODE (str) == USERDEF_LITERAL)
          {
+           string_tree = USERDEF_LITERAL_VALUE (str);
+           id = USERDEF_LITERAL_SUFFIX_ID (str);
+         }
+       else
+         {
+           string_tree = str;
+           /* Look for the suffix identifier.  */
+           token = cp_lexer_peek_token (parser->lexer);
+           if (token->type == CPP_NAME)
+             id = cp_parser_identifier (parser);
+           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;
+             }
+         }
+       sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT
+                              (TREE_TYPE (TREE_TYPE (string_tree))));
+       len = TREE_STRING_LENGTH (string_tree) / sz - 1;
+       if (len != 0)
+         {
            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 (utf8 || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string_tree)))
+           != char_type_node)
+         {
+           error ("invalid encoding prefix in literal operator");
+           return error_mark_node;
+         }
        if (id != error_mark_node)
          {
            const char *name = IDENTIFIER_POINTER (id);
-           return cp_literal_operator_id (name);
+           id = cp_literal_operator_id (name);
          }
-       else
-         return error_mark_node;
+       return id;
       }
 
     default:
Index: testsuite/g++.dg/cpp0x/pr60209-neg.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr60209-neg.C        (revision 0)
+++ testsuite/g++.dg/cpp0x/pr60209-neg.C        (working copy)
@@ -0,0 +1,28 @@
+// PR c++/60209
+// { dg-do compile { target c++11 } }
+
+// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1473
+
+void operator "" "boo" _ya(unsigned long long); // { dg-error "expected empty 
string after" }
+
+void operator "" "boo"_ya(unsigned long long); // { dg-error "expected empty 
string after" }
+
+void operator "" u"" _u(unsigned long long); // { dg-error "invalid encoding 
prefix in literal operator" }
+
+void operator u"" "" _v(unsigned long long); // { dg-error "invalid encoding 
prefix in literal operator" }
+
+void operator U"" "" _w(unsigned long long); // { dg-error "invalid encoding 
prefix in literal operator" }
+
+void operator L"" "" _x(unsigned long long); // { dg-error "invalid encoding 
prefix in literal operator" }
+
+void operator u8"" "" _y(unsigned long long); // { dg-error "invalid encoding 
prefix in literal operator" }
+
+void operator u"" L"" _z(unsigned long long); // { dg-error "unsupported 
non-standard concatenation of string literals" }
+
+void operator ""_p ""_q(unsigned long long); // { dg-error "inconsistent 
user-defined literal suffixes" }
+
+void operator "" "" while(unsigned long long); // { dg-error "unexpected 
keyword; remove space between quotes and suffix identifier" }
+
+void operator "" ""(unsigned long long); // { dg-error "expected suffix 
identifier" }
+
+// { dg-error "invalid encoding prefix in literal operator" "invalid" { target 
*-*-* } 20 }
Index: testsuite/g++.dg/cpp0x/pr60209.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr60209.C    (revision 0)
+++ testsuite/g++.dg/cpp0x/pr60209.C    (working copy)
@@ -0,0 +1,12 @@
+// PR c++/60209
+// { dg-do compile { target c++11 } }
+
+// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1473
+
+void operator "" "" _x(unsigned long long);
+
+void operator "" "" "" _x(unsigned long long);
+
+void operator "" ""_w(unsigned long long);
+
+void operator "" ""_w ""(unsigned long long);
Index: testsuite/g++.dg/cpp1y/udlit-empty-string-neg.C
===================================================================
--- testsuite/g++.dg/cpp1y/udlit-empty-string-neg.C     (revision 212479)
+++ testsuite/g++.dg/cpp1y/udlit-empty-string-neg.C     (working copy)
@@ -5,17 +5,17 @@
 { return 0; }
 
 int
-operator L"*"_Ls(unsigned long long) // { dg-error "invalid encoding prefix in 
literal operator" }
+operator L"*"_Ls(unsigned long long) // { dg-error "expected empty string 
after 'operator'" }
 { return 0; }
 
 int
-operator u"*"_s16(unsigned long long) // { dg-error "invalid encoding prefix 
in literal operator" }
+operator u"*"_s16(unsigned long long) // { dg-error "expected empty string 
after 'operator'" }
 { return 0; }
 
 int
-operator U"*"_s32(unsigned long long) // { dg-error "invalid encoding prefix 
in literal operator" }
+operator U"*"_s32(unsigned long long) // { dg-error "expected empty string 
after 'operator'" }
 { return 0; }
 
 int
-operator u8"*"_u8s(unsigned long long) // { dg-error "invalid encoding prefix 
in literal operator" }
+operator u8"*"_u8s(unsigned long long) // { dg-error "expected empty string 
after 'operator'" }
 { return 0; }

Reply via email to