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]

Patch: RFC: ugly workaround for PR 26390


I'm not checking this in, I thought I'd ask for comments first.

In PR 26390 we are picking the wrong method to call.  If a method m is
declared in A and inherited by B, gcj doesn't realize that this method
is also 'B.m'.  In the PR this leads us to choose the wrong method
when making a super call.  See the patch for a reduced test case.

This patch is a huge hack.  However, I was reluctant to do anything
more complicated since, hopefully, we'll be removing this part of gcj
in the not-so-distant future.

FWIW I think a cleaner fix would look like adding 'invisible' methods
whenever we inherit a method from a superclass (and not just from
interfaces).  My concern is that we would then have to unwrap these at
various places to refer to the method as actually declared; and that
there might also be other unknown fallout from doing this.

The idea in the patch is that if we're trying to pick the most
specific method, and we are comparing a method from a class to a
method from an interface, then we pretend that the method from the
concrete class was declared in the qualifying class -- and not its
actual declaring class.

I think this works in all the cases -- when comparing two interface
methods, or two methods from classes, we compare as before; this
leaves the choice of the most specific method unchanged (as compared
to before the patch).

Any method declared in a class will be considered more specific than a
method declared in an interface, but I don't know of a situation where
that can hurt.

This passes jacks and our test suite.

Tom

Index: gcc/java/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	PR java/26390:
	* parse.y (find_most_specific_methods_list): Added 'class'
	argument.
	(lookup_method_invoke): Updated.

Index: libjava/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	PR java/26390:
	* testsuite/libjava.lang/pr26390.out: New file.
	* testsuite/libjava.lang/pr26390.java: New file.

Index: gcc/java/parse.y
===================================================================
--- gcc/java/parse.y	(revision 112101)
+++ gcc/java/parse.y	(working copy)
@@ -134,7 +134,7 @@
 static int invocation_mode (tree, int);
 static tree find_applicable_accessible_methods_list (int, tree, tree, tree);
 static void search_applicable_methods_list (int, tree, tree, tree, tree *, tree *);
-static tree find_most_specific_methods_list (tree);
+static tree find_most_specific_methods_list (tree, tree);
 static int argument_types_convertible (tree, tree);
 static tree patch_invoke (tree, tree, tree);
 static int maybe_use_access_method (int, tree *, tree *);
@@ -11249,7 +11249,7 @@
   /* Find all candidates and then refine the list, searching for the
      most specific method. */
   list = find_applicable_accessible_methods_list (lc, class, name, atl);
-  list = find_most_specific_methods_list (list);
+  list = find_most_specific_methods_list (list, class);
   if (list && !TREE_CHAIN (list))
     return TREE_VALUE (list);
 
@@ -11441,7 +11441,7 @@
 /* 15.11.2.2 Choose the Most Specific Method */
 
 static tree
-find_most_specific_methods_list (tree list)
+find_most_specific_methods_list (tree list, tree class)
 {
   int max = 0;
   int abstract, candidates;
@@ -11464,8 +11464,23 @@
 	  /* Compare arguments and location where methods where declared */
 	  if (argument_types_convertible (method_v, current_v))
 	    {
+	      /* We have a rather odd special case here.  The front
+		 end doesn't properly implement inheritance, so we
+		 work around it here.  The idea is, if we are
+		 comparing a method declared in a class to one
+		 declared in an interface, and the invocation's
+		 qualifying class is a class (and not an interface),
+		 then we consider the method's class to be the
+		 qualifying class of the invocation.  This lets us
+		 fake the result of ordinary inheritance.  */
+	      tree context_v = DECL_CONTEXT (current_v);
+	      if (TYPE_INTERFACE_P (DECL_CONTEXT (method_v))
+		  && ! TYPE_INTERFACE_P (context_v)
+		  && ! TYPE_INTERFACE_P (class))
+		context_v = class;
+
 	      if (valid_method_invocation_conversion_p
-		  (DECL_CONTEXT (method_v), DECL_CONTEXT (current_v)))
+		  (DECL_CONTEXT (method_v), context_v))
 		{
 		  int v = (DECL_SPECIFIC_COUNT (current_v) += 1);
 		  max = (v > max ? v : max);
Index: libjava/testsuite/libjava.lang/pr26390.out
===================================================================
Index: libjava/testsuite/libjava.lang/pr26390.java
===================================================================
--- libjava/testsuite/libjava.lang/pr26390.java	(revision 0)
+++ libjava/testsuite/libjava.lang/pr26390.java	(revision 0)
@@ -0,0 +1,45 @@
+public class pr26390
+{
+  public interface ComponentPeer {
+    public void setBounds();
+  }
+
+  public interface ContainerPeer extends ComponentPeer {
+  }
+
+  public interface WindowPeer extends ContainerPeer {
+  }
+
+  public interface FramePeer extends WindowPeer {
+  }
+
+  public static class SwingComponentPeer implements ComponentPeer {
+    public void setBounds() {
+    }
+  }
+
+  public static class SwingContainerPeer
+    extends SwingComponentPeer implements ContainerPeer
+  {
+  }
+
+  public static class SwingWindowPeer
+    extends SwingContainerPeer implements WindowPeer
+  {
+  }
+
+  public static class SwingFramePeer
+    extends SwingWindowPeer implements FramePeer
+  {
+    public void setBounds() {
+      super.setBounds();
+    }
+  }
+
+  public static void main(String[] args)
+  {
+    SwingFramePeer s = new SwingFramePeer();
+    s.setBounds();
+  }
+}
+


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