OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / java / parse.y
index a35e6dc..2ea7af0 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 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
 
 This file is part of GNU CC.
@@ -64,7 +64,6 @@ definitions and other extensions.  */
 #include "xref.h"
 #include "function.h"
 #include "except.h"
-#include "defaults.h"
 #include "ggc.h"
 
 #ifndef DIR_SEPARATOR
@@ -102,17 +101,21 @@ 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 void check_inner_class_access PARAMS ((tree, tree, tree));
 static int check_pkg_class_access PARAMS ((tree, tree));
 static void register_package PARAMS ((tree));
 static tree resolve_package PARAMS ((tree, tree *));
 static tree lookup_package_type PARAMS ((const char *, int));
-static tree lookup_package_type_and_set_next PARAMS ((const char *, int, tree *));
 static tree resolve_class PARAMS ((tree, tree, tree, tree));
 static void declare_local_variables PARAMS ((int, tree, tree));
 static void source_start_java_method PARAMS ((tree));
 static void source_end_java_method PARAMS ((void));
-static void expand_start_java_method PARAMS ((tree));
 static tree find_name_in_single_imports PARAMS ((tree));
 static void check_abstract_method_header PARAMS ((tree));
 static tree lookup_java_interface_method2 PARAMS ((tree, tree));
@@ -120,9 +123,10 @@ static tree resolve_expression_name PARAMS ((tree, tree *));
 static tree maybe_create_class_interface_decl PARAMS ((tree, tree, tree, tree));
 static int check_class_interface_creation PARAMS ((int, int, tree, 
                                                  tree, tree, tree));
-static tree patch_method_invocation PARAMS ((tree, tree, tree, 
+static tree patch_method_invocation PARAMS ((tree, tree, tree, int,
                                            int *, tree *));
 static int breakdown_qualified PARAMS ((tree *, tree *, tree));
+static int in_same_package PARAMS ((tree, tree));
 static tree resolve_and_layout PARAMS ((tree, tree));
 static tree qualify_and_find PARAMS ((tree, tree, tree));
 static tree resolve_no_layout PARAMS ((tree, tree));
@@ -148,7 +152,6 @@ 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));
 static tree enter_block PARAMS ((void));
-static tree enter_a_block PARAMS ((tree));
 static tree exit_block PARAMS ((void));
 static tree lookup_name_in_blocks PARAMS ((tree));
 static void maybe_absorb_scoping_blocks PARAMS ((void));
@@ -193,7 +196,7 @@ static tree maybe_access_field PARAMS ((tree, tree, tree));
 static int complete_function_arguments PARAMS ((tree));
 static int check_for_static_method_reference PARAMS ((tree, tree, tree, 
                                                      tree, tree));
-static int not_accessible_p PARAMS ((tree, tree, int));
+static int not_accessible_p PARAMS ((tree, tree, tree, int));
 static void check_deprecation PARAMS ((tree, tree));
 static int class_in_current_package PARAMS ((tree));
 static tree build_if_else_statement PARAMS ((int, tree, tree, tree));
@@ -235,6 +238,7 @@ 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 void fix_constructors PARAMS ((tree));
 static tree build_alias_initializer_parameter_list PARAMS ((int, tree,
                                                            tree, int *));
@@ -244,7 +248,6 @@ static tree create_artificial_method PARAMS ((tree, int, tree, tree, tree));
 static void start_artificial_method_body PARAMS ((tree));
 static void end_artificial_method_body PARAMS ((tree));
 static int check_method_redefinition PARAMS ((tree, tree));
-static int reset_method_name PARAMS ((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));
@@ -287,6 +290,7 @@ static void java_parser_context_pop_initialized_field PARAMS ((void));
 static tree reorder_static_initialized PARAMS ((tree));
 static void java_parser_context_suspend PARAMS ((void));
 static void java_parser_context_resume PARAMS ((void));
+static int pop_current_osb PARAMS ((struct parser_ctxt *));
 
 /* JDK 1.1 work. FIXME */
 
@@ -326,6 +330,7 @@ static tree build_dot_class_method PARAMS ((tree));
 static tree build_dot_class_method_invocation PARAMS ((tree));
 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));
 
 /* Number of error found so far. */
 int java_error_count; 
@@ -334,7 +339,7 @@ int java_warning_count;
 /* Tell when not to fold, when doing xrefs */
 int do_not_fold;
 /* Cyclic inheritance report, as it can be set by layout_class */
-char *cyclic_inheritance_report;
+const char *cyclic_inheritance_report;
  
 /* Tell when we're within an instance initializer */
 static int in_instance_initializer;
@@ -343,7 +348,7 @@ static int in_instance_initializer;
 struct parser_ctxt *ctxp;
 
 /* List of things that were analyzed for which code will be generated */
-static struct parser_ctxt *ctxp_for_generation = NULL;
+struct parser_ctxt *ctxp_for_generation = NULL;
 
 /* binop_lookup maps token to tree_code. It is used where binary
    operations are involved and required by the parser. RDIV_EXPR
@@ -406,6 +411,11 @@ static tree current_this;
    the list of the catch clauses of the currently analysed try block. */
 static tree currently_caught_type_list;
 
+static tree src_parse_roots[1] = { NULL_TREE };
+
+/* All classes seen from source code */
+#define gclass_list src_parse_roots[0]
+
 /* Check modifiers. If one doesn't fit, retrieve it in its declaration
    line and point it out.  */
 /* Should point out the one that don't fit. ASCII/unicode, going
@@ -463,6 +473,7 @@ static tree currently_caught_type_list;
 %token   STATIC_TK       FINAL_TK           SYNCHRONIZED_TK
 %token   VOLATILE_TK     TRANSIENT_TK       NATIVE_TK
 %token   PAD_TK          ABSTRACT_TK        MODIFIER_TK
+%token   STRICT_TK
 
 /* Keep those two in order, too */
 %token   DECR_TK INCR_TK
@@ -579,7 +590,7 @@ static tree currently_caught_type_list;
                        BOOLEAN_TK INTEGRAL_TK FP_TK
 
 /* Added or modified JDK 1.1 rule types  */
-%type   <node>         type_literals array_type_literal
+%type   <node>         type_literals
 
 %%
 /* 19.2 Production from 2.3: The Syntactic Grammar  */
@@ -600,7 +611,6 @@ goal:
                  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_string_root (&cyclic_inheritance_report, 1);
                  ggc_add_root (&ctxp, 1, 
                                sizeof (struct parser_ctxt *),
                                mark_parser_ctxt);
@@ -652,19 +662,22 @@ interface_type:
 ;
 
 array_type:
-       primitive_type OSB_TK CSB_TK
+       primitive_type dims
                { 
-                 $$ = build_java_array_type ($1, -1);
-                 CLASS_LOADED_P ($$) = 1;
+                 int osb = pop_current_osb (ctxp);
+                 tree t = build_java_array_type (($1), -1);
+                 while (--osb)
+                   t = build_unresolved_array_type (t);
+                 $$ = t;
+               }
+|      name dims
+               { 
+                 int osb = pop_current_osb (ctxp);
+                 tree t = $1;
+                 while (osb--)
+                   t = build_unresolved_array_type (t);
+                 $$ = t;
                }
-|      name OSB_TK CSB_TK
-               { $$ = build_unresolved_array_type ($1); }
-|      array_type OSB_TK CSB_TK
-               { $$ = build_unresolved_array_type ($1); }
-|      primitive_type OSB_TK error
-               {RULE ("']' expected"); RECOVER;}
-|      array_type OSB_TK error
-               {RULE ("']' expected"); RECOVER;}
 ;
 
 /* 19.5 Productions from 6: Names  */
@@ -1617,7 +1630,7 @@ switch_label:
                }
 |      DEFAULT_TK REL_CL_TK
                { 
-                 tree lab = build1 (DEFAULT_EXPR, NULL_TREE, NULL_TREE);
+                 tree lab = build (DEFAULT_EXPR, NULL_TREE, NULL_TREE);
                  EXPR_WFL_LINECOL (lab) = $1.location;
                  java_method_add_stmt (current_function_decl, lab);
                }
@@ -1873,9 +1886,9 @@ catch_clause_parameter:
                     declared initialized by the appropriate function
                     call */
                  tree ccpb = enter_block ();
-                 tree init = build_assignment (ASSIGN_TK, $2.location, 
-                                               TREE_PURPOSE ($3), 
-                                               soft_exceptioninfo_call_node);
+                 tree init = build_assignment
+                   (ASSIGN_TK, $2.location, TREE_PURPOSE ($3), 
+                    build (JAVA_EXC_OBJ_EXPR, ptr_type_node));
                  declare_local_variables (0, TREE_VALUE ($3),
                                           build_tree_list (TREE_PURPOSE ($3),
                                                            init));
@@ -1935,33 +1948,18 @@ primary_no_new_array:
                {yyerror ("'class' expected" ); RECOVER;}
 ;
 
-/* Added, JDK1.1 type literals. We can't use `type' directly, so we
-   broke the rule down a bit. */
-
-array_type_literal:
-       primitive_type OSB_TK CSB_TK
-               { 
-                 $$ = build_java_array_type ($1, -1);
-                 CLASS_LOADED_P ($$) = 1;
-               }
-|      name OSB_TK CSB_TK
-               { $$ = build_unresolved_array_type ($1); }
-/* This triggers two reduce/reduce conflict between array_type_literal and
-   dims. FIXME.
-|      array_type OSB_TK CSB_TK
-               { $$ = build_unresolved_array_type ($1); }
-*/
-;
-
 type_literals:
        name DOT_TK CLASS_TK
                { $$ = build_incomplete_class_ref ($2.location, $1); }
-|      array_type_literal DOT_TK CLASS_TK
+|      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:
@@ -2085,15 +2083,16 @@ array_creation_expression:
 |      NEW_TK class_or_interface_type dim_exprs
                { $$ = build_newarray_node ($2, $3, 0); }
 |      NEW_TK primitive_type dim_exprs dims
-               { $$ = build_newarray_node ($2, $3, CURRENT_OSB (ctxp));}
+               { $$ = build_newarray_node ($2, $3, pop_current_osb (ctxp));}
 |      NEW_TK class_or_interface_type dim_exprs dims
-               { $$ = build_newarray_node ($2, $3, CURRENT_OSB (ctxp));}
+               { $$ = build_newarray_node ($2, $3, pop_current_osb (ctxp));}
         /* Added, JDK1.1 anonymous array. Initial documentation rule
            modified */
 |      NEW_TK class_or_interface_type dims array_initializer
                {
                  char *sig;
-                 while (CURRENT_OSB (ctxp)--)
+                 int osb = pop_current_osb (ctxp);
+                 while (osb--)
                    obstack_1grow (&temporary_obstack, '[');
                  sig = obstack_finish (&temporary_obstack);
                  $$ = build (NEW_ANONYMOUS_ARRAY_EXPR, NULL_TREE,
@@ -2101,8 +2100,9 @@ array_creation_expression:
                }
 |      NEW_TK primitive_type dims array_initializer
                { 
+                 int osb = pop_current_osb (ctxp);
                  tree type = $2;
-                 while (CURRENT_OSB (ctxp)--)
+                 while (osb--)
                    type = build_java_array_type (type, -1);
                  $$ = build (NEW_ANONYMOUS_ARRAY_EXPR, NULL_TREE, 
                              build_pointer_type (type), NULL_TREE, $4);
@@ -2325,9 +2325,9 @@ cast_expression:          /* Error handling here is potentially weak */
        OP_TK primitive_type dims CP_TK unary_expression
                { 
                  tree type = $2;
-                 while (CURRENT_OSB (ctxp)--)
+                 int osb = pop_current_osb (ctxp);
+                 while (osb--)
                    type = build_java_array_type (type, -1);
-                 ctxp->osb_depth--;
                  $$ = build_cast ($1.location, type, $5); 
                }
 |      OP_TK primitive_type CP_TK unary_expression
@@ -2337,9 +2337,9 @@ cast_expression:          /* Error handling here is potentially weak */
 |      OP_TK name dims CP_TK unary_expression_not_plus_minus
                { 
                  const char *ptr;
-                 while (CURRENT_OSB (ctxp)--)
+                 int osb = pop_current_osb (ctxp); 
+                 while (osb--)
                    obstack_1grow (&temporary_obstack, '[');
-                 ctxp->osb_depth--;
                  obstack_grow0 (&temporary_obstack, 
                                 IDENTIFIER_POINTER (EXPR_WFL_NODE ($2)),
                                 IDENTIFIER_LENGTH (EXPR_WFL_NODE ($2)));
@@ -2593,6 +2593,25 @@ constant_expression:
 ;
 
 %%
+
+/* Helper function to retrieve an OSB count. Should be used when the
+   `dims:' rule is being used.  */
+
+static int
+pop_current_osb (ctxp)
+     struct parser_ctxt *ctxp;
+{
+  int to_return;
+
+  if (ctxp->osb_depth < 0)
+    abort ();
+  
+  to_return = CURRENT_OSB (ctxp);
+  ctxp->osb_depth--;
+  
+  return to_return;
+}
+
 \f
 
 /* This section of the code deal with save/restoring parser contexts.
@@ -2628,11 +2647,6 @@ void
 java_push_parser_context ()
 {
   create_new_parser_context (0);
-  if (ctxp->next)
-    {
-      ctxp->incomplete_class = ctxp->next->incomplete_class;
-      ctxp->gclass_list = ctxp->next->gclass_list;
-    }
 }  
 
 void 
@@ -2649,8 +2663,6 @@ java_pop_parser_context (generate)
   next = ctxp->next;
   if (next)
     {
-      next->incomplete_class = ctxp->incomplete_class;
-      next->gclass_list = ctxp->gclass_list;
       lineno = ctxp->lineno;
       current_class = ctxp->class_type;
     }
@@ -2662,12 +2674,12 @@ java_pop_parser_context (generate)
   /* Set the single import class file flag to 0 for the current list
      of imported things */
   for (current = ctxp->import_list; current; current = TREE_CHAIN (current))
-    IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_PURPOSE (current)) = 0;
+    IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_VALUE (current)) = 0;
 
   /* And restore those of the previous context */
   if ((ctxp = next))           /* Assignment is really meant here */
     for (current = ctxp->import_list; current; current = TREE_CHAIN (current))
-      IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_PURPOSE (current)) = 1;
+      IS_A_SINGLE_IMPORT_CLASSFILE_NAME_P (TREE_VALUE (current)) = 1;
   
   /* If we pushed a context to parse a class intended to be generated,
      we keep it so we can remember the class. What we could actually
@@ -2764,8 +2776,6 @@ java_parser_context_resume ()
   struct parser_ctxt *restored = saver->next; /* This one is the old current */
 
   /* We need to inherit the list of classes to complete/generate */
-  restored->incomplete_class = old->incomplete_class;
-  restored->gclass_list = old->gclass_list;
   restored->classd_list = old->classd_list;
   restored->class_list = old->class_list;
 
@@ -2777,8 +2787,8 @@ java_parser_context_resume ()
   ctxp = restored;
 
   /* Re-installed the data for the parsing to carry on */
-  bcopy (&old->marker_begining, &ctxp->marker_begining,
-        (size_t)(&ctxp->marker_end - &ctxp->marker_begining));
+  memcpy (&ctxp->marker_begining, &old->marker_begining, 
+         (size_t)(&ctxp->marker_end - &ctxp->marker_begining));
 
   /* Buffer context can now be discarded */
   free (saver);
@@ -2959,7 +2969,6 @@ yyerror (msg)
 
   int save_lineno;
   char *remainder, *code_from_source;
-  extern struct obstack temporary_obstack;
   
   if (!force_error && prev_lineno == lineno)
     return;
@@ -3157,7 +3166,7 @@ unreachable_stmt_error (node)
       parse_error_context (wfl_operator, "Unreachable statement");
     }
   else
-    fatal ("Can't get valid statement - unreachable_stmt_error");
+    abort ();
 }
 
 int
@@ -3248,6 +3257,8 @@ build_array_from_name (type, type_wfl, name, ret_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 */
@@ -3259,14 +3270,20 @@ build_array_from_name (type, type_wfl, name, ret_name)
       if (JPRIMITIVE_TYPE_P (type))
        {
          type = build_java_array_type (type, -1);
-         CLASS_LOADED_P (type) = 1;
          more_dims--;
        }
       /* Otherwise, if we have a WFL for this type, use it (the type
          is already an array on an unresolved type, and we just keep
          on adding dimensions) */
       else if (type_wfl)
-       type = type_wfl;
+       {
+         int i = 0;
+         type = type_wfl;
+         string = IDENTIFIER_POINTER (TYPE_NAME (save));
+         while (string[i]  == '[')
+           ++i;
+         more_dims += i;
+       }
 
       /* Add all the dimensions */
       while (more_dims--)
@@ -3291,23 +3308,26 @@ build_unresolved_array_type (type_or_wfl)
      tree type_or_wfl;
 {
   const char *ptr;
+  tree wfl;
 
   /* TYPE_OR_WFL might be an array on a resolved type. In this case,
      just create a array type */
   if (TREE_CODE (type_or_wfl) == RECORD_TYPE)
-    {
-      tree type = build_java_array_type (type_or_wfl, -1);
-      CLASS_LOADED_P (type) = CLASS_LOADED_P (type_or_wfl);
-      return type;
-    }
+    return build_java_array_type (type_or_wfl, -1);
 
   obstack_1grow (&temporary_obstack, '[');
   obstack_grow0 (&temporary_obstack,
                 IDENTIFIER_POINTER (EXPR_WFL_NODE (type_or_wfl)),
                 IDENTIFIER_LENGTH (EXPR_WFL_NODE (type_or_wfl)));
   ptr = obstack_finish (&temporary_obstack);
-  EXPR_WFL_NODE (type_or_wfl) = get_identifier (ptr);
-  return type_or_wfl;
+  wfl = build_expr_wfl (get_identifier (ptr),
+                       EXPR_WFL_FILENAME (type_or_wfl),
+                       EXPR_WFL_LINENO (type_or_wfl),
+                       EXPR_WFL_COLNO (type_or_wfl));
+  /* Re-install the existing qualifications so that the type can be
+     resolved properly. */
+  EXPR_WFL_QUALIFICATION (wfl) = EXPR_WFL_QUALIFICATION (type_or_wfl);
+  return wfl;
 }
 
 static void
@@ -3457,8 +3477,7 @@ make_nested_class_name (cpc_list)
   /* Why is NO_DOLLAR_IN_LABEL defined? */
 #if 0
 #ifdef NO_DOLLAR_IN_LABEL
-  fatal ("make_nested_class_name: Can't use '$' as a separator "
-        "for inner classes");
+  internal_error ("Can't use '$' as a separator for inner classes");
 #endif
 #endif
   obstack_1grow (&temporary_obstack, '$');
@@ -3517,7 +3536,18 @@ find_as_inner_class (enclosing, name, cl)
          acc = merge_qualified_name (acc, 
                                      EXPR_WFL_NODE (TREE_PURPOSE (qual)));
          BUILD_PTR_FROM_NAME (ptr, acc);
-         decl = do_resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
+
+         /* 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);
        }
 
       /* A NULL qual and a decl means that the search ended
@@ -3631,7 +3661,8 @@ maybe_create_class_interface_decl (decl, raw_name, qualified_name, cl)
   else
     DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
   CLASS_FROM_SOURCE_P (TREE_TYPE (decl)) = 1;
-  CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (TREE_TYPE (decl)) =
+  CLASS_PARSED_P (TREE_TYPE (decl)) = 1;
+  CLASS_FROM_CURRENTLY_COMPILED_P (TREE_TYPE (decl)) =
     IS_A_COMMAND_LINE_FILENAME_P (EXPR_WFL_FILENAME_NODE (cl));
 
   PUSH_CPC (decl, raw_name);
@@ -3642,7 +3673,7 @@ maybe_create_class_interface_decl (decl, raw_name, qualified_name, cl)
   ctxp->class_list = decl;
 
   /* Create a new nodes in the global lists */
-  ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list);
+  gclass_list = tree_cons (NULL_TREE, decl, gclass_list);
   all_class_list = tree_cons (NULL_TREE, decl, all_class_list);
 
   /* Install a new dependency list element */
@@ -3873,7 +3904,14 @@ create_class (flags, id, super, interfaces)
   else
     super_decl_type = NULL_TREE;
 
-  /* Set super info and mark the class a complete */
+  /* A class nested in an interface is implicitly static. */
+  if (INNER_CLASS_DECL_P (decl)
+      && CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (DECL_CONTEXT (decl)))))
+    {
+      flags |= ACC_STATIC;
+    }
+
+  /* Set super info and mark the class as complete. */
   set_super_info (flags, TREE_TYPE (decl), super_decl_type, 
                  ctxp->interface_number);
   ctxp->interface_number = 0;
@@ -3952,7 +3990,7 @@ add_inner_class_fields (class_decl, fct_decl)
          tree wfl, init, list;
          
          /* Avoid non final arguments. */
-         if (!LOCAL_FINAL (decl))
+         if (!LOCAL_FINAL_P (decl))
            continue;
          
          MANGLE_OUTER_LOCAL_VARIABLE_NAME (name, DECL_NAME (decl));
@@ -4044,7 +4082,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);
@@ -4185,11 +4223,29 @@ register_fields (flags, type, variable_list)
       field_decl = add_field (class_type, current_name, real_type, flags);
       CHECK_DEPRECATED (field_decl);
 
-      /* If the couple initializer/initialized is marked ARG_FINAL_P, we
-        mark the created field FIELD_LOCAL_ALIAS, so that we can 
-        hide parameters to this inner class finit$ and constructors. */
+      /* 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
+        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,
+        we mark the created field FIELD_LOCAL_ALIAS, so that we can
+        hide parameters to this inner class finit$ and
+        constructors. It also means that the field isn't final per
+        say. */
       if (ARG_FINAL_P (current))
-       FIELD_LOCAL_ALIAS (field_decl) = 1;
+       {
+         FIELD_LOCAL_ALIAS (field_decl) = 1;
+         FIELD_FINAL (field_decl) = 0;
+       }
       
       /* Check if we must chain. */
       if (must_chain)
@@ -4261,22 +4317,29 @@ generate_finit (class_type)
   return mdecl;
 }
 
-static void
-add_instance_initializer (mdecl)
+static tree
+build_instance_initializer (mdecl)
      tree mdecl;
 {
-  tree current;
-  tree stmt_list = TYPE_II_STMT_LIST (DECL_CONTEXT (mdecl));
   tree compound = NULL_TREE;
+  tree stmt_list = TYPE_II_STMT_LIST (DECL_CONTEXT (mdecl));
+  tree current;
 
-  if (stmt_list)
-    {
-      for (current = stmt_list; current; current = TREE_CHAIN (current))
-       compound = add_stmt_to_compound (compound, NULL_TREE, current);
+  for (current = stmt_list; current; current = TREE_CHAIN (current))
+    compound = add_stmt_to_compound (compound, NULL_TREE, current);
 
-      java_method_add_stmt (mdecl, build1 (INSTANCE_INITIALIZERS_EXPR,
-                                          NULL_TREE, compound));
-    }
+  return compound;
+}
+
+static void
+add_instance_initializer (mdecl)
+     tree mdecl;
+{
+  tree compound = build_instance_initializer (mdecl);
+
+  if (compound)
+    java_method_add_stmt (mdecl, build1 (INSTANCE_INITIALIZERS_EXPR,
+                                        NULL_TREE, compound));
 }
 
 /* Shared accros method_declarator and method_header to remember the
@@ -4476,15 +4539,8 @@ method_header (flags, type, mdecl, throws)
       DECL_FUNCTION_THROWS (meth) = throws;
     }
 
-  /* We set the DECL_NAME to ID so we can track the location where
-     the function was declared. This allow us to report
-     redefinition error accurately. When method are verified,
-     DECL_NAME is reinstalled properly (using the content of the
-     WFL node ID) (see check_method_redefinition). We don't do that
-     when Object is being defined. Constructor <init> names will be
-     reinstalled the same way. */
   if (TREE_TYPE (GET_CPC ()) != object_type_node)
-    DECL_NAME (meth) = id;
+    DECL_FUNCTION_WFL (meth) = id;
 
   /* Set the flag if we correctly processed a constructor */
   if (constructor_ok)
@@ -4544,21 +4600,21 @@ finish_method_declaration (method_body)
   /* 8.4.5 Method Body */
   if ((flags & ACC_ABSTRACT || flags & ACC_NATIVE) && method_body)
     {
-      tree wfl = DECL_NAME (current_function_decl);
-      parse_error_context (wfl
+      tree name = DECL_NAME (current_function_decl);
+      parse_error_context (DECL_FUNCTION_WFL (current_function_decl)
                           "%s method `%s' can't have a body defined",
                           (METHOD_NATIVE (current_function_decl) ?
                            "Native" : "Abstract"),
-                          IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
+                          IDENTIFIER_POINTER (name));
       method_body = NULL_TREE;
     }
   else if (!(flags & ACC_ABSTRACT) && !(flags & ACC_NATIVE) && !method_body)
     {
-      tree wfl = DECL_NAME (current_function_decl);
+      tree name = DECL_NAME (current_function_decl);
       parse_error_context
-       (wfl
+       (DECL_FUNCTION_WFL (current_function_decl)
         "Non native and non abstract method `%s' must have a body defined",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
+        IDENTIFIER_POINTER (name));
       method_body = NULL_TREE;
     }
 
@@ -4688,15 +4744,13 @@ check_abstract_method_header (meth)
      tree meth;
 {
   int flags = get_access_flags_from_decl (meth);
-  /* DECL_NAME might still be a WFL node */
-  tree name = GET_METHOD_NAME (meth);
 
   OBSOLETE_MODIFIER_WARNING2 (MODIFIER_WFL (ABSTRACT_TK), flags,
                              ACC_ABSTRACT, "abstract method",
-                             IDENTIFIER_POINTER (name));
+                             IDENTIFIER_POINTER (DECL_NAME (meth)));
   OBSOLETE_MODIFIER_WARNING2 (MODIFIER_WFL (PUBLIC_TK), flags, 
                              ACC_PUBLIC, "abstract method",
-                             IDENTIFIER_POINTER (name));
+                             IDENTIFIER_POINTER (DECL_NAME (meth)));
 
   check_modifiers ("Illegal modifier `%s' for interface method",
                  flags, INTERFACE_METHOD_MODIFIERS);
@@ -4870,8 +4924,10 @@ parser_check_super_interface (super_decl, this_decl, this_wfl)
       return 1;
     }
 
-  /* Check scope: same package OK, other package: OK if public */
-  if (check_pkg_class_access (DECL_NAME (super_decl), lookup_cl (this_decl)))
+  /* 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)))
     return 1;
 
   SOURCE_FRONTEND_DEBUG (("Completing interface %s with %s",
@@ -4907,8 +4963,10 @@ parser_check_super (super_decl, this_decl, wfl)
       return 1;
     }
 
-  /* Check scope: same package OK, other package: OK if public */
-  if (check_pkg_class_access (DECL_NAME (super_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)))
     return 1;
   
   SOURCE_FRONTEND_DEBUG (("Completing class %s with %s",
@@ -4952,26 +5010,17 @@ static tree
 obtain_incomplete_type (type_name)
      tree type_name;
 {
-  tree ptr, name;
+  tree ptr = NULL_TREE, name;
 
   if (TREE_CODE (type_name) == EXPR_WITH_FILE_LOCATION)
     name = EXPR_WFL_NODE (type_name);
   else if (INCOMPLETE_TYPE_P (type_name))
     name = TYPE_NAME (type_name);
   else
-    fatal ("invalid type name - obtain_incomplete_type");
-
-  for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
-    if (TYPE_NAME (ptr) == name)
-      break;
+    abort ();
 
-  if (!ptr)
-    {
-      BUILD_PTR_FROM_NAME (ptr, name);
-      layout_type (ptr);
-      TREE_CHAIN (ptr) = ctxp->incomplete_class;
-      ctxp->incomplete_class = ptr;
-    }
+  BUILD_PTR_FROM_NAME (ptr, name);
+  layout_type (ptr);
 
   return ptr;
 }
@@ -4993,7 +5042,7 @@ register_incomplete_type (kind, wfl, decl, ptr)
 
   JDEP_KIND (new) = kind;
   JDEP_DECL (new) = decl;
-  JDEP_SOLV (new) = ptr;
+  JDEP_TO_RESOLVE (new) = ptr;
   JDEP_WFL (new) = wfl;
   JDEP_CHAIN (new) = NULL;
   JDEP_MISC (new) = NULL_TREE;
@@ -5182,7 +5231,7 @@ craft_constructor (class_decl, args)
   fix_method_argument_names (parm, decl);
   /* Now, mark the artificial parameters. */
   DECL_FUNCTION_NAP (decl) = artificial;
-  DECL_CONSTRUCTOR_P (decl) = 1;
+  DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
 }
 
 
@@ -5206,6 +5255,7 @@ java_fix_constructors ()
       if (CLASS_INTERFACE (TYPE_NAME (class_type)))
        continue;
 
+      current_class = class_type;
       for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
        {
          if (DECL_CONSTRUCTOR_P (decl))
@@ -5238,7 +5288,6 @@ safe_layout_class (class)
   current_class = save_current_class;
   input_filename = save_input_filename;
   lineno = save_lineno;
-  CLASS_LOADED_P (class) = 1;
 }
 
 static tree
@@ -5259,7 +5308,16 @@ jdep_resolve_class (dep)
   if (!decl)
     complete_class_report_errors (dep);
   else if (PURE_INNER_CLASS_DECL_P (decl))
-    check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep));
+    {
+      tree inner = TREE_TYPE (decl);
+      if (! CLASS_LOADED_P (inner))
+       {
+         safe_layout_class (inner);
+         if (TYPE_SIZE (inner) == error_mark_node)
+           TYPE_SIZE (inner) = NULL_TREE;
+       }
+      check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep));
+    }
   return decl;
 }
 
@@ -5396,8 +5454,7 @@ java_complete_class ()
              break;
 
            default:
-             fatal ("Can't handle patch code %d - java_complete_class",
-                    JDEP_KIND (dep));
+             abort ();
            }
        }
     }
@@ -5450,20 +5507,12 @@ resolve_class (enclosing, class_type, decl, cl)
     {
       while (base != name)
        {
-         if (TREE_CODE (resolved_type) == RECORD_TYPE)
-           resolved_type  = promote_type (resolved_type);
          resolved_type = build_java_array_type (resolved_type, -1);
-         CLASS_LOADED_P (resolved_type) = 1;
          name--;
        }
-      /* Build a fake decl for this, since this is what is expected to
-         be returned.  */
-      resolved_type_decl =
-       build_decl (TYPE_DECL, TYPE_NAME (resolved_type), resolved_type);
-      /* Figure how those two things are important for error report. FIXME */
-      DECL_SOURCE_LINE (resolved_type_decl) = 0;
-      DECL_SOURCE_FILE (resolved_type_decl) = input_filename;
-      TYPE_NAME (class_type) = TYPE_NAME (resolved_type);
+      /* A TYPE_NAME that is a TYPE_DECL was set in
+         build_java_array_type, return it. */
+      resolved_type_decl = TYPE_NAME (resolved_type);
     }
   TREE_TYPE (class_type) = resolved_type;
   return resolved_type_decl;
@@ -5476,20 +5525,20 @@ tree
 do_resolve_class (enclosing, class_type, decl, cl)
      tree enclosing, class_type, decl, cl;
 {
-  tree new_class_decl;
+  tree new_class_decl, super, start;
 
   /* 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 */
 
   /* 0- Search in the current class as an inner class */
+  start = enclosing;
 
   /* 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 name;
       tree intermediate;
 
       if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl)))
@@ -5506,21 +5555,28 @@ do_resolve_class (enclosing, class_type, decl, cl)
        }
 
       /* Now go to the upper classes, bail out if necessary. */
-      enclosing = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
-      if (!enclosing || enclosing == object_type_node)
-       break;
-      
-      if (TREE_CODE (enclosing) == RECORD_TYPE)
-       {
-         enclosing = TYPE_NAME (enclosing);
-         continue;
-       }
+      super = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
+      if (!super || super == object_type_node)
+        break;
 
-      if (TREE_CODE (enclosing) == IDENTIFIER_NODE)
-       BUILD_PTR_FROM_NAME (name, enclosing);
+      if (TREE_CODE (super) == POINTER_TYPE)
+        super = do_resolve_class (NULL, super, NULL, NULL);
       else
-       name = enclosing;
-      enclosing = do_resolve_class (NULL, name, NULL, NULL);
+       super = TYPE_NAME (super);
+      /* We may not have checked for circular inheritance yet, so do so
+         here to prevent an infinite loop. */
+      if (super == start)
+        {
+          if (!cl)
+            cl = lookup_cl (decl);
+         
+          parse_error_context
+            (cl, "Cyclic inheritance involving %s",
+            IDENTIFIER_POINTER (DECL_NAME (enclosing)));
+          break;
+        }
+      enclosing = super;
     }
 
   /* 1- Check for the type in single imports. This will change
@@ -5573,10 +5629,19 @@ do_resolve_class (enclosing, class_type, decl, cl)
 
   /* 5- Check an other compilation unit that bears the name of type */
   load_class (TYPE_NAME (class_type), 0);
-  if (check_pkg_class_access (TYPE_NAME (class_type), 
-                             (cl ? cl : lookup_cl (decl))))
-    return NULL_TREE;
-
+  
+  if (!cl)
+    cl = lookup_cl (decl);
+  
+  /* If we don't have a value for CL, then we're being called recursively. 
+     We can't check package access just yet, but it will be taken care of
+     by the caller. */
+  if (cl)
+    {
+      if (check_pkg_class_access (TYPE_NAME (class_type), cl))
+        return NULL_TREE;
+    }
+  
   /* 6- Last call for a resolution */
   return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
 }
@@ -5782,50 +5847,6 @@ get_printable_method_name (decl)
   return to_return;
 }
 
-/* Reinstall the proper DECL_NAME on METHOD. Return 0 if the method
-   nevertheless needs to be verfied, 1 otherwise.  */
-
-static int
-reset_method_name (method)
-     tree method;
-{
-  if (!DECL_CLINIT_P (method) && !DECL_FINIT_P (method))
-    {
-      /* NAME is just the plain name when Object is being defined */
-      if (DECL_CONTEXT (method) != object_type_node)
-       DECL_NAME (method) = (DECL_CONSTRUCTOR_P (method) ? 
-                             init_identifier_node : GET_METHOD_NAME (method));
-      return 0;
-    }
-  else 
-    return 1;
-}
-
-/* Return the name of METHOD_DECL, when DECL_NAME is a WFL */
-
-tree
-java_get_real_method_name (method_decl)
-     tree method_decl;
-{
-  tree method_name = DECL_NAME (method_decl);
-  if (DECL_CONSTRUCTOR_P (method_decl))
-    return init_identifier_node;
-
-  /* Explain here why METHOD_DECL doesn't have the DECL_CONSTRUCTUR_P
-     and still can be a constructor. FIXME */
-
-  /* Don't confuse method only bearing the name of their class as
-     constructors */
-  else if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (method_decl))
-          && ctxp
-          && GET_CPC_UN () == EXPR_WFL_NODE (method_name)
-          && get_access_flags_from_decl (method_decl) <= ACC_PROTECTED
-          && TREE_TYPE (TREE_TYPE (method_decl)) == void_type_node)
-    return init_identifier_node;
-  else
-    return EXPR_WFL_NODE (method_name);
-}
-
 /* Track method being redefined inside the same class. As a side
    effect, set DECL_NAME to an IDENTIFIER (prior entering this
    function it's a FWL, so we can track errors more accurately.)  */
@@ -5834,28 +5855,23 @@ static int
 check_method_redefinition (class, method)
      tree class, method;
 {
-  tree redef, name;
-  tree cl = DECL_NAME (method);
-  tree sig = TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (method));
-  /* decl name of artificial <clinit> and finit$ doesn't need to be
-     fixed and checked */
+  tree redef, sig;
 
-  /* Reset the method name before running the check. If it returns 1,
-     the method doesn't need to be verified with respect to method
-     redeclaration and we return 0 */
-  if (reset_method_name (method))
+  /* There's no need to verify <clinit> and finit$ */
+  if (DECL_CLINIT_P (method) || DECL_FINIT_P (method))
     return 0;
 
-  name = DECL_NAME (method);
+  sig = TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (method));
   for (redef = TYPE_METHODS (class); redef; redef = TREE_CHAIN (redef))
     {
       if (redef == method)
        break;
-      if (DECL_NAME (redef) == name 
-         && sig == TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (redef)))
+      if (DECL_NAME (redef) == DECL_NAME (method)
+         && sig == TYPE_ARGUMENT_SIGNATURE (TREE_TYPE (redef))
+         && !DECL_ARTIFICIAL (method))
        {
          parse_error_context 
-           (cl, "Duplicate %s declaration `%s'",
+           (DECL_FUNCTION_WFL (method), "Duplicate %s declaration `%s'",
             (DECL_CONSTRUCTOR_P (redef) ? "constructor" : "method"),
             get_printable_method_name (redef));
          return 1;
@@ -5927,13 +5943,6 @@ check_abstract_method_definitions (do_interface, class_decl, type)
          char *t = xstrdup (lang_printable_name 
                            (TREE_TYPE (TREE_TYPE (method)), 0));
          tree ccn = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method)));
-         tree saved_wfl = NULL_TREE;
-         
-         if (TREE_CODE (DECL_NAME (method)) == EXPR_WITH_FILE_LOCATION)
-           {
-             saved_wfl = DECL_NAME (method);
-             DECL_NAME (method) = EXPR_WFL_NODE (DECL_NAME (method));
-           }
          
          parse_error_context 
            (lookup_cl (class_decl),
@@ -5947,9 +5956,6 @@ check_abstract_method_definitions (do_interface, class_decl, type)
             IDENTIFIER_POINTER (DECL_NAME (class_decl)));
          ok = 0;
          free (t);
-
-         if (saved_wfl)
-           DECL_NAME (method) = saved_wfl;
        }
     }
 
@@ -6051,7 +6057,7 @@ java_check_regular_methods (class_decl)
   int saw_constructor = ANONYMOUS_CLASS_P (TREE_TYPE (class_decl));
   tree method;
   tree class = CLASS_TO_HANDLE_TYPE (TREE_TYPE (class_decl));
-  tree saved_found_wfl = NULL_TREE, found = NULL_TREE;
+  tree found = NULL_TREE;
   tree mthrows;
 
   /* It is not necessary to check methods defined in java.lang.Object */
@@ -6065,17 +6071,9 @@ java_check_regular_methods (class_decl)
   for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
     {
       tree sig;
-      tree method_wfl = DECL_NAME (method);
+      tree method_wfl = DECL_FUNCTION_WFL (method);
       int aflags;
 
-      /* If we previously found something and its name was saved,
-         reinstall it now */
-      if (found && saved_found_wfl)
-       {
-         DECL_NAME (found) = saved_found_wfl;
-         saved_found_wfl = NULL_TREE;
-       }
-
       /* Check for redefinitions */
       if (check_method_redefinition (class, method))
        continue;
@@ -6123,11 +6121,6 @@ java_check_regular_methods (class_decl)
          continue;
        }
 
-      /* If found wasn't verified, it's DECL_NAME won't be set properly. 
-        We set it temporarily for the sake of the error report. */
-      saved_found_wfl = DECL_NAME (found);
-      reset_method_name (found);
-
       /* If `found' is declared in an interface, make sure the
         modifier matches. */
       if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (found))) 
@@ -6157,24 +6150,6 @@ java_check_regular_methods (class_decl)
        }
 
       aflags = get_access_flags_from_decl (found);
-      /* If the method has default, access in an other package, then
-        issue a warning that the current method doesn't override the
-        one that was found elsewhere. Do not issue this warning when
-        the match was found in java.lang.Object.  */
-      if (DECL_CONTEXT (found) != object_type_node
-         && ((aflags & ACC_VISIBILITY) == 0)
-         && !class_in_current_package (DECL_CONTEXT (found))
-         && !DECL_CLINIT_P (found)
-         && flag_not_overriding)
-        {
-         parse_warning_context 
-           (method_wfl, "Method `%s' in class `%s' does not override the corresponding method in class `%s', which is private to a different package",
-            lang_printable_name (found, 0),
-            IDENTIFIER_POINTER (DECL_NAME (class_decl)),
-            IDENTIFIER_POINTER (DECL_NAME 
-                                (TYPE_NAME (DECL_CONTEXT (found)))));
-         continue;
-       }
 
       /* Can't override final. Can't override static. */
       if (METHOD_FINAL (found) || METHOD_STATIC (found))
@@ -6236,13 +6211,6 @@ java_check_regular_methods (class_decl)
       /* Inheriting multiple methods with the same signature. FIXME */
     }
   
-  /* Don't forget eventual pending found and saved_found_wfl. Take
-     into account that we might have exited because we saw an
-     artificial method as the last entry. */
-
-  if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
-    DECL_NAME (found) = saved_found_wfl;
-
   if (!TYPE_NVIRTUALS (class))
     TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
 
@@ -6251,7 +6219,7 @@ java_check_regular_methods (class_decl)
   java_check_abstract_method_definitions (class_decl);
 
   if (!saw_constructor)
-    fatal ("No constructor found");
+    abort ();
 }
 
 /* Return a non zero value if the `throws' clause of METHOD (if any)
@@ -6302,8 +6270,6 @@ java_check_abstract_methods (interface_decl)
 
   for (method = TYPE_METHODS (interface); method; method = TREE_CHAIN (method))
     {
-      tree method_wfl = DECL_NAME (method);
-
       /* 2- Check for double definition inside the defining interface */
       if (check_method_redefinition (interface, method))
        continue;
@@ -6314,17 +6280,14 @@ java_check_abstract_methods (interface_decl)
       if (found)
        {
          char *t;
-         tree saved_found_wfl = DECL_NAME (found);
-         reset_method_name (found);
          t = xstrdup (lang_printable_name (TREE_TYPE (TREE_TYPE (found)), 0));
          parse_error_context 
-           (method_wfl,
+           (DECL_FUNCTION_WFL (found),
             "Method `%s' was defined with return type `%s' in class `%s'",
             lang_printable_name (found, 0), t,
             IDENTIFIER_POINTER 
               (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
          free (t);
-         DECL_NAME (found) = saved_found_wfl;
          continue;
        }
     }
@@ -6348,8 +6311,6 @@ java_check_abstract_methods (interface_decl)
                                                 sub_interface_method);
          if (found && (found != sub_interface_method))
            {
-             tree saved_found_wfl = DECL_NAME (found);
-             reset_method_name (found);
              parse_error_context 
                (lookup_cl (sub_interface_method),
                 "Interface `%s' inherits method `%s' from interface `%s'. This method is redefined with a different return type in interface `%s'",
@@ -6360,7 +6321,6 @@ java_check_abstract_methods (interface_decl)
                               (DECL_CONTEXT (sub_interface_method)))),
                 IDENTIFIER_POINTER 
                   (DECL_NAME (TYPE_NAME (DECL_CONTEXT (found)))));
-             DECL_NAME (found) = saved_found_wfl;
            }
        }
     }
@@ -6492,6 +6452,12 @@ process_imports ()
   for (import = ctxp->import_list; import; import = TREE_CHAIN (import))
     {
       tree to_be_found = EXPR_WFL_NODE (TREE_PURPOSE (import));
+      char *original_name;
+
+      obstack_grow0 (&temporary_obstack,
+                    IDENTIFIER_POINTER (to_be_found),
+                    IDENTIFIER_LENGTH (to_be_found));
+      original_name = obstack_finish (&temporary_obstack);
 
       /* Don't load twice something already defined. */
       if (IDENTIFIER_CLASS_VALUE (to_be_found))
@@ -6523,9 +6489,11 @@ process_imports ()
        {
          parse_error_context (TREE_PURPOSE (import),
                               "Class or interface `%s' not found in import",
-                              IDENTIFIER_POINTER (to_be_found));
-         return 1;
+                              original_name);
+         error_found = 1;
        }
+
+      obstack_free (&temporary_obstack, original_name);
       if (error_found)
        return 1;
     }
@@ -6749,9 +6717,16 @@ find_in_imports_on_demand (class_type)
         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);
+       {
+         load_class (node_to_use, 0);
+         decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+       }
       lineno = saved_lineno;
-      return check_pkg_class_access (TYPE_NAME (class_type), cl);
+      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;
     }
   else
     return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */
@@ -6812,35 +6787,6 @@ resolve_package (pkg, next)
 
   *next = EXPR_WFL_QUALIFICATION (pkg);
 
-  /* Try the current package. */
-  if (ctxp->package && !strncmp (name, IDENTIFIER_POINTER (ctxp->package),  
-                                IDENTIFIER_LENGTH (ctxp->package)))
-    {
-      type_name = 
-       lookup_package_type_and_set_next (name, 
-                                         IDENTIFIER_LENGTH (ctxp->package), 
-                                         next );
-      if (type_name)
-       return type_name;
-    }
-
-  /* Search in imported package */
-  for (current = ctxp->import_list; current; current = TREE_CHAIN (current))
-    {
-      tree current_pkg_name = EXPR_WFL_NODE (TREE_PURPOSE (current));
-      int len = IDENTIFIER_LENGTH (current_pkg_name);
-      if (!strncmp (name, IDENTIFIER_POINTER (current_pkg_name), len))
-       {
-         tree left, dummy;
-         
-         breakdown_qualified (&left, &dummy, current_pkg_name);
-         len = IDENTIFIER_LENGTH (left);
-         type_name = lookup_package_type_and_set_next (name, len, next);
-         if (type_name)
-           break;
-       }
-    }
-
   /* Try to progressively construct a type name */
   if (TREE_CODE (pkg) == EXPR_WITH_FILE_LOCATION)
     for (acc = NULL_TREE, current = EXPR_WFL_QUALIFICATION (pkg); 
@@ -6861,27 +6807,6 @@ resolve_package (pkg, next)
 }
 
 static tree
-lookup_package_type_and_set_next (name, len, next)
-     const char *name;
-     int len;
-     tree *next;
-{
-  const char *ptr;
-  tree type_name = lookup_package_type (name, len);
-
-  if (!type_name)
-    return NULL;
-  
-  ptr = IDENTIFIER_POINTER (type_name);
-  while (ptr && (ptr = strchr (ptr, '.'))) 
-    {
-      *next = TREE_CHAIN (*next);
-      ptr++;
-    }
-  return type_name;
-}
-
-static tree
 lookup_package_type (name, from)
      const char *name;
      int from;
@@ -6895,11 +6820,16 @@ lookup_package_type (name, from)
   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
+   access is being attempted. */
+
 static void
 check_inner_class_access (decl, enclosing_decl, cl)
      tree decl, enclosing_decl, cl;
 {
-  int access = 0;
+  const char *access;
+  tree enclosing_decl_type;
 
   /* We don't issue an error message when CL is null. CL can be null
      as a result of processing a JDEP crafted by source_start_java_method
@@ -6909,30 +6839,69 @@ check_inner_class_access (decl, enclosing_decl, cl)
   if (!decl || !cl)
     return;
 
-  /* We grant access to private and protected inner classes if the
-     location from where we're trying to access DECL is an enclosing
-     context for DECL or if both have a common enclosing context. */
+  enclosing_decl_type = TREE_TYPE (enclosing_decl);
+
   if (CLASS_PRIVATE (decl))
-    access = 1;
-  if (CLASS_PROTECTED (decl))
-    access = 2;
-  if (!access)
-    return;
+    {
+      /* Access is permitted only within the body of the top-level
+         class in which DECL is declared. */
+      tree top_level = decl;
+      while (DECL_CONTEXT (top_level))
+        top_level = DECL_CONTEXT (top_level);      
+      while (DECL_CONTEXT (enclosing_decl))
+        enclosing_decl = DECL_CONTEXT (enclosing_decl);
+      if (top_level == enclosing_decl)
+        return;      
+      access = "private";
+    }
+  else if (CLASS_PROTECTED (decl))
+    {
+      tree decl_context;
+      /* Access is permitted from within the same package... */
+      if (in_same_package (decl, enclosing_decl))
+        return;
       
-  if (common_enclosing_context_p (TREE_TYPE (enclosing_decl),
-                                 TREE_TYPE (decl))
-      || enclosing_context_p (TREE_TYPE (enclosing_decl),
-                             TREE_TYPE (decl)))
+      /* ... or from within the body of a subtype of the context in which
+         DECL is declared. */
+      decl_context = DECL_CONTEXT (decl);
+      while (enclosing_decl)
+        {
+         if (CLASS_INTERFACE (decl))
+           {
+             if (interface_of_p (TREE_TYPE (decl_context), 
+                                 enclosing_decl_type))
+               return;
+           }
+         else
+           {
+             /* Eww. The order of the arguments is different!! */
+             if (inherits_from_p (enclosing_decl_type, 
+                                  TREE_TYPE (decl_context)))
+               return;
+           }
+         enclosing_decl = DECL_CONTEXT (enclosing_decl);
+       }      
+      access = "protected";
+    }
+  else if (! CLASS_PUBLIC (decl))
+    {
+      /* Access is permitted only from within the same package as DECL. */
+      if (in_same_package (decl, enclosing_decl))
+        return;
+      access = "non-public";
+    }
+  else
+    /* Class is public. */
     return;
 
-  parse_error_context (cl, "Can't access %s nested %s %s. Only public classes and interfaces in other packages can be accessed",
-                      (access == 1 ? "private" : "protected"),
+  parse_error_context (cl, "Nested %s %s is %s; cannot be accessed from here",
                       (CLASS_INTERFACE (decl) ? "interface" : "class"),
-                      lang_printable_name (decl, 0));
+                      lang_printable_name (decl, 0), access);
 }
 
-/* Check that CLASS_NAME refers to a PUBLIC class. 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.  */
 
 static int
 check_pkg_class_access (class_name, cl)
@@ -6941,7 +6910,7 @@ check_pkg_class_access (class_name, cl)
 {
   tree type;
 
-  if (!QUALIFIED_P (class_name) || !IDENTIFIER_CLASS_VALUE (class_name))
+  if (!IDENTIFIER_CLASS_VALUE (class_name))
     return 0;
 
   if (!(type = TREE_TYPE (IDENTIFIER_CLASS_VALUE (class_name))))
@@ -6953,7 +6922,11 @@ check_pkg_class_access (class_name, cl)
          allowed. */
       tree l, r;
       breakdown_qualified (&l, &r, class_name);
+      if (!QUALIFIED_P (class_name) && !ctxp->package)
+       /* Both in the empty package. */
+        return 0;
       if (l == ctxp->package)
+       /* Both in the same package. */
        return 0;
 
       parse_error_context 
@@ -6979,12 +6952,11 @@ declare_local_variables (modifier, type, vlist)
   int final_p = 0;
 
   /* Push a new block if statements were seen between the last time we
-     pushed a block and now. Keep a cound of block to close */
+     pushed a block and now. Keep a count of blocks to close */
   if (BLOCK_EXPR_BODY (GET_CURRENT_BLOCK (current_function_decl)))
     {
-      tree body = GET_CURRENT_BLOCK (current_function_decl);
       tree b = enter_block ();
-      BLOCK_EXPR_ORIGIN (b) = body;
+      BLOCK_IS_IMPLICIT (b) = 1;
     }
 
   if (modifier)
@@ -7039,6 +7011,7 @@ declare_local_variables (modifier, type, vlist)
       /* Never layout this decl. This will be done when its scope
         will be entered */
       decl = build_decl (VAR_DECL, name, real_type);
+      MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
       LOCAL_FINAL (decl) = final_p;
       BLOCK_CHAIN_DECL (decl);
       
@@ -7116,7 +7089,10 @@ source_start_java_method (fndecl)
       /* Remember if a local variable was declared final (via its
          TREE_LIST of type/name.) Set LOCAL_FINAL accordingly. */
       if (ARG_FINAL_P (tem))
-       LOCAL_FINAL (parm_decl) = 1;
+       {
+         MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (parm_decl);
+         LOCAL_FINAL (parm_decl) = 1;
+       }
 
       BLOCK_CHAIN_DECL (parm_decl);
     }
@@ -7164,57 +7140,20 @@ static void
 end_artificial_method_body (mdecl)
      tree mdecl;
 {
-  BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)) = exit_block ();
+  /* exit_block modifies DECL_FUNCTION_BODY (current_function_decl).
+     It has to be evaluated first. (if mdecl is current_function_decl,
+     we have an undefined behavior if no temporary variable is used.) */
+  tree b = exit_block ();
+  BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (mdecl)) = b;
   exit_block ();
 }
 
-/* Called during expansion. Push decls formerly built from argument
-   list so they're usable during expansion. */
-
-static void
-expand_start_java_method (fndecl)
-     tree fndecl;
-{
-  tree tem, *ptr;
-
-  current_function_decl = fndecl;
-
-  if (! quiet_flag)
-    fprintf (stderr, " [%s.", lang_printable_name (DECL_CONTEXT (fndecl), 0));
-  announce_function (fndecl);
-  if (! quiet_flag)
-    fprintf (stderr, "]");
-
-  pushlevel (1);               /* Prepare for a parameter push */
-  ptr = &DECL_ARGUMENTS (fndecl);
-  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 (fndecl));
-  lineno = DECL_SOURCE_LINE_FIRST (fndecl);
-}
-
 /* Terminate a function and expand its body.  */
 
 static void
 source_end_java_method ()
 {
   tree fndecl = current_function_decl;
-  int flag_asynchronous_exceptions = asynchronous_exceptions;
 
   if (!fndecl)
     return;
@@ -7222,9 +7161,6 @@ source_end_java_method ()
   java_parser_context_save_global ();
   lineno = ctxp->last_ccb_indent1;
 
-  /* Set EH language codes */
-  java_set_exception_lang_code ();
-
   /* Turn function bodies with only a NOP expr null, so they don't get
      generated at all and we won't get warnings when using the -W
      -Wall flags. */
@@ -7246,24 +7182,14 @@ source_end_java_method ()
   if (! flag_emit_class_files && ! flag_emit_xref)
     {
       lineno = DECL_SOURCE_LINE_LAST (fndecl);
-      /* Emit catch-finally clauses */
-      emit_handlers ();
       expand_function_end (input_filename, lineno, 0);
 
-      /* FIXME: If the current method contains any exception handlers,
-        force asynchronous_exceptions: this is necessary because signal
-        handlers in libjava may throw exceptions.  This is far from being
-        a perfect solution, but it's better than doing nothing at all.*/
-      if (catch_clauses)
-       asynchronous_exceptions = 1;
-
       /* Run the optimizers and output assembler code for this function. */
       rest_of_compilation (fndecl);
     }
 
   current_function_decl = NULL_TREE;
   java_parser_context_restore_global ();
-  asynchronous_exceptions = flag_asynchronous_exceptions;
 }
 
 /* Record EXPR in the current function block. Complements compound
@@ -7344,7 +7270,7 @@ java_reorder_fields ()
       initialized_p = 1;
     }
 
-  for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
+  for (current = gclass_list; current; current = TREE_CHAIN (current))
     {
       current_class = TREE_TYPE (TREE_VALUE (current));
 
@@ -7374,11 +7300,11 @@ java_reorder_fields ()
          }
       }
     }
-  stop_reordering = TREE_TYPE (TREE_VALUE (ctxp->gclass_list));
+  stop_reordering = TREE_TYPE (TREE_VALUE (gclass_list));
 }
 
-/* Layout the methods of all classes loaded in one way on an
-   other. Check methods of source parsed classes. Then reorder the
+/* Layout the methods of all classes loaded in one way or another.
+   Check methods of source parsed classes. Then reorder the
    fields and layout the classes or the type of all source parsed
    classes */
 
@@ -7394,19 +7320,16 @@ java_layout_classes ()
   all_class_list = NULL_TREE;
 
   /* Then check the methods of all parsed classes */
-  for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
+  for (current = gclass_list; current; current = TREE_CHAIN (current))
     if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
       java_check_methods (TREE_VALUE (current));
   java_parse_abort_on_error ();
 
-  for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
+  for (current = gclass_list; current; current = TREE_CHAIN (current))
     {
       current_class = TREE_TYPE (TREE_VALUE (current));
       layout_class (current_class);
 
-      /* From now on, the class is considered completely loaded */
-      CLASS_LOADED_P (current_class) = 1;
-
       /* Error reported by the caller */
       if (java_error_count)
        return;
@@ -7472,6 +7395,14 @@ java_complete_expand_methods (class_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 ();
 
@@ -7504,7 +7435,15 @@ 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);
@@ -7532,10 +7471,17 @@ 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 */
@@ -7550,6 +7496,15 @@ 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;
 }
@@ -7615,7 +7570,7 @@ maybe_generate_pre_expand_clinit (class_type)
 }
 
 /* Analyzes a method body and look for something that isn't a
-   MODIFY_EXPR. */
+   MODIFY_EXPR with a constant value.  */
 
 static int
 analyze_clinit_body (bbody)
@@ -7639,11 +7594,10 @@ analyze_clinit_body (bbody)
        break;
        
       case MODIFY_EXPR:
-       bbody = NULL_TREE;
-       break;
+       /* Return 0 if the operand is constant, 1 otherwise.  */
+       return ! TREE_CONSTANT (TREE_OPERAND (bbody, 1));
 
       default:
-       bbody = NULL_TREE;
        return 1;
       }
   return 0;
@@ -7690,7 +7644,7 @@ maybe_yank_clinit (mdecl)
        continue;
 
       /* Anything that isn't String or a basic type is ruled out -- or
-        if we now how to deal with it (when doing things natively) we
+        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))
@@ -7756,7 +7710,39 @@ java_complete_expand_method (mdecl)
       tree fbody = DECL_FUNCTION_BODY (mdecl);
       tree block_body = BLOCK_EXPR_BODY (fbody);
       tree exception_copy = NULL_TREE;
-      expand_start_java_method (mdecl);
+      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 
@@ -7812,7 +7798,7 @@ java_complete_expand_method (mdecl)
       /* Pop the exceptions and sanity check */
       POP_EXCEPTIONS();
       if (currently_caught_type_list)
-       fatal ("Exception list non empty - java_complete_expand_method");
+       abort ();
 
       if (flag_emit_xref)
        DECL_FUNCTION_THROWS (mdecl) = exception_copy;
@@ -7837,11 +7823,13 @@ build_outer_field_access (id, decl)
 {
   tree access = NULL_TREE;
   tree ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
+  tree decl_ctx = DECL_CONTEXT (decl);
 
-  /* If decl's class is the direct outer class of the current_class,
-     build the access as `this$<n>.<field>'. Note that we will break
-     the `private' barrier if we're not emitting bytecodes. */
-  if (ctx == DECL_CONTEXT (decl) 
+  /* If the immediate enclosing context of the current class is the
+     field decl's class or inherits from it; build the access as
+     `this$<n>.<field>'. Note that we will break the `private' barrier
+     if we're not emitting bytecodes. */
+  if ((ctx == decl_ctx || inherits_from_p (ctx, decl_ctx))
       && (!FIELD_PRIVATE (decl) || !flag_emit_class_files ))
     {
       tree thisn = build_current_thisn (current_class);
@@ -7857,14 +7845,14 @@ build_outer_field_access (id, decl)
       /* Now we chain the required number of calls to the access$0 to
         get a hold to the enclosing instance we need, and then we
         build the field access. */
-      access = build_access_to_thisn (current_class, DECL_CONTEXT (decl), lc);
+      access = build_access_to_thisn (current_class, decl_ctx, lc);
 
       /* If the field is private and we're generating bytecode, then
          we generate an access method */
       if (FIELD_PRIVATE (decl) && flag_emit_class_files )
        {
          tree name = build_outer_field_access_methods (decl);
-         access = build_outer_field_access_expr (lc, DECL_CONTEXT (decl),
+         access = build_outer_field_access_expr (lc, decl_ctx,
                                                  name, access, NULL_TREE);
        }
       /* Otherwise we use `access$(this$<j>). ... access$(this$<i>).<field>'.
@@ -7887,14 +7875,26 @@ outer_field_access_p (type, decl)
       || TREE_CODE (decl) != FIELD_DECL
       || DECL_CONTEXT (decl) == type)
     return 0;
+  
+  /* If the inner class extends the declaration context of the field
+     we're try to acces, then this isn't an outer field access */
+  if (inherits_from_p (type, DECL_CONTEXT (decl)))
+    return 0;
 
   for (type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type))); ;
        type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type))))
     {
       if (type == DECL_CONTEXT (decl))
        return 1;
+
       if (!DECL_CONTEXT (TYPE_NAME (type)))
-       break;
+       {
+         /* Before we give up, see whether the field is inherited from
+            the enclosing context we're considering. */
+         if (inherits_from_p (type, DECL_CONTEXT (decl)))
+           return 1;
+         break;
+       }
     }
 
   return 0;
@@ -8031,14 +8031,11 @@ build_outer_field_access_methods (decl)
 {
   tree id, args, stmt, mdecl;
   
-  /* Check point, to be removed. FIXME */
-  if (FIELD_INNER_ACCESS (decl) 
-      && TREE_CODE (FIELD_INNER_ACCESS (decl)) != IDENTIFIER_NODE)
-    abort ();
-
-  if (FIELD_INNER_ACCESS (decl))
+  if (FIELD_INNER_ACCESS_P (decl))
     return FIELD_INNER_ACCESS (decl);
 
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
   /* Create the identifier and a function named after it. */
   id = build_new_access_id ();
 
@@ -8056,17 +8053,21 @@ build_outer_field_access_methods (decl)
                                           TREE_TYPE (decl), id, args, stmt);
   DECL_FUNCTION_ACCESS_DECL (mdecl) = decl;
 
-  /* Create the write access method */
-  args = build_tree_list (inst_id, build_pointer_type (DECL_CONTEXT (decl)));
-  TREE_CHAIN (args) = build_tree_list (wpv_id, TREE_TYPE (decl));
-  TREE_CHAIN (TREE_CHAIN (args)) = end_params_node;
-  stmt = make_qualified_primary (build_wfl_node (inst_id),
-                                build_wfl_node (DECL_NAME (decl)), 0);
-  stmt = build_return (0, build_assignment (ASSIGN_TK, 0, stmt,
-                                           build_wfl_node (wpv_id)));
-
-  mdecl = build_outer_field_access_method (DECL_CONTEXT (decl), 
-                                          TREE_TYPE (decl), id, args, stmt);
+  /* Create the write access method. No write access for final variable */
+  if (!FIELD_FINAL (decl))
+    {
+      args = build_tree_list (inst_id, 
+                             build_pointer_type (DECL_CONTEXT (decl)));
+      TREE_CHAIN (args) = build_tree_list (wpv_id, TREE_TYPE (decl));
+      TREE_CHAIN (TREE_CHAIN (args)) = end_params_node;
+      stmt = make_qualified_primary (build_wfl_node (inst_id),
+                                    build_wfl_node (DECL_NAME (decl)), 0);
+      stmt = build_return (0, build_assignment (ASSIGN_TK, 0, stmt,
+                                               build_wfl_node (wpv_id)));
+      mdecl = build_outer_field_access_method (DECL_CONTEXT (decl), 
+                                              TREE_TYPE (decl), id, 
+                                              args, stmt);
+    }
   DECL_FUNCTION_ACCESS_DECL (mdecl) = decl;
 
   /* Return the access name */
@@ -8216,8 +8217,13 @@ build_access_to_thisn (from, to, lc)
          access = build_method_invocation (access0_wfl, access);
          access = make_qualified_primary (cn, access, lc);
        }
-      
-      from = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (from)));
+
+      /* if FROM isn't an inter 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;
+      from = TREE_TYPE (from);
     }
   return access;
 }
@@ -8238,7 +8244,7 @@ maybe_build_thisn_access_method (type)
 
   /* If TYPE is a top-level class, no access method is required.
      If there already is such an access method, bail out. */
-  if (CLASS_ACCESS0_GENERATED_P (type) || !INNER_CLASS_TYPE_P (type))
+  if (CLASS_ACCESS0_GENERATED_P (type) || !PURE_INNER_CLASS_TYPE_P (type))
     return NULL_TREE;
 
   /* We generate the method. The method looks like:
@@ -8390,7 +8396,7 @@ build_dot_class_method (class)
   /* Create the "class$" function */
   mdecl = create_artificial_method (class, ACC_STATIC, 
                                    build_pointer_type (class_type_node),
-                                   get_identifier ("class$"), args);
+                                   classdollar_identifier_node, args);
   DECL_FUNCTION_THROWS (mdecl) = build_tree_list (NULL_TREE,
                                                  no_class_def_found_error);
   
@@ -8427,7 +8433,7 @@ build_dot_class_method (class)
   
   /* We initialize the variable with the exception handler. */
   catch = build (MODIFY_EXPR, NULL_TREE, catch_clause_param,
-                soft_exceptioninfo_call_node);
+                build (JAVA_EXC_OBJ_EXPR, ptr_type_node));
   add_stmt_to_block (catch_block, NULL_TREE, catch);
 
   /* We add the statement throwing the new exception */
@@ -8464,7 +8470,7 @@ build_dot_class_method_invocation (type)
 
   s = build_string (IDENTIFIER_LENGTH (sig_id), 
                    IDENTIFIER_POINTER (sig_id));
-  return build_method_invocation (build_wfl_node (get_identifier ("class$")),
+  return build_method_invocation (build_wfl_node (classdollar_identifier_node),
                                  build_tree_list (NULL_TREE, s));
 }
 
@@ -8482,6 +8488,10 @@ fix_constructors (mdecl)
   tree thisn_assign, compound = NULL_TREE;
   tree class_type = DECL_CONTEXT (mdecl);
 
+  if (DECL_FIXED_CONSTRUCTOR_P (mdecl))
+    return;
+  DECL_FIXED_CONSTRUCTOR_P (mdecl) = 1;
+
   if (!body)
     {
       /* It is an error for the compiler to generate a default
@@ -8513,7 +8523,7 @@ fix_constructors (mdecl)
       /* We don't generate a super constructor invocation if we're
         compiling java.lang.Object. build_super_invocation takes care
         of that. */
-      compound = java_method_add_stmt (mdecl, build_super_invocation (mdecl));
+      java_method_add_stmt (mdecl, build_super_invocation (mdecl));
 
       /* Insert the instance initializer block right here, after the
          super invocation. */
@@ -8525,7 +8535,9 @@ fix_constructors (mdecl)
   else 
     {
       int found = 0;
+      tree found_call = NULL_TREE;
       tree main_block = BLOCK_EXPR_BODY (body);
+      tree ii;                 /* Instance Initializer */
       
       while (body)
        switch (TREE_CODE (body))
@@ -8536,27 +8548,38 @@ fix_constructors (mdecl)
            break;
          case COMPOUND_EXPR:
          case EXPR_WITH_FILE_LOCATION:
+           found_call = body;
            body = TREE_OPERAND (body, 0);
            break;
          case BLOCK:
+           found_call = body;
            body = BLOCK_EXPR_BODY (body);
            break;
          default:
            found = 0;
            body = NULL_TREE;
          }
+
+      /* Generate the assignment to this$<n>, if necessary */
+      if ((thisn_assign = build_thisn_assign ()))
+        compound = add_stmt_to_compound (compound, NULL_TREE, thisn_assign);
+
       /* The constructor is missing an invocation of super() */
       if (!found)
        compound = add_stmt_to_compound (compound, NULL_TREE,
                                          build_super_invocation (mdecl));
+      /* Explicit super() invokation should take place before the
+         instance initializer blocks. */
+      else
+       {
+         compound = add_stmt_to_compound (compound, NULL_TREE,
+                                          TREE_OPERAND (found_call, 0));
+         TREE_OPERAND (found_call, 0) = empty_stmt_node;
+       }
       
-      /* Generate the assignment to this$<n>, if necessary */
-      if ((thisn_assign = build_thisn_assign ()))
-        compound = add_stmt_to_compound (compound, NULL_TREE, thisn_assign);
-
-      /* Insert the instance initializer block right here, after the
-         super invocation. */
-      add_instance_initializer (mdecl);
+      /* Insert the instance initializer block right after. */
+      if ((ii = build_instance_initializer (mdecl)))
+       compound = add_stmt_to_compound (compound, NULL_TREE, ii);
 
       /* Fix the constructor main block if we're adding extra stmts */
       if (compound)
@@ -8627,7 +8650,7 @@ void
 java_expand_classes ()
 {
   int save_error_count = 0;
-  static struct parser_ctxt *saved_ctxp = NULL;
+  static struct parser_ctxt *cur_ctxp = NULL;
 
   java_parse_abort_on_error ();
   if (!(ctxp = ctxp_for_generation))
@@ -8635,22 +8658,23 @@ java_expand_classes ()
   java_layout_classes ();
   java_parse_abort_on_error ();
 
-  saved_ctxp = ctxp_for_generation;
-  for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
+  cur_ctxp = ctxp_for_generation;
+  for (; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
-      ctxp = ctxp_for_generation;
+      ctxp = cur_ctxp;
+      input_filename = ctxp->filename;
       lang_init_source (2);           /* Error msgs have method prototypes */
       java_complete_expand_classes (); /* Complete and expand classes */
       java_parse_abort_on_error ();
     }
+  input_filename = main_input_filename;
 
   /* Find anonymous classes and expand their constructor, now they
      have been fixed. */
-  for (ctxp_for_generation = saved_ctxp;
-       ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
+  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
     {
       tree current;
-      ctxp = ctxp_for_generation;
+      ctxp = cur_ctxp;
       for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
        {
          current_class = TREE_TYPE (current);
@@ -8662,7 +8686,6 @@ java_expand_classes ()
                  if (DECL_CONSTRUCTOR_P (d))
                    {
                      restore_line_number_status (1);
-                     reset_method_name (d);
                      java_complete_expand_method (d);
                      restore_line_number_status (0);
                      break;    /* We now there are no other ones */
@@ -8681,11 +8704,10 @@ java_expand_classes ()
     return;
 
   /* Now things are stable, go for generation of the class data. */
-  for (ctxp_for_generation = saved_ctxp;
-       ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
+  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
     {
       tree current;
-      ctxp = ctxp_for_generation;
+      ctxp = cur_ctxp;
       for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
        {
          current_class = TREE_TYPE (current);
@@ -8806,7 +8828,9 @@ cut_identifier_in_qualified (wfl)
     if (!TREE_CHAIN (q))
       {
        if (!previous)
-         fatal ("Operating on a non qualified qualified WFL - cut_identifier_in_qualified");
+         /* Operating on a non qualified qualified WFL.  */
+         abort ();
+
        TREE_CHAIN (previous) = NULL_TREE;
        return TREE_PURPOSE (q);
       }
@@ -8855,7 +8879,8 @@ resolve_expression_name (id, orig)
                }
              /* Instance variables can't appear as an argument of
                 an explicit constructor invocation */
-             if (!fs && ctxp->explicit_constructor_p)
+             if (!fs && ctxp->explicit_constructor_p
+                 && !enclosing_context_p (DECL_CONTEXT (decl), current_class))
                {
                  parse_error_context
                    (id, "Can't reference `%s' before the superclass constructor has been called", IDENTIFIER_POINTER (name));
@@ -8866,13 +8891,20 @@ resolve_expression_name (id, orig)
                 to access a field belonging to an outer class, build
                 the access to the field */
              if (!fs && outer_field_access_p (current_class, decl))
-               return build_outer_field_access (id, decl);
+               {
+                 if (CLASS_STATIC (TYPE_NAME (current_class)))
+                   {
+                     static_ref_err (id, DECL_NAME (decl), current_class);
+                     return error_mark_node;
+                   }
+                 return build_outer_field_access (id, decl);
+               }
 
              /* Otherwise build what it takes to access the field */
              access = build_field_ref ((fs ? NULL_TREE : current_this),
                                        DECL_CONTEXT (decl), name);
-             if (fs && !flag_emit_class_files && !flag_emit_xref)
-               access = build_class_init (DECL_CONTEXT (access), access);
+             if (fs)
+               access = maybe_build_class_init_for_field (decl, access);
              /* We may be asked to save the real field access node */
              if (orig)
                *orig = access;
@@ -8935,8 +8967,7 @@ resolve_field_access (qual_wfl, field_decl, field_type)
       && ! flag_emit_class_files && ! flag_emit_xref)
     {
       tree length = build_java_array_length_access (where_found);
-      field_ref =
-       build_java_arraynull_check (type_found, length, int_type_node);
+      field_ref = length;
 
       /* In case we're dealing with a static array, we need to
         initialize its class before the array length can be fetched.
@@ -8956,29 +8987,16 @@ resolve_field_access (qual_wfl, field_decl, field_type)
     field_ref = decl;
   else if (JDECL_P (decl))
     {
-      int static_final_found = 0;
       if (!type_found)
        type_found = DECL_CONTEXT (decl);
-      is_static = JDECL_P (decl) && FIELD_STATIC (decl);
-      if (FIELD_FINAL (decl) && FIELD_STATIC (decl)
-         && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
-         && DECL_INITIAL (decl))
-       {
-         /* When called on a FIELD_DECL of the right (primitive)
-            type, java_complete_tree will try to substitue the decl
-            for it's initial value. */
-         field_ref = java_complete_tree (decl);
-         static_final_found = 1;
-       }
-      else
-       field_ref = build_field_ref ((is_static && !flag_emit_xref? 
-                                     NULL_TREE : where_found), 
-                                    type_found, DECL_NAME (decl));
+      is_static = FIELD_STATIC (decl);
+      field_ref = build_field_ref ((is_static && !flag_emit_xref? 
+                                   NULL_TREE : where_found), 
+                                  type_found, DECL_NAME (decl));
       if (field_ref == error_mark_node)
        return error_mark_node;
-      if (is_static && !static_final_found 
-         && !flag_emit_class_files && !flag_emit_xref)
-       field_ref = build_class_init (DECL_CONTEXT (decl), field_ref);
+      if (is_static)
+       field_ref = maybe_build_class_init_for_field (decl, field_ref);
     }
   else
     field_ref = decl;
@@ -9088,7 +9106,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
            CALL_USING_SUPER (qual_wfl) = 1;
          location = (TREE_CODE (qual_wfl) == CALL_EXPR ?
                      EXPR_WFL_LINECOL (TREE_OPERAND (qual_wfl, 0)) : 0);
-         *where_found = patch_method_invocation (qual_wfl, decl, type, 
+         *where_found = patch_method_invocation (qual_wfl, decl, type,
+                                                 from_super,
                                                  &is_static, &ret_decl);
          if (*where_found == error_mark_node)
            {
@@ -9144,7 +9163,6 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
          if (decl == error_mark_node)
            return 1;
          *type_found = type = QUAL_DECL_TYPE (decl);
-         CLASS_LOADED_P (type) = 1;
          continue;
 
        case CONVERT_EXPR:
@@ -9206,7 +9224,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)
            {
@@ -9214,7 +9233,8 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                (wfl, "Keyword `this' used outside allowed context");
              return 1;
            }
-         if (ctxp->explicit_constructor_p)
+         if (ctxp->explicit_constructor_p
+             && type == current_class)
            {
              parse_error_context (wfl, "Can't reference `this' before the superclass constructor has been called");
              return 1;
@@ -9256,7 +9276,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 */
@@ -9340,7 +9361,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              return 1;
            }
 
-         if (not_accessible_p (TREE_TYPE (decl), decl, 0))
+         if (not_accessible_p (TREE_TYPE (decl), decl, type, 0))
            {
              parse_error_context 
                (qual_wfl, "Can't access %s field `%s.%s' from `%s'",
@@ -9415,8 +9436,9 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              field_decl = lookup_field_wrapper (type,
                                                 EXPR_WFL_NODE (qual_wfl));
 
-             /* Maybe what we're trying to access an inner class. */
-             if (!field_decl)
+             /* Maybe what we're trying to access to is an inner
+                class, only if decl is a TYPE_DECL. */
+             if (!field_decl && TREE_CODE (decl) == TYPE_DECL)
                {
                  tree ptr, inner_decl;
 
@@ -9455,11 +9477,10 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                  && !CLASS_LOADED_P (field_decl_type)
                  && !TYPE_ARRAY_P (field_decl_type))
                resolve_and_layout (field_decl_type, NULL_TREE);
-             if (TYPE_ARRAY_P (field_decl_type))
-               CLASS_LOADED_P (field_decl_type) = 1;
              
              /* Check on accessibility here */
-             if (not_accessible_p (type, field_decl, from_super))
+             if (not_accessible_p (current_class, field_decl,
+                                   DECL_CONTEXT (field_decl), from_super))
                {
                  parse_error_context 
                    (qual_wfl,
@@ -9546,12 +9567,16 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
 }
 
 /* 6.6 Qualified name and access control. Returns 1 if MEMBER (a decl)
-   can't be accessed from REFERENCE (a record type). This should be
-   used when decl is a field or a method.*/
+   can't be accessed from REFERENCE (a record type). If MEMBER
+   features a protected access, we then use WHERE which, if non null,
+   holds the type of MEMBER's access that is checked against
+   6.6.2.1. This function should be used when decl is a field or a
+   method.  */
 
 static int
-not_accessible_p (reference, member, from_super)
+not_accessible_p (reference, member, where, from_super)
      tree reference, member;
+     tree where;
      int from_super;
 {
   int access_flag = get_access_flags_from_decl (member);
@@ -9577,6 +9602,12 @@ not_accessible_p (reference, member, from_super)
       if (from_super)
        return 0;
 
+      /* If where is active, access was made through a
+        qualifier. Access is granted if the type of the qualifier is
+        or is a sublass of the type the access made from (6.6.2.1.)  */
+      if (where && !inherits_from_p (reference, where))
+       return 1;
+
       /* Otherwise, access is granted if occuring from the class where
         member is declared or a subclass of it. Find the right
         context to perform the check */
@@ -9595,11 +9626,16 @@ not_accessible_p (reference, member, from_super)
     }
 
   /* Check access on private members. Access is granted only if it
-     occurs from within the class in which it is declared. Exceptions
-     are accesses from inner-classes. */
+     occurs from within the class in which it is declared -- that does
+     it for innerclasses too. */
   if (access_flag & ACC_PRIVATE)
-    return (current_class == DECL_CONTEXT (member) ? 0 : 
-           (INNER_CLASS_TYPE_P (current_class) ? 0 : 1));
+    {
+      if (reference == DECL_CONTEXT (member))
+       return 0;
+      if (enclosing_context_p (reference, DECL_CONTEXT (member)))
+       return 0;
+      return 1;
+    }
 
   /* Default access are permitted only when occuring within the
      package in which the type (REFERENCE) is declared. In other words,
@@ -9636,7 +9672,7 @@ check_deprecation (wfl, decl)
          strcpy (the, "class");
          break;
        default:
-         fatal ("unexpected DECL code - check_deprecation");
+         abort ();
        }
       parse_warning_context 
        (wfl, "The %s `%s' in class `%s' has been deprecated", 
@@ -9710,8 +9746,10 @@ maybe_access_field (decl, where, type)
    used. IS_STATIC is set to 1 if the invoked function is static. */
 
 static tree
-patch_method_invocation (patch, primary, where, is_static, ret_decl)
+patch_method_invocation (patch, primary, where, from_super,
+                        is_static, ret_decl)
      tree patch, primary, where;
+     int from_super;
      int *is_static;
      tree *ret_decl;
 {
@@ -9722,6 +9760,7 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
   int is_static_flag = 0;
   int is_super_init = 0;
   tree this_arg = NULL_TREE;
+  int is_array_clone_call = 0;
   
   /* Should be overriden if everything goes well. Otherwise, if
      something fails, it should keep this value. It stop the
@@ -9796,6 +9835,9 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
       else
        this_arg = primary = resolved;
       
+      if (TYPE_ARRAY_P (type) && identifier == get_identifier ("clone"))
+        is_array_clone_call = 1;
+      
       /* IDENTIFIER_WFL will be used to report any problem further */
       wfl = identifier_wfl;
     }
@@ -9863,7 +9905,29 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
          alternate class is specified. */
       else
        {
-         class_to_search = (where ? where : current_class);
+         if (where != NULL_TREE)
+           class_to_search = where;
+         else if (QUALIFIED_P (name))
+           class_to_search = current_class;
+         else
+           {
+             class_to_search = current_class;
+
+             for (;;)
+               {
+                 if (has_method (class_to_search, name))
+                   break;
+                 if (! INNER_CLASS_TYPE_P (class_to_search))
+                   {
+                     parse_error_context (wfl,
+                                          "No method named `%s' in scope",
+                                          IDENTIFIER_POINTER (name));
+                     PATCH_METHOD_RETURN_ERROR ();
+                   }
+                 class_to_search
+                   = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class_to_search)));
+               }
+           }
          lc = 0;
        }
 
@@ -9877,6 +9941,10 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
          can't be executed then. */
       if (!list)
        PATCH_METHOD_RETURN_ERROR ();
+      
+      if (TYPE_ARRAY_P (class_to_search)
+          && DECL_NAME (list) == get_identifier ("clone"))
+        is_array_clone_call = 1;
 
       /* Check for static reference if non static methods */
       if (check_for_static_method_reference (wfl, patch, list, 
@@ -9945,16 +10013,26 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
 
   /* Check accessibility, position the is_static flag, build and
      return the call */
-  if (not_accessible_p (DECL_CONTEXT (current_function_decl), list, 0))
-    {
-      char *fct_name = xstrdup (lang_printable_name (list, 0));
-      parse_error_context 
-       (wfl, "Can't access %s method `%s %s.%s' from `%s'",
-        java_accstring_lookup (get_access_flags_from_decl (list)),
-        lang_printable_name (TREE_TYPE (TREE_TYPE (list)), 0), 
-        IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list)))), 
-        fct_name, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
-      free (fct_name);
+  if (not_accessible_p (DECL_CONTEXT (current_function_decl), list,
+                       (primary ? TREE_TYPE (TREE_TYPE (primary)) : 
+                        NULL_TREE), 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 =
+       java_accstring_lookup (get_access_flags_from_decl (list));
+      const char *klass =
+       IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CONTEXT (list))));
+      const char *refklass =
+       IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
+      const char *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,
+                          "Can't access %s %s `%s.%s' from `%s'",
+                          access, what, klass, fct_name, refklass);
       PATCH_METHOD_RETURN_ERROR ();
     }
   check_deprecation (wfl, list);
@@ -9971,7 +10049,33 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
 
       /* Secretly pass the current_this/primary as a second argument */
       if (primary || current_this)
-       args = tree_cons (NULL_TREE, (primary ? primary : current_this), args);
+       {
+         tree extra_arg;
+         tree this_type = (current_this ?
+                           TREE_TYPE (TREE_TYPE (current_this)) : NULL_TREE);
+         /* Method's (list) enclosing context */
+         tree mec = DECL_CONTEXT (TYPE_NAME (DECL_CONTEXT (list)));
+         /* If we have a primary, use it. */
+         if (primary)
+           extra_arg = primary;
+         /* The current `this' is an inner class but isn't a direct
+            enclosing context for the inner class we're trying to
+            create. Build an access to the proper enclosing context
+            and use it. */
+         else if (current_this && PURE_INNER_CLASS_TYPE_P (this_type)
+                  && this_type != TREE_TYPE (mec))
+           {
+
+             extra_arg = build_access_to_thisn (current_class,
+                                                TREE_TYPE (mec), 0);
+             extra_arg = java_complete_tree (extra_arg);
+           }
+         /* Otherwise, just use the current `this' as an enclosing
+             context. */
+         else
+           extra_arg = current_this;
+         args = tree_cons (NULL_TREE, extra_arg, args);
+       }
       else
        args = tree_cons (NULL_TREE, integer_zero_node, args);
     }
@@ -10031,7 +10135,7 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
       /* Prepare to pass hidden parameters to finit$, if any. */
       finit_parms = build_alias_initializer_parameter_list 
        (AIPL_FUNCTION_FINIT_INVOCATION, current_class, NULL_TREE, NULL);
-
+      
       finit_call = 
        build_method_invocation (build_wfl_node (finit_identifier_node),
                                 finit_parms);
@@ -10147,7 +10251,7 @@ patch_invoke (patch, method, args)
 {
   tree dtable, func;
   tree original_call, t, ta;
-  tree cond = NULL_TREE;
+  tree check = NULL_TREE;
 
   /* Last step for args: convert build-in types. If we're dealing with
      a new TYPE() type call, the first argument to the constructor
@@ -10186,12 +10290,11 @@ patch_invoke (patch, method, args)
             optimization pass to eliminate redundant checks.  */
          if (TREE_VALUE (args) != current_this)
            {
-             /* We use a SAVE_EXPR here to make sure we only evaluate
+             /* We use a save_expr here to make sure we only evaluate
                 the new `self' expression once.  */
              tree save_arg = save_expr (TREE_VALUE (args));
              TREE_VALUE (args) = save_arg;
-             cond = build (EQ_EXPR, boolean_type_node, save_arg,
-                           null_pointer_node);
+             check = java_check_reference (save_arg, 1);
            }
          /* Fall through.  */
 
@@ -10208,7 +10311,7 @@ patch_invoke (patch, method, args)
          break;
 
        default:
-         fatal ("internal error - unknown invocation_mode result");
+         abort ();
        }
 
       /* Ensure self_type is initialized, (invokestatic). FIXME */
@@ -10251,22 +10354,11 @@ patch_invoke (patch, method, args)
       patch = build (COMPOUND_EXPR, TREE_TYPE (new), patch, saved_new);
     }
 
-  /* If COND is set, then we are building a check to see if the object
+  /* If CHECK is set, then we are building a check to see if the object
      is NULL.  */
-  if (cond != NULL_TREE)
-    {
-      /* We have to make the `then' branch a compound expression to
-        make the types turn out right.  This seems bizarre.  */
-      patch = build (COND_EXPR, TREE_TYPE (patch), cond,
-                    build (COMPOUND_EXPR, TREE_TYPE (patch),
-                           build (CALL_EXPR, void_type_node,
-                                  build_address_of (soft_nullpointer_node),
-                                  NULL_TREE, NULL_TREE),
-                           (FLOAT_TYPE_P (TREE_TYPE (patch))
-                            ? build_real (TREE_TYPE (patch), dconst0)
-                            : build1 (CONVERT_EXPR, TREE_TYPE (patch),
-                                      integer_zero_node))),
-                    patch);
+  if (check != NULL_TREE)
+    {
+      patch = build (COMPOUND_EXPR, TREE_TYPE (patch), check, patch);
       TREE_SIDE_EFFECTS (patch) = 1;
     }
 
@@ -10356,7 +10448,7 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
        {
          tree cm = TREE_VALUE (current);
          char string [4096];
-         if (!cm || not_accessible_p (class, cm, 0))
+         if (!cm || not_accessible_p (class, cm, NULL_TREE, 0))
            continue;
          sprintf 
            (string, "  `%s' in `%s'%s",
@@ -10441,15 +10533,23 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
   /* Search classes */
   else
     {
-      tree sc = class;
-      int seen_inner_class = 0;
       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
+        something at this point. */
+      if (ID_FINIT_P (name) || ID_CLASSDOLLAR_P (name))
+       {
+         lc = 1;
+         if (!list)
+           abort ();
+       }
+
       /* We must search all interfaces of this class */
       if (!lc)
       {
-       tree basetype_vec = TYPE_BINFO_BASETYPES (sc);
+       tree basetype_vec = TYPE_BINFO_BASETYPES (class);
        int n = TREE_VEC_LENGTH (basetype_vec), i;
        for (i = 1; i < n; i++)
          {
@@ -10464,24 +10564,6 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
          }
       }
 
-      /* Search enclosing context of inner classes before looking
-         ancestors up. */
-      while (!lc && INNER_CLASS_TYPE_P (class))
-       {
-         tree rlist;
-         seen_inner_class = 1;
-         class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
-         rlist = find_applicable_accessible_methods_list (lc, class, 
-                                                          name, arglist);
-         list = chainon (rlist, list);
-       }
-
-      if (!lc && seen_inner_class 
-         && TREE_TYPE (DECL_CONTEXT (TYPE_NAME (sc))) == CLASSTYPE_SUPER (sc))
-       class = CLASSTYPE_SUPER (sc);
-      else
-       class = sc;
-
       /* Search superclass */
       if (!lc && CLASSTYPE_SUPER (class) != NULL_TREE)
        {
@@ -10533,14 +10615,14 @@ search_applicable_methods_list (lc, method, name, arglist, list, all_list)
       if (lc && !DECL_CONSTRUCTOR_P (method))
        continue;
       else if (!lc && (DECL_CONSTRUCTOR_P (method) 
-                      || (GET_METHOD_NAME (method) != name)))
+                      || (DECL_NAME (method) != name)))
        continue;
-         
+
       if (argument_types_convertible (method, arglist))
        {
          /* Retain accessible methods only */
          if (!not_accessible_p (DECL_CONTEXT (current_function_decl), 
-                                method, 0))
+                                method, NULL_TREE, 0))
            *list = tree_cons (NULL_TREE, method, *list);
          else
            /* Also retain all selected method here */
@@ -10767,6 +10849,10 @@ 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 == 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));
@@ -10781,7 +10867,7 @@ qualify_ambiguous_name (id)
        qual_wfl = QUAL_WFL (qual);
        again = 1;
       }
-    else 
+    else
       {
        name = EXPR_WFL_NODE (qual_wfl);
        if (!name)
@@ -10809,8 +10895,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 */
@@ -10848,7 +10936,7 @@ qualify_ambiguous_name (id)
      expression name. If we saw a NEW_ARRAY_EXPR before and want to
      address length, it is OK. */
   else if ((decl = lookup_field_wrapper (ptr_type, name))
-          || (new_array_found && name == length_identifier_node))
+          || name == length_identifier_node)
     {
       RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
       QUAL_RESOLUTION (qual) = (new_array_found ? NULL_TREE : decl);
@@ -10873,7 +10961,8 @@ qualify_ambiguous_name (id)
   /* Method call, array references and cast are expression name */
   else if (TREE_CODE (QUAL_WFL (qual)) == CALL_EXPR
           || TREE_CODE (QUAL_WFL (qual)) == ARRAY_REF
-          || TREE_CODE (QUAL_WFL (qual)) == CONVERT_EXPR)
+          || TREE_CODE (QUAL_WFL (qual)) == CONVERT_EXPR
+          || TREE_CODE (QUAL_WFL (qual)) == MODIFY_EXPR)
     RESOLVE_EXPRESSION_NAME_P (qual_wfl) = 1;
 
   /* Check here that NAME isn't declared by more than one
@@ -10935,6 +11024,35 @@ breakdown_qualified (left, right, source)
   return 0;
 }
 
+/* Return TRUE if two classes are from the same package. */
+
+static int
+in_same_package (name1, name2)
+  tree name1, name2;
+{
+  tree tmp;
+  tree pkg1;
+  tree pkg2;
+  
+  if (TREE_CODE (name1) == TYPE_DECL)
+    name1 = DECL_NAME (name1);
+  if (TREE_CODE (name2) == TYPE_DECL)
+    name2 = DECL_NAME (name2);
+
+  if (QUALIFIED_P (name1) != QUALIFIED_P (name2))
+    /* One in empty package. */
+    return 0;
+
+  if (QUALIFIED_P (name1) == 0 && QUALIFIED_P (name2) == 0)
+    /* Both in empty package. */
+    return 1;
+
+  breakdown_qualified (&pkg1, &tmp, name1);
+  breakdown_qualified (&pkg2, &tmp, name2);
+  
+  return (pkg1 == pkg2);
+}
+
 /* Patch tree nodes in a function body. When a BLOCK is found, push
    local variable decls if present.
    Same as java_complete_lhs, but does resolve static finals to values. */
@@ -10944,7 +11062,7 @@ java_complete_tree (node)
      tree node;
 {
   node = java_complete_lhs (node);
-  if (JDECL_P (node) && FIELD_STATIC (node) && FIELD_FINAL (node) 
+  if (JDECL_P (node) && CLASS_FINAL_VARIABLE_P (node)
       && DECL_INITIAL (node) != NULL_TREE
       && !flag_emit_xref)
     {
@@ -10963,6 +11081,8 @@ java_complete_tree (node)
          else
            return value;
        }
+      else
+        DECL_FIELD_FINAL_IUD (node) = 0;
     }
   return node;
 }
@@ -11108,6 +11228,10 @@ java_complete_lhs (node)
     case TRY_FINALLY_EXPR:
       COMPLETE_CHECK_OP_0 (node);
       COMPLETE_CHECK_OP_1 (node);
+      if (TREE_OPERAND (node, 0) == empty_stmt_node)
+       return TREE_OPERAND (node, 1);
+      if (TREE_OPERAND (node, 1) == empty_stmt_node)
+       return TREE_OPERAND (node, 0);
       CAN_COMPLETE_NORMALLY (node)
        = (CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0))
           && CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)));
@@ -11341,9 +11465,9 @@ java_complete_lhs (node)
          EXPR_WFL_NODE (node) = body;
          TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body);
          CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body);
-         if (body == empty_stmt_node)
+         if (body == empty_stmt_node || TREE_CONSTANT (body))
            {
-             /* Optimization;  makes it easier to detect empty bodies. */
+             /* Makes it easier to constant fold, detect empty bodies. */
              return body;
            }
          if (body == error_mark_node)
@@ -11415,9 +11539,11 @@ java_complete_lhs (node)
        {
          tree decl, wfl = TREE_OPERAND (node, 0);
          int in_this = CALL_THIS_CONSTRUCTOR_P (node);
+         int from_super = (EXPR_WFL_NODE (TREE_OPERAND (node, 0)) ==
+                           super_identifier_node);
 
-         node = patch_method_invocation (node, NULL_TREE, 
-                                         NULL_TREE, 0, &decl);
+         node = patch_method_invocation (node, NULL_TREE, NULL_TREE,
+                                         from_super, 0, &decl);
          if (node == error_mark_node)
            return error_mark_node;
 
@@ -11453,6 +11579,8 @@ java_complete_lhs (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);
 
@@ -11466,7 +11594,7 @@ java_complete_lhs (node)
              class. TESTME, FIXME */
          tree lvalue = java_stabilize_reference (TREE_OPERAND (node, 0)); 
 
-         /* Hand stablize the lhs on both places */
+         /* Hand stabilize the lhs on both places */
          TREE_OPERAND (node, 0) = lvalue;
          TREE_OPERAND (TREE_OPERAND (node, 1), 0) = 
            (flag_emit_class_files ? lvalue : save_expr (lvalue));
@@ -11483,6 +11611,14 @@ java_complete_lhs (node)
          nn = java_complete_tree (build_cast (EXPR_WFL_LINECOL (wfl_op2), 
                                               TREE_TYPE (lvalue), nn));
 
+         /* If the assignment is compound and has reference type,
+            then ensure the LHS has type String and nothing else.  */
+         if (JREFERENCE_TYPE_P (TREE_TYPE (lvalue))
+             && ! JSTRING_TYPE_P (TREE_TYPE (lvalue)))
+           parse_error_context (wfl_op2,
+                                "Incompatible type for `+='. Can't convert `%s' to `java.lang.String'",
+                                lang_printable_name (TREE_TYPE (lvalue), 0));
+
          /* 15.25.2.b: Left hand is an array access. FIXME */
        }
 
@@ -11649,7 +11785,7 @@ java_complete_lhs (node)
          return field;
        }
       else
-       fatal ("unimplemented java_complete_tree for COMPONENT_REF");
+       abort ();
       break;
 
     case THIS_EXPR:
@@ -11696,8 +11832,7 @@ java_complete_lhs (node)
       if ((nn = patch_string (node)))
        node = nn;
       else
-       fatal ("No case for tree code `%s' - java_complete_tree\n",
-              tree_code_name [TREE_CODE (node)]);
+       internal_error ("No case for %s", tree_code_name [TREE_CODE (node)]);
     }
   return node;
 }
@@ -11774,18 +11909,13 @@ build_expr_block (body, decls)
 static tree
 enter_block ()
 {
-  return (enter_a_block (build_expr_block (NULL_TREE, NULL_TREE)));
-}
+  tree b = build_expr_block (NULL_TREE, NULL_TREE);
 
-/* Link block B supercontext to the previous block. The current
-   function DECL is used as supercontext when enter_a_block is called
-   for the first time for a given function. The current function body
-   (DECL_FUNCTION_BODY) is set to be block B.  */
+  /* Link block B supercontext to the previous block. The current
+     function DECL is used as supercontext when enter_a_block is called
+     for the first time for a given function. The current function body
+     (DECL_FUNCTION_BODY) is set to be block B.  */
 
-static tree
-enter_a_block (b)
-     tree b;
-{
   tree fndecl = current_function_decl; 
 
   if (!fndecl) {
@@ -11846,7 +11976,7 @@ lookup_name_in_blocks (name)
 
       /* Paranoid sanity check. To be removed */
       if (TREE_CODE (b) != BLOCK)
-       fatal ("non block expr function body - lookup_name_in_blocks");
+       abort ();
 
       for (current = BLOCK_EXPR_DECLS (b); current; 
           current = TREE_CHAIN (current))
@@ -11860,7 +11990,7 @@ lookup_name_in_blocks (name)
 static void
 maybe_absorb_scoping_blocks ()
 {
-  while (BLOCK_EXPR_ORIGIN (GET_CURRENT_BLOCK (current_function_decl)))
+  while (BLOCK_IS_IMPLICIT (GET_CURRENT_BLOCK (current_function_decl)))
     {
       tree b = exit_block ();
       java_method_add_stmt (current_function_decl, b);
@@ -11874,6 +12004,7 @@ maybe_absorb_scoping_blocks ()
    are completing them.  */
 
 /* Wrap a non WFL node around a WFL.  */
+
 static tree
 build_wfl_wrap (node, location)
     tree node;
@@ -11894,7 +12025,6 @@ build_wfl_wrap (node, location)
   return wfl;
 }
 
-
 /* Build a super() constructor invocation. Returns empty_stmt_node if
    we're currently dealing with the class java.lang.Object. */
 
@@ -12010,6 +12140,214 @@ print_int_node (node)
   return buffer;
 }
 
+\f
+
+/* This section of the code handle assignment check with FINAL
+   variables.  */
+
+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;
+}
+
+/* Figure whether all final static variable have been initialized.  */
+
+static void
+check_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_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)));
+}
+
+/* This function marks all final variable locally unassigned.  */
+
+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;
+}
+
+/* Figure whether all final variables have beem initialized in MDECL
+   and mark MDECL accordingly.  */
+
+static void
+check_final_variable_local_assignment_flag (class, mdecl)
+     tree class;
+     tree mdecl;
+{
+  tree field;
+  int initialized = 0;
+  int non_initialized = 0; 
+
+  if (DECL_FUNCTION_SYNTHETIC_CTOR (mdecl))
+    return;
+
+  /* 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++;
+      }
+
+  /* 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;
+}
+
+/* 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;
+{
+  int res;
+  switch (TREE_CODE (stmt))
+    {
+    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;
+    }
+  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)));
+      }
+
+}
+
 /* Return 1 if an assignment to a FINAL is attempted in a non suitable
    context.  */
 
@@ -12017,27 +12355,52 @@ static int
 check_final_assignment (lvalue, wfl)
      tree lvalue, wfl;
 {
-  if (TREE_CODE (lvalue) == COMPOUND_EXPR 
+  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);
 
-  /* When generating class files, references to the `length' field
-     look a bit different.  */
-  if ((flag_emit_class_files
-       && TREE_CODE (lvalue) == COMPONENT_REF
-       && TYPE_ARRAY_P (TREE_TYPE (TREE_OPERAND (lvalue, 0)))
-       && FIELD_FINAL (TREE_OPERAND (lvalue, 1)))
-      || (TREE_CODE (lvalue) == FIELD_DECL
-         && FIELD_FINAL (lvalue)
-         && !DECL_CLINIT_P (current_function_decl)
-         && !DECL_FINIT_P (current_function_decl)))
+  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))
     {
-      parse_error_context 
-        (wfl, "Can't assign a value to the final variable `%s'",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl)));
-      return 1;
+      DECL_FIELD_FINAL_IUD (lvalue) = 1;
+      return 0;
     }
-  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
@@ -12056,6 +12419,7 @@ maybe_build_primttype_type_ref (rhs, wfl)
       if (TREE_CODE (n) == VAR_DECL 
          && DECL_NAME (n) == TYPE_identifier_node
          && rhs_type == class_ptr_type
+         && TREE_CODE (wfl) == EXPR_WITH_FILE_LOCATION
          && TREE_CODE (EXPR_WFL_NODE (wfl)) == IDENTIFIER_NODE)
        {
          const char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl));
@@ -12196,15 +12560,23 @@ patch_assignment (node, wfl_op1, wfl_op2)
       tree check;
       tree base = lvalue;
 
-      /* We need to retrieve the right argument for _Jv_CheckArrayStore */
+      /* 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
        {
-         if (flag_bounds_check)
-           base = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (base, 0), 1), 0);
-         else
-           base = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
+          tree op = TREE_OPERAND (base, 0);
+         
+          /* We can have a SAVE_EXPR here when doing String +=.  */
+          if (TREE_CODE (op) == SAVE_EXPR)
+            op = TREE_OPERAND (op, 0);
+          if (flag_bounds_check)
+            base = TREE_OPERAND (TREE_OPERAND (op, 1), 0);
+          else
+            base = TREE_OPERAND (op, 0);
        }
 
       /* Build the invocation of _Jv_CheckArrayStore */
@@ -12230,22 +12602,37 @@ patch_assignment (node, wfl_op1, wfl_op2)
            TREE_OPERAND (lvalue, 1) = build (COMPOUND_EXPR, lhs_type,
                                              check, TREE_OPERAND (lvalue, 1));
        }
-      else 
+      else if (flag_bounds_check)
        {
+          tree hook = lvalue;
+          tree compound = TREE_OPERAND (lvalue, 0);
+          tree bound_check, new_compound;
+
+          if (TREE_CODE (compound) == SAVE_EXPR)
+            {
+              compound = TREE_OPERAND (compound, 0);
+              hook = TREE_OPERAND (hook, 0);
+            }
+
+          /* Find the array bound check, hook the original array access. */
+          bound_check = TREE_OPERAND (compound, 0);
+          TREE_OPERAND (hook, 0) = TREE_OPERAND (compound, 1);
+
          /* 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);
-       }
+          new_compound =
+            build (COMPOUND_EXPR, void_type_node, bound_check, check);
+
+          /* Re-assemble the augmented array access. */
+          lvalue = build (COMPOUND_EXPR, lhs_type, new_compound, lvalue);
+        }
+      else
+        lvalue = build (COMPOUND_EXPR, lhs_type, check, lvalue);
     }
 
   /* Final locals can be used as case values in switch
      statement. Prepare them for this eventuality. */
   if (TREE_CODE (lvalue) == VAR_DECL 
-      && LOCAL_FINAL (lvalue)
+      && LOCAL_FINAL_P (lvalue)
       && TREE_CONSTANT (new_rhs)
       && IDENTIFIER_LOCAL_VALUE (DECL_NAME (lvalue))
       && JINTEGRAL_TYPE_P (TREE_TYPE (lvalue))
@@ -12282,7 +12669,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 (rhs == soft_exceptioninfo_call_node)
+      else if (TREE_CODE (rhs) == JAVA_EXC_OBJ_EXPR)
        new_rhs = rhs;
     }
   return new_rhs;
@@ -12408,6 +12795,20 @@ valid_ref_assignconv_cast_p (source, dest, cast)
     source = TREE_TYPE (source);
   if (TREE_CODE (dest) == POINTER_TYPE)
     dest = TREE_TYPE (dest);
+
+  /* If source and dest are being compiled from bytecode, they may need to
+     be loaded. */
+  if (CLASS_P (source) && !CLASS_LOADED_P (source))
+    {
+      load_class (source, 1);
+      safe_layout_class (source);
+    }
+  if (CLASS_P (dest) && !CLASS_LOADED_P (dest))
+    {
+      load_class (dest, 1);
+      safe_layout_class (dest);
+    }
+
   /* Case where SOURCE is a class type */
   if (TYPE_CLASS_P (source))
     {
@@ -12619,8 +13020,8 @@ operator_string (node)
     case PREDECREMENT_EXPR:    /* Fall through */
     case POSTDECREMENT_EXPR: BUILD_OPERATOR_STRING ("--");
     default:
-      fatal ("unregistered operator %s - operator_string",
-            tree_code_name [TREE_CODE (node)]);
+      internal_error ("unregistered operator %s",
+                     tree_code_name [TREE_CODE (node)]);
     }
   return NULL;
 #undef BUILD_OPERATOR_STRING
@@ -12726,6 +13127,26 @@ patch_binop (node, wfl_op1, wfl_op2)
 
   EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
 
+  /* If either op<n>_type are NULL, this might be early signs of an
+     error situation, unless it's too early to tell (in case we're
+     handling a `+', `==', `!=' or `instanceof'.) We want to set op<n>_type
+     correctly so the error can be later on reported accurately. */
+  if (! (code == PLUS_EXPR || code == NE_EXPR 
+        || code == EQ_EXPR || code == INSTANCEOF_EXPR))
+    {
+      tree n;
+      if (! op1_type)
+       {
+         n = java_complete_tree (op1);
+         op1_type = TREE_TYPE (n);
+       }
+      if (! op2_type)
+       {
+         n = java_complete_tree (op2);
+         op2_type = TREE_TYPE (n);
+       }
+    }
+
   switch (code)
     {
     /* 15.16 Multiplicative operators */
@@ -13299,8 +13720,7 @@ build_unaryop (op_token, op_location, op1)
     case MINUS_TK: op = NEGATE_EXPR; break;
     case NEG_TK: op = TRUTH_NOT_EXPR; break;
     case NOT_TK: op = BIT_NOT_EXPR; break;
-    default: fatal ("Unknown token `%d' for unary operator - build_unaryop",
-                   op_token);
+    default: abort ();
     }
 
   unaryop = build1 (op, NULL_TREE, op1);
@@ -13374,8 +13794,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
@@ -13598,7 +14021,7 @@ resolve_type_during_patch (type)
 {
   if (unresolved_type_p (type, NULL))
     {
-      tree type_decl = resolve_no_layout (EXPR_WFL_NODE (type), type);
+      tree type_decl = resolve_and_layout (EXPR_WFL_NODE (type), type);
       if (!type_decl)
        {
          parse_error_context (type, 
@@ -13606,11 +14029,7 @@ resolve_type_during_patch (type)
                               IDENTIFIER_POINTER (EXPR_WFL_NODE (type)));
          return NULL_TREE;
        }
-      else
-       {
-         CLASS_LOADED_P (TREE_TYPE (type_decl)) = 1;
-         return TREE_TYPE (type_decl);
-       }
+      return TREE_TYPE (type_decl);
     }
   return type;
 }
@@ -14768,7 +15187,7 @@ patch_synchronized_statement (node, wfl_op1)
   tree expr = java_complete_tree (TREE_OPERAND (node, 0));
   tree block = TREE_OPERAND (node, 1);
 
-  tree enter, exit, expr_decl, assignment;
+  tree tmp, enter, exit, expr_decl, assignment;
 
   if (expr == error_mark_node)
     {
@@ -14776,6 +15195,10 @@ patch_synchronized_statement (node, wfl_op1)
       return expr;
     }
 
+  /* We might be trying to synchronize on a STRING_CST */
+  if ((tmp = patch_string (expr)))
+    expr = tmp;
+
   /* The TYPE of expr must be a reference type */
   if (!JREFERENCE_TYPE_P (TREE_TYPE (expr)))
     {
@@ -15126,6 +15549,29 @@ patch_conditional_expr (node, wfl_cond, wfl_op1)
   return node;
 }
 
+/* Wrap EXPR with code to initialize DECL's class, if appropriate. */
+
+static tree
+maybe_build_class_init_for_field (decl, expr)
+    tree decl, expr;
+{
+  tree clas = DECL_CONTEXT (decl);
+  if (flag_emit_class_files || flag_emit_xref)
+    return expr;
+
+  if (TREE_CODE (decl) == VAR_DECL && FIELD_STATIC (decl)
+      && FIELD_FINAL (decl))
+    {
+      tree init = DECL_INITIAL (decl);
+      if (init != NULL_TREE)
+       init = fold_constant_for_init (init, decl);
+      if (init != NULL_TREE && CONSTANT_VALUE_P (init))
+       return expr;
+    }
+
+  return build_class_init (clas, expr);
+}
+
 /* Try to constant fold NODE.
    If NODE is not a constant expression, return NULL_EXPR.
    CONTEXT is a static final VAR_DECL whose initializer we are folding. */
@@ -15138,11 +15584,13 @@ fold_constant_for_init (node, context)
   tree op0, op1, val;
   enum tree_code code = TREE_CODE (node);
 
-  if (code == STRING_CST || code == INTEGER_CST || code == REAL_CST)
-    return node;
-
   switch (code)
     {
+    case STRING_CST:
+    case INTEGER_CST:
+    case REAL_CST:
+      return node;
+
     case PLUS_EXPR:
     case MINUS_EXPR:
     case MULT_EXPR:
@@ -15213,6 +15661,8 @@ 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:
@@ -15300,8 +15750,6 @@ mark_parser_ctxt (p)
   ggc_mark_tree (pc->class_type);
   ggc_mark_tree (pc->function_decl);
   ggc_mark_tree (pc->package);
-  ggc_mark_tree (pc->incomplete_class);
-  ggc_mark_tree (pc->gclass_list);
   ggc_mark_tree (pc->class_list);
   ggc_mark_tree (pc->current_parsed_class);
   ggc_mark_tree (pc->current_parsed_class_un);
@@ -15317,3 +15765,10 @@ mark_parser_ctxt (p)
   if (pc->next)
     mark_parser_ctxt (&pc->next);
 }
+
+void
+init_src_parse ()
+{
+  /* Register roots with the garbage collector.  */
+  ggc_add_tree_root (src_parse_roots, sizeof (src_parse_roots) / sizeof(tree));
+}