diff options
author | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2007-03-03 15:32:13 +0000 |
---|---|---|
committer | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2007-03-03 15:32:13 +0000 |
commit | 4606b05cd78922cf9b214471c36ef066f3fa9e50 (patch) | |
tree | a37e403d644d8673beafbffae9500ca26a0f8fd2 | |
parent | 9f1fd47476f8b7cfb1d14e7409b73b38a892cad3 (diff) | |
download | gcc-4606b05cd78922cf9b214471c36ef066f3fa9e50.zip gcc-4606b05cd78922cf9b214471c36ef066f3fa9e50.tar.gz gcc-4606b05cd78922cf9b214471c36ef066f3fa9e50.tar.bz2 |
re PR c++/15787 (Poor error message with if and blocks)
2007-03-03 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
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
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/parser.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/else-2.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/else.C | 13 |
5 files changed, 66 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3319d7b..5349dc4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2007-03-03 Manuel Lopez-Ibanez <manu@gcc.gnu.org> + + 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 <simartin@users.sourceforge.net> PR c++/28253 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b8af4d2..f21ad7b 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 ("%<else%> without a previous %<if%>"); + } + } /* 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 e2d41a9..2b4a696 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-03-03 Manuel Lopez-Ibanez <manu@gcc.gnu.org> + + PR c++/15787 + * g++.dg/parse/else.C: New. + * g++.dg/parse/else-2.C: New. + 2007-03-03 Paul Thomas <pault@gcc.gnu.org> Tobias Burnus <burnus@net-b.de> 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 0000000..7f0b23c --- /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 0000000..87ea982 --- /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; + } +} |