2007-03-03 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
authormanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Mar 2007 15:32:13 +0000 (15:32 +0000)
committermanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Mar 2007 15:32:13 +0000 (15:32 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122505 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/else-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/else.C [new file with mode: 0644]

index 3319d7b..5349dc4 100644 (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
index b8af4d2..f21ad7b 100644 (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");
index e2d41a9..2b4a696 100644 (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>
 
diff --git a/gcc/testsuite/g++.dg/parse/else-2.C b/gcc/testsuite/g++.dg/parse/else-2.C
new file mode 100644 (file)
index 0000000..7f0b23c
--- /dev/null
@@ -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 (file)
index 0000000..87ea982
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options " " }
+
+int f()
+{
+  if (1)
+    {
+      return 1;
+  else  // { dg-error "expected .\}. before 'else'" }
+    {
+      return 0;
+    }
+}