diff options
author | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-11-26 19:01:54 +0000 |
---|---|---|
committer | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-11-26 19:01:54 +0000 |
commit | 10c93a350ac625f7e49f1aa87d4b2838ead89f43 (patch) | |
tree | 3aa88863b57e5e2d234313c7a65fb6d464e0d2ee /gcc | |
parent | 64f91bdc6c66b1bc7b832cb4cb296ed424f1867c (diff) | |
download | gcc-10c93a350ac625f7e49f1aa87d4b2838ead89f43.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@130446 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/c-parser.c | 74 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/19990413-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/parse-else-error-2.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/parse-else-error-3.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/parse-else-error-4.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/parse-else-error.c | 12 |
8 files changed, 141 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41aaf4b3ba8..d475e408985 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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++ diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 529354701a4..1e32b5b9d98 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 05e3960c5d6..5ca77e8a70e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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++ diff --git a/gcc/testsuite/gcc.dg/cpp/19990413-1.c b/gcc/testsuite/gcc.dg/cpp/19990413-1.c index 61d8ad6550d..17d8441e8e6 100644 --- a/gcc/testsuite/gcc.dg/cpp/19990413-1.c +++ b/gcc/testsuite/gcc.dg/cpp/19990413-1.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 } } */ } diff --git a/gcc/testsuite/gcc.dg/parse-else-error-2.c b/gcc/testsuite/gcc.dg/parse-else-error-2.c new file mode 100644 index 00000000000..ce59af3813e --- /dev/null +++ b/gcc/testsuite/gcc.dg/parse-else-error-2.c @@ -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" } */ diff --git a/gcc/testsuite/gcc.dg/parse-else-error-3.c b/gcc/testsuite/gcc.dg/parse-else-error-3.c new file mode 100644 index 00000000000..13666f595dd --- /dev/null +++ b/gcc/testsuite/gcc.dg/parse-else-error-3.c @@ -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; + } +} diff --git a/gcc/testsuite/gcc.dg/parse-else-error-4.c b/gcc/testsuite/gcc.dg/parse-else-error-4.c new file mode 100644 index 00000000000..617c3f3e3f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/parse-else-error-4.c @@ -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'" } */ + } +} diff --git a/gcc/testsuite/gcc.dg/parse-else-error.c b/gcc/testsuite/gcc.dg/parse-else-error.c new file mode 100644 index 00000000000..ca20bdf9ff6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/parse-else-error.c @@ -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'" } */ + { + } +} |