summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authormanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>2007-11-26 19:01:54 +0000
committermanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>2007-11-26 19:01:54 +0000
commit10c93a350ac625f7e49f1aa87d4b2838ead89f43 (patch)
tree3aa88863b57e5e2d234313c7a65fb6d464e0d2ee /gcc
parent64f91bdc6c66b1bc7b832cb4cb296ed424f1867c (diff)
downloadgcc-10c93a350ac625f7e49f1aa87d4b2838ead89f43.tar.gz
2007-11-26 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/23722 * c-parser.c (struct c_parser): New bit in_if_block. (c_parser_compound_statement_nostart): Handle unexpected 'else' keyword. (c_parser_statement_after_labels): Set in_if_block to false while parsing. (c_parser_if_body): Don't call c_parser_statement_after_labels if a semicolon is found, just consume it. Don't call c_parser_statement_after_labels if an open brace is found, call c_parser_compound_statement instead. (c_parser_else_body): New. (c_parser_if_statement): Set in_if_block to true when parsing the body of the 'if' statement. Use c_parser_else_body. testsuite/ * gcc.dg/cpp/19990413-1.c: Update. * gcc.dg/parse-else-error.c: New. * gcc.dg/parse-else-error-2.c: New. * gcc.dg/parse-else-error-3.c: New. * gcc.dg/parse-else-error-4.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@130446 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/c-parser.c74
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.dg/cpp/19990413-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/parse-else-error-2.c13
-rw-r--r--gcc/testsuite/gcc.dg/parse-else-error-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/parse-else-error-4.c14
-rw-r--r--gcc/testsuite/gcc.dg/parse-else-error.c12
8 files changed, 141 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 41aaf4b3ba8..d475e408985 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+2007-11-26 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
+ PR c/23722
+ * c-parser.c (struct c_parser): New bit in_if_block.
+ (c_parser_compound_statement_nostart): Handle unexpected 'else'
+ keyword.
+ (c_parser_statement_after_labels): Set in_if_block to false while
+ parsing.
+ (c_parser_if_body): Don't call c_parser_statement_after_labels if
+ a semicolon is found, just consume it. Don't call
+ c_parser_statement_after_labels if an open brace is found, call
+ c_parser_compound_statement instead.
+ (c_parser_else_body): New.
+ (c_parser_if_statement): Set in_if_block to true when parsing the
+ body of the 'if' statement. Use c_parser_else_body.
+
2007-11-26 Andreas Krebbel <krebbel1@de.ibm.com>
PR 34081/C++
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 529354701a4..1e32b5b9d98 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -280,6 +280,8 @@ typedef struct c_parser GTY(())
/* True if we're processing a pragma, and shouldn't automatically
consume CPP_PRAGMA_EOL. */
BOOL_BITFIELD in_pragma : 1;
+ /* True if we're parsing the outermost block of an if statement. */
+ BOOL_BITFIELD in_if_block : 1;
/* True if we want to lex an untranslated string. */
BOOL_BITFIELD lex_untranslated_string : 1;
/* Objective-C specific parser/lexer information. */
@@ -3541,6 +3543,20 @@ c_parser_compound_statement_nostart (c_parser *parser)
c_parser_error (parser, "expected declaration or statement");
return;
}
+ else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+ {
+ if (parser->in_if_block)
+ {
+ error ("%H""expected %<}%> before %<else%>", &loc);
+ return;
+ }
+ else
+ {
+ error ("%H%<else%> without a previous %<if%>", &loc);
+ c_parser_consume_token (parser);
+ continue;
+ }
+ }
else
{
statement:
@@ -3740,6 +3756,8 @@ c_parser_statement_after_labels (c_parser *parser)
{
location_t loc = c_parser_peek_token (parser)->location;
tree stmt = NULL_TREE;
+ bool in_if_block = parser->in_if_block;
+ parser->in_if_block = false;
switch (c_parser_peek_token (parser)->type)
{
case CPP_OPEN_BRACE:
@@ -3873,6 +3891,8 @@ c_parser_statement_after_labels (c_parser *parser)
earlier? */
if (stmt && CAN_HAVE_LOCATION_P (stmt))
SET_EXPR_LOCATION (stmt, loc);
+
+ parser->in_if_block = in_if_block;
}
/* Parse a parenthesized condition from an if, do or while statement.
@@ -3906,11 +3926,13 @@ c_parser_c99_block_statement (c_parser *parser)
return c_end_compound_stmt (block, flag_isoc99);
}
-/* Parse the body of an if statement or the else half thereof. This
- is just parsing a statement but (a) it is a block in C99, (b) we
- track whether the body is an if statement for the sake of
- -Wparentheses warnings, (c) we handle an empty body specially for
- the sake of -Wempty-body warnings. */
+/* Parse the body of an if statement. This is just parsing a
+ statement but (a) it is a block in C99, (b) we track whether the
+ body is an if statement for the sake of -Wparentheses warnings, (c)
+ we handle an empty body specially for the sake of -Wempty-body
+ warnings, and (d) we call parser_compound_statement directly
+ because c_parser_statement_after_labels resets
+ parser->in_if_block. */
static tree
c_parser_if_body (c_parser *parser, bool *if_p)
@@ -3923,8 +3945,37 @@ c_parser_if_body (c_parser *parser, bool *if_p)
c_parser_label (parser);
*if_p = c_parser_next_token_is_keyword (parser, RID_IF);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- add_stmt (build_empty_stmt ());
- c_parser_statement_after_labels (parser);
+ {
+ add_stmt (build_empty_stmt ());
+ c_parser_consume_token (parser);
+ }
+ else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+ add_stmt (c_parser_compound_statement (parser));
+ else
+ c_parser_statement_after_labels (parser);
+ return c_end_compound_stmt (block, flag_isoc99);
+}
+
+/* Parse the else body of an if statement. This is just parsing a
+ statement but (a) it is a block in C99, (b) we handle an empty body
+ specially for the sake of -Wempty-body warnings. */
+
+static tree
+c_parser_else_body (c_parser *parser)
+{
+ tree block = c_begin_compound_stmt (flag_isoc99);
+ while (c_parser_next_token_is_keyword (parser, RID_CASE)
+ || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+ || (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+ c_parser_label (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ add_stmt (build_empty_stmt ());
+ c_parser_consume_token (parser);
+ }
+ else
+ c_parser_statement_after_labels (parser);
return c_end_compound_stmt (block, flag_isoc99);
}
@@ -3941,18 +3992,23 @@ c_parser_if_statement (c_parser *parser)
tree block;
location_t loc;
tree cond;
- bool first_if = false, second_if = false;
+ bool first_if = false;
tree first_body, second_body;
+ bool in_if_block;
+
gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
c_parser_consume_token (parser);
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
cond = c_parser_paren_condition (parser);
+ in_if_block = parser->in_if_block;
+ parser->in_if_block = true;
first_body = c_parser_if_body (parser, &first_if);
+ parser->in_if_block = in_if_block;
if (c_parser_next_token_is_keyword (parser, RID_ELSE))
{
c_parser_consume_token (parser);
- second_body = c_parser_if_body (parser, &second_if);
+ second_body = c_parser_else_body (parser);
}
else
second_body = NULL_TREE;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 05e3960c5d6..5ca77e8a70e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2007-11-26 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
+ PR c/23722
+ * gcc.dg/cpp/19990413-1.c: Update.
+ * gcc.dg/parse-else-error.c: New.
+ * gcc.dg/parse-else-error-2.c: New.
+ * gcc.dg/parse-else-error-3.c: New.
+ * gcc.dg/parse-else-error-4.c: New.
+
2007-11-26 Andreas Krebbel <krebbel1@de.ibm.com>
PR 34081/C++
diff --git a/gcc/testsuite/gcc.dg/cpp/19990413-1.c b/gcc/testsuite/gcc.dg/cpp/19990413-1.c
index 61d8ad6550d..17d8441e8e6 100644
--- a/gcc/testsuite/gcc.dg/cpp/19990413-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/19990413-1.c
@@ -9,5 +9,5 @@ func(void)
{
FOO(i
= 4)
- else; /* { dg-error "parse error|syntax error|expected" "error on this line" { target *-*-* } { 12 } } */
+ else; /* { dg-error "'else' without a previous 'if'" "error on this line" { target *-*-* } { 12 } } */
}
diff --git a/gcc/testsuite/gcc.dg/parse-else-error-2.c b/gcc/testsuite/gcc.dg/parse-else-error-2.c
new file mode 100644
index 00000000000..ce59af3813e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parse-else-error-2.c
@@ -0,0 +1,13 @@
+/* PR 23722 */
+/* { dg-do compile } */
+/* { dg-options "-fsyntax-only" } */
+int f()
+{
+ if (1)
+ {
+ return 1;
+ else /* { dg-error "expected .\}. before 'else'" } */
+ {
+ }
+ }
+} /* { dg-error "expected identifier or '\\(' before .\}. token" } */
diff --git a/gcc/testsuite/gcc.dg/parse-else-error-3.c b/gcc/testsuite/gcc.dg/parse-else-error-3.c
new file mode 100644
index 00000000000..13666f595dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parse-else-error-3.c
@@ -0,0 +1,11 @@
+/* PR 23722 */
+/* { dg-do compile } */
+/* { dg-options "-fsyntax-only" } */
+int f()
+{
+
+ else /* { dg-error "'else' without a previous 'if'" } */
+ {
+ return 0;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/parse-else-error-4.c b/gcc/testsuite/gcc.dg/parse-else-error-4.c
new file mode 100644
index 00000000000..617c3f3e3f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parse-else-error-4.c
@@ -0,0 +1,14 @@
+/* PR 23722 */
+/* { dg-do compile } */
+/* { dg-options "-fsyntax-only" } */
+int f()
+{
+ if (1)
+ {
+ return 1;
+ }
+ else
+ {
+ else; /* { dg-error "'else' without a previous 'if'" } */
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/parse-else-error.c b/gcc/testsuite/gcc.dg/parse-else-error.c
new file mode 100644
index 00000000000..ca20bdf9ff6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parse-else-error.c
@@ -0,0 +1,12 @@
+/* PR 23722 */
+/* { dg-do compile } */
+/* { dg-options "-fsyntax-only" } */
+int f()
+{
+ if (1)
+ {
+ return 1;
+ else /* { dg-error "expected .\}. before 'else'" } */
+ {
+ }
+}