From 10c93a350ac625f7e49f1aa87d4b2838ead89f43 Mon Sep 17 00:00:00 2001 From: manu Date: Mon, 26 Nov 2007 19:01:54 +0000 Subject: [PATCH] 2007-11-26 Manuel Lopez-Ibanez 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 --- gcc/ChangeLog | 16 +++++++ gcc/c-parser.c | 74 +++++++++++++++++++++++++++---- gcc/testsuite/ChangeLog | 9 ++++ gcc/testsuite/gcc.dg/cpp/19990413-1.c | 2 +- gcc/testsuite/gcc.dg/parse-else-error-2.c | 13 ++++++ gcc/testsuite/gcc.dg/parse-else-error-3.c | 11 +++++ gcc/testsuite/gcc.dg/parse-else-error-4.c | 14 ++++++ gcc/testsuite/gcc.dg/parse-else-error.c | 12 +++++ 8 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/parse-else-error-2.c create mode 100644 gcc/testsuite/gcc.dg/parse-else-error-3.c create mode 100644 gcc/testsuite/gcc.dg/parse-else-error-4.c create mode 100644 gcc/testsuite/gcc.dg/parse-else-error.c 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 + + 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 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 %", &loc); + return; + } + else + { + error ("%H% without a previous %", &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 + + 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 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'" } */ + { + } +} -- 2.11.0