This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [RFC] PR c/23722 bad error recovery with if blocks and else
:ADDPATCH c:
A much nicer version of the patch. Also, using explicit locations as
Tom requested.
Bootstrapped and regression tested. OK to commit?
2007-11-22 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/23722
* c-parser.c (struct c_parser): New bit in_if_stmt.
(c_parser_compound_statement_nostart): Handle unexpected 'else' keyword.
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.
Index: gcc/testsuite/gcc.dg/parse-else-error.c
===================================================================
--- gcc/testsuite/gcc.dg/parse-else-error.c (revision 0)
+++ gcc/testsuite/gcc.dg/parse-else-error.c (revision 0)
@@ -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'" } */
+ {
+ }
+}
Index: gcc/testsuite/gcc.dg/parse-else-error-3.c
===================================================================
--- gcc/testsuite/gcc.dg/parse-else-error-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/parse-else-error-3.c (revision 0)
@@ -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;
+ }
+}
Index: gcc/testsuite/gcc.dg/cpp/19990413-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/19990413-1.c (revision 130174)
+++ gcc/testsuite/gcc.dg/cpp/19990413-1.c (working copy)
@@ -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 } } */
}
Index: gcc/testsuite/gcc.dg/parse-else-error-2.c
===================================================================
--- gcc/testsuite/gcc.dg/parse-else-error-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/parse-else-error-2.c (revision 0)
@@ -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" } */
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c (revision 130174)
+++ gcc/c-parser.c (working copy)
@@ -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 processing the body of an if statement. */
+ BOOL_BITFIELD in_if_stmt : 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_p
c_parser_error (parser, "expected declaration or statement");
return;
}
+ else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+ {
+ if (parser->in_if_stmt)
+ {
+ error ("%H""expected %<}%> before %<else%>", &loc);
+ return;
+ }
+ else
+ {
+ error ("%H%<else%> without a previous %<if%>", &loc);
+ c_parser_consume_token (parser);
+ continue;
+ }
+ }
else
{
statement:
@@ -3915,7 +3931,11 @@ c_parser_c99_block_statement (c_parser *
static tree
c_parser_if_body (c_parser *parser, bool *if_p)
{
- tree block = c_begin_compound_stmt (flag_isoc99);
+ tree block;
+ bool in_if_stmt = parser->in_if_stmt;
+
+ parser->in_if_stmt = true;
+ 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)
@@ -3925,6 +3945,7 @@ c_parser_if_body (c_parser *parser, bool
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
add_stmt (build_empty_stmt ());
c_parser_statement_after_labels (parser);
+ parser->in_if_stmt = in_if_stmt;
return c_end_compound_stmt (block, flag_isoc99);
}