diff options
author | apbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-08-17 21:07:07 +0000 |
---|---|---|
committer | apbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-08-17 21:07:07 +0000 |
commit | 6eb959329f3e10ce3d614e2701a701d89f95cb35 (patch) | |
tree | 48423fd61c7cb8b8e91a0e83679b52ebad7e88a7 | |
parent | 9eb5329a77371d6c73106fb7ad74245dffd31fbb (diff) | |
download | gcc-6eb959329f3e10ce3d614e2701a701d89f95cb35.tar.gz |
2001-08-16 Alexandre Petit-Bianco <apbianco@redhat.com>
* jcf-parse.c (load_class): New locals saved and class_loaded. If
loading a class_or_name fails, try considering an innerclass name
and load the enclosing context.
* parse.y (resolve_inner_class): New function.
(find_as_inner_class): Added leading comment.
(register_incomplete_type): Keep the current context as enclosing
context for JDEP_FIELD dependencies.
(do_resolve_class): Locals new_class_decl and super initialized to
NULL. Call resolve_inner_class, explore the enclosing context
superclass if necessary.
Fixes PR java/4007
2001-08-12 Alexandre Petit-Bianco <apbianco@redhat.com>
* decl.c (init_decl_processing): exception_type_node,
class_not_found_type_node, and no_class_def_found_type_node
initialized. predef_filenames augmented accordingly.
instinit_identifier_node initialized.
* java-tree.def (INSTANCE_INITIALIZERS_EXPR): Entry removed.
* java-tree.h (enum java_tree_index): New entries
JTI_EXCEPTION_TYPE_NODE, JTI_CLASS_NOT_FOUND_TYPE_NODE,
JTI_NO_CLASS_DEF_FOUND_TYPE_NODE, JTI_INSTINIT_IDENTIFIER_NODE.
(exception_type_node): New macro.
(class_not_found_type_node): Likewise.
(no_class_def_found_type_node): Likewise.
(instinit_identifier_node): Likewise.
(PREDEF_FILENAMES_SIZE): Adjusted.
(TYPE_HAS_FINAL_VARIABLE): Fixed typo.
(struct lang_type): Fixed typo in bitfield name.
(DECL_INSTINIT_P): New macro.
(ID_INSTINIT_P): Likewise.
* jcf-write.c (generate_classfile): instinit$ bears the Synthetic
attribute.
* parse.y (encapsulate_with_try_catch): New function.
(generate_instinit): Likewise.
(build_instinit_invocation): Likewise.
(ctors_unchecked_throws_clause_p): Likewise.
(add_instance_initializer): Deleted.
(build_instance_initializer): Likewise.
(in_instance_initializer): Likewise.
(check_method_redefinition): instinit$ not to be verified.
(java_complete_expand_methods): Generate instinit$, simplified code.
(build_dot_class_method): Eliminated unnecessary locals. Use
encapsulate_with_try_catch, removed unnecessary code.
(fix_constructors): New local iii. Use build_instinit_invocation.
(patch_method_invocation): Added comment.
(maybe_use_access_method): Don't consider instinit$.
(find_applicable_accessible_methods_list): Shorten the search for
instinit$ too.
(java_complete_lhs): case INSTANCE_INITIALIZERS_EXPR removed.
(patch_return): Use DECL_INSTINIT_P instead of in_instance_initializer.
(patch_throw_statement): Likewise. Fixed typo.
2001-08-09 Alexandre Petit-Bianco <apbianco@redhat.com>
* expr.c (java_lang_expand_expr): Call `expand_end_bindings' and
`poplevel' in the right order.
(http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01061.html )
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44982 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/java/ChangeLog | 70 | ||||
-rw-r--r-- | gcc/java/decl.c | 10 | ||||
-rw-r--r-- | gcc/java/expr.c | 2 | ||||
-rw-r--r-- | gcc/java/java-tree.def | 6 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 20 | ||||
-rw-r--r-- | gcc/java/jcf-parse.c | 30 | ||||
-rw-r--r-- | gcc/java/jcf-write.c | 3 | ||||
-rw-r--r-- | gcc/java/parse.y | 387 |
8 files changed, 371 insertions, 157 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 9be2fce3693..6db866fd59b 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,17 @@ +2001-08-16 Alexandre Petit-Bianco <apbianco@redhat.com> + + * jcf-parse.c (load_class): New locals saved and class_loaded. If + loading a class_or_name fails, try considering an innerclass name + and load the enclosing context. + * parse.y (resolve_inner_class): New function. + (find_as_inner_class): Added leading comment. + (register_incomplete_type): Keep the current context as enclosing + context for JDEP_FIELD dependencies. + (do_resolve_class): Locals new_class_decl and super initialized to + NULL. Call resolve_inner_class, explore the enclosing context + superclass if necessary. + Fixes PR java/4007 + 2001-08-16 Tom Tromey <tromey@redhat.com> * jcf-dump.c (main): Updated for change to jcf_path_seal. @@ -13,6 +27,47 @@ * Make-lang.in (java/decl.o): Update dependencies. * decl.c: Include libfuncs.h, don't include toplev.h. +2001-08-12 Alexandre Petit-Bianco <apbianco@redhat.com> + + * decl.c (init_decl_processing): exception_type_node, + class_not_found_type_node, and no_class_def_found_type_node + initialized. predef_filenames augmented accordingly. + instinit_identifier_node initialized. + * java-tree.def (INSTANCE_INITIALIZERS_EXPR): Entry removed. + * java-tree.h (enum java_tree_index): New entries + JTI_EXCEPTION_TYPE_NODE, JTI_CLASS_NOT_FOUND_TYPE_NODE, + JTI_NO_CLASS_DEF_FOUND_TYPE_NODE, JTI_INSTINIT_IDENTIFIER_NODE. + (exception_type_node): New macro. + (class_not_found_type_node): Likewise. + (no_class_def_found_type_node): Likewise. + (instinit_identifier_node): Likewise. + (PREDEF_FILENAMES_SIZE): Adjusted. + (TYPE_HAS_FINAL_VARIABLE): Fixed typo. + (struct lang_type): Fixed typo in bitfield name. + (DECL_INSTINIT_P): New macro. + (ID_INSTINIT_P): Likewise. + * jcf-write.c (generate_classfile): instinit$ bears the Synthetic + attribute. + * parse.y (encapsulate_with_try_catch): New function. + (generate_instinit): Likewise. + (build_instinit_invocation): Likewise. + (ctors_unchecked_throws_clause_p): Likewise. + (add_instance_initializer): Deleted. + (build_instance_initializer): Likewise. + (in_instance_initializer): Likewise. + (check_method_redefinition): instinit$ not to be verified. + (java_complete_expand_methods): Generate instinit$, simplified code. + (build_dot_class_method): Eliminated unnecessary locals. Use + encapsulate_with_try_catch, removed unnecessary code. + (fix_constructors): New local iii. Use build_instinit_invocation. + (patch_method_invocation): Added comment. + (maybe_use_access_method): Don't consider instinit$. + (find_applicable_accessible_methods_list): Shorten the search for + instinit$ too. + (java_complete_lhs): case INSTANCE_INITIALIZERS_EXPR removed. + (patch_return): Use DECL_INSTINIT_P instead of in_instance_initializer. + (patch_throw_statement): Likewise. Fixed typo. + 2001-08-12 David Edelsohn <edelsohn@gnu.org> Revert: @@ -31,6 +86,11 @@ * lex.h: Don't include setjmp.h. Don't define SET_FLOAT_HANDLER or prototype set_float_handler. +2001-08-09 Alexandre Petit-Bianco <apbianco@redhat.com> + + * expr.c (java_lang_expand_expr): Call `expand_end_bindings' and + `poplevel' in the right order. + 2001-08-09 Richard Henderson <rth@redhat.com> * Make-lang.in (class.o): Depend on TARGET_H. @@ -390,7 +450,7 @@ 2001-05-07 Alexandre Petit-Bianco <apbianco@redhat.com> - * parse.y (fix_constructors): Removed unecessary assignment to + * parse.y (fix_constructors): Removed unnecessary assignment to local. Moved assignment to `this$<n>', fixed comments and indentation. (build_wfl_wrap): Fixed indentation. @@ -2912,7 +2972,7 @@ Sun Aug 6 00:47:24 2000 Ovidiu Predescu <ovidiu@cup.hp.com> 2000-06-25 Alexandre Petit-Bianco <apbianco@cygnus.com> * parse.y (do_resolve_class): Minor optimiztion in the package - list search. Removed unecessary test and return statement. + list search. Removed unnecessary test and return statement. (valid_ref_assignconv_cast_p): Order of arguments to enclosing_context_p fixed. @@ -3296,7 +3356,7 @@ Mon Apr 24 14:59:36 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> 2000-04-24 Alexandre Petit-Bianco <apbianco@cygnus.com> - * parse.y (source_start_java_method): Deleted unecessary code. + * parse.y (source_start_java_method): Deleted unnecessary code. (patch_method_invocation): Fixed comment. 2000-04-24 Robert Lipe <robertlipe@usa.net> @@ -3860,7 +3920,7 @@ Fri Feb 25 18:00:37 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> * parse.y (resolve_expression_name): Use `orig' as a second argument to resolve_field_access. - (resolve_field_access): Removed unecessary code when dealing with + (resolve_field_access): Removed unnecessary code when dealing with static fields. Wed Feb 23 17:41:50 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> @@ -11650,7 +11710,7 @@ Thu Sep 11 19:45:18 1997 Alexandre Petit-Bianco <apbianco@cygnus.com> layout. * typeck.c: (parse_signature_string): Temporary use permanent_obstack. (build_java_signature): Temporary use permanent_obstack. - * verify.c: (verify_jvm_instruction): removed unecessary verification + * verify.c: (verify_jvm_instruction): removed unnecessary verification on ACC_SUPER flag. * java-tree.h (METHOD_NATIVE, METHOD_TRANSIENT): Defined. (FIELD_VOLATILE, FIELD_TRANSIENT): Defined. diff --git a/gcc/java/decl.c b/gcc/java/decl.c index abb49fa5acf..ecfa9aa17bc 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -541,10 +541,16 @@ init_decl_processing () string_ptr_type_node = promote_type (string_type_node); class_type_node = lookup_class (get_identifier ("java.lang.Class")); throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable")); + exception_type_node = lookup_class (get_identifier ("java.lang.Exception")); runtime_exception_type_node = lookup_class (get_identifier ("java.lang.RuntimeException")); error_exception_type_node = lookup_class (get_identifier ("java.lang.Error")); + class_not_found_type_node = + lookup_class (get_identifier ("java.lang.ClassNotFoundException")); + no_class_def_found_type_node = + lookup_class (get_identifier ("java.lang.NoClassDefFoundError")); + rawdata_ptr_type_node = promote_type (lookup_class (get_identifier ("gnu.gcj.RawData"))); @@ -557,6 +563,9 @@ init_decl_processing () predef_filenames [4] = get_identifier ("java/lang/String.java"); predef_filenames [5] = get_identifier ("java/lang/Throwable.java"); predef_filenames [6] = get_identifier ("gnu/gcj/RawData.java"); + predef_filenames [7] = get_identifier ("java/lang/Exception"); + predef_filenames [8] = get_identifier ("java/lang/ClassNotFoundException"); + predef_filenames [9] = get_identifier ("java/lang/NoClassDefFoundError"); methodtable_type = make_node (RECORD_TYPE); layout_type (methodtable_type); @@ -572,6 +581,7 @@ init_decl_processing () /* The new `finit$' special method identifier. This one is now generated in place of `$finit$'. */ finit_identifier_node = get_identifier ("finit$"); + instinit_identifier_node = get_identifier ("instinit$"); void_signature_node = get_identifier ("()V"); length_identifier_node = get_identifier ("length"); this_identifier_node = get_identifier ("this"); diff --git a/gcc/java/expr.c b/gcc/java/expr.c index f7056fee4f4..d1cc19e93b8 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -2505,8 +2505,8 @@ java_lang_expand_expr (exp, target, tmode, modifier) } expand_expr (body, const0_rtx, VOIDmode, 0); emit_queue (); - poplevel (1, 1, 0); expand_end_bindings (getdecls (), 1, 0); + poplevel (1, 1, 0); return const0_rtx; } return const0_rtx; diff --git a/gcc/java/java-tree.def b/gcc/java/java-tree.def index c2e926f910b..f15bc38701f 100644 --- a/gcc/java/java-tree.def +++ b/gcc/java/java-tree.def @@ -88,12 +88,6 @@ DEFTREECODE (NEW_ARRAY_INIT, "new_array_init", '1', 1) reference from. */ DEFTREECODE (CLASS_LITERAL, "class_literal", '1', 1) -/* Instance initializer. - Operand 0 contains the intance initializer statement. This tree node - is used for context detection, so that special rules can be - enforced. */ -DEFTREECODE (INSTANCE_INITIALIZERS_EXPR, "instance_initializers_expr", '1', 1) - /* The Java object within the exception object from the runtime. */ DEFTREECODE (JAVA_EXC_OBJ_EXPR, "java_exc_obj_expr", 'e', 0) diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index d114747a8e7..ef4e0632b79 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -251,9 +251,12 @@ enum java_tree_index JTI_STRING_TYPE_NODE, JTI_STRING_PTR_TYPE_NODE, JTI_THROWABLE_TYPE_NODE, + JTI_EXCEPTION_TYPE_NODE, JTI_RUNTIME_EXCEPTION_TYPE_NODE, JTI_ERROR_EXCEPTION_TYPE_NODE, JTI_RAWDATA_PTR_TYPE_NODE, + JTI_CLASS_NOT_FOUND_TYPE_NODE, + JTI_NO_CLASS_DEF_FOUND_TYPE_NODE, JTI_BYTE_ARRAY_TYPE_NODE, JTI_SHORT_ARRAY_TYPE_NODE, @@ -278,6 +281,7 @@ enum java_tree_index JTI_INIT_IDENTIFIER_NODE, JTI_CLINIT_IDENTIFIER_NODE, JTI_FINIT_IDENTIFIER_NODE, + JTI_INSTINIT_IDENTIFIER_NODE, JTI_FINIT_LEG_IDENTIFIER_NODE, JTI_VOID_SIGNATURE_NODE, JTI_LENGTH_IDENTIFIER_NODE, @@ -408,12 +412,18 @@ extern tree java_global_trees[JTI_MAX]; java_global_trees[JTI_STRING_PTR_TYPE_NODE] #define throwable_type_node \ java_global_trees[JTI_THROWABLE_TYPE_NODE] +#define exception_type_node \ + java_global_trees[JTI_EXCEPTION_TYPE_NODE] #define runtime_exception_type_node \ java_global_trees[JTI_RUNTIME_EXCEPTION_TYPE_NODE] #define error_exception_type_node \ java_global_trees[JTI_ERROR_EXCEPTION_TYPE_NODE] #define rawdata_ptr_type_node \ java_global_trees[JTI_RAWDATA_PTR_TYPE_NODE] +#define class_not_found_type_node \ + java_global_trees[JTI_CLASS_NOT_FOUND_TYPE_NODE] +#define no_class_def_found_type_node \ + java_global_trees[JTI_NO_CLASS_DEF_FOUND_TYPE_NODE] #define byte_array_type_node \ java_global_trees[JTI_BYTE_ARRAY_TYPE_NODE] @@ -463,6 +473,8 @@ extern tree java_global_trees[JTI_MAX]; java_global_trees[JTI_FINIT_IDENTIFIER_NODE] /* "finit$" */ #define finit_leg_identifier_node \ java_global_trees[JTI_FINIT_LEG_IDENTIFIER_NODE] /* "$finit$" */ +#define instinit_identifier_node \ + java_global_trees[JTI_INSTINIT_IDENTIFIER_NODE] /* "instinit$" */ #define void_signature_node \ java_global_trees[JTI_VOID_SIGNATURE_NODE] /* "()V" */ #define length_identifier_node \ @@ -598,7 +610,7 @@ extern tree java_global_trees[JTI_MAX]; #define nativecode_ptr_array_type_node \ java_global_trees[JTI_NATIVECODE_PTR_ARRAY_TYPE_NODE] -#define PREDEF_FILENAMES_SIZE 7 +#define PREDEF_FILENAMES_SIZE 10 extern tree predef_filenames[PREDEF_FILENAMES_SIZE]; #define nativecode_ptr_type_node ptr_type_node @@ -937,7 +949,7 @@ struct lang_decl_var #define TYPE_PACKAGE_LIST(T) (TYPE_LANG_SPECIFIC(T)->package_list) #define TYPE_PRIVATE_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->pic) #define TYPE_PROTECTED_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->poic) -#define TYPE_HAS_FINAL_VARIABLE(T) (TYPE_LANG_SPECIFIC(T)->afv) +#define TYPE_HAS_FINAL_VARIABLE(T) (TYPE_LANG_SPECIFIC(T)->hfv) struct lang_type { @@ -955,7 +967,7 @@ struct lang_type tree package_list; /* List of package names, progressive */ unsigned pic:1; /* Private Inner Class. */ unsigned poic:1; /* Protected Inner Class. */ - unsigned afv:1; /* Has final variables */ + unsigned hfv:1; /* Has final variables */ }; #ifdef JAVA_USE_HANDLES @@ -1197,6 +1209,7 @@ struct rtx_def * java_lang_expand_expr PARAMS ((tree, rtx, enum machine_mode, #define DECL_INIT_P(DECL) (ID_INIT_P (DECL_NAME (DECL))) #define DECL_FINIT_P(DECL) (ID_FINIT_P (DECL_NAME (DECL))) #define DECL_CLINIT_P(DECL) (ID_CLINIT_P (DECL_NAME (DECL))) +#define DECL_INSTINIT_P(DECL) (ID_INSTINIT_P (DECL_NAME (DECL))) /* Predicates on method identifiers. Kept close to other macros using them */ @@ -1209,6 +1222,7 @@ struct rtx_def * java_lang_expand_expr PARAMS ((tree, rtx, enum machine_mode, || (ID) == finit_leg_identifier_node) #define ID_CLINIT_P(ID) ((ID) == clinit_identifier_node) #define ID_CLASSDOLLAR_P(ID) ((ID) == classdollar_identifier_node) +#define ID_INSTINIT_P(ID) ((ID) == instinit_identifier_node) /* Access flags etc for a variable/field (a FIELD_DECL): */ diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index c73d1dcf3b2..e258167feb1 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -650,7 +650,8 @@ load_class (class_or_name, verbose) tree class_or_name; int verbose; { - tree name; + tree name, saved; + int class_loaded; /* class_or_name can be the name of the class we want to load */ if (TREE_CODE (class_or_name) == IDENTIFIER_NODE) @@ -663,8 +664,31 @@ load_class (class_or_name, verbose) else name = DECL_NAME (TYPE_NAME (class_or_name)); - if (read_class (name) == 0 && verbose) - error ("Cannot find file for class %s.", IDENTIFIER_POINTER (name)); + saved = name; + while (1) + { + char *dollar; + + if ((class_loaded = read_class (name))) + break; + + /* We failed loading name. Now consider that we might be looking + for a inner class but it's only available in source for in + its enclosing context. */ + if ((dollar = strrchr (IDENTIFIER_POINTER (name), '$'))) + { + int c = *dollar; + *dollar = '\0'; + name = get_identifier (IDENTIFIER_POINTER (name)); + *dollar = c; + } + /* Otherwise, we failed, we bail. */ + else + break; + } + + if (!class_loaded && verbose) + error ("Cannot find file for class %s.", IDENTIFIER_POINTER (saved)); } /* Parse the .class file JCF. */ diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c index ca453c8edd9..7339e95315b 100644 --- a/gcc/java/jcf-write.c +++ b/gcc/java/jcf-write.c @@ -2935,7 +2935,8 @@ generate_classfile (clas, state) i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE); /* Make room for the Synthetic attribute (of zero length.) */ - if (DECL_FINIT_P (part) + if (DECL_FINIT_P (part) + || DECL_INSTINIT_P (part) || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part)) || TYPE_DOT_CLASS (clas) == part) { diff --git a/gcc/java/parse.y b/gcc/java/parse.y index a1f36aaa281..b4eb9301df5 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -221,6 +221,7 @@ static tree string_constant_concatenation PARAMS ((tree, tree)); static tree build_string_concatenation PARAMS ((tree, tree)); static tree patch_string_cst PARAMS ((tree)); static tree patch_string PARAMS ((tree)); +static tree encapsulate_with_try_catch PARAMS ((int, tree, tree, tree)); static tree build_try_statement PARAMS ((int, tree, tree)); static tree build_try_finally_statement PARAMS ((int, tree, tree)); static tree patch_try_statement PARAMS ((tree)); @@ -229,6 +230,7 @@ static tree patch_throw_statement PARAMS ((tree, tree)); static void check_thrown_exceptions PARAMS ((int, tree)); static int check_thrown_exceptions_do PARAMS ((tree)); static void purge_unchecked_exceptions PARAMS ((tree)); +static bool ctors_unchecked_throws_clause_p PARAMS ((tree)); static void check_throws_clauses PARAMS ((tree, tree, tree)); static void finish_method_declaration PARAMS ((tree)); static tree build_super_invocation PARAMS ((tree)); @@ -239,8 +241,8 @@ static tree build_this_super_qualified_invocation PARAMS ((int, tree, tree, static const char *get_printable_method_name PARAMS ((tree)); static tree patch_conditional_expr PARAMS ((tree, tree, tree)); static tree generate_finit PARAMS ((tree)); -static void add_instance_initializer PARAMS ((tree)); -static tree build_instance_initializer PARAMS ((tree)); +static tree generate_instinit PARAMS ((tree)); +static tree build_instinit_invocation PARAMS ((tree)); static void fix_constructors PARAMS ((tree)); static tree build_alias_initializer_parameter_list PARAMS ((int, tree, tree, int *)); @@ -300,6 +302,8 @@ static tree maybe_make_nested_class_name PARAMS ((tree)); static void make_nested_class_name PARAMS ((tree)); static void set_nested_class_simple_name_value PARAMS ((tree, int)); static void link_nested_class_to_enclosing PARAMS ((void)); +static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *, + tree *, tree)); static tree find_as_inner_class PARAMS ((tree, tree, tree)); static tree find_as_inner_class_do PARAMS ((tree, tree)); static int check_inner_class_redefinition PARAMS ((tree, tree)); @@ -349,9 +353,6 @@ int do_not_fold; /* Cyclic inheritance report, as it can be set by layout_class */ const char *cyclic_inheritance_report; -/* Tell when we're within an instance initializer */ -static int in_instance_initializer; - /* The current parser context */ struct parser_ctxt *ctxp; @@ -3528,6 +3529,74 @@ check_inner_class_redefinition (raw_name, cl) return 0; } +/* Tries to find a decl for CLASS_TYPE within ENCLOSING. If we fail, + we remember ENCLOSING and SUPER. */ + +static tree +resolve_inner_class (circularity_hash, cl, enclosing, super, class_type) + struct hash_table *circularity_hash; + tree cl, *enclosing, *super, class_type; +{ + tree local_enclosing = *enclosing; + tree local_super = NULL_TREE; + + while (local_enclosing) + { + tree intermediate, decl; + + hash_lookup (circularity_hash, + (const hash_table_key) local_enclosing, TRUE, NULL); + + if ((decl = find_as_inner_class (local_enclosing, class_type, cl))) + return decl; + + intermediate = local_enclosing; + /* Explore enclosing contexts. */ + while (INNER_CLASS_DECL_P (intermediate)) + { + intermediate = DECL_CONTEXT (intermediate); + if ((decl = find_as_inner_class (intermediate, class_type, cl))) + return decl; + } + + /* Now go to the upper classes, bail out if necessary. We will + analyze the returned SUPER and act accordingly (see + do_resolve_class.) */ + local_super = CLASSTYPE_SUPER (TREE_TYPE (local_enclosing)); + if (!local_super || local_super == object_type_node) + break; + + if (TREE_CODE (local_super) == POINTER_TYPE) + local_super = do_resolve_class (NULL, local_super, NULL, NULL); + else + local_super = TYPE_NAME (local_super); + + /* We may not have checked for circular inheritance yet, so do so + here to prevent an infinite loop. */ + if (hash_lookup (circularity_hash, + (const hash_table_key) local_super, FALSE, NULL)) + { + if (!cl) + cl = lookup_cl (local_enclosing); + + parse_error_context + (cl, "Cyclic inheritance involving %s", + IDENTIFIER_POINTER (DECL_NAME (local_enclosing))); + local_enclosing = NULL_TREE; + } + local_enclosing = local_super; + } + + /* We failed. Return LOCAL_SUPER and LOCAL_ENCLOSING. */ + *super = local_super; + *enclosing = local_enclosing; + + return NULL_TREE; +} + +/* Within ENCLOSING, find a decl for NAME and return it. NAME can be + qualified. */ + static tree find_as_inner_class (enclosing, name, cl) tree enclosing, name, cl; @@ -4363,29 +4432,71 @@ generate_finit (class_type) return mdecl; } +/* Generate a function to run the instance initialization code. The + private method is called `instinit$'. Unless we're dealing with an + anonymous class, we determine whether all ctors of CLASS_TYPE + declare a checked exception in their `throws' clause in order to + see whether it's necessary to encapsulate the instance initializer + statements in a try/catch/rethrow sequence. */ + static tree -build_instance_initializer (mdecl) - tree mdecl; +generate_instinit (class_type) + tree class_type; { - tree compound = NULL_TREE; - tree stmt_list = TYPE_II_STMT_LIST (DECL_CONTEXT (mdecl)); tree current; + tree compound = NULL_TREE; + tree parms = tree_cons (this_identifier_node, + build_pointer_type (class_type), end_params_node); + tree mdecl = create_artificial_method (class_type, ACC_PRIVATE, + void_type_node, + instinit_identifier_node, parms); + + layout_class_method (class_type, CLASSTYPE_SUPER (class_type), + mdecl, NULL_TREE); - for (current = stmt_list; current; current = TREE_CHAIN (current)) + /* Gather all the statements in a compound */ + for (current = TYPE_II_STMT_LIST (class_type); + current; current = TREE_CHAIN (current)) compound = add_stmt_to_compound (compound, NULL_TREE, current); - return compound; + /* We need to encapsulate COMPOUND by a try/catch statement to + rethrow exceptions that might occur in the instance initializer. + We do that only if all ctors of CLASS_TYPE are set to catch a + checked exception. This doesn't apply to anonymous classes (since + they don't have declared ctors.) */ + if (!ANONYMOUS_CLASS_P (class_type) && + ctors_unchecked_throws_clause_p (class_type)) + { + compound = encapsulate_with_try_catch (0, exception_type_node, compound, + build1 (THROW_EXPR, NULL_TREE, + build_wfl_node (wpv_id))); + DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE, + exception_type_node); + } + + start_artificial_method_body (mdecl); + java_method_add_stmt (mdecl, compound); + end_artificial_method_body (mdecl); + + return mdecl; } -static void -add_instance_initializer (mdecl) - tree mdecl; +/* FIXME */ +static tree +build_instinit_invocation (class_type) + tree class_type; { - tree compound = build_instance_initializer (mdecl); + tree to_return = NULL_TREE; - if (compound) - java_method_add_stmt (mdecl, build1 (INSTANCE_INITIALIZERS_EXPR, - NULL_TREE, compound)); + if (TYPE_II_STMT_LIST (class_type)) + { + tree parm = build_tree_list (NULL_TREE, + build_wfl_node (this_identifier_node)); + to_return = + build_method_invocation (build_wfl_node (instinit_identifier_node), + parm); + } + return to_return; } /* Shared accros method_declarator and method_header to remember the @@ -5095,7 +5206,7 @@ register_incomplete_type (kind, wfl, decl, ptr) /* For some dependencies, set the enclosing class of the current class to be the enclosing context */ if ((kind == JDEP_SUPER || kind == JDEP_INTERFACE - || kind == JDEP_ANONYMOUS || kind == JDEP_FIELD) + || kind == JDEP_ANONYMOUS) && GET_ENCLOSING_CPC ()) JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ()); else @@ -5574,7 +5685,7 @@ tree do_resolve_class (enclosing, class_type, decl, cl) tree enclosing, class_type, decl, cl; { - tree new_class_decl, super; + tree new_class_decl = NULL_TREE, super = NULL_TREE; struct hash_table _ht, *circularity_hash = &_ht; /* This hash table is used to register the classes we're going @@ -5590,58 +5701,25 @@ do_resolve_class (enclosing, class_type, decl, cl) being loaded from class file. FIXME. */ while (enclosing) { - tree intermediate; - - hash_lookup (circularity_hash, - (const hash_table_key) enclosing, TRUE, NULL); - - if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl))) - { - hash_table_free (circularity_hash); - return new_class_decl; - } - - intermediate = enclosing; - /* Explore enclosing contexts. */ - while (INNER_CLASS_DECL_P (intermediate)) - { - intermediate = DECL_CONTEXT (intermediate); - if ((new_class_decl = find_as_inner_class (intermediate, - class_type, cl))) - { - hash_table_free (circularity_hash); - return new_class_decl; - } - } - - /* Now go to the upper classes, bail out if necessary. */ - super = CLASSTYPE_SUPER (TREE_TYPE (enclosing)); - if (!super || super == object_type_node) - break; + new_class_decl = resolve_inner_class (circularity_hash, cl, &enclosing, + &super, class_type); + if (new_class_decl) + break; - if (TREE_CODE (super) == POINTER_TYPE) - super = do_resolve_class (NULL, super, NULL, NULL); + /* If we haven't found anything because SUPER reached Object and + ENCLOSING happens to be an innerclass, try the enclosing context. */ + if ((!super || super == object_type_node) && + enclosing && INNER_CLASS_DECL_P (enclosing)) + enclosing = DECL_CONTEXT (enclosing); else - super = TYPE_NAME (super); - - /* We may not have checked for circular inheritance yet, so do so - here to prevent an infinite loop. */ - if (hash_lookup (circularity_hash, - (const hash_table_key) super, FALSE, NULL)) - { - if (!cl) - cl = lookup_cl (enclosing); - - parse_error_context - (cl, "Cyclic inheritance involving %s", - IDENTIFIER_POINTER (DECL_NAME (enclosing))); - break; - } - enclosing = super; + enclosing = NULL_TREE; } hash_table_free (circularity_hash); + if (new_class_decl) + return new_class_decl; + /* 1- Check for the type in single imports. This will change TYPE_NAME() if something relevant is found */ find_in_imports (class_type); @@ -5920,8 +5998,9 @@ check_method_redefinition (class, method) { tree redef, sig; - /* There's no need to verify <clinit> and finit$ */ - if (DECL_CLINIT_P (method) || DECL_FINIT_P (method)) + /* There's no need to verify <clinit> and finit$ and instinit$ */ + if (DECL_CLINIT_P (method) + || DECL_FINIT_P (method) || DECL_INSTINIT_P (method)) return 0; sig = TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (method)); @@ -7460,7 +7539,7 @@ static void java_complete_expand_methods (class_decl) tree class_decl; { - tree clinit, finit, decl, first_decl; + tree clinit, decl, first_decl; current_class = TREE_TYPE (class_decl); @@ -7482,13 +7561,15 @@ java_complete_expand_methods (class_decl) first_decl = TYPE_METHODS (current_class); clinit = maybe_generate_pre_expand_clinit (current_class); - /* Then generate finit$ (if we need to) because constructor will + /* Then generate finit$ (if we need to) because constructors will try to use it.*/ if (TYPE_FINIT_STMT_LIST (current_class)) - { - finit = generate_finit (current_class); - java_complete_expand_method (finit); - } + java_complete_expand_method (generate_finit (current_class)); + + /* Then generate instinit$ (if we need to) because constructors will + try to use it. */ + if (TYPE_II_STMT_LIST (current_class)) + java_complete_expand_method (generate_instinit (current_class)); /* Now do the constructors */ for (decl = first_decl ; !java_error_count && decl; decl = TREE_CHAIN (decl)) @@ -8498,9 +8579,7 @@ build_dot_class_method (class) #define BWF(S) build_wfl_node (get_identifier ((S))) #define MQN(X,Y) make_qualified_name ((X), (Y), 0) tree args, tmp, saved_current_function_decl, mdecl; - tree stmt, throw_stmt, catch, catch_block, try_block; - tree catch_clause_param; - tree class_not_found_exception, no_class_def_found_error; + tree stmt, throw_stmt; static tree get_message_wfl, type_parm_wfl; @@ -8520,33 +8599,24 @@ build_dot_class_method (class) /* Build the qualified name java.lang.Class.forName */ tmp = MQN (MQN (MQN (BWF ("java"), BWF ("lang")), BWF ("Class")), BWF ("forName")); - - /* For things we have to catch and throw */ - class_not_found_exception = - lookup_class (get_identifier ("java.lang.ClassNotFoundException")); - no_class_def_found_error = - lookup_class (get_identifier ("java.lang.NoClassDefFoundError")); - load_class (class_not_found_exception, 1); - load_class (no_class_def_found_error, 1); - + load_class (class_not_found_type_node, 1); + load_class (no_class_def_found_type_node, 1); + /* Create the "class$" function */ mdecl = create_artificial_method (class, ACC_STATIC, build_pointer_type (class_type_node), classdollar_identifier_node, args); - DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE, - no_class_def_found_error); - + DECL_FUNCTION_THROWS (mdecl) = + build_tree_list (NULL_TREE, no_class_def_found_type_node); + /* We start by building the try block. We need to build: return (java.lang.Class.forName (type)); */ stmt = build_method_invocation (tmp, build_tree_list (NULL_TREE, type_parm_wfl)); stmt = build_return (0, stmt); - /* Put it in a block. That's the try block */ - try_block = build_expr_block (stmt, NULL_TREE); /* Now onto the catch block. We start by building the expression - throwing a new exception: - throw new NoClassDefFoundError (_.getMessage); */ + throwing a new exception: throw new NoClassDefFoundError (_.getMessage) */ throw_stmt = make_qualified_name (build_wfl_node (wpv_id), get_message_wfl, 0); throw_stmt = build_method_invocation (throw_stmt, NULL_TREE); @@ -8559,27 +8629,9 @@ build_dot_class_method (class) /* Build the throw, (it's too early to use BUILD_THROW) */ throw_stmt = build1 (THROW_EXPR, NULL_TREE, throw_stmt); - /* Build the catch block to encapsulate all this. We begin by - building an decl for the catch clause parameter and link it to - newly created block, the catch block. */ - catch_clause_param = - build_decl (VAR_DECL, wpv_id, - build_pointer_type (class_not_found_exception)); - catch_block = build_expr_block (NULL_TREE, catch_clause_param); - - /* We initialize the variable with the exception handler. */ - catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param, - build (JAVA_EXC_OBJ_EXPR, ptr_type_node)); - add_stmt_to_block (catch_block, NULL_TREE, catch); - - /* We add the statement throwing the new exception */ - add_stmt_to_block (catch_block, NULL_TREE, throw_stmt); - - /* Build a catch expression for all this */ - catch_block = build1 (CATCH_EXPR, NULL_TREE, catch_block); - - /* Build the try/catch sequence */ - stmt = build_try_statement (0, try_block, catch_block); + /* Encapsulate STMT in a try block. The catch clause executes THROW_STMT */ + stmt = encapsulate_with_try_catch (0, class_not_found_type_node, + stmt, throw_stmt); fix_method_argument_names (args, mdecl); layout_class_method (class, NULL_TREE, mdecl, NULL_TREE); @@ -8620,6 +8672,7 @@ static void fix_constructors (mdecl) tree mdecl; { + tree iii; /* Instance Initializer Invocation */ tree body = DECL_FUNCTION_BODY (mdecl); tree thisn_assign, compound = NULL_TREE; tree class_type = DECL_CONTEXT (mdecl); @@ -8661,9 +8714,9 @@ fix_constructors (mdecl) of that. */ java_method_add_stmt (mdecl, build_super_invocation (mdecl)); - /* Insert the instance initializer block right here, after the - super invocation. */ - add_instance_initializer (mdecl); + /* FIXME */ + if ((iii = build_instinit_invocation (class_type))) + java_method_add_stmt (mdecl, iii); end_artificial_method_body (mdecl); } @@ -8674,7 +8727,6 @@ fix_constructors (mdecl) int invokes_this = 0; tree found_call = NULL_TREE; tree main_block = BLOCK_EXPR_BODY (body); - tree ii; /* Instance Initializer */ while (body) switch (TREE_CODE (body)) @@ -8717,8 +8769,8 @@ fix_constructors (mdecl) } /* Insert the instance initializer block right after. */ - if (!invokes_this && (ii = build_instance_initializer (mdecl))) - compound = add_stmt_to_compound (compound, NULL_TREE, ii); + if (!invokes_this && (iii = build_instinit_invocation (class_type))) + compound = add_stmt_to_compound (compound, NULL_TREE, iii); /* Fix the constructor main block if we're adding extra stmts */ if (compound) @@ -10285,6 +10337,8 @@ patch_method_invocation (patch, primary, where, from_super, if (ret_decl) *ret_decl = list; patch = patch_invoke (patch, list, args); + + /* Now is a good time to insert the call to finit$ */ if (is_super_init && CLASS_HAS_FINIT_P (current_class)) { tree finit_parms, finit_call; @@ -10346,7 +10400,8 @@ maybe_use_access_method (is_super_init, mdecl, this_arg) 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)) return 0; /* If we're calling a method found in an enclosing class, generate @@ -10717,10 +10772,10 @@ find_applicable_accessible_methods_list (lc, class, name, arglist) search_applicable_methods_list (lc, TYPE_METHODS (class), name, arglist, &list, &all_list); - /* When looking finit$ or class$, we turn LC to 1 so that we - only search in class. Note that we should have found + /* When looking finit$, class$ or instinit$, we turn LC to 1 so + that we only search in class. Note that we should have found something at this point. */ - if (ID_FINIT_P (name) || ID_CLASSDOLLAR_P (name)) + if (ID_FINIT_P (name) || ID_CLASSDOLLAR_P (name) || ID_INSTINIT_P (name)) { lc = 1; if (!list) @@ -12001,16 +12056,6 @@ java_complete_lhs (node) return error_mark_node; break; - case INSTANCE_INITIALIZERS_EXPR: - in_instance_initializer++; - node = java_complete_tree (TREE_OPERAND (node, 0)); - in_instance_initializer--; - if (node != error_mark_node) - TREE_TYPE (node) = void_type_node; - else - return error_mark_node; - break; - default: CAN_COMPLETE_NORMALLY (node) = 1; /* Ok: may be we have a STRING_CST or a crafted `StringBuffer' @@ -14709,12 +14754,12 @@ patch_return (node) if (!return_exp && (mtype != void_type_node && !DECL_CONSTRUCTOR_P (meth))) error_found = 2; - if (in_instance_initializer) + if (DECL_INSTINIT_P (current_function_decl)) error_found = 1; if (error_found) { - if (in_instance_initializer) + if (DECL_INSTINIT_P (current_function_decl)) parse_error_context (wfl_operator, "`return' inside instance initializer"); @@ -15234,6 +15279,39 @@ patch_switch_statement (node) /* 14.18 The try/catch statements */ +/* Encapsulate TRY_STMTS' in a try catch sequence. The catch clause + catches TYPE and executes CATCH_STMTS. */ + +static tree +encapsulate_with_try_catch (location, type, try_stmts, catch_stmts) + int location; + tree type, try_stmts, catch_stmts; +{ + tree try_block, catch_clause_param, catch_block, catch; + + /* First build a try block */ + try_block = build_expr_block (try_stmts, NULL_TREE); + + /* Build a catch block: we need a catch clause parameter */ + catch_clause_param = build_decl (VAR_DECL, + wpv_id, build_pointer_type (type)); + /* And a block */ + catch_block = build_expr_block (NULL_TREE, catch_clause_param); + + /* Initialize the variable and store in the block */ + catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param, + build (JAVA_EXC_OBJ_EXPR, ptr_type_node)); + add_stmt_to_block (catch_block, NULL_TREE, catch); + + /* Add the catch statements */ + add_stmt_to_block (catch_block, NULL_TREE, catch_stmts); + + /* Now we can build a CATCH_EXPR */ + catch_block = build1 (CATCH_EXPR, NULL_TREE, catch_block); + + return build_try_statement (location, try_block, catch_block); +} + static tree build_try_statement (location, try_block, catches) int location; @@ -15468,12 +15546,13 @@ patch_throw_statement (node, wfl_op1) unchecked_ok = IS_UNCHECKED_EXCEPTION_P (TREE_TYPE (type)); SET_WFL_OPERATOR (wfl_operator, node, wfl_op1); - /* An instance can't throw a checked excetion unless that exception + /* An instance can't throw a checked exception unless that exception is explicitely declared in the `throws' clause of each constructor. This doesn't apply to anonymous classes, since they don't have declared constructors. */ if (!unchecked_ok - && in_instance_initializer && !ANONYMOUS_CLASS_P (current_class)) + && DECL_INSTINIT_P (current_function_decl) + && !ANONYMOUS_CLASS_P (current_class)) { tree current; for (current = TYPE_METHODS (current_class); current; @@ -15621,6 +15700,38 @@ purge_unchecked_exceptions (mdecl) DECL_FUNCTION_THROWS (mdecl) = new; } +/* This function goes over all of CLASS_TYPE ctors and checks whether + each of then features at least one unchecked exception in it + `throws' clause. If it's the case, it returns `true', `false' + otherwise. */ + +static bool +ctors_unchecked_throws_clause_p (class_type) + tree class_type; +{ + tree current; + + for (current = TYPE_METHODS (class_type); current; + current = TREE_CHAIN (current)) + { + bool ctu = false; /* Ctor Throws Unchecked */ + if (DECL_CONSTRUCTOR_P (current)) + { + tree throws; + for (throws = DECL_FUNCTION_THROWS (current); throws && !ctu; + throws = TREE_CHAIN (throws)) + if (inherits_from_p (TREE_VALUE (throws), exception_type_node)) + ctu = true; + } + /* We return false as we found one ctor that is unfit. */ + if (!ctu && DECL_CONSTRUCTOR_P (current)) + return false; + } + /* All ctors feature at least one unchecked exception in their + `throws' clause. */ + return true; +} + /* 15.24 Conditional Operator ?: */ static tree |