re PR c/23722 (bad error recovery with if blocks and else)

2007-11-26  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

	PR c/23722
	* c-parser.c (struct c_parser): New bit in_if_block.
	(c_parser_compound_statement_nostart): Handle unexpected 'else'
	keyword.
	(c_parser_statement_after_labels): Set in_if_block to false while
	parsing.
	(c_parser_if_body): Don't call c_parser_statement_after_labels if
	a semicolon is found, just consume it. Don't call
	c_parser_statement_after_labels if an open brace is found, call
	c_parser_compound_statement instead.
	(c_parser_else_body): New.
	(c_parser_if_statement): Set in_if_block to true when parsing the
	body of the 'if' statement. Use c_parser_else_body.

testsuite/
	* gcc.dg/cpp/19990413-1.c: Update.
	* gcc.dg/parse-else-error.c: New.
	* gcc.dg/parse-else-error-2.c: New.
	* gcc.dg/parse-else-error-3.c: New.
	* gcc.dg/parse-else-error-4.c: New.

From-SVN: r130446
This commit is contained in:
Manuel López-Ibáñez 2007-11-26 19:01:54 +00:00
parent 0e7edcd5eb
commit b4b560332c
8 changed files with 141 additions and 10 deletions

View File

@ -1,3 +1,19 @@
2007-11-26 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/23722
* c-parser.c (struct c_parser): New bit in_if_block.
(c_parser_compound_statement_nostart): Handle unexpected 'else'
keyword.
(c_parser_statement_after_labels): Set in_if_block to false while
parsing.
(c_parser_if_body): Don't call c_parser_statement_after_labels if
a semicolon is found, just consume it. Don't call
c_parser_statement_after_labels if an open brace is found, call
c_parser_compound_statement instead.
(c_parser_else_body): New.
(c_parser_if_statement): Set in_if_block to true when parsing the
body of the 'if' statement. Use c_parser_else_body.
2007-11-26 Andreas Krebbel <krebbel1@de.ibm.com>
PR 34081/C++

View File

@ -280,6 +280,8 @@ typedef struct c_parser GTY(())
/* True if we're processing a pragma, and shouldn't automatically
consume CPP_PRAGMA_EOL. */
BOOL_BITFIELD in_pragma : 1;
/* True if we're parsing the outermost block of an if statement. */
BOOL_BITFIELD in_if_block : 1;
/* True if we want to lex an untranslated string. */
BOOL_BITFIELD lex_untranslated_string : 1;
/* Objective-C specific parser/lexer information. */
@ -3541,6 +3543,20 @@ c_parser_compound_statement_nostart (c_parser *parser)
c_parser_error (parser, "expected declaration or statement");
return;
}
else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
{
if (parser->in_if_block)
{
error ("%H""expected %<}%> before %<else%>", &loc);
return;
}
else
{
error ("%H%<else%> without a previous %<if%>", &loc);
c_parser_consume_token (parser);
continue;
}
}
else
{
statement:
@ -3740,6 +3756,8 @@ c_parser_statement_after_labels (c_parser *parser)
{
location_t loc = c_parser_peek_token (parser)->location;
tree stmt = NULL_TREE;
bool in_if_block = parser->in_if_block;
parser->in_if_block = false;
switch (c_parser_peek_token (parser)->type)
{
case CPP_OPEN_BRACE:
@ -3873,6 +3891,8 @@ c_parser_statement_after_labels (c_parser *parser)
earlier? */
if (stmt && CAN_HAVE_LOCATION_P (stmt))
SET_EXPR_LOCATION (stmt, loc);
parser->in_if_block = in_if_block;
}
/* Parse a parenthesized condition from an if, do or while statement.
@ -3906,11 +3926,13 @@ c_parser_c99_block_statement (c_parser *parser)
return c_end_compound_stmt (block, flag_isoc99);
}
/* Parse the body of an if statement or the else half thereof. This
is just parsing a statement but (a) it is a block in C99, (b) we
track whether the body is an if statement for the sake of
-Wparentheses warnings, (c) we handle an empty body specially for
the sake of -Wempty-body warnings. */
/* Parse the body of an if statement. This is just parsing a
statement but (a) it is a block in C99, (b) we track whether the
body is an if statement for the sake of -Wparentheses warnings, (c)
we handle an empty body specially for the sake of -Wempty-body
warnings, and (d) we call parser_compound_statement directly
because c_parser_statement_after_labels resets
parser->in_if_block. */
static tree
c_parser_if_body (c_parser *parser, bool *if_p)
@ -3923,8 +3945,37 @@ c_parser_if_body (c_parser *parser, bool *if_p)
c_parser_label (parser);
*if_p = c_parser_next_token_is_keyword (parser, RID_IF);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
add_stmt (build_empty_stmt ());
c_parser_statement_after_labels (parser);
{
add_stmt (build_empty_stmt ());
c_parser_consume_token (parser);
}
else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
add_stmt (c_parser_compound_statement (parser));
else
c_parser_statement_after_labels (parser);
return c_end_compound_stmt (block, flag_isoc99);
}
/* Parse the else body of an if statement. This is just parsing a
statement but (a) it is a block in C99, (b) we handle an empty body
specially for the sake of -Wempty-body warnings. */
static tree
c_parser_else_body (c_parser *parser)
{
tree block = c_begin_compound_stmt (flag_isoc99);
while (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
|| (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
c_parser_label (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
add_stmt (build_empty_stmt ());
c_parser_consume_token (parser);
}
else
c_parser_statement_after_labels (parser);
return c_end_compound_stmt (block, flag_isoc99);
}
@ -3941,18 +3992,23 @@ c_parser_if_statement (c_parser *parser)
tree block;
location_t loc;
tree cond;
bool first_if = false, second_if = false;
bool first_if = false;
tree first_body, second_body;
bool in_if_block;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
c_parser_consume_token (parser);
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
cond = c_parser_paren_condition (parser);
in_if_block = parser->in_if_block;
parser->in_if_block = true;
first_body = c_parser_if_body (parser, &first_if);
parser->in_if_block = in_if_block;
if (c_parser_next_token_is_keyword (parser, RID_ELSE))
{
c_parser_consume_token (parser);
second_body = c_parser_if_body (parser, &second_if);
second_body = c_parser_else_body (parser);
}
else
second_body = NULL_TREE;

View File

@ -1,3 +1,12 @@
2007-11-26 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/23722
* gcc.dg/cpp/19990413-1.c: Update.
* gcc.dg/parse-else-error.c: New.
* gcc.dg/parse-else-error-2.c: New.
* gcc.dg/parse-else-error-3.c: New.
* gcc.dg/parse-else-error-4.c: New.
2007-11-26 Andreas Krebbel <krebbel1@de.ibm.com>
PR 34081/C++

View File

@ -9,5 +9,5 @@ func(void)
{
FOO(i
= 4)
else; /* { dg-error "parse error|syntax error|expected" "error on this line" { target *-*-* } { 12 } } */
else; /* { dg-error "'else' without a previous 'if'" "error on this line" { target *-*-* } { 12 } } */
}

View File

@ -0,0 +1,13 @@
/* PR 23722 */
/* { dg-do compile } */
/* { dg-options "-fsyntax-only" } */
int f()
{
if (1)
{
return 1;
else /* { dg-error "expected .\}. before 'else'" } */
{
}
}
} /* { dg-error "expected identifier or '\\(' before .\}. token" } */

View File

@ -0,0 +1,11 @@
/* PR 23722 */
/* { dg-do compile } */
/* { dg-options "-fsyntax-only" } */
int f()
{
else /* { dg-error "'else' without a previous 'if'" } */
{
return 0;
}
}

View File

@ -0,0 +1,14 @@
/* PR 23722 */
/* { dg-do compile } */
/* { dg-options "-fsyntax-only" } */
int f()
{
if (1)
{
return 1;
}
else
{
else; /* { dg-error "'else' without a previous 'if'" } */
}
}

View File

@ -0,0 +1,12 @@
/* PR 23722 */
/* { dg-do compile } */
/* { dg-options "-fsyntax-only" } */
int f()
{
if (1)
{
return 1;
else /* { dg-error "expected .\}. before 'else'" } */
{
}
}