Patch: fix for PRs java/1343 and java/6336

Tom Tromey tromey@redhat.com
Thu May 9 18:13:00 GMT 2002


This patch fixes both PR java/1343 and PR java/6336.

It works by slightly changing the logic of how a nested class name is
chosen.  Basically, in a function context we now add a number to the
end (except in situations where we might already have a unique number
at the end).

In order for this to work properly I also had to fix parse-scan.y to
duplicate the logic.  I ended up just rewriting the naming code there,
as it seemed simplest.  Now it parallels the parse.y code in a fairly
obvious way.

I rebuilt libgcj with this on x86 with no problems.  I also ran the
test suite with no regressions.  And, it solves the problems in the
PRs.  I plan to check in the test cases in a separate patch.

Ok to commit?

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	Fix for PR java/1343, PR java/6336:
	* parse.y (make_nested_class_name): Remove extraneous `else'; fix
	formatting.  Changed return type.
	(anonymous_class_counter): Moved to top of file.
	(maybe_make_nested_class_name): Append number to class name for
	function-local classes.
	* parse-scan.y (struct class_context): New type.
	(current_class_context): New global.
	(anonymous_context, method_context): New globals.
	(push_class_context): Rewrote.
	(pop_class_context): Likewise.
	(current_class, current_class_length): Removed.
	(make_class_name_recursive): New function.
	(get_class_name): Likewise.
	(report_class_declaration): Use it.
	(report_main_declaration): Likewise.
	(reset_report): Reset current_class_context.
	(anonymous_class_creation): Pass anonymous_context to
	report_class_declaration.
	(method_declarator): Push and pop class context.
	(method_depth): New global.
	(obstack_chunk_alloc): New macro.
	(obstack_chunk_free): Likewise.

Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.377
diff -u -r1.377 parse.y
--- parse.y 7 May 2002 18:42:50 -0000 1.377
+++ parse.y 8 May 2002 04:52:58 -0000
@@ -294,7 +294,7 @@
 /* JDK 1.1 work. FIXME */
 
 static tree maybe_make_nested_class_name PARAMS ((tree));
-static void make_nested_class_name PARAMS ((tree));
+static int make_nested_class_name PARAMS ((tree));
 static void set_nested_class_simple_name_value PARAMS ((tree, int));
 static void link_nested_class_to_enclosing PARAMS ((void));
 static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *,
@@ -422,6 +422,10 @@
    `ctxp->current_loop'.  */
 static tree case_label_list; 
 
+/* Anonymous class counter. Will be reset to 1 every time a non
+   anonymous class gets created. */
+static int anonymous_class_counter = 1;
+
 static tree src_parse_roots[1];
 
 /* All classes seen from source code */
@@ -3496,24 +3500,28 @@
   return 0;
 }
 
-static void
+/* Construct a nested class name.  If the final component starts with
+   a digit, return true.  Otherwise return false.  */
+static int
 make_nested_class_name (cpc_list)
      tree cpc_list;
 {
   tree name;
 
   if (!cpc_list)
-    return;
-  else
-    make_nested_class_name (TREE_CHAIN (cpc_list));
+    return 0;
+
+  make_nested_class_name (TREE_CHAIN (cpc_list));
 
   /* Pick the qualified name when dealing with the first upmost
      enclosing class */
-  name = (TREE_CHAIN (cpc_list) ? 
-	  TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
+  name = (TREE_CHAIN (cpc_list)
+	  ? TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
   obstack_grow (&temporary_obstack,
 		IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name));
   obstack_1grow (&temporary_obstack, '$');
+
+  return ISDIGIT (IDENTIFIER_POINTER (name)[0]);
 }
 
 /* Can't redefine a class already defined in an earlier scope. */
@@ -3722,7 +3730,20 @@
 
   if (CPC_INNER_P ())
     {
-      make_nested_class_name (GET_CPC_LIST ());
+      /* If we're in a function, we must append a number to create the
+	 nested class name.  However, we don't do this if the class we
+	 are constructing is anonymous, because in that case we'll
+	 already have a number as the class name.  */
+      if (! make_nested_class_name (GET_CPC_LIST ())
+	  && current_function_decl != NULL_TREE
+	  && ! ISDIGIT (IDENTIFIER_POINTER (name)[0]))
+	{
+	  char buf[10];
+	  sprintf (buf, "%d", anonymous_class_counter);
+	  ++anonymous_class_counter;
+	  obstack_grow (&temporary_obstack, buf, strlen (buf));
+	  obstack_1grow (&temporary_obstack, '$');
+	}
       obstack_grow0 (&temporary_obstack,
 		     IDENTIFIER_POINTER (name), 
 		     IDENTIFIER_LENGTH (name));
@@ -3862,10 +3883,6 @@
   return decl;
 }
 
-/* Anonymous class counter. Will be reset to 1 every time a non
-   anonymous class gets created. */
-static int anonymous_class_counter = 1;
-
 /* Patch anonymous class CLASS, by either extending or implementing
    DEP.  */
 
Index: parse-scan.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse-scan.y,v
retrieving revision 1.21
diff -u -r1.21 parse-scan.y
--- parse-scan.y 4 Apr 2001 17:56:25 -0000 1.21
+++ parse-scan.y 9 May 2002 17:30:30 -0000
@@ -1,5 +1,5 @@
 /* Parser grammar for quick source code scan of Java(TM) language programs.
-   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
    Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
 
 This file is part of GNU CC.
@@ -43,6 +43,9 @@
 #include "obstack.h"
 #include "toplev.h"
 
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
 extern char *input_filename;
 extern FILE *finput, *out;
 
@@ -62,13 +65,9 @@
 static int absorber;
 #define USE_ABSORBER absorber = 0
 
-/* Keep track of the current class name and package name.  */
-static char *current_class;
+/* Keep track of the current package name.  */
 static const char *package_name;
 
-/* Keep track of the current inner class qualifier. */
-static int current_class_length;
-
 /* Keep track of whether things have be listed before.  */
 static int previous_output;
 
@@ -85,6 +84,22 @@
 /* Numbers anonymous classes */
 static int anonymous_count;
 
+/* This is used to record the current class context.  */
+struct class_context
+{
+  char *name;
+  struct class_context *next;
+};
+
+/* The global class context.  */
+static struct class_context *current_class_context;
+
+/* A special constant used to represent an anonymous context.  */
+static const char *anonymous_context = "ANONYMOUS";
+
+/* Count of method depth.  */
+static int method_depth; 
+
 /* Record a method declaration  */
 struct method_declarator {
   const char *method_name;
@@ -99,6 +114,9 @@
 }
 
 /* Two actions for this grammar */
+static int make_class_name_recursive PARAMS ((struct obstack *stack,
+					      struct class_context *ctx));
+static char *get_class_name PARAMS ((void));
 static void report_class_declaration PARAMS ((const char *));
 static void report_main_declaration PARAMS ((struct method_declarator *));
 static void push_class_context PARAMS ((const char *));
@@ -430,7 +448,10 @@
 
 /* 19.8.3 Productions from 8.4: Method Declarations  */
 method_declaration:
-	method_header method_body
+	method_header
+		{ ++method_depth; }
+	method_body
+		{ --method_depth; }
 ;
 
 method_header:	
@@ -923,10 +944,10 @@
 
 anonymous_class_creation:
 	NEW_TK class_type OP_TK CP_TK
-		{ report_class_declaration (NULL); }
+		{ report_class_declaration (anonymous_context); }
 	class_body         
 |	NEW_TK class_type OP_TK argument_list CP_TK
-		{ report_class_declaration (NULL); }
+		{ report_class_declaration (anonymous_context); }
 	class_body
 ;
 
@@ -1155,58 +1176,100 @@
 push_class_context (name)
     const char *name;
 {
-  /* If we already have CURRENT_CLASS set, we're in an inter
-     class. Mangle its name. */
-  if (current_class)
-    {
-      const char *p;
-      char anonymous [3];
-      int additional_length;
-      
-      /* NAME set to NULL indicates an anonymous class, which are named by
-	 numbering them. */
-      if (!name)
-	{
-	  sprintf (anonymous, "%d", ++anonymous_count);
-	  p = anonymous;
-	}
-      else
-	p = name;
-      
-      additional_length = strlen (p)+1; /* +1 for `$' */
-      current_class = xrealloc (current_class, 
-				current_class_length + additional_length + 1);
-      current_class [current_class_length] = '$';
-      strcpy (&current_class [current_class_length+1], p);
-      current_class_length += additional_length;
-    }
-  else
-    {
-      if (!name)
-	return;
-      current_class_length = strlen (name);
-      current_class = xmalloc (current_class_length+1);
-      strcpy (current_class, name);
-    }
+  struct class_context *ctx;
+
+  ctx = (struct class_context *) xmalloc (sizeof (struct class_context));
+  ctx->name = (char *) name;
+  ctx->next = current_class_context;
+  current_class_context = ctx;
 }
 
 static void
 pop_class_context ()
 {
-  /* Go back to the last `$' and cut. */
-  while (--current_class_length > 0
-        && current_class [current_class_length] != '$')
-    ;
-  if (current_class_length)
+  struct class_context *ctx;
+
+  if (current_class_context == NULL)
+    return;
+
+  ctx = current_class_context->next;
+  if (current_class_context->name != anonymous_context)
+    free (current_class_context->name);
+  free (current_class_context);
+
+  current_class_context = ctx;
+  if (current_class_context == NULL)
+    anonymous_count = 0;
+}
+
+/* Recursively construct the class name.  This is just a helper
+   function for get_class_name().  */
+static int
+make_class_name_recursive (stack, ctx)
+     struct obstack *stack;
+     struct class_context *ctx;
+{
+  if (! ctx)
+    return 0;
+
+  make_class_name_recursive (stack, ctx->next);
+
+  /* Replace an anonymous context with the appropriate counter value.  */
+  if (ctx->name == anonymous_context)
     {
-      current_class = xrealloc (current_class, current_class_length+1);
-      current_class [current_class_length] = '\0';
+      char buf[50];
+      ++anonymous_count;
+      sprintf (buf, "%d", anonymous_count);
+      ctx->name = xstrdup (buf);
     }
-  else
+
+  obstack_grow (stack, ctx->name, strlen (ctx->name));
+  obstack_1grow (stack, '$');
+
+  return ISDIGIT (ctx->name[0]);
+}
+
+/* Return a newly allocated string holding the name of the class.  */
+static char *
+get_class_name ()
+{
+  char *result;
+  int last_was_digit;
+  struct obstack name_stack;
+
+  obstack_init (&name_stack);
+
+  /* Duplicate the logic of parse.y:maybe_make_nested_class_name().  */
+  last_was_digit = make_class_name_recursive (&name_stack,
+					      current_class_context->next);
+
+  if (! last_was_digit
+      && method_depth
+      && current_class_context->name != anonymous_context)
     {
-      current_class = NULL;
-      anonymous_count = 0;
+      char buf[50];
+      ++anonymous_count;
+      sprintf (buf, "%d", anonymous_count);
+      obstack_grow (&name_stack, buf, strlen (buf));
+      obstack_1grow (&name_stack, '$');
     }
+
+  if (current_class_context->name == anonymous_context)
+    {
+      char buf[50];
+      ++anonymous_count;
+      sprintf (buf, "%d", anonymous_count);
+      current_class_context->name = xstrdup (buf);
+      obstack_grow0 (&name_stack, buf, strlen (buf));
+    }
+  else
+    obstack_grow0 (&name_stack, current_class_context->name,
+		   strlen (current_class_context->name));
+
+  result = xstrdup (obstack_finish (&name_stack));
+  obstack_free (&name_stack, NULL);
+
+  return result;
 }
 
 /* Actions defined here */
@@ -1220,17 +1283,21 @@
   push_class_context (name);
   if (flag_dump_class)
     {
+      char *name = get_class_name ();
+
       if (!previous_output)
 	{
 	  if (flag_list_filename)
 	    fprintf (out, "%s: ", input_filename);
 	  previous_output = 1;
 	}
-	
+
       if (package_name)
-	fprintf (out, "%s.%s ", package_name, current_class);
+	fprintf (out, "%s.%s ", package_name, name);
       else
-	fprintf (out, "%s ", current_class);
+	fprintf (out, "%s ", name);
+
+      free (name);
     }
 }
 
@@ -1247,14 +1314,16 @@
       && declarator->args [0] == '[' 
       && (! strcmp (declarator->args+1, "String")
 	  || ! strcmp (declarator->args + 1, "java.lang.String"))
-      && current_class)
+      && current_class_context)
     {
       if (!previous_output)
 	{
+	  char *name = get_class_name ();
 	  if (package_name)
-	    fprintf (out, "%s.%s ", package_name, current_class);
+	    fprintf (out, "%s.%s ", package_name, name);
 	  else
-	    fprintf (out, "%s", current_class);
+	    fprintf (out, "%s", name);
+	  free (name);
 	  previous_output = 1;
 	}
     }
@@ -1274,7 +1343,7 @@
 {
   previous_output = 0;
   package_name = NULL;
-  current_class = NULL;
+  current_class_context = NULL;
   complexity = 0;
 }
 



More information about the Gcc-patches mailing list