OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / java / parse.y
index 2ac6409..0aded25 100644 (file)
@@ -81,7 +81,7 @@ static tree  find_field PARAMS ((tree, tree));
 static tree lookup_field_wrapper PARAMS ((tree, tree));
 static int   duplicate_declaration_error_p PARAMS ((tree, tree, tree));
 static void  register_fields PARAMS ((int, tree, tree));
-static tree parser_qualified_classname PARAMS ((int, tree));
+static tree parser_qualified_classname PARAMS ((tree));
 static int  parser_check_super PARAMS ((tree, tree, tree));
 static int  parser_check_super_interface PARAMS ((tree, tree, tree));
 static void check_modifiers_consistency PARAMS ((int));
@@ -99,8 +99,10 @@ static void complete_class_report_errors PARAMS ((jdep *));
 static int process_imports PARAMS ((void));
 static void read_import_dir PARAMS ((tree));
 static int find_in_imports_on_demand PARAMS ((tree));
-static int find_in_imports PARAMS ((tree));
+static void find_in_imports 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 *));
@@ -120,6 +122,7 @@ static tree patch_method_invocation PARAMS ((tree, tree, tree,
                                            int *, tree *));
 static int breakdown_qualified PARAMS ((tree *, 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));
 static int invocation_mode PARAMS ((tree, int));
 static tree find_applicable_accessible_methods_list PARAMS ((int, tree, 
@@ -136,6 +139,7 @@ static tree obtain_incomplete_type PARAMS ((tree));
 static tree java_complete_lhs PARAMS ((tree));
 static tree java_complete_tree PARAMS ((tree));
 static tree maybe_generate_pre_expand_clinit PARAMS ((tree));
+static int maybe_yank_clinit PARAMS ((tree));
 static void java_complete_expand_method PARAMS ((tree));
 static int  unresolved_type_p PARAMS ((tree, tree *));
 static void create_jdep_list PARAMS ((struct parser_ctxt *));
@@ -179,7 +183,7 @@ static tree build_newarray_node PARAMS ((tree, tree, int));
 static tree patch_newarray PARAMS ((tree));
 static tree resolve_type_during_patch PARAMS ((tree));
 static tree build_this PARAMS ((int));
-static tree build_wfl_wrap PARAMS ((tree));
+static tree build_wfl_wrap PARAMS ((tree, int));
 static tree build_return PARAMS ((int, tree));
 static tree patch_return PARAMS ((tree));
 static tree maybe_access_field PARAMS ((tree, tree, tree));
@@ -638,6 +642,11 @@ name:
 
 simple_name:
        identifier              /* Default rule */
+       {
+         if (strchr (IDENTIFIER_POINTER (EXPR_WFL_NODE ($$)), '$'))
+           parse_error_context ($$, "Invalid type name `%s'",
+                                IDENTIFIER_POINTER (EXPR_WFL_NODE ($$)));
+       }
 ;
 
 qualified_name:
@@ -681,7 +690,7 @@ package_declaration:
        PACKAGE_TK name SC_TK
                { 
                  ctxp->package = EXPR_WFL_NODE ($2);
-                 package_list = tree_cons (ctxp->package, NULL, package_list);
+                 register_package (ctxp->package);
                }
 |      PACKAGE_TK error
                {yyerror ("Missing name"); RECOVER;}
@@ -697,7 +706,7 @@ import_declaration:
 single_type_import_declaration:
        IMPORT_TK name SC_TK
                {
-                 tree name = EXPR_WFL_NODE ($2), node, last_name;
+                 tree name = EXPR_WFL_NODE ($2), last_name;
                  int   i = IDENTIFIER_LENGTH (name)-1;
                  const char *last = &IDENTIFIER_POINTER (name)[i];
                  while (last != IDENTIFIER_POINTER (name))
@@ -716,7 +725,7 @@ single_type_import_declaration:
                           IDENTIFIER_POINTER (name), 
                           IDENTIFIER_POINTER (err));
                      else
-                       REGISTER_IMPORT ($2, last_name)
+                       REGISTER_IMPORT ($2, last_name);
                    }
                  else
                    REGISTER_IMPORT ($2, last_name);
@@ -734,10 +743,10 @@ type_import_on_demand_declaration:
                  /* Don't import java.lang.* twice. */
                  if (name != java_lang_id)
                    {
-                     tree node = build_tree_list ($2, NULL_TREE);
                      read_import_dir ($2);
-                     TREE_CHAIN (node) = ctxp->import_demand_list;
-                     ctxp->import_demand_list = node;
+                     ctxp->import_demand_list = 
+                       chainon (ctxp->import_demand_list,
+                                build_tree_list ($2, NULL_TREE));
                    }
                }
 |      IMPORT_TK name DOT_TK error
@@ -1326,6 +1335,8 @@ block_end:
                    DECL_END_SOURCE_LINE (current_function_decl) = 
                      EXPR_WFL_ADD_COL ($1.location, 1);                  
                  $$ = exit_block ();
+                 if (!BLOCK_SUBBLOCKS ($$))
+                   BLOCK_SUBBLOCKS ($$) = empty_stmt_node;
                }
 ;
 
@@ -1626,7 +1637,11 @@ do_statement:
 
 for_statement:
        for_begin SC_TK expression SC_TK for_update CP_TK statement
-               { $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7); }
+               {
+                 if (TREE_CODE_CLASS (TREE_CODE ($3)) == 'c')
+                   $3 = build_wfl_node ($3);
+                 $$ = finish_for_loop (EXPR_WFL_LINECOL ($3), $3, $5, $7);
+               }
 |      for_begin SC_TK SC_TK for_update CP_TK statement
                { 
                  $$ = finish_for_loop (0, NULL_TREE, $4, $6);
@@ -2076,6 +2091,11 @@ dim_exprs:
 dim_expr:
        OSB_TK expression CSB_TK
                { 
+                 if (JNUMERIC_TYPE_P (TREE_TYPE ($2)))
+                   {
+                     $2 = build_wfl_node ($2);
+                     TREE_TYPE ($2) = NULL_TREE;
+                   }
                  EXPR_WFL_LINECOL ($2) = $1.location;
                  $$ = $2;
                }
@@ -3456,8 +3476,8 @@ find_as_inner_class (enclosing, name, cl)
     {
       tree acc = NULL_TREE, decl = NULL_TREE, ptr;
 
-      for(qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl; 
-         qual = TREE_CHAIN (qual))
+      for (qual = EXPR_WFL_QUALIFICATION (cl); qual && !decl; 
+          qual = TREE_CHAIN (qual))
        {
          acc = merge_qualified_name (acc, 
                                      EXPR_WFL_NODE (TREE_PURPOSE (qual)));
@@ -3477,7 +3497,18 @@ find_as_inner_class (enclosing, name, cl)
   else
     qual = build_tree_list (build_expr_wfl (name, NULL, 0, 0), NULL_TREE);
 
-  return find_as_inner_class_do (qual, enclosing);
+  if (!(to_return = find_as_inner_class_do (qual, enclosing)))
+    {
+      /* It might be the case that the enclosing class was loaded as
+        bytecode, in which case it will be missing the
+        DECL_INNER_CLASS_LIST. We build a fully qualified internal
+        innerclass name and we try to load it. */
+      tree fqin = identifier_subst (name, "", '.', '$', "");
+      tree ptr;
+      BUILD_PTR_FROM_NAME (ptr, fqin);
+      to_return = resolve_class (NULL_TREE, ptr, NULL_TREE, cl);
+    }
+  return to_return;
 }
 
 /* We go inside the list of sub classes and try to find a way
@@ -3634,7 +3665,7 @@ create_interface (flags, id, super)
      tree id, super;
 {
   tree raw_name = EXPR_WFL_NODE (id);
-  tree q_name = parser_qualified_classname (flags & ACC_STATIC, raw_name);
+  tree q_name = parser_qualified_classname (raw_name);
   tree decl = IDENTIFIER_CLASS_VALUE (q_name);
 
   EXPR_WFL_NODE (id) = q_name; /* Keep source location, even if refined. */
@@ -3769,7 +3800,7 @@ create_class (flags, id, super, interfaces)
   tree class_id, decl;
   tree super_decl_type;
 
-  class_id = parser_qualified_classname (0, raw_name);
+  class_id = parser_qualified_classname (raw_name);
   decl = IDENTIFIER_CLASS_VALUE (class_id);
   EXPR_WFL_NODE (id) = class_id;
 
@@ -3825,13 +3856,6 @@ create_class (flags, id, super, interfaces)
   CLASS_COMPLETE_P (decl) = 1;
   add_superinterfaces (decl, interfaces);
 
-  /* If the class is a top level inner class, install an alias. */
-  if (INNER_CLASS_DECL_P (decl) && CLASS_STATIC (decl))
-    {
-      tree alias = parser_qualified_classname (1, raw_name);
-      IDENTIFIER_GLOBAL_VALUE (alias) = decl;
-    }
-
   /* Add the private this$<n> field, Replicate final locals still in
      scope as private final fields mangled like val$<local_name>.
      This doesn't not occur for top level (static) inner classes. */
@@ -3990,23 +4014,27 @@ lookup_field_wrapper (class, name)
      tree class, name;
 {
   tree type = class;
-  tree decl;
+  tree decl = NULL_TREE;
   java_parser_context_save_global ();
-  decl = lookup_field (&type, 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) && (!decl || decl == error_mark_node))
+  if (INNER_CLASS_TYPE_P (class))
     {
       char *alias_buffer;
+      tree new_name;
       MANGLE_OUTER_LOCAL_VARIABLE_NAME (alias_buffer, name);
-      name = get_identifier (alias_buffer);
-      type = class;
-      decl = lookup_field (&type, name);
+      new_name = get_identifier (alias_buffer);
+      decl = lookup_field (&type, new_name);
       if (decl && decl != error_mark_node)
        FIELD_LOCAL_ALIAS_USED (decl) = 1;
     }
+  if (!decl || decl == error_mark_node)
+    {
+      type = class;
+      decl = lookup_field (&type, name);
+    }
 
   java_parser_context_restore_global ();
   return decl == error_mark_node ? NULL : decl;
@@ -4099,11 +4127,11 @@ register_fields (flags, type, variable_list)
       tree init = TREE_VALUE (current);
       tree current_name = EXPR_WFL_NODE (cl);
 
-      /* Can't declare static fields in inner classes */
+      /* Can't declare non-final static fields in inner classes */
       if ((flags & ACC_STATIC) && !TOPLEVEL_CLASS_TYPE_P (class_type)
-         && !CLASS_INTERFACE (TYPE_NAME (class_type)))
+          && !(flags & ACC_FINAL))
        parse_error_context 
-         (cl, "Field `%s' can't be static in innerclass `%s'. Only members of interfaces and top-level classes can be static",
+          (cl, "Field `%s' can't be static in inner class `%s' unless it is final",
           IDENTIFIER_POINTER (EXPR_WFL_NODE (cl)),
           lang_printable_name (class_type, 0));
 
@@ -4278,7 +4306,7 @@ method_header (flags, type, mdecl, throws)
          && !CLASS_INTERFACE (TYPE_NAME (this_class)))
        parse_error_context 
          (id, "Class `%s' must be declared abstract to define abstract method `%s'", 
-          IDENTIFIER_POINTER (DECL_NAME (ctxp->current_parsed_class)),
+          IDENTIFIER_POINTER (DECL_NAME (GET_CPC ())),
           IDENTIFIER_POINTER (EXPR_WFL_NODE (id)));
     }
 
@@ -4610,10 +4638,8 @@ check_modifiers_consistency (flags)
 
   acc_count = 0;
   cl = NULL_TREE;
-  THIS_MODIFIER_ONLY (flags, ACC_FINAL, FINAL_TK - PUBLIC_TK,
-                     acc_count, cl);
-  THIS_MODIFIER_ONLY (flags, ACC_VOLATILE, VOLATILE_TK - PUBLIC_TK,
-                     acc_count, cl);
+  THIS_MODIFIER_ONLY (flags, ACC_FINAL, FINAL_TK, acc_count, cl);
+  THIS_MODIFIER_ONLY (flags, ACC_VOLATILE, VOLATILE_TK, acc_count, cl);
   if (acc_count > 1)
     parse_error_context (cl,
                         "Inconsistent member declaration.  At most one of `final' or `volatile' may be specified");
@@ -4672,7 +4698,7 @@ method_declarator (id, list)
 
       /* Then this$<n> */
       type = TREE_TYPE (DECL_CONTEXT (GET_CPC ()));
-      thisn = build_current_thisn (TYPE_NAME (GET_CPC ()));
+      thisn = build_current_thisn (TREE_TYPE (GET_CPC ()));
       list = tree_cons (build_wfl_node (thisn), build_pointer_type (type),
                        list);
     }
@@ -4769,14 +4795,12 @@ unresolved_type_p (wfl, returned)
    qualification from the current package definition. */
 
 static tree
-parser_qualified_classname (is_static, name)
-     int is_static;
+parser_qualified_classname (name)
      tree name;
 {
   tree nested_class_name;
 
-  if (!is_static 
-      && (nested_class_name = maybe_make_nested_class_name (name)))
+  if ((nested_class_name = maybe_make_nested_class_name (name)))
     return nested_class_name;
 
   if (ctxp->package)
@@ -5191,6 +5215,8 @@ jdep_resolve_class (dep)
   if (!decl)
     complete_class_report_errors (dep);
 
+  if (PURE_INNER_CLASS_DECL_P (decl))
+    check_inner_class_access (decl, JDEP_ENCLOSING (dep), JDEP_WFL (dep));
   return decl;
 }
 
@@ -5206,10 +5232,8 @@ java_complete_class ()
 
   push_obstacks (&permanent_obstack, &permanent_obstack);
 
-  /* Process imports and reverse the import on demand list */
+  /* Process imports */
   process_imports ();
-  if (ctxp->import_demand_list)
-    ctxp->import_demand_list = nreverse (ctxp->import_demand_list);
 
   /* Rever things so we have the right order */
   ctxp->class_list = nreverse (ctxp->class_list);
@@ -5248,6 +5272,7 @@ java_complete_class ()
                pop_obstacks ();
                TREE_TYPE (field_decl) = field_type;
                DECL_ALIGN (field_decl) = 0;
+               DECL_USER_ALIGN (field_decl) = 0;
                layout_decl (field_decl, 0);
                SOURCE_FRONTEND_DEBUG 
                  (("Completed field/var decl `%s' with `%s'",
@@ -5413,10 +5438,10 @@ do_resolve_class (enclosing, class_type, decl, cl)
      tree enclosing, class_type, decl, cl;
 {
   tree new_class_decl;
-  tree original_name = NULL_TREE;
 
   /* Do not try to replace TYPE_NAME (class_type) by a variable, since
-     its is changed by find_in_imports{_on_demand} */
+     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 */
 
@@ -5430,6 +5455,15 @@ do_resolve_class (enclosing, class_type, decl, cl)
       if ((new_class_decl = find_as_inner_class (enclosing, class_type, cl)))
         return new_class_decl;
 
+      /* Explore enclosing contexts. */
+      while (INNER_CLASS_DECL_P (enclosing))
+       {
+         enclosing = DECL_CONTEXT (enclosing);
+         if ((new_class_decl = find_as_inner_class (enclosing, 
+                                                    class_type, cl)))
+           return new_class_decl;
+       }
+
       /* Now go to the upper classes, bail out if necessary. */
       enclosing = CLASSTYPE_SUPER (TREE_TYPE (enclosing));
       if (!enclosing || enclosing == object_type_node)
@@ -5442,20 +5476,17 @@ do_resolve_class (enclosing, class_type, decl, cl)
        }
 
       if (TREE_CODE (enclosing) == IDENTIFIER_NODE)
-       {
-         BUILD_PTR_FROM_NAME (name, enclosing);
-       }
+       BUILD_PTR_FROM_NAME (name, enclosing);
       else
        name = enclosing;
       enclosing = do_resolve_class (NULL, name, NULL, NULL);
     }
 
-  /* 1- Check for the type in single imports */
-  if (find_in_imports (class_type))
-    return NULL_TREE;
+  /* 1- Check for the type in single imports. This will change
+     TYPE_NAME() if something relevant is found */
+  find_in_imports (class_type);
 
-  /* 2- And check for the type in the current compilation unit. If it fails,
-     try with a name qualified with the package name we've seen so far */
+  /* 2- And check for the type in the current compilation unit */
   if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
     {
       if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
@@ -5464,41 +5495,13 @@ do_resolve_class (enclosing, class_type, decl, cl)
       return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
     }
 
-  original_name = TYPE_NAME (class_type);
+  /* 3- Search according to the current package definition */
   if (!QUALIFIED_P (TYPE_NAME (class_type)))
     {
-      tree package;
-      for (package = package_list; package; package = TREE_CHAIN (package))
-       {
-         tree new_qualified;
-         
-         new_qualified = merge_qualified_name (TREE_PURPOSE (package),
-                                               original_name);
-         TYPE_NAME (class_type) = new_qualified;
-         new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
-         if (!new_class_decl)
-           load_class (TYPE_NAME (class_type), 0);
-         new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
-         if (new_class_decl)
-           {
-             if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
-                 !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
-               load_class (TYPE_NAME (class_type), 0);
-             return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
-           }
-       }
-    }
-
-  TYPE_NAME (class_type) = original_name;
-
-  /* 3- 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 ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
-    return new_class_decl;
+      if ((new_class_decl = qualify_and_find (class_type, ctxp->package,
+                                            TYPE_NAME (class_type))))
+       return new_class_decl;
+    }
 
   /* 4- Check the import on demands. Don't allow bar.baz to be
      imported from foo.* */
@@ -5506,10 +5509,57 @@ do_resolve_class (enclosing, class_type, decl, cl)
     if (find_in_imports_on_demand (class_type))
       return NULL_TREE;
 
-  /* 5- Last call for a resolution */
+  /* If found in find_in_imports_on_demant, the type has already been
+     loaded. */
+  if ((new_class_decl = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type))))
+    return new_class_decl;
+
+  /* 5- Try with a name qualified with the package name we've seen so far */
+  if (!QUALIFIED_P (TYPE_NAME (class_type)))
+    {
+      tree package;
+
+      /* If there is a current package (ctxp->package), it's the first
+        element of package_list and we can skip it. */
+      for (package = (ctxp->package ? 
+                     TREE_CHAIN (package_list) : package_list);
+          package; package = TREE_CHAIN (package))
+       if ((new_class_decl = qualify_and_find (class_type,
+                                              TREE_PURPOSE (package), 
+                                              TYPE_NAME (class_type))))
+         return new_class_decl;
+    }
+
+  /* 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;
+
+  /* 6- Last call for a resolution */
   return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
 }
 
+static tree
+qualify_and_find (class_type, package, name)
+     tree class_type, package, name;
+{
+  tree new_qualified = merge_qualified_name (package, name);
+  tree new_class_decl;
+
+  if (!IDENTIFIER_CLASS_VALUE (new_qualified))
+    load_class (new_qualified, 0);
+  if ((new_class_decl = IDENTIFIER_CLASS_VALUE (new_qualified)))
+    {
+      if (!CLASS_LOADED_P (TREE_TYPE (new_class_decl)) &&
+         !CLASS_FROM_SOURCE_P (TREE_TYPE (new_class_decl)))
+       load_class (new_qualified, 0);
+      TYPE_NAME (class_type) = new_qualified;
+      return IDENTIFIER_CLASS_VALUE (new_qualified);
+    }
+  return NULL_TREE;
+}
+
 /* Resolve NAME and lay it out (if not done and if not the current
    parsed class). Return a decl node. This function is meant to be
    called when type resolution is necessary during the walk pass.  */
@@ -5815,7 +5865,9 @@ check_abstract_method_definitions (do_interface, class_decl, type)
              other_name = EXPR_WFL_NODE (other_name);
            if (!DECL_CLINIT_P (other_method)
                && !DECL_CONSTRUCTOR_P (other_method)
-               && method_name == other_name && method_sig == s)
+               && method_name == other_name
+               && method_sig == s
+               && !METHOD_ABSTRACT (other_method))
              {
                found = 1;
                break;
@@ -6383,10 +6435,10 @@ process_imports ()
   return 0;
 }
 
-/* Possibly find a class imported by a single-type import statement. Return
-   1 if an error occured, 0 otherwise. */
+/* Possibly find and mark a class imported by a single-type import
+   statement.  */
 
-static int
+static void
 find_in_imports (class_type)
      tree class_type;
 {
@@ -6398,7 +6450,6 @@ find_in_imports (class_type)
        TYPE_NAME (class_type) = EXPR_WFL_NODE (TREE_PURPOSE (import));
        QUALIFIED_P (TYPE_NAME (class_type)) = 1;
       }
-  return 0;
 }
 
 static int
@@ -6608,6 +6659,30 @@ find_in_imports_on_demand (class_type)
     return (seen_once < 0 ? 0 : seen_once); /* It's ok not to have found */
 }
 
+/* Add package NAME to the list of package encountered so far. To
+   speed up class lookup in do_resolve_class, we make sure a
+   particular package is added only once.  */
+
+static void
+register_package (name)
+     tree name;
+{
+  static struct hash_table _pht, *pht = NULL;
+
+  if (!pht)
+    {
+      hash_table_init (&_pht, hash_newfunc, 
+                      java_hash_hash_tree_node, java_hash_compare_tree_node);
+      pht = &_pht;
+    }
+  
+  if (!hash_lookup (pht, (const hash_table_key) name, FALSE, NULL))
+    {
+      package_list = chainon (package_list, build_tree_list (name, NULL));
+      hash_lookup (pht, (const hash_table_key) name, TRUE, NULL);
+    }
+}
+
 static tree
 resolve_package (pkg, next)
      tree pkg, *next;
@@ -6677,7 +6752,10 @@ resolve_package (pkg, next)
        if ((type_name = resolve_no_layout (acc, NULL_TREE)))
          {
            type_name = acc;
-           *next = TREE_CHAIN (current);
+           /* resolve_package should be used in a loop, hence we
+              point at this one to naturally process the next one at
+              the next iteration. */
+           *next = current;
            break;
          }
       }
@@ -6719,6 +6797,42 @@ lookup_package_type (name, from)
   return get_identifier (subname);
 }
 
+static void
+check_inner_class_access (decl, enclosing_decl, cl)
+     tree decl, enclosing_decl, cl;
+{
+  int access = 0;
+
+  /* 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
+     for the purpose of patching its parm decl. But the error would
+     have been already trapped when fixing the method's signature.
+     DECL can also be NULL in case of earlier errors. */
+  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. */
+  if (CLASS_PRIVATE (decl))
+    access = 1;
+  if (CLASS_PROTECTED (decl))
+    access = 2;
+  if (!access)
+    return;
+      
+  if (common_enclosing_context_p (TREE_TYPE (enclosing_decl),
+                                 TREE_TYPE (decl))
+      || enclosing_context_p (TREE_TYPE (enclosing_decl),
+                             TREE_TYPE (decl)))
+    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"),
+                      (CLASS_INTERFACE (decl) ? "interface" : "class"),
+                      lang_printable_name (decl, 0));
+}
+
 /* Check that CLASS_NAME refers to a PUBLIC class. Return 0 if no
    access violations were found, 1 otherwise.  */
 
@@ -7373,26 +7487,28 @@ maybe_generate_pre_expand_clinit (class_type)
   for (current = TYPE_CLINIT_STMT_LIST (class_type); current;
        current = TREE_CHAIN (current))
     {
+      tree stmt = current;
       /* We build the assignment expression that will initialize the
         field to its value. There are strict rules on static
         initializers (8.5). FIXME */
-      tree stmt = build_debugable_stmt (EXPR_WFL_LINECOL (current), current);
+      if (TREE_CODE (stmt) != BLOCK && stmt != empty_stmt_node)
+       stmt = build_debugable_stmt (EXPR_WFL_LINECOL (stmt), stmt);
       java_method_add_stmt (mdecl, stmt);
     }
 
   end_artificial_method_body (mdecl);
 
-  /* Now we want to place <clinit> as the last method for interface so
-     that it doesn't interfere with the dispatch table based
-     lookup. */
-  if (CLASS_INTERFACE (TYPE_NAME (class_type))
-      && TREE_CHAIN (TYPE_METHODS (class_type)))
+  /* Now we want to place <clinit> as the last method (because we need
+     it at least for interface so that it doesn't interfere with the
+     dispatch table based lookup. */
+  if (TREE_CHAIN (TYPE_METHODS (class_type)))
     {
-      tree current = 
-       TYPE_METHODS (class_type) = TREE_CHAIN (TYPE_METHODS (class_type));
+      current = TREE_CHAIN (TYPE_METHODS (class_type));
+      TYPE_METHODS (class_type) = current;
 
       while (TREE_CHAIN (current))
        current = TREE_CHAIN (current);
+
       TREE_CHAIN (current) = mdecl;
       TREE_CHAIN (mdecl) = NULL_TREE;
     }
@@ -7400,12 +7516,63 @@ maybe_generate_pre_expand_clinit (class_type)
   return mdecl;
 }
 
+/* See whether we could get rid of <clinit>. Criteria are: all static
+   final fields have constant initial values and the body of <clinit>
+   is empty. Return 1 if <clinit> was discarded, 0 otherwise. */
+
+static int
+maybe_yank_clinit (mdecl)
+     tree mdecl;
+{
+  tree type, current;
+  tree fbody, bbody;
+  
+  if (!DECL_CLINIT_P (mdecl))
+    return 0;
+  
+  /* If the body isn't empty, then we keep <clinit> */
+  fbody = DECL_FUNCTION_BODY (mdecl);
+  if ((bbody = BLOCK_EXPR_BODY (fbody)))
+    bbody = BLOCK_EXPR_BODY (bbody);
+  if (bbody && bbody != empty_stmt_node)
+    return 0;
+  
+  type = DECL_CONTEXT (mdecl);
+  current = TYPE_FIELDS (type);
+
+  for (current = (current ? TREE_CHAIN (current) : current); 
+       current; current = TREE_CHAIN (current))
+    if (!(FIELD_STATIC (current) && FIELD_FINAL (current)
+         && DECL_INITIAL (current) && TREE_CONSTANT (DECL_INITIAL (current))))
+      break;
+
+  if (current)
+    return 0;
+
+  /* Get rid of <clinit> in the class' list of methods */
+  if (TYPE_METHODS (type) == mdecl)
+    TYPE_METHODS (type) = TREE_CHAIN (mdecl);
+  else
+    for (current = TYPE_METHODS (type); current; 
+        current = TREE_CHAIN (current))
+      if (TREE_CHAIN (current) == mdecl)
+       {
+         TREE_CHAIN (current) = TREE_CHAIN (mdecl);
+         break;
+       }
+
+  return 1;
+}
+
+
 /* Complete and expand a method.  */
 
 static void
 java_complete_expand_method (mdecl)
      tree mdecl;
 {
+  int yank_clinit = 0;
+
   current_function_decl = mdecl;
   /* Fix constructors before expanding them */
   if (DECL_CONSTRUCTOR_P (mdecl))
@@ -7454,15 +7621,19 @@ java_complete_expand_method (mdecl)
          && !flag_emit_xref)
        missing_return_error (current_function_decl);
 
-      complete_start_java_method (mdecl); 
-
+      /* Check wether we could just get rid of clinit, now the picture
+         is complete. */
+      if (!(yank_clinit = maybe_yank_clinit (mdecl)))
+       complete_start_java_method (mdecl); 
+      
       /* Don't go any further if we've found error(s) during the
-         expansion */
-      if (!java_error_count)
+        expansion */
+      if (!java_error_count && !yank_clinit)
        source_end_java_method ();
       else
        {
-         pushdecl_force_head (DECL_ARGUMENTS (mdecl));
+         if (java_error_count)
+           pushdecl_force_head (DECL_ARGUMENTS (mdecl));
          poplevel (1, 0, 1);
        }
 
@@ -7883,7 +8054,7 @@ build_access_to_thisn (from, to, lc)
 
 /* Build an access function to the this$<n> local to TYPE. NULL_TREE
    is returned if nothing needs to be generated. Otherwise, the method
-   generated, fully walked and a method decl is returned.  
+   generated and a method decl is returned.  
 
    NOTE: These generated methods should be declared in a class file
    attribute so that they can't be referred to directly.  */
@@ -8226,6 +8397,7 @@ verify_constructor_super (mdecl)
      tree mdecl;
 {
   tree class = CLASSTYPE_SUPER (current_class);
+  int super_inner = PURE_INNER_CLASS_TYPE_P (class);
   tree sdecl;
 
   if (!class)
@@ -8238,17 +8410,19 @@ verify_constructor_super (mdecl)
       for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
        if (DECL_CONSTRUCTOR_P (sdecl))
          {
-           tree arg_type;
-           for (arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
-                arg_type != end_params_node && 
-                  mdecl_arg_type != end_params_node;
+           tree m_arg_type;
+           tree arg_type = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
+           if (super_inner)
+             arg_type = TREE_CHAIN (arg_type);
+           for (m_arg_type = mdecl_arg_type; 
+                (arg_type != end_params_node 
+                 && m_arg_type != end_params_node);
                 arg_type = TREE_CHAIN (arg_type), 
-                mdecl_arg_type = TREE_CHAIN (mdecl_arg_type))
-             if (TREE_VALUE (arg_type) != TREE_VALUE (mdecl_arg_type))
+                  m_arg_type = TREE_CHAIN (m_arg_type))
+             if (TREE_VALUE (arg_type) != TREE_VALUE (m_arg_type))
                break;
 
-           if (arg_type == end_params_node && 
-               mdecl_arg_type == end_params_node)
+           if (arg_type == end_params_node && m_arg_type == end_params_node)
              return 0;
          }
     }
@@ -8256,9 +8430,10 @@ verify_constructor_super (mdecl)
     {
       for (sdecl = TYPE_METHODS (class); sdecl; sdecl = TREE_CHAIN (sdecl))
        {
-         if (DECL_CONSTRUCTOR_P (sdecl)
-             && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl))) 
-                == end_params_node)
+         tree arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (sdecl)));
+         if (super_inner)
+           arg = TREE_CHAIN (arg);
+         if (DECL_CONSTRUCTOR_P (sdecl) && arg == end_params_node)
            return 0;
        }
     }
@@ -8279,12 +8454,6 @@ java_expand_classes ()
   java_layout_classes ();
   java_parse_abort_on_error ();
 
-  /* The list of packages declaration seen so far needs to be
-     reversed, so that package declared in a file being compiled gets
-     priority over packages declared as a side effect of parsing other
-     files.*/
-  package_list = nreverse (package_list);
-
   saved_ctxp = ctxp_for_generation;
   for (; ctxp_for_generation; ctxp_for_generation = ctxp_for_generation->next)
     {
@@ -8363,7 +8532,7 @@ make_qualified_primary (primary, right, location)
   tree wfl;
 
   if (TREE_CODE (primary) != EXPR_WITH_FILE_LOCATION)
-    wfl = build_wfl_wrap (primary);
+    wfl = build_wfl_wrap (primary, location);
   else
     {
       wfl = primary;
@@ -8580,12 +8749,25 @@ resolve_field_access (qual_wfl, field_decl, field_type)
     return error_mark_node;
 
   /* Resolve the LENGTH field of an array here */
-  if (DECL_NAME (decl) == length_identifier_node && TYPE_ARRAY_P (type_found)
+  if (DECL_P (decl) && DECL_NAME (decl) == length_identifier_node 
+      && type_found && TYPE_ARRAY_P (type_found) 
       && ! 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);
+
+      /* In case we're dealing with a static array, we need to
+        initialize its class before the array length can be fetched.
+        It's also a good time to create a DECL_RTL for the field if
+        none already exists, otherwise if the field was declared in a
+        class found in an external file and hasn't been (and won't
+        be) accessed for its value, none will be created. */
+      if (TREE_CODE (where_found) == VAR_DECL && FIELD_STATIC (where_found))
+       {
+         build_static_field_ref (where_found);
+         field_ref = build_class_init (DECL_CONTEXT (where_found), field_ref);
+       }
     }
   /* We might have been trying to resolve field.method(). In which
      case, the resolution is over and decl is the answer */
@@ -8597,12 +8779,14 @@ resolve_field_access (qual_wfl, field_decl, field_type)
       if (!type_found)
        type_found = DECL_CONTEXT (decl);
       is_static = JDECL_P (decl) && FIELD_STATIC (decl);
-      if (FIELD_FINAL (decl) 
+      if (FIELD_FINAL (decl) && FIELD_STATIC (decl)
          && JPRIMITIVE_TYPE_P (TREE_TYPE (decl))
-         && DECL_LANG_SPECIFIC (decl)
          && DECL_INITIAL (decl))
        {
-         field_ref = 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
@@ -8613,7 +8797,7 @@ resolve_field_access (qual_wfl, field_decl, field_type)
        return error_mark_node;
       if (is_static && !static_final_found 
          && !flag_emit_class_files && !flag_emit_xref)
-       field_ref = build_class_init (type_found, field_ref);
+       field_ref = build_class_init (DECL_CONTEXT (decl), field_ref);
     }
   else
     field_ref = decl;
@@ -8847,9 +9031,19 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              *where_found = decl = current_this;
              *type_found = type = QUAL_DECL_TYPE (decl);
            }
-         /* We're trying to access the this from somewhere else... */
+         /* We're trying to access the this from somewhere else. Make sure
+            it's allowed before doing so. */
          else
            {
+             if (!enclosing_context_p (type, current_class))
+               {
+                 char *p  = xstrdup (lang_printable_name (type, 0));
+                 parse_error_context (qual_wfl, "Can't use variable `%s.this': type `%s' isn't an outer type of type `%s'", 
+                                      p, p, 
+                                      lang_printable_name (current_class, 0));
+                 free (p);
+                 return 1;
+               }
              *where_found = decl = build_current_thisn (type);
              from_qualified_this = 1;
            }
@@ -8891,7 +9085,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
            {
              tree list;
              *where_found = decl = resolve_no_layout (name, qual_wfl);
-             /* We wan't to be absolutely that the class is laid
+             /* We want to be absolutely sure that the class is laid
                  out. We're going to search something inside it. */
              *type_found = type = TREE_TYPE (decl);
              layout_class (type);
@@ -9015,6 +9209,24 @@ 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)
+               {
+                 tree ptr, inner_decl;
+
+                 BUILD_PTR_FROM_NAME (ptr, EXPR_WFL_NODE (qual_wfl));
+                 inner_decl = resolve_class (decl, ptr, NULL_TREE, qual_wfl);
+                 if (inner_decl)
+                   {
+                     check_inner_class_access (inner_decl, decl, qual_wfl); 
+                     type = TREE_TYPE (inner_decl);
+                     decl = inner_decl;
+                     from_type = 1;
+                     continue;
+                   }
+               }
+
              if (field_decl == NULL_TREE)
                {
                  parse_error_context 
@@ -9129,7 +9341,8 @@ 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). */
+   can't be accessed from REFERENCE (a record type). This should be
+   used when decl is a field or a method.*/
 
 static int
 not_accessible_p (reference, member, from_super)
@@ -9138,6 +9351,10 @@ not_accessible_p (reference, member, from_super)
 {
   int access_flag = get_access_flags_from_decl (member);
 
+  /* Inner classes are processed by check_inner_class_access */
+  if (INNER_CLASS_TYPE_P (reference))
+    return 0;
+
   /* Access always granted for members declared public */
   if (access_flag & ACC_PUBLIC)
     return 0;
@@ -9156,7 +9373,17 @@ not_accessible_p (reference, member, from_super)
        return 0;
 
       /* Otherwise, access is granted if occuring from the class where
-        member is declared or a subclass of it */
+        member is declared or a subclass of it. Find the right
+        context to perform the check */
+      if (PURE_INNER_CLASS_TYPE_P (reference))
+        {
+          while (INNER_CLASS_TYPE_P (reference))
+            {
+              if (inherits_from_p (reference, DECL_CONTEXT (member)))
+                return 0;
+              reference = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (reference)));
+            }
+        }
       if (inherits_from_p (reference, DECL_CONTEXT (member)))
        return 0;
       return 1;
@@ -9164,8 +9391,7 @@ 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. This section is probably not
-     complete. FIXME */
+     are accesses from inner-classes. */
   if (access_flag & ACC_PRIVATE)
     return (current_class == DECL_CONTEXT (member) ? 0 : 
            (INNER_CLASS_TYPE_P (current_class) ? 0 : 1));
@@ -9317,6 +9543,16 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
 
       type = GET_SKIP_TYPE (resolved);
       resolve_and_layout (type, NULL_TREE);
+      
+      if (JPRIMITIVE_TYPE_P (type))
+        {
+        parse_error_context
+          (identifier_wfl,
+          "Can't invoke a method on primitive type `%s'",
+          IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+        PATCH_METHOD_RETURN_ERROR ();         
+      }      
+      
       list = lookup_method_invoke (0, identifier_wfl, type, identifier, args);
       args = nreverse (args);
 
@@ -9479,7 +9715,7 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
             
             maybe_use_access_method returns a non zero value if the
             this_arg has to be moved into the (then generated) stub
-            argument list. In the mean time, the selected function
+            argument list. In the meantime, the selected function
             might have be replaced by a generated stub. */
          if (maybe_use_access_method (is_super_init, &list, &this_arg))
            args = tree_cons (NULL_TREE, this_arg, args);
@@ -9528,6 +9764,30 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl)
        args = tree_cons (NULL_TREE, integer_zero_node, args);
     }
 
+  /* This handles the situation where a constructor invocation needs
+     to have an enclosing context passed as a second parameter (the
+     constructor is one of an inner class. We extract it from the
+     current function.  */
+  if (is_super_init && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list)))
+    {
+      tree enclosing_decl = DECL_CONTEXT (TYPE_NAME (current_class));
+      tree extra_arg;
+
+      if (ANONYMOUS_CLASS_P (current_class) || !DECL_CONTEXT (enclosing_decl))
+       {
+         extra_arg = DECL_FUNCTION_BODY (current_function_decl);
+         extra_arg = TREE_CHAIN (BLOCK_EXPR_DECLS (extra_arg));
+       }
+      else
+       {
+         tree dest = TREE_TYPE (DECL_CONTEXT (enclosing_decl));
+         extra_arg = 
+           build_access_to_thisn (TREE_TYPE (enclosing_decl), dest, 0);
+         extra_arg = java_complete_tree (extra_arg);
+       }
+      args = tree_cons (NULL_TREE, extra_arg, args);
+    }
+
   is_static_flag = METHOD_STATIC (list);
   if (! METHOD_STATIC (list) && this_arg != NULL_TREE)
     args = tree_cons (NULL_TREE, this_arg, args);
@@ -9623,7 +9883,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg)
   if (non_static_context)
     {
       ctx = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current_class)));
-      if (ctx == DECL_CONTEXT (md))
+      if (inherits_from_p (ctx, DECL_CONTEXT (md)))
        {
          ta = build_current_thisn (current_class);
          ta = build_wfl_node (ta);
@@ -9634,7 +9894,7 @@ maybe_use_access_method (is_super_init, mdecl, this_arg)
          while (type)
            {
              maybe_build_thisn_access_method (type);
-             if (type == DECL_CONTEXT (md))
+             if (inherits_from_p (type, DECL_CONTEXT (md)))
                {
                  ta = build_access_to_thisn (ctx, type, 0);
                  break;
@@ -9917,9 +10177,29 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
      int lc;
      tree class, name, arglist;
 {
-  static int object_done = 0;
+  static struct hash_table t, *searched_classes = NULL;
+  static int search_not_done = 0;
   tree list = NULL_TREE, all_list = NULL_TREE;
 
+  /* Check the hash table to determine if this class has been searched 
+     already. */
+  if (searched_classes)
+    {
+      if (hash_lookup (searched_classes, 
+                      (const hash_table_key) class, FALSE, NULL))
+       return NULL;
+    }
+  else
+    {
+      hash_table_init (&t, hash_newfunc, java_hash_hash_tree_node,
+                      java_hash_compare_tree_node);
+      searched_classes = &t;
+    }
+    
+  search_not_done++;
+  hash_lookup (searched_classes, 
+              (const hash_table_key) class, TRUE, NULL);
+
   if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class))
     {
       load_class (class, 1);
@@ -9927,32 +10207,11 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
     }
 
   /* Search interfaces */
-  if (CLASS_INTERFACE (TYPE_NAME (class)))
+  if (TREE_CODE (TYPE_NAME (class)) == TYPE_DECL 
+      && CLASS_INTERFACE (TYPE_NAME (class)))
     {
-      static struct hash_table t, *searched_interfaces = NULL;
-      static int search_not_done = 0;
       int i, n;
       tree basetype_vec = TYPE_BINFO_BASETYPES (class);
-
-      /* Search in the hash table, otherwise create a new one if
-         necessary and insert the new entry. */
-
-      if (searched_interfaces)
-       {
-         if (hash_lookup (searched_interfaces, 
-                          (const hash_table_key) class, FALSE, NULL))
-           return NULL;
-       }
-      else
-       {
-         hash_table_init (&t, hash_newfunc, java_hash_hash_tree_node,
-                          java_hash_compare_tree_node);
-         searched_interfaces = &t;
-       }
-
-      hash_lookup (searched_interfaces, 
-                  (const hash_table_key) class, TRUE, NULL);
-
       search_applicable_methods_list (lc, TYPE_METHODS (class), 
                                      name, arglist, &list, &all_list);
       n = TREE_VEC_LENGTH (basetype_vec);
@@ -9961,23 +10220,9 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
          tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
          tree rlist;
 
-         search_not_done++;
          rlist = find_applicable_accessible_methods_list (lc,  t, name, 
                                                           arglist);
          list = chainon (rlist, list);
-         search_not_done--;
-       }
-
-      /* We're done. Reset the searched interfaces list and finally search
-         java.lang.Object */
-      if (!search_not_done)
-       {  
-         if (!object_done)
-           search_applicable_methods_list (lc, 
-                                           TYPE_METHODS (object_type_node),
-                                           name, arglist, &list, &all_list);
-         hash_table_free (searched_interfaces);
-         searched_interfaces = NULL;  
        }
     }
   /* Search classes */
@@ -9993,17 +10238,17 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
       {
        tree basetype_vec = TYPE_BINFO_BASETYPES (sc);
        int n = TREE_VEC_LENGTH (basetype_vec), i;
-       object_done = 1;
        for (i = 1; i < n; i++)
          {
            tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
-           tree rlist;
            if (t != object_type_node)
-             rlist = find_applicable_accessible_methods_list (lc, t,
-                                                              name, arglist);
-           list = chainon (rlist, list);
+             {
+               tree rlist
+                 = find_applicable_accessible_methods_list (lc, t,
+                                                            name, arglist);
+               list = chainon (rlist, list);
+             }
          }
-       object_done = 0;
       }
 
       /* Search enclosing context of inner classes before looking
@@ -10024,10 +10269,35 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
       else
        class = sc;
 
-      for (class = (lc ? NULL_TREE : CLASSTYPE_SUPER (class)); 
-        class; class = CLASSTYPE_SUPER (class))
-       search_applicable_methods_list (lc, TYPE_METHODS (class), 
-                                       name, arglist, &list, &all_list);
+      /* Search superclass */
+      if (!lc && CLASSTYPE_SUPER (class) != NULL_TREE)
+       {
+          tree rlist;
+          class = CLASSTYPE_SUPER (class);
+          rlist = find_applicable_accessible_methods_list (lc, class, 
+                                                           name, arglist);
+          list = chainon (rlist, list);
+        }
+    }
+
+  search_not_done--;
+
+  /* We're done. Reset the searched classes list and finally search
+     java.lang.Object if it wasn't searched already. */
+  if (!search_not_done)
+    {
+      if (!lc
+         && TYPE_METHODS (object_type_node)
+         && !hash_lookup (searched_classes, 
+                           (const hash_table_key) object_type_node, 
+                           FALSE, NULL))
+       {
+          search_applicable_methods_list (lc, 
+                                          TYPE_METHODS (object_type_node),
+                                          name, arglist, &list, &all_list);
+        }
+      hash_table_free (searched_classes);
+      searched_classes = NULL;
     }
 
   /* Either return the list obtained or all selected (but
@@ -10035,7 +10305,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
   return (!list ? all_list : list);
 }
 
-/* Effectively search for the approriate method in method */
+/* Effectively search for the appropriate method in method */
 
 static void 
 search_applicable_methods_list (lc, method, name, arglist, list, all_list)
@@ -10064,7 +10334,7 @@ search_applicable_methods_list (lc, method, name, arglist, list, all_list)
            *all_list = tree_cons (NULL_TREE, method, *list);
        }
     }
-}    
+}
 
 /* 15.11.2.2 Choose the Most Specific Method */
 
@@ -10073,6 +10343,7 @@ find_most_specific_methods_list (list)
      tree list;
 {
   int max = 0;
+  int abstract, candidates;
   tree current, new_list = NULL_TREE;
   for (current = list; current; current = TREE_CHAIN (current))
     {
@@ -10081,42 +10352,59 @@ find_most_specific_methods_list (list)
 
       for (method = list; method; method = TREE_CHAIN (method))
        {
+         tree method_v, current_v;
          /* Don't test a method against itself */
          if (method == current)
            continue;
 
-         /* Compare arguments and location where method where declared */
-         if (argument_types_convertible (TREE_VALUE (method), 
-                                         TREE_VALUE (current))
-             && valid_method_invocation_conversion_p 
-                  (DECL_CONTEXT (TREE_VALUE (method)), 
-                   DECL_CONTEXT (TREE_VALUE (current))))
+         method_v = TREE_VALUE (method);
+         current_v = TREE_VALUE (current);
+
+         /* Compare arguments and location where methods where declared */
+         if (argument_types_convertible (method_v, current_v))
            {
-             int v = ++DECL_SPECIFIC_COUNT (TREE_VALUE (current));
-             max = (v > max ? v : max);
+             if (valid_method_invocation_conversion_p 
+                 (DECL_CONTEXT (method_v), DECL_CONTEXT (current_v))
+                 || (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v))
+                     && enclosing_context_p (DECL_CONTEXT (method_v),
+                                             DECL_CONTEXT (current_v))))
+               {
+                 int v = (DECL_SPECIFIC_COUNT (current_v) += 
+                   (INNER_CLASS_TYPE_P (DECL_CONTEXT (current_v)) ? 2 : 1));
+                 max = (v > max ? v : max);
+               }
            }
        }
     }
 
   /* Review the list and select the maximally specific methods */
-  for (current = list; current; current = TREE_CHAIN (current))
+  for (current = list, abstract = -1, candidates = -1;
+       current; current = TREE_CHAIN (current))
     if (DECL_SPECIFIC_COUNT (TREE_VALUE (current)) == max)
-      new_list = tree_cons (NULL_TREE, TREE_VALUE (current), new_list);
+      {
+       new_list = tree_cons (NULL_TREE, TREE_VALUE (current), new_list);
+       abstract += (METHOD_ABSTRACT (TREE_VALUE (current)) ? 1 : 0);
+       candidates++;
+      }
 
   /* If we have several and they're all abstract, just pick the
      closest one. */
+  if (candidates > 0 && (candidates == abstract))
+    {
+      new_list = nreverse (new_list);
+      TREE_CHAIN (new_list) = NULL_TREE;
+    }
 
-  if (new_list && TREE_CHAIN (new_list))
+  /* We have several, we couldn't find a most specific, all but one are
+     abstract, we pick the only non abstract one. */
+  if (candidates > 0 && !max && (candidates == abstract+1))
     {
-      tree c;
-      for (c = new_list; c && METHOD_ABSTRACT (TREE_VALUE (c)); 
-          c = TREE_CHAIN (c))
-        ;
-      if (!c)
-       {
-         new_list = nreverse (new_list);
-         TREE_CHAIN (new_list) = NULL_TREE;
-       }
+      for (current = new_list; current; current = TREE_CHAIN (current))
+       if (!METHOD_ABSTRACT (TREE_VALUE (current)))
+         {
+           TREE_CHAIN (current) = NULL_TREE;
+           new_list = current;
+         }
     }
 
   /* If we can't find one, lower expectations and try to gather multiple
@@ -10421,8 +10709,8 @@ java_complete_tree (node)
      tree node;
 {
   node = java_complete_lhs (node);
-  if (TREE_CODE (node) == VAR_DECL && FIELD_STATIC (node)
-      && FIELD_FINAL (node) && DECL_INITIAL (node) != NULL_TREE
+  if (JDECL_P (node) && FIELD_STATIC (node) && FIELD_FINAL (node) 
+      && DECL_INITIAL (node) != NULL_TREE
       && !flag_emit_xref)
     {
       tree value = DECL_INITIAL (node);
@@ -10712,7 +11000,7 @@ java_complete_lhs (node)
       else
        node = patch_switch_statement (node);
 
-      if (TREE_OPERAND (node, 0) == error_mark_node)
+      if (node == error_mark_node || TREE_OPERAND (node, 0) == error_mark_node)
        nn = error_mark_node;
       else
        {
@@ -10932,7 +11220,8 @@ java_complete_lhs (node)
                  (type == string_ptr_type_node && ! flag_emit_class_files))
                return empty_stmt_node;
            }
-         DECL_INITIAL (nn) = NULL_TREE;
+         if (! flag_emit_class_files)
+           DECL_INITIAL (nn) = NULL_TREE;
        }
       wfl_op2 = TREE_OPERAND (node, 1);
 
@@ -11355,8 +11644,9 @@ maybe_absorb_scoping_blocks ()
 
 /* Wrap a non WFL node around a WFL.  */
 static tree
-build_wfl_wrap (node)
+build_wfl_wrap (node, location)
     tree node;
+    int location;
 {
   tree wfl, node_to_insert = node;
   
@@ -11368,7 +11658,7 @@ build_wfl_wrap (node)
   else
     wfl = build_expr_wfl (NULL_TREE, ctxp->filename, 0, 0);
 
-  EXPR_WFL_LINECOL (wfl) = EXPR_WFL_LINECOL (node);
+  EXPR_WFL_LINECOL (wfl) = location;
   EXPR_WFL_QUALIFICATION (wfl) = build_tree_list (node_to_insert, NULL_TREE);
   return wfl;
 }
@@ -11534,7 +11824,8 @@ maybe_build_primttype_type_ref (rhs, wfl)
       tree n = TREE_OPERAND (rhs, 1);
       if (TREE_CODE (n) == VAR_DECL 
          && DECL_NAME (n) == TYPE_identifier_node
-         && rhs_type == class_ptr_type)
+         && rhs_type == class_ptr_type
+         && TREE_CODE (EXPR_WFL_NODE (wfl)) == IDENTIFIER_NODE)
        {
          const char *self_name = IDENTIFIER_POINTER (EXPR_WFL_NODE (wfl));
          if (!strncmp (self_name, "java.lang.", 10))
@@ -11870,7 +12161,6 @@ valid_ref_assignconv_cast_p (source, dest, cast)
       if (TYPE_CLASS_P (dest))
        return  (source == dest 
                 || inherits_from_p (source, dest)
-                || enclosing_context_p (dest, source /*source, dest*/)
                 || (cast && inherits_from_p (dest, source)));
       if (TYPE_INTERFACE_P (dest))
        {
@@ -12824,7 +13114,10 @@ patch_incomplete_class_ref (node)
     return error_mark_node;
 
   if (!flag_emit_class_files || JPRIMITIVE_TYPE_P (ref_type))
-    return 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 we're emitting class files and we have to deal with non
      primitive types, we invoke (and consider generating) the
@@ -13047,7 +13340,7 @@ resolve_type_during_patch (type)
 {
   if (unresolved_type_p (type, NULL))
     {
-      tree type_decl = resolve_no_layout (EXPR_WFL_NODE (type), NULL_TREE);
+      tree type_decl = resolve_no_layout (EXPR_WFL_NODE (type), type);
       if (!type_decl)
        {
          parse_error_context (type, 
@@ -13426,7 +13719,8 @@ patch_new_array_init (type, node)
          TREE_PURPOSE (current) = NULL_TREE;
          all_constant = 0;
        }
-      if (elt && TREE_VALUE (elt) == error_mark_node)
+      if (elt && TREE_CODE (elt) == TREE_LIST 
+         && TREE_VALUE (elt) == error_mark_node)
        error_seen = 1;
     }
 
@@ -13492,7 +13786,7 @@ array_constructor_check_entry (type, entry)
   
   if (new_value)
     {
-      new_value = maybe_build_primttype_type_ref (new_value, wfl_operator);
+      new_value = maybe_build_primttype_type_ref (new_value, wfl_value);
       TREE_VALUE (entry) = new_value;
     }
 
@@ -14588,12 +14882,9 @@ fold_constant_for_init (node, context)
   tree op0, op1, val;
   enum tree_code code = TREE_CODE (node);
 
-  if (code == STRING_CST)
+  if (code == STRING_CST || code == INTEGER_CST || code == REAL_CST)
     return node;
 
-  if (code == INTEGER_CST || code == REAL_CST)
-    return convert (TREE_TYPE (context), node);
-
   switch (code)
     {
     case PLUS_EXPR: