Commit aecf4109 by Tom Tromey Committed by Tom Tromey

parse.y (java_check_regular_methods): Typo fixes.

	* 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.

From-SVN: r70388
parent b9172475
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> 2003-08-05 Tom Tromey <tromey@redhat.com>
Fix for PR java/11600: Fix for PR java/11600:
......
...@@ -57,6 +57,7 @@ static tree get_dispatch_table (tree, tree); ...@@ -57,6 +57,7 @@ static tree get_dispatch_table (tree, tree);
static int supers_all_compiled (tree type); static int supers_all_compiled (tree type);
static void add_interface_do (tree, tree, int); static void add_interface_do (tree, tree, int);
static tree maybe_layout_super_class (tree, tree); static tree maybe_layout_super_class (tree, tree);
static void add_miranda_methods (tree, tree);
static int assume_compiled (const char *); static int assume_compiled (const char *);
static tree build_method_symbols_entry (tree); static tree build_method_symbols_entry (tree);
...@@ -1034,6 +1035,8 @@ get_access_flags_from_decl (tree decl) ...@@ -1034,6 +1035,8 @@ get_access_flags_from_decl (tree decl)
access_flags |= ACC_ABSTRACT; access_flags |= ACC_ABSTRACT;
if (METHOD_STRICTFP (decl)) if (METHOD_STRICTFP (decl))
access_flags |= ACC_STRICT; access_flags |= ACC_STRICT;
if (METHOD_INVISIBLE (decl))
access_flags |= ACC_INVISIBLE;
return access_flags; return access_flags;
} }
abort (); abort ();
...@@ -1808,8 +1811,9 @@ layout_class (tree this_class) ...@@ -1808,8 +1811,9 @@ layout_class (tree this_class)
layout_type (this_class); layout_type (this_class);
/* Also recursively load/layout any superinterfaces, but only if class was /* Also recursively load/layout any superinterfaces, but only if
loaded from bytecode. The source parser will take care of this itself. */ class was loaded from bytecode. The source parser will take care
of this itself. */
if (!CLASS_FROM_SOURCE_P (this_class)) if (!CLASS_FROM_SOURCE_P (this_class))
{ {
tree basetype_vec = TYPE_BINFO_BASETYPES (this_class); tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
...@@ -1837,7 +1841,7 @@ layout_class (tree this_class) ...@@ -1837,7 +1841,7 @@ layout_class (tree this_class)
} }
} }
/* Convert the size back to an SI integer value */ /* Convert the size back to an SI integer value. */
TYPE_SIZE_UNIT (this_class) = TYPE_SIZE_UNIT (this_class) =
fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class))); fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class)));
...@@ -1845,6 +1849,53 @@ layout_class (tree this_class) ...@@ -1845,6 +1849,53 @@ layout_class (tree this_class)
class_list = TREE_CHAIN (class_list); 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 void
layout_class_methods (tree this_class) layout_class_methods (tree this_class)
{ {
...@@ -1866,6 +1917,15 @@ layout_class_methods (tree this_class) ...@@ -1866,6 +1917,15 @@ layout_class_methods (tree this_class)
else else
dtable_count = integer_zero_node; 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)); TYPE_METHODS (this_class) = nreverse (TYPE_METHODS (this_class));
for (method_decl = TYPE_METHODS (this_class); for (method_decl = TYPE_METHODS (this_class);
......
...@@ -977,6 +977,9 @@ struct lang_decl_func GTY(()) ...@@ -977,6 +977,9 @@ struct lang_decl_func GTY(())
unsigned int fixed_ctor : 1; unsigned int fixed_ctor : 1;
unsigned int init_calls_this : 1; unsigned int init_calls_this : 1;
unsigned int strictfp : 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(()) struct treetreehash_entry GTY(())
...@@ -1071,6 +1074,12 @@ struct lang_type GTY(()) ...@@ -1071,6 +1074,12 @@ struct lang_type GTY(())
#define JCF_u4 unsigned long #define JCF_u4 unsigned long
#define JCF_u2 unsigned short #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 void java_parse_file (int);
extern bool java_mark_addressable (tree); extern bool java_mark_addressable (tree);
extern tree java_type_for_mode (enum machine_mode, int); extern tree java_type_for_mode (enum machine_mode, int);
...@@ -1084,7 +1093,7 @@ extern tree lookup_class (tree); ...@@ -1084,7 +1093,7 @@ extern tree lookup_class (tree);
extern tree lookup_java_constructor (tree, tree); extern tree lookup_java_constructor (tree, tree);
extern tree lookup_java_method (tree, tree, tree); extern tree lookup_java_method (tree, tree, tree);
extern tree lookup_argument_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 int has_method (tree, tree);
extern tree promote_type (tree); extern tree promote_type (tree);
extern tree get_constant (struct JCF*, int); extern tree get_constant (struct JCF*, int);
...@@ -1302,6 +1311,7 @@ extern void init_resource_processing (void); ...@@ -1302,6 +1311,7 @@ extern void init_resource_processing (void);
#define METHOD_NATIVE(DECL) (DECL_LANG_SPECIFIC(DECL)->u.f.native) #define METHOD_NATIVE(DECL) (DECL_LANG_SPECIFIC(DECL)->u.f.native)
#define METHOD_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL) #define METHOD_ABSTRACT(DECL) DECL_LANG_FLAG_5 (DECL)
#define METHOD_STRICTFP(DECL) (DECL_LANG_SPECIFIC (DECL)->u.f.strictfp) #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 JAVA_FILE_P(NODE) TREE_LANG_FLAG_2 (NODE)
#define CLASS_FILE_P(NODE) TREE_LANG_FLAG_3 (NODE) #define CLASS_FILE_P(NODE) TREE_LANG_FLAG_3 (NODE)
......
...@@ -2919,6 +2919,12 @@ generate_classfile (tree clas, struct jcf_partial *state) ...@@ -2919,6 +2919,12 @@ generate_classfile (tree clas, struct jcf_partial *state)
tree type = TREE_TYPE (part); tree type = TREE_TYPE (part);
tree save_function = current_function_decl; tree save_function = current_function_decl;
int synthetic_p = 0; int synthetic_p = 0;
/* Invisible Miranda methods shouldn't end up in the .class
file. */
if (METHOD_INVISIBLE (part))
continue;
current_function_decl = part; current_function_decl = part;
ptr = append_chunk (NULL, 8, state); ptr = append_chunk (NULL, 8, state);
i = get_access_flags (part); PUT2 (i); i = get_access_flags (part); PUT2 (i);
......
...@@ -230,6 +230,9 @@ typedef struct JCF GTY(()) { ...@@ -230,6 +230,9 @@ typedef struct JCF GTY(()) {
#define ACC_INTERFACE 0x0200 #define ACC_INTERFACE 0x0200
#define ACC_ABSTRACT 0x0400 #define ACC_ABSTRACT 0x0400
#define ACC_STRICT 0x0800 #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) #define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
......
...@@ -224,6 +224,7 @@ static void check_thrown_exceptions (int, tree, tree); ...@@ -224,6 +224,7 @@ static void check_thrown_exceptions (int, tree, tree);
static int check_thrown_exceptions_do (tree); static int check_thrown_exceptions_do (tree);
static void purge_unchecked_exceptions (tree); static void purge_unchecked_exceptions (tree);
static bool ctors_unchecked_throws_clause_p (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 check_throws_clauses (tree, tree, tree);
static void finish_method_declaration (tree); static void finish_method_declaration (tree);
static tree build_super_invocation (tree); static tree build_super_invocation (tree);
...@@ -244,7 +245,9 @@ static void start_artificial_method_body (tree); ...@@ -244,7 +245,9 @@ static void start_artificial_method_body (tree);
static void end_artificial_method_body (tree); static void end_artificial_method_body (tree);
static int check_method_redefinition (tree, tree); static int check_method_redefinition (tree, tree);
static int check_method_types_complete (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 java_check_regular_methods (tree);
static void check_interface_throws_clauses (tree, tree);
static void java_check_abstract_methods (tree); static void java_check_abstract_methods (tree);
static void unreachable_stmt_error (tree); static void unreachable_stmt_error (tree);
static tree find_expr_with_wfl (tree); static tree find_expr_with_wfl (tree);
...@@ -6244,11 +6247,35 @@ java_check_methods (tree class_decl) ...@@ -6244,11 +6247,35 @@ java_check_methods (tree class_decl)
CLASS_METHOD_CHECKED_P (TREE_TYPE (class_decl)) = 1; 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 /* Check all the methods of CLASS_DECL. Methods are first completed
then checked according to regular method existence rules. If no then checked according to regular method existence rules. If no
constructor for CLASS_DECL were encountered, then build its constructor for CLASS_DECL were encountered, then build its
declaration. */ declaration. */
static void static void
java_check_regular_methods (tree class_decl) java_check_regular_methods (tree class_decl)
{ {
...@@ -6298,7 +6325,8 @@ 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)); 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 */ /* Inner class can't declare static methods */
if (METHOD_STATIC (method) && !TOPLEVEL_CLASS_DECL_P (class_decl)) if (METHOD_STATIC (method) && !TOPLEVEL_CLASS_DECL_P (class_decl))
...@@ -6357,7 +6385,7 @@ java_check_regular_methods (tree class_decl) ...@@ -6357,7 +6385,7 @@ java_check_regular_methods (tree class_decl)
continue; continue;
parse_error_context parse_error_context
(method_wfl, (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"), (METHOD_FINAL (found) ? "Final" : "Static"),
lang_printable_name (found, 0), lang_printable_name (found, 0),
(METHOD_FINAL (found) ? "final" : "static"), (METHOD_FINAL (found) ? "final" : "static"),
...@@ -6371,7 +6399,7 @@ java_check_regular_methods (tree class_decl) ...@@ -6371,7 +6399,7 @@ java_check_regular_methods (tree class_decl)
{ {
parse_error_context parse_error_context
(method_wfl, (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), lang_printable_name (found, 0),
IDENTIFIER_POINTER IDENTIFIER_POINTER
(DECL_NAME (TYPE_NAME (DECL_CONTEXT (found))))); (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
...@@ -6380,7 +6408,7 @@ java_check_regular_methods (tree class_decl) ...@@ -6380,7 +6408,7 @@ java_check_regular_methods (tree class_decl)
/* - Overriding/hiding public must be public /* - Overriding/hiding public must be public
- Overriding/hiding protected must be protected or 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 access, then the overriding or hiding method must not be
private; otherwise, a compile-time error occurs. If private; otherwise, a compile-time error occurs. If
`found' belongs to an interface, things have been already `found' belongs to an interface, things have been already
...@@ -6402,13 +6430,20 @@ java_check_regular_methods (tree class_decl) ...@@ -6402,13 +6430,20 @@ java_check_regular_methods (tree class_decl)
continue; continue;
} }
/* Overriding methods must have compatible `throws' clauses on checked /* Check this method against all the other implementations it
exceptions, if any */ overrides. Here we only check the class hierarchy; the rest
check_throws_clauses (method, method_wfl, found); of the checking is done later. If this method is just a
Miranda method, we can skip the check. */
/* Inheriting multiple methods with the same signature. FIXME */ 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)) if (!TYPE_NVIRTUALS (class))
TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
...@@ -6420,13 +6455,83 @@ java_check_regular_methods (tree class_decl) ...@@ -6420,13 +6455,83 @@ java_check_regular_methods (tree class_decl)
abort (); abort ();
} }
/* Return a nonzero value if the `throws' clause of METHOD (if any) /* Check to make sure that all the methods in all the interfaces
is incompatible with the `throws' clause of FOUND (if any). */ 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 static void
check_throws_clauses (tree method, tree method_wfl, tree found) 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 */ /* Can't check these things with class loaded from bytecode. FIXME */
if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (found))) if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (found)))
...@@ -6435,14 +6540,18 @@ check_throws_clauses (tree method, tree method_wfl, tree found) ...@@ -6435,14 +6540,18 @@ check_throws_clauses (tree method, tree method_wfl, tree found)
for (mthrows = DECL_FUNCTION_THROWS (method); for (mthrows = DECL_FUNCTION_THROWS (method);
mthrows; mthrows = TREE_CHAIN (mthrows)) mthrows; mthrows = TREE_CHAIN (mthrows))
{ {
tree fthrows;
/* We don't verify unchecked expressions */ /* We don't verify unchecked expressions */
if (IS_UNCHECKED_EXCEPTION_P (TREE_VALUE (mthrows))) if (IS_UNCHECKED_EXCEPTION_P (TREE_VALUE (mthrows)))
continue; continue;
/* Checked expression must be compatible */ /* Checked expression must be compatible */
for (fthrows = DECL_FUNCTION_THROWS (found); for (fthrows = DECL_FUNCTION_THROWS (found);
fthrows; fthrows = TREE_CHAIN (fthrows)) fthrows; fthrows = TREE_CHAIN (fthrows))
{
if (inherits_from_p (TREE_VALUE (mthrows), TREE_VALUE (fthrows))) if (inherits_from_p (TREE_VALUE (mthrows), TREE_VALUE (fthrows)))
break; break;
}
if (!fthrows) if (!fthrows)
{ {
parse_error_context parse_error_context
...@@ -6456,7 +6565,6 @@ check_throws_clauses (tree method, tree method_wfl, tree found) ...@@ -6456,7 +6565,6 @@ check_throws_clauses (tree method, tree method_wfl, tree found)
} }
/* Check abstract method of interface INTERFACE */ /* Check abstract method of interface INTERFACE */
static void static void
java_check_abstract_methods (tree interface_decl) java_check_abstract_methods (tree interface_decl)
{ {
...@@ -6470,8 +6578,7 @@ java_check_abstract_methods (tree interface_decl) ...@@ -6470,8 +6578,7 @@ java_check_abstract_methods (tree interface_decl)
if (check_method_redefinition (interface, method)) if (check_method_redefinition (interface, method))
continue; continue;
/* 3- Overriding is OK as far as we preserve the return type and /* 3- Overriding is OK as far as we preserve the return type. */
the thrown exceptions (FIXME) */
found = lookup_java_interface_method2 (interface, method); found = lookup_java_interface_method2 (interface, method);
if (found) if (found)
{ {
...@@ -10100,7 +10207,7 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super, ...@@ -10100,7 +10207,7 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
tree this_arg = NULL_TREE; tree this_arg = NULL_TREE;
int is_array_clone_call = 0; 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 something fails, it should keep this value. It stop the
evaluation of a bogus assignment. See java_complete_tree, evaluation of a bogus assignment. See java_complete_tree,
MODIFY_EXPR: for the reasons why we sometimes want to keep on MODIFY_EXPR: for the reasons why we sometimes want to keep on
...@@ -11057,10 +11164,15 @@ find_most_specific_methods_list (tree list) ...@@ -11057,10 +11164,15 @@ find_most_specific_methods_list (tree list)
/* If we have several and they're all abstract, just pick the /* If we have several and they're all abstract, just pick the
closest one. */ 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); new_list = nreverse (new_list);
TREE_CHAIN (new_list) = NULL_TREE; TREE_CHAIN (new_list) = NULL_TREE;
return new_list;
} }
/* We have several (we couldn't find a most specific), all but one /* We have several (we couldn't find a most specific), all but one
......
...@@ -42,7 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ ...@@ -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 convert_ieee_real_to_integer (tree, tree);
static tree parse_signature_type (const unsigned char **, static tree parse_signature_type (const unsigned char **,
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); static tree build_null_signature (tree);
tree * type_map; tree * type_map;
...@@ -687,87 +687,119 @@ set_java_signature (tree type, tree sig) ...@@ -687,87 +687,119 @@ set_java_signature (tree type, tree sig)
#endif #endif
} }
/* Search in class SEARCHED_CLASS (and its superclasses) for a method /* Search in SEARCHED_CLASS and its superclasses for a method matching
matching METHOD_NAME and signature SIGNATURE. If SEARCHED_INTERFACE is METHOD_NAME and signature METHOD_SIGNATURE. This function will
not NULL_TREE then first search its superinterfaces for a similar match. only search for methods declared in the class hierarchy; interfaces
Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is will not be considered. Returns NULL_TREE if the method is not
used on method candidates to build their (sometimes partial) found. */
signature. */
tree 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); build_java_argument_signature);
} }
/* Search in class SEARCHED_CLASS (and its superclasses and /* Like lookup_argument_method, but lets the caller set any flags
implemented interfaces) for a method matching METHOD_NAME and desired. */
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.) */
tree 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, method_name, method_signature,
build_java_argument_signature); build_java_argument_signature);
} }
/* Search in class SEARCHED_CLASS (and its superclasses) for a method /* Search in class SEARCHED_CLASS (and its superclasses) for a method
matching METHOD_NAME and signature METHOD_SIGNATURE. Return a matching METHOD_NAME and signature METHOD_SIGNATURE. Return a
FUNCTION_DECL on success, or NULL_TREE if none found. (Contrast 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. */ SEARCHED_CLASS is an interface, search it too. */
tree 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; return lookup_do (searched_class, SEARCH_INTERFACE, method_name,
/* 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,
method_signature, build_java_signature); 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 int
has_method (tree class, tree method_name) has_method (tree class, tree method_name)
{ {
return lookup_do (class, class, method_name, return lookup_do (class, SEARCH_INTERFACE,
NULL_TREE, build_null_signature) != NULL_TREE; method_name, NULL_TREE,
build_null_signature) != NULL_TREE;
} }
/* Search in class SEARCHED_CLASS (and its superclasses) for a method /* Search in class SEARCHED_CLASS (and its superclasses) for a method
matching METHOD_NAME and signature SIGNATURE. Also search in matching METHOD_NAME and signature SIGNATURE. FLAGS control some
SEARCHED_INTERFACE (and its superinterfaces) for a similar match. 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 Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is
used on method candidates to build their (sometimes partial) used on method candidates to build their (sometimes partial)
signature. */ signature. */
static tree 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 signature, tree (*signature_builder) (tree))
{ {
tree method; tree method;
int first_time = 1;
if (searched_interface) /* 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)
{
/* 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 i;
int interface_len = int interface_len =
TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_interface)) - 1; TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_class)) - 1;
for (i = interface_len; i > 0; i--) for (i = interface_len; i > 0; i--)
{ {
tree child = tree child =
TREE_VEC_ELT (TYPE_BINFO_BASETYPES (searched_interface), i); TREE_VEC_ELT (TYPE_BINFO_BASETYPES (searched_class), i);
tree iclass = BINFO_TYPE (child); tree iclass = BINFO_TYPE (child);
/* If the superinterface hasn't been loaded yet, do so now. */ /* If the superinterface hasn't been loaded yet, do so now. */
...@@ -776,35 +808,21 @@ lookup_do (tree searched_class, tree searched_interface, tree method_name, ...@@ -776,35 +808,21 @@ lookup_do (tree searched_class, tree searched_interface, tree method_name,
else if (!CLASS_LOADED_P (iclass)) else if (!CLASS_LOADED_P (iclass))
load_class (iclass, 1); load_class (iclass, 1);
for (method = TYPE_METHODS (iclass); /* Note that we don't care about SEARCH_VISIBLE here,
method != NULL_TREE; method = TREE_CHAIN (method)) since an interface can never have an invisible
{ method. */
tree method_sig = (*signature_builder) (TREE_TYPE (method)); method = lookup_do (iclass, SEARCH_INTERFACE,
method_name, signature, signature_builder);
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) if (method != NULL_TREE)
return method; return method;
} }
} }
}
while (searched_class != NULL_TREE) /* If we're only searching for interface methods, then we've
{ already searched all the superinterfaces. Our superclass is
for (method = TYPE_METHODS (searched_class); Object, but we don't want to search that. */
method != NULL_TREE; method = TREE_CHAIN (method)) if ((flags & SEARCH_ONLY_INTERFACE))
{ break;
tree method_sig = (*signature_builder) (TREE_TYPE (method));
if (DECL_NAME (method) == method_name && method_sig == signature)
return method;
}
searched_class = CLASSTYPE_SUPER (searched_class); searched_class = CLASSTYPE_SUPER (searched_class);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment