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


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

Patch: PR java/1414


A long time ago I submitted a patch for PR 1414 (used to be PR 383).
This PR concerns the fact that duplicate case labels aren't detected
in `-C' mode.  (And since then `--syntax-only' mode has also stopped
detecting duplicates.)

This patch was approved, but it was a bit hacky, and I think that Per
didn't like it either (though I was unable to dig up his message
explaining why).  Anyway, I never checked the patch in.

Today I rewrote the patch to be cleaner.  Now instead of checking
duplicates in the bytecode generator we detect them in the front end.

I verified this on the test cases in the PR and by using it to rebuild
libgcj.

This patch isn't perfect.  It introduces a new global.  Ideally I
think we'd store the case label information in an easier-to-handle way
directly on the switch itself.  Doing that looked hard though :-(.  I
also looked into simply adding a list on the side (as this patch does)
to the switch, but I don't think that is possible.

Is this patch ok?

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	Patch for PR java/1414:
	* parse.y (case_label_list): New global.
	(goal): Register case_label_list with GC.
	(java_complete_lhs): Save new case on case_label_list.
	(patch_switch_statement): Check for duplicate case labels.

Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.91
diff -u -r1.91 jcf-write.c
--- jcf-write.c 2001/10/11 23:50:49 1.91
+++ jcf-write.c 2001/11/07 20:41:31
@@ -1757,7 +1757,8 @@
 		    gap_start--;
 		  }
 		relocs[gap_start++] = reloc;
-		/* Note we don't check for duplicates.  FIXME! */
+		/* Note we don't check for duplicates.  This is
+		   handled by the parser.  */
 	      }
 
 	    if (2 * sw_state.num_cases
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.321
diff -u -r1.321 parse.y
--- parse.y 2001/10/11 23:50:48 1.321
+++ parse.y 2001/11/07 20:41:44
@@ -423,6 +423,13 @@
    the list of the catch clauses of the currently analysed try block. */
 static tree currently_caught_type_list;
 
+/* This holds a linked list of all the case labels for the current
+   switch statement.  It is only used when checking to see if there
+   are duplicate labels.  FIXME: probably this should just be attached
+   to the switch itself; then it could be referenced via
+   `ctxp->current_loop'.  */
+static tree case_label_list; 
+
 static tree src_parse_roots[1] = { NULL_TREE };
 
 /* All classes seen from source code */
@@ -623,6 +630,7 @@
 		  ggc_add_tree_root (&package_list, 1);
 		  ggc_add_tree_root (&current_this, 1);
 		  ggc_add_tree_root (&currently_caught_type_list, 1);
+		  ggc_add_tree_root (&case_label_list, 1);
 		  ggc_add_root (&ctxp, 1, 
 				sizeof (struct parser_ctxt *),
 				mark_parser_ctxt);
@@ -11647,10 +11655,13 @@
       cn = fold (convert (int_type_node, cn));
       TREE_CONSTANT_OVERFLOW (cn) = 0;
       CAN_COMPLETE_NORMALLY (cn) = 1;
+
+      /* Save the label on a list so that we can later check for
+	 duplicates.  */
+      case_label_list = tree_cons (node, cn, case_label_list);
 
-      /* Multiple instance of a case label bearing the same
-	 value is checked during code generation. The case
-	 expression is allright so far. */
+      /* Multiple instance of a case label bearing the same value is
+	 checked later. The case expression is all right so far. */
       if (TREE_CODE (cn) == VAR_DECL)
 	cn = DECL_INITIAL (cn);
       TREE_OPERAND (node, 0) = cn;
@@ -15415,6 +15426,7 @@
      tree node;
 {
   tree se = TREE_OPERAND (node, 0), se_type;
+  tree save, iter;
 
   /* Complete the switch expression */
   se = TREE_OPERAND (node, 0) = java_complete_tree (se);
@@ -15432,7 +15444,42 @@
       return error_mark_node;
     }
 
+  /* Save and restore the outer case label list.  */
+  save = case_label_list;
+  case_label_list = NULL_TREE;
+
   TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1));
+
+  /* See if we've found a duplicate label.  We can't leave this until
+     code generation, because in `--syntax-only' and `-C' modes we
+     don't do ordinary code generation.  */
+  for (iter = case_label_list; iter != NULL_TREE; iter = TREE_CHAIN (iter))
+    {
+      HOST_WIDE_INT val = TREE_INT_CST_LOW (TREE_VALUE (iter));
+      tree subiter;
+      for (subiter = TREE_CHAIN (iter);
+	   subiter != NULL_TREE;
+	   subiter = TREE_CHAIN (subiter))
+	{
+	  HOST_WIDE_INT subval = TREE_INT_CST_LOW (TREE_VALUE (subiter));
+	  if (val == subval)
+	    {
+	      EXPR_WFL_LINECOL (wfl_operator)
+		= EXPR_WFL_LINECOL (TREE_PURPOSE (iter));
+	      /* The case_label_list is in reverse order, so print the
+		 outer label first.  */
+	      parse_error_context (wfl_operator, "duplicate case label: `%d'",
+				   subval);
+	      EXPR_WFL_LINECOL (wfl_operator)
+		= EXPR_WFL_LINECOL (TREE_PURPOSE (subiter));
+	      parse_error_context (wfl_operator, "original label is here");
+
+	      break;
+	    }
+	}
+    }
+
+  case_label_list = save;
 
   /* Ready to return */
   if (TREE_CODE (TREE_OPERAND (node, 1)) == ERROR_MARK)


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