[multiple changes]

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 )

From-SVN: r44982
parent 0779eeb2
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> 2001-08-16 Tom Tromey <tromey@redhat.com>
* jcf-dump.c (main): Updated for change to jcf_path_seal. * jcf-dump.c (main): Updated for change to jcf_path_seal.
...@@ -13,6 +27,47 @@ ...@@ -13,6 +27,47 @@
* Make-lang.in (java/decl.o): Update dependencies. * Make-lang.in (java/decl.o): Update dependencies.
* decl.c: Include libfuncs.h, don't include toplev.h. * 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> 2001-08-12 David Edelsohn <edelsohn@gnu.org>
Revert: Revert:
...@@ -31,6 +86,11 @@ ...@@ -31,6 +86,11 @@
* lex.h: Don't include setjmp.h. Don't define * lex.h: Don't include setjmp.h. Don't define
SET_FLOAT_HANDLER or prototype set_float_handler. 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> 2001-08-09 Richard Henderson <rth@redhat.com>
* Make-lang.in (class.o): Depend on TARGET_H. * Make-lang.in (class.o): Depend on TARGET_H.
...@@ -390,7 +450,7 @@ ...@@ -390,7 +450,7 @@
2001-05-07 Alexandre Petit-Bianco <apbianco@redhat.com> 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 local. Moved assignment to `this$<n>', fixed comments and
indentation. indentation.
(build_wfl_wrap): Fixed indentation. (build_wfl_wrap): Fixed indentation.
...@@ -2912,7 +2972,7 @@ Sun Aug 6 00:47:24 2000 Ovidiu Predescu <ovidiu@cup.hp.com> ...@@ -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> 2000-06-25 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (do_resolve_class): Minor optimiztion in the package * 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 (valid_ref_assignconv_cast_p): Order of arguments to
enclosing_context_p fixed. enclosing_context_p fixed.
...@@ -3296,7 +3356,7 @@ Mon Apr 24 14:59:36 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> ...@@ -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> 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. (patch_method_invocation): Fixed comment.
2000-04-24 Robert Lipe <robertlipe@usa.net> 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> ...@@ -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 * parse.y (resolve_expression_name): Use `orig' as a second
argument to resolve_field_access. 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. static fields.
Wed Feb 23 17:41:50 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> 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> ...@@ -11650,7 +11710,7 @@ Thu Sep 11 19:45:18 1997 Alexandre Petit-Bianco <apbianco@cygnus.com>
layout. layout.
* typeck.c: (parse_signature_string): Temporary use permanent_obstack. * typeck.c: (parse_signature_string): Temporary use permanent_obstack.
(build_java_signature): 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. on ACC_SUPER flag.
* java-tree.h (METHOD_NATIVE, METHOD_TRANSIENT): Defined. * java-tree.h (METHOD_NATIVE, METHOD_TRANSIENT): Defined.
(FIELD_VOLATILE, FIELD_TRANSIENT): Defined. (FIELD_VOLATILE, FIELD_TRANSIENT): Defined.
......
...@@ -541,10 +541,16 @@ init_decl_processing () ...@@ -541,10 +541,16 @@ init_decl_processing ()
string_ptr_type_node = promote_type (string_type_node); string_ptr_type_node = promote_type (string_type_node);
class_type_node = lookup_class (get_identifier ("java.lang.Class")); class_type_node = lookup_class (get_identifier ("java.lang.Class"));
throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable")); throwable_type_node = lookup_class (get_identifier ("java.lang.Throwable"));
exception_type_node = lookup_class (get_identifier ("java.lang.Exception"));
runtime_exception_type_node = runtime_exception_type_node =
lookup_class (get_identifier ("java.lang.RuntimeException")); lookup_class (get_identifier ("java.lang.RuntimeException"));
error_exception_type_node = error_exception_type_node =
lookup_class (get_identifier ("java.lang.Error")); 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 rawdata_ptr_type_node
= promote_type (lookup_class (get_identifier ("gnu.gcj.RawData"))); = promote_type (lookup_class (get_identifier ("gnu.gcj.RawData")));
...@@ -557,6 +563,9 @@ init_decl_processing () ...@@ -557,6 +563,9 @@ init_decl_processing ()
predef_filenames [4] = get_identifier ("java/lang/String.java"); predef_filenames [4] = get_identifier ("java/lang/String.java");
predef_filenames [5] = get_identifier ("java/lang/Throwable.java"); predef_filenames [5] = get_identifier ("java/lang/Throwable.java");
predef_filenames [6] = get_identifier ("gnu/gcj/RawData.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); methodtable_type = make_node (RECORD_TYPE);
layout_type (methodtable_type); layout_type (methodtable_type);
...@@ -572,6 +581,7 @@ init_decl_processing () ...@@ -572,6 +581,7 @@ init_decl_processing ()
/* The new `finit$' special method identifier. This one is now /* The new `finit$' special method identifier. This one is now
generated in place of `$finit$'. */ generated in place of `$finit$'. */
finit_identifier_node = get_identifier ("finit$"); finit_identifier_node = get_identifier ("finit$");
instinit_identifier_node = get_identifier ("instinit$");
void_signature_node = get_identifier ("()V"); void_signature_node = get_identifier ("()V");
length_identifier_node = get_identifier ("length"); length_identifier_node = get_identifier ("length");
this_identifier_node = get_identifier ("this"); this_identifier_node = get_identifier ("this");
......
...@@ -2505,8 +2505,8 @@ java_lang_expand_expr (exp, target, tmode, modifier) ...@@ -2505,8 +2505,8 @@ java_lang_expand_expr (exp, target, tmode, modifier)
} }
expand_expr (body, const0_rtx, VOIDmode, 0); expand_expr (body, const0_rtx, VOIDmode, 0);
emit_queue (); emit_queue ();
poplevel (1, 1, 0);
expand_end_bindings (getdecls (), 1, 0); expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 1, 0);
return const0_rtx; return const0_rtx;
} }
return const0_rtx; return const0_rtx;
......
...@@ -88,12 +88,6 @@ DEFTREECODE (NEW_ARRAY_INIT, "new_array_init", '1', 1) ...@@ -88,12 +88,6 @@ DEFTREECODE (NEW_ARRAY_INIT, "new_array_init", '1', 1)
reference from. */ reference from. */
DEFTREECODE (CLASS_LITERAL, "class_literal", '1', 1) 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. */ /* The Java object within the exception object from the runtime. */
DEFTREECODE (JAVA_EXC_OBJ_EXPR, "java_exc_obj_expr", 'e', 0) DEFTREECODE (JAVA_EXC_OBJ_EXPR, "java_exc_obj_expr", 'e', 0)
......
...@@ -251,9 +251,12 @@ enum java_tree_index ...@@ -251,9 +251,12 @@ enum java_tree_index
JTI_STRING_TYPE_NODE, JTI_STRING_TYPE_NODE,
JTI_STRING_PTR_TYPE_NODE, JTI_STRING_PTR_TYPE_NODE,
JTI_THROWABLE_TYPE_NODE, JTI_THROWABLE_TYPE_NODE,
JTI_EXCEPTION_TYPE_NODE,
JTI_RUNTIME_EXCEPTION_TYPE_NODE, JTI_RUNTIME_EXCEPTION_TYPE_NODE,
JTI_ERROR_EXCEPTION_TYPE_NODE, JTI_ERROR_EXCEPTION_TYPE_NODE,
JTI_RAWDATA_PTR_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_BYTE_ARRAY_TYPE_NODE,
JTI_SHORT_ARRAY_TYPE_NODE, JTI_SHORT_ARRAY_TYPE_NODE,
...@@ -278,6 +281,7 @@ enum java_tree_index ...@@ -278,6 +281,7 @@ enum java_tree_index
JTI_INIT_IDENTIFIER_NODE, JTI_INIT_IDENTIFIER_NODE,
JTI_CLINIT_IDENTIFIER_NODE, JTI_CLINIT_IDENTIFIER_NODE,
JTI_FINIT_IDENTIFIER_NODE, JTI_FINIT_IDENTIFIER_NODE,
JTI_INSTINIT_IDENTIFIER_NODE,
JTI_FINIT_LEG_IDENTIFIER_NODE, JTI_FINIT_LEG_IDENTIFIER_NODE,
JTI_VOID_SIGNATURE_NODE, JTI_VOID_SIGNATURE_NODE,
JTI_LENGTH_IDENTIFIER_NODE, JTI_LENGTH_IDENTIFIER_NODE,
...@@ -408,12 +412,18 @@ extern tree java_global_trees[JTI_MAX]; ...@@ -408,12 +412,18 @@ extern tree java_global_trees[JTI_MAX];
java_global_trees[JTI_STRING_PTR_TYPE_NODE] java_global_trees[JTI_STRING_PTR_TYPE_NODE]
#define throwable_type_node \ #define throwable_type_node \
java_global_trees[JTI_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 \ #define runtime_exception_type_node \
java_global_trees[JTI_RUNTIME_EXCEPTION_TYPE_NODE] java_global_trees[JTI_RUNTIME_EXCEPTION_TYPE_NODE]
#define error_exception_type_node \ #define error_exception_type_node \
java_global_trees[JTI_ERROR_EXCEPTION_TYPE_NODE] java_global_trees[JTI_ERROR_EXCEPTION_TYPE_NODE]
#define rawdata_ptr_type_node \ #define rawdata_ptr_type_node \
java_global_trees[JTI_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 \ #define byte_array_type_node \
java_global_trees[JTI_BYTE_ARRAY_TYPE_NODE] java_global_trees[JTI_BYTE_ARRAY_TYPE_NODE]
...@@ -463,6 +473,8 @@ extern tree java_global_trees[JTI_MAX]; ...@@ -463,6 +473,8 @@ extern tree java_global_trees[JTI_MAX];
java_global_trees[JTI_FINIT_IDENTIFIER_NODE] /* "finit$" */ java_global_trees[JTI_FINIT_IDENTIFIER_NODE] /* "finit$" */
#define finit_leg_identifier_node \ #define finit_leg_identifier_node \
java_global_trees[JTI_FINIT_LEG_IDENTIFIER_NODE] /* "$finit$" */ 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 \ #define void_signature_node \
java_global_trees[JTI_VOID_SIGNATURE_NODE] /* "()V" */ java_global_trees[JTI_VOID_SIGNATURE_NODE] /* "()V" */
#define length_identifier_node \ #define length_identifier_node \
...@@ -598,7 +610,7 @@ extern tree java_global_trees[JTI_MAX]; ...@@ -598,7 +610,7 @@ extern tree java_global_trees[JTI_MAX];
#define nativecode_ptr_array_type_node \ #define nativecode_ptr_array_type_node \
java_global_trees[JTI_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]; extern tree predef_filenames[PREDEF_FILENAMES_SIZE];
#define nativecode_ptr_type_node ptr_type_node #define nativecode_ptr_type_node ptr_type_node
...@@ -937,7 +949,7 @@ struct lang_decl_var ...@@ -937,7 +949,7 @@ struct lang_decl_var
#define TYPE_PACKAGE_LIST(T) (TYPE_LANG_SPECIFIC(T)->package_list) #define TYPE_PACKAGE_LIST(T) (TYPE_LANG_SPECIFIC(T)->package_list)
#define TYPE_PRIVATE_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->pic) #define TYPE_PRIVATE_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->pic)
#define TYPE_PROTECTED_INNER_CLASS(T) (TYPE_LANG_SPECIFIC(T)->poic) #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 struct lang_type
{ {
...@@ -955,7 +967,7 @@ struct lang_type ...@@ -955,7 +967,7 @@ struct lang_type
tree package_list; /* List of package names, progressive */ tree package_list; /* List of package names, progressive */
unsigned pic:1; /* Private Inner Class. */ unsigned pic:1; /* Private Inner Class. */
unsigned poic:1; /* Protected Inner Class. */ unsigned poic:1; /* Protected Inner Class. */
unsigned afv:1; /* Has final variables */ unsigned hfv:1; /* Has final variables */
}; };
#ifdef JAVA_USE_HANDLES #ifdef JAVA_USE_HANDLES
...@@ -1197,6 +1209,7 @@ struct rtx_def * java_lang_expand_expr PARAMS ((tree, rtx, enum machine_mode, ...@@ -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_INIT_P(DECL) (ID_INIT_P (DECL_NAME (DECL)))
#define DECL_FINIT_P(DECL) (ID_FINIT_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_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 /* Predicates on method identifiers. Kept close to other macros using
them */ them */
...@@ -1209,6 +1222,7 @@ struct rtx_def * java_lang_expand_expr PARAMS ((tree, rtx, enum machine_mode, ...@@ -1209,6 +1222,7 @@ struct rtx_def * java_lang_expand_expr PARAMS ((tree, rtx, enum machine_mode,
|| (ID) == finit_leg_identifier_node) || (ID) == finit_leg_identifier_node)
#define ID_CLINIT_P(ID) ((ID) == clinit_identifier_node) #define ID_CLINIT_P(ID) ((ID) == clinit_identifier_node)
#define ID_CLASSDOLLAR_P(ID) ((ID) == classdollar_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): */ /* Access flags etc for a variable/field (a FIELD_DECL): */
......
...@@ -650,7 +650,8 @@ load_class (class_or_name, verbose) ...@@ -650,7 +650,8 @@ load_class (class_or_name, verbose)
tree class_or_name; tree class_or_name;
int verbose; int verbose;
{ {
tree name; tree name, saved;
int class_loaded;
/* class_or_name can be the name of the class we want to load */ /* class_or_name can be the name of the class we want to load */
if (TREE_CODE (class_or_name) == IDENTIFIER_NODE) if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
...@@ -663,8 +664,31 @@ load_class (class_or_name, verbose) ...@@ -663,8 +664,31 @@ load_class (class_or_name, verbose)
else else
name = DECL_NAME (TYPE_NAME (class_or_name)); name = DECL_NAME (TYPE_NAME (class_or_name));
if (read_class (name) == 0 && verbose) saved = name;
error ("Cannot find file for class %s.", IDENTIFIER_POINTER (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. */ /* Parse the .class file JCF. */
......
...@@ -2936,6 +2936,7 @@ generate_classfile (clas, state) ...@@ -2936,6 +2936,7 @@ generate_classfile (clas, state)
/* Make room for the Synthetic attribute (of zero length.) */ /* 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)) || OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part))
|| TYPE_DOT_CLASS (clas) == part) || TYPE_DOT_CLASS (clas) == part)
{ {
......
...@@ -221,6 +221,7 @@ static tree string_constant_concatenation PARAMS ((tree, tree)); ...@@ -221,6 +221,7 @@ static tree string_constant_concatenation PARAMS ((tree, tree));
static tree build_string_concatenation PARAMS ((tree, tree)); static tree build_string_concatenation PARAMS ((tree, tree));
static tree patch_string_cst PARAMS ((tree)); static tree patch_string_cst PARAMS ((tree));
static tree patch_string 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_statement PARAMS ((int, tree, tree));
static tree build_try_finally_statement PARAMS ((int, tree, tree)); static tree build_try_finally_statement PARAMS ((int, tree, tree));
static tree patch_try_statement PARAMS ((tree)); static tree patch_try_statement PARAMS ((tree));
...@@ -229,6 +230,7 @@ static tree patch_throw_statement PARAMS ((tree, tree)); ...@@ -229,6 +230,7 @@ static tree patch_throw_statement PARAMS ((tree, tree));
static void check_thrown_exceptions PARAMS ((int, tree)); static void check_thrown_exceptions PARAMS ((int, tree));
static int check_thrown_exceptions_do PARAMS ((tree)); static int check_thrown_exceptions_do PARAMS ((tree));
static void purge_unchecked_exceptions 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 check_throws_clauses PARAMS ((tree, tree, tree));
static void finish_method_declaration PARAMS ((tree)); static void finish_method_declaration PARAMS ((tree));
static tree build_super_invocation PARAMS ((tree)); static tree build_super_invocation PARAMS ((tree));
...@@ -239,8 +241,8 @@ static tree build_this_super_qualified_invocation PARAMS ((int, tree, 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 const char *get_printable_method_name PARAMS ((tree));
static tree patch_conditional_expr PARAMS ((tree, tree, tree)); static tree patch_conditional_expr PARAMS ((tree, tree, tree));
static tree generate_finit PARAMS ((tree)); static tree generate_finit PARAMS ((tree));
static void add_instance_initializer PARAMS ((tree)); static tree generate_instinit PARAMS ((tree));
static tree build_instance_initializer PARAMS ((tree)); static tree build_instinit_invocation PARAMS ((tree));
static void fix_constructors PARAMS ((tree)); static void fix_constructors PARAMS ((tree));
static tree build_alias_initializer_parameter_list PARAMS ((int, tree, static tree build_alias_initializer_parameter_list PARAMS ((int, tree,
tree, int *)); tree, int *));
...@@ -300,6 +302,8 @@ static tree maybe_make_nested_class_name PARAMS ((tree)); ...@@ -300,6 +302,8 @@ static tree maybe_make_nested_class_name PARAMS ((tree));
static void 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 set_nested_class_simple_name_value PARAMS ((tree, int));
static void link_nested_class_to_enclosing PARAMS ((void)); 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 PARAMS ((tree, tree, tree));
static tree find_as_inner_class_do PARAMS ((tree, tree)); static tree find_as_inner_class_do PARAMS ((tree, tree));
static int check_inner_class_redefinition PARAMS ((tree, tree)); static int check_inner_class_redefinition PARAMS ((tree, tree));
...@@ -349,9 +353,6 @@ int do_not_fold; ...@@ -349,9 +353,6 @@ int do_not_fold;
/* Cyclic inheritance report, as it can be set by layout_class */ /* Cyclic inheritance report, as it can be set by layout_class */
const char *cyclic_inheritance_report; const char *cyclic_inheritance_report;
/* Tell when we're within an instance initializer */
static int in_instance_initializer;
/* The current parser context */ /* The current parser context */
struct parser_ctxt *ctxp; struct parser_ctxt *ctxp;
...@@ -3528,6 +3529,74 @@ check_inner_class_redefinition (raw_name, cl) ...@@ -3528,6 +3529,74 @@ check_inner_class_redefinition (raw_name, cl)
return 0; 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 static tree
find_as_inner_class (enclosing, name, cl) find_as_inner_class (enclosing, name, cl)
tree enclosing, name, cl; tree enclosing, name, cl;
...@@ -4363,29 +4432,71 @@ generate_finit (class_type) ...@@ -4363,29 +4432,71 @@ generate_finit (class_type)
return mdecl; 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 static tree
build_instance_initializer (mdecl) generate_instinit (class_type)
tree mdecl; tree class_type;
{ {
tree compound = NULL_TREE;
tree stmt_list = TYPE_II_STMT_LIST (DECL_CONTEXT (mdecl));
tree current; 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);
for (current = stmt_list; current; current = TREE_CHAIN (current)) layout_class_method (class_type, CLASSTYPE_SUPER (class_type),
mdecl, NULL_TREE);
/* 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); 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 /* FIXME */
add_instance_initializer (mdecl) static tree
tree mdecl; build_instinit_invocation (class_type)
tree class_type;
{ {
tree compound = build_instance_initializer (mdecl); tree to_return = NULL_TREE;
if (compound) if (TYPE_II_STMT_LIST (class_type))
java_method_add_stmt (mdecl, build1 (INSTANCE_INITIALIZERS_EXPR, {
NULL_TREE, compound)); 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 /* Shared accros method_declarator and method_header to remember the
...@@ -5095,7 +5206,7 @@ register_incomplete_type (kind, wfl, decl, ptr) ...@@ -5095,7 +5206,7 @@ register_incomplete_type (kind, wfl, decl, ptr)
/* For some dependencies, set the enclosing class of the current /* For some dependencies, set the enclosing class of the current
class to be the enclosing context */ class to be the enclosing context */
if ((kind == JDEP_SUPER || kind == JDEP_INTERFACE if ((kind == JDEP_SUPER || kind == JDEP_INTERFACE
|| kind == JDEP_ANONYMOUS || kind == JDEP_FIELD) || kind == JDEP_ANONYMOUS)
&& GET_ENCLOSING_CPC ()) && GET_ENCLOSING_CPC ())
JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ()); JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ());
else else
...@@ -5574,7 +5685,7 @@ tree ...@@ -5574,7 +5685,7 @@ tree
do_resolve_class (enclosing, class_type, decl, cl) do_resolve_class (enclosing, class_type, decl, cl)
tree 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; struct hash_table _ht, *circularity_hash = &_ht;
/* This hash table is used to register the classes we're going /* This hash table is used to register the classes we're going
...@@ -5590,58 +5701,25 @@ do_resolve_class (enclosing, class_type, decl, cl) ...@@ -5590,58 +5701,25 @@ do_resolve_class (enclosing, class_type, decl, cl)
being loaded from class file. FIXME. */ being loaded from class file. FIXME. */
while (enclosing) while (enclosing)
{ {
tree intermediate; new_class_decl = resolve_inner_class (circularity_hash, cl, &enclosing,
&super, class_type);
hash_lookup (circularity_hash, if (new_class_decl)
(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; break;
if (TREE_CODE (super) == POINTER_TYPE) /* If we haven't found anything because SUPER reached Object and
super = do_resolve_class (NULL, super, NULL, NULL); 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 else
super = TYPE_NAME (super); enclosing = NULL_TREE;
/* 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;
} }
hash_table_free (circularity_hash); hash_table_free (circularity_hash);
if (new_class_decl)
return new_class_decl;
/* 1- Check for the type in single imports. This will change /* 1- Check for the type in single imports. This will change
TYPE_NAME() if something relevant is found */ TYPE_NAME() if something relevant is found */
find_in_imports (class_type); find_in_imports (class_type);
...@@ -5920,8 +5998,9 @@ check_method_redefinition (class, method) ...@@ -5920,8 +5998,9 @@ check_method_redefinition (class, method)
{ {
tree redef, sig; tree redef, sig;
/* There's no need to verify <clinit> and finit$ */ /* There's no need to verify <clinit> and finit$ and instinit$ */
if (DECL_CLINIT_P (method) || DECL_FINIT_P (method)) if (DECL_CLINIT_P (method)
|| DECL_FINIT_P (method) || DECL_INSTINIT_P (method))
return 0; return 0;
sig = TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (method)); sig = TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (method));
...@@ -7460,7 +7539,7 @@ static void ...@@ -7460,7 +7539,7 @@ static void
java_complete_expand_methods (class_decl) java_complete_expand_methods (class_decl)
tree class_decl; tree class_decl;
{ {
tree clinit, finit, decl, first_decl; tree clinit, decl, first_decl;
current_class = TREE_TYPE (class_decl); current_class = TREE_TYPE (class_decl);
...@@ -7482,13 +7561,15 @@ java_complete_expand_methods (class_decl) ...@@ -7482,13 +7561,15 @@ java_complete_expand_methods (class_decl)
first_decl = TYPE_METHODS (current_class); first_decl = TYPE_METHODS (current_class);
clinit = maybe_generate_pre_expand_clinit (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.*/ try to use it.*/
if (TYPE_FINIT_STMT_LIST (current_class)) if (TYPE_FINIT_STMT_LIST (current_class))
{ java_complete_expand_method (generate_finit (current_class));
finit = generate_finit (current_class);
java_complete_expand_method (finit); /* 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 */ /* Now do the constructors */
for (decl = first_decl ; !java_error_count && decl; decl = TREE_CHAIN (decl)) for (decl = first_decl ; !java_error_count && decl; decl = TREE_CHAIN (decl))
...@@ -8498,9 +8579,7 @@ build_dot_class_method (class) ...@@ -8498,9 +8579,7 @@ build_dot_class_method (class)
#define BWF(S) build_wfl_node (get_identifier ((S))) #define BWF(S) build_wfl_node (get_identifier ((S)))
#define MQN(X,Y) make_qualified_name ((X), (Y), 0) #define MQN(X,Y) make_qualified_name ((X), (Y), 0)
tree args, tmp, saved_current_function_decl, mdecl; tree args, tmp, saved_current_function_decl, mdecl;
tree stmt, throw_stmt, catch, catch_block, try_block; tree stmt, throw_stmt;
tree catch_clause_param;
tree class_not_found_exception, no_class_def_found_error;
static tree get_message_wfl, type_parm_wfl; static tree get_message_wfl, type_parm_wfl;
...@@ -8520,33 +8599,24 @@ build_dot_class_method (class) ...@@ -8520,33 +8599,24 @@ build_dot_class_method (class)
/* Build the qualified name java.lang.Class.forName */ /* Build the qualified name java.lang.Class.forName */
tmp = MQN (MQN (MQN (BWF ("java"), tmp = MQN (MQN (MQN (BWF ("java"),
BWF ("lang")), BWF ("Class")), BWF ("forName")); BWF ("lang")), BWF ("Class")), BWF ("forName"));
load_class (class_not_found_type_node, 1);
/* For things we have to catch and throw */ load_class (no_class_def_found_type_node, 1);
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);
/* Create the "class$" function */ /* Create the "class$" function */
mdecl = create_artificial_method (class, ACC_STATIC, mdecl = create_artificial_method (class, ACC_STATIC,
build_pointer_type (class_type_node), build_pointer_type (class_type_node),
classdollar_identifier_node, args); classdollar_identifier_node, args);
DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE, DECL_FUNCTION_THROWS (mdecl) =
no_class_def_found_error); build_tree_list (NULL_TREE, no_class_def_found_type_node);
/* We start by building the try block. We need to build: /* We start by building the try block. We need to build:
return (java.lang.Class.forName (type)); */ return (java.lang.Class.forName (type)); */
stmt = build_method_invocation (tmp, stmt = build_method_invocation (tmp,
build_tree_list (NULL_TREE, type_parm_wfl)); build_tree_list (NULL_TREE, type_parm_wfl));
stmt = build_return (0, stmt); 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 /* Now onto the catch block. We start by building the expression
throwing a new exception: throwing a new exception: throw new NoClassDefFoundError (_.getMessage) */
throw new NoClassDefFoundError (_.getMessage); */
throw_stmt = make_qualified_name (build_wfl_node (wpv_id), throw_stmt = make_qualified_name (build_wfl_node (wpv_id),
get_message_wfl, 0); get_message_wfl, 0);
throw_stmt = build_method_invocation (throw_stmt, NULL_TREE); throw_stmt = build_method_invocation (throw_stmt, NULL_TREE);
...@@ -8559,27 +8629,9 @@ build_dot_class_method (class) ...@@ -8559,27 +8629,9 @@ build_dot_class_method (class)
/* Build the throw, (it's too early to use BUILD_THROW) */ /* Build the throw, (it's too early to use BUILD_THROW) */
throw_stmt = build1 (THROW_EXPR, NULL_TREE, throw_stmt); throw_stmt = build1 (THROW_EXPR, NULL_TREE, throw_stmt);
/* Build the catch block to encapsulate all this. We begin by /* Encapsulate STMT in a try block. The catch clause executes THROW_STMT */
building an decl for the catch clause parameter and link it to stmt = encapsulate_with_try_catch (0, class_not_found_type_node,
newly created block, the catch block. */ stmt, throw_stmt);
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);
fix_method_argument_names (args, mdecl); fix_method_argument_names (args, mdecl);
layout_class_method (class, NULL_TREE, mdecl, NULL_TREE); layout_class_method (class, NULL_TREE, mdecl, NULL_TREE);
...@@ -8620,6 +8672,7 @@ static void ...@@ -8620,6 +8672,7 @@ static void
fix_constructors (mdecl) fix_constructors (mdecl)
tree mdecl; tree mdecl;
{ {
tree iii; /* Instance Initializer Invocation */
tree body = DECL_FUNCTION_BODY (mdecl); tree body = DECL_FUNCTION_BODY (mdecl);
tree thisn_assign, compound = NULL_TREE; tree thisn_assign, compound = NULL_TREE;
tree class_type = DECL_CONTEXT (mdecl); tree class_type = DECL_CONTEXT (mdecl);
...@@ -8661,9 +8714,9 @@ fix_constructors (mdecl) ...@@ -8661,9 +8714,9 @@ fix_constructors (mdecl)
of that. */ of that. */
java_method_add_stmt (mdecl, build_super_invocation (mdecl)); java_method_add_stmt (mdecl, build_super_invocation (mdecl));
/* Insert the instance initializer block right here, after the /* FIXME */
super invocation. */ if ((iii = build_instinit_invocation (class_type)))
add_instance_initializer (mdecl); java_method_add_stmt (mdecl, iii);
end_artificial_method_body (mdecl); end_artificial_method_body (mdecl);
} }
...@@ -8674,7 +8727,6 @@ fix_constructors (mdecl) ...@@ -8674,7 +8727,6 @@ fix_constructors (mdecl)
int invokes_this = 0; int invokes_this = 0;
tree found_call = NULL_TREE; tree found_call = NULL_TREE;
tree main_block = BLOCK_EXPR_BODY (body); tree main_block = BLOCK_EXPR_BODY (body);
tree ii; /* Instance Initializer */
while (body) while (body)
switch (TREE_CODE (body)) switch (TREE_CODE (body))
...@@ -8717,8 +8769,8 @@ fix_constructors (mdecl) ...@@ -8717,8 +8769,8 @@ fix_constructors (mdecl)
} }
/* Insert the instance initializer block right after. */ /* Insert the instance initializer block right after. */
if (!invokes_this && (ii = build_instance_initializer (mdecl))) if (!invokes_this && (iii = build_instinit_invocation (class_type)))
compound = add_stmt_to_compound (compound, NULL_TREE, ii); compound = add_stmt_to_compound (compound, NULL_TREE, iii);
/* Fix the constructor main block if we're adding extra stmts */ /* Fix the constructor main block if we're adding extra stmts */
if (compound) if (compound)
...@@ -10285,6 +10337,8 @@ patch_method_invocation (patch, primary, where, from_super, ...@@ -10285,6 +10337,8 @@ patch_method_invocation (patch, primary, where, from_super,
if (ret_decl) if (ret_decl)
*ret_decl = list; *ret_decl = list;
patch = patch_invoke (patch, list, args); 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)) if (is_super_init && CLASS_HAS_FINIT_P (current_class))
{ {
tree finit_parms, finit_call; tree finit_parms, finit_call;
...@@ -10346,7 +10400,8 @@ maybe_use_access_method (is_super_init, mdecl, this_arg) ...@@ -10346,7 +10400,8 @@ maybe_use_access_method (is_super_init, mdecl, this_arg)
if (is_super_init if (is_super_init
|| DECL_CONTEXT (md) == current_class || DECL_CONTEXT (md) == current_class
|| !PURE_INNER_CLASS_TYPE_P (current_class) || !PURE_INNER_CLASS_TYPE_P (current_class)
|| DECL_FINIT_P (md)) || DECL_FINIT_P (md)
|| DECL_INSTINIT_P (md))
return 0; return 0;
/* If we're calling a method found in an enclosing class, generate /* 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) ...@@ -10717,10 +10772,10 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
search_applicable_methods_list (lc, TYPE_METHODS (class), search_applicable_methods_list (lc, TYPE_METHODS (class),
name, arglist, &list, &all_list); name, arglist, &list, &all_list);
/* When looking finit$ or class$, we turn LC to 1 so that we /* When looking finit$, class$ or instinit$, we turn LC to 1 so
only search in class. Note that we should have found that we only search in class. Note that we should have found
something at this point. */ 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; lc = 1;
if (!list) if (!list)
...@@ -12001,16 +12056,6 @@ java_complete_lhs (node) ...@@ -12001,16 +12056,6 @@ java_complete_lhs (node)
return error_mark_node; return error_mark_node;
break; 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: default:
CAN_COMPLETE_NORMALLY (node) = 1; CAN_COMPLETE_NORMALLY (node) = 1;
/* Ok: may be we have a STRING_CST or a crafted `StringBuffer' /* Ok: may be we have a STRING_CST or a crafted `StringBuffer'
...@@ -14709,12 +14754,12 @@ patch_return (node) ...@@ -14709,12 +14754,12 @@ patch_return (node)
if (!return_exp && (mtype != void_type_node && !DECL_CONSTRUCTOR_P (meth))) if (!return_exp && (mtype != void_type_node && !DECL_CONSTRUCTOR_P (meth)))
error_found = 2; error_found = 2;
if (in_instance_initializer) if (DECL_INSTINIT_P (current_function_decl))
error_found = 1; error_found = 1;
if (error_found) if (error_found)
{ {
if (in_instance_initializer) if (DECL_INSTINIT_P (current_function_decl))
parse_error_context (wfl_operator, parse_error_context (wfl_operator,
"`return' inside instance initializer"); "`return' inside instance initializer");
...@@ -15234,6 +15279,39 @@ patch_switch_statement (node) ...@@ -15234,6 +15279,39 @@ patch_switch_statement (node)
/* 14.18 The try/catch statements */ /* 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 static tree
build_try_statement (location, try_block, catches) build_try_statement (location, try_block, catches)
int location; int location;
...@@ -15468,12 +15546,13 @@ patch_throw_statement (node, wfl_op1) ...@@ -15468,12 +15546,13 @@ patch_throw_statement (node, wfl_op1)
unchecked_ok = IS_UNCHECKED_EXCEPTION_P (TREE_TYPE (type)); unchecked_ok = IS_UNCHECKED_EXCEPTION_P (TREE_TYPE (type));
SET_WFL_OPERATOR (wfl_operator, node, wfl_op1); 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 is explicitely declared in the `throws' clause of each
constructor. This doesn't apply to anonymous classes, since they constructor. This doesn't apply to anonymous classes, since they
don't have declared constructors. */ don't have declared constructors. */
if (!unchecked_ok if (!unchecked_ok
&& in_instance_initializer && !ANONYMOUS_CLASS_P (current_class)) && DECL_INSTINIT_P (current_function_decl)
&& !ANONYMOUS_CLASS_P (current_class))
{ {
tree current; tree current;
for (current = TYPE_METHODS (current_class); current; for (current = TYPE_METHODS (current_class); current;
...@@ -15621,6 +15700,38 @@ purge_unchecked_exceptions (mdecl) ...@@ -15621,6 +15700,38 @@ purge_unchecked_exceptions (mdecl)
DECL_FUNCTION_THROWS (mdecl) = new; 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 ?: */ /* 15.24 Conditional Operator ?: */
static tree static tree
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment