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 ();
...@@ -1747,14 +1750,14 @@ layout_class (tree this_class) ...@@ -1747,14 +1750,14 @@ layout_class (tree this_class)
{ {
tree super_class = CLASSTYPE_SUPER (this_class); tree super_class = CLASSTYPE_SUPER (this_class);
tree field; tree field;
class_list = tree_cons (this_class, NULL_TREE, class_list); class_list = tree_cons (this_class, NULL_TREE, class_list);
if (CLASS_BEING_LAIDOUT (this_class)) if (CLASS_BEING_LAIDOUT (this_class))
{ {
char buffer [1024]; char buffer [1024];
char *report; char *report;
tree current; tree current;
sprintf (buffer, " with `%s'", sprintf (buffer, " with `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)))); IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
obstack_grow (&temporary_obstack, buffer, strlen (buffer)); obstack_grow (&temporary_obstack, buffer, strlen (buffer));
...@@ -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,14 +1841,61 @@ layout_class (tree this_class) ...@@ -1837,14 +1841,61 @@ 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)));
CLASS_BEING_LAIDOUT (this_class) = 0; CLASS_BEING_LAIDOUT (this_class) = 0;
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,11 +1917,20 @@ layout_class_methods (tree this_class) ...@@ -1866,11 +1917,20 @@ 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);
method_decl; method_decl = TREE_CHAIN (method_decl)) 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); method_decl, dtable_count);
TYPE_NVIRTUALS (this_class) = dtable_count; TYPE_NVIRTUALS (this_class) = dtable_count;
......
...@@ -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)
......
...@@ -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,124 +687,142 @@ set_java_signature (tree type, tree sig) ...@@ -687,124 +687,142 @@ 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
int i; a method declared in an interface context. */
int interface_len = if (searched_class != NULL_TREE
TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_interface)) - 1; && CLASS_INTERFACE (TYPE_NAME (searched_class)))
flags |= SEARCH_ONLY_INTERFACE;
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;
}
}
}
while (searched_class != NULL_TREE) while (searched_class != NULL_TREE)
{ {
for (method = TYPE_METHODS (searched_class); /* First search this class. If we're only searching the
method != NULL_TREE; method = TREE_CHAIN (method)) superclass, skip this. */
{ if (! ((flags & SEARCH_SUPER) && first_time))
tree method_sig = (*signature_builder) (TREE_TYPE (method)); {
if (DECL_NAME (method) == method_name && method_sig == signature) for (method = TYPE_METHODS (searched_class);
return method; 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); 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