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] PR java/19870: Private static members accessed across nestedclasses (Part 2, Take 2)


Hi,

  Here is a resubmission of the patch for PR java/19870 part 2:

    http://gcc.gnu.org/ml/java-patches/2005-q2/msg00742.html

I had withdrawn that patch to investigate a miscompilation of
java.util.AbstractList$1.finit$(). I have fixed that in this
version of the patch. I apologise for the unnecessarily long
time I took to get around to submitting this.

Tested on i686-pc-linux-gnu. The effect of this patch on
the libjava testsuite (including Jacks) is:

  FAIL: 15.12.3-explicit-constructor-9
  FAIL: 3.10.2-round-8
  XPASS: 8.5.2-non-static-member-usage-2
  XPASS: 3.10.2-double-14

3.10.2-round-8 and 3.10.2-double-14 are side-effects of the bug
reported in PR java/22113 and just happen to be exposed by this
patch. I therefore recommend adjusting jacks.xfail only for the
other two for this patch.

I am attaching the patch and the testsuite adjustments for this
patch, including a test that demonstrates what is now possible.

Thanks,
Ranjit.

:ADDPATCH java:

-- 
Ranjit Mathew       Email: rmathew AT gmail DOT com

Bangalore, INDIA.     Web: http://ranjitmathew.hostingzero.com/
Index: ChangeLog
from  Ranjit Mathew  <rmathew@hotmail.com>

	PR java/19870
	* parse.y (nested_field_access_p): Rename to nested_member_access_p
	and expand to handle method accesses across nested classes.
	(build_outer_method_access_method): Rename to
	build_nested_method_access_method.  Minor adjustments to comments.
	(resolve_expression_name): Use the newly-renamed
	nested_member_access_p method.
	(resolve_qualified_expression_name): Likewise.
	(patch_method_invocation): Also consider static methods for access
	method generation.  Minor adjustments to comments.
	(maybe_use_access_method): Use the more general
	nested_memeber_access_p to determine access across nested class
	boundaries.  Allow THIS_ARG to be NULL (for static methods).

Index: parse.y
===================================================================
--- parse.y	2005-08-13 11:39:50.000000000 +0530
+++ parse.y	2005-08-14 18:24:53.000000000 +0530
@@ -326,10 +326,10 @@ static tree build_nested_field_access (t
 static tree build_nested_field_access_methods (tree);
 static tree build_nested_field_access_method (tree, tree, tree, tree, tree);
 static tree build_nested_field_access_expr (int, tree, tree, tree, tree);
-static tree build_outer_method_access_method (tree);
+static tree build_nested_method_access_method (tree);
 static tree build_new_access_id (void);
 
-static int nested_field_access_p (tree, tree);
+static int nested_member_access_p (tree, tree);
 static int nested_field_expanded_access_p (tree, tree *, tree *, tree *);
 static tree nested_field_access_fix (tree, tree, tree);
 
@@ -8371,20 +8371,22 @@ build_nested_field_access (tree id, tree
   return resolve_expression_name (access, NULL);
 }
 
-/* Return a nonzero value if DECL describes a field access across nested
+/* Return a nonzero value if DECL describes a member access across nested
    class boundaries.  That is, DECL is in a class that either encloses,
-   is enclosed by or shares a common enclosing class with, the class
+   is enclosed by or shares a common enclosing class with the class
    TYPE.  */
 
 static int
-nested_field_access_p (tree type, tree decl)
+nested_member_access_p (tree type, tree decl)
 {
   bool is_static = false;
   tree decl_type = DECL_CONTEXT (decl);
   tree type_root, decl_type_root;
 
   if (decl_type == type
-      || (TREE_CODE (decl) != FIELD_DECL && TREE_CODE (decl) != VAR_DECL))
+      || (TREE_CODE (decl) != FIELD_DECL
+          && TREE_CODE (decl) != VAR_DECL
+          && TREE_CODE (decl) != FUNCTION_DECL))
     return 0;
   
   if (!INNER_CLASS_TYPE_P (type)
@@ -8392,10 +8394,12 @@ nested_field_access_p (tree type, tree d
            && INNER_CLASS_TYPE_P (decl_type)))
     return 0;
 
-  is_static = FIELD_STATIC (decl);
+  is_static = (TREE_CODE (decl) == FUNCTION_DECL)
+              ? METHOD_STATIC (decl)
+              : FIELD_STATIC (decl);
 
   /* If TYPE extends the declaration context of the non-static
-     field we're trying to access, then this isn't a nested field
+     member we're trying to access, then this isn't a nested member
      access we need to worry about.  */
   if (!is_static && inherits_from_p (type, decl_type))
     return 0;
@@ -8672,10 +8676,10 @@ build_nested_field_access_method (tree c
 
 
 /* This section deals with building access function necessary for
-   certain kinds of method invocation from inner classes.  */
+   certain kinds of method invocation across nested class boundaries.  */
 
 static tree
-build_outer_method_access_method (tree decl)
+build_nested_method_access_method (tree decl)
 {
   tree saved_current_function_decl, mdecl;
   tree args = NULL_TREE, call_args = NULL_TREE;
@@ -8724,8 +8728,7 @@ build_outer_method_access_method (tree d
   start_artificial_method_body (mdecl);
 
   /* The actual method invocation uses the same args. When invoking a
-     static methods that way, we don't want to skip the first
-     argument. */
+     static methods that way, we don't want to skip the first argument.  */
   carg = args;
   if (!METHOD_STATIC (decl))
     carg = TREE_CHAIN (carg);
@@ -8744,10 +8747,10 @@ build_outer_method_access_method (tree d
   end_artificial_method_body (mdecl);
   current_function_decl = saved_current_function_decl;
 
-  /* Back tag the access function so it know what it accesses */
+  /* Back tag the access function so it know what it accesses.  */
   DECL_FUNCTION_ACCESS_DECL (decl) = mdecl;
 
-  /* Tag the current method so it knows it has an access generated */
+  /* Tag the current method so it knows it has an access generated.  */
   return DECL_FUNCTION_INNER_ACCESS (decl) = mdecl;
 }
 
@@ -9572,7 +9575,7 @@ resolve_expression_name (tree id, tree *
 	      /* If we're processing an inner class and we're trying
 		 to access a field belonging to an outer class, build
 		 the access to the field.  */
-	      if (nested_field_access_p (current_class, decl))
+	      if (nested_member_access_p (current_class, decl))
 		{
 		  if (!fs && CLASS_STATIC (TYPE_NAME (current_class)))
 		    {
@@ -10129,7 +10132,7 @@ resolve_qualified_expression_name (tree 
                           if (TREE_CODE (*where_found) == POINTER_TYPE)
                             *where_found = TREE_TYPE (*where_found);
                         }
-                      if (nested_field_access_p (current_class, decl))
+                      if (nested_member_access_p (current_class, decl))
                         decl = build_nested_field_access (qual_wfl, decl);
 		    }
 		  else
@@ -10272,7 +10275,7 @@ resolve_qualified_expression_name (tree 
               if (is_static
                   && FIELD_PRIVATE (field_decl)
                   && flag_emit_class_files
-                  && nested_field_access_p (current_class, field_decl))
+                  && nested_member_access_p (current_class, field_decl))
                 field_decl = build_nested_field_access (qual_wfl, field_decl);
 
 	      /* This is the decl found and eventually the next one to
@@ -10572,16 +10575,22 @@ patch_method_invocation (tree patch, tre
 		 IDENTIFIER_POINTER (name));
 	      PATCH_METHOD_RETURN_ERROR ();
 	    }
-	  if (list && !METHOD_STATIC (list))
+	  if (list)
 	    {
-	      char *fct_name = xstrdup (lang_printable_name (list, 2));
-	      parse_error_context
-		(identifier_wfl,
-		 "Can't make static reference to method %<%s %s%> in class %qs",
-		 lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0),
-		 fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
-	      free (fct_name);
-	      PATCH_METHOD_RETURN_ERROR ();
+              if (METHOD_STATIC (list))
+                maybe_use_access_method (0, &list, NULL);
+              else
+                {
+                  char *fct_name = xstrdup (lang_printable_name (list, 2));
+                  parse_error_context
+                    (identifier_wfl,
+                     "Can't make static reference to method %<%s %s%> in class %qs",
+                     lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0),
+                     fct_name,
+                     IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+                  free (fct_name);
+                  PATCH_METHOD_RETURN_ERROR ();
+                }
 	    }
 	}
       else
@@ -10698,7 +10707,7 @@ patch_method_invocation (tree patch, tre
           && DECL_NAME (list) == get_identifier ("clone"))
         is_array_clone_call = 1;
 
-      /* Check for static reference if non static methods */
+      /* Check for static reference of non static methods.  */
       if (check_for_static_method_reference (wfl, patch, list,
 					     class_to_search, primary))
 	PATCH_METHOD_RETURN_ERROR ();
@@ -10718,8 +10727,8 @@ patch_method_invocation (tree patch, tre
 	}
 
       /* Non static methods are called with the current object extra
-	 argument. If patch a `new TYPE()', the argument is the value
-	 returned by the object allocator. If method is resolved as a
+	 argument.  If PATCH is a `new TYPE()', the argument is the value
+	 returned by the object allocator.  If method is resolved as a
 	 primary, use the primary otherwise use the current THIS. */
       args = nreverse (args);
       if (TREE_CODE (patch) != NEW_CLASS_EXPR)
@@ -10731,16 +10740,16 @@ patch_method_invocation (tree patch, tre
 
 	     1) We're not generating bytecodes:
 
-	     - LIST is non static. It's invocation is transformed from
+	     - LIST is non-static.  Its invocation is transformed from
 	       x(a1,...,an) into this$<n>.x(a1,....an).
-	     - LIST is static. It's invocation is transformed from
+	     - LIST is static.  Its invocation is transformed from
 	       x(a1,...,an) into TYPE_OF(this$<n>).x(a1,....an)
 
 	     2) We're generating bytecodes:
 
-	     - LIST is non static. It's invocation is transformed from
+	     - LIST is non-static.  Its invocation is transformed from
 	       x(a1,....,an) into access$<n>(this$<n>,a1,...,an).
-	     - LIST is static. It's invocation is transformed from
+	     - LIST is static.  Its invocation is transformed from
 	       x(a1,....,an) into TYPE_OF(this$<n>).x(a1,....an).
 
 	     Of course, this$<n> can be arbitrarily complex, ranging from
@@ -10749,10 +10758,12 @@ patch_method_invocation (tree patch, tre
 
 	     maybe_use_access_method returns a nonzero value if the
 	     this_arg has to be moved into the (then generated) stub
-	     argument list. In the meantime, the selected function
-	     might have be replaced by a generated stub. */
-	  if (!primary &&
-	      maybe_use_access_method (is_super_init, &list, &this_arg))
+	     argument list.  In the meantime, the selected function
+	     might have been replaced by a generated stub.  */
+          if (METHOD_STATIC (list))
+            maybe_use_access_method (0, &list, NULL);
+	  else if (!primary &&
+	           maybe_use_access_method (is_super_init, &list, &this_arg))
 	    {
 	      args = tree_cons (NULL_TREE, this_arg, args);
 	      this_arg = NULL_TREE; /* So it doesn't get chained twice */
@@ -10920,8 +10931,8 @@ check_for_static_method_reference (tree 
   return 0;
 }
 
-/* Fix the invocation of *MDECL if necessary in the case of a
-   invocation from an inner class. *THIS_ARG might be modified
+/* Fix the invocation of *MDECL if necessary in the case of an
+   invocation across a nested class.  *THIS_ARG might be modified
    appropriately and an alternative access to *MDECL might be
    returned.  */
 
@@ -10929,25 +10940,26 @@ static int
 maybe_use_access_method (int is_super_init, tree *mdecl, tree *this_arg)
 {
   tree ctx;
-  tree md = *mdecl, ta = *this_arg;
+  tree md = *mdecl, ta = NULL_TREE;
   int to_return = 0;
   int non_static_context = !METHOD_STATIC (md);
 
   if (is_super_init
-      || DECL_CONTEXT (md) == current_class
-      || !PURE_INNER_CLASS_TYPE_P (current_class)
       || DECL_FINIT_P (md)
-      || DECL_INSTINIT_P (md))
+      || DECL_INSTINIT_P (md)
+      || !nested_member_access_p (current_class, md))
     return 0;
 
   /* If we're calling a method found in an enclosing class, generate
-     what it takes to retrieve the right this. Don't do that if we're
-     invoking a static method. Note that if MD's type is unrelated to
+     what it takes to retrieve the right `this'.  Don't do that if we're
+     invoking a static method.  Note that if MD's type is unrelated to
      CURRENT_CLASS, then the current this can be used. */
 
   if (non_static_context 
-      && !inherits_from_p (current_class, DECL_CONTEXT (md)))
+      && !inherits_from_p (current_class, DECL_CONTEXT (md))
+      && DECL_CONTEXT (TYPE_NAME (current_class)))
     {
+      ta = *this_arg;
       ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
       if (inherits_from_p (ctx, DECL_CONTEXT (md)))
 	{
@@ -10973,16 +10985,17 @@ maybe_use_access_method (int is_super_in
     }
 
   /* We might have to use an access method to get to MD. We can
-     break the method access rule as far as we're not generating
-     bytecode */
+     break the method access rule as long as we're not generating
+     bytecode.  */
   if (METHOD_PRIVATE (md) && flag_emit_class_files)
     {
-      md = build_outer_method_access_method (md);
+      md = build_nested_method_access_method (md);
       to_return = 1;
     }
 
   *mdecl = md;
-  *this_arg = ta;
+  if (this_arg)
+    *this_arg = ta;
 
   /* Returning a nonzero value indicates we were doing a non static
      method invocation that is now a static invocation. It will have
Index: ChangeLog
from  Ranjit Mathew  <rmathew@hotmail.com>

	More testsuite adjustments for PR java/19870.
	* testsuite/libjava.lang/PR19870_2.java: New testcase.
	* testsuite/libjava.lang/PR19870_2.out: Expected output for the
	new testcase.
	* testsuite/libjava.jacks/jacks.xfail: Remove
	8.5.2-non-static-member-usage-2 and add 15.12.3-explicit-constructor-9.

Index: testsuite/libjava.lang/PR19870_2.java
===================================================================
--- testsuite/libjava.lang/PR19870_2.java	2005-06-18 15:36:00.000000000 +0530
+++ testsuite/libjava.lang/PR19870_2.java	2005-06-18 15:35:42.000000000 +0530
@@ -0,0 +1,39 @@
+// PR19870: Test synthetic accessor generation for private static methods
+// accessed across nested class boundaries.
+public class PR19870_2
+{
+  static class A
+  {
+    private static void foo( )
+    {
+      System.out.println( "1");
+    }
+
+    private static void bar( int x)
+    {
+      System.out.println( x);
+      snafu( );
+      PR19870_2.snafu( );
+    }
+  }
+
+  static class B
+  {
+    private static void foo( )
+    {
+      A.foo( );
+    }
+  }
+
+  private static void snafu( )
+  {
+    System.out.println( "3");
+  }
+
+  public static void main( String[] args)
+  {
+    A.foo( );
+    A.bar( 2);
+    B.foo( );
+  }
+}
Index: testsuite/libjava.lang/PR19870_2.out
===================================================================
--- testsuite/libjava.lang/PR19870_2.out	2005-06-18 15:36:11.000000000 +0530
+++ testsuite/libjava.lang/PR19870_2.out	2005-06-18 15:36:40.000000000 +0530
@@ -0,0 +1,5 @@
+1
+2
+3
+3
+1
Index: testsuite/libjava.jacks/jacks.xfail
===================================================================
--- testsuite/libjava.jacks/jacks.xfail	2005-06-19 07:48:43.000000000 +0530
+++ testsuite/libjava.jacks/jacks.xfail	2005-06-19 07:49:49.000000000 +0530
@@ -174,6 +174,7 @@
 15.12.3-explicit-constructor-4
 15.12.3-explicit-constructor-5
 15.12.3-explicit-constructor-7
+15.12.3-explicit-constructor-9
 15.12.3-runtime-mode-1
 15.12.3-runtime-mode-2
 15.12.3-runtime-mode-3
@@ -635,7 +636,6 @@
 8.5-inheritance-3
 8.5-inheritance-6
 8.5.2-accessible-static-member-usage-3
-8.5.2-non-static-member-usage-2
 8.5.2-non-static-member-usage-4
 8.5.2-non-static-member-usage-5
 8.6-abrupt-1

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