re PR c++/29234 (Call to operator() of temporary object wrongly parsed)

/cp
2013-11-02  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/29234
	PR c++/56037
	* parser.c (cp_parser_cast_expression): If we aren't looking at
	a cast-expression don't call cp_parser_type_id.
	(cp_parser_postfix_expression): Likewise for compound-literal.
	(cp_parser_tokens_start_cast_expression): Adjust.

/testsuite
2013-11-02  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/29234
	PR c++/56037
	* g++.dg/parse/pr29234.C: New.
	* g++.dg/parse/pr56037.C: Likewise.

From-SVN: r204312
This commit is contained in:
Paolo Carlini 2013-11-02 09:34:13 +00:00 committed by Paolo Carlini
parent ef86cd2bf2
commit 2afe03827a
5 changed files with 101 additions and 31 deletions

View File

@ -1,3 +1,12 @@
2013-11-02 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/29234
PR c++/56037
* parser.c (cp_parser_cast_expression): If we aren't looking at
a cast-expression don't call cp_parser_type_id.
(cp_parser_postfix_expression): Likewise for compound-literal.
(cp_parser_tokens_start_cast_expression): Adjust.
2013-11-01 Edward Smith-Rowland <3dw4rd@verizon.net> 2013-11-01 Edward Smith-Rowland <3dw4rd@verizon.net>
PR c++/58708 PR c++/58708

View File

@ -5817,31 +5817,45 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{ {
tree initializer = NULL_TREE; tree initializer = NULL_TREE;
bool saved_in_type_id_in_expr_p; bool compound_literal_p;
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
/* Consume the `('. */ /* Consume the `('. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
/* Parse the type. */
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; /* Avoid calling cp_parser_type_id pointlessly, see comment
parser->in_type_id_in_expr_p = true; in cp_parser_cast_expression about c++/29234. */
type = cp_parser_type_id (parser); cp_lexer_save_tokens (parser->lexer);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
/* Look for the `)'. */ compound_literal_p
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
/*consume_paren=*/true)
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
/* Roll back the tokens we skipped. */
cp_lexer_rollback_tokens (parser->lexer);
if (!compound_literal_p)
cp_parser_simulate_error (parser);
else
{
/* Parse the type. */
bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
parser->in_type_id_in_expr_p = true;
type = cp_parser_type_id (parser);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
}
/* If things aren't going well, there's no need to /* If things aren't going well, there's no need to
keep going. */ keep going. */
if (!cp_parser_error_occurred (parser)) if (!cp_parser_error_occurred (parser))
{ {
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) bool non_constant_p;
{ /* Parse the brace-enclosed initializer list. */
bool non_constant_p; initializer = cp_parser_braced_list (parser,
/* Parse the brace-enclosed initializer list. */ &non_constant_p);
initializer = cp_parser_braced_list (parser,
&non_constant_p);
}
else
cp_parser_simulate_error (parser);
} }
/* If that worked, we're definitely looking at a /* If that worked, we're definitely looking at a
compound-literal expression. */ compound-literal expression. */
@ -7509,6 +7523,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
case CPP_CLOSE_SQUARE: case CPP_CLOSE_SQUARE:
case CPP_CLOSE_PAREN: case CPP_CLOSE_PAREN:
case CPP_CLOSE_BRACE: case CPP_CLOSE_BRACE:
case CPP_OPEN_BRACE:
case CPP_DOT: case CPP_DOT:
case CPP_DOT_STAR: case CPP_DOT_STAR:
case CPP_DEREF: case CPP_DEREF:
@ -7576,7 +7591,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 compound_literal_p; bool cast_expression_p;
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.
@ -7599,26 +7614,38 @@ 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):
struct S { void operator () (); };
void foo ()
{
( S()() );
}
As a type-id we parse the parenthesized S()() as a function
returning a function, groktypename complains and we cannot
back up in this case either.
Therefore, we scan ahead to the closing `)', and check to see Therefore, we scan ahead to the closing `)', and check to see
if the token after the `)' is a `{'. If so, we are not if the tokens after the `)' can start a cast-expression. Otherwise
looking at a cast-expression. we are dealing with an unary-expression, a postfix-expression
or something else.
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);
/* Skip tokens until the next token is a closing parenthesis.
If we find the closing `)', and the next token is a `{', then /* We may be looking at a cast-expression. */
we are looking at a compound-literal. */ cast_expression_p
compound_literal_p
= (cp_parser_skip_to_closing_parenthesis (parser, false, false, = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
/*consume_paren=*/true) /*consume_paren=*/true)
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); && 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 were looking at a compound-literal, simulate an error /* If we aren't looking at a cast-expression, simulate an error so
so that the call to cp_parser_parse_definitely below will that the call to cp_parser_parse_definitely below will fail. */
fail. */ if (!cast_expression_p)
if (compound_literal_p)
cp_parser_simulate_error (parser); cp_parser_simulate_error (parser);
else else
{ {
@ -7637,8 +7664,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
/* At this point this can only be either a cast or a /* At this point this can only be either a cast or a
parenthesized ctor such as `(T ())' that looks like a cast to parenthesized ctor such as `(T ())' that looks like a cast to
function returning T. */ function returning T. */
if (!cp_parser_error_occurred (parser) if (!cp_parser_error_occurred (parser))
&& cp_parser_tokens_start_cast_expression (parser))
{ {
cp_parser_parse_definitely (parser); cp_parser_parse_definitely (parser);
expr = cp_parser_cast_expression (parser, expr = cp_parser_cast_expression (parser,

View File

@ -1,3 +1,10 @@
2013-11-02 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/29234
PR c++/56037
* g++.dg/parse/pr29234.C: New.
* g++.dg/parse/pr56037.C: Likewise.
2013-11-01 Balaji V. Iyer <balaji.v.iyer@intel.com> 2013-11-01 Balaji V. Iyer <balaji.v.iyer@intel.com>
* gcc.dg/cilk-plus/cilk-plus.exp: Loaded libcilkrts library path and * gcc.dg/cilk-plus/cilk-plus.exp: Loaded libcilkrts library path and

View File

@ -0,0 +1,16 @@
// PR c++/29234
struct S { void operator()(); };
void foo ()
{
( S()() );
}
struct C { void operator[](C); };
void bar ()
{
C x;
( C()[x] );
}

View File

@ -0,0 +1,12 @@
// PR c++/56037
struct T
{
T(int, int);
};
int main()
{
static const int zero = 0;
(T(int(zero), int(zero)));
}