This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: RFA: fix miranda methods in gcj
- From: Tom Tromey <tromey at redhat dot com>
- To: GCC libjava patches <java-patches at gcc dot gnu dot org>
- Cc: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: 12 Aug 2003 11:13:23 -0600
- Subject: Patch: RFA: fix miranda methods in gcj
- Reply-to: tromey at redhat dot com
This patch fixes changes gcj to correctly implement Miranda methods.
This is based on one of the patches we needed to get eclipse
working. However, that patch caused a regression, so I've rewritten
parts of it.
In order to avoid any regressions in Jacks, I also changed how gcj
checks `throws' clauses.
This patch works by adding a new `invisible' method (marked with
METHOD_INVISIBLE) to any abstract class that doesn't re-declare an
abstract method inherited from an implemented interface.
This probably won't seem like the obvious approach, especially since
some code now needs to ignore invisible methods. However, this
approach is useful because we need these methods to properly lay out
vtables.
This part of gcj remains a mess, unfortunately. Some of the new code
is pretty easy to follow, but some things remain difficult. For
instance, look at the new FIXME in find_most_specific_methods_list.
It would be useful if we could generate a dummy METHOD_DECL here,
which would have the required merged `throws' clause, but which would
otherwise forward to a real METHOD_DECL. However, this doesn't seem
possible given the current framework. So, we still don't correctly
implement throws-clause checking.
Tested on x86 Red Hat Linux 9. There were no regressions; I included
jacks in these tests (actually jacks provided the bulk of actual
testing of this patch). Also, I rebuilt rhug with this patch for good
measure.
Ok to commit?
Tom
Index: gcc/java/ChangeLog
from Tom Tromey <tromey@redhat.com>
* parse.y (java_check_regular_methods): Typo fixes. Call
check_interface_throws_clauses. Use
check_concrete_throws_clauses.
(check_interface_throws_clauses): New function.
(check_concrete_throws_clauses): New function.
(hack_is_accessible_p): New function.
(find_most_specific_methods_list): Added FIXME.
* typeck.c (lookup_do): Use `flags' argument to decide what to
do. Reimplemented.
(lookup_argument_method_generic): New function.
(lookup_argument_method2): Removed.
* jcf.h (ACC_INVISIBLE): New define.
* jcf-write.c (generate_classfile): Skip invisible methods.
* class.c (add_miranda_methods): New function.
(layout_class_methods): Use it.
(get_access_flags_from_decl): Use ACC_INVISIBLE.
* java-tree.h (METHOD_INVISIBLE): New define.
(lang_decl_func) [invisible]: New field.
(lookup_argument_method_generic): Declare.
(SEARCH_INTERFACE): New define.
(SEARCH_SUPER): Likewise.
(SEARCH_ONLY_INTERFACE): Likewise.
(SEARCH_VISIBLE): Likewise.
(lookup_argument_method2): Removed declaration.
Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.163
diff -u -r1.163 class.c
--- gcc/java/class.c 4 Aug 2003 19:06:24 -0000 1.163
+++ gcc/java/class.c 12 Aug 2003 17:07:02 -0000
@@ -57,6 +57,7 @@
static int supers_all_compiled (tree type);
static void add_interface_do (tree, tree, int);
static tree maybe_layout_super_class (tree, tree);
+static void add_miranda_methods (tree, tree);
static int assume_compiled (const char *);
static tree build_method_symbols_entry (tree);
@@ -1034,6 +1035,8 @@
access_flags |= ACC_ABSTRACT;
if (METHOD_STRICTFP (decl))
access_flags |= ACC_STRICT;
+ if (METHOD_INVISIBLE (decl))
+ access_flags |= ACC_INVISIBLE;
return access_flags;
}
abort ();
@@ -1747,14 +1750,14 @@
{
tree super_class = CLASSTYPE_SUPER (this_class);
tree field;
-
+
class_list = tree_cons (this_class, NULL_TREE, class_list);
if (CLASS_BEING_LAIDOUT (this_class))
{
char buffer [1024];
char *report;
tree current;
-
+
sprintf (buffer, " with `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
obstack_grow (&temporary_obstack, buffer, strlen (buffer));
@@ -1808,8 +1811,9 @@
layout_type (this_class);
- /* Also recursively load/layout any superinterfaces, but only if class was
- loaded from bytecode. The source parser will take care of this itself. */
+ /* Also recursively load/layout any superinterfaces, but only if
+ class was loaded from bytecode. The source parser will take care
+ of this itself. */
if (!CLASS_FROM_SOURCE_P (this_class))
{
tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
@@ -1837,14 +1841,61 @@
}
}
- /* Convert the size back to an SI integer value */
- TYPE_SIZE_UNIT (this_class) =
+ /* Convert the size back to an SI integer value. */
+ TYPE_SIZE_UNIT (this_class) =
fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class)));
CLASS_BEING_LAIDOUT (this_class) = 0;
class_list = TREE_CHAIN (class_list);
}
+static void
+add_miranda_methods (tree base_class, tree search_class)
+{
+ tree basetype_vec = TYPE_BINFO_BASETYPES (search_class);
+ int i, n = TREE_VEC_LENGTH (basetype_vec);
+ for (i = 1; i < n; ++i)
+ {
+ tree method_decl;
+ tree elt = TREE_VEC_ELT (basetype_vec, i);
+ if (elt == NULL_TREE)
+ break;
+ elt = BINFO_TYPE (elt);
+
+ /* Note that order matters here. However, all the base classes
+ will have been laid out at this point, so the order will
+ always be correct. Also, this code must match similar layout
+ code in the runtime. */
+ for (method_decl = TYPE_METHODS (elt);
+ method_decl; method_decl = TREE_CHAIN (method_decl))
+ {
+ tree sig, override;
+
+ /* An interface can have <clinit>. */
+ if (ID_CLINIT_P (DECL_NAME (method_decl)))
+ continue;
+
+ sig = build_java_argument_signature (TREE_TYPE (method_decl));
+ override = lookup_argument_method (base_class,
+ DECL_NAME (method_decl), sig);
+ if (override == NULL_TREE)
+ {
+ /* Found a Miranda method. Add it. */
+ tree new_method;
+ sig = build_java_signature (TREE_TYPE (method_decl));
+ new_method
+ = add_method (base_class,
+ get_access_flags_from_decl (method_decl),
+ DECL_NAME (method_decl), sig);
+ METHOD_INVISIBLE (new_method) = 1;
+ }
+ }
+
+ /* Try superinterfaces. */
+ add_miranda_methods (base_class, elt);
+ }
+}
+
void
layout_class_methods (tree this_class)
{
@@ -1866,11 +1917,20 @@
else
dtable_count = integer_zero_node;
+ if (CLASS_ABSTRACT (TYPE_NAME (this_class)))
+ {
+ /* An abstract class can have methods which are declared only in
+ an implemented interface. These are called "Miranda
+ methods". We make a dummy method entry for such methods
+ here. */
+ add_miranda_methods (this_class, this_class);
+ }
+
TYPE_METHODS (this_class) = nreverse (TYPE_METHODS (this_class));
for (method_decl = TYPE_METHODS (this_class);
method_decl; method_decl = TREE_CHAIN (method_decl))
- dtable_count = layout_class_method (this_class, super_class,
+ dtable_count = layout_class_method (this_class, super_class,
method_decl, dtable_count);
TYPE_NVIRTUALS (this_class) = dtable_count;
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.181
diff -u -r1.181 java-tree.h
--- gcc/java/java-tree.h 5 Aug 2003 14:11:46 -0000 1.181
+++ gcc/java/java-tree.h 12 Aug 2003 17:07:03 -0000
@@ -977,6 +977,9 @@
unsigned int fixed_ctor : 1;
unsigned int init_calls_this : 1;
unsigned int strictfp : 1;
+ unsigned int invisible : 1; /* Set for methods we generate
+ internally but which shouldn't be
+ written to the .class file. */
};
struct treetreehash_entry GTY(())
@@ -1071,6 +1074,12 @@
#define JCF_u4 unsigned long
#define JCF_u2 unsigned short
+/* Possible values to pass to lookup_argument_method_generic. */
+#define SEARCH_INTERFACE 1
+#define SEARCH_SUPER 2
+#define SEARCH_ONLY_INTERFACE 4
+#define SEARCH_VISIBLE 8
+
extern void java_parse_file (int);
extern bool java_mark_addressable (tree);
extern tree java_type_for_mode (enum machine_mode, int);
@@ -1084,7 +1093,7 @@
extern tree lookup_java_constructor (tree, tree);
extern tree lookup_java_method (tree, tree, tree);
extern tree lookup_argument_method (tree, tree, tree);
-extern tree lookup_argument_method2 (tree, tree, tree);
+extern tree lookup_argument_method_generic (tree, tree, tree, int);
extern int has_method (tree, tree);
extern tree promote_type (tree);
extern tree get_constant (struct JCF*, int);
@@ -1302,6 +1311,7 @@
#define METHOD_NATIVE(DECL) (DECL_LANG_SPECIFIC(DECL)->u.f.native)
#define METHOD_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL)
#define METHOD_STRICTFP(DECL) (DECL_LANG_SPECIFIC (DECL)->u.f.strictfp)
+#define METHOD_INVISIBLE(DECL) (DECL_LANG_SPECIFIC (DECL)->u.f.invisible)
#define JAVA_FILE_P(NODE) TREE_LANG_FLAG_2 (NODE)
#define CLASS_FILE_P(NODE) TREE_LANG_FLAG_3 (NODE)
Index: gcc/java/jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.129
diff -u -r1.129 jcf-write.c
--- gcc/java/jcf-write.c 19 Jul 2003 16:09:48 -0000 1.129
+++ gcc/java/jcf-write.c 12 Aug 2003 17:07:04 -0000
@@ -2919,6 +2919,12 @@
tree type = TREE_TYPE (part);
tree save_function = current_function_decl;
int synthetic_p = 0;
+
+ /* Invisible Miranda methods shouldn't end up in the .class
+ file. */
+ if (METHOD_INVISIBLE (part))
+ continue;
+
current_function_decl = part;
ptr = append_chunk (NULL, 8, state);
i = get_access_flags (part); PUT2 (i);
Index: gcc/java/jcf.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf.h,v
retrieving revision 1.39
diff -u -r1.39 jcf.h
--- gcc/java/jcf.h 3 Jul 2003 04:24:01 -0000 1.39
+++ gcc/java/jcf.h 12 Aug 2003 17:07:04 -0000
@@ -230,6 +230,9 @@
#define ACC_INTERFACE 0x0200
#define ACC_ABSTRACT 0x0400
#define ACC_STRICT 0x0800
+/* "Invisible" refers to Miranda methods inserted into an abstract
+ #class. It is also used in the runtime. */
+#define ACC_INVISIBLE 0x1000
#define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
Index: gcc/java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.438
diff -u -r1.438 parse.y
--- gcc/java/parse.y 5 Aug 2003 18:47:22 -0000 1.438
+++ gcc/java/parse.y 12 Aug 2003 17:07:09 -0000
@@ -224,6 +224,7 @@
static int check_thrown_exceptions_do (tree);
static void purge_unchecked_exceptions (tree);
static bool ctors_unchecked_throws_clause_p (tree);
+static void check_concrete_throws_clauses (tree, tree, tree, tree);
static void check_throws_clauses (tree, tree, tree);
static void finish_method_declaration (tree);
static tree build_super_invocation (tree);
@@ -244,7 +245,9 @@
static void end_artificial_method_body (tree);
static int check_method_redefinition (tree, tree);
static int check_method_types_complete (tree);
+static bool hack_is_accessible_p (tree, tree);
static void java_check_regular_methods (tree);
+static void check_interface_throws_clauses (tree, tree);
static void java_check_abstract_methods (tree);
static void unreachable_stmt_error (tree);
static tree find_expr_with_wfl (tree);
@@ -6244,11 +6247,35 @@
CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)) = 1;
}
+/* Like not_accessible_p, but doesn't refer to the current class at
+ all. */
+static bool
+hack_is_accessible_p (tree member, tree from_where)
+{
+ int flags = get_access_flags_from_decl (member);
+
+ if (from_where == DECL_CONTEXT (member)
+ || (flags & ACC_PUBLIC))
+ return true;
+
+ if ((flags & ACC_PROTECTED))
+ {
+ if (inherits_from_p (from_where, DECL_CONTEXT (member)))
+ return true;
+ }
+
+ if ((flags & ACC_PRIVATE))
+ return false;
+
+ /* Package private, or protected. */
+ return in_same_package (TYPE_NAME (from_where),
+ TYPE_NAME (DECL_CONTEXT (member)));
+}
+
/* Check all the methods of CLASS_DECL. Methods are first completed
then checked according to regular method existence rules. If no
constructor for CLASS_DECL were encountered, then build its
declaration. */
-
static void
java_check_regular_methods (tree class_decl)
{
@@ -6298,7 +6325,8 @@
}
sig = build_java_argument_signature (TREE_TYPE (method));
- found = lookup_argument_method2 (class, DECL_NAME (method), sig);
+ found = lookup_argument_method_generic (class, DECL_NAME (method), sig,
+ SEARCH_SUPER | SEARCH_INTERFACE);
/* Inner class can't declare static methods */
if (METHOD_STATIC (method) && !TOPLEVEL_CLASS_DECL_P (class_decl))
@@ -6357,7 +6385,7 @@
continue;
parse_error_context
(method_wfl,
- "%s methods can't be overriden. Method `%s' is %s in class `%s'",
+ "%s methods can't be overridden. Method `%s' is %s in class `%s'",
(METHOD_FINAL (found) ? "Final" : "Static"),
lang_printable_name (found, 0),
(METHOD_FINAL (found) ? "final" : "static"),
@@ -6371,7 +6399,7 @@
{
parse_error_context
(method_wfl,
- "Instance methods can't be overriden by a static method. Method `%s' is an instance method in class `%s'",
+ "Instance methods can't be overridden by a static method. Method `%s' is an instance method in class `%s'",
lang_printable_name (found, 0),
IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
@@ -6380,7 +6408,7 @@
/* - Overriding/hiding public must be public
- Overriding/hiding protected must be protected or public
- - If the overriden or hidden method has default (package)
+ - If the overridden or hidden method has default (package)
access, then the overriding or hiding method must not be
private; otherwise, a compile-time error occurs. If
`found' belongs to an interface, things have been already
@@ -6402,13 +6430,20 @@
continue;
}
- /* Overriding methods must have compatible `throws' clauses on checked
- exceptions, if any */
- check_throws_clauses (method, method_wfl, found);
-
- /* Inheriting multiple methods with the same signature. FIXME */
+ /* Check this method against all the other implementations it
+ overrides. Here we only check the class hierarchy; the rest
+ of the checking is done later. If this method is just a
+ Miranda method, we can skip the check. */
+ if (! METHOD_INVISIBLE (method))
+ check_concrete_throws_clauses (class, method, DECL_NAME (method), sig);
}
+ /* The above throws clause check only looked at superclasses. Now
+ we must also make sure that all methods declared in interfaces
+ have compatible throws clauses. FIXME: there are more efficient
+ ways to organize this checking; we should implement one. */
+ check_interface_throws_clauses (class, class);
+
if (!TYPE_NVIRTUALS (class))
TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
@@ -6420,13 +6455,83 @@
abort ();
}
-/* Return a nonzero value if the `throws' clause of METHOD (if any)
- is incompatible with the `throws' clause of FOUND (if any). */
+/* Check to make sure that all the methods in all the interfaces
+ implemented by CLASS_DECL are compatible with the concrete
+ implementations available in CHECK_CLASS_DECL. */
+static void
+check_interface_throws_clauses (tree check_class_decl, tree class_decl)
+{
+ for (; class_decl != NULL_TREE; class_decl = CLASSTYPE_SUPER (class_decl))
+ {
+ tree bases = TYPE_BINFO_BASETYPES (class_decl);
+ int iface_len = TREE_VEC_LENGTH (bases) - 1;
+ int i;
+ for (i = iface_len; i > 0; --i)
+ {
+ tree interface = BINFO_TYPE (TREE_VEC_ELT (bases, i));
+ tree iface_method;
+
+ for (iface_method = TYPE_METHODS (interface);
+ iface_method != NULL_TREE;
+ iface_method = TREE_CHAIN (iface_method))
+ {
+ tree sig, method;
+
+ /* First look for a concrete method implemented or
+ inherited by this class. No need to search
+ interfaces here, since we're already looking through
+ all of them. */
+ sig = build_java_argument_signature (TREE_TYPE (iface_method));
+ method
+ = lookup_argument_method_generic (check_class_decl,
+ DECL_NAME (iface_method),
+ sig, SEARCH_VISIBLE);
+ /* If we don't find an implementation, that is ok. Any
+ potential errors from that are diagnosed elsewhere.
+ Also, multiple inheritance with conflicting throws
+ clauses is fine in the absence of a concrete
+ implementation. */
+ if (method != NULL_TREE && !METHOD_ABSTRACT (method))
+ {
+ tree method_wfl = DECL_FUNCTION_WFL (method);
+ check_throws_clauses (method, method_wfl, iface_method);
+ }
+ }
+
+ /* Now check superinterfaces. */
+ check_interface_throws_clauses (check_class_decl, interface);
+ }
+ }
+}
+
+/* Check throws clauses of a method against the clauses of all the
+ methods it overrides. We do this by searching up the class
+ hierarchy, examining all matching accessible methods. */
+static void
+check_concrete_throws_clauses (tree class, tree self_method,
+ tree name, tree signature)
+{
+ tree method = lookup_argument_method_generic (class, name, signature,
+ SEARCH_SUPER | SEARCH_VISIBLE);
+ while (method != NULL_TREE)
+ {
+ if (! METHOD_INVISIBLE (method) && hack_is_accessible_p (method, class))
+ check_throws_clauses (self_method, DECL_FUNCTION_WFL (self_method),
+ method);
+
+ method = lookup_argument_method_generic (DECL_CONTEXT (method),
+ name, signature,
+ SEARCH_SUPER | SEARCH_VISIBLE);
+ }
+}
+
+/* Generate an error if the `throws' clause of METHOD (if any) is
+ incompatible with the `throws' clause of FOUND (if any). */
static void
check_throws_clauses (tree method, tree method_wfl, tree found)
{
- tree mthrows, fthrows;
+ tree mthrows;
/* Can't check these things with class loaded from bytecode. FIXME */
if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (found)))
@@ -6435,28 +6540,31 @@
for (mthrows = DECL_FUNCTION_THROWS (method);
mthrows; mthrows = TREE_CHAIN (mthrows))
{
+ tree fthrows;
+
/* We don't verify unchecked expressions */
if (IS_UNCHECKED_EXCEPTION_P (TREE_VALUE (mthrows)))
continue;
/* Checked expression must be compatible */
for (fthrows = DECL_FUNCTION_THROWS (found);
fthrows; fthrows = TREE_CHAIN (fthrows))
- if (inherits_from_p (TREE_VALUE (mthrows), TREE_VALUE (fthrows)))
- break;
+ {
+ if (inherits_from_p (TREE_VALUE (mthrows), TREE_VALUE (fthrows)))
+ break;
+ }
if (!fthrows)
{
parse_error_context
- (method_wfl, "Invalid checked exception class `%s' in `throws' clause. The exception must be a subclass of an exception thrown by `%s' from class `%s'",
+ (method_wfl, "Invalid checked exception class `%s' in `throws' clause. The exception must be a subclass of an exception thrown by `%s' from class `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (TREE_VALUE (mthrows)))),
lang_printable_name (found, 0),
IDENTIFIER_POINTER
- (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
+ (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
}
}
}
/* Check abstract method of interface INTERFACE */
-
static void
java_check_abstract_methods (tree interface_decl)
{
@@ -6470,8 +6578,7 @@
if (check_method_redefinition (interface, method))
continue;
- /* 3- Overriding is OK as far as we preserve the return type and
- the thrown exceptions (FIXME) */
+ /* 3- Overriding is OK as far as we preserve the return type. */
found = lookup_java_interface_method2 (interface, method);
if (found)
{
@@ -10100,7 +10207,7 @@
tree this_arg = NULL_TREE;
int is_array_clone_call = 0;
- /* Should be overriden if everything goes well. Otherwise, if
+ /* Should be overridden if everything goes well. Otherwise, if
something fails, it should keep this value. It stop the
evaluation of a bogus assignment. See java_complete_tree,
MODIFY_EXPR: for the reasons why we sometimes want to keep on
@@ -11057,10 +11164,15 @@
/* If we have several and they're all abstract, just pick the
closest one. */
- if (candidates > 0 && (candidates == abstract))
+ if (candidates > 0 && candidates == abstract)
{
+ /* FIXME: merge the throws clauses. There is no convenient way
+ to do this in gcj right now, since ideally we'd like to
+ introduce a new METHOD_DECL here, but that is really not
+ possible. */
new_list = nreverse (new_list);
TREE_CHAIN (new_list) = NULL_TREE;
+ return new_list;
}
/* We have several (we couldn't find a most specific), all but one
Index: gcc/java/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/typeck.c,v
retrieving revision 1.56
diff -u -r1.56 typeck.c
--- gcc/java/typeck.c 18 Jan 2003 22:15:51 -0000 1.56
+++ gcc/java/typeck.c 12 Aug 2003 17:07:09 -0000
@@ -42,7 +42,7 @@
static tree convert_ieee_real_to_integer (tree, tree);
static tree parse_signature_type (const unsigned char **,
const unsigned char *);
-static tree lookup_do (tree, tree, tree, tree, tree (*)(tree));
+static tree lookup_do (tree, int, tree, tree, tree (*)(tree));
static tree build_null_signature (tree);
tree * type_map;
@@ -687,124 +687,142 @@
#endif
}
-/* Search in class SEARCHED_CLASS (and its superclasses) for a method
- matching METHOD_NAME and signature SIGNATURE. If SEARCHED_INTERFACE is
- not NULL_TREE then first search its superinterfaces for a similar match.
- Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is
- used on method candidates to build their (sometimes partial)
- signature. */
-
+/* Search in SEARCHED_CLASS and its superclasses for a method matching
+ METHOD_NAME and signature METHOD_SIGNATURE. This function will
+ only search for methods declared in the class hierarchy; interfaces
+ will not be considered. Returns NULL_TREE if the method is not
+ found. */
tree
-lookup_argument_method (tree searched_class, tree method_name, tree method_signature)
+lookup_argument_method (tree searched_class, tree method_name,
+ tree method_signature)
{
- return lookup_do (searched_class, NULL_TREE, method_name, method_signature,
+ return lookup_do (searched_class, 0,
+ method_name, method_signature,
build_java_argument_signature);
}
-/* Search in class SEARCHED_CLASS (and its superclasses and
- implemented interfaces) for a method matching METHOD_NAME and
- argument signature METHOD_SIGNATURE. Return a FUNCTION_DECL on
- success, or NULL_TREE if none found. (Contrast lookup_java_method,
- which takes into account return type.) */
-
+/* Like lookup_argument_method, but lets the caller set any flags
+ desired. */
tree
-lookup_argument_method2 (tree searched_class, tree method_name, tree method_signature)
+lookup_argument_method_generic (tree searched_class, tree method_name,
+ tree method_signature, int flags)
{
- return lookup_do (CLASSTYPE_SUPER (searched_class), searched_class,
+ return lookup_do (searched_class, flags,
method_name, method_signature,
build_java_argument_signature);
}
+
/* Search in class SEARCHED_CLASS (and its superclasses) for a method
matching METHOD_NAME and signature METHOD_SIGNATURE. Return a
FUNCTION_DECL on success, or NULL_TREE if none found. (Contrast
- lookup_argument_method, which ignores return type.) If
+ lookup_argument_method, which ignores return type.) If
SEARCHED_CLASS is an interface, search it too. */
-
tree
-lookup_java_method (tree searched_class, tree method_name, tree method_signature)
+lookup_java_method (tree searched_class, tree method_name,
+ tree method_signature)
{
- tree searched_interface;
-
- /* If this class is an interface class, search its superinterfaces
- * first. A superinterface is not an interface's superclass: a super
- * interface is implemented by the interface. */
-
- searched_interface = (CLASS_INTERFACE (TYPE_NAME (searched_class)) ?
- searched_class : NULL_TREE);
- return lookup_do (searched_class, searched_interface, method_name,
+ return lookup_do (searched_class, SEARCH_INTERFACE, method_name,
method_signature, build_java_signature);
}
-/* Return true iff CLASS (or its ancestors) has a method METHOD_NAME. */
-
+/* Return true iff CLASS (or its ancestors) has a method METHOD_NAME. ?*/
int
has_method (tree class, tree method_name)
{
- return lookup_do (class, class, method_name,
- NULL_TREE, build_null_signature) != NULL_TREE;
+ return lookup_do (class, SEARCH_INTERFACE,
+ method_name, NULL_TREE,
+ build_null_signature) != NULL_TREE;
}
/* Search in class SEARCHED_CLASS (and its superclasses) for a method
- matching METHOD_NAME and signature SIGNATURE. Also search in
- SEARCHED_INTERFACE (and its superinterfaces) for a similar match.
+ matching METHOD_NAME and signature SIGNATURE. FLAGS control some
+ parameters of the search.
+
+ SEARCH_INTERFACE means also search interfaces and superinterfaces
+ of SEARCHED_CLASS.
+
+ SEARCH_SUPER means skip SEARCHED_CLASS and start with its
+ superclass.
+
+ SEARCH_ONLY_INTERFACE means don't search ordinary classes, but
+ instead only search interfaces and superinterfaces.
+
+ SEARCH_VISIBLE means skip methods for which METHOD_INVISIBLE is
+ set.
+
Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is
used on method candidates to build their (sometimes partial)
signature. */
-
static tree
-lookup_do (tree searched_class, tree searched_interface, tree method_name,
+lookup_do (tree searched_class, int flags, tree method_name,
tree signature, tree (*signature_builder) (tree))
{
tree method;
-
- if (searched_interface)
- {
- int i;
- int interface_len =
- TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_interface)) - 1;
-
- for (i = interface_len; i > 0; i--)
- {
- tree child =
- TREE_VEC_ELT (TYPE_BINFO_BASETYPES (searched_interface), i);
- tree iclass = BINFO_TYPE (child);
-
- /* If the superinterface hasn't been loaded yet, do so now. */
- if (CLASS_FROM_SOURCE_P (iclass))
- safe_layout_class (iclass);
- else if (!CLASS_LOADED_P (iclass))
- load_class (iclass, 1);
-
- for (method = TYPE_METHODS (iclass);
- method != NULL_TREE; method = TREE_CHAIN (method))
- {
- tree method_sig = (*signature_builder) (TREE_TYPE (method));
-
- if (DECL_NAME (method) == method_name && method_sig == signature)
- return method;
- }
-
- /* it could be defined in a supersuperinterface */
- if (CLASS_INTERFACE (TYPE_NAME (iclass)))
- {
- method = lookup_do (iclass, iclass, method_name,
- signature, signature_builder);
- if (method != NULL_TREE)
- return method;
- }
- }
- }
+ int first_time = 1;
+
+ /* If the incoming class is an interface, then we will only return
+ a method declared in an interface context. */
+ if (searched_class != NULL_TREE
+ && CLASS_INTERFACE (TYPE_NAME (searched_class)))
+ flags |= SEARCH_ONLY_INTERFACE;
while (searched_class != NULL_TREE)
{
- for (method = TYPE_METHODS (searched_class);
- method != NULL_TREE; method = TREE_CHAIN (method))
- {
- tree method_sig = (*signature_builder) (TREE_TYPE (method));
- if (DECL_NAME (method) == method_name && method_sig == signature)
- return method;
- }
+ /* First search this class. If we're only searching the
+ superclass, skip this. */
+ if (! ((flags & SEARCH_SUPER) && first_time))
+ {
+ for (method = TYPE_METHODS (searched_class);
+ method != NULL_TREE; method = TREE_CHAIN (method))
+ {
+ tree method_sig = (*signature_builder) (TREE_TYPE (method));
+ if (DECL_NAME (method) == method_name && method_sig == signature)
+ {
+ /* If the caller requires a visible method, then we
+ skip invisible methods here. */
+ if (! (flags & SEARCH_VISIBLE)
+ || ! METHOD_INVISIBLE (method))
+ return method;
+ }
+ }
+ }
+ first_time = 0;
+
+ /* Search interfaces, if required. */
+ if ((flags & SEARCH_INTERFACE))
+ {
+ int i;
+ int interface_len =
+ TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_class)) - 1;
+
+ for (i = interface_len; i > 0; i--)
+ {
+ tree child =
+ TREE_VEC_ELT (TYPE_BINFO_BASETYPES (searched_class), i);
+ tree iclass = BINFO_TYPE (child);
+
+ /* If the superinterface hasn't been loaded yet, do so now. */
+ if (CLASS_FROM_SOURCE_P (iclass))
+ safe_layout_class (iclass);
+ else if (!CLASS_LOADED_P (iclass))
+ load_class (iclass, 1);
+
+ /* Note that we don't care about SEARCH_VISIBLE here,
+ since an interface can never have an invisible
+ method. */
+ method = lookup_do (iclass, SEARCH_INTERFACE,
+ method_name, signature, signature_builder);
+ if (method != NULL_TREE)
+ return method;
+ }
+ }
+
+ /* If we're only searching for interface methods, then we've
+ already searched all the superinterfaces. Our superclass is
+ Object, but we don't want to search that. */
+ if ((flags & SEARCH_ONLY_INTERFACE))
+ break;
searched_class = CLASSTYPE_SUPER (searched_class);
}
Index: libjava/testsuite/ChangeLog
from Tom Tromey <tromey@redhat.com>
* libjava.jacks/jacks.xfail: Updated to account for new passes.
* libjava.compile/abstr.xfail: Now can compile from bytecode.
* libjava.compile/PR5641.xfail: Now can compile from bytecode.
2003-08-12 Tom Tromey <tromey@redhat.com>
Index: libjava/testsuite/libjava.compile/PR5641.xfail
===================================================================
RCS file: /cvs/gcc/gcc/libjava/testsuite/libjava.compile/PR5641.xfail,v
retrieving revision 1.1
diff -u -r1.1 PR5641.xfail
--- libjava/testsuite/libjava.compile/PR5641.xfail 11 Feb 2002 00:18:52 -0000 1.1
+++ libjava/testsuite/libjava.compile/PR5641.xfail 12 Aug 2003 17:08:01 -0000
@@ -1,2 +1 @@
no-link
-xfail-byte
Index: libjava/testsuite/libjava.compile/abstr.xfail
===================================================================
RCS file: /cvs/gcc/gcc/libjava/testsuite/libjava.compile/abstr.xfail,v
retrieving revision 1.2
diff -u -r1.2 abstr.xfail
--- libjava/testsuite/libjava.compile/abstr.xfail 16 Dec 2000 02:06:29 -0000 1.2
+++ libjava/testsuite/libjava.compile/abstr.xfail 12 Aug 2003 17:08:01 -0000
@@ -1,2 +1 @@
no-link
-xfail-byte
Index: libjava/testsuite/libjava.jacks/jacks.xfail
===================================================================
RCS file: /cvs/gcc/gcc/libjava/testsuite/libjava.jacks/jacks.xfail,v
retrieving revision 1.6
diff -u -r1.6 jacks.xfail
--- libjava/testsuite/libjava.jacks/jacks.xfail 10 Mar 2003 16:39:15 -0000 1.6
+++ libjava/testsuite/libjava.jacks/jacks.xfail 12 Aug 2003 17:08:03 -0000
@@ -141,8 +141,6 @@
8.1.1.1-default-abstract-15
8.1.1.1-default-abstract-19
8.1.1.1-default-abstract-21
-8.1.1.1-default-abstract-22
-8.1.1.1-default-abstract-24
8.1.1.1-default-abstract-25
8.1.2-static-1
8.1.2-static-11
@@ -223,21 +221,15 @@
8.5-inheritance-3
8.5-inheritance-6
8.5.2-non-static-member-usage-2
-8.4.6-miranda-2
-8.4.6-miranda-3
-8.4.6-miranda-4
8.4.6-inheritance-1
8.4.6-inheritance-2
8.4.6.2-hiding-3
8.4.6.4-multiple-3
8.4.6.4-multiple-4
-8.4.6.4-multiple-5
8.4.6.4-multiple-7
8.4.6.4-multiple-8
8.4.6.4-abstract-1
8.4.6.4-abstract-2
-8.4.6.4-abstract-4
-8.4.6.4-abstract-9
8.4.6.4-abstract-10
8.4.6.1-override-3
8.4.6.3-modifier-8
@@ -252,11 +244,6 @@
8.4.6.3-default-12
8.4.6.3-default-14
8.4.6.3-signature-4
-8.4.6.3-signature-7
-8.4.6.3-signature-9
-8.4.6.3-signature-10
-8.4.6.3-signature-12
-8.4.6.3-signature-15
8.7-abrupt-1
8.7-complete-1
8.7-complete-3
@@ -613,10 +600,7 @@
9.2-implicit-4
9.2-implicit-6
9.2-implicit-7
-9.2-implicit-11
-9.2-implicit-12
9.2-implicit-15
-9.2-implicit-17
9.2-implicit-18
9.2-implicit-19
3.2-valid-1