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
This commit is contained in:
parent
6ab9469a15
commit
3881a11b4a
@ -1,3 +1,19 @@
|
||||
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>
|
||||
|
||||
PR java/23300.
|
||||
|
113
gcc/java/parse.y
113
gcc/java/parse.y
@ -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_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 decl)
|
||||
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 decl)
|
||||
&& 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 class, tree type, tree name,
|
||||
|
||||
|
||||
/* 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 decl)
|
||||
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 decl)
|
||||
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 *orig)
|
||||
/* 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 wfl, tree *found_decl,
|
||||
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 wfl, tree *found_decl,
|
||||
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, tree primary, tree where, int from_super,
|
||||
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, tree primary, tree where, int from_super,
|
||||
&& 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, tree primary, tree where, int from_super,
|
||||
}
|
||||
|
||||
/* 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, tree primary, tree where, int from_super,
|
||||
|
||||
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, tree primary, tree where, int from_super,
|
||||
|
||||
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 wfl, tree node, tree method,
|
||||
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_init, tree *mdecl, tree *this_arg)
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
Loading…
Reference in New Issue
Block a user