This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Java: Fix PR 1262
- From: Bryce McKinlay <mckinlay at redhat dot com>
- To: java-patches at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Mon, 28 Jun 2004 23:02:11 -0400
- Subject: 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. */