OSDN Git Service

Merge from pch-branch up to tag pch-commit-20020603.
[pf3gnuchains/gcc-fork.git] / gcc / java / parse.y
index 9985c73..960bd90 100644 (file)
@@ -1,6 +1,6 @@
 /* Source code parsing and tree node generation for the GNU compiler
    for the Java(TM) language.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
 
 This file is part of GNU CC.
@@ -51,6 +51,7 @@ definitions and other extensions.  */
 #include <dirent.h>
 #include "tree.h"
 #include "rtl.h"
+#include "real.h"
 #include "obstack.h"
 #include "toplev.h"
 #include "flags.h"
@@ -65,6 +66,7 @@ definitions and other extensions.  */
 #include "function.h"
 #include "except.h"
 #include "ggc.h"
+#include "debug.h"
 
 #ifndef DIR_SEPARATOR
 #define DIR_SEPARATOR '/'
@@ -99,21 +101,15 @@ static tree parse_jdk1_1_error PARAMS ((const char *));
 static void complete_class_report_errors PARAMS ((jdep *));
 static int process_imports PARAMS ((void));
 static void read_import_dir PARAMS ((tree));
-static int find_in_imports_on_demand PARAMS ((tree));
-static void find_in_imports PARAMS ((tree));
-static void check_static_final_variable_assignment_flag PARAMS ((tree));
-static void reset_static_final_variable_assignment_flag PARAMS ((tree));
-static void check_final_variable_local_assignment_flag PARAMS ((tree, tree));
-static void reset_final_variable_local_assignment_flag PARAMS ((tree));
-static int  check_final_variable_indirect_assignment PARAMS ((tree));
-static void check_final_variable_global_assignment_flag PARAMS ((tree));
+static int find_in_imports_on_demand PARAMS ((tree, tree));
+static void find_in_imports PARAMS ((tree, tree));
 static void check_inner_class_access PARAMS ((tree, tree, tree));
-static int check_pkg_class_access PARAMS ((tree, tree));
+static int check_pkg_class_access PARAMS ((tree, tree, bool));
 static void register_package PARAMS ((tree));
-static tree resolve_package PARAMS ((tree, tree *));
-static tree lookup_package_type PARAMS ((const char *, int));
+static tree resolve_package PARAMS ((tree, tree *, tree *));
 static tree resolve_class PARAMS ((tree, tree, tree, tree));
 static void declare_local_variables PARAMS ((int, tree, tree));
+static void dump_java_tree PARAMS ((enum tree_dump_index, tree));
 static void source_start_java_method PARAMS ((tree));
 static void source_end_java_method PARAMS ((void));
 static tree find_name_in_single_imports PARAMS ((tree));
@@ -141,13 +137,17 @@ static tree patch_invoke PARAMS ((tree, tree, tree));
 static int maybe_use_access_method PARAMS ((int, tree *, tree *));
 static tree lookup_method_invoke PARAMS ((int, tree, tree, tree, tree));
 static tree register_incomplete_type PARAMS ((int, tree, tree, tree));
+static tree check_inner_circular_reference PARAMS ((tree, tree));
+static tree check_circular_reference PARAMS ((tree));
 static tree obtain_incomplete_type PARAMS ((tree));
 static tree java_complete_lhs PARAMS ((tree));
 static tree java_complete_tree PARAMS ((tree));
 static tree maybe_generate_pre_expand_clinit PARAMS ((tree));
-static int analyze_clinit_body PARAMS ((tree));
+static int analyze_clinit_body PARAMS ((tree, tree));
 static int maybe_yank_clinit PARAMS ((tree));
+static void start_complete_expand_method PARAMS ((tree));
 static void java_complete_expand_method PARAMS ((tree));
+static void java_expand_method_bodies PARAMS ((tree));
 static int  unresolved_type_p PARAMS ((tree, tree *));
 static void create_jdep_list PARAMS ((struct parser_ctxt *));
 static tree build_expr_block PARAMS ((tree, tree));
@@ -159,8 +159,7 @@ static tree build_method_invocation PARAMS ((tree, tree));
 static tree build_new_invocation PARAMS ((tree, tree));
 static tree build_assignment PARAMS ((int, int, tree, tree));
 static tree build_binop PARAMS ((enum tree_code, int, tree, tree));
-static int check_final_assignment PARAMS ((tree ,tree));
-static tree patch_assignment PARAMS ((tree, tree, tree ));
+static tree patch_assignment PARAMS ((tree, tree));
 static tree patch_binop PARAMS ((tree, tree, tree));
 static tree build_unaryop PARAMS ((int, int, tree));
 static tree build_incdec PARAMS ((int, int, tree, int));
@@ -175,6 +174,7 @@ static int valid_method_invocation_conversion_p PARAMS ((tree, tree));
 static tree try_builtin_assignconv PARAMS ((tree, tree, tree));
 static tree try_reference_assignconv PARAMS ((tree, tree));
 static tree build_unresolved_array_type PARAMS ((tree));
+static int build_type_name_from_array_name PARAMS ((tree, tree *));
 static tree build_array_from_name PARAMS ((tree, tree, tree, tree *));
 static tree build_array_ref PARAMS ((int, tree, tree));
 static tree patch_array_ref PARAMS ((tree));
@@ -219,6 +219,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));
@@ -227,6 +228,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));
@@ -237,12 +239,12 @@ 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 *));
-static void craft_constructor PARAMS ((tree, tree));
+static tree craft_constructor PARAMS ((tree, tree));
 static int verify_constructor_super PARAMS ((tree));
 static tree create_artificial_method PARAMS ((tree, int, tree, tree, tree));
 static void start_artificial_method_body PARAMS ((tree));
@@ -251,7 +253,6 @@ static int check_method_redefinition PARAMS ((tree, tree));
 static int check_method_types_complete PARAMS ((tree));
 static void java_check_regular_methods PARAMS ((tree));
 static void java_check_abstract_methods PARAMS ((tree));
-static tree maybe_build_primttype_type_ref PARAMS ((tree, tree));
 static void unreachable_stmt_error PARAMS ((tree));
 static tree find_expr_with_wfl PARAMS ((tree));
 static void missing_return_error PARAMS ((tree));
@@ -295,9 +296,10 @@ static int pop_current_osb PARAMS ((struct parser_ctxt *));
 /* JDK 1.1 work. FIXME */
 
 static tree maybe_make_nested_class_name PARAMS ((tree));
-static void make_nested_class_name PARAMS ((tree));
+static int 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 ((htab_t, 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));
@@ -332,6 +334,11 @@ static void create_new_parser_context PARAMS ((int));
 static void mark_parser_ctxt PARAMS ((void *));
 static tree maybe_build_class_init_for_field PARAMS ((tree, tree));
 
+static int attach_init_test_initialization_flags PARAMS ((PTR *, PTR));
+static int emit_test_initialization PARAMS ((PTR *, PTR));
+
+static char *string_convert_int_cst PARAMS ((tree));
+
 /* Number of error found so far. */
 int java_error_count; 
 /* Number of warning found so far. */
@@ -341,9 +348,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;
 
@@ -355,7 +359,7 @@ struct parser_ctxt *ctxp_for_generation = NULL;
    covers both integral/floating point division. The code is changed
    once the type of both operator is worked out.  */
 
-static enum tree_code binop_lookup[19] = 
+static const enum tree_code binop_lookup[19] = 
   { 
     PLUS_EXPR, MINUS_EXPR, MULT_EXPR, RDIV_EXPR, TRUNC_MOD_EXPR,
     LSHIFT_EXPR, RSHIFT_EXPR, URSHIFT_EXPR, 
@@ -371,47 +375,58 @@ static enum tree_code binop_lookup[19] =
 #define BINOP_COMPOUND_CANDIDATES 11
 
 /* The "$L" identifier we use to create labels.  */
-static tree label_id = NULL_TREE;
+static GTY(()) tree label_id;
 
 /* The "StringBuffer" identifier used for the String `+' operator. */
-static tree wfl_string_buffer = NULL_TREE
+static GTY(()) tree wfl_string_buffer
 
 /* The "append" identifier used for String `+' operator.  */
-static tree wfl_append = NULL_TREE;
+static GTY(()) tree wfl_append;
 
 /* The "toString" identifier used for String `+' operator. */
-static tree wfl_to_string = NULL_TREE;
+static GTY(()) tree wfl_to_string;
 
 /* The "java.lang" import qualified name.  */
-static tree java_lang_id = NULL_TREE;
+static GTY(()) tree java_lang_id;
 
 /* The generated `inst$' identifier used for generated enclosing
    instance/field access functions.  */
-static tree inst_id = NULL_TREE;
+static GTY(()) tree inst_id;
 
 /* The "java.lang.Cloneable" qualified name.  */
-static tree java_lang_cloneable = NULL_TREE;
+static GTY(()) tree java_lang_cloneable;
 
 /* The "java.io.Serializable" qualified name.  */
-static tree java_io_serializable = NULL_TREE
+static GTY(()) tree java_io_serializable
 
 /* Context and flag for static blocks */
-static tree current_static_block = NULL_TREE;
+static GTY(()) tree current_static_block;
 
 /* The generated `write_parm_value$' identifier.  */
-static tree wpv_id;
+static GTY(()) tree wpv_id;
 
 /* The list of all packages we've seen so far */
-static tree package_list = NULL_TREE;
+static GTY(()) tree package_list;
  
-/* Hold THIS for the scope of the current public method decl.  */
-static tree current_this;
+/* Hold THIS for the scope of the current method decl.  */
+static GTY(()) tree current_this;
 
 /* Hold a list of catch clauses list. The first element of this list is
    the list of the catch clauses of the currently analysed try block. */
-static tree currently_caught_type_list;
+static GTY(()) tree currently_caught_type_list;
+
+/* This holds a linked list of all the case labels for the current
+   switch statement.  It is only used when checking to see if there
+   are duplicate labels.  FIXME: probably this should just be attached
+   to the switch itself; then it could be referenced via
+   `ctxp->current_loop'.  */
+static GTY(()) tree case_label_list; 
+
+/* Anonymous class counter. Will be reset to 1 every time a non
+   anonymous class gets created. */
+static int anonymous_class_counter = 1;
 
-static tree src_parse_roots[1] = { NULL_TREE };
+static GTY(()) tree src_parse_roots[1];
 
 /* All classes seen from source code */
 #define gclass_list src_parse_roots[0]
@@ -472,8 +487,8 @@ static tree src_parse_roots[1] = { NULL_TREE };
 %token   PUBLIC_TK       PRIVATE_TK         PROTECTED_TK
 %token   STATIC_TK       FINAL_TK           SYNCHRONIZED_TK
 %token   VOLATILE_TK     TRANSIENT_TK       NATIVE_TK
-%token   PAD_TK          ABSTRACT_TK        MODIFIER_TK
-%token   STRICT_TK
+%token   PAD_TK          ABSTRACT_TK        STRICT_TK
+%token   MODIFIER_TK
 
 /* Keep those two in order, too */
 %token   DECR_TK INCR_TK
@@ -559,7 +574,7 @@ static tree src_parse_roots[1] = { NULL_TREE };
                        switch_statement synchronized_statement throw_statement
                        try_statement switch_expression switch_block
                        catches catch_clause catch_clause_parameter finally
-                       anonymous_class_creation
+                       anonymous_class_creation trap_overflow_corner_case
 %type    <node>         return_statement break_statement continue_statement
 
 %type    <operator>     ASSIGN_TK      MULT_ASSIGN_TK  DIV_ASSIGN_TK  
@@ -598,19 +613,6 @@ goal:
                 {
                  /* Register static variables with the garbage
                     collector.  */
-                 ggc_add_tree_root (&label_id, 1);
-                 ggc_add_tree_root (&wfl_string_buffer, 1);
-                 ggc_add_tree_root (&wfl_append, 1);
-                 ggc_add_tree_root (&wfl_to_string, 1);
-                 ggc_add_tree_root (&java_lang_id, 1);
-                 ggc_add_tree_root (&inst_id, 1);
-                 ggc_add_tree_root (&java_lang_cloneable, 1);
-                 ggc_add_tree_root (&java_io_serializable, 1);
-                 ggc_add_tree_root (&current_static_block, 1);
-                 ggc_add_tree_root (&wpv_id, 1);
-                 ggc_add_tree_root (&package_list, 1);
-                 ggc_add_tree_root (&current_this, 1);
-                 ggc_add_tree_root (&currently_caught_type_list, 1);
                  ggc_add_root (&ctxp, 1, 
                                sizeof (struct parser_ctxt *),
                                mark_parser_ctxt);
@@ -781,8 +783,14 @@ type_import_on_demand_declaration:
        IMPORT_TK name DOT_TK MULT_TK SC_TK
                {
                  tree name = EXPR_WFL_NODE ($2);
-                 /* Don't import java.lang.* twice. */
-                 if (name != java_lang_id)
+                 tree it;
+                 /* Search for duplicates. */
+                 for (it = ctxp->import_demand_list; it; it = TREE_CHAIN (it))
+                   if (EXPR_WFL_NODE (TREE_PURPOSE (it)) == name)
+                     break;
+                 /* Don't import the same thing more than once, just ignore
+                    duplicates (7.5.2) */
+                 if (! it)
                    {
                      read_import_dir ($2);
                      ctxp->import_demand_list = 
@@ -918,8 +926,11 @@ class_body_declaration:
 |      constructor_declaration
 |      block                   /* Added, JDK1.1, instance initializer */
                {
-                 TREE_CHAIN ($1) = CPC_INSTANCE_INITIALIZER_STMT (ctxp);
-                 SET_CPC_INSTANCE_INITIALIZER_STMT (ctxp, $1);
+                 if ($1 != empty_stmt_node)
+                   {
+                     TREE_CHAIN ($1) = CPC_INSTANCE_INITIALIZER_STMT (ctxp);
+                     SET_CPC_INSTANCE_INITIALIZER_STMT (ctxp, $1);
+                   }
                }
 ;
 
@@ -1328,6 +1339,8 @@ abstract_method_declaration:
 array_initializer:
        OCB_TK CCB_TK
                { $$ = build_new_array_init ($1.location, NULL_TREE); }
+|      OCB_TK C_TK CCB_TK
+               { $$ = build_new_array_init ($1.location, NULL_TREE); }
 |      OCB_TK variable_initializers CCB_TK
                { $$ = build_new_array_init ($1.location, $2); }
 |      OCB_TK variable_initializers C_TK CCB_TK
@@ -1444,7 +1457,13 @@ statement_without_trailing_substatement:
 empty_statement:
        SC_TK
                { 
-                 if (flag_extraneous_semicolon)
+                 if (flag_extraneous_semicolon 
+                     && ! current_static_block 
+                     && (! current_function_decl || 
+                         /* Verify we're not in a inner class declaration */
+                         (GET_CPC () != TYPE_NAME
+                          (DECL_CONTEXT (current_function_decl)))))
+                          
                    {
                      EXPR_WFL_SET_LINECOL (wfl_operator, lineno, -1);
                      parse_warning_context (wfl_operator, "An empty declaration is a deprecated feature that should not be used");
@@ -1571,7 +1590,7 @@ switch_statement:
        switch_block
                { 
                  /* Make into "proper list" of COMPOUND_EXPRs.
-                    I.e. make the last statment also have its own
+                    I.e. make the last statement also have its own
                     COMPOUND_EXPR. */
                  maybe_absorb_scoping_blocks ();
                  TREE_OPERAND ($1, 1) = exit_block ();
@@ -1888,7 +1907,7 @@ catch_clause_parameter:
                  tree ccpb = enter_block ();
                  tree init = build_assignment
                    (ASSIGN_TK, $2.location, TREE_PURPOSE ($3), 
-                    build_exception_object_ref (ptr_type_node));
+                    build (JAVA_EXC_OBJ_EXPR, ptr_type_node));
                  declare_local_variables (0, TREE_VALUE ($3),
                                           build_tree_list (TREE_PURPOSE ($3),
                                                            init));
@@ -1954,9 +1973,12 @@ type_literals:
 |      array_type DOT_TK CLASS_TK
                { $$ = build_incomplete_class_ref ($2.location, $1); }
 |      primitive_type DOT_TK CLASS_TK
-               { $$ = build_class_ref ($1); }
+                { $$ = build_incomplete_class_ref ($2.location, $1); }
 |      VOID_TK DOT_TK CLASS_TK
-               { $$ = build_class_ref (void_type_node); }
+                { 
+                   $$ = build_incomplete_class_ref ($2.location,
+                                                   void_type_node);
+                }
 ;
 
 class_instance_creation_expression:
@@ -2090,7 +2112,8 @@ array_creation_expression:
                  char *sig;
                  int osb = pop_current_osb (ctxp);
                  while (osb--)
-                   obstack_1grow (&temporary_obstack, '[');
+                   obstack_grow (&temporary_obstack, "[]", 2);
+                 obstack_1grow (&temporary_obstack, '\0');
                  sig = obstack_finish (&temporary_obstack);
                  $$ = build (NEW_ANONYMOUS_ARRAY_EXPR, NULL_TREE,
                              $2, get_identifier (sig), $4);
@@ -2277,16 +2300,24 @@ post_decrement_expression:
                { $$ = build_incdec ($2.token, $2.location, $1, 1); }
 ;
 
-unary_expression:
+trap_overflow_corner_case:
        pre_increment_expression
 |      pre_decrement_expression
 |      PLUS_TK unary_expression
                {$$ = build_unaryop ($1.token, $1.location, $2); }
-|      MINUS_TK unary_expression
-               {$$ = build_unaryop ($1.token, $1.location, $2); }
 |      unary_expression_not_plus_minus
 |      PLUS_TK error
                {yyerror ("Missing term"); RECOVER}
+;
+
+unary_expression:
+       trap_overflow_corner_case
+               {
+                 error_if_numeric_overflow ($1);
+                 $$ = $1;
+               }
+|      MINUS_TK trap_overflow_corner_case
+               {$$ = build_unaryop ($1.token, $1.location, $2); }
 |      MINUS_TK error
                {yyerror ("Missing term"); RECOVER}
 ;
@@ -2335,11 +2366,12 @@ cast_expression:                /* Error handling here is potentially weak */
                { 
                  const char *ptr;
                  int osb = pop_current_osb (ctxp); 
+                 obstack_grow (&temporary_obstack, 
+                               IDENTIFIER_POINTER (EXPR_WFL_NODE ($2)),
+                               IDENTIFIER_LENGTH (EXPR_WFL_NODE ($2)));
                  while (osb--)
-                   obstack_1grow (&temporary_obstack, '[');
-                 obstack_grow0 (&temporary_obstack, 
-                                IDENTIFIER_POINTER (EXPR_WFL_NODE ($2)),
-                                IDENTIFIER_LENGTH (EXPR_WFL_NODE ($2)));
+                   obstack_grow (&temporary_obstack, "[]", 2);
+                 obstack_1grow (&temporary_obstack, '\0');
                  ptr = obstack_finish (&temporary_obstack);
                  EXPR_WFL_NODE ($2) = get_identifier (ptr);
                  $$ = build_cast ($1.location, $2, $5);
@@ -2743,7 +2775,7 @@ static void
 java_parser_context_suspend ()
 {
   /* This makes debugging through java_debug_context easier */
-  static const char *name = "<inner buffer context>";
+  static const char *const name = "<inner buffer context>";
 
   /* Duplicate the previous context, use it to save the globals we're
      interested in */
@@ -3054,19 +3086,11 @@ issue_warning_error_from_context (cl, msg, ap)
 void
 parse_error_context VPARAMS ((tree cl, const char *msg, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  tree cl;
-  const char *msg;
-#endif
-  va_list ap;
-
-  VA_START (ap, msg);
-#ifndef ANSI_PROTOTYPES
-  cl = va_arg (ap, tree);
-  msg = va_arg (ap, const char *);
-#endif
+  VA_OPEN (ap, msg);
+  VA_FIXEDARG (ap, tree, cl);
+  VA_FIXEDARG (ap, const char *, msg);
   issue_warning_error_from_context (cl, msg, ap);
-  va_end (ap);
+  VA_CLOSE (ap);
 }
 
 /* Issue a warning at a current source line CL */
@@ -3074,22 +3098,14 @@ parse_error_context VPARAMS ((tree cl, const char *msg, ...))
 static void
 parse_warning_context VPARAMS ((tree cl, const char *msg, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  tree cl;
-  const char *msg;
-#endif
-  va_list ap;
-
-  VA_START (ap, msg);
-#ifndef ANSI_PROTOTYPES
-  cl = va_arg (ap, tree);
-  msg = va_arg (ap, const char *);
-#endif
+  VA_OPEN (ap, msg);
+  VA_FIXEDARG (ap, tree, cl);
+  VA_FIXEDARG (ap, const char *, msg);
 
   force_error = do_warning = 1;
   issue_warning_error_from_context (cl, msg, ap);
   do_warning = force_error = 0;
-  va_end (ap);
+  VA_CLOSE (ap);
 }
 
 static tree
@@ -3239,25 +3255,42 @@ variable_redefinition_error (context, name, type, line)
                       type_name, IDENTIFIER_POINTER (name), line);
 }
 
+/* If ANAME is terminated with `[]', it indicates an array. This
+   function returns the number of `[]' found and if this number is
+   greater than zero, it extracts the array type name and places it in
+   the node pointed to by TRIMMED unless TRIMMED is null.  */
+
+static int
+build_type_name_from_array_name (aname, trimmed)
+     tree aname;
+     tree *trimmed;
+{
+  const char *name = IDENTIFIER_POINTER (aname);
+  int len = IDENTIFIER_LENGTH (aname);
+  int array_dims;
+
+  STRING_STRIP_BRACKETS (name, len, array_dims);
+
+  if (array_dims && trimmed)
+    *trimmed = get_identifier_with_length (name, len);
+
+  return array_dims;
+}
+
 static tree
 build_array_from_name (type, type_wfl, name, ret_name)
      tree type, type_wfl, name, *ret_name;
 {
   int more_dims = 0;
-  const char *string;
 
   /* Eventually get more dims */
-  string = IDENTIFIER_POINTER (name);
-  while (string [more_dims] == '[')
-    more_dims++;
+  more_dims = build_type_name_from_array_name (name, &name);
   
   /* If we have, then craft a new type for this variable */
   if (more_dims)
     {
       tree save = type;
 
-      name = get_identifier (&string [more_dims]);
-
       /* If we have a pointer, use its type */
       if (TREE_CODE (type) == POINTER_TYPE)
         type = TREE_TYPE (type);
@@ -3274,12 +3307,9 @@ build_array_from_name (type, type_wfl, name, ret_name)
          on adding dimensions) */
       else if (type_wfl)
        {
-         int i = 0;
          type = type_wfl;
-         string = IDENTIFIER_POINTER (TYPE_NAME (save));
-         while (string[i]  == '[')
-           ++i;
-         more_dims += i;
+         more_dims += build_type_name_from_array_name (TYPE_NAME (save),
+                                                       NULL);
        }
 
       /* Add all the dimensions */
@@ -3312,10 +3342,10 @@ build_unresolved_array_type (type_or_wfl)
   if (TREE_CODE (type_or_wfl) == RECORD_TYPE)
     return build_java_array_type (type_or_wfl, -1);
 
-  obstack_1grow (&temporary_obstack, '[');
-  obstack_grow0 (&temporary_obstack,
+  obstack_grow (&temporary_obstack,
                 IDENTIFIER_POINTER (EXPR_WFL_NODE (type_or_wfl)),
                 IDENTIFIER_LENGTH (EXPR_WFL_NODE (type_or_wfl)));
+  obstack_grow0 (&temporary_obstack, "[]", 2);
   ptr = obstack_finish (&temporary_obstack);
   wfl = build_expr_wfl (get_identifier (ptr),
                        EXPR_WFL_FILENAME (type_or_wfl),
@@ -3432,7 +3462,9 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d
       else
        {
          check_modifiers_consistency (flags);
-         icaf = ACC_PRIVATE|ACC_PROTECTED;
+         icaf = ACC_PROTECTED;
+         if (! CLASS_INTERFACE (GET_CPC ()))
+           icaf |= ACC_PRIVATE;
        }
     }
 
@@ -3454,30 +3486,28 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d
   return 0;
 }
 
-static void
+/* Construct a nested class name.  If the final component starts with
+   a digit, return true.  Otherwise return false.  */
+static int
 make_nested_class_name (cpc_list)
      tree cpc_list;
 {
   tree name;
 
   if (!cpc_list)
-    return;
-  else
-    make_nested_class_name (TREE_CHAIN (cpc_list));
+    return 0;
+
+  make_nested_class_name (TREE_CHAIN (cpc_list));
 
   /* Pick the qualified name when dealing with the first upmost
      enclosing class */
-  name = (TREE_CHAIN (cpc_list) ? 
-         TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
+  name = (TREE_CHAIN (cpc_list)
+         TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
   obstack_grow (&temporary_obstack,
                IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name));
-  /* Why is NO_DOLLAR_IN_LABEL defined? */
-#if 0
-#ifdef NO_DOLLAR_IN_LABEL
-  internal_error ("Can't use '$' as a separator for inner classes");
-#endif
-#endif
   obstack_1grow (&temporary_obstack, '$');
+
+  return ISDIGIT (IDENTIFIER_POINTER (name)[0]);
 }
 
 /* Can't redefine a class already defined in an earlier scope. */
@@ -3500,6 +3530,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)
+     htab_t circularity_hash;
+     tree cl, *enclosing, *super, class_type;
+{
+  tree local_enclosing = *enclosing;
+  tree local_super = NULL_TREE;
+
+  while (local_enclosing)
+    {
+      tree intermediate, decl;
+
+      *htab_find_slot (circularity_hash, local_enclosing, INSERT) =
+       local_enclosing;
+
+      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 (htab_find (circularity_hash, local_super) != 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;
+        }
+      else
+       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;
@@ -3533,18 +3631,7 @@ find_as_inner_class (enclosing, name, cl)
          acc = merge_qualified_name (acc, 
                                      EXPR_WFL_NODE (TREE_PURPOSE (qual)));
          BUILD_PTR_FROM_NAME (ptr, acc);
-
-         /* Don't try to resolve ACC as a class name if it follows
-            the current package name. We don't want to pick something
-            that's accidentally there: for example `a.b.c' in package
-            `a.b' shouldn't trigger loading `a' if it's there by
-            itself. */
-         if (ctxp->package
-             && strstr (IDENTIFIER_POINTER (ctxp->package),
-                        IDENTIFIER_POINTER (acc)))
-           decl = NULL;
-         else
-           decl = do_resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
+         decl = do_resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
        }
 
       /* A NULL qual and a decl means that the search ended
@@ -3558,7 +3645,7 @@ find_as_inner_class (enclosing, name, cl)
   /* Otherwise, create a qual for the other part of the resolution. */
   else
     qual = build_tree_list (build_expr_wfl (name, NULL, 0, 0), NULL_TREE);
-
+  
   return find_as_inner_class_do (qual, enclosing);
 }
 
@@ -3617,7 +3704,6 @@ link_nested_class_to_enclosing ()
       DECL_INNER_CLASS_LIST (enclosing) = 
        tree_cons (GET_CPC (), GET_CPC_UN (),
                   DECL_INNER_CLASS_LIST (enclosing));
-      enclosing = enclosing;
     }
 }
 
@@ -3629,7 +3715,20 @@ maybe_make_nested_class_name (name)
 
   if (CPC_INNER_P ())
     {
-      make_nested_class_name (GET_CPC_LIST ());
+      /* If we're in a function, we must append a number to create the
+        nested class name.  However, we don't do this if the class we
+        are constructing is anonymous, because in that case we'll
+        already have a number as the class name.  */
+      if (! make_nested_class_name (GET_CPC_LIST ())
+         && current_function_decl != NULL_TREE
+         && ! ISDIGIT (IDENTIFIER_POINTER (name)[0]))
+       {
+         char buf[10];
+         sprintf (buf, "%d", anonymous_class_counter);
+         ++anonymous_class_counter;
+         obstack_grow (&temporary_obstack, buf, strlen (buf));
+         obstack_1grow (&temporary_obstack, '$');
+       }
       obstack_grow0 (&temporary_obstack,
                     IDENTIFIER_POINTER (name), 
                     IDENTIFIER_LENGTH (name));
@@ -3720,6 +3819,11 @@ create_interface (flags, id, super)
   tree q_name = parser_qualified_classname (raw_name);
   tree decl = IDENTIFIER_CLASS_VALUE (q_name);
 
+  /* Certain syntax errors are making SUPER be like ID. Avoid this
+     case. */
+  if (ctxp->class_err && id == super)
+    super = NULL;
+
   EXPR_WFL_NODE (id) = q_name; /* Keep source location, even if refined. */
 
   /* Basic checks: scope, redefinition, modifiers */ 
@@ -3732,7 +3836,12 @@ create_interface (flags, id, super)
   /* Suspend the current parsing context if we're parsing an inner
      interface */
   if (CPC_INNER_P ())
-    java_parser_context_suspend ();
+    {
+      java_parser_context_suspend ();
+      /* Interface members are public. */
+      if (CLASS_INTERFACE (GET_CPC ()))
+       flags |= ACC_PUBLIC;
+    }
 
   /* Push a new context for (static) initialized upon declaration fields */
   java_parser_context_push_initialized_field ();
@@ -3744,7 +3853,7 @@ create_interface (flags, id, super)
   if ((flags & ACC_ABSTRACT) && flag_redundant)
     parse_warning_context 
       (MODIFIER_WFL (ABSTRACT_TK),
-       "Redundant use of `abstract' modifier. Interface `%s' is implicitely abstract", IDENTIFIER_POINTER (raw_name));
+       "Redundant use of `abstract' modifier. Interface `%s' is implicitly abstract", IDENTIFIER_POINTER (raw_name));
 
   /* Create a new decl if DECL is NULL, otherwise fix it */
   decl = maybe_create_class_interface_decl (decl, raw_name, q_name, id);
@@ -3759,10 +3868,6 @@ create_interface (flags, id, super)
   return decl;
 }
 
-/* Anonymous class counter. Will be reset to 1 every time a non
-   anonymous class gets created. */
-static int anonymous_class_counter = 1;
-
 /* Patch anonymous class CLASS, by either extending or implementing
    DEP.  */
 
@@ -3852,6 +3957,11 @@ create_class (flags, id, super, interfaces)
   tree class_id, decl;
   tree super_decl_type;
 
+  /* Certain syntax errors are making SUPER be like ID. Avoid this
+     case. */
+  if (ctxp->class_err && id == super)
+    super = NULL;
+
   class_id = parser_qualified_classname (raw_name);
   decl = IDENTIFIER_CLASS_VALUE (class_id);
   EXPR_WFL_NODE (id) = class_id;
@@ -3866,7 +3976,13 @@ create_class (flags, id, super, interfaces)
   /* Suspend the current parsing context if we're parsing an inner
      class or an anonymous class. */
   if (CPC_INNER_P ())
-    java_parser_context_suspend ();
+    {
+      java_parser_context_suspend ();
+      /* Interface members are public. */
+      if (CLASS_INTERFACE (GET_CPC ()))
+       flags |= ACC_PUBLIC;
+    }
+    
   /* Push a new context for (static) initialized upon declaration fields */
   java_parser_context_push_initialized_field ();
 
@@ -3944,13 +4060,16 @@ static void
 end_class_declaration (resume)
      int resume;
 {
-  /* If an error occured, context weren't pushed and won't need to be
+  /* If an error occurred, context weren't pushed and won't need to be
      popped by a resume. */
-  int no_error_occured = ctxp->next && GET_CPC () != error_mark_node;
+  int no_error_occurred = ctxp->next && GET_CPC () != error_mark_node;
+
+  if (GET_CPC () != error_mark_node)
+    dump_java_tree (TDI_class, GET_CPC ());
 
   java_parser_context_pop_initialized_field ();
   POP_CPC ();
-  if (resume && no_error_occured)
+  if (resume && no_error_occurred)
     java_parser_context_resume ();
 
   /* We're ending a class declaration, this is a good time to reset
@@ -4079,7 +4198,7 @@ lookup_field_wrapper (class, name)
   /* Last chance: if we're within the context of an inner class, we
      might be trying to access a local variable defined in an outer
      context. We try to look for it now. */
-  if (INNER_CLASS_TYPE_P (class))
+  if (INNER_CLASS_TYPE_P (class) && TREE_CODE (name) == IDENTIFIER_NODE)
     {
       tree new_name;
       MANGLE_OUTER_LOCAL_VARIABLE_NAME (new_name, name);
@@ -4093,6 +4212,13 @@ lookup_field_wrapper (class, name)
       decl = lookup_field (&type, name);
     }
 
+  /* If the field still hasn't been found, try the next enclosing context. */
+  if (!decl && INNER_CLASS_TYPE_P (class))
+    {
+      tree outer_type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
+      decl = lookup_field_wrapper (outer_type, name);
+    }
+
   java_parser_context_restore_global ();
   return decl == error_mark_node ? NULL : decl;
 }
@@ -4223,14 +4349,12 @@ register_fields (flags, type, variable_list)
       /* If the field denotes a final instance variable, then we
         allocate a LANG_DECL_SPECIFIC part to keep track of its
         initialization. We also mark whether the field was
-        initialized upon it's declaration. We don't do that if the
+        initialized upon its declaration. We don't do that if the
         created field is an alias to a final local. */
       if (!ARG_FINAL_P (current) && (flags & ACC_FINAL))
        {
          MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field_decl);
          DECL_FIELD_FINAL_WFL (field_decl) = cl;
-         if ((flags & ACC_STATIC) && init)
-           DECL_FIELD_FINAL_IUD (field_decl) = 1;
        }
 
       /* If the couple initializer/initialized is marked ARG_FINAL_P,
@@ -4284,7 +4408,7 @@ register_fields (flags, type, variable_list)
 /* Generate finit$, using the list of initialized fields to populate
    its body. finit$'s parameter(s) list is adjusted to include the
    one(s) used to initialized the field(s) caching outer context
-   local(s). */
+   local(s).  */
 
 static tree
 generate_finit (class_type)
@@ -4314,29 +4438,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
@@ -4387,7 +4553,8 @@ method_header (flags, type, mdecl, throws)
       ABSTRACT_CHECK (flags, ACC_STATIC, id, "Static");
       ABSTRACT_CHECK (flags, ACC_FINAL, id, "Final");
       ABSTRACT_CHECK (flags, ACC_NATIVE, id, "Native");
-      ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED,id, "Synchronized");
+      ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED, id, "Synchronized");
+      ABSTRACT_CHECK (flags, ACC_STRICT, id, "Strictfp");
       if (!CLASS_ABSTRACT (TYPE_NAME (this_class))
          && !CLASS_INTERFACE (TYPE_NAME (this_class)))
        parse_error_context 
@@ -4413,6 +4580,7 @@ method_header (flags, type, mdecl, throws)
          JCONSTRUCTOR_CHECK (flags, ACC_FINAL, id, "final");
          JCONSTRUCTOR_CHECK (flags, ACC_NATIVE, id, "native");
          JCONSTRUCTOR_CHECK (flags, ACC_SYNCHRONIZED, id, "synchronized");
+         JCONSTRUCTOR_CHECK (flags, ACC_STRICT, id, "strictfp");
        }
       /* If we found error here, we don't consider it's OK to tread
         the method definition as a constructor, for the rest of this
@@ -4656,32 +4824,23 @@ constructor_circularity_msg (from, to)
 /* Verify a circular call to METH. Return 1 if an error is found, 0
    otherwise.  */
 
+static GTY(()) tree vcc_list;
 static int
 verify_constructor_circularity (meth, current)
      tree meth, current;
 {
-  static tree list = NULL_TREE;
-  static int initialized_p;
   tree c;
 
-  /* If we haven't already registered LIST with the garbage collector,
-     do so now.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&list, 1);
-      initialized_p = 1;
-    }
-
   for (c = DECL_CONSTRUCTOR_CALLS (current); c; c = TREE_CHAIN (c))
     {
       if (TREE_VALUE (c) == meth)
        {
          char *t;
-         if (list)
+         if (vcc_list)
            {
              tree liste;
-             list = nreverse (list);
-             for (liste = list; liste; liste = TREE_CHAIN (liste))
+             vcc_list = nreverse (vcc_list);
+             for (liste = vcc_list; liste; liste = TREE_CHAIN (liste))
                {
                  parse_error_context 
                    (TREE_PURPOSE (TREE_PURPOSE (liste)), "%s",
@@ -4695,16 +4854,16 @@ verify_constructor_circularity (meth, current)
                               "%s: recursive invocation of constructor `%s'",
                               constructor_circularity_msg (current, meth), t);
          free (t);
-         list = NULL_TREE;
+         vcc_list = NULL_TREE;
          return 1;
        }
     }
   for (c = DECL_CONSTRUCTOR_CALLS (current); c; c = TREE_CHAIN (c))
     {
-      list = tree_cons (c, current, list);
+      vcc_list = tree_cons (c, current, vcc_list);
       if (verify_constructor_circularity (meth, TREE_VALUE (c)))
        return 1;
-      list = TREE_CHAIN (list);
+      vcc_list = TREE_CHAIN (vcc_list);
     }
   return 0;
 }
@@ -4912,19 +5071,20 @@ parser_check_super_interface (super_decl, this_decl, this_wfl)
   if (!CLASS_INTERFACE (super_decl))
     {
       parse_error_context 
-       (this_wfl, "Can't use %s `%s' to implement/extend %s `%s'",
-        (TYPE_ARRAY_P (super_type) ? "array" : "class"),
-        IDENTIFIER_POINTER (DECL_NAME (super_decl)),
+       (this_wfl, "%s `%s' can't implement/extend %s `%s'",
         (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (this_decl))) ? 
-         "interface" : "class"),
-        IDENTIFIER_POINTER (DECL_NAME (this_decl)));
+         "Interface" : "Class"),
+        IDENTIFIER_POINTER (DECL_NAME (this_decl)),
+        (TYPE_ARRAY_P (super_type) ? "array" : "class"),
+        IDENTIFIER_POINTER (DECL_NAME (super_decl)));
       return 1;
     }
 
   /* Check top-level interface access. Inner classes are subject to member 
      access rules (6.6.1). */
   if (! INNER_CLASS_P (super_type)
-      && check_pkg_class_access (DECL_NAME (super_decl), lookup_cl (this_decl)))
+      && check_pkg_class_access (DECL_NAME (super_decl),
+                                lookup_cl (this_decl), true))
     return 1;
 
   SOURCE_FRONTEND_DEBUG (("Completing interface %s with %s",
@@ -4963,7 +5123,7 @@ parser_check_super (super_decl, this_decl, wfl)
   /* Check top-level class scope. Inner classes are subject to member access
      rules (6.6.1). */
   if (! INNER_CLASS_P (super_type)
-      && (check_pkg_class_access (DECL_NAME (super_decl), wfl)))
+      && (check_pkg_class_access (DECL_NAME (super_decl), wfl, true)))
     return 1;
   
   SOURCE_FRONTEND_DEBUG (("Completing class %s with %s",
@@ -5045,10 +5205,12 @@ register_incomplete_type (kind, wfl, decl, ptr)
   JDEP_MISC (new) = NULL_TREE;
   /* 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)
+  if ((kind == JDEP_INTERFACE  || kind == JDEP_ANONYMOUS)
       && GET_ENCLOSING_CPC ())
     JDEP_ENCLOSING (new) = TREE_VALUE (GET_ENCLOSING_CPC ());
+  else if (kind == JDEP_SUPER)
+    JDEP_ENCLOSING (new) = (GET_ENCLOSING_CPC () ? 
+                           TREE_VALUE (GET_ENCLOSING_CPC ()) : NULL_TREE);
   else
     JDEP_ENCLOSING (new) = GET_CPC ();
   JDEP_GET_PATCH (new) = (tree *)NULL;
@@ -5058,6 +5220,89 @@ register_incomplete_type (kind, wfl, decl, ptr)
   return ptr;
 }
 
+/* This checks for circular references with innerclasses. We start
+   from SOURCE and should never reach TARGET. Extended/implemented
+   types in SOURCE have their enclosing context checked not to reach
+   TARGET. When the last enclosing context of SOURCE is reached, its
+   extended/implemented types are also checked not to reach TARGET.
+   In case of error, WFL of the offending type is returned; NULL_TREE
+   otherwise.  */
+
+static tree
+check_inner_circular_reference (source, target)
+     tree source;
+     tree target;
+{
+  tree basetype_vec = TYPE_BINFO_BASETYPES (source);
+  tree ctx, cl;
+  int i;
+
+  if (!basetype_vec)
+    return NULL_TREE;
+
+  for (i = 0; i < TREE_VEC_LENGTH (basetype_vec); i++)
+    {
+      tree su;
+
+      /* We can end up with a NULL_TREE or an incomplete type here if
+        we encountered previous type resolution errors. It's safe to
+        simply ignore these cases.  */
+      if (TREE_VEC_ELT (basetype_vec, i) == NULL_TREE)
+       continue;
+      su = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
+      if (INCOMPLETE_TYPE_P (su))
+       continue;
+
+      if (inherits_from_p (su, target))
+       return lookup_cl (TYPE_NAME (su));
+
+      for (ctx = DECL_CONTEXT (TYPE_NAME (su)); ctx; ctx = DECL_CONTEXT (ctx))
+       {
+         /* An enclosing context shouldn't be TARGET */
+         if (ctx == TYPE_NAME (target))
+           return lookup_cl (TYPE_NAME (su));
+
+         /* When we reach the enclosing last context, start a check
+            on it, with the same target */
+         if (! DECL_CONTEXT (ctx) &&
+             (cl = check_inner_circular_reference (TREE_TYPE (ctx), target)))
+           return cl;
+       }
+    }
+  return NULL_TREE;
+}
+
+/* Explore TYPE's `extends' clause member(s) and return the WFL of the
+   offending type if a circularity is detected. NULL_TREE is returned
+   otherwise. TYPE can be an interface or a class.   */
+
+static tree
+check_circular_reference (type)
+     tree type;
+{
+  tree basetype_vec = TYPE_BINFO_BASETYPES (type);
+  int i;
+
+  if (!basetype_vec)
+    return NULL_TREE;
+
+  if (! CLASS_INTERFACE (TYPE_NAME (type)))
+    {
+      if (inherits_from_p (CLASSTYPE_SUPER (type), type))
+       return lookup_cl (TYPE_NAME (type));
+      return NULL_TREE;
+    }
+    
+  for (i = 0; i < TREE_VEC_LENGTH (basetype_vec); i++)
+    {
+      tree vec_elt = TREE_VEC_ELT (basetype_vec, i);
+      if (vec_elt && BINFO_TYPE (vec_elt) != object_type_node
+         && interface_of_p (type, BINFO_TYPE (vec_elt)))
+       return lookup_cl (TYPE_NAME (BINFO_TYPE (vec_elt)));
+    }
+  return NULL_TREE;
+}
+
 void
 java_check_circular_reference ()
 {
@@ -5065,30 +5310,15 @@ java_check_circular_reference ()
   for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
     {
       tree type = TREE_TYPE (current);
-      if (CLASS_INTERFACE (current))
-       {
-         /* Check all interfaces this class extends */
-         tree basetype_vec = TYPE_BINFO_BASETYPES (type);
-         int n, i;
+      tree cl;
 
-         if (!basetype_vec)
-           return;
-         n = TREE_VEC_LENGTH (basetype_vec);
-         for (i = 0; i < n; i++)
-           {
-             tree vec_elt = TREE_VEC_ELT (basetype_vec, i);
-             if (vec_elt && BINFO_TYPE (vec_elt) != object_type_node 
-                 && interface_of_p (type, BINFO_TYPE (vec_elt)))
-               parse_error_context (lookup_cl (current),
-                                    "Cyclic interface inheritance");
-           }
-       }
-      else
-       if (inherits_from_p (CLASSTYPE_SUPER (type), type))
-         parse_error_context (lookup_cl (current), 
-                              "Cyclic class inheritance%s",
-                              (cyclic_inheritance_report ?
-                               cyclic_inheritance_report : ""));
+      cl = check_circular_reference (type);
+      if (! cl)
+       cl = check_inner_circular_reference (type, type);
+      if (cl)
+       parse_error_context (cl, "Cyclic class inheritance%s",
+                            (cyclic_inheritance_report ?
+                             cyclic_inheritance_report : ""));
     }
 }
 
@@ -5180,7 +5410,7 @@ build_alias_initializer_parameter_list (mode, class_type, parm, artificial)
    where found. ARGS is non NULL when a special signature must be
    enforced. This is the case for anonymous classes.  */
 
-static void
+static tree
 craft_constructor (class_decl, args)
      tree class_decl, args;
 {
@@ -5229,6 +5459,7 @@ craft_constructor (class_decl, args)
   /* Now, mark the artificial parameters. */
   DECL_FUNCTION_NAP (decl) = artificial;
   DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
+  return decl;
 }
 
 
@@ -5340,6 +5571,13 @@ java_complete_class ()
        cclass = TREE_CHAIN (cclass), cclassd = CLASSD_CHAIN (cclassd))
     {
       jdep *dep;
+
+      /* We keep the compilation unit imports in the class so that
+        they can be used later to resolve type dependencies that
+        aren't necessary to solve now. */
+      TYPE_IMPORT_LIST (TREE_TYPE (cclass)) = ctxp->import_list;
+      TYPE_IMPORT_DEMAND_LIST (TREE_TYPE (cclass)) = ctxp->import_demand_list;
+
       for (dep = CLASSD_FIRST (cclassd); dep; dep = JDEP_CHAIN (dep))
        {
          tree decl;
@@ -5406,7 +5644,7 @@ java_complete_class ()
                  tree mdecl = JDEP_DECL (dep), signature;
                  /* Recompute and reset the signature, check first that
                     all types are now defined. If they're not,
-                    dont build the signature. */
+                    don't build the signature. */
                  if (check_method_types_complete (mdecl))
                    {
                      signature = build_java_signature (TREE_TYPE (mdecl));
@@ -5465,9 +5703,9 @@ static tree
 resolve_class (enclosing, class_type, decl, cl)
      tree enclosing, class_type, decl, cl;
 {
-  const char *name = IDENTIFIER_POINTER (TYPE_NAME (class_type));
-  const char *base = name;
+  tree tname = TYPE_NAME (class_type);
   tree resolved_type = TREE_TYPE (class_type);
+  int array_dims = 0;
   tree resolved_type_decl;
   
   if (resolved_type != NULL_TREE)
@@ -5485,13 +5723,9 @@ resolve_class (enclosing, class_type, decl, cl)
 
   /* 1- Check to see if we have an array. If true, find what we really
      want to resolve  */
-  while (name[0] == '[')
-    name++;
-  if (base != name)
-    {
-      TYPE_NAME (class_type) = get_identifier (name);
-      WFL_STRIP_BRACKET (cl, cl);
-    }
+  if ((array_dims = build_type_name_from_array_name (tname,
+                                                    &TYPE_NAME (class_type))))
+    WFL_STRIP_BRACKET (cl, cl);
 
   /* 2- Resolve the bare type */
   if (!(resolved_type_decl = do_resolve_class (enclosing, class_type, 
@@ -5500,15 +5734,10 @@ resolve_class (enclosing, class_type, decl, cl)
   resolved_type = TREE_TYPE (resolved_type_decl);
 
   /* 3- If we have and array, reconstruct the array down to its nesting */
-  if (base != name)
+  if (array_dims)
     {
-      while (base != name)
-       {
-         resolved_type = build_java_array_type (resolved_type, -1);
-         name--;
-       }
-      /* A TYPE_NAME that is a TYPE_DECL was set in
-         build_java_array_type, return it. */
+      for (; array_dims; array_dims--)
+       resolved_type = build_java_array_type (resolved_type, -1);
       resolved_type_decl = TYPE_NAME (resolved_type);
     }
   TREE_TYPE (class_type) = resolved_type;
@@ -5516,54 +5745,55 @@ resolve_class (enclosing, class_type, decl, cl)
 }
 
 /* Effectively perform the resolution of class CLASS_TYPE. DECL or CL
-   are used to report error messages.  */
+   are used to report error messages. Do not try to replace TYPE_NAME
+   (class_type) by a variable, since it is changed by
+   find_in_imports{_on_demand} and (but it doesn't really matter)
+   qualify_and_find.  */
 
 tree
 do_resolve_class (enclosing, class_type, decl, cl)
      tree enclosing, class_type, decl, cl;
 {
-  tree new_class_decl;
+  tree new_class_decl = NULL_TREE, super = NULL_TREE;
+  tree saved_enclosing_type = enclosing ? TREE_TYPE (enclosing) : NULL_TREE;
+  tree decl_result;
+  htab_t circularity_hash;
 
-  /* Do not try to replace TYPE_NAME (class_type) by a variable, since
-     it is changed by find_in_imports{_on_demand} and (but it doesn't
-     really matter) qualify_and_find */
+  /* This hash table is used to register the classes we're going
+     through when searching the current class as an inner class, in
+     order to detect circular references. Remember to free it before
+     returning the section 0- of this function. */
+  circularity_hash = htab_create (20, htab_hash_pointer, htab_eq_pointer, 
+                                 NULL);
 
-  /* 0- Search in the current class as an inner class */
-
-  /* Maybe some code here should be added to load the class or
+  /* 0- Search in the current class as an inner class.
+     Maybe some code here should be added to load the class or
      something, at least if the class isn't an inner class and ended
      being loaded from class file. FIXME. */
   while (enclosing)
     {
-      tree intermediate;
-
-      if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl)))
-        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)))
-           return new_class_decl;
-       }
-
-      /* Now go to the upper classes, bail out if necessary. */
-      enclosing = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
-      if (!enclosing || enclosing == 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 (enclosing) == POINTER_TYPE)
-       enclosing = do_resolve_class (NULL, enclosing, 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
-        enclosing = TYPE_NAME (enclosing);
+       enclosing = NULL_TREE;
     }
 
+  htab_delete (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);
+  find_in_imports (saved_enclosing_type, class_type);
 
   /* 2- And check for the type in the current compilation unit */
   if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
@@ -5585,7 +5815,7 @@ do_resolve_class (enclosing, class_type, decl, cl)
   /* 4- Check the import on demands. Don't allow bar.baz to be
      imported from foo.* */
   if (!QUALIFIED_P (TYPE_NAME (class_type)))
-    if (find_in_imports_on_demand (class_type))
+    if (find_in_imports_on_demand (saved_enclosing_type, class_type))
       return NULL_TREE;
 
   /* If found in find_in_imports_on_demant, the type has already been
@@ -5620,12 +5850,37 @@ do_resolve_class (enclosing, class_type, decl, cl)
      by the caller. */
   if (cl)
     {
-      if (check_pkg_class_access (TYPE_NAME (class_type), cl))
+      if (check_pkg_class_access (TYPE_NAME (class_type), cl, true))
         return NULL_TREE;
     }
-  
+
   /* 6- Last call for a resolution */
-  return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+  decl_result = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+
+  /* The final lookup might have registered a.b.c into a.b$c If we
+     failed at the first lookup, progressively change the name if
+     applicable and use the matching DECL instead. */
+  if (!decl_result && QUALIFIED_P (TYPE_NAME (class_type)))
+    {
+      char *separator;
+      tree name = TYPE_NAME (class_type);
+      char *namebuffer = alloca (IDENTIFIER_LENGTH (name) + 1);
+
+      strcpy (namebuffer, IDENTIFIER_POINTER (name));
+
+      do {
+
+       /* Reach the last '.', and if applicable, replace it by a `$' and
+          see if this exists as a type. */
+       if ((separator = strrchr (namebuffer, '.')))
+         {
+           *separator = '$';
+           name = get_identifier (namebuffer);
+           decl_result = IDENTIFIER_CLASS_VALUE (name);
+         }
+      } while (!decl_result && separator);
+    }
+  return decl_result;
 }
 
 static tree
@@ -5728,15 +5983,24 @@ resolve_no_layout (name, cl)
   return decl;
 }
 
-/* Called when reporting errors. Skip leader '[' in a complex array
-   type description that failed to be resolved.  */
+/* Called when reporting errors. Skip the '[]'s in a complex array
+   type description that failed to be resolved. purify_type_name can't
+   use an identifier tree.  */
 
 static const char *
 purify_type_name (name)
      const char *name;
 {
-  while (*name && *name == '[')
-    name++;
+  int len = strlen (name);
+  int bracket_found;
+
+  STRING_STRIP_BRACKETS (name, len, bracket_found);
+  if (bracket_found)
+    {
+      char *stripped_name = xmemdup (name, len, len+1);
+      stripped_name [len] = '\0';
+      return stripped_name;
+    }
   return name;
 }
 
@@ -5839,8 +6103,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));
@@ -6028,7 +6293,7 @@ java_check_methods (class_decl)
 }
 
 /* Check all the methods of CLASS_DECL. Methods are first completed
-   then checked according to regular method existance rules.  If no
+   then checked according to regular method existence rules.  If no
    constructor for CLASS_DECL were encountered, then build its
    declaration.  */
 
@@ -6378,34 +6643,33 @@ lookup_java_method2 (clas, method_decl, do_interface)
 /* Return the line that matches DECL line number, and try its best to
    position the column number. Used during error reports.  */
 
+static GTY(()) tree cl_v;
 static tree
 lookup_cl (decl)
      tree decl;
 {
-  static tree cl = NULL_TREE;
   char *line, *found;
   
   if (!decl)
     return NULL_TREE;
 
-  if (cl == NULL_TREE)
+  if (cl_v == NULL_TREE)
     {
-      cl = build_expr_wfl (NULL_TREE, NULL, 0, 0);
-      ggc_add_tree_root (&cl, 1);
+      cl_v = build_expr_wfl (NULL_TREE, NULL, 0, 0);
     }
 
-  EXPR_WFL_FILENAME_NODE (cl) = get_identifier (DECL_SOURCE_FILE (decl));
-  EXPR_WFL_SET_LINECOL (cl, DECL_SOURCE_LINE_FIRST (decl), -1);
+  EXPR_WFL_FILENAME_NODE (cl_v) = get_identifier (DECL_SOURCE_FILE (decl));
+  EXPR_WFL_SET_LINECOL (cl_v, DECL_SOURCE_LINE_FIRST (decl), -1);
 
-  line = java_get_line_col (EXPR_WFL_FILENAME (cl), 
-                           EXPR_WFL_LINENO (cl), EXPR_WFL_COLNO (cl));
+  line = java_get_line_col (EXPR_WFL_FILENAME (cl_v), 
+                           EXPR_WFL_LINENO (cl_v), EXPR_WFL_COLNO (cl_v));
 
   found = strstr ((const char *)line, 
                  (const char *)IDENTIFIER_POINTER (DECL_NAME (decl)));
   if (found)
-    EXPR_WFL_SET_LINECOL (cl, EXPR_WFL_LINENO (cl), found - line);
+    EXPR_WFL_SET_LINECOL (cl_v, EXPR_WFL_LINENO (cl_v), found - line);
 
-  return cl;
+  return cl_v;
 }
 
 /* Look for a simple name in the single-type import list */
@@ -6452,7 +6716,7 @@ process_imports ()
          QUALIFIED_P (to_be_found) = 1;
          load_class (to_be_found, 0);
          error_found =
-           check_pkg_class_access (to_be_found, TREE_PURPOSE (import));
+           check_pkg_class_access (to_be_found, TREE_PURPOSE (import), true);
          
          /* We found it, we can bail out */
          if (IDENTIFIER_CLASS_VALUE (to_be_found))
@@ -6486,17 +6750,22 @@ process_imports ()
    statement.  */
 
 static void
-find_in_imports (class_type)
+find_in_imports (enclosing_type, class_type)
+     tree enclosing_type;
      tree class_type;
 {
-  tree import;
-
-  for (import = ctxp->import_list; import; import = TREE_CHAIN (import))
-    if (TREE_VALUE (import) == TYPE_NAME (class_type))
-      {
-       TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import));
-       QUALIFIED_P (TYPE_NAME (class_type)) = 1;
-      }
+  tree import = (enclosing_type ? TYPE_IMPORT_LIST (enclosing_type) : 
+                ctxp->import_list);
+  while (import)
+    {
+      if (TREE_VALUE (import) == TYPE_NAME (class_type))
+       {
+         TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import));
+         QUALIFIED_P (TYPE_NAME (class_type)) = 1;
+         return;
+       }
+      import = TREE_CHAIN (import);
+    }
 }
 
 static int
@@ -6536,7 +6805,6 @@ read_import_dir (wfl)
   void *entry;
   struct buffer filename[1];
 
-
   if (IS_AN_IMPORT_ON_DEMAND_P (package_id))
     return;
   IS_AN_IMPORT_ON_DEMAND_P (package_id) = 1;
@@ -6627,7 +6895,7 @@ read_import_dir (wfl)
       static int first = 1;
       if (first)
        {
-         error ("Can't find default package `%s'. Check the CLASSPATH environment variable and the access to the archives.", package_name);
+         error ("Can't find default package `%s'. Check the CLASSPATH environment variable and the access to the archives", package_name);
          java_error_count++;
          first = 0;
        }
@@ -6641,75 +6909,103 @@ read_import_dir (wfl)
 }
 
 /* Possibly find a type in the import on demands specified
-   types. Returns 1 if an error occured, 0 otherwise. Run throught the
+   types. Returns 1 if an error occurred, 0 otherwise. Run through the
    entire list, to detected potential double definitions.  */
                 
 static int
-find_in_imports_on_demand (class_type)
+find_in_imports_on_demand (enclosing_type, class_type)
+     tree enclosing_type;
      tree class_type;
 {
-  tree node, import, node_to_use = NULL_TREE;
-  int seen_once = -1;
+  tree class_type_name = TYPE_NAME (class_type);
+  tree import = (enclosing_type ? TYPE_IMPORT_DEMAND_LIST (enclosing_type) :
+                 ctxp->import_demand_list);
   tree cl = NULL_TREE;
+  int seen_once = -1;  /* -1 when not set, 1 if seen once, >1 otherwise. */
+  int to_return = -1;  /* -1 when not set, 0 or 1 otherwise */
+  tree node;
 
-  for (import = ctxp->import_demand_list; import; import = TREE_CHAIN (import))
+  for (; import; import = TREE_CHAIN (import))
     {
+      int saved_lineno = lineno;
+      int access_check;
       const char *id_name;
+      tree decl, type_name_copy;
+
       obstack_grow (&temporary_obstack, 
                    IDENTIFIER_POINTER (EXPR_WFL_NODE (TREE_PURPOSE (import))),
                    IDENTIFIER_LENGTH (EXPR_WFL_NODE (TREE_PURPOSE (import))));
       obstack_1grow (&temporary_obstack, '.');
       obstack_grow0 (&temporary_obstack, 
-                    IDENTIFIER_POINTER (TYPE_NAME (class_type)),
-                    IDENTIFIER_LENGTH (TYPE_NAME (class_type)));
+                    IDENTIFIER_POINTER (class_type_name),
+                    IDENTIFIER_LENGTH (class_type_name));
       id_name = obstack_finish (&temporary_obstack);
              
-      node = maybe_get_identifier (id_name);
-      if (node && IS_A_CLASSFILE_NAME (node))
+      if (! (node = maybe_get_identifier (id_name)))
+       continue;
+
+      /* Setup lineno so that it refers to the line of the import (in
+        case we parse a class file and encounter errors */
+      lineno = EXPR_WFL_LINENO (TREE_PURPOSE (import));
+
+      type_name_copy = TYPE_NAME (class_type);
+      TYPE_NAME (class_type) = node;
+      QUALIFIED_P (node) = 1;
+      decl = IDENTIFIER_CLASS_VALUE (node);
+      access_check = -1;
+      /* If there is no DECL set for the class or if the class isn't
+        loaded and not seen in source yet, then load */
+      if (!decl || (!CLASS_LOADED_P (TREE_TYPE (decl))
+                   && !CLASS_FROM_SOURCE_P (TREE_TYPE (decl))))
+       {
+         load_class (node, 0);
+         decl = IDENTIFIER_CLASS_VALUE (node);
+       }
+      if (decl && ! INNER_CLASS_P (TREE_TYPE (decl)))
+       access_check = check_pkg_class_access (node, TREE_PURPOSE (import),
+                                              false);
+      else
+       /* 6.6.1: Inner classes are subject to member access rules. */
+       access_check = 0;
+
+      lineno = saved_lineno;
+
+      /* If the loaded class is not accessible or couldn't be loaded,
+        we restore the original TYPE_NAME and process the next
+        import. */
+      if (access_check || !decl)
+       {
+         TYPE_NAME (class_type) = type_name_copy;
+         continue;
+       }
+      
+      /* If the loaded class is accessible, we keep a tab on it to
+        detect and report multiple inclusions. */
+      if (IS_A_CLASSFILE_NAME (node))
        {
          if (seen_once < 0)
            {
              cl = TREE_PURPOSE (import);
              seen_once = 1;
-             node_to_use = node;
            }
-         else
+         else if (seen_once >= 0)
            {
+             tree location = (cl ? cl : TREE_PURPOSE (import));
+             tree package = (cl ? EXPR_WFL_NODE (cl) : 
+                             EXPR_WFL_NODE (TREE_PURPOSE (import)));
              seen_once++;
              parse_error_context 
-               (TREE_PURPOSE (import), 
+               (location,
                 "Type `%s' also potentially defined in package `%s'",
-                IDENTIFIER_POINTER (TYPE_NAME (class_type)),
-                IDENTIFIER_POINTER (EXPR_WFL_NODE (TREE_PURPOSE (import))));
+                IDENTIFIER_POINTER (TYPE_NAME (class_type)), 
+                IDENTIFIER_POINTER (package));
            }
        }
+      to_return = access_check;
     }
 
   if (seen_once == 1)
-    {
-      /* Setup lineno so that it refers to the line of the import (in
-        case we parse a class file and encounter errors */
-      tree decl;
-      int saved_lineno = lineno;
-      lineno = EXPR_WFL_LINENO (cl);
-      TYPE_NAME (class_type) = node_to_use;
-      QUALIFIED_P (TYPE_NAME (class_type)) = 1;
-      decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
-      /* If there is no DECL set for the class or if the class isn't
-        loaded and not seen in source yet, the load */
-      if (!decl || (!CLASS_LOADED_P (TREE_TYPE (decl))
-                   && !CLASS_FROM_SOURCE_P (TREE_TYPE (decl))))
-       {
-         load_class (node_to_use, 0);
-         decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
-       }
-      lineno = saved_lineno;
-      if (! INNER_CLASS_P (TREE_TYPE (decl)))
-       return check_pkg_class_access (TYPE_NAME (class_type), cl);
-      else
-        /* 6.6.1: Inner classes are subject to member access rules. */
-        return 0;
-    }
+    return to_return;
   else
     return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */
 }
@@ -6722,62 +7018,47 @@ static void
 register_package (name)
      tree name;
 {
-  static struct hash_table _pht, *pht = NULL;
+  static htab_t pht;
+  PTR *e;
 
-  if (!pht)
-    {
-      hash_table_init (&_pht, hash_newfunc, 
-                      java_hash_hash_tree_node, java_hash_compare_tree_node);
-      pht = &_pht;
-    }
-  
-  if (!hash_lookup (pht, (const hash_table_key) name, FALSE, NULL))
+  if (pht == NULL)
+    pht = htab_create (50, htab_hash_pointer, htab_eq_pointer, NULL);
+
+  e = htab_find_slot (pht, name, INSERT);
+  if (*e == NULL)
     {
       package_list = chainon (package_list, build_tree_list (name, NULL));
-      hash_lookup (pht, (const hash_table_key) name, TRUE, NULL);
+      *e = name;
     }
 }
 
 static tree
-resolve_package (pkg, next)
-     tree pkg, *next;
+resolve_package (pkg, next, type_name)
+     tree pkg, *next, *type_name;
 {
-  tree current, acc;
-  tree type_name = NULL_TREE;
-  const char *name = IDENTIFIER_POINTER (EXPR_WFL_NODE (pkg));
+  tree current;
+  tree decl = NULL_TREE;
+  *type_name = NULL_TREE;
 
   /* The trick is to determine when the package name stops and were
      the name of something contained in the package starts. Then we
      return a fully qualified name of what we want to get. */
 
-  /* Do a quick search on well known package names */
-  if (!strncmp (name, "java.lang.reflect", 17))
-    {
-      *next = 
-       TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg))));
-      type_name = lookup_package_type (name, 17);
-    }
-  else if (!strncmp (name, "java.lang", 9))
-    {
-      *next = TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg)));
-      type_name = lookup_package_type (name, 9);
-    }
-
-  /* If we found something here, return */
-  if (type_name)
-    return type_name; 
-
   *next = EXPR_WFL_QUALIFICATION (pkg);
 
   /* Try to progressively construct a type name */
   if (TREE_CODE (pkg) == EXPR_WITH_FILE_LOCATION)
-    for (acc = NULL_TREE, current = EXPR_WFL_QUALIFICATION (pkg); 
+    for (current = EXPR_WFL_QUALIFICATION (pkg); 
         current; current = TREE_CHAIN (current))
       {
-       acc = merge_qualified_name (acc, EXPR_WFL_NODE (QUAL_WFL (current)));
-       if ((type_name = resolve_no_layout (acc, NULL_TREE)))
+       /* If we don't have what we're expecting, exit now. TYPE_NAME
+          will be null and the error caught later. */
+       if (TREE_CODE (QUAL_WFL (current)) != EXPR_WITH_FILE_LOCATION)
+         break;
+       *type_name = 
+         merge_qualified_name (*type_name, EXPR_WFL_NODE (QUAL_WFL (current)));
+       if ((decl = resolve_no_layout (*type_name, NULL_TREE)))
          {
-           type_name = acc;
            /* resolve_package should be used in a loop, hence we
               point at this one to naturally process the next one at
               the next iteration. */
@@ -6785,22 +7066,9 @@ resolve_package (pkg, next)
            break;
          }
       }
-  return type_name;
+  return decl;
 }
 
-static tree
-lookup_package_type (name, from)
-     const char *name;
-     int from;
-{
-  char subname [128];
-  const char *sub = &name[from+1];
-  while (*sub != '.' && *sub)
-    sub++;
-  strncpy (subname, name, sub-name);
-  subname [sub-name] = '\0';
-  return get_identifier (subname);
-}
 
 /* Check accessibility of inner classes according to member access rules. 
    DECL is the inner class, ENCLOSING_DECL is the class from which the
@@ -6881,14 +7149,16 @@ check_inner_class_access (decl, enclosing_decl, cl)
                       lang_printable_name (decl, 0), access);
 }
 
-/* Accessibility check for top-level classes. If CLASS_NAME is in a foreign 
-   package, it must be PUBLIC. Return 0 if no access violations were found, 
-   1 otherwise.  */
+/* Accessibility check for top-level classes. If CLASS_NAME is in a
+   foreign package, it must be PUBLIC. Return 0 if no access
+   violations were found, 1 otherwise. If VERBOSE is true and an error
+   was found, it is reported and accounted for.  */
 
 static int
-check_pkg_class_access (class_name, cl)
+check_pkg_class_access (class_name, cl, verbose)
      tree class_name;
      tree cl;
+     bool verbose;
 {
   tree type;
 
@@ -6911,10 +7181,11 @@ check_pkg_class_access (class_name, cl)
        /* Both in the same package. */
        return 0;
 
-      parse_error_context 
-       (cl, "Can't access %s `%s'. Only public classes and interfaces in other packages can be accessed",
-        (CLASS_INTERFACE (TYPE_NAME (type)) ? "interface" : "class"),
-        IDENTIFIER_POINTER (class_name));
+      if (verbose)
+       parse_error_context 
+         (cl, "Can't access %s `%s'. Only public classes and interfaces in other packages can be accessed",
+          (CLASS_INTERFACE (TYPE_NAME (type)) ? "interface" : "class"),
+          IDENTIFIER_POINTER (class_name));
       return 1;
     }
   return 0;
@@ -6994,7 +7265,7 @@ declare_local_variables (modifier, type, vlist)
         will be entered */
       decl = build_decl (VAR_DECL, name, real_type);
       MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
-      LOCAL_FINAL (decl) = final_p;
+      DECL_FINAL (decl) = final_p;
       BLOCK_CHAIN_DECL (decl);
       
       /* If doing xreferencing, replace the line number with the WFL
@@ -7069,11 +7340,11 @@ source_start_java_method (fndecl)
        parm_decl = build_decl (PARM_DECL, name, type);
 
       /* Remember if a local variable was declared final (via its
-         TREE_LIST of type/name.) Set LOCAL_FINAL accordingly. */
+         TREE_LIST of type/name.) Set DECL_FINAL accordingly. */
       if (ARG_FINAL_P (tem))
        {
          MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (parm_decl);
-         LOCAL_FINAL (parm_decl) = 1;
+         DECL_FINAL (parm_decl) = 1;
        }
 
       BLOCK_CHAIN_DECL (parm_decl);
@@ -7106,7 +7377,7 @@ create_artificial_method (class, flags, type, name, args)
   return mdecl;
 }
 
-/* Starts the body if an artifical method.  */
+/* Starts the body if an artificial method.  */
 
 static void
 start_artificial_method_body (mdecl)
@@ -7130,6 +7401,24 @@ end_artificial_method_body (mdecl)
   exit_block ();
 }
 
+/* Dump a tree of some kind.  This is a convenience wrapper for the
+   dump_* functions in tree-dump.c.  */
+static void
+dump_java_tree (phase, t)
+     enum tree_dump_index phase;
+     tree t;
+{
+  FILE *stream;
+  int flags;
+
+  stream = dump_begin (phase, &flags);
+  if (stream)
+    {
+      dump_node (t, flags, stream);
+      dump_end (phase, stream);
+    }
+}
+
 /* Terminate a function and expand its body.  */
 
 static void
@@ -7149,6 +7438,10 @@ source_end_java_method ()
   if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) == empty_stmt_node)
     BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE;
 
+  /* We've generated all the trees for this function, and it has been
+     patched.  Dump it to a file if the user requested it.  */
+  dump_java_tree (TDI_original, fndecl);
+
   /* Generate function's code */
   if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
       && ! flag_emit_class_files
@@ -7238,20 +7531,12 @@ void java_layout_seen_class_methods ()
     }
 }
 
+static GTY(()) tree stop_reordering;
 void
 java_reorder_fields ()
 {
-  static tree stop_reordering = NULL_TREE;
-  static int initialized_p;
   tree current;
 
-  /* Register STOP_REORDERING with the garbage collector.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&stop_reordering, 1);
-      initialized_p = 1;
-    }
-
   for (current = gclass_list; current; current = TREE_CHAIN (current))
     {
       current_class = TREE_TYPE (TREE_VALUE (current));
@@ -7282,7 +7567,9 @@ java_reorder_fields ()
          }
       }
     }
-  stop_reordering = TREE_TYPE (TREE_VALUE (gclass_list));
+  /* There are cases were gclass_list will be empty. */
+  if (gclass_list)
+    stop_reordering = TREE_TYPE (TREE_VALUE (gclass_list));
 }
 
 /* Layout the methods of all classes loaded in one way or another.
@@ -7373,18 +7660,10 @@ 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);
 
-  /* Find whether the class has final variables */
-  for (decl = TYPE_FIELDS (current_class); decl; decl = TREE_CHAIN (decl))
-    if (FIELD_FINAL (decl))
-      {
-       TYPE_HAS_FINAL_VARIABLE (current_class) = 1;
-       break;
-      }
-
   /* Initialize a new constant pool */
   init_outgoing_cpool ();
 
@@ -7395,13 +7674,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))
@@ -7417,16 +7698,8 @@ java_complete_expand_methods (class_decl)
       if (no_body)
        restore_line_number_status (1);
 
-      /* Reset the final local variable assignment flags */
-      if (TYPE_HAS_FINAL_VARIABLE (current_class))
-       reset_final_variable_local_assignment_flag (current_class);
-
       java_complete_expand_method (decl);
 
-      /* Check for missed out final variable assignment */
-      if (TYPE_HAS_FINAL_VARIABLE (current_class))
-       check_final_variable_local_assignment_flag (current_class, decl);
-      
       if (no_body)
        restore_line_number_status (0);
     }
@@ -7434,16 +7707,23 @@ java_complete_expand_methods (class_decl)
   /* First, do the ordinary methods. */
   for (decl = first_decl; decl; decl = TREE_CHAIN (decl))
     {
+      /* Ctors aren't part of this batch. */
+      if (DECL_CONSTRUCTOR_P (decl) || DECL_CLINIT_P (decl))
+       continue;
+      
       /* Skip abstract or native methods -- but do handle native
         methods when generating JNI stubs.  */
-      if (METHOD_ABSTRACT (decl)
-         || (! flag_jni && METHOD_NATIVE (decl))
-         || DECL_CONSTRUCTOR_P (decl) || DECL_CLINIT_P (decl))
-       continue;
+      if (METHOD_ABSTRACT (decl) || (! flag_jni && METHOD_NATIVE (decl)))
+       {
+         DECL_FUNCTION_BODY (decl) = NULL_TREE;
+         continue;
+       }
 
       if (METHOD_NATIVE (decl))
        {
-         tree body = build_jni_stub (decl);
+         tree body;
+         current_function_decl = decl;
+         body = build_jni_stub (decl);
          BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)) = body;
        }
 
@@ -7453,17 +7733,10 @@ java_complete_expand_methods (class_decl)
   /* If there is indeed a <clinit>, fully expand it now */
   if (clinit)
     {
-      /* Reset the final local variable assignment flags */
-      if (TYPE_HAS_FINAL_VARIABLE (current_class))
-       reset_static_final_variable_assignment_flag (current_class);
       /* Prevent the use of `this' inside <clinit> */
       ctxp->explicit_constructor_p = 1;
       java_complete_expand_method (clinit);
       ctxp->explicit_constructor_p = 0;
-      /* Check for missed out static final variable assignment */
-      if (TYPE_HAS_FINAL_VARIABLE (current_class)
-         && !CLASS_INTERFACE (class_decl))
-       check_static_final_variable_assignment_flag (current_class);
     }
   
   /* We might have generated a class$ that we now want to expand */
@@ -7478,15 +7751,6 @@ java_complete_expand_methods (class_decl)
          && verify_constructor_circularity (decl, decl))
        break;
 
-  /* Final check on the initialization of final variables. */
-  if (TYPE_HAS_FINAL_VARIABLE (current_class))
-    {
-      check_final_variable_global_assignment_flag (current_class);
-      /* If we have an interface, check for uninitialized fields. */
-      if (CLASS_INTERFACE (class_decl))
-       check_static_final_variable_assignment_flag (current_class);
-    }
-
   /* Save the constant pool. We'll need to restore it later. */
   TYPE_CPOOL (current_class) = outgoing_cpool;
 }
@@ -7555,8 +7819,8 @@ maybe_generate_pre_expand_clinit (class_type)
    MODIFY_EXPR with a constant value.  */
 
 static int
-analyze_clinit_body (bbody)
-     tree bbody;
+analyze_clinit_body (this_class, bbody)
+     tree this_class, bbody;
 {
   while (bbody)
     switch (TREE_CODE (bbody))
@@ -7570,14 +7834,27 @@ analyze_clinit_body (bbody)
        break;
        
       case COMPOUND_EXPR:
-       if (analyze_clinit_body (TREE_OPERAND (bbody, 0)))
+       if (analyze_clinit_body (this_class, TREE_OPERAND (bbody, 0)))
          return 1;
        bbody = TREE_OPERAND (bbody, 1);
        break;
        
       case MODIFY_EXPR:
-       /* Return 0 if the operand is constant, 1 otherwise.  */
-       return ! TREE_CONSTANT (TREE_OPERAND (bbody, 1));
+       /* If we're generating to class file and we're dealing with an
+          array initialization, we return 1 to keep <clinit> */
+       if (TREE_CODE (TREE_OPERAND (bbody, 1)) == NEW_ARRAY_INIT
+           && flag_emit_class_files)
+         return 1;
+
+       /* There are a few cases where we're required to keep
+          <clinit>:
+          - If this is an assignment whose operand is not constant,
+          - If this is an assignment to a non-initialized field,
+          - If this field is not a member of the current class.
+       */
+       return (! TREE_CONSTANT (TREE_OPERAND (bbody, 1))
+               || ! DECL_INITIAL (TREE_OPERAND (bbody, 0))
+               || DECL_CONTEXT (TREE_OPERAND (bbody, 0)) != this_class);
 
       default:
        return 1;
@@ -7596,7 +7873,6 @@ maybe_yank_clinit (mdecl)
 {
   tree type, current;
   tree fbody, bbody;
-  int found = 0;
   
   if (!DECL_CLINIT_P (mdecl))
     return 0;
@@ -7612,7 +7888,7 @@ maybe_yank_clinit (mdecl)
     return 0;
   if (bbody && ! flag_emit_class_files && bbody != empty_stmt_node)
     return 0;
-  
+
   type = DECL_CONTEXT (mdecl);
   current = TYPE_FIELDS (type);
 
@@ -7621,40 +7897,30 @@ maybe_yank_clinit (mdecl)
     {
       tree f_init;
 
-      /* We're not interested in non static field */
+      /* We're not interested in non-static fields.  */
       if (!FIELD_STATIC (current))
        continue;
 
+      /* Nor in fields without initializers. */
+      f_init = DECL_INITIAL (current);
+      if (f_init == NULL_TREE)
+       continue;
+
       /* Anything that isn't String or a basic type is ruled out -- or
         if we know how to deal with it (when doing things natively) we
         should generated an empty <clinit> so that SUID are computed
         correctly. */
       if (! JSTRING_TYPE_P (TREE_TYPE (current))
          && ! JNUMERIC_TYPE_P (TREE_TYPE (current)))
-       break;
-         
-      f_init = DECL_INITIAL (current);
-      /* If we're emitting native code, we want static final fields to
-        have constant initializers. If we don't meet these
-        conditions, we keep <clinit> */
-      if (!flag_emit_class_files
-         && !(FIELD_FINAL (current) && f_init && TREE_CONSTANT (f_init)))
-       break;
-      /* If we're emitting bytecode, we want static fields to have
-        constant initializers or no initializer. If we don't meet
-        these conditions, we keep <clinit> */
-      if (flag_emit_class_files && f_init && !TREE_CONSTANT (f_init))
-       break;
+       return 0;
+
+      if (! FIELD_FINAL (current) || ! TREE_CONSTANT (f_init))
+       return 0;
     }
 
   /* Now we analyze the method body and look for something that
      isn't a MODIFY_EXPR */
-  if (bbody == empty_stmt_node)
-    found = 0;
-  else
-    found = analyze_clinit_body (bbody);
-
-  if (current || found)
+  if (bbody != empty_stmt_node && analyze_clinit_body (type, bbody))
     return 0;
 
   /* Get rid of <clinit> in the class' list of methods */
@@ -7672,6 +7938,40 @@ maybe_yank_clinit (mdecl)
   return 1;
 }
 
+/* Install the argument from MDECL. Suitable to completion and
+   expansion of mdecl's body.  */
+
+static void
+start_complete_expand_method (mdecl)
+     tree mdecl;
+{
+  tree tem;
+
+  pushlevel (1);               /* Prepare for a parameter push */
+  tem = BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (current_function_decl));
+  DECL_ARGUMENTS (mdecl) = tem;
+
+  for (; tem; tem = TREE_CHAIN (tem))
+    {
+      /* TREE_CHAIN (tem) will change after pushdecl. */ 
+      tree next = TREE_CHAIN (tem);
+      tree type = TREE_TYPE (tem);
+      if (PROMOTE_PROTOTYPES
+         && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
+         && INTEGRAL_TYPE_P (type))
+       type = integer_type_node;
+      DECL_ARG_TYPE (tem) = type;
+      layout_decl (tem, 0);
+      pushdecl (tem);
+      /* Re-install the next so that the list is kept and the loop
+        advances. */
+      TREE_CHAIN (tem) = next;
+    }
+  pushdecl_force_head (DECL_ARGUMENTS (mdecl));
+  lineno = DECL_SOURCE_LINE_FIRST (mdecl);
+  build_result_decl (mdecl);
+}
+
 
 /* Complete and expand a method.  */
 
@@ -7679,7 +7979,7 @@ static void
 java_complete_expand_method (mdecl)
      tree mdecl;
 {
-  int yank_clinit = 0;
+  tree fbody, block_body, exception_copy;
 
   current_function_decl = mdecl;
   /* Fix constructors before expanding them */
@@ -7687,103 +7987,152 @@ java_complete_expand_method (mdecl)
     fix_constructors (mdecl);
   
   /* Expand functions that have a body */
-  if (DECL_FUNCTION_BODY (mdecl))
-    {
-      tree fbody = DECL_FUNCTION_BODY (mdecl);
-      tree block_body = BLOCK_EXPR_BODY (fbody);
-      tree exception_copy = NULL_TREE;
-      tree tem, *ptr;
-
-      current_function_decl = mdecl;
-
-      if (! quiet_flag)
-       fprintf (stderr, " [%s.",
-                lang_printable_name (DECL_CONTEXT (mdecl), 0));
-      announce_function (mdecl);
-      if (! quiet_flag)
-       fprintf (stderr, "]");
-
-      pushlevel (1);           /* Prepare for a parameter push */
-      ptr = &DECL_ARGUMENTS (mdecl);
-      tem  = BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (current_function_decl));
-      while (tem)
-       {
-         tree next = TREE_CHAIN (tem);
-         tree type = TREE_TYPE (tem);
-         if (PROMOTE_PROTOTYPES
-             && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
-             && INTEGRAL_TYPE_P (type))
-           type = integer_type_node;
-         DECL_ARG_TYPE (tem) = type;
-         layout_decl (tem, 0);
-         pushdecl (tem);
-         *ptr = tem;
-         ptr = &TREE_CHAIN (tem);
-         tem = next;
-       }
-      *ptr = NULL_TREE;
-      pushdecl_force_head (DECL_ARGUMENTS (mdecl));
-      lineno = DECL_SOURCE_LINE_FIRST (mdecl);
-
-      build_result_decl (mdecl);
-
-      current_this 
-       = (!METHOD_STATIC (mdecl) ? 
-          BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl)) : NULL_TREE);
-
-      /* Purge the `throws' list of unchecked exceptions. If we're
-        doing xref, save a copy of the list and re-install it
-        later. */
-      if (flag_emit_xref)
-       exception_copy = copy_list (DECL_FUNCTION_THROWS (mdecl));
+  if (!DECL_FUNCTION_BODY (mdecl))
+    return;
+
+  fbody = DECL_FUNCTION_BODY (mdecl);
+  block_body = BLOCK_EXPR_BODY (fbody);
+  exception_copy = NULL_TREE;
 
-      purge_unchecked_exceptions (mdecl);
+  current_function_decl = mdecl;
 
-      /* Install exceptions thrown with `throws' */
-      PUSH_EXCEPTIONS (DECL_FUNCTION_THROWS (mdecl));
+  if (! quiet_flag)
+    fprintf (stderr, " [%s.",
+            lang_printable_name (DECL_CONTEXT (mdecl), 0));
+  announce_function (mdecl);
+  if (! quiet_flag)
+    fprintf (stderr, "]");
+  
+  /* Prepare the function for tree completion */
+  start_complete_expand_method (mdecl);
 
-      if (block_body != NULL_TREE)
-       {
-         block_body = java_complete_tree (block_body);
+  /* Install the current this */
+  current_this = (!METHOD_STATIC (mdecl) ? 
+                 BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl)) : NULL_TREE);
 
-         if (! flag_emit_xref && ! METHOD_NATIVE (mdecl))
-           check_for_initialization (block_body);
-         ctxp->explicit_constructor_p = 0;
+  /* Purge the `throws' list of unchecked exceptions (we save a copy
+     of the list and re-install it later.) */
+  exception_copy = copy_list (DECL_FUNCTION_THROWS (mdecl));
+  purge_unchecked_exceptions (mdecl);
+  
+  /* Install exceptions thrown with `throws' */
+  PUSH_EXCEPTIONS (DECL_FUNCTION_THROWS (mdecl));
+  
+  if (block_body != NULL_TREE)
+    {
+      block_body = java_complete_tree (block_body);
+      
+      /* Before we check initialization, attached all class initialization
+        variable to the block_body */
+      htab_traverse (DECL_FUNCTION_INIT_TEST_TABLE (mdecl),
+                    attach_init_test_initialization_flags, block_body);
+      
+      if (! flag_emit_xref && ! METHOD_NATIVE (mdecl))
+       {
+         check_for_initialization (block_body, mdecl);
+         
+         /* Go through all the flags marking the initialization of
+            static variables and see whether they're definitively
+            assigned, in which case the type is remembered as
+            definitively initialized in MDECL. */
+         if (STATIC_CLASS_INIT_OPT_P ())
+           {
+             /* Always register the context as properly initialized in
+                MDECL. This used with caution helps removing extra
+                initialization of self. */
+             if (METHOD_STATIC (mdecl))
+               {
+                 *(htab_find_slot 
+                   (DECL_FUNCTION_INITIALIZED_CLASS_TABLE (mdecl),
+                    DECL_CONTEXT (mdecl), INSERT)) = DECL_CONTEXT (mdecl);
+               }
+           }
        }
+      ctxp->explicit_constructor_p = 0;
+    }
+  
+  BLOCK_EXPR_BODY (fbody) = block_body;
+  
+  /* If we saw a return but couldn't evaluate it properly, we'll have
+     an error_mark_node here. */
+  if (block_body != error_mark_node
+      && (block_body == NULL_TREE || CAN_COMPLETE_NORMALLY (block_body))
+      && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE
+      && !flag_emit_xref)
+    missing_return_error (current_function_decl);
 
-      BLOCK_EXPR_BODY (fbody) = block_body;
+  /* See if we can get rid of <clinit> if MDECL happens to be <clinit> */
+  maybe_yank_clinit (mdecl);
 
-      /* If we saw a return but couldn't evaluate it properly, we'll
-        have an error_mark_node here. */
-      if (block_body != error_mark_node
-         && (block_body == NULL_TREE || CAN_COMPLETE_NORMALLY (block_body))
-         && TREE_CODE (TREE_TYPE (TREE_TYPE (mdecl))) != VOID_TYPE
-         && !flag_emit_xref)
-       missing_return_error (current_function_decl);
+  /* Pop the current level, with special measures if we found errors. */
+  if (java_error_count)
+    pushdecl_force_head (DECL_ARGUMENTS (mdecl));
+  poplevel (1, 0, 1);
 
-      /* Check wether we could just get rid of clinit, now the picture
-         is complete. */
-      if (!(yank_clinit = maybe_yank_clinit (mdecl)))
-       complete_start_java_method (mdecl); 
-      
-      /* Don't go any further if we've found error(s) during the
-        expansion */
-      if (!java_error_count && !yank_clinit)
-       source_end_java_method ();
-      else
+  /* Pop the exceptions and sanity check */
+  POP_EXCEPTIONS();
+  if (currently_caught_type_list)
+    abort ();
+
+  /* Restore the copy of the list of exceptions if emitting xrefs. */
+  DECL_FUNCTION_THROWS (mdecl) = exception_copy;
+}
+
+/* For with each class for which there's code to generate. */
+
+static void
+java_expand_method_bodies (class)
+     tree class;
+{
+  tree decl;
+  for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl))
+    {
+      if (!DECL_FUNCTION_BODY (decl))
+       continue;
+
+      current_function_decl = decl;
+
+      /* It's time to assign the variable flagging static class
+        initialization based on which classes invoked static methods
+        are definitely initializing. This should be flagged. */
+      if (STATIC_CLASS_INIT_OPT_P ())
        {
-         if (java_error_count)
-           pushdecl_force_head (DECL_ARGUMENTS (mdecl));
-         poplevel (1, 0, 1);
+         tree list = DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (decl);
+         for (; list != NULL_TREE;  list = TREE_CHAIN (list))
+           {
+             /* Executed for each statement calling a static function.
+                LIST is a TREE_LIST whose PURPOSE is the called function
+                and VALUE is a compound whose second operand can be patched
+                with static class initialization flag assignments.  */
+
+             tree called_method = TREE_PURPOSE (list);
+             tree compound = TREE_VALUE (list);
+             tree assignment_compound_list
+               = build_tree_list (called_method, NULL);
+
+             /* For each class definitely initialized in
+                CALLED_METHOD, fill ASSIGNMENT_COMPOUND with
+                assignment to the class initialization flag. */
+             htab_traverse (DECL_FUNCTION_INITIALIZED_CLASS_TABLE (called_method),
+                            emit_test_initialization,
+                            assignment_compound_list);
+
+             if (TREE_VALUE (assignment_compound_list))
+               TREE_OPERAND (compound, 1)
+                 = TREE_VALUE (assignment_compound_list);
+           }
        }
 
-      /* Pop the exceptions and sanity check */
-      POP_EXCEPTIONS();
-      if (currently_caught_type_list)
-       abort ();
+      /* Prepare the function for RTL expansion */  
+      start_complete_expand_method (decl);
 
-      if (flag_emit_xref)
-       DECL_FUNCTION_THROWS (mdecl) = exception_copy;
+      /* Expand function start, generate initialization flag
+        assignment, and handle synchronized methods. */
+      complete_start_java_method (decl);
+
+      /* Expand the rest of the function body and terminate
+         expansion. */
+      source_end_java_method ();
     }
 }
 
@@ -7943,14 +8292,6 @@ outer_field_access_fix (wfl, node, rhs)
   
   if (outer_field_expanded_access_p (node, &name, &arg_type, &arg))
     {
-      /* At any rate, check whether we're trying to assign a value to
-        a final. */
-      tree accessed = (JDECL_P (node) ? node : 
-                      (TREE_CODE (node) == COMPONENT_REF ? 
-                       TREE_OPERAND (node, 1) : node));
-      if (check_final_assignment (accessed, wfl))
-       return error_mark_node;
-  
       node = build_outer_field_access_expr (EXPR_WFL_LINECOL (wfl), 
                                            arg_type, name, arg, rhs);
       return java_complete_tree (node);
@@ -8180,7 +8521,7 @@ build_access_to_thisn (from, to, lc)
 {
   tree access = NULL_TREE;
 
-  while (from != to)
+  while (from != to && PURE_INNER_CLASS_TYPE_P (from))
     {
       if (!access)
         {
@@ -8200,8 +8541,8 @@ build_access_to_thisn (from, to, lc)
          access = make_qualified_primary (cn, access, lc);
        }
 
-      /* if FROM isn't an inter class, that's fine, we've done
-         enough. What we're looking for can be accessed from there. */
+      /* If FROM isn't an inner class, that's fine, we've done enough.
+         What we're looking for can be accessed from there.  */
       from = DECL_CONTEXT (TYPE_NAME (from));
       if (!from)
        break;
@@ -8260,27 +8601,19 @@ maybe_build_thisn_access_method (type)
    This function can be invoked with TYPE to NULL, available and then
    has to count the parser context.  */
 
+static GTY(()) tree saved_thisn;
+static GTY(()) tree saved_type;
+
 static tree
 build_current_thisn (type)
     tree type;
 {
   static int saved_i = -1;
-  static tree saved_thisn = NULL_TREE;
-  static tree saved_type = NULL_TREE;
   static int saved_type_i = 0;
-  static int initialized_p;
   tree decl;
-  char buffer [80];
+  char buffer [24];
   int i = 0;
 
-  /* Register SAVED_THISN and SAVED_TYPE with the garbage collector.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&saved_thisn, 1);
-      ggc_add_tree_root (&saved_type, 1);
-      initialized_p = 1;
-    }
-
   if (type)
     {
       if (type == saved_type)
@@ -8337,6 +8670,9 @@ build_thisn_assign ()
         throw new NoClassDefFoundError(e.getMessage());}
     } */
 
+static GTY(()) tree get_message_wfl;
+static GTY(()) tree type_parm_wfl;
+
 static tree
 build_dot_class_method (class)
      tree class;
@@ -8344,18 +8680,12 @@ 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;
-
-  static tree get_message_wfl, type_parm_wfl;
+  tree stmt, throw_stmt;
 
   if (!get_message_wfl)
     {
       get_message_wfl = build_wfl_node (get_identifier ("getMessage"));
       type_parm_wfl = build_wfl_node (get_identifier ("type$"));
-      ggc_add_tree_root (&get_message_wfl, 1);
-      ggc_add_tree_root (&type_parm_wfl, 1);
     }
 
   /* Build the arguments */
@@ -8366,33 +8696,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);
@@ -8405,27 +8726,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_exception_object_ref (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);
@@ -8450,6 +8753,10 @@ build_dot_class_method_invocation (type)
   else
     sig_id = DECL_NAME (TYPE_NAME (type));
 
+  /* Ensure that the proper name separator is used */
+  sig_id = unmangle_classname (IDENTIFIER_POINTER (sig_id),
+                              IDENTIFIER_LENGTH (sig_id));
+
   s = build_string (IDENTIFIER_LENGTH (sig_id), 
                    IDENTIFIER_POINTER (sig_id));
   return build_method_invocation (build_wfl_node (classdollar_identifier_node),
@@ -8466,6 +8773,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);
@@ -8507,9 +8815,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);
     }
@@ -8517,15 +8825,17 @@ fix_constructors (mdecl)
   else 
     {
       int found = 0;
+      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))
          {
          case CALL_EXPR:
            found = CALL_EXPLICIT_CONSTRUCTOR_P (body);
+           if (CALL_THIS_CONSTRUCTOR_P (body))
+             invokes_this = 1;
            body = NULL_TREE;
            break;
          case COMPOUND_EXPR:
@@ -8559,9 +8869,11 @@ fix_constructors (mdecl)
          TREE_OPERAND (found_call, 0) = empty_stmt_node;
        }
       
+      DECL_INIT_CALLS_THIS (mdecl) = invokes_this;
+
       /* Insert the instance initializer block right after. */
-      if ((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)
@@ -8605,7 +8917,9 @@ verify_constructor_super (mdecl)
                  && m_arg_type != end_params_node);
                 arg_type = TREE_CHAIN (arg_type), 
                   m_arg_type = TREE_CHAIN (m_arg_type))
-             if (TREE_VALUE (arg_type) != TREE_VALUE (m_arg_type))
+             if (!valid_method_invocation_conversion_p 
+                    (TREE_VALUE (arg_type),
+                     TREE_VALUE (m_arg_type)))
                break;
 
            if (arg_type == end_params_node && m_arg_type == end_params_node)
@@ -8628,6 +8942,7 @@ verify_constructor_super (mdecl)
 
 /* Generate code for all context remembered for code generation.  */
 
+static GTY(()) tree reversed_class_list;
 void
 java_expand_classes ()
 {
@@ -8640,8 +8955,7 @@ java_expand_classes ()
   java_layout_classes ();
   java_parse_abort_on_error ();
 
-  cur_ctxp = ctxp_for_generation;
-  for (; cur_ctxp; cur_ctxp = cur_ctxp->next)
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       ctxp = cur_ctxp;
       input_filename = ctxp->filename;
@@ -8651,9 +8965,11 @@ java_expand_classes ()
     }
   input_filename = main_input_filename;
 
-  /* Find anonymous classes and expand their constructor, now they
-     have been fixed. */
-  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
+
+  /* Find anonymous classes and expand their constructor. This extra pass is
+     neccessary because the constructor itself is only generated when the
+     method in which it is defined is expanded. */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       tree current;
       ctxp = cur_ctxp;
@@ -8670,7 +8986,7 @@ java_expand_classes ()
                      restore_line_number_status (1);
                      java_complete_expand_method (d);
                      restore_line_number_status (0);
-                     break;    /* We now there are no other ones */
+                     break;    /* There is only one constructor. */
                    }
                }
            }
@@ -8686,20 +9002,61 @@ java_expand_classes ()
     return;
 
   /* Now things are stable, go for generation of the class data. */
-  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
+
+  /* We pessimistically marked all fields external until we knew
+     what set of classes we were planning to compile.  Now mark
+     those that will be generated locally as not external.  */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       tree current;
       ctxp = cur_ctxp;
       for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
        {
-         current_class = TREE_TYPE (current);
+         tree class = TREE_TYPE (current);
+         tree field;
+         for (field = TYPE_FIELDS (class); field ; field = TREE_CHAIN (field))
+           if (FIELD_STATIC (field))
+             DECL_EXTERNAL (field) = 0;
+       }
+    }
+
+  /* Compile the classes.  */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
+    {
+      tree current;
+      reversed_class_list = NULL;
+
+      ctxp = cur_ctxp;
+
+      /* We write out the classes in reverse order.  This ensures that
+        inner classes are written before their containing classes,
+        which is important for parallel builds.  Otherwise, the
+        class file for the outer class may be found, but the class
+        file for the inner class may not be present.  In that
+        situation, the compiler cannot fall back to the original
+        source, having already read the outer class, so we must
+        prevent that situation.  */
+      for (current = ctxp->class_list; 
+          current; 
+          current = TREE_CHAIN (current))
+       reversed_class_list
+         = tree_cons (NULL_TREE, current, reversed_class_list);
+
+      for (current = reversed_class_list; 
+          current; 
+          current = TREE_CHAIN (current))
+       {
+         current_class = TREE_TYPE (TREE_VALUE (current));
          outgoing_cpool = TYPE_CPOOL (current_class);
          if (flag_emit_class_files)
            write_classfile (current_class);
          if (flag_emit_xref)
            expand_xref (current_class);
          else if (! flag_syntax_only)
-           finish_class ();
+           {
+             java_expand_method_bodies (current_class);
+             finish_class ();
+           }
        }
     }
 }
@@ -8879,7 +9236,10 @@ resolve_expression_name (id, orig)
                      static_ref_err (id, DECL_NAME (decl), current_class);
                      return error_mark_node;
                    }
-                 return build_outer_field_access (id, decl);
+                 access = build_outer_field_access (id, decl);
+                 if (orig)
+                   *orig = access;
+                 return access;
                }
 
              /* Otherwise build what it takes to access the field */
@@ -8908,8 +9268,15 @@ resolve_expression_name (id, orig)
     }
 
   /* We've got an error here */
-  parse_error_context (id, "Undefined variable `%s'", 
-                      IDENTIFIER_POINTER (name));
+  if (INNER_CLASS_TYPE_P (current_class))
+    parse_error_context (id, 
+                        "Local variable `%s' can't be accessed from within the inner class `%s' unless it is declared final",
+                        IDENTIFIER_POINTER (name),
+                        IDENTIFIER_POINTER (DECL_NAME
+                                            (TYPE_NAME (current_class))));
+  else
+    parse_error_context (id, "Undefined variable `%s'", 
+                        IDENTIFIER_POINTER (name));
 
   return error_mark_node;
 }
@@ -8925,7 +9292,7 @@ static_ref_err (wfl, field_id, class_type)
      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type))));
 }
 
-/* 15.10.1 Field Acess Using a Primary and/or Expression Name.
+/* 15.10.1 Field Access Using a Primary and/or Expression Name.
    We return something suitable to generate the field access. We also
    return the field decl in FIELD_DECL and its type in FIELD_TYPE.  If
    recipient's address can be null. */
@@ -9091,6 +9458,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
          *where_found = patch_method_invocation (qual_wfl, decl, type,
                                                  from_super,
                                                  &is_static, &ret_decl);
+         from_super = 0;
          if (*where_found == error_mark_node)
            {
              RESTORE_THIS_AND_CURRENT_CLASS;
@@ -9128,7 +9496,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
             forcoming function's argument. */
          if (previous_call_static && is_static)
            {
-             decl = build (COMPOUND_EXPR, type, decl, *where_found);
+             decl = build (COMPOUND_EXPR, TREE_TYPE (*where_found),
+                           decl, *where_found);
              TREE_SIDE_EFFECTS (decl) = 1;
            }
          else
@@ -9206,7 +9575,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
       previous_call_static = 0;
 
       /* It can be the keyword THIS */
-      if (EXPR_WFL_NODE (qual_wfl) == this_identifier_node)
+      if (TREE_CODE (qual_wfl) == EXPR_WITH_FILE_LOCATION
+         && EXPR_WFL_NODE (qual_wfl) == this_identifier_node)
        {
          if (!current_this)
            {
@@ -9220,7 +9590,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              parse_error_context (wfl, "Can't reference `this' before the superclass constructor has been called");
              return 1;
            }
-         /* We have to generate code for intermediate acess */
+         /* We have to generate code for intermediate access */
          if (!from_type || TREE_TYPE (TREE_TYPE (current_this)) == type)
            {
              *where_found = decl = current_this;
@@ -9257,7 +9627,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
        }
 
       /* 15.10.2 Accessing Superclass Members using SUPER */
-      if (EXPR_WFL_NODE (qual_wfl) == super_identifier_node)
+      if (TREE_CODE (qual_wfl) == EXPR_WITH_FILE_LOCATION
+         && EXPR_WFL_NODE (qual_wfl) == super_identifier_node)
        {
          tree node;
          /* Check on the restricted use of SUPER */
@@ -9284,11 +9655,12 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
         assume a variable/class name was meant. */
       if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
        {
-         tree name = resolve_package (wfl, &q);
-         if (name)
+         tree name;
+         if ((decl = resolve_package (wfl, &q, &name)))
            {
              tree list;
-             *where_found = decl = resolve_no_layout (name, qual_wfl);
+             *where_found = decl;
+
              /* We want to be absolutely sure that the class is laid
                  out. We're going to search something inside it. */
              *type_found = type = TREE_TYPE (decl);
@@ -9318,17 +9690,16 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              else
                parse_error_context
                  (qual_wfl, "Undefined variable or class name: `%s'",
-                  IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)));
+                  IDENTIFIER_POINTER (name));
              return 1;
            }
        }
 
       /* We have a type name. It's been already resolved when the
         expression was qualified. */
-      else if (RESOLVE_TYPE_NAME_P (qual_wfl))
+      else if (RESOLVE_TYPE_NAME_P (qual_wfl) && QUAL_RESOLUTION (q))
        {
-         if (!(decl = QUAL_RESOLUTION (q)))
-           return 1;           /* Error reported already */
+         decl = QUAL_RESOLUTION (q);
 
          /* Sneak preview. If next we see a `new', we're facing a
             qualification with resulted in a type being selected
@@ -9356,7 +9727,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
          type = TREE_TYPE (decl);
          from_type = 1;
        }
-      /* We resolve and expression name */
+      /* We resolve an expression name */
       else 
        {
          tree field_decl = NULL_TREE;
@@ -9392,6 +9763,16 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                }
            }
 
+         /* Report and error if we're using a numerical litteral as a
+             qualifier. It can only be an INTEGER_CST. */
+         else if (TREE_CODE (qual_wfl) == INTEGER_CST)
+           {
+             parse_error_context
+               (wfl, "Can't use type `%s' as a qualifier",
+                lang_printable_name (TREE_TYPE (qual_wfl), 0));
+             return 1;
+           }
+
          /* We have to search for a field, knowing the type of its
              container. The flag FROM_TYPE indicates that we resolved
              the last member of the expression as a type name, which
@@ -9409,7 +9790,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                    (qual_wfl, "Attempt to reference field `%s' in `%s %s'",
                     IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)),
                     lang_printable_name (type, 0),
-                    IDENTIFIER_POINTER (DECL_NAME (field_decl)));
+                    IDENTIFIER_POINTER (DECL_NAME (decl)));
                  return 1;
                }
              
@@ -9588,7 +9969,7 @@ not_accessible_p (reference, member, where, from_super)
       if (where && !inherits_from_p (reference, where))
        return 1;
 
-      /* Otherwise, access is granted if occuring from the class where
+      /* Otherwise, access is granted if occurring from the class where
         member is declared or a subclass of it. Find the right
         context to perform the check */
       if (PURE_INNER_CLASS_TYPE_P (reference))
@@ -9617,7 +9998,7 @@ not_accessible_p (reference, member, where, from_super)
       return 1;
     }
 
-  /* Default access are permitted only when occuring within the
+  /* Default access are permitted only when occurring within the
      package in which the type (REFERENCE) is declared. In other words,
      REFERENCE is defined in the current package */
   if (ctxp->package)
@@ -9646,32 +10027,37 @@ check_deprecation (wfl, decl)
          strcpy (the, "method");
          break;
        case FIELD_DECL:
+       case VAR_DECL:
          strcpy (the, "field");
          break;
        case TYPE_DECL:
-         strcpy (the, "class");
-         break;
+         parse_warning_context (wfl, "The class `%s' has been deprecated",
+                                IDENTIFIER_POINTER (DECL_NAME (decl)));
+         return;
        default:
          abort ();
        }
-      parse_warning_context 
-       (wfl, "The %s `%s' in class `%s' has been deprecated", 
-        the, lang_printable_name (decl, 0),
-        IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))));
+      /* Don't issue a message if the context as been deprecated as a
+         whole. */
+      if (! CLASS_DEPRECATED (TYPE_NAME (DECL_CONTEXT (decl))))
+       parse_warning_context 
+         (wfl, "The %s `%s' in class `%s' has been deprecated", 
+          the, lang_printable_name (decl, 0),
+          IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))));
     }
 }
 
 /* Returns 1 if class was declared in the current package, 0 otherwise */
 
+static GTY(()) tree cicp_cache;
 static int
 class_in_current_package (class)
      tree class;
 {
-  static tree cache = NULL_TREE;
   int qualified_flag;
   tree left;
 
-  if (cache == class)
+  if (cicp_cache == class)
     return 1;
 
   qualified_flag = QUALIFIED_P (DECL_NAME (TYPE_NAME (class)));
@@ -9692,15 +10078,7 @@ class_in_current_package (class)
   breakdown_qualified (&left, NULL, DECL_NAME (TYPE_NAME (class)));
   if (ctxp->package == left)
     {
-      static int initialized_p;
-      /* Register CACHE with the garbage collector.  */
-      if (!initialized_p)
-       {
-         ggc_add_tree_root (&cache, 1);
-         initialized_p = 1;
-       }
-
-      cache = class;
+      cicp_cache = class;
       return 1;
     }
   return 0;
@@ -9770,6 +10148,12 @@ patch_method_invocation (patch, primary, where, from_super,
       qualify_ambiguous_name (wfl);
       resolved = resolve_field_access (wfl, NULL, NULL);
 
+      if (TREE_CODE (resolved) == VAR_DECL && FIELD_STATIC (resolved)
+         && FIELD_FINAL (resolved) 
+         && !inherits_from_p (DECL_CONTEXT (resolved), current_class)
+         && !flag_emit_class_files && !flag_emit_xref)
+       resolved = build_class_init (DECL_CONTEXT (resolved), resolved);
+
       if (resolved == error_mark_node)
        PATCH_METHOD_RETURN_ERROR ();
 
@@ -9934,7 +10318,8 @@ patch_method_invocation (patch, primary, where, from_super,
       /* Check for inner classes creation from illegal contexts */
       if (lc && (INNER_CLASS_TYPE_P (class_to_search)
                 && !CLASS_STATIC (TYPE_NAME (class_to_search)))
-         && INNER_ENCLOSING_SCOPE_CHECK (class_to_search))
+         && INNER_ENCLOSING_SCOPE_CHECK (class_to_search)
+         && !DECL_INIT_P (current_function_decl))
        {
          parse_error_context 
            (wfl, "No enclosing instance for inner class `%s' is in scope%s",
@@ -9968,7 +10353,7 @@ patch_method_invocation (patch, primary, where, from_super,
             - LIST is non static. It's invocation is transformed from
               x(a1,....,an) into access$<n>(this$<n>,a1,...,an).
             - LIST is static. It's invocation is transformed from
-              x(a1,....,an) into TYPEOF(this$<n>).x(a1,....an).
+              x(a1,....,an) into TYPE_OF(this$<n>).x(a1,....an).
 
             Of course, this$<n> can be abitrary complex, ranging from
             this$0 (the immediate outer context) to 
@@ -9978,7 +10363,8 @@ patch_method_invocation (patch, primary, where, from_super,
             this_arg has to be moved into the (then generated) stub
             argument list. In the meantime, the selected function
             might have be replaced by a generated stub. */
-         if (maybe_use_access_method (is_super_init, &list, &this_arg))
+         if (!primary &&
+             maybe_use_access_method (is_super_init, &list, &this_arg))
            {
              args = tree_cons (NULL_TREE, this_arg, args);
              this_arg = NULL_TREE; /* So it doesn't get chained twice */
@@ -9999,15 +10385,15 @@ patch_method_invocation (patch, primary, where, from_super,
       /* Calls to clone() on array types are permitted as a special-case. */
       && !is_array_clone_call)
     {
-      const char *fct_name = IDENTIFIER_POINTER (DECL_NAME (list));
-      const char *access =
+      const char *const fct_name = IDENTIFIER_POINTER (DECL_NAME (list));
+      const char *const access =
        java_accstring_lookup (get_access_flags_from_decl (list));
-      const char *klass =
+      const char *const klass =
        IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list))));
-      const char *refklass =
+      const char *const refklass =
        IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
-      const char *what = (DECL_CONSTRUCTOR_P (list)
-                         ? "constructor" : "method");
+      const char *const what = (DECL_CONSTRUCTOR_P (list)
+                               ? "constructor" : "method");
       /* FIXME: WFL yields the wrong message here but I don't know
         what else to use.  */
       parse_error_context (wfl,
@@ -10015,7 +10401,13 @@ patch_method_invocation (patch, primary, where, from_super,
                           access, what, klass, fct_name, refklass);
       PATCH_METHOD_RETURN_ERROR ();
     }
-  check_deprecation (wfl, list);
+
+  /* Deprecation check: check whether the method being invoked or the
+     instance-being-created's type are deprecated. */
+  if (TREE_CODE (patch) == NEW_CLASS_EXPR)
+    check_deprecation (wfl, TYPE_NAME (DECL_CONTEXT (list)));
+  else
+    check_deprecation (wfl, list);
 
   /* If invoking a innerclass constructor, there are hidden parameters
      to pass */
@@ -10062,25 +10454,15 @@ patch_method_invocation (patch, primary, where, from_super,
 
   /* 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)))
+     constructor is one of an inner class). */
+  if ((is_super_init || 
+       (TREE_CODE (patch) == CALL_EXPR && name == this_identifier_node))
+      && 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);
-       }
+      tree dest = TYPE_NAME (DECL_CONTEXT (list));
+      tree extra_arg = 
+       build_access_to_thisn (current_class, DECL_CONTEXT (dest), 0);
+      extra_arg = java_complete_tree (extra_arg);
       args = tree_cons (NULL_TREE, extra_arg, args);
     }
 
@@ -10108,6 +10490,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;
@@ -10123,9 +10507,9 @@ patch_method_invocation (patch, primary, where, from_super,
       /* Generate the code used to initialize fields declared with an
         initialization statement and build a compound statement along
         with the super constructor invocation. */
+      CAN_COMPLETE_NORMALLY (patch) = 1;
       patch = build (COMPOUND_EXPR, void_type_node, patch,
                     java_complete_tree (finit_call));
-      CAN_COMPLETE_NORMALLY (patch) = 1;
     }
   return patch;
 }
@@ -10169,7 +10553,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
@@ -10255,7 +10640,6 @@ patch_invoke (patch, method, args)
     func = method;
   else
     {
-      tree signature = build_java_signature (TREE_TYPE (method));
       switch (invocation_mode (method, CALL_USING_SUPER (patch)))
        {
        case INVOKE_VIRTUAL:
@@ -10280,9 +10664,12 @@ patch_invoke (patch, method, args)
 
        case INVOKE_SUPER:
        case INVOKE_STATIC:
-         func = build_known_method_ref (method, TREE_TYPE (method),
-                                        DECL_CONTEXT (method),
-                                        signature, args);
+         {
+           tree signature = build_java_signature (TREE_TYPE (method));
+           func = build_known_method_ref (method, TREE_TYPE (method),
+                                          DECL_CONTEXT (method),
+                                          signature, args);
+         }
          break;
 
        case INVOKE_INTERFACE:
@@ -10301,6 +10688,7 @@ patch_invoke (patch, method, args)
   TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method));
   TREE_OPERAND (patch, 0) = func;
   TREE_OPERAND (patch, 1) = args;
+  patch = check_for_builtin (method, patch);
   original_call = patch;
 
   /* We're processing a `new TYPE ()' form. New is called and its
@@ -10312,6 +10700,8 @@ patch_invoke (patch, method, args)
     {
       tree class = DECL_CONTEXT (method);
       tree c1, saved_new, size, new;
+      tree alloc_node;
+
       if (flag_emit_class_files || flag_emit_xref)
        {
          TREE_TYPE (patch) = build_pointer_type (class);
@@ -10320,8 +10710,11 @@ patch_invoke (patch, method, args)
       if (!TYPE_SIZE (class))
        safe_layout_class (class);
       size = size_in_bytes (class);
+      alloc_node =
+       (class_has_finalize_method (class) ? alloc_object_node
+                                          : alloc_no_finalizer_node);
       new = build (CALL_EXPR, promote_type (class),
-                  build_address_of (alloc_object_node),
+                  build_address_of (alloc_node),
                   tree_cons (NULL_TREE, build_class_ref (class),
                              build_tree_list (NULL_TREE, 
                                               size_in_bytes (class))),
@@ -10342,6 +10735,30 @@ patch_invoke (patch, method, args)
       TREE_SIDE_EFFECTS (patch) = 1;
     }
 
+  /* In order to be able to modify PATCH later, we SAVE_EXPR it and
+     put it as the first expression of a COMPOUND_EXPR. The second
+     expression being an empty statement to be later patched if
+     necessary. We remember a TREE_LIST (the PURPOSE is the method,
+     the VALUE is the compound) in a hashtable and return a
+     COMPOUND_EXPR built so that the result of the evaluation of the
+     original PATCH node is returned. */
+  if (STATIC_CLASS_INIT_OPT_P ()
+      && current_function_decl && METHOD_STATIC (method))
+    {
+      tree list;
+      tree fndecl = current_function_decl;
+      tree save = save_expr (patch);
+      tree type = TREE_TYPE (patch);
+
+      patch = build (COMPOUND_EXPR, type, save, empty_stmt_node);
+      list = tree_cons (method, patch,
+                       DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl));
+
+      DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl) = list;
+
+      patch = build (COMPOUND_EXPR, type, patch, save);
+    }
+
   return patch;
 }
 
@@ -10407,7 +10824,14 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
      know the arguments' types. */
 
   if (lc && ANONYMOUS_CLASS_P (class))
-    craft_constructor (TYPE_NAME (class), atl);
+    {
+      tree saved_current_class;
+      tree mdecl = craft_constructor (TYPE_NAME (class), atl);
+      saved_current_class = current_class;
+      current_class = class;
+      fix_constructors (mdecl);
+      current_class = saved_current_class;
+    }
 
   /* Find all candidates and then refine the list, searching for the
      most specific method. */
@@ -10462,7 +10886,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
      int lc;
      tree class, name, arglist;
 {
-  static struct hash_table t, *searched_classes = NULL;
+  static htab_t searched_classes;
   static int search_not_done = 0;
   tree list = NULL_TREE, all_list = NULL_TREE;
 
@@ -10470,20 +10894,17 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
      already. */
   if (searched_classes)
     {
-      if (hash_lookup (searched_classes, 
-                      (const hash_table_key) class, FALSE, NULL))
-       return NULL;
+      if (htab_find (searched_classes, class) != NULL)
+       return NULL;
     }
   else
     {
-      hash_table_init (&t, hash_newfunc, java_hash_hash_tree_node,
-                      java_hash_compare_tree_node);
-      searched_classes = &t;
+      searched_classes = htab_create (10, htab_hash_pointer,
+                                     htab_eq_pointer, NULL);
     }
     
   search_not_done++;
-  hash_lookup (searched_classes, 
-              (const hash_table_key) class, TRUE, NULL);
+  *htab_find_slot (searched_classes, class, INSERT) = class;
 
   if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class))
     {
@@ -10516,10 +10937,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)
@@ -10563,15 +10984,13 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
     {
       if (!lc
          && TYPE_METHODS (object_type_node)
-         && !hash_lookup (searched_classes, 
-                           (const hash_table_key) object_type_node, 
-                           FALSE, NULL))
+         && htab_find (searched_classes, object_type_node) == NULL)
        {
           search_applicable_methods_list (lc, 
                                           TYPE_METHODS (object_type_node),
                                           name, arglist, &list, &all_list);
         }
-      hash_table_free (searched_classes);
+      htab_delete (searched_classes);
       searched_classes = NULL;
     }
 
@@ -10701,25 +11120,15 @@ find_most_specific_methods_list (list)
    corresponding parameter of M1. Implementation expects M2_OR_ARGLIST
    to change less often than M1. */
 
+static GTY(()) tree m2_arg_value;
+static GTY(()) tree m2_arg_cache;
+
 static int
 argument_types_convertible (m1, m2_or_arglist)
     tree m1, m2_or_arglist;
 {
-  static tree m2_arg_value = NULL_TREE;
-  static tree m2_arg_cache = NULL_TREE;
-  static int initialized_p;
-
   register tree m1_arg, m2_arg;
 
-  /* Register M2_ARG_VALUE and M2_ARG_CACHE with the garbage
-     collector.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&m2_arg_value, 1);
-      ggc_add_tree_root (&m2_arg_cache, 1);
-      initialized_p = 1;
-    }
-
   SKIP_THIS_AND_ARTIFICIAL_PARMS (m1_arg, m1)
 
   if (m2_arg_value == m2_or_arglist)
@@ -10784,7 +11193,9 @@ qualify_ambiguous_name (id)
       {
       case CALL_EXPR:
        qual_wfl = TREE_OPERAND (qual_wfl, 0);
-       if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION)
+       if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION
+           || (EXPR_WFL_QUALIFICATION (qual_wfl)
+               && TREE_CODE (EXPR_WFL_QUALIFICATION (qual_wfl)) == TREE_LIST))
          {
            qual = EXPR_WFL_QUALIFICATION (qual_wfl);
            qual_wfl = QUAL_WFL (qual);
@@ -10828,7 +11239,17 @@ qualify_ambiguous_name (id)
 
     else if (code == INTEGER_CST)
       name = qual_wfl;
-    
+
+    else if (code == CONVERT_EXPR &&
+            TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
+      name = TREE_OPERAND (qual_wfl, 0);
+
+    else if (code == CONVERT_EXPR
+            && TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == CALL_EXPR
+            && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0))
+                == EXPR_WITH_FILE_LOCATION))
+      name = TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0);
+
     else if ((code == ARRAY_REF || code == CALL_EXPR || code == MODIFY_EXPR) &&
             TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
       name = EXPR_WFL_NODE (TREE_OPERAND (qual_wfl, 0));
@@ -10843,7 +11264,7 @@ qualify_ambiguous_name (id)
        qual_wfl = QUAL_WFL (qual);
        again = 1;
       }
-    else 
+    else
       {
        name = EXPR_WFL_NODE (qual_wfl);
        if (!name)
@@ -10871,8 +11292,10 @@ qualify_ambiguous_name (id)
        qual_wfl = QUAL_WFL (qual);
        if (TREE_CODE (qual_wfl) == CALL_EXPR)
          again = 1;
-       else
+       else if (TREE_CODE (qual_wfl) == EXPR_WITH_FILE_LOCATION)
          name = EXPR_WFL_NODE (qual_wfl);
+       else if (TREE_CODE (qual_wfl) == NEW_CLASS_EXPR)
+         name = TREE_OPERAND (qual_wfl, 0);
        this_found = 1;
       }
     /* If we have a SUPER, we set the context accordingly */
@@ -10924,9 +11347,12 @@ qualify_ambiguous_name (id)
        of the compilation unit containing NAME,
      - NAME is declared by exactly on type-import-on-demand declaration
      of the compilation unit containing NAME. 
-     - NAME is actually a STRING_CST. */
-  else if (TREE_CODE (name) == STRING_CST || TREE_CODE (name) == INTEGER_CST
-          || (decl = resolve_and_layout (name, NULL_TREE)))
+     - NAME is actually a STRING_CST.
+     This can't happen if the expression was qualified by `this.' */
+  else if (! this_found &&
+          (TREE_CODE (name) == STRING_CST ||
+           TREE_CODE (name) == INTEGER_CST ||
+           (decl = resolve_and_layout (name, NULL_TREE))))
     {
       RESOLVE_TYPE_NAME_P (qual_wfl) = 1;
       QUAL_RESOLUTION (qual) = decl;
@@ -11046,17 +11472,16 @@ java_complete_tree (node)
       DECL_INITIAL (node) = value;
       if (value != NULL_TREE)
        {
-         /* fold_constant_for_init sometimes widen the original type
-             of the constant (i.e. byte to int.) It's not desirable,
+         /* fold_constant_for_init sometimes widens the original type
+             of the constant (i.e. byte to int). It's not desirable,
              especially if NODE is a function argument. */
-         if (TREE_CODE (value) == INTEGER_CST
+         if ((TREE_CODE (value) == INTEGER_CST
+              || TREE_CODE (value) == REAL_CST)
              && TREE_TYPE (node) != TREE_TYPE (value))
            return convert (TREE_TYPE (node), value);
          else
            return value;
        }
-      else
-        DECL_FIELD_FINAL_IUD (node) = 0;
     }
   return node;
 }
@@ -11212,21 +11637,6 @@ java_complete_lhs (node)
       TREE_TYPE (node) = TREE_TYPE (TREE_OPERAND (node, 0));
       return node;
 
-    case CLEANUP_POINT_EXPR:
-      COMPLETE_CHECK_OP_0 (node);
-      TREE_TYPE (node) = void_type_node;
-      CAN_COMPLETE_NORMALLY (node) = 
-       CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0));
-      return node;
-
-    case WITH_CLEANUP_EXPR:
-      COMPLETE_CHECK_OP_0 (node);
-      COMPLETE_CHECK_OP_2 (node);
-      CAN_COMPLETE_NORMALLY (node) = 
-       CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0));
-      TREE_TYPE (node) = void_type_node;
-      return node;
-
     case LABELED_BLOCK_EXPR:
       PUSH_LABELED_BLOCK (node);
       if (LABELED_BLOCK_BODY (node))
@@ -11264,6 +11674,9 @@ java_complete_lhs (node)
          cn = fold_constant_for_init (DECL_INITIAL (TREE_OPERAND (cn, 1)),
                                       TREE_OPERAND (cn, 1));
        }
+      /* Accept final locals too. */
+      else if (TREE_CODE (cn) == VAR_DECL && DECL_FINAL (cn))
+       cn = fold_constant_for_init (DECL_INITIAL (cn), cn);
 
       if (!TREE_CONSTANT (cn) && !flag_emit_xref)
        {
@@ -11287,10 +11700,15 @@ java_complete_lhs (node)
        }
 
       cn = fold (convert (int_type_node, cn));
+      TREE_CONSTANT_OVERFLOW (cn) = 0;
+      CAN_COMPLETE_NORMALLY (cn) = 1;
+
+      /* Save the label on a list so that we can later check for
+        duplicates.  */
+      case_label_list = tree_cons (node, cn, case_label_list);
 
-      /* Multiple instance of a case label bearing the same
-        value is checked during code generation. The case
-        expression is allright so far. */
+      /* Multiple instance of a case label bearing the same value is
+        checked later. The case expression is all right so far. */
       if (TREE_CODE (cn) == VAR_DECL)
        cn = DECL_INITIAL (cn);
       TREE_OPERAND (node, 0) = cn;
@@ -11396,14 +11814,28 @@ java_complete_lhs (node)
              if (TREE_CODE (nn) != EXIT_EXPR)
                {
                  SET_WFL_OPERATOR (wfl_operator, node, wfl_op2);
-                 parse_error_context (wfl_operator, "Unreachable statement");
+                 if (SUPPRESS_UNREACHABLE_ERROR (nn))
+                   {
+                     /* Perhaps this warning should have an
+                        associated flag.  The code being compiled is
+                        pedantically correct, but useless.  */
+                     parse_warning_context (wfl_operator,
+                                            "Unreachable statement");
+                   }
+                 else
+                   parse_error_context (wfl_operator,
+                                        "Unreachable statement");
                }
            }
          TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1));
          if (TREE_OPERAND (node, 1) == error_mark_node)
            return error_mark_node;
+         /* Even though we might allow the case where the first
+            operand doesn't return normally, we still should compute
+            CAN_COMPLETE_NORMALLY correctly.  */
          CAN_COMPLETE_NORMALLY (node)
-           = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1));
+           = (CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0))
+              && CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)));
        }
       TREE_TYPE (node) = TREE_TYPE (TREE_OPERAND (node, 1));
       break;
@@ -11544,17 +11976,35 @@ java_complete_lhs (node)
          
          value = fold_constant_for_init (nn, nn);
 
-         if (value != NULL_TREE)
+         /* When we have a primitype type, or a string and we're not
+             emitting a class file, we actually don't want to generate
+             anything for the assignment. */
+         if (value != NULL_TREE &&
+             (JPRIMITIVE_TYPE_P (TREE_TYPE (value)) || 
+              (TREE_TYPE (value) == string_ptr_type_node &&
+               ! flag_emit_class_files)))
            {
-             tree type = TREE_TYPE (value);
-             if (JPRIMITIVE_TYPE_P (type) || 
-                 (type == string_ptr_type_node && ! flag_emit_class_files))
-               return empty_stmt_node;
+             /* Prepare node for patch_assignment */
+             TREE_OPERAND (node, 1) = value;
+             /* Call patch assignment to verify the assignment */
+             if (patch_assignment (node, wfl_op1) == error_mark_node)
+               return error_mark_node;
+             /* Set DECL_INITIAL properly (a conversion might have
+                 been decided by patch_assignment) and return the
+                 empty statement. */
+             else
+               {
+                 tree patched = patch_string (TREE_OPERAND (node, 1));
+                 if (patched)
+                   DECL_INITIAL (nn) = patched;
+                 else
+                   DECL_INITIAL (nn) = TREE_OPERAND (node, 1);
+                 DECL_FIELD_FINAL_IUD (nn) = 1;
+                 return empty_stmt_node;
+               }
            }
          if (! flag_emit_class_files)
            DECL_INITIAL (nn) = NULL_TREE;
-         if (CLASS_FINAL_VARIABLE_P (nn))
-           DECL_FIELD_FINAL_IUD (nn) = 0;
        }
       wfl_op2 = TREE_OPERAND (node, 1);
 
@@ -11632,13 +12082,26 @@ java_complete_lhs (node)
        }
       else
        {
-         node = patch_assignment (node, wfl_op1, wfl_op2);
+         node = patch_assignment (node, wfl_op1);
+         if (node == error_mark_node)
+           return error_mark_node;
          /* Reorganize the tree if necessary. */
          if (flag && (!JREFERENCE_TYPE_P (TREE_TYPE (node)) 
                       || JSTRING_P (TREE_TYPE (node))))
            node = java_refold (node);
        }
-      
+
+      /* Seek to set DECL_INITIAL to a proper value, since it might have
+        undergone a conversion in patch_assignment. We do that only when
+        it's necessary to have DECL_INITIAL properly set. */
+      nn = TREE_OPERAND (node, 0);
+      if (TREE_CODE (nn) == VAR_DECL 
+         && DECL_INITIAL (nn) && CONSTANT_VALUE_P (DECL_INITIAL (nn))
+         && FIELD_STATIC (nn) && FIELD_FINAL (nn) 
+         && (JPRIMITIVE_TYPE_P (TREE_TYPE (nn))
+             || TREE_TYPE (nn) == string_ptr_type_node))
+       DECL_INITIAL (nn) = TREE_OPERAND (node, 1);
+
       CAN_COMPLETE_NORMALLY (node) = 1;
       return node;
 
@@ -11789,16 +12252,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'
@@ -11837,8 +12290,6 @@ complete_function_arguments (node)
         `+' operator. Build `parm.toString()' and expand it. */
       if ((temp = patch_string (parm)))
        parm = temp;
-      /* Inline PRIMTYPE.TYPE read access */
-      parm = maybe_build_primttype_type_ref (parm, wfl);
 
       TREE_VALUE (cn) = parm;
     }
@@ -11877,7 +12328,7 @@ build_expr_block (body, decls)
   return node;
 }
 
-/* Create a new function block and link it approriately to current
+/* Create a new function block and link it appropriately to current
    function block chain */
 
 static tree
@@ -12087,339 +12538,124 @@ build_assignment (op, op_location, lhs, rhs)
   return assignment;
 }
 
-/* Print an INTEGER_CST node in a static buffer, and return the buffer. */
-
-char *
-print_int_node (node)
-    tree node;
+/* Print an INTEGER_CST node as decimal in a static buffer, and return
+   the buffer.  This is used only for string conversion.  */
+static char *
+string_convert_int_cst (node)
+     tree node;
 {
-  static char buffer [80];
-  if (TREE_CONSTANT_OVERFLOW (node))
-    sprintf (buffer, "<overflow>");
-    
-  if (TREE_INT_CST_HIGH (node) == 0)
-    sprintf (buffer, HOST_WIDE_INT_PRINT_UNSIGNED,
-            TREE_INT_CST_LOW (node));
-  else if (TREE_INT_CST_HIGH (node) == -1
-          && TREE_INT_CST_LOW (node) != 0)
-    {
-      buffer [0] = '-';
-      sprintf (&buffer [1], HOST_WIDE_INT_PRINT_UNSIGNED,
-              -TREE_INT_CST_LOW (node));
-    }
-  else
-    sprintf (buffer, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
-            TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node));
-
-  return buffer;
-}
+  static char buffer[80];
 
-\f
+  unsigned HOST_WIDE_INT lo = TREE_INT_CST_LOW (node);
+  unsigned HOST_WIDE_INT hi = TREE_INT_CST_HIGH (node);
+  char *p = buffer + sizeof (buffer) - 1;
+  int neg = 0;
 
-/* This section of the code handle assignment check with FINAL
-   variables.  */
+  unsigned HOST_WIDE_INT hibit = (((unsigned HOST_WIDE_INT) 1)
+                                 << (HOST_BITS_PER_WIDE_INT - 1));
 
-static void
-reset_static_final_variable_assignment_flag (class)
-     tree class;
-{
-  tree field;
-  for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
-    if (CLASS_FINAL_VARIABLE_P (field))
-      DECL_FIELD_FINAL_LIIC (field) = 0;
-}
+  *p-- = '\0';
 
-/* Figure whether all final static variable have been initialized.  */
-
-static void
-check_static_final_variable_assignment_flag (class)
-     tree class;
-{
-  tree field;
+  /* If negative, note the fact and negate the value.  */
+  if ((hi & hibit))
+    {
+      lo = ~lo;
+      hi = ~hi;
+      if (++lo == 0)
+       ++hi;
+      neg = 1;
+    }
 
-  for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
-    if (CLASS_FINAL_VARIABLE_P (field)
-       && !DECL_FIELD_FINAL_IUD (field) && !DECL_FIELD_FINAL_LIIC (field))
-      parse_error_context
-       (DECL_FIELD_FINAL_WFL (field),
-        "Blank static final variable `%s' may not have been initialized",
-        IDENTIFIER_POINTER (DECL_NAME (field)));
-}
+  /* Divide by 10 until there are no bits left.  */
+  while (hi || lo)
+    {
+      unsigned HOST_WIDE_INT acc = 0;
+      unsigned HOST_WIDE_INT outhi = 0, outlo = 0;
+      unsigned int i;
 
-/* This function marks all final variable locally unassigned.  */
+      /* Use long division to compute the result and the remainder.  */
+      for (i = 0; i < 2 * HOST_BITS_PER_WIDE_INT; ++i)
+       {
+         /* Shift a bit into accumulator.  */
+         acc <<= 1;
+         if ((hi & hibit))
+           acc |= 1;
 
-static void
-reset_final_variable_local_assignment_flag (class)
-     tree class;
-{
-  tree field;
-  for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
-    if (FINAL_VARIABLE_P (field))
-      DECL_FIELD_FINAL_LIIC (field) = 0;
-}
+         /* Shift the value.  */
+         hi <<= 1;
+         if ((lo & hibit))
+           hi |= 1;
+         lo <<= 1;
 
-/* Figure whether all final variables have beem initialized in MDECL
-   and mark MDECL accordingly.  */
+         /* Shift the correct bit into the result.  */
+         outhi <<= 1;
+         if ((outlo & hibit))
+           outhi |= 1;
+         outlo <<= 1;
+         if (acc >= 10)
+           {
+             acc -= 10;
+             outlo |= 1;
+           }
+       }
 
-static void
-check_final_variable_local_assignment_flag (class, mdecl)
-     tree class;
-     tree mdecl;
-{
-  tree field;
-  int initialized = 0;
-  int non_initialized = 0; 
+      /* FIXME: ASCII assumption.  */
+      *p-- = '0' + acc;
 
-  if (DECL_FUNCTION_SYNTHETIC_CTOR (mdecl))
-    return;
+      hi = outhi;
+      lo = outlo;
+    }
 
-  /* First find out whether all final variables or no final variable
-     are initialized in this ctor. We don't take into account final
-     variable that have been initialized upon declaration.  */
-  for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
-    if (FINAL_VARIABLE_P (field) && !DECL_FIELD_FINAL_IUD (field))
-      {
-       if (DECL_FIELD_FINAL_LIIC (field))
-         initialized++;
-       else
-         non_initialized++;
-      }
+  if (neg)
+    *p-- = '-';
 
-  /* There were no non initialized variable and no initialized variable.
-     This ctor is fine. */
-  if (!non_initialized && !initialized)
-    DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 1;
-  /* If no variables have been initialized, that fine. We'll check
-     later whether this ctor calls a constructor which initializes
-     them. We mark the ctor as not initializing all its finals. */
-  else if (initialized == 0)
-    DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 0;
-  /* If we have a mixed bag, then we have a problem. We need to report
-     all the variables we're not initializing.  */
-  else if (initialized && non_initialized)
-    {
-      DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 0;
-      for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
-       if (FIELD_FINAL (field)
-           && !DECL_FIELD_FINAL_IUD (field) && !DECL_FIELD_FINAL_LIIC (field))
-         {
-           parse_error_context 
-             (lookup_cl (mdecl),
-              "Blank final variable `%s' may not have been initialized in this constructor",
-              IDENTIFIER_POINTER (DECL_NAME (field)));
-           DECL_FIELD_FINAL_IERR (field) = 1;
-         }
-    }
-  /* Otherwise we know this ctor is initializing all its final
-     variable. We mark it so. */
-  else
-    DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 1;
+  return p + 1;
 }
 
-/* This function recurses in a simple what through STMT and stops when
-   it finds a constructor call. It then verifies that the called
-   constructor initialized its final properly. Return 1 upon success,
-   0 or -1 otherwise.  */
-
-static int
-check_final_variable_indirect_assignment (stmt)
-     tree stmt;
+/* Print an INTEGER_CST node in a static buffer, and return the
+   buffer.  This is used only for error handling.  */
+char *
+print_int_node (node)
+    tree node;
 {
-  int res;
-  switch (TREE_CODE (stmt))
+  static char buffer [80];
+  if (TREE_CONSTANT_OVERFLOW (node))
+    sprintf (buffer, "<overflow>");
+    
+  if (TREE_INT_CST_HIGH (node) == 0)
+    sprintf (buffer, HOST_WIDE_INT_PRINT_UNSIGNED,
+            TREE_INT_CST_LOW (node));
+  else if (TREE_INT_CST_HIGH (node) == -1
+          && TREE_INT_CST_LOW (node) != 0)
     {
-    case EXPR_WITH_FILE_LOCATION:
-      return check_final_variable_indirect_assignment (EXPR_WFL_NODE (stmt));
-    case COMPOUND_EXPR:
-      res = check_final_variable_indirect_assignment (TREE_OPERAND (stmt, 0));
-      if (res)
-       return res;
-      return check_final_variable_indirect_assignment (TREE_OPERAND (stmt, 1));
-    case SAVE_EXPR:
-      return check_final_variable_indirect_assignment (TREE_OPERAND (stmt, 0));
-    case CALL_EXPR:
-      {
-       tree decl = TREE_OPERAND (stmt, 0);
-       tree fbody;
-
-       if (TREE_CODE (decl) != FUNCTION_DECL)
-         decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
-       if (TREE_CODE (decl) != FUNCTION_DECL)
-         abort ();
-       if (DECL_FUNCTION_ALL_FINAL_INITIALIZED (decl))
-         return 1;
-       if (DECL_FINIT_P (decl) || DECL_CONTEXT (decl) != current_class)
-         return -1;
-       fbody = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl));
-       if (fbody == error_mark_node)
-         return -1;
-       fbody = BLOCK_EXPR_BODY (fbody);
-       return check_final_variable_indirect_assignment (fbody);
-      }
-    default:
-      break;
+      buffer [0] = '-';
+      sprintf (&buffer [1], HOST_WIDE_INT_PRINT_UNSIGNED,
+              -TREE_INT_CST_LOW (node));
     }
-  return 0;
-}
-
-/* This is the last chance to catch a final variable initialization
-   problem. This routine will report an error if a final variable was
-   never (globally) initialized and never reported as not having been
-   initialized properly. */
-
-static void
-check_final_variable_global_assignment_flag (class)
-     tree class;
-{
-  tree field, mdecl;
-  int nnctor = 0;
-
-  /* We go through all natural ctors and see whether they're
-     initializing all their final variables or not. */
-  current_function_decl = NULL_TREE; /* For the error report. */
-  for (mdecl = TYPE_METHODS (class); mdecl; mdecl = TREE_CHAIN (mdecl))
-    if (DECL_CONSTRUCTOR_P (mdecl) && ! DECL_FUNCTION_SYNTHETIC_CTOR (mdecl))
-      {
-       if (!DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl))
-         {
-           /* It doesn't. Maybe it calls a constructor that initializes
-              them.  find out. */
-           tree fbody = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl));
-           if (fbody == error_mark_node)
-             continue;
-           fbody = BLOCK_EXPR_BODY (fbody);
-           if (check_final_variable_indirect_assignment (fbody) == 1)
-             {
-               DECL_FUNCTION_ALL_FINAL_INITIALIZED (mdecl) = 1;
-               nnctor++;
-             }
-           else
-             parse_error_context
-               (lookup_cl (mdecl),
-                "Final variable initialization error in this constructor");
-         }
-       else
-         nnctor++;
-      }
-
-  /* Finally we catch final variables that never were initialized */
-  for (field = TYPE_FIELDS (class); field; field = TREE_CHAIN (field))
-    if (FINAL_VARIABLE_P (field)
-       /* If the field wasn't initialized upon declaration */
-       && !DECL_FIELD_FINAL_IUD (field)
-       /* There wasn't natural ctor in which the field could have been
-          initialized */
-       && !nnctor
-       /* If we never reported a problem with this field */
-       && !DECL_FIELD_FINAL_IERR (field))
-      {
-       current_function_decl = NULL;
-       parse_error_context
-         (DECL_FIELD_FINAL_WFL (field),
-          "Final variable `%s' hasn't been initialized upon its declaration",
-          IDENTIFIER_POINTER (DECL_NAME (field)));
-      }
+  else
+    sprintf (buffer, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+            TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node));
 
+  return buffer;
 }
 
+\f
 /* Return 1 if an assignment to a FINAL is attempted in a non suitable
    context.  */
 
-static int
-check_final_assignment (lvalue, wfl)
-     tree lvalue, wfl;
-{
-  if (TREE_CODE (lvalue) != COMPONENT_REF && !JDECL_P (lvalue))
-    return 0;
-
-  if (TREE_CODE (lvalue) == COMPONENT_REF
-      && JDECL_P (TREE_OPERAND (lvalue, 1)))
-    lvalue = TREE_OPERAND (lvalue, 1);
-
-  if (!FIELD_FINAL (lvalue))
-    return 0;
-
-  /* Now the logic. We can modify a final VARIABLE:
-     1) in finit$, (its declaration was followed by an initialization,)
-     2) consistently in each natural ctor, if it wasn't initialized in
-        finit$ or once in <clinit>.  In any other cases, an error should be
-       reported. */
-  if (DECL_FINIT_P (current_function_decl))
-    {
-      DECL_FIELD_FINAL_IUD (lvalue) = 1;
-      return 0;
-    }
-
-  if (!DECL_FUNCTION_SYNTHETIC_CTOR (current_function_decl)
-      /* Only if it wasn't given a value upon initialization */
-      && DECL_LANG_SPECIFIC (lvalue) && !DECL_FIELD_FINAL_IUD (lvalue)
-      /* If it was never assigned a value in this constructor */
-      && !DECL_FIELD_FINAL_LIIC (lvalue))
-    {
-      /* Turn the locally assigned flag on, it will be checked later
-        on to point out at discrepancies. */
-      DECL_FIELD_FINAL_LIIC (lvalue) = 1;
-      if (DECL_CLINIT_P (current_function_decl))
-       DECL_FIELD_FINAL_IUD (lvalue) = 1;
-      return 0;
-    }
-
-  /* Other problems should be reported right away. */
-  parse_error_context 
-    (wfl, "Can't %sassign a value to the final variable `%s'",
-     (FIELD_STATIC (lvalue) ? "re" : ""),
-     IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
-
-  /* Note that static field can be initialized once and only once. */
-  if (FIELD_STATIC (lvalue))
-    DECL_FIELD_FINAL_IERR (lvalue) = 1;
-
-  return 1;
-}
-
-/* Inline references to java.lang.PRIMTYPE.TYPE when accessed in
-   read. This is needed to avoid circularities in the implementation
-   of these fields in libjava. */
-
-static tree
-maybe_build_primttype_type_ref (rhs, wfl)
-    tree rhs, wfl;
-{
-  tree to_return = NULL_TREE;
-  tree rhs_type = TREE_TYPE (rhs);
-  if (TREE_CODE (rhs) == COMPOUND_EXPR)
-    {
-      tree n = TREE_OPERAND (rhs, 1);
-      if (TREE_CODE (n) == VAR_DECL 
-         && DECL_NAME (n) == TYPE_identifier_node
-         && rhs_type == class_ptr_type
-         && TREE_CODE (EXPR_WFL_NODE (wfl)) == IDENTIFIER_NODE)
-       {
-         const char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl));
-         if (!strncmp (self_name, "java.lang.", 10))
-           to_return = build_primtype_type_ref (self_name);
-       }
-    }
-  return (to_return ? to_return : rhs );
-}
-
 /* 15.25 Assignment operators. */
 
 static tree
-patch_assignment (node, wfl_op1, wfl_op2)
+patch_assignment (node, wfl_op1)
      tree node;
      tree wfl_op1;
-     tree wfl_op2;
 {
   tree rhs = TREE_OPERAND (node, 1);
   tree lvalue = TREE_OPERAND (node, 0), llvalue;
   tree lhs_type = NULL_TREE, rhs_type, new_rhs = NULL_TREE;
   int error_found = 0;
   int lvalue_from_array = 0;
-
-  /* Can't assign to a (blank) final. */
-  if (check_final_assignment (lvalue, wfl_op1))
-    error_found = 1;
+  int is_return = 0;
 
   EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
 
@@ -12428,9 +12664,8 @@ patch_assignment (node, wfl_op1, wfl_op2)
     {
       lhs_type = TREE_TYPE (lvalue);
     }
-  /* Or Lhs can be a array acccess. Should that be lvalue ? FIXME +
-     comment on reason why */
-  else if (TREE_CODE (wfl_op1) == ARRAY_REF)
+  /* Or Lhs can be an array access. */
+  else if (TREE_CODE (lvalue) == ARRAY_REF)
     {
       lhs_type = TREE_TYPE (lvalue);
       lvalue_from_array = 1;
@@ -12440,21 +12675,21 @@ patch_assignment (node, wfl_op1, wfl_op2)
     lhs_type = TREE_TYPE (lvalue);
   /* Or a function return slot */
   else if (TREE_CODE (lvalue) == RESULT_DECL)
-    lhs_type = TREE_TYPE (lvalue);
+    {
+      /* If the return type is an integral type, then we create the
+        RESULT_DECL with a promoted type, but we need to do these
+        checks against the unpromoted type to ensure type safety.  So
+        here we look at the real type, not the type of the decl we
+        are modifying.  */
+      lhs_type = TREE_TYPE (TREE_TYPE (current_function_decl));
+      is_return = 1;
+    }
   /* Otherwise, we might want to try to write into an optimized static
      final, this is an of a different nature, reported further on. */
   else if (TREE_CODE (wfl_op1) == EXPR_WITH_FILE_LOCATION
           && resolve_expression_name (wfl_op1, &llvalue))
     {
-      if (!error_found && check_final_assignment (llvalue, wfl_op1))
-       {
-         /* What we should do instead is resetting the all the flags
-            previously set, exchange lvalue for llvalue and continue. */
-         error_found = 1;
-         return error_mark_node;
-       }
-      else 
-       lhs_type = TREE_TYPE (lvalue);
+      lhs_type = TREE_TYPE (lvalue);
     }
   else 
     {
@@ -12463,6 +12698,7 @@ patch_assignment (node, wfl_op1, wfl_op2)
     }
 
   rhs_type = TREE_TYPE (rhs);
+
   /* 5.1 Try the assignment conversion for builtin type. */
   new_rhs = try_builtin_assignconv (wfl_op1, lhs_type, rhs);
 
@@ -12500,7 +12736,7 @@ patch_assignment (node, wfl_op1, wfl_op2)
          wfl = wfl_operator;
          if (COMPOUND_ASSIGN_P (TREE_OPERAND (node, 1)))
            strcpy (operation, "assignment");
-         else if (TREE_CODE (TREE_OPERAND (node, 0)) == RESULT_DECL)
+         else if (is_return)
            strcpy (operation, "`return'");
          else
            strcpy (operation, "`='");
@@ -12517,77 +12753,52 @@ patch_assignment (node, wfl_op1, wfl_op2)
       error_found = 1;
     }
 
-  /* Inline read access to java.lang.PRIMTYPE.TYPE */
-  if (new_rhs)
-    new_rhs = maybe_build_primttype_type_ref (new_rhs, wfl_op2);
-
   if (error_found)
     return error_mark_node;
 
+  /* If we're processing a `return' statement, promote the actual type
+     to the promoted type.  */
+  if (is_return)
+    new_rhs = convert (TREE_TYPE (lvalue), new_rhs);
+
   /* 10.10: Array Store Exception runtime check */
   if (!flag_emit_class_files
       && !flag_emit_xref
       && lvalue_from_array 
       && JREFERENCE_TYPE_P (TYPE_ARRAY_ELEMENT (lhs_type)))
     {
-      tree check;
-      tree base = lvalue;
-
-      /* We need to retrieve the right argument for
-         _Jv_CheckArrayStore.  This is somewhat complicated by bounds
-         and null pointer checks, both of which wrap the operand in
-         one layer of COMPOUND_EXPR.  */
-      if (TREE_CODE (lvalue) == COMPOUND_EXPR)
-       base = TREE_OPERAND (lvalue, 0);
-      else
-       {
-         base = TREE_OPERAND (base, 0);
-         if (flag_bounds_check)
-           base = TREE_OPERAND (base, 1);
-         if (flag_check_references)
-           base = TREE_OPERAND (base, 1);
-         base = TREE_OPERAND (base, 0);        
-       }
-
-      /* Build the invocation of _Jv_CheckArrayStore */
+      tree array, store_check, base, index_expr;
+      
+      /* Save RHS so that it doesn't get re-evaluated by the store check. */ 
       new_rhs = save_expr (new_rhs);
-      check = build (CALL_EXPR, void_type_node,
-                    build_address_of (soft_checkarraystore_node),
-                    tree_cons (NULL_TREE, base,
-                               build_tree_list (NULL_TREE, new_rhs)),
-                    NULL_TREE);
-      TREE_SIDE_EFFECTS (check) = 1;
-
-      /* We have to decide on an insertion point */
-      if (TREE_CODE (lvalue) == COMPOUND_EXPR)
-       {
-         tree t;
-         if (flag_bounds_check)
-           {
-             t = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0);
-             TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0) =
-               build (COMPOUND_EXPR, void_type_node, t, check);
-           }
-         else
-           TREE_OPERAND (lvalue, 1) = build (COMPOUND_EXPR, lhs_type,
-                                             check, TREE_OPERAND (lvalue, 1));
-       }
-      else 
+
+      /* Get the INDIRECT_REF. */
+      array = TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0);
+      /* Get the array pointer expr. */
+      array = TREE_OPERAND (array, 0);
+      store_check = build_java_arraystore_check (array, new_rhs);
+      
+      index_expr = TREE_OPERAND (lvalue, 1);
+      
+      if (TREE_CODE (index_expr) == COMPOUND_EXPR)
        {
-         /* Make sure the bound check will happen before the store check */
-         if (flag_bounds_check)
-           TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0) =
-             build (COMPOUND_EXPR, void_type_node,
-                    TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0), check);
-         else
-           lvalue = build (COMPOUND_EXPR, lhs_type, check, lvalue);
+         /* A COMPOUND_EXPR here is a bounds check. The bounds check must 
+            happen before the store check, so prepare to insert the store
+            check within the second operand of the existing COMPOUND_EXPR. */
+         base = index_expr;
        }
+      else
+        base = lvalue;
+      
+      index_expr = TREE_OPERAND (base, 1);
+      TREE_OPERAND (base, 1) = build (COMPOUND_EXPR, TREE_TYPE (index_expr), 
+                                     store_check, index_expr);
     }
 
   /* Final locals can be used as case values in switch
      statement. Prepare them for this eventuality. */
   if (TREE_CODE (lvalue) == VAR_DECL 
-      && LOCAL_FINAL_P (lvalue)
+      && DECL_FINAL (lvalue)
       && TREE_CONSTANT (new_rhs)
       && IDENTIFIER_LOCAL_VALUE (DECL_NAME (lvalue))
       && JINTEGRAL_TYPE_P (TREE_TYPE (lvalue))
@@ -12604,9 +12815,8 @@ patch_assignment (node, wfl_op1, wfl_op2)
 }
 
 /* Check that type SOURCE can be cast into type DEST. If the cast
-   can't occur at all, return 0 otherwise 1. This function is used to
-   produce accurate error messages on the reasons why an assignment
-   failed. */
+   can't occur at all, return NULL; otherwise, return a possibly
+   modified rhs.  */
 
 static tree
 try_reference_assignconv (lhs_type, rhs)
@@ -12624,7 +12834,7 @@ try_reference_assignconv (lhs_type, rhs)
       else if (valid_ref_assignconv_cast_p (rhs_type, lhs_type, 0))
        new_rhs = rhs;
       /* This is a magic assignment that we process differently */
-      else if (TREE_CODE (rhs) == EXC_PTR_EXPR)
+      else if (TREE_CODE (rhs) == JAVA_EXC_OBJ_EXPR)
        new_rhs = rhs;
     }
   return new_rhs;
@@ -12651,12 +12861,6 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs)
        new_rhs = rhs;
     }
 
-  /* Zero accepted everywhere */
-  else if (TREE_CODE (rhs) == INTEGER_CST 
-      && TREE_INT_CST_HIGH (rhs) == 0 && TREE_INT_CST_LOW (rhs) == 0
-      && JPRIMITIVE_TYPE_P (rhs_type))
-    new_rhs = convert (lhs_type, rhs);
-
   /* 5.1.1 Try Identity Conversion,
      5.1.2 Try Widening Primitive Conversion */
   else if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type))
@@ -13074,7 +13278,7 @@ patch_binop (node, wfl_op1, wfl_op2)
   tree op1_type = TREE_TYPE (op1);
   tree op2_type = TREE_TYPE (op2);
   tree prom_type = NULL_TREE, cn;
-  int code = TREE_CODE (node);
+  enum tree_code code = TREE_CODE (node);
 
   /* If 1, tell the routine that we have to return error_mark_node
      after checking for the initialization of the RHS */
@@ -13120,10 +13324,35 @@ patch_binop (node, wfl_op1, wfl_op2)
          break;
        }
       prom_type = binary_numeric_promotion (op1_type, op2_type, &op1, &op2);
+
+      /* Detect integral division by zero */
+      if ((code == RDIV_EXPR || code == TRUNC_MOD_EXPR)
+         && TREE_CODE (prom_type) == INTEGER_TYPE
+         && (op2 == integer_zero_node || op2 == long_zero_node ||
+             (TREE_CODE (op2) == INTEGER_CST &&
+              ! TREE_INT_CST_LOW (op2)  && ! TREE_INT_CST_HIGH (op2))))
+       {
+         parse_warning_context (wfl_operator, "Evaluating this expression will result in an arithmetic exception being thrown");
+         TREE_CONSTANT (node) = 0;
+       }
+         
       /* Change the division operator if necessary */
       if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE)
        TREE_SET_CODE (node, TRUNC_DIV_EXPR);
 
+      /* Before divisions as is disapear, try to simplify and bail if
+         applicable, otherwise we won't perform even simple
+         simplifications like (1-1)/3. We can't do that with floating
+         point number, folds can't handle them at this stage. */
+      if (code == RDIV_EXPR && TREE_CONSTANT (op1) && TREE_CONSTANT (op2)
+         && JINTEGRAL_TYPE_P (op1) && JINTEGRAL_TYPE_P (op2))
+       {
+         TREE_TYPE (node) = prom_type;
+         node = fold (node);
+         if (TREE_CODE (node) != code)
+           return node;
+       }
+
       if (TREE_CODE (prom_type) == INTEGER_TYPE
          && flag_use_divide_subroutine
          && ! flag_emit_class_files
@@ -13201,7 +13430,7 @@ patch_binop (node, wfl_op1, wfl_op2)
        }
 
       /* Unary numeric promotion (5.6.1) is performed on each operand
-         separatly */
+         separately */
       op1 = do_unary_numeric_promotion (op1);
       op2 = do_unary_numeric_promotion (op2);
 
@@ -13221,7 +13450,7 @@ patch_binop (node, wfl_op1, wfl_op2)
       if (code == URSHIFT_EXPR && ! flag_emit_class_files)
        {
          tree to_return;
-          tree utype = unsigned_type (prom_type);
+          tree utype = java_unsigned_type (prom_type);
           op1 = convert (utype, op1);
          TREE_SET_CODE (node, RSHIFT_EXPR);
           TREE_OPERAND (node, 0) = op1;
@@ -13241,6 +13470,15 @@ patch_binop (node, wfl_op1, wfl_op2)
 
       TREE_TYPE (node) = boolean_type_node;
 
+      /* OP1_TYPE might be NULL when OP1 is a string constant.  */
+      if ((cn = patch_string (op1))) 
+       {
+         op1 = cn;
+         op1_type = TREE_TYPE (op1);
+       }
+      if (op1_type == NULL_TREE)
+       abort ();
+
       if (!(op2_type = resolve_type_during_patch (op2)))
        return error_mark_node;
 
@@ -13330,6 +13568,14 @@ patch_binop (node, wfl_op1, wfl_op2)
          error_found = 1;
          break;
        }
+      else if (integer_zerop (op1))
+       {
+         return code == TRUTH_ANDIF_EXPR ? op1 : op2;
+       }
+      else if (integer_onep (op1))
+       {
+         return code == TRUTH_ANDIF_EXPR ? op2 : op1;
+       }
       /* The type of the conditional operators is BOOLEAN */
       prom_type = boolean_type_node;
       break;
@@ -13411,6 +13657,8 @@ patch_binop (node, wfl_op1, wfl_op2)
        }
       prom_type = boolean_type_node;
       break;
+    default:
+      abort ();
     }
 
   if (error_found)
@@ -13478,9 +13726,9 @@ merge_string_cste (op1, op2, after)
   /* Reasonable integer constant can be treated right away */
   if (TREE_CODE (op2) == INTEGER_CST && !TREE_CONSTANT_OVERFLOW (op2))
     {
-      static const char *boolean_true = "true";
-      static const char *boolean_false = "false";
-      static const char *null_pointer = "null";
+      static const char *const boolean_true = "true";
+      static const char *const boolean_false = "false";
+      static const char *const null_pointer = "null";
       char ch[3];
       const char *string;
       
@@ -13497,8 +13745,8 @@ merge_string_cste (op1, op2, after)
          string = ch;
        }
       else
-         string = print_int_node (op2);
-      
+       string = string_convert_int_cst (op2);
+
       return do_merge_string_cste (op1, string, strlen (string), after);
     }
   return NULL_TREE;
@@ -13577,8 +13825,8 @@ build_string_concatenation (op1, op2)
     op2 = patch_string_cst (op2);
 
   /* If either one of the constant is null and the other non null
-     operand is a String object, return it. */
-  if (JSTRING_TYPE_P (TREE_TYPE (op1)) && !op2)
+     operand is a String constant, return it. */
+  if ((TREE_CODE (op1) == STRING_CST) && !op2)
     return op1;
 
   /* If OP1 isn't already a StringBuffer, create and
@@ -13696,7 +13944,7 @@ build_incdec (op_token, op_location, op1, is_post_p)
      tree op1;
      int is_post_p;
 {
-  static enum tree_code lookup [2][2] = 
+  static const enum tree_code lookup [2][2] = 
     {
       { PREDECREMENT_EXPR, PREINCREMENT_EXPR, },
       { POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, },
@@ -13749,8 +13997,11 @@ patch_incomplete_class_ref (node)
 
   if (!flag_emit_class_files || JPRIMITIVE_TYPE_P (ref_type))
     {
+      tree dot = build_class_ref (ref_type);
       /* A class referenced by `foo.class' is initialized.  */
-      return build_class_init (ref_type, build_class_ref (ref_type));
+      if (!flag_emit_class_files)
+       dot = build_class_init (ref_type, dot);
+      return java_complete_tree (dot);
     }
 
   /* If we're emitting class files and we have to deal with non
@@ -13814,26 +14065,14 @@ patch_unaryop (node, wfl_op)
               && TREE_OPERAND (decl, 1)
               && (TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)))
        {
-         tree lvalue;
-         /* Before screaming, check that we're not in fact trying to
-            increment a optimized static final access, in which case
-            we issue an different error message. */
-         if (!(TREE_CODE (wfl_op) == EXPR_WITH_FILE_LOCATION
-               && resolve_expression_name (wfl_op, &lvalue)
-               && check_final_assignment (lvalue, wfl_op)))
-           parse_error_context (wfl_operator, "Invalid argument to `%s'",
-                                operator_string (node));
          TREE_TYPE (node) = error_mark_node;
          error_found = 1;
        }
       
-      if (check_final_assignment (op, wfl_op))
-       error_found = 1;
-
       /* From now on, we know that op if a variable and that it has a
          valid wfl. We use wfl_op to locate errors related to the
          ++/-- operand. */
-      else if (!JNUMERIC_TYPE_P (op_type))
+      if (!JNUMERIC_TYPE_P (op_type))
        {
          parse_error_context
            (wfl_op, "Invalid argument type `%s' to `%s'",
@@ -13994,10 +14233,15 @@ patch_cast (node, wfl_op)
      tree wfl_op;
 {
   tree op = TREE_OPERAND (node, 0);
-  tree op_type = TREE_TYPE (op);
   tree cast_type = TREE_TYPE (node);
+  tree patched, op_type;
   char *t1;
 
+  /* Some string patching might be necessary at this stage */
+  if ((patched = patch_string (op)))
+    TREE_OPERAND (node, 0) = op = patched;
+  op_type = TREE_TYPE (op);
+
   /* First resolve OP_TYPE if unresolved */
   if (!(cast_type = resolve_type_during_patch (cast_type)))
     return error_mark_node;
@@ -14145,16 +14389,7 @@ patch_array_ref (node)
       TREE_OPERAND (node, 1) = index;
     }
   else
-    {
-      /* The save_expr is for correct evaluation order.  It would be cleaner
-        to use force_evaluation_order (see comment there), but that is
-        difficult when we also have to deal with bounds checking. */
-      if (TREE_SIDE_EFFECTS (index))
-       array = save_expr (array);
-      node = build_java_arrayaccess (array, array_type, index);
-      if (TREE_SIDE_EFFECTS (index))
-       node = build (COMPOUND_EXPR, array_type, array, node);
-    }
+    node = build_java_arrayaccess (array, array_type, index);
   TREE_TYPE (node) = array_type;
   return node;
 }
@@ -14401,7 +14636,7 @@ array_constructor_check_entry (type, entry)
   /* Check and report errors */
   if (!new_value)
     {
-      const char *msg = (!valid_cast_to_p (type_value, type) ?
+      const char *const msg = (!valid_cast_to_p (type_value, type) ?
                   "Can't" : "Explicit cast needed to");
       if (!array_type_string)
        array_type_string = xstrdup (lang_printable_name (type, 1));
@@ -14412,10 +14647,7 @@ array_constructor_check_entry (type, entry)
     }
   
   if (new_value)
-    {
-      new_value = maybe_build_primttype_type_ref (new_value, wfl_value);
-      TREE_VALUE (entry) = new_value;
-    }
+    TREE_VALUE (entry) = new_value;
 
   if (array_type_string)
     free (array_type_string);
@@ -14475,12 +14707,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");
        
@@ -14512,18 +14744,6 @@ patch_return (node)
       tree exp = java_complete_tree (return_exp);
       tree modify, patched;
 
-      /* If the function returned value and EXP are booleans, EXP has
-      to be converted into the type of DECL_RESULT, which is integer
-      (see complete_start_java_method) */
-      if (TREE_TYPE (exp) == boolean_type_node &&
-         TREE_TYPE (TREE_TYPE (meth)) == boolean_type_node)
-       exp = convert_to_integer (TREE_TYPE (DECL_RESULT (meth)), exp);
-
-      /* `null' can be assigned to a function returning a reference */
-      if (JREFERENCE_TYPE_P (TREE_TYPE (TREE_TYPE (meth))) &&
-         exp == null_pointer_node)
-       exp = build_null_of_type (TREE_TYPE (TREE_TYPE (meth)));
-
       if ((patched = patch_string (exp)))
        exp = patched;
       
@@ -14565,6 +14785,9 @@ patch_if_else_statement (node)
      tree node;
 {
   tree expression = TREE_OPERAND (node, 0);
+  int can_complete_normally
+    = (CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1))
+       | CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 2)));
 
   TREE_TYPE (node) = error_mark_node;
   EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
@@ -14580,11 +14803,22 @@ patch_if_else_statement (node)
       return error_mark_node;
     }
   
+  if (TREE_CODE (expression) == INTEGER_CST)
+    {
+      if (integer_zerop (expression))
+       node = TREE_OPERAND (node, 2);
+      else
+       node = TREE_OPERAND (node, 1);
+      if (CAN_COMPLETE_NORMALLY (node) != can_complete_normally)
+       {
+         node = build (COMPOUND_EXPR, void_type_node, node, empty_stmt_node);
+         CAN_COMPLETE_NORMALLY (node) = can_complete_normally;
+       }
+      return node;
+    }
   TREE_TYPE (node) = void_type_node;
   TREE_SIDE_EFFECTS (node) = 1;
-  CAN_COMPLETE_NORMALLY (node)
-    = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1))
-    | CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 2));
+  CAN_COMPLETE_NORMALLY (node) = can_complete_normally;
   return node;
 }
 
@@ -14664,7 +14898,7 @@ build_new_loop (loop_body)
        COMPOUND_EXPR           (loop main body)
          EXIT_EXPR             (this order is for while/for loops.
          LABELED_BLOCK_EXPR      the order is reversed for do loops)
-           LABEL_DECL           (a continue occuring here branches at the 
+           LABEL_DECL           (a continue occurring here branches at the 
            BODY                         end of this labeled block)
        INCREMENT               (if any)
 
@@ -14738,7 +14972,22 @@ finish_for_loop (location, condition, update, body)
   /* Put the condition and the loop body in place */
   tree loop = finish_loop_body (location, condition, body, 0);
   /* LOOP is the current loop which has been now popped of the loop
-     stack. Install the update block */
+     stack.  Mark the update block as reachable and install it.  We do
+     this because the (current interpretation of the) JLS requires
+     that the update expression be considered reachable even if the
+     for loop's body doesn't complete normally.  */
+  if (update != NULL_TREE && update != empty_stmt_node)
+    {
+      tree up2 = update;
+      if (TREE_CODE (up2) == EXPR_WITH_FILE_LOCATION)
+       up2 = EXPR_WFL_NODE (up2);
+      /* Try to detect constraint violations.  These would be
+        programming errors somewhere.  */
+      if (! IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (up2)))
+         || TREE_CODE (up2) == LOOP_EXPR)
+       abort ();
+      SUPPRESS_UNREACHABLE_ERROR (up2) = 1;
+    }
   LOOP_EXPR_BODY_UPDATE_BLOCK (LOOP_EXPR_BODY (loop)) = update;
   return loop;
 }
@@ -14965,6 +15214,7 @@ patch_switch_statement (node)
      tree node;
 {
   tree se = TREE_OPERAND (node, 0), se_type;
+  tree save, iter;
 
   /* Complete the switch expression */
   se = TREE_OPERAND (node, 0) = java_complete_tree (se);
@@ -14982,8 +15232,43 @@ patch_switch_statement (node)
       return error_mark_node;
     }
 
+  /* Save and restore the outer case label list.  */
+  save = case_label_list;
+  case_label_list = NULL_TREE;
+
   TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1));
 
+  /* See if we've found a duplicate label.  We can't leave this until
+     code generation, because in `--syntax-only' and `-C' modes we
+     don't do ordinary code generation.  */
+  for (iter = case_label_list; iter != NULL_TREE; iter = TREE_CHAIN (iter))
+    {
+      HOST_WIDE_INT val = TREE_INT_CST_LOW (TREE_VALUE (iter));
+      tree subiter;
+      for (subiter = TREE_CHAIN (iter);
+          subiter != NULL_TREE;
+          subiter = TREE_CHAIN (subiter))
+       {
+         HOST_WIDE_INT subval = TREE_INT_CST_LOW (TREE_VALUE (subiter));
+         if (val == subval)
+           {
+             EXPR_WFL_LINECOL (wfl_operator)
+               = EXPR_WFL_LINECOL (TREE_PURPOSE (iter));
+             /* The case_label_list is in reverse order, so print the
+                outer label first.  */
+             parse_error_context (wfl_operator, "duplicate case label: `"
+                                  HOST_WIDE_INT_PRINT_DEC "'", subval);
+             EXPR_WFL_LINECOL (wfl_operator)
+               = EXPR_WFL_LINECOL (TREE_PURPOSE (subiter));
+             parse_error_context (wfl_operator, "original label is here");
+
+             break;
+           }
+       }
+    }
+
+  case_label_list = save;
+
   /* Ready to return */
   if (TREE_CODE (TREE_OPERAND (node, 1)) == ERROR_MARK)
     {
@@ -15000,6 +15285,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;
@@ -15192,13 +15510,9 @@ patch_synchronized_statement (node, wfl_op1)
   CAN_COMPLETE_NORMALLY (exit) = 1;
   assignment = build (MODIFY_EXPR, NULL_TREE, expr_decl, expr);
   TREE_SIDE_EFFECTS (assignment) = 1;
-  node = build1 (CLEANUP_POINT_EXPR, NULL_TREE,
-                build (COMPOUND_EXPR, NULL_TREE,
-                       build (WITH_CLEANUP_EXPR, NULL_TREE,
-                              build (COMPOUND_EXPR, NULL_TREE,
-                                     assignment, enter),
-                              NULL_TREE, exit),
-                       block));
+  node = build (COMPOUND_EXPR, NULL_TREE,
+               build (COMPOUND_EXPR, NULL_TREE, assignment, enter),
+               build (TRY_FINALLY_EXPR, NULL_TREE, block, exit));
   node = build_expr_block (node, expr_decl);
 
   return java_complete_tree (node);
@@ -15234,12 +15548,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
-     is explicitely declared in the `throws' clause of each
+  /* An instance can't throw a checked exception unless that exception
+     is explicitly 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; 
@@ -15387,6 +15702,38 @@ purge_unchecked_exceptions (mdecl)
   DECL_FUNCTION_THROWS (mdecl) = new;
 }
 
+/* This function goes over all of CLASS_TYPE ctors and checks whether
+   each of them features at least one unchecked exception in its
+   `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
@@ -15613,8 +15960,6 @@ fold_constant_for_init (node, context)
       DECL_INITIAL (node) = NULL_TREE;
       val = fold_constant_for_init (val, node);
       DECL_INITIAL (node) = val;
-      if (!val && CLASS_FINAL_VARIABLE_P (node))
-       DECL_FIELD_FINAL_IUD (node) = 0;
       return val;
 
     case EXPR_WITH_FILE_LOCATION:
@@ -15636,8 +15981,14 @@ fold_constant_for_init (node, context)
            }
          else
            {
+             /* Install the proper context for the field resolution.
+                The prior context is restored once the name is
+                properly qualified. */
+             tree saved_current_class = current_class;
              /* Wait until the USE_COMPONENT_REF re-write.  FIXME. */
+             current_class = DECL_CONTEXT (context);
              qualify_ambiguous_name (node);
+             current_class = saved_current_class;
              if (resolve_field_access (node, &decl, NULL)
                  && decl != NULL_TREE)
                return fold_constant_for_init (decl, decl);
@@ -15721,6 +16072,87 @@ mark_parser_ctxt (p)
 void
 init_src_parse ()
 {
-  /* Register roots with the garbage collector.  */
-  ggc_add_tree_root (src_parse_roots, sizeof (src_parse_roots) / sizeof(tree));
+  /* Sanity check; we've been bit by this before.  */
+  if (ARRAY_SIZE (ctxp->modifier_ctx) != MODIFIER_TK - PUBLIC_TK)
+    abort ();
 }
+
+\f
+
+/* This section deals with the functions that are called when tables
+   recording class initialization information are traversed.  */
+
+/* Attach to PTR (a block) the declaration found in ENTRY. */
+
+static int
+attach_init_test_initialization_flags (entry, ptr)
+     PTR *entry;
+     PTR ptr;
+{
+  tree block = (tree)ptr;
+  struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
+  
+  TREE_CHAIN (ite->value) = BLOCK_EXPR_DECLS (block);
+  BLOCK_EXPR_DECLS (block) = ite->value;
+  return true;
+}
+
+/* This function is called for each classes that is known definitely
+   assigned when a given static method was called. This function
+   augments a compound expression (INFO) storing all assignment to
+   initialized static class flags if a flag already existed, otherwise
+   a new one is created.  */
+
+static int
+emit_test_initialization (entry_p, info)
+     PTR *entry_p;
+     PTR info;
+{
+  tree l = (tree) info;
+  tree decl, init;
+  tree key = (tree) *entry_p;
+  tree *ite;
+  htab_t cf_ht = DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl);
+
+  /* If we haven't found a flag and we're dealing with self registered
+     with current_function_decl, then don't do anything. Self is
+     always added as definitely initialized but this information is
+     valid only if used outside the current function. */
+  if (current_function_decl == TREE_PURPOSE (l)
+      && java_treetreehash_find (cf_ht, key) == NULL)
+    return true;
+    
+  ite = java_treetreehash_new (cf_ht, key);
+
+  /* If we don't have a variable, create one and install it. */
+  if (*ite == NULL)
+    {
+      tree block;
+      
+      decl = build_decl (VAR_DECL, NULL_TREE, boolean_type_node);
+      MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
+      LOCAL_CLASS_INITIALIZATION_FLAG (decl) = 1;
+      DECL_CONTEXT (decl) = current_function_decl;
+      DECL_INITIAL (decl) = boolean_true_node;
+
+      /* The trick is to find the right context for it. */
+      block = BLOCK_SUBBLOCKS (GET_CURRENT_BLOCK (current_function_decl));
+      TREE_CHAIN (decl) = BLOCK_EXPR_DECLS (block);
+      BLOCK_EXPR_DECLS (block) = decl;
+      *ite = decl;
+    }
+  else
+    decl = *ite;
+
+  /* Now simply augment the compound that holds all the assignments
+     pertaining to this method invocation. */
+  init = build (MODIFY_EXPR, boolean_type_node, decl, boolean_true_node);
+  TREE_SIDE_EFFECTS (init) = 1;
+  TREE_VALUE (l) = add_stmt_to_compound (TREE_VALUE (l), void_type_node, init);
+  TREE_SIDE_EFFECTS (TREE_VALUE (l)) = 1;
+
+  return true;
+}
+
+#include "gt-java-parse.h"
+#include "gtype-java.h"