aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/java/parse.c')
-rw-r--r--gcc/java/parse.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/gcc/java/parse.c b/gcc/java/parse.c
index b01055a..2f77d74 100644
--- a/gcc/java/parse.c
+++ b/gcc/java/parse.c
@@ -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);