===================================================================
@@ -4404,7 +4404,7 @@
#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"
===================================================================
@@ -1556,22 +1556,21 @@
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.
+ Since all format macros in inttypes.h start with "PRI" or "SCN"
+ suffixes beginning with these will be interpreted as macros and the
+ string and the macro parsed as separate tokens. A warning is issued. */
+ if (ustrcmp (cur, (const unsigned char *) "PRI") == 0
+ || ustrcmp (cur, (const unsigned char *) "SCN") == 0)
{
/* 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 +1688,21 @@
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.
+ Since all format macros in inttypes.h start with "PRI" or "SCN"
+ suffixes beginning with these will be interpreted as macros and the
+ string and the macro parsed as separate tokens. A warning is issued. */
+ if (ustrcmp (cur, (const unsigned char *) "PRI") == 0
+ || ustrcmp (cur, (const unsigned char *) "SCN") == 0)
{
/* 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))
===================================================================
@@ -12370,6 +12370,8 @@
{
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);
@@ -12569,10 +12571,20 @@
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;
@@ -12590,15 +12602,49 @@
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. */
===================================================================
@@ -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);
===================================================================
@@ -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; }
===================================================================
@@ -0,0 +1,7 @@
+// { dg-options -std=c++1y }
+
+#include "complex_literals.h"
+
+auto cx = 1.1if;
+
+auto cn = 123if;
===================================================================
@@ -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)); }