aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel López-Ibáñez <manu@gcc.gnu.org>2007-03-03 15:32:13 +0000
committerManuel López-Ibáñez <manu@gcc.gnu.org>2007-03-03 15:32:13 +0000
commit4606b05cd78922cf9b214471c36ef066f3fa9e50 (patch)
treea37e403d644d8673beafbffae9500ca26a0f8fd2
parent9f1fd47476f8b7cfb1d14e7409b73b38a892cad3 (diff)
downloadgcc-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/ChangeLog11
-rw-r--r--gcc/cp/parser.c29
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/parse/else-2.C11
-rw-r--r--gcc/testsuite/g++.dg/parse/else.C13
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;
+ }
+}