summaryrefslogtreecommitdiff
path: root/gcc/java
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2003-08-12 20:34:51 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2003-08-12 20:34:51 +0000
commitaf74ab68ba5a2073bc66e570f938e11d3e71c0fe (patch)
treeb0eccc2bad8dc4ad0fc0c2540ee347467640fdec /gcc/java
parente50c12fc93d9d59f81785ba705c7f80dce7845de (diff)
downloadgcc-af74ab68ba5a2073bc66e570f938e11d3e71c0fe.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70388 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/java')
-rw-r--r--gcc/java/ChangeLog27
-rw-r--r--gcc/java/class.c74
-rw-r--r--gcc/java/java-tree.h12
-rw-r--r--gcc/java/jcf-write.c6
-rw-r--r--gcc/java/jcf.h3
-rw-r--r--gcc/java/parse.y156
-rw-r--r--gcc/java/typeck.c184
7 files changed, 349 insertions, 113 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 0d6578ceaed..10358153bf0 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,30 @@
+2003-08-11 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.
+
2003-08-05 Tom Tromey <tromey@redhat.com>
Fix for PR java/11600:
diff --git a/gcc/java/class.c b/gcc/java/class.c
index fbec8d0a9ca..620a8a2e6c9 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -57,6 +57,7 @@ static tree get_dispatch_table (tree, tree);
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 @@ get_access_flags_from_decl (tree decl)
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 @@ layout_class (tree this_class)
{
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_class (tree this_class)
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 @@ layout_class (tree this_class)
}
}
- /* 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 @@ layout_class_methods (tree this_class)
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;
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 920d2886653..0a7a542a9f5 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -977,6 +977,9 @@ struct lang_decl_func GTY(())
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 @@ struct lang_type GTY(())
#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_class (tree);
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 @@ extern void init_resource_processing (void);
#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)
diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c
index 44c9ec1cf80..3609807a410 100644
--- a/gcc/java/jcf-write.c
+++ b/gcc/java/jcf-write.c
@@ -2919,6 +2919,12 @@ generate_classfile (tree clas, struct jcf_partial *state)
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);
diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
index 970656732c0..5b97fec9525 100644
--- a/gcc/java/jcf.h
+++ b/gcc/java/jcf.h
@@ -230,6 +230,9 @@ typedef struct JCF GTY(()) {
#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)
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index 6ca734aa684..a9f8d6ecc6b 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -224,6 +224,7 @@ static void check_thrown_exceptions (int, tree, tree);
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 start_artificial_method_body (tree);
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 @@ java_check_methods (tree class_decl)
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 @@ java_check_regular_methods (tree class_decl)
}
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 @@ java_check_regular_methods (tree class_decl)
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 @@ java_check_regular_methods (tree class_decl)
{
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 @@ java_check_regular_methods (tree class_decl)
/* - 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 @@ java_check_regular_methods (tree class_decl)
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 @@ java_check_regular_methods (tree class_decl)
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 @@ check_throws_clauses (tree method, tree method_wfl, tree found)
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 @@ java_check_abstract_methods (tree interface_decl)
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 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
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 @@ find_most_specific_methods_list (tree list)
/* 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
diff --git a/gcc/java/typeck.c b/gcc/java/typeck.c
index 468de74cbb6..972cb8b3686 100644
--- a/gcc/java/typeck.c
+++ b/gcc/java/typeck.c
@@ -42,7 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
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 @@ set_java_signature (tree type, tree sig)
#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);
}