re PR java/13273 (gcj generates call to abstract method)
authorAndrew Haley <aph@redhat.com>
Fri, 16 Jan 2004 17:11:08 +0000 (17:11 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Fri, 16 Jan 2004 17:11:08 +0000 (17:11 +0000)
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

gcc/java/ChangeLog
gcc/java/decl.c
gcc/java/java-tree.h
gcc/java/jcf-parse.c
gcc/java/typeck.c

index a7c2855..8cb9376 100644 (file)
@@ -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
index 1ce2ad3..ab8c2ae 100644 (file)
@@ -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);
 
index 9d4fcdd..22f41bd 100644 (file)
@@ -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);
index 3214092..309c28d 100644 (file)
@@ -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;
index ddee2ba..dc8a8c5 100644 (file)
@@ -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.