This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[Patch] PR java/19870: Private static members accessed across nestedclasses (Part 2, Take 2)
- From: Ranjit Mathew <rmathew at gmail dot com>
- To: GCJ Patches <java-patches at gcc dot gnu dot org>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 14 Aug 2005 21:13:45 +0530
- Subject: [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