Hi,
submitter ran a static analysis tool on parser.c and found in the main
switch of cp_parser_operator some broken cases having to do with user
defined literals. When I looked into it I found a rather convoluted
logic which tried to possibly emit *both* the error message for and
invalid encoding prefix (as tested in udlit-enc-prefix-neg.C) and the
error message for non-empty string after 'operator' (untested in the
testsuite) before returning error_mark_node. Then when only the former
was appropriate, it was emitted twice. The second missed cases - too big
string_len.
Now, I don't think it should be so common that the user code has both
issues in the same user defined literal (in that case providing both
error messages at once would make debugging quicker), thus in the below
I decided to simplify everything and immediately return error_mark_node
after any error along the way.
Tested x86_64-linux.
Thanks,
Paolo.
////////////////////////
/cp
2013-07-25 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/57880
* parser.c (cp_parser_operator, case CPP_WSTRING, CPP_STRING16,
CPP_STRING32, CPP_UTF8STRING, CPP_WSTRING_USERDEF,
CPP_STRING16_USERDEF, CPP_STRING32_USERDEF, CPP_UTF8STRING_USERDEF):
Fix string_len management, tidy.
/testsuite
2013-07-25 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/57880
* g++.dg/cpp1y/udlit-empty-string-neg.C: New.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 201214)
+++ cp/parser.c (working copy)
@@ -12261,7 +12261,6 @@ 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);
@@ -12462,20 +12461,22 @@ cp_parser_operator (cp_parser* parser)
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;
+ 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");
- if (TREE_STRING_LENGTH (token->u.value) > string_len)
{
+ 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;
}
@@ -12505,21 +12506,23 @@ cp_parser_operator (cp_parser* parser)
}
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;
+ /* Fall through. */
+
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");
+ {
+ error ("invalid encoding prefix in literal operator");
+ return error_mark_node;
+ }
{
tree string_tree = USERDEF_LITERAL_VALUE (token->u.value);
- if (TREE_STRING_LENGTH (string_tree) > string_len)
+ if (TREE_STRING_LENGTH (string_tree) > 2)
{
error ("expected empty string after %<operator%> keyword");
return error_mark_node;
Index: testsuite/g++.dg/cpp1y/udlit-empty-string-neg.C
===================================================================
--- testsuite/g++.dg/cpp1y/udlit-empty-string-neg.C (revision 0)
+++ testsuite/g++.dg/cpp1y/udlit-empty-string-neg.C (working copy)
@@ -0,0 +1,5 @@
+// { dg-options -std=c++1y }
+
+int
+operator "*"_s(unsigned long long) // { dg-error "expected empty string after
'operator'" }
+{ return 0; }