Commit 17adeaa7 by Paolo Carlini Committed by Paolo Carlini

re PR c++/54891 ([C++11] lambda-expression and explicit type conversion (cast notation))

/cp
2014-06-30  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54891
	* parser.c (cp_parser_tokens_start_cast_expression): In C++11
	a '[' can also start a primary-expression.
	(cp_parser_cast_expression): Parse a cast-expression only tentatively
	when cp_parser_tokens_start_cast_expression returns -1.

/testsuite
2014-06-30  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54891
	* g++.dg/cpp0x/lambda/lambda-cast1.C: New.

From-SVN: r212162
parent 6e7ceb17
2014-06-30 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/54891
* parser.c (cp_parser_tokens_start_cast_expression): In C++11
a '[' can also start a primary-expression.
(cp_parser_cast_expression): Parse a cast-expression only tentatively
when cp_parser_tokens_start_cast_expression returns -1.
2014-06-30 Jason Merrill <jason@redhat.com> 2014-06-30 Jason Merrill <jason@redhat.com>
PR c++/61539 PR c++/61539
......
...@@ -4109,6 +4109,7 @@ complain_flags (bool decltype_p) ...@@ -4109,6 +4109,7 @@ complain_flags (bool decltype_p)
this this
( expression ) ( expression )
id-expression id-expression
lambda-expression (C++11)
GNU Extensions: GNU Extensions:
...@@ -7621,10 +7622,10 @@ cp_parser_delete_expression (cp_parser* parser) ...@@ -7621,10 +7622,10 @@ cp_parser_delete_expression (cp_parser* parser)
tf_warning_or_error); tf_warning_or_error);
} }
/* Returns true if TOKEN may start a cast-expression and false /* Returns 1 if TOKEN may start a cast-expression and, in C++11,
otherwise. */ isn't '[', -1 if TOKEN is '[' in C++11, 0 otherwise. */
static bool static int
cp_parser_tokens_start_cast_expression (cp_parser *parser) cp_parser_tokens_start_cast_expression (cp_parser *parser)
{ {
cp_token *token = cp_lexer_peek_token (parser->lexer); cp_token *token = cp_lexer_peek_token (parser->lexer);
...@@ -7667,7 +7668,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser) ...@@ -7667,7 +7668,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
case CPP_OR: case CPP_OR:
case CPP_OR_OR: case CPP_OR_OR:
case CPP_EOF: case CPP_EOF:
return false; return 0;
case CPP_OPEN_PAREN: case CPP_OPEN_PAREN:
/* In ((type ()) () the last () isn't a valid cast-expression, /* In ((type ()) () the last () isn't a valid cast-expression,
...@@ -7675,12 +7676,15 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser) ...@@ -7675,12 +7676,15 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
return cp_lexer_peek_nth_token (parser->lexer, 2)->type return cp_lexer_peek_nth_token (parser->lexer, 2)->type
!= CPP_CLOSE_PAREN; != CPP_CLOSE_PAREN;
/* '[' may start a primary-expression in obj-c++. */ /* '[' may start a primary-expression in obj-c++ and in C++11,
as a lambda-expression, eg, '(void)[]{}'. */
case CPP_OPEN_SQUARE: case CPP_OPEN_SQUARE:
if (cxx_dialect >= cxx11)
return -1;
return c_dialect_objc (); return c_dialect_objc ();
default: default:
return true; return 1;
} }
} }
...@@ -7705,7 +7709,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, ...@@ -7705,7 +7709,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
{ {
tree type = NULL_TREE; tree type = NULL_TREE;
tree expr = NULL_TREE; tree expr = NULL_TREE;
bool cast_expression_p; int cast_expression = 0;
const char *saved_message; const char *saved_message;
/* There's no way to know yet whether or not this is a cast. /* There's no way to know yet whether or not this is a cast.
...@@ -7728,6 +7732,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, ...@@ -7728,6 +7732,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
will commit to the parse at that point, because we cannot will commit to the parse at that point, because we cannot
undo the action that is done when creating a new class. So, undo the action that is done when creating a new class. So,
then we cannot back up and do a postfix-expression. then we cannot back up and do a postfix-expression.
Another tricky case is the following (c++/29234): Another tricky case is the following (c++/29234):
struct S { void operator () (); }; struct S { void operator () (); };
...@@ -7746,20 +7751,30 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, ...@@ -7746,20 +7751,30 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
we are dealing with an unary-expression, a postfix-expression we are dealing with an unary-expression, a postfix-expression
or something else. or something else.
Yet another tricky case, in C++11, is the following (c++/54891):
(void)[]{};
The issue is that usually, besides the case of lambda-expressions,
the parenthesized type-id cannot be followed by '[', and, eg, we
want to parse '(C ())[2];' in parse/pr26997.C as unary-expression.
Thus, if cp_parser_tokens_start_cast_expression returns -1, below
we don't commit, we try a cast-expression, then an unary-expression.
Save tokens so that we can put them back. */ Save tokens so that we can put them back. */
cp_lexer_save_tokens (parser->lexer); cp_lexer_save_tokens (parser->lexer);
/* We may be looking at a cast-expression. */ /* We may be looking at a cast-expression. */
cast_expression_p if (cp_parser_skip_to_closing_parenthesis (parser, false, false,
= (cp_parser_skip_to_closing_parenthesis (parser, false, false, /*consume_paren=*/true))
/*consume_paren=*/true) cast_expression
&& cp_parser_tokens_start_cast_expression (parser)); = cp_parser_tokens_start_cast_expression (parser);
/* Roll back the tokens we skipped. */ /* Roll back the tokens we skipped. */
cp_lexer_rollback_tokens (parser->lexer); cp_lexer_rollback_tokens (parser->lexer);
/* If we aren't looking at a cast-expression, simulate an error so /* If we aren't looking at a cast-expression, simulate an error so
that the call to cp_parser_parse_definitely below will fail. */ that the call to cp_parser_error_occurred below returns true. */
if (!cast_expression_p) if (!cast_expression)
cp_parser_simulate_error (parser); cp_parser_simulate_error (parser);
else else
{ {
...@@ -7780,13 +7795,19 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, ...@@ -7780,13 +7795,19 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
function returning T. */ function returning T. */
if (!cp_parser_error_occurred (parser)) if (!cp_parser_error_occurred (parser))
{ {
cp_parser_parse_definitely (parser); /* Only commit if the cast-expression doesn't start with '[' in
C++11, which may or may not start a lambda-expression. */
if (cast_expression > 0)
cp_parser_commit_to_topmost_tentative_parse (parser);
expr = cp_parser_cast_expression (parser, expr = cp_parser_cast_expression (parser,
/*address_p=*/false, /*address_p=*/false,
/*cast_p=*/true, /*cast_p=*/true,
/*decltype_p=*/false, /*decltype_p=*/false,
pidk); pidk);
if (cp_parser_parse_definitely (parser))
{
/* Warn about old-style casts, if so requested. */ /* Warn about old-style casts, if so requested. */
if (warn_old_style_cast if (warn_old_style_cast
&& !in_system_header_at (input_location) && !in_system_header_at (input_location)
...@@ -7805,6 +7826,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, ...@@ -7805,6 +7826,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
expr = build_c_cast (input_location, type, expr); expr = build_c_cast (input_location, type, expr);
return expr; return expr;
} }
}
else else
cp_parser_abort_tentative_parse (parser); cp_parser_abort_tentative_parse (parser);
} }
......
2014-06-30 Paolo Carlini <paolo.carlini@oracle.com> 2014-06-30 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/54891
* g++.dg/cpp0x/lambda/lambda-cast1.C: New.
2014-06-30 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/51400 PR c++/51400
* g++.dg/cpp0x/constexpr-attribute3.C: New. * g++.dg/cpp0x/constexpr-attribute3.C: New.
......
// PR c++/54891
// { dg-do compile { target c++11 } }
int main()
{
(void)[]{};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment