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
parent 9f1fd474
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> 2007-03-02 Simon Martin <simartin@users.sourceforge.net>
PR c++/28253 PR c++/28253
......
...@@ -1410,6 +1410,7 @@ typedef struct cp_parser GTY(()) ...@@ -1410,6 +1410,7 @@ typedef struct cp_parser GTY(())
#define IN_ITERATION_STMT 2 #define IN_ITERATION_STMT 2
#define IN_OMP_BLOCK 4 #define IN_OMP_BLOCK 4
#define IN_OMP_FOR 8 #define IN_OMP_FOR 8
#define IN_IF_STMT 16
unsigned char in_statement; unsigned char in_statement;
/* TRUE if we are presently parsing the body of a switch 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) ...@@ -6538,6 +6539,19 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
|| token->type == CPP_EOF || token->type == CPP_EOF
|| token->type == CPP_PRAGMA_EOL) || token->type == CPP_PRAGMA_EOL)
break; 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. */ /* Parse the statement. */
cp_parser_statement (parser, in_statement_expr, true, NULL); cp_parser_statement (parser, in_statement_expr, true, NULL);
...@@ -6603,12 +6617,17 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) ...@@ -6603,12 +6617,17 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
if (keyword == RID_IF) if (keyword == RID_IF)
{ {
bool nested_if; bool nested_if;
unsigned char in_statement;
/* Add the condition. */ /* Add the condition. */
finish_if_stmt_cond (condition, statement); finish_if_stmt_cond (condition, statement);
/* Parse the then-clause. */ /* Parse the then-clause. */
in_statement = parser->in_statement;
parser->in_statement |= IN_IF_STMT;
cp_parser_implicitly_scoped_statement (parser, &nested_if); cp_parser_implicitly_scoped_statement (parser, &nested_if);
parser->in_statement = in_statement;
finish_then_clause (statement); finish_then_clause (statement);
/* If the next token is `else', parse the else-clause. */ /* If the next token is `else', parse the else-clause. */
...@@ -6954,6 +6973,7 @@ cp_parser_jump_statement (cp_parser* parser) ...@@ -6954,6 +6973,7 @@ cp_parser_jump_statement (cp_parser* parser)
tree statement = error_mark_node; tree statement = error_mark_node;
cp_token *token; cp_token *token;
enum rid keyword; enum rid keyword;
unsigned char in_statement;
/* Peek at the next token. */ /* Peek at the next token. */
token = cp_parser_require (parser, CPP_KEYWORD, "jump-statement"); token = cp_parser_require (parser, CPP_KEYWORD, "jump-statement");
...@@ -6965,14 +6985,15 @@ cp_parser_jump_statement (cp_parser* parser) ...@@ -6965,14 +6985,15 @@ cp_parser_jump_statement (cp_parser* parser)
switch (keyword) switch (keyword)
{ {
case RID_BREAK: case RID_BREAK:
switch (parser->in_statement) in_statement = parser->in_statement & ~IN_IF_STMT;
switch (in_statement)
{ {
case 0: case 0:
error ("break statement not within loop or switch"); error ("break statement not within loop or switch");
break; break;
default: default:
gcc_assert ((parser->in_statement & IN_SWITCH_STMT) gcc_assert ((in_statement & IN_SWITCH_STMT)
|| parser->in_statement == IN_ITERATION_STMT); || in_statement == IN_ITERATION_STMT);
statement = finish_break_stmt (); statement = finish_break_stmt ();
break; break;
case IN_OMP_BLOCK: case IN_OMP_BLOCK:
...@@ -6986,7 +7007,7 @@ cp_parser_jump_statement (cp_parser* parser) ...@@ -6986,7 +7007,7 @@ cp_parser_jump_statement (cp_parser* parser)
break; break;
case RID_CONTINUE: case RID_CONTINUE:
switch (parser->in_statement & ~IN_SWITCH_STMT) switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
{ {
case 0: case 0:
error ("continue statement not within a loop"); error ("continue statement not within a loop");
......
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> 2007-03-03 Paul Thomas <pault@gcc.gnu.org>
Tobias Burnus <burnus@net-b.de> Tobias Burnus <burnus@net-b.de>
// { dg-do compile }
// { dg-options " " }
int f()
{
else // { dg-error "'else' without a previous 'if'" }
{
return 0;
}
}
// { dg-do compile }
// { dg-options " " }
int f()
{
if (1)
{
return 1;
else // { dg-error "expected .\}. before 'else'" }
{
return 0;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment