]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
parse.y (java_check_regular_methods): Typo fixes.
authorTom Tromey <tromey@redhat.com>
Tue, 12 Aug 2003 20:34:51 +0000 (20:34 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Tue, 12 Aug 2003 20:34:51 +0000 (20:34 +0000)
* 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

gcc/java/ChangeLog
gcc/java/class.c
gcc/java/java-tree.h
gcc/java/jcf-write.c
gcc/java/jcf.h
gcc/java/parse.y
gcc/java/typeck.c

index 0d6578ceaed006679b0f882e54203e5d8ea883e7..10358153bf0f0c9e27a5e71cdd1d4097cf97bd52 100644 (file)
@@ -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:
index fbec8d0a9caf83fd1053330b36864f2b476f3a8e..620a8a2e6c96d467a66b239cb076a52d2a150598 100644 (file)
@@ -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;
index 920d28866531c88804baaa2d331f5c93531babe1..0a7a542a9f5c92fda5c7ca67ff26a1a6ebbb4fbd 100644 (file)
@@ -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)
index 44c9ec1cf80dcdd02b2b0d2f8458d3d535aaa21c..3609807a4100d7e00bc796ca39909a64209fe833 100644 (file)
@@ -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);
index 970656732c063f4b271225f7ebdfe0935ea9180f..5b97fec95256b0f22042c5fd41cfdc45be642c9f 100644 (file)
@@ -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)
 
index 6ca734aa68465da3206726e144d884f527e05e71..a9f8d6ecc6b89e07ca4d0427bddff5a86b690c5d 100644 (file)
@@ -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
index 468de74cbb6841c4912c1b64ebe217ca0779c2c3..972cb8b3686b3b5540633b0df9cbe785f1a81d3e 100644 (file)
@@ -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);
     }