diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index a7c2855836f..8cb93760ea5 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,15 @@ +2004-01-16 Andrew Haley + + 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 * class.c (gen_indirect_dispatch_tables): Fix string length diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 1ce2ad324c2..ab8c2ae7ab4 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 9d4fcdd27a7..22f41bd7523 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 32140920676..309c28da153 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 ddee2ba198b..dc8a8c56255 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 (searched_class == NULL_TREE) + return NULL_TREE; - /* 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) + 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.