4.0 backport of PR 19870

Matthias Klose doko@cs.tu-berlin.de
Wed Sep 28 08:00:00 GMT 2005


Following the suggested list of backports in PR 24018, trying to
backport PR 19870 results in failures in the libjava testsuite, all of
the form
Exception during runtime initialization
java.lang.ExceptionInInitializerError
 <<No stacktrace available>>
Caused by: java.util.NoSuchElementException
 <<No stacktrace available>>
FAIL: InvokeReturn execution - gij test
I'm attaching the backport attempt.
 Matthias
libjava:
2005年05月26日 Ranjit Mathew <rmathew@hotmail.com>
	Testsuite adjustments for PR java/19870.
	* testsuite/libjava.lang/PR19870.java: New testcase.
	* testsuite/libjava.lang/PR19870.out: Expected output for the
	testcase.
	* testsuite/libjava.jacks/jacks.xfail: Add
	8.5.2-accessible-static-member-usage-3 and 15.8.4-static-2
2005年08月16日 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.
gcc/java:
2005年05月26日 Ranjit Mathew <rmathew@hotmail.com>
	PR java/19870.
	* java-tree.h (OUTER_FIELD_ACCESS_IDENTIFIER_P): Rename to
	NESTED_FIELD_ACCESS_IDENTIFIER_P.
	(FIELD_INNER_ACCESS): Rename to FIELD_NESTED_ACCESS.
	(FIELD_INNER_ACCESS_P): Rename to FIELD_NESTED_ACCESS_P.
	* jcf-write.c (generate_classfile): Use
	NESTED_FIELD_ACCESS_IDENTIFIER_P instead of
	OUTER_FIELD_ACCESS_IDENTIFIER_P.
	* parse.y (build_outer_field_access): Rename to
	build_nested_field_access. Support static fields and outer-to-inner
	class accesses.
	(outer_field_access_p): Rename to nested_field_access_p. Support
	static fields and generalise to outer-to-inner class and sibling
	inner class accesses.
	(outer_field_expanded_access_p): Rename to
	nested_field_expanded_access_p and support static fields.
	(outer_field_access_fix): Rename to nested_field_access_fix and
	support static fields.
	(build_outer_field_access_expr): Rename to
	build_nested_field_access_expr and support static fields.
	(build_outer_field_access_methods): Rename to
	build_nested_field_access_methods and support static fields. For
	static fields, generate accessors without class instance parameters.
	(build_outer_field_access_method): Rename to
	build_nested_field_access_method and support static fields.
	(build_outer_method_access_method): Use
	NESTED_FIELD_ACCESS_IDENTIFIER_P instead of
	OUTER_FIELD_ACCESS_IDENTIFIER_P.
	(resolve_expression_name): Consider static field accesses across
	nested classes.
	(resolve_qualified_expression_name): Likewise.
	(java_complete_lhs): Use nested_field_access_fix instead of
	outer_field_access_fix.
	(patch_unary_op): Rename outer_field_flag to nested_field_flag.
	Use nested_field_expanded_access_p instead of
	outer_field_expanded_access_p. Use nested_field_access_fix instead
	of outer_field_access_fix.
	(check_thrown_exceptions): Use NESTED_FIELD_ACCESS_IDENTIFIER_P
	instead of OUTER_FIELD_ACCESS_IDENTIFIER_P.
2005年08月16日 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).
 
diff -urN gcc.old/java/java-tree.h gcc/java/java-tree.h
--- gcc.old/java/java-tree.h	2005年06月07日 00:18:15.000000000 +0000
+++ gcc/java/java-tree.h	2005年09月27日 11:26:44.904735176 +0000
@@ -71,7 +71,7 @@
 IS_CRAFTED_STRING_BUFFER_P (in CALL_EXPR)
 IS_INIT_CHECKED (in SAVE_EXPR)
 6: CAN_COMPLETE_NORMALLY (in statement nodes)
- OUTER_FIELD_ACCESS_IDENTIFIER_P (in IDENTIFIER_NODE)
+ NESTED_FIELD_ACCESS_IDENTIFIER_P (in IDENTIFIER_NODE)
 
 Usage of TYPE_LANG_FLAG_?:
 0: CLASS_ACCESS0_GENERATED_P (in RECORD_TYPE)
@@ -905,16 +905,16 @@
 #define DECL_LOCAL_START_PC(NODE) (DECL_LANG_SPECIFIC (NODE)->u.v.start_pc)
 /* The end (bytecode) pc for the valid range of this local variable. */
 #define DECL_LOCAL_END_PC(NODE) (DECL_LANG_SPECIFIC (NODE)->u.v.end_pc)
-/* For a VAR_DECLor PARM_DECL, used to chain decls with the same
+/* For a VAR_DECL or PARM_DECL, used to chain decls with the same
 slot_number in decl_map. */
 #define DECL_LOCAL_SLOT_CHAIN(NODE) (DECL_LANG_SPECIFIC(NODE)->u.v.slot_chain)
 /* For a FIELD_DECL, holds the name of the access method. Used to
- read/write the content of the field from an inner class. */
-#define FIELD_INNER_ACCESS(DECL) \
+ read/write the content of the field across nested class boundaries. */
+#define FIELD_NESTED_ACCESS(DECL) \
 (DECL_LANG_SPECIFIC (VAR_OR_FIELD_CHECK (DECL))->u.v.am)
-/* Safely tests whether FIELD_INNER_ACCESS exists or not. */
-#define FIELD_INNER_ACCESS_P(DECL) \
- DECL_LANG_SPECIFIC (DECL) && FIELD_INNER_ACCESS (DECL)
+/* Safely tests whether FIELD_NESTED_ACCESS exists or not. */
+#define FIELD_NESTED_ACCESS_P(DECL) \
+ DECL_LANG_SPECIFIC (DECL) && FIELD_NESTED_ACCESS (DECL)
 /* True if a final field was initialized upon its declaration
 or in an initializer. Set after definite assignment. */
 #define DECL_FIELD_FINAL_IUD(NODE) (DECL_LANG_SPECIFIC (NODE)->u.v.final_iud)
@@ -1690,9 +1690,9 @@
 /* True if NODE (a statement) can complete normally. */
 #define CAN_COMPLETE_NORMALLY(NODE) TREE_LANG_FLAG_6 (NODE)
 
-/* True if NODE (an IDENTIFIER) bears the name of a outer field from
- inner class access function. */
-#define OUTER_FIELD_ACCESS_IDENTIFIER_P(NODE) \
+/* True if NODE (an IDENTIFIER) bears the name of an outer field from
+ inner class (or vice versa) access function. */
+#define NESTED_FIELD_ACCESS_IDENTIFIER_P(NODE) \
 TREE_LANG_FLAG_6 (IDENTIFIER_NODE_CHECK (NODE))
 
 /* True if NODE belongs to an inner class TYPE_DECL node.
diff -urN gcc.old/java/jcf-write.c gcc/java/jcf-write.c
--- gcc.old/java/jcf-write.c	2005年05月15日 20:50:42.000000000 +0000
+++ gcc/java/jcf-write.c	2005年09月27日 11:27:14.696206184 +0000
@@ -3088,7 +3088,7 @@
 /* Make room for the Synthetic attribute (of zero length.) */
 if (DECL_FINIT_P (part)
 	 || DECL_INSTINIT_P (part)
-	 || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
+	 || NESTED_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
 	 || TYPE_DOT_CLASS (clas) == part)
 	{
 	 i++;
diff -urN gcc.old/java/parse.y gcc/java/parse.y
--- gcc.old/java/parse.y	2005年08月17日 23:04:00.000000000 +0000
+++ gcc/java/parse.y	2005年09月27日 11:29:26.721135344 +0000
@@ -321,19 +321,17 @@
 static tree build_access_to_thisn (tree, tree, int);
 static tree maybe_build_thisn_access_method (tree);
 
-static tree build_outer_field_access (tree, tree);
-static tree build_outer_field_access_methods (tree);
-static tree build_outer_field_access_expr (int, tree, tree,
-						 tree, tree);
-static tree build_outer_method_access_method (tree);
+static tree build_nested_field_access (tree, tree);
+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_nested_method_access_method (tree);
 static tree build_new_access_id (void);
-static tree build_outer_field_access_method (tree, tree, tree,
-						 tree, tree);
 
-static int outer_field_access_p (tree, tree);
-static int outer_field_expanded_access_p (tree, tree *,
-						 tree *, tree *);
-static tree outer_field_access_fix (tree, 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);
+
 static tree build_incomplete_class_ref (int, tree);
 static tree patch_incomplete_class_ref (tree);
 static tree create_anonymous_class (tree);
@@ -8343,114 +8341,163 @@
 fields either directly by using the relevant access to this$<n> or
 by invoking an access method crafted for that purpose. */
 
-/* Build the necessary access from an inner class to an outer
- class. This routine could be optimized to cache previous result
+/* Build the necessary access across nested class boundaries.
+ This routine could be optimized to cache previous result
 (decl, current_class and returned access). When an access method
- needs to be generated, it always takes the form of a read. It might
- be later turned into a write by calling outer_field_access_fix. */
+ needs to be generated, it always takes the form of a read. It might
+ be later turned into a write by calling nested_field_access_fix. */
 
 static tree
-build_outer_field_access (tree id, tree decl)
+build_nested_field_access (tree id, tree decl)
 {
 tree access = NULL_TREE;
- tree ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
+ tree ctx = NULL_TREE;
 tree decl_ctx = DECL_CONTEXT (decl);
+ bool is_static = FIELD_STATIC (decl);
+
+ if (DECL_CONTEXT (TYPE_NAME (current_class)))
+ ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
 
- /* If the immediate enclosing context of the current class is the
- field decl's class or inherits from it; build the access as
- `this$<n>.<field>'. Note that we will break the `private' barrier
- if we're not emitting bytecodes. */
- if ((ctx == decl_ctx || inherits_from_p (ctx, decl_ctx))
- && (!FIELD_PRIVATE (decl) || !flag_emit_class_files ))
+ /* For non-static fields, if the immediate enclosing context of the
+ current class is the field decl's class or inherits from it,
+ build the access as `this$<n>.<field>'. Note that we will break
+ the `private' barrier if we're not emitting bytecodes. */
+ if (!is_static
+ && ctx
+ && (ctx == decl_ctx || inherits_from_p (ctx, decl_ctx))
+ && (!FIELD_PRIVATE (decl) || !flag_emit_class_files))
 {
 tree thisn = build_current_thisn (current_class);
 access = make_qualified_primary (build_wfl_node (thisn),
 				 id, EXPR_WFL_LINECOL (id));
 }
- /* Otherwise, generate access methods to outer this and access the
- field (either using an access method or by direct access.) */
+ /* Otherwise, generate and use accessor methods for the field as
+ needed. */
 else
 {
 int lc = EXPR_WFL_LINECOL (id);
 
 /* Now we chain the required number of calls to the access0ドル to
-	 get a hold to the enclosing instance we need, and then we
-	 build the field access. */
- access = build_access_to_thisn (current_class, decl_ctx, lc);
+	 get a hold to the enclosing instance we need for a non-static
+ field, and then we build the field access. */
+ if (!is_static)
+ access = build_access_to_thisn (current_class, decl_ctx, lc);
 
 /* If the field is private and we're generating bytecode, then
- we generate an access method */
- if (FIELD_PRIVATE (decl) && flag_emit_class_files )
+ we generate an access method. */
+ if (FIELD_PRIVATE (decl) && flag_emit_class_files)
 	{
-	 tree name = build_outer_field_access_methods (decl);
-	 access = build_outer_field_access_expr (lc, decl_ctx,
-						 name, access, NULL_TREE);
+	 tree name = build_nested_field_access_methods (decl);
+	 access = build_nested_field_access_expr (lc, decl_ctx,
+						 name, access, NULL_TREE);
 	}
- /* Otherwise we use `access$(this$<j>). ... access$(this$<i>).<field>'.
+ /* Otherwise we use `access$(this$<j>). ... access$(this$<i>).<field>'
+ for non-static fields.
 	 Once again we break the `private' access rule from a foreign
-	 class. */
+	 class. */
+ else if (is_static)
+ {
+ tree class_name = DECL_NAME (TYPE_NAME (decl_ctx));
+ access
+ = make_qualified_primary (build_wfl_node (class_name), id, lc);
+ }
 else
-	access = make_qualified_primary (access, id, lc);
+ access = make_qualified_primary (access, id, lc);
 }
+
 return resolve_expression_name (access, NULL);
 }
 
-/* Return a nonzero value if NODE describes an outer field inner
- access. */
+/* 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
+ TYPE. */
 
 static int
-outer_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) != FUNCTION_DECL))
+ return 0;
+ 
 if (!INNER_CLASS_TYPE_P (type)
- || TREE_CODE (decl) != FIELD_DECL
- || DECL_CONTEXT (decl) == type)
+ && !(TREE_CODE (decl_type) == RECORD_TYPE
+ && INNER_CLASS_TYPE_P (decl_type)))
 return 0;
 
- /* If the inner class extends the declaration context of the field
- we're trying to access, then this isn't an outer field access */
- if (inherits_from_p (type, DECL_CONTEXT (decl)))
+ is_static = (TREE_CODE (decl) == FUNCTION_DECL)
+ ? METHOD_STATIC (decl)
+ : FIELD_STATIC (decl);
+
+ /* If TYPE extends the declaration context of the non-static
+ 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;
 
- for (type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type))); ;
- type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type))))
- {
- if (type == DECL_CONTEXT (decl))
-	return 1;
-
- if (!DECL_CONTEXT (TYPE_NAME (type)))
-	{
-	 /* Before we give up, see whether the field is inherited from
-	 the enclosing context we're considering. */
-	 if (inherits_from_p (type, DECL_CONTEXT (decl)))
-	 return 1;
-	 break;
-	}
+ for (type_root = type;
+ DECL_CONTEXT (TYPE_NAME (type_root));
+ type_root = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type_root))))
+ {
+ if (type_root == decl_type)
+ return 1;
+
+ /* Before we give up, see whether it is a non-static field
+ inherited from the enclosing context we are considering. */
+ if (!DECL_CONTEXT (TYPE_NAME (type_root))
+ && !is_static
+ && inherits_from_p (type_root, decl_type))
+ return 1;
+ }
+
+ if (TREE_CODE (decl_type) == RECORD_TYPE
+ && INNER_CLASS_TYPE_P (decl_type))
+ {
+ for (decl_type_root = decl_type;
+ DECL_CONTEXT (TYPE_NAME (decl_type_root));
+ decl_type_root
+ = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (decl_type_root))))
+ {
+ if (decl_type_root == type)
+ return 1;
+ }
 }
+ else
+ decl_type_root = decl_type;
+ 
+ if (type_root == decl_type_root)
+ return 1;
 
 return 0;
 }
 
-/* Return a nonzero value if NODE represents an outer field inner
- access that was been already expanded. As a side effect, it returns
+/* Return a nonzero value if NODE represents a cross-nested-class 
+ access that has already been expanded. As a side effect, it returns
 the name of the field being accessed and the argument passed to the
 access function, suitable for a regeneration of the access method
- call if necessary. */
+ call if necessary. */
 
 static int
-outer_field_expanded_access_p (tree node, tree *name, tree *arg_type,
-			 tree *arg)
+nested_field_expanded_access_p (tree node, tree *name, tree *arg_type,
+			 tree *arg)
 {
 int identified = 0;
 
 if (TREE_CODE (node) != CALL_EXPR)
 return 0;
 
- /* Well, gcj generates slightly different tree nodes when compiling
- to native or bytecodes. It's the case for function calls. */
+ /* Well, GCJ generates slightly different tree nodes when compiling
+ to native or bytecodes. It's the case for function calls. */
 
 if (flag_emit_class_files
 && TREE_CODE (node) == CALL_EXPR
- && OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (TREE_OPERAND (node, 0))))
+ && NESTED_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (TREE_OPERAND (node, 0))))
 identified = 1;
 else if (!flag_emit_class_files)
 {
@@ -8462,7 +8509,7 @@
 	 node = TREE_OPERAND (node, 0);
 	 if (TREE_OPERAND (node, 0)
 	 && TREE_CODE (TREE_OPERAND (node, 0)) == FUNCTION_DECL
-	 && (OUTER_FIELD_ACCESS_IDENTIFIER_P
+	 && (NESTED_FIELD_ACCESS_IDENTIFIER_P
 		 (DECL_NAME (TREE_OPERAND (node, 0)))))
 	 identified = 1;
 	}
@@ -8472,26 +8519,37 @@
 {
 tree argument = TREE_OPERAND (node, 1);
 *name = DECL_NAME (TREE_OPERAND (node, 0));
- *arg_type = TREE_TYPE (TREE_TYPE (TREE_VALUE (argument)));
- *arg = TREE_VALUE (argument);
+
+ /* The accessors for static fields do not take in a this$<n> argument,
+ so we take the class name from the accessor's context instead. */
+ if (argument)
+ {
+ *arg_type = TREE_TYPE (TREE_TYPE (TREE_VALUE (argument)));
+ *arg = TREE_VALUE (argument);
+ }
+ else
+ {
+ *arg_type = DECL_CONTEXT (TREE_OPERAND (node, 0));
+ *arg = NULL_TREE;
+ }
 }
 return identified;
 }
 
-/* Detect in NODE an outer field read access from an inner class and
- transform it into a write with RHS as an argument. This function is
- called from the java_complete_lhs when an assignment to a LHS can
- be identified. */
+/* Detect in NODE cross-nested-class field read access and
+ transform it into a write with RHS as an argument. This function
+ is called from the java_complete_lhs when an assignment to a LHS can
+ be identified. */
 
 static tree
-outer_field_access_fix (tree wfl, tree node, tree rhs)
+nested_field_access_fix (tree wfl, tree node, tree rhs)
 {
 tree name, arg_type, arg;
 
- if (outer_field_expanded_access_p (node, &name, &arg_type, &arg))
+ if (nested_field_expanded_access_p (node, &name, &arg_type, &arg))
 {
- node = build_outer_field_access_expr (EXPR_WFL_LINECOL (wfl),
-					 arg_type, name, arg, rhs);
+ node = build_nested_field_access_expr (EXPR_WFL_LINECOL (wfl),
+					 arg_type, name, arg, rhs);
 return java_complete_tree (node);
 }
 return NULL_TREE;
@@ -8504,23 +8562,34 @@
 read access. */
 
 static tree
-build_outer_field_access_expr (int lc, tree type, tree access_method_name,
-			 tree arg1, tree arg2)
+build_nested_field_access_expr (int lc, tree type, tree access_method_name,
+			 tree arg1, tree arg2)
 {
 tree args, cn, access;
 
- args = arg1 ? arg1 :
- build_wfl_node (build_current_thisn (current_class));
- args = build_tree_list (NULL_TREE, args);
+ if (arg1)
+ args = build_tree_list (NULL_TREE, arg1);
+ else
+ args = NULL_TREE;
 
 if (arg2)
- args = tree_cons (NULL_TREE, arg2, args);
+ {
+ if (args)
+ args = tree_cons (NULL_TREE, arg2, args);
+ else
+ args = build_tree_list (NULL_TREE, arg2);
+ }
 
- access = build_method_invocation (build_wfl_node (access_method_name), args);
+ access
+ = build_method_invocation (build_wfl_node (access_method_name), args);
 cn = build_wfl_node (DECL_NAME (TYPE_NAME (type)));
+
 return make_qualified_primary (cn, access, lc);
 }
 
+/* Build the name of a synthetic accessor used to access class members
+ across nested class boundaries. */
+
 static tree
 build_new_access_id (void)
 {
@@ -8531,8 +8600,8 @@
 return get_identifier (buffer);
 }
 
-/* Create the static access functions for the outer field DECL. We define a
- read:
+/* Create the static access functions for the cross-nested-class field DECL.
+ We define a read:
 TREE_TYPE (<field>) access$<n> (DECL_CONTEXT (<field>) inst$) {
 return inst$.field;
 }
@@ -8541,63 +8610,89 @@
 TREE_TYPE (<field>) value$) {
 return inst$.field = value$;
 }
- We should have a usage flags on the DECL so we can lazily turn the ones
- we're using for code generation. FIXME.
+ For static fields, these methods are generated without the instance
+ parameter.
+ We should have a usage flag on the DECL so we can lazily turn the ones
+ we're using for code generation. FIXME.
 */
 
 static tree
-build_outer_field_access_methods (tree decl)
+build_nested_field_access_methods (tree decl)
 {
- tree id, args, stmt, mdecl;
+ tree id, args, stmt, mdecl, class_name = NULL_TREE;
+ bool is_static = FIELD_STATIC (decl);
 
- if (FIELD_INNER_ACCESS_P (decl))
- return FIELD_INNER_ACCESS (decl);
+ if (FIELD_NESTED_ACCESS_P (decl))
+ return FIELD_NESTED_ACCESS (decl);
 
 MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
 
- /* Create the identifier and a function named after it. */
+ /* Create the identifier and a function named after it. */
 id = build_new_access_id ();
 
 /* The identifier is marked as bearing the name of a generated write
- access function for outer field accessed from inner classes. */
- OUTER_FIELD_ACCESS_IDENTIFIER_P (id) = 1;
+ access function for outer field accessed from inner classes. */
+ NESTED_FIELD_ACCESS_IDENTIFIER_P (id) = 1;
 
- /* Create the read access */
- args = build_tree_list (inst_id, build_pointer_type (DECL_CONTEXT (decl)));
- TREE_CHAIN (args) = end_params_node;
- stmt = make_qualified_primary (build_wfl_node (inst_id),
-				 build_wfl_node (DECL_NAME (decl)), 0);
+ /* Create the read access. */
+ if (!is_static)
+ {
+ args = build_tree_list (inst_id,
+ build_pointer_type (DECL_CONTEXT (decl)));
+ TREE_CHAIN (args) = end_params_node;
+ stmt = make_qualified_primary (build_wfl_node (inst_id),
+				 build_wfl_node (DECL_NAME (decl)), 0);
+ }
+ else
+ {
+ args = end_params_node;
+ class_name = DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)));
+ stmt = make_qualified_primary (build_wfl_node (class_name),
+ build_wfl_node (DECL_NAME (decl)), 0);
+ }
 stmt = build_return (0, stmt);
- mdecl = build_outer_field_access_method (DECL_CONTEXT (decl),
-					 TREE_TYPE (decl), id, args, stmt);
+ mdecl = build_nested_field_access_method (DECL_CONTEXT (decl),
+					 TREE_TYPE (decl), id, args, stmt);
 DECL_FUNCTION_ACCESS_DECL (mdecl) = decl;
 
- /* Create the write access method. No write access for final variable */
+ /* Create the write access method. No write access for final variable */
 if (!FIELD_FINAL (decl))
 {
- args = build_tree_list (inst_id,
-			 build_pointer_type (DECL_CONTEXT (decl)));
- TREE_CHAIN (args) = build_tree_list (wpv_id, TREE_TYPE (decl));
- TREE_CHAIN (TREE_CHAIN (args)) = end_params_node;
- stmt = make_qualified_primary (build_wfl_node (inst_id),
-				 build_wfl_node (DECL_NAME (decl)), 0);
+ if (!is_static)
+ {
+ args = build_tree_list (inst_id,
+			 build_pointer_type (DECL_CONTEXT (decl)));
+ TREE_CHAIN (args) = build_tree_list (wpv_id, TREE_TYPE (decl));
+ TREE_CHAIN (TREE_CHAIN (args)) = end_params_node;
+ stmt = make_qualified_primary (build_wfl_node (inst_id),
+				 build_wfl_node (DECL_NAME (decl)),
+ 0);
+ }
+ else
+ {
+ args = build_tree_list (wpv_id, TREE_TYPE (decl));
+ TREE_CHAIN (args) = end_params_node;
+ stmt = make_qualified_primary (build_wfl_node (class_name),
+ build_wfl_node (DECL_NAME (decl)),
+ 0);
+ }
 stmt = build_return (0, build_assignment (ASSIGN_TK, 0, stmt,
 						build_wfl_node (wpv_id)));
- mdecl = build_outer_field_access_method (DECL_CONTEXT (decl),
-					 TREE_TYPE (decl), id,
-					 args, stmt);
+ mdecl = build_nested_field_access_method (DECL_CONTEXT (decl),
+					 TREE_TYPE (decl), id,
+					 args, stmt);
 }
 DECL_FUNCTION_ACCESS_DECL (mdecl) = decl;
 
 /* Return the access name */
- return FIELD_INNER_ACCESS (decl) = id;
+ return FIELD_NESTED_ACCESS (decl) = id;
 }
 
-/* Build an field access method NAME. */
+/* Build a field access method NAME. */
 
 static tree
-build_outer_field_access_method (tree class, tree type, tree name,
-				 tree args, tree body)
+build_nested_field_access_method (tree class, tree type, tree name,
+				 tree args, tree body)
 {
 tree saved_current_function_decl, mdecl;
 
@@ -8618,10 +8713,10 @@
 
 
 /* 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;
@@ -8641,7 +8736,7 @@
 
 /* Obtain an access identifier and mark it */
 id = build_new_access_id ();
- OUTER_FIELD_ACCESS_IDENTIFIER_P (id) = 1;
+ NESTED_FIELD_ACCESS_IDENTIFIER_P (id) = 1;
 
 carg = TYPE_ARG_TYPES (TREE_TYPE (decl));
 /* Create the arguments, as much as the original */
@@ -8670,8 +8765,7 @@
 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);
@@ -8690,10 +8784,10 @@
 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;
 }
 
@@ -8707,7 +8801,7 @@
 others. Access methods to this$<n> are build on the fly if
 necessary. This CAN'T be used to solely access this$<n-1> from
 this$<n> (which alway yield to special cases and optimization, see
- for example build_outer_field_access). */
+ for example build_nested_field_access). */
 
 static tree
 build_access_to_thisn (tree from, tree to, int lc)
@@ -9512,15 +9606,15 @@
 
 	 /* 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 (!fs && outer_field_access_p (current_class, decl))
+		 the access to the field. */
+	 if (nested_member_access_p (current_class, decl))
 		{
-		 if (CLASS_STATIC (TYPE_NAME (current_class)))
+		 if (!fs && CLASS_STATIC (TYPE_NAME (current_class)))
 		 {
 		 static_ref_err (id, DECL_NAME (decl), current_class);
 		 return error_mark_node;
 		 }
-		 access = build_outer_field_access (id, decl);
+		 access = build_nested_field_access (id, decl);
 		 if (orig)
 		 *orig = access;
 		 return access;
@@ -10054,18 +10148,29 @@
 	 decl = QUAL_RESOLUTION (q);
 	 if (!type)
 		{
-		 if (TREE_CODE (decl) == FIELD_DECL && !FIELD_STATIC (decl))
+		 if (TREE_CODE (decl) == FIELD_DECL
+ || TREE_CODE (decl) == VAR_DECL)
 		 {
-		 if (current_this)
-			*where_found = current_this;
-		 else
-			{
-			 static_ref_err (qual_wfl, DECL_NAME (decl),
-					 current_class);
-			 return 1;
-			}
- if (outer_field_access_p (current_class, decl))
- decl = build_outer_field_access (qual_wfl, decl);
+ if (TREE_CODE (decl) == FIELD_DECL
+ && !FIELD_STATIC (decl))
+ {
+ 	 if (current_this)
+ *where_found = current_this;
+ else
+ {
+ static_ref_err (qual_wfl, DECL_NAME (decl),
+ current_class);
+ return 1;
+ }
+ }
+ else
+ {
+ *where_found = TREE_TYPE (decl);
+ if (TREE_CODE (*where_found) == POINTER_TYPE)
+ *where_found = TREE_TYPE (*where_found);
+ }
+ if (nested_member_access_p (current_class, decl))
+ decl = build_nested_field_access (qual_wfl, decl);
 		 }
 		 else
 		 {
@@ -10174,7 +10279,7 @@
 		}
 	 from_cast = from_super = 0;
 
-	 /* It's an access from a type but it isn't static, we
+	 /* If it's an access from a type but isn't static, we
 		 make it relative to `this'. */
 	 if (!is_static && from_type)
 		decl = current_this;
@@ -10189,8 +10294,8 @@
 		 return 1;
 		}
 
-	 /* We want to keep the location were found it, and the type
-		 we found. */
+ /* We want to keep the location where we found it, and the
+ type we found. */
 	 *where_found = decl;
 	 *type_found = type;
 
@@ -10198,10 +10303,18 @@
 		 qualified this */
 	 if (from_qualified_this)
 		{
-		 field_decl = build_outer_field_access (qual_wfl, field_decl);
+		 field_decl
+ = build_nested_field_access (qual_wfl, field_decl);
 		 from_qualified_this = 0;
 		}
 
+ /* If needed, generate accessors for static field access. */
+ if (is_static
+ && FIELD_PRIVATE (field_decl)
+ && flag_emit_class_files
+ && 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
 		 search from */
 	 decl = field_decl;
@@ -10499,16 +10612,22 @@
 		 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
@@ -10625,7 +10744,7 @@
 && 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 ();
@@ -10645,8 +10764,8 @@
 	}
 
 /* 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)
@@ -10658,16 +10777,16 @@
 
 	 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
@@ -10676,10 +10795,12 @@
 
 	 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 */
@@ -10847,8 +10968,8 @@
 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. */
 
@@ -10856,25 +10977,26 @@
 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)))
 	{
@@ -10900,16 +11022,17 @@
 }
 
 /* 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
@@ -12191,10 +12314,10 @@
 if ((nn = patch_string (TREE_OPERAND (node, 1))))
 	TREE_OPERAND (node, 1) = nn;
 
- if ((nn = outer_field_access_fix (wfl_op1, TREE_OPERAND (node, 0),
-					TREE_OPERAND (node, 1))))
+ if ((nn = nested_field_access_fix (wfl_op1, TREE_OPERAND (node, 0),
+					 TREE_OPERAND (node, 1))))
 	{
-	 /* We return error_mark_node if outer_field_access_fix
+	 /* We return error_mark_node if nested_field_access_fix
 	 detects we write into a final. */
 	 if (nn == error_mark_node)
 	 return error_mark_node;
@@ -14226,7 +14349,7 @@
 tree op = TREE_OPERAND (node, 0);
 tree op_type = TREE_TYPE (op);
 tree prom_type = NULL_TREE, value, decl;
- int outer_field_flag = 0;
+ int nested_field_flag = 0;
 int code = TREE_CODE (node);
 int error_found = 0;
 
@@ -14243,10 +14366,11 @@
 /* 15.14.2 Prefix Decrement Operator -- */
 case PREDECREMENT_EXPR:
 op = decl = extract_field_decl (op);
- outer_field_flag = outer_field_expanded_access_p (op, NULL, NULL, NULL);
+ nested_field_flag
+ = nested_field_expanded_access_p (op, NULL, NULL, NULL);
 /* We might be trying to change an outer field accessed using
 access method. */
- if (outer_field_flag)
+ if (nested_field_flag)
 	{
 	 /* Retrieve the decl of the field we're trying to access. We
 do that by first retrieving the function we would call to
@@ -14300,15 +14424,15 @@
 	 }
 
 	 /* We remember we might be accessing an outer field */
-	 if (outer_field_flag)
+	 if (nested_field_flag)
 	 {
 	 /* We re-generate an access to the field */
 	 value = build2 (PLUS_EXPR, TREE_TYPE (op),
-			 build_outer_field_access (wfl_op, decl), value);
+			 build_nested_field_access (wfl_op, decl), value);
 
 	 /* And we patch the original access$() into a write
 with plus_op as a rhs */
-	 return outer_field_access_fix (node, op, value);
+	 return nested_field_access_fix (node, op, value);
 	 }
 
 	 /* And write back into the node. */
@@ -15903,7 +16027,7 @@
 int is_array_call = 0;
 
 /* Skip check within generated methods, such as access$<n>. */
- if (OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (current_function_decl)))
+ if (NESTED_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (current_function_decl)))
 return;
 
 if (this_expr != NULL_TREE
diff -urN --exclude=CVS libjava.old/testsuite/libjava.jacks/jacks.xfail libjava/testsuite/libjava.jacks/jacks.xfail
--- libjava.old/testsuite/libjava.jacks/jacks.xfail	2005年08月17日 23:10:49.000000000 +0000
+++ libjava/testsuite/libjava.jacks/jacks.xfail	2005年09月27日 11:33:06.624704920 +0000
@@ -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
@@ -306,6 +307,7 @@
 15.8.2-type-12
 15.8.2-type-13
 15.8.2-type-14
+15.8.4-static-2
 15.8.5-field-expression-6
 15.8.5-method-expression-8
 15.8.5-variable-5
@@ -629,7 +631,7 @@
 8.5-inheritance-2
 8.5-inheritance-3
 8.5-inheritance-6
-8.5.2-non-static-member-usage-2
+8.5.2-accessible-static-member-usage-3
 8.5.2-non-static-member-usage-4
 8.5.2-non-static-member-usage-5
 8.6-abrupt-1
diff -urN --exclude=CVS libjava.old/testsuite/libjava.lang/PR19870.java libjava/testsuite/libjava.lang/PR19870.java
--- libjava.old/testsuite/libjava.lang/PR19870.java	1970年01月01日 00:00:00.000000000 +0000
+++ libjava/testsuite/libjava.lang/PR19870.java	2005年09月27日 11:23:08.909571432 +0000
@@ -0,0 +1,44 @@
+// PR19870: Test static field access across nested class boundaries.
+//
+public class PR19870
+{
+ private static int x = 123;
+
+ static class Foo
+ {
+ private static int junk = 1000;
+
+ static void snafu( )
+ {
+ System.out.println( x);
+ x = 456;
+ System.out.println( PR19870.x);
+ PR19870.x = 789;
+ System.out.println( PR19870.x);
+
+ System.out.println( Bar.junk);
+ }
+ }
+
+ static class Bar
+ {
+ private static int junk = 1984;
+
+ static void snafu( )
+ {
+ System.out.println( Foo.junk);
+ Foo.junk = 2000;
+ System.out.println( Foo.junk);
+ }
+ }
+
+ public static void main( String[] args)
+ {
+ Foo.snafu( );
+ Bar.snafu( );
+
+ System.out.println( Foo.junk);
+ Foo.junk = 3000;
+ System.out.println( Foo.junk);
+ }
+}
diff -urN --exclude=CVS libjava.old/testsuite/libjava.lang/PR19870.out libjava/testsuite/libjava.lang/PR19870.out
--- libjava.old/testsuite/libjava.lang/PR19870.out	1970年01月01日 00:00:00.000000000 +0000
+++ libjava/testsuite/libjava.lang/PR19870.out	2005年09月27日 11:23:36.245415752 +0000
@@ -0,0 +1,8 @@
+123
+456
+789
+1984
+1000
+2000
+2000
+3000
diff -urN --exclude=CVS libjava.old/testsuite/libjava.lang/PR19870_2.java libjava/testsuite/libjava.lang/PR19870_2.java
--- libjava.old/testsuite/libjava.lang/PR19870_2.java	1970年01月01日 00:00:00.000000000 +0000
+++ libjava/testsuite/libjava.lang/PR19870_2.java	2005年09月27日 11:32:18.883962616 +0000
@@ -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( );
+ }
+}
diff -urN --exclude=CVS libjava.old/testsuite/libjava.lang/PR19870_2.out libjava/testsuite/libjava.lang/PR19870_2.out
--- libjava.old/testsuite/libjava.lang/PR19870_2.out	1970年01月01日 00:00:00.000000000 +0000
+++ libjava/testsuite/libjava.lang/PR19870_2.out	2005年09月27日 11:32:38.954911368 +0000
@@ -0,0 +1,5 @@
+1
+2
+3
+3
+1


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /