diff options
author | Alexandre Petit-Bianco <apbianco@cygnus.com> | 2000-06-01 07:44:58 +0000 |
---|---|---|
committer | Alexandre Petit-Bianco <apbianco@gcc.gnu.org> | 2000-06-01 00:44:58 -0700 |
commit | 152de068640f04fc98afdd252a828d7f601c5d65 (patch) | |
tree | 586253d11f233cbb77aa2d57a0c67ea6ec106370 /gcc | |
parent | 3aac3c2fd48d6b18b196acb1b9ad5cf9a0cd85ac (diff) | |
download | gcc-152de068640f04fc98afdd252a828d7f601c5d65.zip gcc-152de068640f04fc98afdd252a828d7f601c5d65.tar.gz gcc-152de068640f04fc98afdd252a828d7f601c5d65.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/java/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/java/class.c | 24 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 1 | ||||
-rw-r--r-- | gcc/java/parse.c | 43 | ||||
-rw-r--r-- | gcc/java/parse.h | 20 | ||||
-rw-r--r-- | gcc/java/parse.y | 43 |
6 files changed, 118 insertions, 25 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 9fdc4f0..7bd5521 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -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 diff --git a/gcc/java/class.c b/gcc/java/class.c index 21232e7..dcc5448 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -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; diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index a05573f..8f2b2c8 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -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)); 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); diff --git a/gcc/java/parse.h b/gcc/java/parse.h index 4ffee79..24b0b9b 100644 --- a/gcc/java/parse.h +++ b/gcc/java/parse.h @@ -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 diff --git a/gcc/java/parse.y b/gcc/java/parse.y index e14ec75..83cd49e 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -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); |