mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 17:30:54 +08:00
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:
parent
0e7edcd5eb
commit
b4b560332c
@ -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++
|
||||
|
@ -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;
|
||||
|
@ -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++
|
||||
|
@ -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 } } */
|
||||
}
|
||||
|
13
gcc/testsuite/gcc.dg/parse-else-error-2.c
Normal file
13
gcc/testsuite/gcc.dg/parse-else-error-2.c
Normal 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" } */
|
11
gcc/testsuite/gcc.dg/parse-else-error-3.c
Normal file
11
gcc/testsuite/gcc.dg/parse-else-error-3.c
Normal 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;
|
||||
}
|
||||
}
|
14
gcc/testsuite/gcc.dg/parse-else-error-4.c
Normal file
14
gcc/testsuite/gcc.dg/parse-else-error-4.c
Normal 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'" } */
|
||||
}
|
||||
}
|
12
gcc/testsuite/gcc.dg/parse-else-error.c
Normal file
12
gcc/testsuite/gcc.dg/parse-else-error.c
Normal 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'" } */
|
||||
{
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user