Commit 3881a11b by Ranjit Mathew Committed by Ranjit Mathew

re PR java/19870 (gcj -C doesn't generate accessors for private members across…

re PR java/19870 (gcj -C doesn't generate accessors for private members across nested class boundaries)

	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).

From-SVN: r103163
parent 6ab9469a
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).
2005-08-15 Tom Tromey <tromey@redhat.com> 2005-08-15 Tom Tromey <tromey@redhat.com>
PR java/23300. PR java/23300.
......
...@@ -326,10 +326,10 @@ static tree build_nested_field_access (tree, tree); ...@@ -326,10 +326,10 @@ static tree build_nested_field_access (tree, tree);
static tree build_nested_field_access_methods (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_method (tree, tree, tree, tree, tree);
static tree build_nested_field_access_expr (int, 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 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 int nested_field_expanded_access_p (tree, tree *, tree *, tree *);
static tree nested_field_access_fix (tree, tree, tree); static tree nested_field_access_fix (tree, tree, tree);
...@@ -8371,20 +8371,22 @@ build_nested_field_access (tree id, tree decl) ...@@ -8371,20 +8371,22 @@ build_nested_field_access (tree id, tree decl)
return resolve_expression_name (access, NULL); 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, 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. */ TYPE. */
static int static int
nested_field_access_p (tree type, tree decl) nested_member_access_p (tree type, tree decl)
{ {
bool is_static = false; bool is_static = false;
tree decl_type = DECL_CONTEXT (decl); tree decl_type = DECL_CONTEXT (decl);
tree type_root, decl_type_root; tree type_root, decl_type_root;
if (decl_type == type 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; return 0;
if (!INNER_CLASS_TYPE_P (type) if (!INNER_CLASS_TYPE_P (type)
...@@ -8392,10 +8394,12 @@ nested_field_access_p (tree type, tree decl) ...@@ -8392,10 +8394,12 @@ nested_field_access_p (tree type, tree decl)
&& INNER_CLASS_TYPE_P (decl_type))) && INNER_CLASS_TYPE_P (decl_type)))
return 0; 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 /* 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. */ access we need to worry about. */
if (!is_static && inherits_from_p (type, decl_type)) if (!is_static && inherits_from_p (type, decl_type))
return 0; return 0;
...@@ -8672,10 +8676,10 @@ build_nested_field_access_method (tree class, tree type, tree name, ...@@ -8672,10 +8676,10 @@ build_nested_field_access_method (tree class, tree type, tree name,
/* This section deals with building access function necessary for /* 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 static tree
build_outer_method_access_method (tree decl) build_nested_method_access_method (tree decl)
{ {
tree saved_current_function_decl, mdecl; tree saved_current_function_decl, mdecl;
tree args = NULL_TREE, call_args = NULL_TREE; tree args = NULL_TREE, call_args = NULL_TREE;
...@@ -8724,8 +8728,7 @@ build_outer_method_access_method (tree decl) ...@@ -8724,8 +8728,7 @@ build_outer_method_access_method (tree decl)
start_artificial_method_body (mdecl); start_artificial_method_body (mdecl);
/* The actual method invocation uses the same args. When invoking a /* The actual method invocation uses the same args. When invoking a
static methods that way, we don't want to skip the first static methods that way, we don't want to skip the first argument. */
argument. */
carg = args; carg = args;
if (!METHOD_STATIC (decl)) if (!METHOD_STATIC (decl))
carg = TREE_CHAIN (carg); carg = TREE_CHAIN (carg);
...@@ -8744,10 +8747,10 @@ build_outer_method_access_method (tree decl) ...@@ -8744,10 +8747,10 @@ build_outer_method_access_method (tree decl)
end_artificial_method_body (mdecl); end_artificial_method_body (mdecl);
current_function_decl = saved_current_function_decl; 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; 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; return DECL_FUNCTION_INNER_ACCESS (decl) = mdecl;
} }
...@@ -9572,7 +9575,7 @@ resolve_expression_name (tree id, tree *orig) ...@@ -9572,7 +9575,7 @@ resolve_expression_name (tree id, tree *orig)
/* If we're processing an inner class and we're trying /* If we're processing an inner class and we're trying
to access a field belonging to an outer class, build to access a field belonging to an outer class, build
the access to the field. */ 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))) if (!fs && CLASS_STATIC (TYPE_NAME (current_class)))
{ {
...@@ -10129,7 +10132,7 @@ resolve_qualified_expression_name (tree wfl, tree *found_decl, ...@@ -10129,7 +10132,7 @@ resolve_qualified_expression_name (tree wfl, tree *found_decl,
if (TREE_CODE (*where_found) == POINTER_TYPE) if (TREE_CODE (*where_found) == POINTER_TYPE)
*where_found = TREE_TYPE (*where_found); *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); decl = build_nested_field_access (qual_wfl, decl);
} }
else else
...@@ -10272,7 +10275,7 @@ resolve_qualified_expression_name (tree wfl, tree *found_decl, ...@@ -10272,7 +10275,7 @@ resolve_qualified_expression_name (tree wfl, tree *found_decl,
if (is_static if (is_static
&& FIELD_PRIVATE (field_decl) && FIELD_PRIVATE (field_decl)
&& flag_emit_class_files && 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); field_decl = build_nested_field_access (qual_wfl, field_decl);
/* This is the decl found and eventually the next one to /* This is the decl found and eventually the next one to
...@@ -10572,16 +10575,22 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super, ...@@ -10572,16 +10575,22 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
IDENTIFIER_POINTER (name)); IDENTIFIER_POINTER (name));
PATCH_METHOD_RETURN_ERROR (); PATCH_METHOD_RETURN_ERROR ();
} }
if (list && !METHOD_STATIC (list)) if (list)
{ {
char *fct_name = xstrdup (lang_printable_name (list, 2)); if (METHOD_STATIC (list))
parse_error_context maybe_use_access_method (0, &list, NULL);
(identifier_wfl, else
"Can't make static reference to method %<%s %s%> in class %qs", {
lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0), char *fct_name = xstrdup (lang_printable_name (list, 2));
fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); parse_error_context
free (fct_name); (identifier_wfl,
PATCH_METHOD_RETURN_ERROR (); "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 else
...@@ -10698,7 +10707,7 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super, ...@@ -10698,7 +10707,7 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
&& DECL_NAME (list) == get_identifier ("clone")) && DECL_NAME (list) == get_identifier ("clone"))
is_array_clone_call = 1; 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, if (check_for_static_method_reference (wfl, patch, list,
class_to_search, primary)) class_to_search, primary))
PATCH_METHOD_RETURN_ERROR (); PATCH_METHOD_RETURN_ERROR ();
...@@ -10718,8 +10727,8 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super, ...@@ -10718,8 +10727,8 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
} }
/* Non static methods are called with the current object extra /* Non static methods are called with the current object extra
argument. If patch a `new TYPE()', the argument is the value argument. If PATCH is a `new TYPE()', the argument is the value
returned by the object allocator. If method is resolved as a returned by the object allocator. If method is resolved as a
primary, use the primary otherwise use the current THIS. */ primary, use the primary otherwise use the current THIS. */
args = nreverse (args); args = nreverse (args);
if (TREE_CODE (patch) != NEW_CLASS_EXPR) if (TREE_CODE (patch) != NEW_CLASS_EXPR)
...@@ -10731,16 +10740,16 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super, ...@@ -10731,16 +10740,16 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
1) We're not generating bytecodes: 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). 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) x(a1,...,an) into TYPE_OF(this$<n>).x(a1,....an)
2) We're generating bytecodes: 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). 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). x(a1,....,an) into TYPE_OF(this$<n>).x(a1,....an).
Of course, this$<n> can be arbitrarily complex, ranging from Of course, this$<n> can be arbitrarily complex, ranging from
...@@ -10749,10 +10758,12 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super, ...@@ -10749,10 +10758,12 @@ patch_method_invocation (tree patch, tree primary, tree where, int from_super,
maybe_use_access_method returns a nonzero value if the maybe_use_access_method returns a nonzero value if the
this_arg has to be moved into the (then generated) stub this_arg has to be moved into the (then generated) stub
argument list. In the meantime, the selected function argument list. In the meantime, the selected function
might have be replaced by a generated stub. */ might have been replaced by a generated stub. */
if (!primary && if (METHOD_STATIC (list))
maybe_use_access_method (is_super_init, &list, &this_arg)) 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); args = tree_cons (NULL_TREE, this_arg, args);
this_arg = NULL_TREE; /* So it doesn't get chained twice */ this_arg = NULL_TREE; /* So it doesn't get chained twice */
...@@ -10920,8 +10931,8 @@ check_for_static_method_reference (tree wfl, tree node, tree method, ...@@ -10920,8 +10931,8 @@ check_for_static_method_reference (tree wfl, tree node, tree method,
return 0; return 0;
} }
/* Fix the invocation of *MDECL if necessary in the case of a /* Fix the invocation of *MDECL if necessary in the case of an
invocation from an inner class. *THIS_ARG might be modified invocation across a nested class. *THIS_ARG might be modified
appropriately and an alternative access to *MDECL might be appropriately and an alternative access to *MDECL might be
returned. */ returned. */
...@@ -10929,25 +10940,26 @@ static int ...@@ -10929,25 +10940,26 @@ static int
maybe_use_access_method (int is_super_init, tree *mdecl, tree *this_arg) maybe_use_access_method (int is_super_init, tree *mdecl, tree *this_arg)
{ {
tree ctx; tree ctx;
tree md = *mdecl, ta = *this_arg; tree md = *mdecl, ta = NULL_TREE;
int to_return = 0; int to_return = 0;
int non_static_context = !METHOD_STATIC (md); int non_static_context = !METHOD_STATIC (md);
if (is_super_init if (is_super_init
|| DECL_CONTEXT (md) == current_class
|| !PURE_INNER_CLASS_TYPE_P (current_class)
|| DECL_FINIT_P (md) || DECL_FINIT_P (md)
|| DECL_INSTINIT_P (md)) || DECL_INSTINIT_P (md)
|| !nested_member_access_p (current_class, md))
return 0; return 0;
/* If we're calling a method found in an enclosing class, generate /* 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 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 invoking a static method. Note that if MD's type is unrelated to
CURRENT_CLASS, then the current this can be used. */ CURRENT_CLASS, then the current this can be used. */
if (non_static_context 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))); ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
if (inherits_from_p (ctx, DECL_CONTEXT (md))) if (inherits_from_p (ctx, DECL_CONTEXT (md)))
{ {
...@@ -10973,16 +10985,17 @@ maybe_use_access_method (int is_super_init, tree *mdecl, tree *this_arg) ...@@ -10973,16 +10985,17 @@ maybe_use_access_method (int is_super_init, tree *mdecl, tree *this_arg)
} }
/* We might have to use an access method to get to MD. We can /* 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 break the method access rule as long as we're not generating
bytecode */ bytecode. */
if (METHOD_PRIVATE (md) && flag_emit_class_files) 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; to_return = 1;
} }
*mdecl = md; *mdecl = md;
*this_arg = ta; if (this_arg)
*this_arg = ta;
/* Returning a nonzero value indicates we were doing a non static /* Returning a nonzero value indicates we were doing a non static
method invocation that is now a static invocation. It will have method invocation that is now a static invocation. It will have
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment