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
This commit is contained in:
Manuel López-Ibáñez 2007-03-03 15:32:13 +00:00
parent 9f1fd47476
commit 4606b05cd7
5 changed files with 66 additions and 4 deletions

View file

@ -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

View file

@ -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");

View file

@ -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>

View file

@ -0,0 +1,11 @@
// { dg-do compile }
// { dg-options " " }
int f()
{
else // { dg-error "'else' without a previous 'if'" }
{
return 0;
}
}

View file

@ -0,0 +1,13 @@
// { dg-do compile }
// { dg-options " " }
int f()
{
if (1)
{
return 1;
else // { dg-error "expected .\}. before 'else'" }
{
return 0;
}
}