aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Haley <aph@redhat.com>2004-01-16 17:11:08 +0000
committerAndrew Haley <aph@gcc.gnu.org>2004-01-16 17:11:08 +0000
commite081a9c4c7807286757f2e8054f79cedcb67d5b2 (patch)
tree8ba436e6c9894a273df64bd748665bd74dfab8b7 /gcc
parentab8ffc795c01db35bc620c7f22a2c5236ba958c2 (diff)
downloadgcc-e081a9c4c7807286757f2e8054f79cedcb67d5b2.zip
gcc-e081a9c4c7807286757f2e8054f79cedcb67d5b2.tar.gz
gcc-e081a9c4c7807286757f2e8054f79cedcb67d5b2.tar.bz2
re PR java/13273 (gcj generates call to abstract method)
2004-01-16 Andrew Haley <aph@redhat.com> PR java/13273: * typeck.c (shallow_find_method): New. (find_method_in_superclasses): New. (find_method_in_interfaces): New. (lookup_do): Rewrite. * java-tree.h (SEARCH_ONLY_INTERFACE): Delete. * jcf-parse.c (read_class): Save and restore output_class. * decl.c (java_expand_body): Set output_class from fndecl. From-SVN: r75980
Diffstat (limited to 'gcc')
-rw-r--r--gcc/java/ChangeLog12
-rw-r--r--gcc/java/decl.c3
-rw-r--r--gcc/java/java-tree.h3
-rw-r--r--gcc/java/jcf-parse.c4
-rw-r--r--gcc/java/typeck.c177
5 files changed, 128 insertions, 71 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index a7c2855..8cb9376 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,15 @@
+2004-01-16 Andrew Haley <aph@redhat.com>
+
+ PR java/13273:
+ * typeck.c (shallow_find_method): New.
+ (find_method_in_superclasses): New.
+ (find_method_in_interfaces): New.
+ (lookup_do): Rewrite.
+ * java-tree.h (SEARCH_ONLY_INTERFACE): Delete.
+
+ * jcf-parse.c (read_class): Save and restore output_class.
+ * decl.c (java_expand_body): Set output_class from fndecl.
+
2004-01-15 Michael Chastain <mec.gnu@mindspring.com>
* class.c (gen_indirect_dispatch_tables): Fix string length
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 1ce2ad3..ab8c2ae 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -1820,8 +1820,7 @@ java_expand_body (tree fndecl)
current_function_decl = fndecl;
input_location = DECL_SOURCE_LOCATION (fndecl);
- output_class = DECL_CONTEXT (current_function_decl);
- current_class = DECL_CONTEXT (fndecl);
+ output_class = current_class = DECL_CONTEXT (fndecl);
timevar_push (TV_EXPAND);
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 9d4fcdd..22f41bd 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -1117,8 +1117,7 @@ struct lang_type GTY(())
/* 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
+#define SEARCH_VISIBLE 4
extern void java_parse_file (int);
extern bool java_mark_addressable (tree);
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 3214092..309c28d 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -468,6 +468,7 @@ read_class (tree name)
JCF this_jcf, *jcf;
tree icv, class = NULL_TREE;
tree save_current_class = current_class;
+ tree save_output_class = output_class;
location_t save_location = input_location;
JCF *save_current_jcf = current_jcf;
@@ -545,7 +546,8 @@ read_class (tree name)
load_inner_classes (class);
}
- output_class = current_class = save_current_class;
+ output_class = save_output_class;
+ current_class = save_current_class;
input_location = save_location;
current_jcf = save_current_jcf;
return 1;
diff --git a/gcc/java/typeck.c b/gcc/java/typeck.c
index ddee2ba..dc8a8c5 100644
--- a/gcc/java/typeck.c
+++ b/gcc/java/typeck.c
@@ -735,6 +735,92 @@ has_method (tree class, tree method_name)
build_null_signature) != NULL_TREE;
}
+/* Search in class SEARCHED_CLASS, but not its superclasses, for a
+ method matching METHOD_NAME and signature SIGNATURE. A private
+ helper for lookup_do. */
+static tree
+shallow_find_method (tree searched_class, int flags, tree method_name,
+ tree signature, tree (*signature_builder) (tree))
+{
+ tree method;
+ 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;
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Search in the superclasses of SEARCHED_CLASS for a method matching
+ METHOD_NAME and signature SIGNATURE. A private helper for
+ lookup_do. */
+static tree
+find_method_in_superclasses (tree searched_class, int flags,
+ tree method_name,
+ tree signature, tree (*signature_builder) (tree))
+{
+ tree klass;
+ for (klass = CLASSTYPE_SUPER (searched_class); klass != NULL_TREE;
+ klass = CLASSTYPE_SUPER (klass))
+ {
+ tree method;
+ method = shallow_find_method (klass, flags, method_name,
+ signature, signature_builder);
+ if (method != NULL_TREE)
+ return method;
+ }
+
+ return NULL_TREE;
+}
+
+/* Search in the interfaces of SEARCHED_CLASS and its superinterfaces
+ for a method matching METHOD_NAME and signature SIGNATURE. A
+ private helper for lookup_do. */
+static tree
+find_method_in_interfaces (tree searched_class, int flags, tree method_name,
+ tree signature, tree (*signature_builder) (tree))
+{
+ 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);
+
+ /* First, we look in ICLASS. If that doesn't work we'll
+ recursively look through all its superinterfaces. */
+ tree method = shallow_find_method (iclass, flags, method_name,
+ signature, signature_builder);
+ if (method != NULL_TREE)
+ return method;
+
+ method = find_method_in_interfaces
+ (iclass, flags, method_name, signature, signature_builder);
+ if (method != NULL_TREE)
+ return method;
+ }
+
+ return NULL_TREE;
+}
+
+
/* Search in class SEARCHED_CLASS (and its superclasses) for a method
matching METHOD_NAME and signature SIGNATURE. FLAGS control some
parameters of the search.
@@ -745,9 +831,6 @@ has_method (tree class, tree method_name)
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.
@@ -759,74 +842,36 @@ lookup_do (tree searched_class, int flags, tree method_name,
tree signature, tree (*signature_builder) (tree))
{
tree 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;
+
+ if (searched_class == NULL_TREE)
+ return NULL_TREE;
- while (searched_class != NULL_TREE)
+ if (flags & SEARCH_SUPER)
{
- /* 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);
+ if (searched_class == NULL_TREE)
+ return NULL_TREE;
}
- return NULL_TREE;
+ /* First look in our own methods. */
+ method = shallow_find_method (searched_class, flags, method_name,
+ signature, signature_builder);
+ if (method)
+ return method;
+
+ /* Then look in our superclasses. */
+ if (! CLASS_INTERFACE (TYPE_NAME (searched_class)))
+ method = find_method_in_superclasses (searched_class, flags, method_name,
+ signature, signature_builder);
+ if (method)
+ return method;
+
+ /* If that doesn't work, look in our interfaces. */
+ if (flags & SEARCH_INTERFACE)
+ method = find_method_in_interfaces (searched_class, flags, method_name,
+ signature, signature_builder);
+
+ return method;
}
/* Search in class CLAS for a constructor matching METHOD_SIGNATURE.