[PATCH] Java: Fix to PR #108 + interface dispatch fix.

Alexandre Petit-Bianco apbianco@cygnus.com
Mon Mar 6 22:28:00 GMT 2000


I'm checking in this fix to PR #108, which also includes an interface
dispatch fix from Godmar Back:

  http://sourceware.cygnus.com/ml/java-prs/1999-q4/msg00174.html
  http://gcc.gnu.org/ml/gcc-patches/1999-12/msg00539.html

./A

2000-03-06  Bryce McKinlay <bryce@albatross.co.nz>

	* typeck.c (lookup_do): Search superinterfaces first
	when looking up an interface method. From Godmar Back
	<gback@cs.utah.edu>

2000-03-02  Alexandre Petit-Bianco  <apbianco@cygnus.com>

	* java-tree.h (lookup_argument_method2): Declared.
	(safe_layout_class): Prototype moved from parse.h.
	* parse.h (safe_layout_class): Prototype moved to java-tree.h.
	* parse.y (java_check_regular_methods): Local `super_class' gone.
	Call lookup_argument_method2 instead of lookup_argument_method.
	Perform modifier match for methods found declared in implemented
	interfaces. Fixed indentation problem. Overriding/hiding error
	report to take place only for methods found in classes.
	* typeck.c (lookup_argument_method): Changed leading
	comment. Re-written by calling lookup_do.
	(lookup_argument_method2): New function.
	(lookup_java_method): Re-written by calling lookup_do.
	(lookup_do): New function.

Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/java-tree.h,v
retrieving revision 1.56
diff -u -p -r1.56 java-tree.h
--- java-tree.h	2000/03/04 22:27:35	1.56
+++ java-tree.h	2000/03/07 06:16:24
@@ -510,6 +510,7 @@ extern tree lookup_class PARAMS ((tree))
 extern tree lookup_java_constructor PARAMS ((tree, tree));
 extern tree lookup_java_method PARAMS ((tree, tree, tree));
 extern tree lookup_argument_method PARAMS ((tree, tree, tree));
+extern tree lookup_argument_method2 PARAMS ((tree, tree, tree));
 extern tree promote_type PARAMS ((tree));
 extern tree get_constant PARAMS ((struct JCF*, int));
 extern tree get_name_constant PARAMS ((struct JCF*, int));
@@ -665,6 +666,7 @@ extern char* open_class PARAMS ((char *,
 # endif /* JCF_USE_STDIO */
 #endif
 void java_debug_context PARAMS ((void));
+void safe_layout_class PARAMS ((tree));
 
 extern tree get_boehm_type_descriptor PARAMS ((tree));
 
Index: parse.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.h,v
retrieving revision 1.45
diff -u -p -r1.45 parse.h
--- parse.h	2000/02/29 02:34:48	1.45
+++ parse.h	2000/03/07 06:16:26
@@ -678,7 +678,6 @@ struct parser_ctxt {
 };
 
 #ifndef JC1_LITE
-void safe_layout_class PARAMS ((tree));
 void java_complete_class PARAMS ((void));
 void java_check_circular_reference PARAMS ((void));
 void java_fix_constructors PARAMS ((void));
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/parse.y,v
retrieving revision 1.136
diff -u -p -r1.136 parse.y
--- parse.y	2000/02/26 02:05:35	1.136
+++ parse.y	2000/03/07 06:16:54
@@ -4762,7 +4762,7 @@ check_abstract_method_definitions (do_in
     }
 }
 
-/* Check that CLASS_DECL somehoow implements all inherited abstract
+/* Check that CLASS_DECL somehow implements all inherited abstract
    methods.  */
 
 static void
@@ -4807,7 +4807,6 @@ java_check_regular_methods (class_decl)
   int saw_constructor = 0;
   tree method;
   tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl));
-  tree super_class = CLASSTYPE_SUPER (class);
   tree saved_found_wfl = NULL_TREE, found = NULL_TREE;
   tree mthrows;
 
@@ -4859,7 +4858,7 @@ java_check_regular_methods (class_decl)
 	}
 
       sig = build_java_argument_signature (TREE_TYPE (method));
-      found = lookup_argument_method (super_class, DECL_NAME (method), sig);
+      found = lookup_argument_method2 (class, DECL_NAME (method), sig);
 
       /* Nothing overrides or it's a private method. */
       if (!found)
@@ -4875,12 +4874,25 @@ java_check_regular_methods (class_decl)
       saved_found_wfl = DECL_NAME (found);
       reset_method_name (found);
 
+      /* If `found' is declared in an interface, make sure the
+	 modifier matches. */
+      if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (found))) 
+	  && clinit_identifier_node != DECL_NAME (found)
+	  && !METHOD_PUBLIC (method))
+	{
+	  tree found_decl = TYPE_NAME (DECL_CONTEXT (found));
+	  parse_error_context (method_wfl, "Class `%s' must override `%s' with a public method in order to implement interface `%s'",
+			       IDENTIFIER_POINTER (DECL_NAME (class_decl)),
+			       lang_printable_name (method, 0),
+			       IDENTIFIER_POINTER (DECL_NAME (found_decl)));
+	}
+
       /* Can't override a method with the same name and different return
 	 types. */
       if (TREE_TYPE (TREE_TYPE (found)) != TREE_TYPE (TREE_TYPE (method)))
 	{
-	  char *t = xstrdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)),
-						 0));
+	  char *t = xstrdup 
+	    (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), 0));
 	  parse_error_context 
 	    (method_wfl,
 	     "Method `%s' was defined with return type `%s' in class `%s'", 
@@ -4943,12 +4955,15 @@ java_check_regular_methods (class_decl)
 	 - Overriding/hiding protected must be protected or public
          - If the overriden or hidden method has default (package)
            access, then the overriding or hiding method must not be
-           private; otherwise, a compile-time error occurs */
-      if ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method)) 
-	  || (METHOD_PROTECTED (found) 
-	      && !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method)))
-	  || (!(aflags & (ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC))
-	      && METHOD_PRIVATE (method)))
+           private; otherwise, a compile-time error occurs.  If
+           `found' belongs to an interface, things have been already
+           taken care of.  */
+      if (!CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (found)))
+	  && ((METHOD_PUBLIC (found) && !METHOD_PUBLIC (method))
+	      || (METHOD_PROTECTED (found) 
+		  && !(METHOD_PUBLIC (method) || METHOD_PROTECTED (method)))
+	      || (!(aflags & (ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC))
+		  && METHOD_PRIVATE (method))))
 	{
 	  parse_error_context 
 	    (method_wfl,
Index: typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/typeck.c,v
retrieving revision 1.24
diff -u -p -r1.24 typeck.c
--- typeck.c	2000/02/26 19:56:23	1.24
+++ typeck.c	2000/03/07 06:16:55
@@ -37,6 +37,7 @@ The Free Software Foundation is independ
 static tree convert_ieee_real_to_integer PARAMS ((tree, tree));
 static tree parse_signature_type PARAMS ((const unsigned char **,
 					 const unsigned char *));
+static tree lookup_do PARAMS ((tree, tree, tree, tree, tree (*)(tree)));
 
 tree * type_map;
 extern struct obstack permanent_obstack;
@@ -713,106 +714,129 @@ set_java_signature (type, sig)
 #endif
 }
 
-/* Search in class CLAS (and its superclasses) 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.) */
+/* 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.  */
 
 tree
-lookup_argument_method (clas, method_name, method_signature)
-     tree clas, method_name, method_signature;
+lookup_argument_method (searched_class, method_name, method_signature)
+     tree searched_class, method_name, method_signature;
 {
-  tree method;
-  while (clas != NULL_TREE)
-    {
-      for (method = TYPE_METHODS (clas);
-	   method != NULL_TREE;  method = TREE_CHAIN (method))
-	{
-	  tree method_sig = build_java_argument_signature (TREE_TYPE (method));
-	  tree name = DECL_NAME (method);
-	  if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
-	       EXPR_WFL_NODE (name) : name) == method_name 
-	      && method_sig == method_signature)
-	    return method;
-	}
-      clas = CLASSTYPE_SUPER (clas);
-    }
-  return NULL_TREE;
+  return lookup_do (searched_class, NULL_TREE, method_name, method_signature, 
+		    build_java_argument_signature);
 }
 
-/* Search in class CLAS (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.) */
+/* 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.) */
 
 tree
-lookup_java_method (searched_class, method_name, method_signature)
+lookup_argument_method2 (searched_class, method_name, method_signature)
      tree searched_class, method_name, method_signature;
 {
-  tree method;
-  tree currently_searched = searched_class;
-
-  while (currently_searched != NULL_TREE)
-    {
-      for (method = TYPE_METHODS (currently_searched);
-	   method != NULL_TREE;  method = TREE_CHAIN (method))
-	{
-	  tree method_sig = build_java_signature (TREE_TYPE (method));
-	  tree name = DECL_NAME (method);
+  return lookup_do (CLASSTYPE_SUPER (searched_class), searched_class,
+		    method_name, method_signature, 
+		    build_java_argument_signature);
+}
 
-	  if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
-	       EXPR_WFL_NODE (name) : name) == method_name
-	      && method_sig == method_signature)
-	    return method;
-	}
-      currently_searched = CLASSTYPE_SUPER (currently_searched);
-    }
+/* 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
+   SEARCHED_CLASS is an interface, search it too. */
 
-  /* If this class is an interface class, search its superinterfaces as
-   * well.  A superinterface is not an interface's superclass: a
-   * super interface is implemented by the interface.
-   */
+tree
+lookup_java_method (searched_class, method_name, method_signature)
+     tree searched_class, method_name, 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, 
+		    method_signature, build_java_signature);
+}
+
+/* Search in class SEARCHED_CLASS (an its superclasses) for a method
+   matching METHOD_NAME and signature SIGNATURE.  Also search in
+   SEARCHED_INTERFACE (an 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.  */
 
-  currently_searched = searched_class;
-  if (CLASS_INTERFACE (TYPE_NAME (currently_searched)))
+static tree
+lookup_do (searched_class, searched_interface, method_name, signature, signature_builder)
+     tree searched_class, searched_interface, method_name, signature;
+     tree (*signature_builder) PARAMS ((tree));
+{
+  tree method;
+  
+  if (searched_interface)
     {
       int i;
       int interface_len = 
-	TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (currently_searched)) - 1;
+	TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_interface)) - 1;
 
       for (i = interface_len; i > 0; i--)
        {
          tree child = 
-	   TREE_VEC_ELT (TYPE_BINFO_BASETYPES (currently_searched), i);
+	   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_LOADED_P (iclass))
-           load_class (iclass, 1);
+	 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 = build_java_signature (TREE_TYPE (method));
+             tree method_sig = (*signature_builder) (TREE_TYPE (method));
 	     tree name = DECL_NAME (method);
 
 	     if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
 		  EXPR_WFL_NODE (name) : name) == method_name
-		 && method_sig == method_signature)
+		 && method_sig == signature)
                return method;
            }
 
          /* it could be defined in a supersuperinterface */
          if (CLASS_INTERFACE (TYPE_NAME (iclass)))
            {
-             method = lookup_java_method (iclass, 
-					  method_name, 
-					  method_signature);
+             method = lookup_do (iclass, iclass, method_name, 
+				 signature, signature_builder);
              if (method != NULL_TREE) 
 	       return method;
            }
        }
     }
+
+  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));
+	  tree name = DECL_NAME (method);
+
+	  if ((TREE_CODE (name) == EXPR_WITH_FILE_LOCATION ?
+	       EXPR_WFL_NODE (name) : name) == method_name
+	      && method_sig == signature)
+	    return method;
+	}
+      searched_class = CLASSTYPE_SUPER (searched_class);
+    }
+
   return NULL_TREE;
 }
 


More information about the Gcc-patches mailing list