This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR java/13273: [3.4 regression] gcj generates call to abstract method


This problem was caused by method lookup being performed in the wrong
order by the bytecode compiler: we were looking at interfaces before
superclasses, whereas the spec is quite clear that we must look first
at superclasses.

I rewrote lookup_do() because there seemed no way to patch it so that
one could be sure it followed the spec.

Checked x86_64-unknown-linux-gnu full bootstrap + full Eclipse build,
no regressions.

Andrew.


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.

Index: java/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/typeck.c,v
retrieving revision 1.58
diff -p -2 -c -r1.58 typeck.c
*** java/typeck.c	20 Dec 2003 15:38:28 -0000	1.58
--- java/typeck.c	16 Jan 2004 16:25:57 -0000
*************** has_method (tree class, tree method_name
*** 736,739 ****
--- 736,825 ----
  }
  
+ /* 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
*************** has_method (tree class, tree method_name
*** 746,752 ****
     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.
--- 832,835 ----
*************** lookup_do (tree searched_class, int flag
*** 760,831 ****
  {
    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;
  
!   while (searched_class != NULL_TREE)
      {
-       /* 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);
      }
  
!   return NULL_TREE;
  }
  
--- 843,876 ----
  {
    tree method;
!     
!   if (searched_class == NULL_TREE)
!     return NULL_TREE;
  
!   if (flags & SEARCH_SUPER)
      {
        searched_class = CLASSTYPE_SUPER (searched_class);
+       if (searched_class == 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;
  }
  
Index: java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.175
diff -p -2 -c -r1.175 decl.c
*** java/decl.c	9 Jan 2004 17:08:43 -0000	1.175
--- java/decl.c	16 Jan 2004 16:25:51 -0000
*************** java_expand_body (tree fndecl)
*** 1821,1826 ****
    current_function_decl = fndecl;
    input_location = DECL_SOURCE_LOCATION (fndecl);
!   output_class = DECL_CONTEXT (current_function_decl);
!   current_class = DECL_CONTEXT (fndecl);
  
    timevar_push (TV_EXPAND);
--- 1821,1825 ----
    current_function_decl = fndecl;
    input_location = DECL_SOURCE_LOCATION (fndecl);
!   output_class = current_class = DECL_CONTEXT (fndecl);
  
    timevar_push (TV_EXPAND);
Index: java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.193
diff -p -2 -c -r1.193 java-tree.h
*** java/java-tree.h	9 Jan 2004 19:55:13 -0000	1.193
--- java/java-tree.h	16 Jan 2004 16:25:52 -0000
*************** struct lang_type GTY(())
*** 1118,1123 ****
  #define SEARCH_INTERFACE      1
  #define SEARCH_SUPER          2
! #define SEARCH_ONLY_INTERFACE 4
! #define SEARCH_VISIBLE        8
  
  extern void java_parse_file (int);
--- 1118,1122 ----
  #define SEARCH_INTERFACE      1
  #define SEARCH_SUPER          2
! #define SEARCH_VISIBLE        4
  
  extern void java_parse_file (int);
Index: java/jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.156
diff -p -2 -c -r1.156 jcf-parse.c
*** java/jcf-parse.c	9 Jan 2004 17:08:44 -0000	1.156
--- java/jcf-parse.c	16 Jan 2004 16:25:52 -0000
*************** read_class (tree name)
*** 469,472 ****
--- 469,473 ----
    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;
*************** read_class (tree name)
*** 546,550 ****
      }
  
!   output_class = current_class = save_current_class;
    input_location = save_location;
    current_jcf = save_current_jcf;
--- 547,552 ----
      }
  
!   output_class = save_output_class;
!   current_class = save_current_class;
    input_location = save_location;
    current_jcf = save_current_jcf;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]