class.c (common_enclosing_context_p): New function.
2000-04-24 Alexandre Petit-Bianco <apbianco@cygnus.com> * class.c (common_enclosing_context_p): New function. * java-tree.h (common_enclosing_context_p): Added prototype. * parse.h (INNER_ENCLOSING_SCOPE_CHECK): Relaxed test to allow classes sharing an outer context with the current instance. * parse.y (build_access_to_thisn): Fixed leading comment. (verify_constructor_super): New local `supper_inner'. Skip enclosing context argument in the case of inner class constructors. (patch_method_invocation): Insert proper context as second parameter to pure inner class constructor super invocations. This fixes the Java PR #177. From-SVN: r34332
This commit is contained in:
parent
3aac3c2fd4
commit
152de06864
@ -200,6 +200,18 @@ Wed Apr 26 14:29:33 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* parse.y (register_incomplete_type): Handle JDEP_ANONYMOUS.
|
||||
|
||||
2000-04-24 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* class.c (common_enclosing_context_p): New function.
|
||||
* java-tree.h (common_enclosing_context_p): Added prototype.
|
||||
* parse.h (INNER_ENCLOSING_SCOPE_CHECK): Relaxed test to allow
|
||||
classes sharing an outer context with the current instance.
|
||||
* parse.y (build_access_to_thisn): Fixed leading comment.
|
||||
(verify_constructor_super): New local `supper_inner'. Skip
|
||||
enclosing context argument in the case of inner class constructors.
|
||||
(patch_method_invocation): Insert proper context as second
|
||||
parameter to pure inner class constructor super invocations.
|
||||
|
||||
Mon Apr 24 14:59:36 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
|
||||
|
||||
* parse.y (end_class_declaration): Reset the interface number
|
||||
|
@ -486,6 +486,30 @@ enclosing_context_p (type1, type2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 1 iff there exists a common enclosing context between TYPE1
|
||||
and TYPE2. */
|
||||
|
||||
int common_enclosing_context_p (type1, type2)
|
||||
tree type1, type2;
|
||||
{
|
||||
if (!PURE_INNER_CLASS_TYPE_P (type1) && !PURE_INNER_CLASS_TYPE_P (type2))
|
||||
return 0;
|
||||
|
||||
for (type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))); type1;
|
||||
type1 = (PURE_INNER_CLASS_TYPE_P (type1) ?
|
||||
TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))) : NULL_TREE))
|
||||
{
|
||||
tree current;
|
||||
for (current = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))); current;
|
||||
current = (PURE_INNER_CLASS_TYPE_P (current) ?
|
||||
TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) :
|
||||
NULL_TREE))
|
||||
if (type1 == current)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
add_interface_do (basetype_vec, interface_class, i)
|
||||
tree basetype_vec, interface_class;
|
||||
|
@ -696,6 +696,7 @@ extern void set_super_info PARAMS ((int, tree, tree, int));
|
||||
extern int get_access_flags_from_decl PARAMS ((tree));
|
||||
extern int interface_of_p PARAMS ((tree, tree));
|
||||
extern int inherits_from_p PARAMS ((tree, tree));
|
||||
extern int common_enclosing_context_p PARAMS ((tree, tree));
|
||||
extern int enclosing_context_p PARAMS ((tree, tree));
|
||||
extern void complete_start_java_method PARAMS ((tree));
|
||||
extern tree build_result_decl PARAMS ((tree));
|
||||
|
@ -10642,7 +10642,7 @@ build_access_to_thisn (from, to, lc)
|
||||
|
||||
/* Build an access function to the this$<n> local to TYPE. NULL_TREE
|
||||
is returned if nothing needs to be generated. Otherwise, the method
|
||||
generated, fully walked and a method decl is returned.
|
||||
generated and a method decl is returned.
|
||||
|
||||
NOTE: These generated methods should be declared in a class file
|
||||
attribute so that they can't be referred to directly. */
|
||||
@ -10985,6 +10985,7 @@ verify_constructor_super (mdecl)
|
||||
tree mdecl;
|
||||
{
|
||||
tree class = CLASSTYPE_SUPER (current_class);
|
||||
int super_inner = PURE_INNER_CLASS_TYPE_P (class);
|
||||
tree sdecl;
|
||||
|
||||
if (!class)
|
||||
@ -10997,10 +10998,11 @@ verify_constructor_super (mdecl)
|
||||
for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
|
||||
if (DECL_CONSTRUCTOR_P (sdecl))
|
||||
{
|
||||
tree arg_type;
|
||||
for (arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
|
||||
arg_type != end_params_node &&
|
||||
mdecl_arg_type != end_params_node;
|
||||
tree arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
|
||||
if (super_inner)
|
||||
arg_type = TREE_CHAIN (arg_type);
|
||||
for (; (arg_type != end_params_node
|
||||
&& mdecl_arg_type != end_params_node);
|
||||
arg_type = TREE_CHAIN (arg_type),
|
||||
mdecl_arg_type = TREE_CHAIN (mdecl_arg_type))
|
||||
if (TREE_VALUE (arg_type) != TREE_VALUE (mdecl_arg_type))
|
||||
@ -11015,9 +11017,10 @@ verify_constructor_super (mdecl)
|
||||
{
|
||||
for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
|
||||
{
|
||||
if (DECL_CONSTRUCTOR_P (sdecl)
|
||||
&& TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)))
|
||||
== end_params_node)
|
||||
tree arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
|
||||
if (super_inner)
|
||||
arg = TREE_CHAIN (arg);
|
||||
if (DECL_CONSTRUCTOR_P (sdecl) && arg == end_params_node)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -12286,6 +12289,30 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
|
||||
args = tree_cons (NULL_TREE, integer_zero_node, args);
|
||||
}
|
||||
|
||||
/* This handles the situation where a constructor invocation needs
|
||||
to have an enclosing context passed as a second parameter (the
|
||||
constructor is one of an inner class. We extract it from the
|
||||
current function. */
|
||||
if (is_super_init && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list)))
|
||||
{
|
||||
tree enclosing_decl = DECL_CONTEXT (TYPE_NAME (current_class));
|
||||
tree extra_arg;
|
||||
|
||||
if (ANONYMOUS_CLASS_P (current_class) || !DECL_CONTEXT (enclosing_decl))
|
||||
{
|
||||
extra_arg = DECL_FUNCTION_BODY (current_function_decl);
|
||||
extra_arg = TREE_CHAIN (BLOCK_EXPR_DECLS (extra_arg));
|
||||
}
|
||||
else
|
||||
{
|
||||
tree dest = TREE_TYPE (DECL_CONTEXT (enclosing_decl));
|
||||
extra_arg =
|
||||
build_access_to_thisn (TREE_TYPE (enclosing_decl), dest, 0);
|
||||
extra_arg = java_complete_tree (extra_arg);
|
||||
}
|
||||
args = tree_cons (NULL_TREE, extra_arg, args);
|
||||
}
|
||||
|
||||
is_static_flag = METHOD_STATIC (list);
|
||||
if (! METHOD_STATIC (list) && this_arg != NULL_TREE)
|
||||
args = tree_cons (NULL_TREE, this_arg, args);
|
||||
|
@ -822,15 +822,17 @@ struct parser_ctxt {
|
||||
|
||||
/* Make sure that innerclass T sits in an appropriate enclosing
|
||||
context. */
|
||||
#define INNER_ENCLOSING_SCOPE_CHECK(T) \
|
||||
(INNER_CLASS_TYPE_P ((T)) && !ANONYMOUS_CLASS_P ((T)) \
|
||||
&& ((current_this \
|
||||
/* We have a this and it's not the right one */ \
|
||||
&& (DECL_CONTEXT (TYPE_NAME ((T))) \
|
||||
!= TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this)))) \
|
||||
&& !inherits_from_p (TREE_TYPE (TREE_TYPE (current_this)), \
|
||||
TREE_TYPE (DECL_CONTEXT (TYPE_NAME (T))))) \
|
||||
/* We don't have a this. */ \
|
||||
#define INNER_ENCLOSING_SCOPE_CHECK(T) \
|
||||
(INNER_CLASS_TYPE_P ((T)) && !ANONYMOUS_CLASS_P ((T)) \
|
||||
&& ((current_this \
|
||||
/* We have a this and it's not the right one */ \
|
||||
&& (DECL_CONTEXT (TYPE_NAME ((T))) \
|
||||
!= TYPE_NAME (TREE_TYPE (TREE_TYPE (current_this)))) \
|
||||
&& !inherits_from_p (TREE_TYPE (TREE_TYPE (current_this)), \
|
||||
TREE_TYPE (DECL_CONTEXT (TYPE_NAME (T)))) \
|
||||
&& !common_enclosing_context_p (TREE_TYPE (TREE_TYPE (current_this)), \
|
||||
(T))) \
|
||||
/* We don't have a this. */ \
|
||||
|| !current_this))
|
||||
|
||||
/* Push macro. First argument to PUSH_CPC is a DECL_TYPE, second
|
||||
|
@ -7944,7 +7944,7 @@ build_access_to_thisn (from, to, lc)
|
||||
|
||||
/* Build an access function to the this$<n> local to TYPE. NULL_TREE
|
||||
is returned if nothing needs to be generated. Otherwise, the method
|
||||
generated, fully walked and a method decl is returned.
|
||||
generated and a method decl is returned.
|
||||
|
||||
NOTE: These generated methods should be declared in a class file
|
||||
attribute so that they can't be referred to directly. */
|
||||
@ -8287,6 +8287,7 @@ verify_constructor_super (mdecl)
|
||||
tree mdecl;
|
||||
{
|
||||
tree class = CLASSTYPE_SUPER (current_class);
|
||||
int super_inner = PURE_INNER_CLASS_TYPE_P (class);
|
||||
tree sdecl;
|
||||
|
||||
if (!class)
|
||||
@ -8299,10 +8300,11 @@ verify_constructor_super (mdecl)
|
||||
for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
|
||||
if (DECL_CONSTRUCTOR_P (sdecl))
|
||||
{
|
||||
tree arg_type;
|
||||
for (arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
|
||||
arg_type != end_params_node &&
|
||||
mdecl_arg_type != end_params_node;
|
||||
tree arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
|
||||
if (super_inner)
|
||||
arg_type = TREE_CHAIN (arg_type);
|
||||
for (; (arg_type != end_params_node
|
||||
&& mdecl_arg_type != end_params_node);
|
||||
arg_type = TREE_CHAIN (arg_type),
|
||||
mdecl_arg_type = TREE_CHAIN (mdecl_arg_type))
|
||||
if (TREE_VALUE (arg_type) != TREE_VALUE (mdecl_arg_type))
|
||||
@ -8317,9 +8319,10 @@ verify_constructor_super (mdecl)
|
||||
{
|
||||
for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
|
||||
{
|
||||
if (DECL_CONSTRUCTOR_P (sdecl)
|
||||
&& TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)))
|
||||
== end_params_node)
|
||||
tree arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
|
||||
if (super_inner)
|
||||
arg = TREE_CHAIN (arg);
|
||||
if (DECL_CONSTRUCTOR_P (sdecl) && arg == end_params_node)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -9588,6 +9591,30 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
|
||||
args = tree_cons (NULL_TREE, integer_zero_node, args);
|
||||
}
|
||||
|
||||
/* This handles the situation where a constructor invocation needs
|
||||
to have an enclosing context passed as a second parameter (the
|
||||
constructor is one of an inner class. We extract it from the
|
||||
current function. */
|
||||
if (is_super_init && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list)))
|
||||
{
|
||||
tree enclosing_decl = DECL_CONTEXT (TYPE_NAME (current_class));
|
||||
tree extra_arg;
|
||||
|
||||
if (ANONYMOUS_CLASS_P (current_class) || !DECL_CONTEXT (enclosing_decl))
|
||||
{
|
||||
extra_arg = DECL_FUNCTION_BODY (current_function_decl);
|
||||
extra_arg = TREE_CHAIN (BLOCK_EXPR_DECLS (extra_arg));
|
||||
}
|
||||
else
|
||||
{
|
||||
tree dest = TREE_TYPE (DECL_CONTEXT (enclosing_decl));
|
||||
extra_arg =
|
||||
build_access_to_thisn (TREE_TYPE (enclosing_decl), dest, 0);
|
||||
extra_arg = java_complete_tree (extra_arg);
|
||||
}
|
||||
args = tree_cons (NULL_TREE, extra_arg, args);
|
||||
}
|
||||
|
||||
is_static_flag = METHOD_STATIC (list);
|
||||
if (! METHOD_STATIC (list) && this_arg != NULL_TREE)
|
||||
args = tree_cons (NULL_TREE, this_arg, args);
|
||||
|
Loading…
Reference in New Issue
Block a user