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]
Other format: [Raw text]

Java: Fix PR 1262


This patch fixes PR 1262. GCJ would incorrectly override "invisible" package-private methods from a superclass in another package. The patch recognizes this case and assigns a new vtable entry for the new method. There is also some code cleanup/reorganization - a couple of static methods moved from parse.y and made extern, and "breakdown_qualified" is renamed to the clearer "split_qualified_name".

The runtime has the same bug and will require a similar patch to handle bytecode and --indirect-dispatch classes.

No regressions. OK to commit?

Bryce


2004-06-28  Bryce McKinlay  <mckinlay@redhat.com>

	PR java/1262
	* class.c (layout_class_method): Do not override package-private
	method if its in a different package.
	(split_qualified_name): Move here from parse.y. Rename from
	breakdown_qualified. Add comment.
	(in_same_package): Move here from parse.y. Add comment.
	* java-tree.h (break_down_qualified, in_same_package): Declare.
	(in_same_package): Likewise.
	* parse.y (breakdown_qualified, in_same_package): Moved to class.c.
	Callers updated.

Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.188
diff -u -r1.188 class.c
--- class.c	27 Jun 2004 18:16:48 -0000	1.188
+++ class.c	29 Jun 2004 02:24:58 -0000
@@ -2214,9 +2214,24 @@
     {
       tree method_sig =
 	build_java_argument_signature (TREE_TYPE (method_decl));
+      bool method_override = 0;
       tree super_method = lookup_argument_method (super_class, method_name,
 						  method_sig);
-      if (super_method != NULL_TREE && ! METHOD_PRIVATE (super_method))
+      if (super_method != NULL_TREE)
+        {
+	  method_override = 1;
+	  if (! METHOD_PUBLIC (super_method) && 
+	      ! METHOD_PROTECTED (super_method))
+	    {
+	      /* Don't override private method, or default-access method in 
+		 another package.  */
+	      if (METHOD_PRIVATE (super_method) ||
+		  ! in_same_package (TYPE_NAME (this_class), 
+				     TYPE_NAME (super_class)))
+		method_override = 0;
+	   }
+	}
+      if (method_override)
 	{
 	  tree method_index = get_method_index (super_method);
 	  set_method_index (method_decl, method_index);
@@ -2538,4 +2553,63 @@
 			      java_treetreehash_compare, free, xcalloc, free);
 }
 
+/* Break down qualified IDENTIFIER into package and class-name components.
+   For example, given SOURCE "pkg.foo.Bar", LEFT will be set to
+   "pkg.foo", and RIGHT to "Bar". */
+
+int
+split_qualified_name (tree *left, tree *right, tree source)
+{
+  char *p, *base;
+  int l = IDENTIFIER_LENGTH (source);
+
+  base = alloca (l + 1);
+  memcpy (base, IDENTIFIER_POINTER (source), l + 1);
+
+  /* Breakdown NAME into REMAINDER . IDENTIFIER.  */
+  p = base + l - 1;
+  while (*p != '.' && p != base)
+    p--;
+
+  /* We didn't find a '.'. Return an error.  */
+  if (p == base)
+    return 1;
+
+  *p = '\0';
+  if (right)
+    *right = get_identifier (p+1);
+  *left = get_identifier (base);
+
+  return 0;
+}
+
+/* Given two classes (TYPE_DECL) or class names (IDENTIFIER), return TRUE 
+   if the classes are from the same package. */
+
+int
+in_same_package (tree name1, tree name2)
+{
+  tree tmp;
+  tree pkg1;
+  tree pkg2;
+
+  if (TREE_CODE (name1) == TYPE_DECL)
+    name1 = DECL_NAME (name1);
+  if (TREE_CODE (name2) == TYPE_DECL)
+    name2 = DECL_NAME (name2);
+
+  if (QUALIFIED_P (name1) != QUALIFIED_P (name2))
+    /* One in empty package. */
+    return 0;
+
+  if (QUALIFIED_P (name1) == 0 && QUALIFIED_P (name2) == 0)
+    /* Both in empty package. */
+    return 1;
+
+  split_qualified_name (&pkg1, &tmp, name1);
+  split_qualified_name (&pkg2, &tmp, name2);
+
+  return (pkg1 == pkg2);
+}
+
 #include "gt-java-class.h"
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.201
diff -u -r1.201 java-tree.h
--- java-tree.h	29 May 2004 05:11:41 -0000	1.201
+++ java-tree.h	29 Jun 2004 02:24:59 -0000
@@ -1355,6 +1355,9 @@
 extern tree emit_catch_table (tree);
 
 extern void gen_indirect_dispatch_tables (tree type);
+extern int split_qualified_name (tree *left, tree *right, tree source);
+extern int in_same_package (tree, tree);
+
 
 #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
 
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.488
diff -u -r1.488 parse.y
--- parse.y	27 Jun 2004 18:16:47 -0000	1.488
+++ parse.y	29 Jun 2004 02:25:02 -0000
@@ -122,8 +122,6 @@
 static tree maybe_create_class_interface_decl (tree, tree, tree, tree);
 static int check_class_interface_creation (int, int, tree, tree, tree, tree);
 static tree patch_method_invocation (tree, tree, tree, int, int *, tree *);
-static int breakdown_qualified (tree *, tree *, tree);
-static int in_same_package (tree, tree);
 static tree resolve_and_layout (tree, tree);
 static tree qualify_and_find (tree, tree, tree);
 static tree resolve_no_layout (tree, tree);
@@ -5744,7 +5742,7 @@
 	 class and then treat Id as a member type.  If we can't find Q
 	 as a class then we fall through.  */
       tree q, left, left_type, right;
-      if (breakdown_qualified (&left, &right, TYPE_NAME (class_type)) == 0)
+      if (split_qualified_name (&left, &right, TYPE_NAME (class_type)) == 0)
 	{
 	  BUILD_PTR_FROM_NAME (left_type, left);
 	  q = do_resolve_class (enclosing, left_type, decl, cl);
@@ -6823,7 +6821,7 @@
 	     inner class.  The only way for us to know is to try again
 	     after having dropped a qualifier. If we can't break it further,
 	     we have an error. */
-	  if (breakdown_qualified (&left, NULL, to_be_found))
+	  if (split_qualified_name (&left, NULL, to_be_found))
 	    break;
 
 	  to_be_found = left;
@@ -7257,7 +7255,7 @@
       /* Access to a private class within the same package is
          allowed. */
       tree l, r;
-      breakdown_qualified (&l, &r, class_name);
+      split_qualified_name (&l, &r, class_name);
       if (!QUALIFIED_P (class_name) && !ctxp->package)
 	/* Both in the empty package. */
         return 0;
@@ -10193,7 +10191,7 @@
     return 1;
 
   /* Compare the left part of the name of CLASS with the package name */
-  breakdown_qualified (&left, NULL, DECL_NAME (TYPE_NAME (class)));
+  split_qualified_name (&left, NULL, DECL_NAME (TYPE_NAME (class)));
   if (ctxp->package == left)
     {
       cicp_cache = class;
@@ -11345,60 +11343,6 @@
     RESOLVE_PACKAGE_NAME_P (id) = 1;
 }
 
-static int
-breakdown_qualified (tree *left, tree *right, tree source)
-{
-  char *p, *base;
-  int l = IDENTIFIER_LENGTH (source);
-
-  base = alloca (l + 1);
-  memcpy (base, IDENTIFIER_POINTER (source), l + 1);
-
-  /* Breakdown NAME into REMAINDER . IDENTIFIER.  */
-  p = base + l - 1;
-  while (*p != '.' && p != base)
-    p--;
-
-  /* We didn't find a '.'. Return an error.  */
-  if (p == base)
-    return 1;
-
-  *p = '\0';
-  if (right)
-    *right = get_identifier (p+1);
-  *left = get_identifier (base);
-
-  return 0;
-}
-
-/* Return TRUE if two classes are from the same package. */
-
-static int
-in_same_package (tree name1, tree name2)
-{
-  tree tmp;
-  tree pkg1;
-  tree pkg2;
-
-  if (TREE_CODE (name1) == TYPE_DECL)
-    name1 = DECL_NAME (name1);
-  if (TREE_CODE (name2) == TYPE_DECL)
-    name2 = DECL_NAME (name2);
-
-  if (QUALIFIED_P (name1) != QUALIFIED_P (name2))
-    /* One in empty package. */
-    return 0;
-
-  if (QUALIFIED_P (name1) == 0 && QUALIFIED_P (name2) == 0)
-    /* Both in empty package. */
-    return 1;
-
-  breakdown_qualified (&pkg1, &tmp, name1);
-  breakdown_qualified (&pkg2, &tmp, name2);
-
-  return (pkg1 == pkg2);
-}
-
 /* Patch tree nodes in a function body. When a BLOCK is found, push
    local variable decls if present.
    Same as java_complete_lhs, but does resolve static finals to values. */

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