This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix PR c/9262


> I talked to Mark about this and we figured out the history of these
> changes.  Basically, when the C front end was converted to
> function-at-a-time mode it was intended that these problems be caught
> much earlier, during parsing instead of RTL generation, and that
> add_case_node would never see ill-formed trees like this.  That is
> presently the case for the C++ front end -- if you run your test case
> through cc1plus you'll see it gives (too many) error messages but does
> not crash -- but not for the C front end.

Ok.

> First, please try to change the C parser so that it does not add case
> labels to the chain of statements if there is no enclosing SWITCH_STMT.
> This may be impractical.

But there is an enclosing SWITCH_STMT by the time the case label is added to 
the chain. Otherwise the parse error "not within a switch statement" would 
trigger and the case label would not be added.

The problem is that the parser chains the case labels to the SWITCH_STMT 
itself, not to its SWITCH_BODY. And it's up to c-typeck.c:c_finish_case() to 
rechain them to the latter. Therefore, if the function is not called (as it 
is the case for this PR), there are never rechained and we end up passing a 
SWITCH_STMT with an empty SWITCH_BODY to add_case_node(), which doesn't like 
that at all.

The straightforward solution that consists in rechaining the labels on the 
first addition seems to work. I just had to modify a few line numbers for 
-Wswitch warnings in three testcases.

Bootstrapped/regtested on i586-redhat-linux-gnu (c,c++,objc,f77). Ok for 
mainline?

-- 
Eric Botcazou


2003-02-21  Eric Botcazou  <ebotcazou at libertysurf dot fr>

	PR c/9262
	* c-typeck.c (do_case): Attach the first case label to the SWITCH_BODY.
	(c_finish_case): Rechain the next statements to the SWITCH_STMT.


2003-02-21  Eric Botcazou  <ebotcazou at libertysurf dot fr>

	* gcc.dg/switch-2.c: New test.
	* gcc.dg/switch-3.c: New test.
	* gcc.dg/Wswitch.c: Adjust line numbers.
	* gcc.dg/Wswitch-default.c: Likewise.
	* gcc.dg/Wswitch-enum.c: Likewise.
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.220
diff -u -p -r1.220 c-typeck.c
--- c-typeck.c	19 Feb 2003 00:51:16 -0000	1.220
+++ c-typeck.c	21 Feb 2003 12:07:59 -0000
@@ -7179,11 +7179,19 @@ do_case (low_value, high_value)
 
   if (switch_stack)
     {
+      bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE);
+
       label = c_add_case_label (switch_stack->cases, 
 				SWITCH_COND (switch_stack->switch_stmt), 
 				low_value, high_value);
       if (label == error_mark_node)
 	label = NULL_TREE;
+      else if (switch_was_empty_p)
+	{
+	  /* Attach the first case label to the SWITCH_BODY.  */
+	  SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt);
+	  TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE;
+	}
     }
   else if (low_value)
     error ("case label not within a switch statement");
@@ -7200,7 +7208,8 @@ c_finish_case ()
 {
   struct c_switch *cs = switch_stack;
 
-  RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt)); 
+  /* Rechain the next statements to the SWITCH_STMT.  */
+  last_tree = cs->switch_stmt;
 
   /* Pop the stack.  */
   switch_stack = switch_stack->next;
/* PR c/9262 */
/* Originator: Rasmus Hahn <rassahah at neofonie dot de> */
/* { dg-do compile } */

int foo(int i)
{
  switch (i)
    case 3:
      return 1,
}  /* { dg-error "(parse|syntax) error" } */
/* PR c/9262 */
/* Originator: Rasmus Hahn <rassahah at neofonie dot de> */
/* { dg-do compile } */

int foo(int i)
{
  switch (i)
    case 3:
      return 1;
    case 4:      /* { dg-error "not within a switch statement" } */
      return 1;
}
Index: testsuite/gcc.dg/Wswitch.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/Wswitch.c,v
retrieving revision 1.2
diff -u -p -r1.2 Wswitch.c
--- testsuite/gcc.dg/Wswitch.c	4 Feb 2002 22:05:15 -0000	1.2
+++ testsuite/gcc.dg/Wswitch.c	21 Feb 2003 11:51:05 -0000
@@ -19,9 +19,9 @@ foo (int i, int j, enum e ei, enum e ej,
     case 4: return 3;
     default: break;
     }
-  switch (ei)
-    { /* { dg-warning "enumeration value `e1' not handled in switch" "enum e1" } */
-    } /* { dg-warning "enumeration value `e2' not handled in switch" "enum e2" { target *-*-* } 23 } */
+  switch (ei) /* { dg-warning "enumeration value `e1' not handled in switch" "enum e1" } */
+    { /*{ dg-warning "enumeration value `e2' not handled in switch" "enum e2" { target *-*-* } 22 } */
+    }
   switch (ej)
     {
     default: break;
Index: testsuite/gcc.dg/Wswitch-default.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/Wswitch-default.c,v
retrieving revision 1.1
diff -u -p -r1.1 Wswitch-default.c
--- testsuite/gcc.dg/Wswitch-default.c	23 Mar 2002 16:33:44 -0000	1.1
+++ testsuite/gcc.dg/Wswitch-default.c	21 Feb 2003 11:51:28 -0000
@@ -18,8 +18,8 @@ foo (int i, int j, enum e ei, enum e ej,
     case 4: return 3;
     default: break;
     }
-  switch (ei)
-    { /* { dg-warning "switch missing default case" } */
+  switch (ei) /* { dg-warning "switch missing default case" } */
+    {
     }
   switch (ej)
     {
Index: testsuite/gcc.dg/Wswitch-enum.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/Wswitch-enum.c,v
retrieving revision 1.1
diff -u -p -r1.1 Wswitch-enum.c
--- testsuite/gcc.dg/Wswitch-enum.c	26 Mar 2002 15:36:37 -0000	1.1
+++ testsuite/gcc.dg/Wswitch-enum.c	21 Feb 2003 11:51:51 -0000
@@ -19,9 +19,9 @@ foo (int i, int j, enum e ei, enum e ej,
     case 4: return 3;
     default: break;
     }
-  switch (ei)
-    { /* { dg-warning "enumeration value `e1' not handled in switch" "enum e1" } */
-    } /* { dg-warning "enumeration value `e2' not handled in switch" "enum e2" { target *-*-* } 23 } */
+  switch (ei) /* { dg-warning "enumeration value `e1' not handled in switch" "enum e1" } */
+    { /* { dg-warning "enumeration value `e2' not handled in switch" "enum e2" { target *-*-* } 22 } */
+    }
   switch (ej)
     { /* { dg-warning "enumeration value `e1' not handled in switch" "enum e1" { target *-*-* } 28 } */
     default: break;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]