From 4606b05cd78922cf9b214471c36ef066f3fa9e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20L=C3=B3pez-Ib=C3=A1=C3=B1ez?= Date: Sat, 3 Mar 2007 15:32:13 +0000 Subject: [PATCH] re PR c++/15787 (Poor error message with if and blocks) 2007-03-03 Manuel Lopez-Ibanez PR c++/15787 * parser.c (struct cp_parser): New IN_IF_STMT. (cp_parser_statement_seq_opt): Handle an unexpected 'else', returning if parsing the body of an 'if' statement or issuing an error and continuing. (cp_parser_selection_statement): Set IN_IF_STMT bit when parsing body of 'if'. (cp_parser_jump_statement): Mask new IN_IF_STMT bit. testsuite/ * g++.dg/parse/else.C: New. * g++.dg/parse/else-2.C: New. From-SVN: r122505 --- gcc/cp/ChangeLog | 11 +++++++++++ gcc/cp/parser.c | 29 +++++++++++++++++++++++++---- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/parse/else-2.C | 11 +++++++++++ gcc/testsuite/g++.dg/parse/else.C | 13 +++++++++++++ 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/else-2.C create mode 100644 gcc/testsuite/g++.dg/parse/else.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3319d7bb74b..5349dc4abde 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2007-03-03 Manuel Lopez-Ibanez + + PR c++/15787 + * parser.c (struct cp_parser): New IN_IF_STMT. + (cp_parser_statement_seq_opt): Handle an unexpected 'else', + returning if parsing the body of an 'if' statement or issuing an + error and continuing. + (cp_parser_selection_statement): Set IN_IF_STMT bit when parsing + body of 'if'. + (cp_parser_jump_statement): Mask new IN_IF_STMT bit. + 2007-03-02 Simon Martin PR c++/28253 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b8af4d288bd..f21ad7bcb5e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1410,6 +1410,7 @@ typedef struct cp_parser GTY(()) #define IN_ITERATION_STMT 2 #define IN_OMP_BLOCK 4 #define IN_OMP_FOR 8 +#define IN_IF_STMT 16 unsigned char in_statement; /* TRUE if we are presently parsing the body of a switch statement. @@ -6538,6 +6539,19 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) || token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL) break; + + /* If we are in a compound statement and find 'else' then + something went wrong. */ + else if (token->type == CPP_KEYWORD && token->keyword == RID_ELSE) + { + if (parser->in_statement & IN_IF_STMT) + break; + else + { + token = cp_lexer_consume_token (parser->lexer); + error ("% without a previous %"); + } + } /* Parse the statement. */ cp_parser_statement (parser, in_statement_expr, true, NULL); @@ -6603,12 +6617,17 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) if (keyword == RID_IF) { bool nested_if; + unsigned char in_statement; /* Add the condition. */ finish_if_stmt_cond (condition, statement); /* Parse the then-clause. */ + in_statement = parser->in_statement; + parser->in_statement |= IN_IF_STMT; cp_parser_implicitly_scoped_statement (parser, &nested_if); + parser->in_statement = in_statement; + finish_then_clause (statement); /* If the next token is `else', parse the else-clause. */ @@ -6954,6 +6973,7 @@ cp_parser_jump_statement (cp_parser* parser) tree statement = error_mark_node; cp_token *token; enum rid keyword; + unsigned char in_statement; /* Peek at the next token. */ token = cp_parser_require (parser, CPP_KEYWORD, "jump-statement"); @@ -6965,14 +6985,15 @@ cp_parser_jump_statement (cp_parser* parser) switch (keyword) { case RID_BREAK: - switch (parser->in_statement) + in_statement = parser->in_statement & ~IN_IF_STMT; + switch (in_statement) { case 0: error ("break statement not within loop or switch"); break; default: - gcc_assert ((parser->in_statement & IN_SWITCH_STMT) - || parser->in_statement == IN_ITERATION_STMT); + gcc_assert ((in_statement & IN_SWITCH_STMT) + || in_statement == IN_ITERATION_STMT); statement = finish_break_stmt (); break; case IN_OMP_BLOCK: @@ -6986,7 +7007,7 @@ cp_parser_jump_statement (cp_parser* parser) break; case RID_CONTINUE: - switch (parser->in_statement & ~IN_SWITCH_STMT) + switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT)) { case 0: error ("continue statement not within a loop"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e2d41a9b134..2b4a6962e2e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-03-03 Manuel Lopez-Ibanez + + PR c++/15787 + * g++.dg/parse/else.C: New. + * g++.dg/parse/else-2.C: New. + 2007-03-03 Paul Thomas Tobias Burnus diff --git a/gcc/testsuite/g++.dg/parse/else-2.C b/gcc/testsuite/g++.dg/parse/else-2.C new file mode 100644 index 00000000000..7f0b23cd701 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/else-2.C @@ -0,0 +1,11 @@ +// { dg-do compile } +// { dg-options " " } + +int f() +{ + + else // { dg-error "'else' without a previous 'if'" } + { + return 0; + } +} diff --git a/gcc/testsuite/g++.dg/parse/else.C b/gcc/testsuite/g++.dg/parse/else.C new file mode 100644 index 00000000000..87ea982a81c --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/else.C @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-options " " } + +int f() +{ + if (1) + { + return 1; + else // { dg-error "expected .\}. before 'else'" } + { + return 0; + } +}