OSDN Git Service

Merge from pch-branch up to tag pch-commit-20020603.
[pf3gnuchains/gcc-fork.git] / gcc / java / parse.y
index 80c60fd..960bd90 100644 (file)
@@ -1,6 +1,6 @@
 /* Source code parsing and tree node generation for the GNU compiler
    for the Java(TM) language.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
 
 This file is part of GNU CC.
@@ -51,6 +51,7 @@ definitions and other extensions.  */
 #include <dirent.h>
 #include "tree.h"
 #include "rtl.h"
+#include "real.h"
 #include "obstack.h"
 #include "toplev.h"
 #include "flags.h"
@@ -65,6 +66,7 @@ definitions and other extensions.  */
 #include "function.h"
 #include "except.h"
 #include "ggc.h"
+#include "debug.h"
 
 #ifndef DIR_SEPARATOR
 #define DIR_SEPARATOR '/'
@@ -104,10 +106,10 @@ static void find_in_imports PARAMS ((tree, tree));
 static void check_inner_class_access PARAMS ((tree, tree, tree));
 static int check_pkg_class_access PARAMS ((tree, tree, bool));
 static void register_package PARAMS ((tree));
-static tree resolve_package PARAMS ((tree, tree *));
-static tree lookup_package_type PARAMS ((const char *, int));
+static tree resolve_package PARAMS ((tree, tree *, tree *));
 static tree resolve_class PARAMS ((tree, tree, tree, tree));
 static void declare_local_variables PARAMS ((int, tree, tree));
+static void dump_java_tree PARAMS ((enum tree_dump_index, tree));
 static void source_start_java_method PARAMS ((tree));
 static void source_end_java_method PARAMS ((void));
 static tree find_name_in_single_imports PARAMS ((tree));
@@ -141,7 +143,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 analyze_clinit_body PARAMS ((tree));
+static int analyze_clinit_body PARAMS ((tree, tree));
 static int maybe_yank_clinit PARAMS ((tree));
 static void start_complete_expand_method PARAMS ((tree));
 static void java_complete_expand_method PARAMS ((tree));
@@ -242,7 +244,7 @@ static tree build_instinit_invocation PARAMS ((tree));
 static void fix_constructors PARAMS ((tree));
 static tree build_alias_initializer_parameter_list PARAMS ((int, tree,
                                                            tree, int *));
-static void craft_constructor PARAMS ((tree, tree));
+static tree craft_constructor PARAMS ((tree, tree));
 static int verify_constructor_super PARAMS ((tree));
 static tree create_artificial_method PARAMS ((tree, int, tree, tree, tree));
 static void start_artificial_method_body PARAMS ((tree));
@@ -294,11 +296,10 @@ static int pop_current_osb PARAMS ((struct parser_ctxt *));
 /* JDK 1.1 work. FIXME */
 
 static tree maybe_make_nested_class_name PARAMS ((tree));
-static void make_nested_class_name PARAMS ((tree));
+static int make_nested_class_name PARAMS ((tree));
 static void set_nested_class_simple_name_value PARAMS ((tree, int));
 static void link_nested_class_to_enclosing PARAMS ((void));
-static tree resolve_inner_class PARAMS ((struct hash_table *, tree, tree *,
-                                        tree *, tree));
+static tree resolve_inner_class PARAMS ((htab_t, tree, tree *, tree *, tree));
 static tree find_as_inner_class PARAMS ((tree, tree, tree));
 static tree find_as_inner_class_do PARAMS ((tree, tree));
 static int check_inner_class_redefinition PARAMS ((tree, tree));
@@ -333,9 +334,10 @@ static void create_new_parser_context PARAMS ((int));
 static void mark_parser_ctxt PARAMS ((void *));
 static tree maybe_build_class_init_for_field PARAMS ((tree, tree));
 
-static bool attach_init_test_initialization_flags PARAMS ((struct hash_entry *,
-                                                         PTR));
-static bool emit_test_initialization PARAMS ((struct hash_entry *, PTR));
+static int attach_init_test_initialization_flags PARAMS ((PTR *, PTR));
+static int emit_test_initialization PARAMS ((PTR *, PTR));
+
+static char *string_convert_int_cst PARAMS ((tree));
 
 /* Number of error found so far. */
 int java_error_count; 
@@ -357,7 +359,7 @@ struct parser_ctxt *ctxp_for_generation = NULL;
    covers both integral/floating point division. The code is changed
    once the type of both operator is worked out.  */
 
-static enum tree_code binop_lookup[19] = 
+static const enum tree_code binop_lookup[19] = 
   { 
     PLUS_EXPR, MINUS_EXPR, MULT_EXPR, RDIV_EXPR, TRUNC_MOD_EXPR,
     LSHIFT_EXPR, RSHIFT_EXPR, URSHIFT_EXPR, 
@@ -373,54 +375,58 @@ static enum tree_code binop_lookup[19] =
 #define BINOP_COMPOUND_CANDIDATES 11
 
 /* The "$L" identifier we use to create labels.  */
-static tree label_id = NULL_TREE;
+static GTY(()) tree label_id;
 
 /* The "StringBuffer" identifier used for the String `+' operator. */
-static tree wfl_string_buffer = NULL_TREE
+static GTY(()) tree wfl_string_buffer
 
 /* The "append" identifier used for String `+' operator.  */
-static tree wfl_append = NULL_TREE;
+static GTY(()) tree wfl_append;
 
 /* The "toString" identifier used for String `+' operator. */
-static tree wfl_to_string = NULL_TREE;
+static GTY(()) tree wfl_to_string;
 
 /* The "java.lang" import qualified name.  */
-static tree java_lang_id = NULL_TREE;
+static GTY(()) tree java_lang_id;
 
 /* The generated `inst$' identifier used for generated enclosing
    instance/field access functions.  */
-static tree inst_id = NULL_TREE;
+static GTY(()) tree inst_id;
 
 /* The "java.lang.Cloneable" qualified name.  */
-static tree java_lang_cloneable = NULL_TREE;
+static GTY(()) tree java_lang_cloneable;
 
 /* The "java.io.Serializable" qualified name.  */
-static tree java_io_serializable = NULL_TREE
+static GTY(()) tree java_io_serializable
 
 /* Context and flag for static blocks */
-static tree current_static_block = NULL_TREE;
+static GTY(()) tree current_static_block;
 
 /* The generated `write_parm_value$' identifier.  */
-static tree wpv_id;
+static GTY(()) tree wpv_id;
 
 /* The list of all packages we've seen so far */
-static tree package_list = NULL_TREE;
+static GTY(()) tree package_list;
  
 /* Hold THIS for the scope of the current method decl.  */
-static tree current_this;
+static GTY(()) tree current_this;
 
 /* Hold a list of catch clauses list. The first element of this list is
    the list of the catch clauses of the currently analysed try block. */
-static tree currently_caught_type_list;
+static GTY(()) tree currently_caught_type_list;
 
 /* This holds a linked list of all the case labels for the current
    switch statement.  It is only used when checking to see if there
    are duplicate labels.  FIXME: probably this should just be attached
    to the switch itself; then it could be referenced via
    `ctxp->current_loop'.  */
-static tree case_label_list; 
+static GTY(()) tree case_label_list; 
 
-static tree src_parse_roots[1] = { NULL_TREE };
+/* Anonymous class counter. Will be reset to 1 every time a non
+   anonymous class gets created. */
+static int anonymous_class_counter = 1;
+
+static GTY(()) tree src_parse_roots[1];
 
 /* All classes seen from source code */
 #define gclass_list src_parse_roots[0]
@@ -481,8 +487,8 @@ static tree src_parse_roots[1] = { NULL_TREE };
 %token   PUBLIC_TK       PRIVATE_TK         PROTECTED_TK
 %token   STATIC_TK       FINAL_TK           SYNCHRONIZED_TK
 %token   VOLATILE_TK     TRANSIENT_TK       NATIVE_TK
-%token   PAD_TK          ABSTRACT_TK        MODIFIER_TK
-%token   STRICT_TK
+%token   PAD_TK          ABSTRACT_TK        STRICT_TK
+%token   MODIFIER_TK
 
 /* Keep those two in order, too */
 %token   DECR_TK INCR_TK
@@ -607,20 +613,6 @@ goal:
                 {
                  /* Register static variables with the garbage
                     collector.  */
-                 ggc_add_tree_root (&label_id, 1);
-                 ggc_add_tree_root (&wfl_string_buffer, 1);
-                 ggc_add_tree_root (&wfl_append, 1);
-                 ggc_add_tree_root (&wfl_to_string, 1);
-                 ggc_add_tree_root (&java_lang_id, 1);
-                 ggc_add_tree_root (&inst_id, 1);
-                 ggc_add_tree_root (&java_lang_cloneable, 1);
-                 ggc_add_tree_root (&java_io_serializable, 1);
-                 ggc_add_tree_root (&current_static_block, 1);
-                 ggc_add_tree_root (&wpv_id, 1);
-                 ggc_add_tree_root (&package_list, 1);
-                 ggc_add_tree_root (&current_this, 1);
-                 ggc_add_tree_root (&currently_caught_type_list, 1);
-                 ggc_add_tree_root (&case_label_list, 1);
                  ggc_add_root (&ctxp, 1, 
                                sizeof (struct parser_ctxt *),
                                mark_parser_ctxt);
@@ -1598,7 +1590,7 @@ switch_statement:
        switch_block
                { 
                  /* Make into "proper list" of COMPOUND_EXPRs.
-                    I.e. make the last statment also have its own
+                    I.e. make the last statement also have its own
                     COMPOUND_EXPR. */
                  maybe_absorb_scoping_blocks ();
                  TREE_OPERAND ($1, 1) = exit_block ();
@@ -3494,30 +3486,28 @@ check_class_interface_creation (is_interface, flags, raw_name, qualified_name, d
   return 0;
 }
 
-static void
+/* Construct a nested class name.  If the final component starts with
+   a digit, return true.  Otherwise return false.  */
+static int
 make_nested_class_name (cpc_list)
      tree cpc_list;
 {
   tree name;
 
   if (!cpc_list)
-    return;
-  else
-    make_nested_class_name (TREE_CHAIN (cpc_list));
+    return 0;
+
+  make_nested_class_name (TREE_CHAIN (cpc_list));
 
   /* Pick the qualified name when dealing with the first upmost
      enclosing class */
-  name = (TREE_CHAIN (cpc_list) ? 
-         TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
+  name = (TREE_CHAIN (cpc_list)
+         TREE_PURPOSE (cpc_list) : DECL_NAME (TREE_VALUE (cpc_list)));
   obstack_grow (&temporary_obstack,
                IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name));
-  /* Why is NO_DOLLAR_IN_LABEL defined? */
-#if 0
-#ifdef NO_DOLLAR_IN_LABEL
-  internal_error ("Can't use '$' as a separator for inner classes");
-#endif
-#endif
   obstack_1grow (&temporary_obstack, '$');
+
+  return ISDIGIT (IDENTIFIER_POINTER (name)[0]);
 }
 
 /* Can't redefine a class already defined in an earlier scope. */
@@ -3545,7 +3535,7 @@ check_inner_class_redefinition (raw_name, cl)
 
 static tree
 resolve_inner_class (circularity_hash, cl, enclosing, super, class_type)
-     struct hash_table *circularity_hash;
+     htab_t circularity_hash;
      tree cl, *enclosing, *super, class_type;
 {
   tree local_enclosing = *enclosing;
@@ -3555,8 +3545,8 @@ resolve_inner_class (circularity_hash, cl, enclosing, super, class_type)
     {
       tree intermediate, decl;
 
-      hash_lookup (circularity_hash, 
-                  (const  hash_table_key) local_enclosing, TRUE, NULL);
+      *htab_find_slot (circularity_hash, local_enclosing, INSERT) =
+       local_enclosing;
 
       if ((decl = find_as_inner_class (local_enclosing, class_type, cl)))
        return decl;
@@ -3584,8 +3574,7 @@ resolve_inner_class (circularity_hash, cl, enclosing, super, class_type)
 
       /* We may not have checked for circular inheritance yet, so do so
          here to prevent an infinite loop. */
-      if (hash_lookup (circularity_hash,
-                      (const hash_table_key) local_super, FALSE, NULL))
+      if (htab_find (circularity_hash, local_super) != NULL)
         {
           if (!cl)
             cl = lookup_cl (local_enclosing);
@@ -3715,7 +3704,6 @@ link_nested_class_to_enclosing ()
       DECL_INNER_CLASS_LIST (enclosing) = 
        tree_cons (GET_CPC (), GET_CPC_UN (),
                   DECL_INNER_CLASS_LIST (enclosing));
-      enclosing = enclosing;
     }
 }
 
@@ -3727,7 +3715,20 @@ maybe_make_nested_class_name (name)
 
   if (CPC_INNER_P ())
     {
-      make_nested_class_name (GET_CPC_LIST ());
+      /* If we're in a function, we must append a number to create the
+        nested class name.  However, we don't do this if the class we
+        are constructing is anonymous, because in that case we'll
+        already have a number as the class name.  */
+      if (! make_nested_class_name (GET_CPC_LIST ())
+         && current_function_decl != NULL_TREE
+         && ! ISDIGIT (IDENTIFIER_POINTER (name)[0]))
+       {
+         char buf[10];
+         sprintf (buf, "%d", anonymous_class_counter);
+         ++anonymous_class_counter;
+         obstack_grow (&temporary_obstack, buf, strlen (buf));
+         obstack_1grow (&temporary_obstack, '$');
+       }
       obstack_grow0 (&temporary_obstack,
                     IDENTIFIER_POINTER (name), 
                     IDENTIFIER_LENGTH (name));
@@ -3852,7 +3853,7 @@ create_interface (flags, id, super)
   if ((flags & ACC_ABSTRACT) && flag_redundant)
     parse_warning_context 
       (MODIFIER_WFL (ABSTRACT_TK),
-       "Redundant use of `abstract' modifier. Interface `%s' is implicitely abstract", IDENTIFIER_POINTER (raw_name));
+       "Redundant use of `abstract' modifier. Interface `%s' is implicitly abstract", IDENTIFIER_POINTER (raw_name));
 
   /* Create a new decl if DECL is NULL, otherwise fix it */
   decl = maybe_create_class_interface_decl (decl, raw_name, q_name, id);
@@ -3867,10 +3868,6 @@ create_interface (flags, id, super)
   return decl;
 }
 
-/* Anonymous class counter. Will be reset to 1 every time a non
-   anonymous class gets created. */
-static int anonymous_class_counter = 1;
-
 /* Patch anonymous class CLASS, by either extending or implementing
    DEP.  */
 
@@ -4063,13 +4060,16 @@ static void
 end_class_declaration (resume)
      int resume;
 {
-  /* If an error occured, context weren't pushed and won't need to be
+  /* If an error occurred, context weren't pushed and won't need to be
      popped by a resume. */
-  int no_error_occured = ctxp->next && GET_CPC () != error_mark_node;
+  int no_error_occurred = ctxp->next && GET_CPC () != error_mark_node;
+
+  if (GET_CPC () != error_mark_node)
+    dump_java_tree (TDI_class, GET_CPC ());
 
   java_parser_context_pop_initialized_field ();
   POP_CPC ();
-  if (resume && no_error_occured)
+  if (resume && no_error_occurred)
     java_parser_context_resume ();
 
   /* We're ending a class declaration, this is a good time to reset
@@ -4212,6 +4212,13 @@ lookup_field_wrapper (class, name)
       decl = lookup_field (&type, name);
     }
 
+  /* If the field still hasn't been found, try the next enclosing context. */
+  if (!decl && INNER_CLASS_TYPE_P (class))
+    {
+      tree outer_type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
+      decl = lookup_field_wrapper (outer_type, name);
+    }
+
   java_parser_context_restore_global ();
   return decl == error_mark_node ? NULL : decl;
 }
@@ -4546,7 +4553,8 @@ method_header (flags, type, mdecl, throws)
       ABSTRACT_CHECK (flags, ACC_STATIC, id, "Static");
       ABSTRACT_CHECK (flags, ACC_FINAL, id, "Final");
       ABSTRACT_CHECK (flags, ACC_NATIVE, id, "Native");
-      ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED,id, "Synchronized");
+      ABSTRACT_CHECK (flags, ACC_SYNCHRONIZED, id, "Synchronized");
+      ABSTRACT_CHECK (flags, ACC_STRICT, id, "Strictfp");
       if (!CLASS_ABSTRACT (TYPE_NAME (this_class))
          && !CLASS_INTERFACE (TYPE_NAME (this_class)))
        parse_error_context 
@@ -4572,6 +4580,7 @@ method_header (flags, type, mdecl, throws)
          JCONSTRUCTOR_CHECK (flags, ACC_FINAL, id, "final");
          JCONSTRUCTOR_CHECK (flags, ACC_NATIVE, id, "native");
          JCONSTRUCTOR_CHECK (flags, ACC_SYNCHRONIZED, id, "synchronized");
+         JCONSTRUCTOR_CHECK (flags, ACC_STRICT, id, "strictfp");
        }
       /* If we found error here, we don't consider it's OK to tread
         the method definition as a constructor, for the rest of this
@@ -4815,32 +4824,23 @@ constructor_circularity_msg (from, to)
 /* Verify a circular call to METH. Return 1 if an error is found, 0
    otherwise.  */
 
+static GTY(()) tree vcc_list;
 static int
 verify_constructor_circularity (meth, current)
      tree meth, current;
 {
-  static tree list = NULL_TREE;
-  static int initialized_p;
   tree c;
 
-  /* If we haven't already registered LIST with the garbage collector,
-     do so now.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&list, 1);
-      initialized_p = 1;
-    }
-
   for (c = DECL_CONSTRUCTOR_CALLS (current); c; c = TREE_CHAIN (c))
     {
       if (TREE_VALUE (c) == meth)
        {
          char *t;
-         if (list)
+         if (vcc_list)
            {
              tree liste;
-             list = nreverse (list);
-             for (liste = list; liste; liste = TREE_CHAIN (liste))
+             vcc_list = nreverse (vcc_list);
+             for (liste = vcc_list; liste; liste = TREE_CHAIN (liste))
                {
                  parse_error_context 
                    (TREE_PURPOSE (TREE_PURPOSE (liste)), "%s",
@@ -4854,16 +4854,16 @@ verify_constructor_circularity (meth, current)
                               "%s: recursive invocation of constructor `%s'",
                               constructor_circularity_msg (current, meth), t);
          free (t);
-         list = NULL_TREE;
+         vcc_list = NULL_TREE;
          return 1;
        }
     }
   for (c = DECL_CONSTRUCTOR_CALLS (current); c; c = TREE_CHAIN (c))
     {
-      list = tree_cons (c, current, list);
+      vcc_list = tree_cons (c, current, vcc_list);
       if (verify_constructor_circularity (meth, TREE_VALUE (c)))
        return 1;
-      list = TREE_CHAIN (list);
+      vcc_list = TREE_CHAIN (vcc_list);
     }
   return 0;
 }
@@ -5071,12 +5071,12 @@ parser_check_super_interface (super_decl, this_decl, this_wfl)
   if (!CLASS_INTERFACE (super_decl))
     {
       parse_error_context 
-       (this_wfl, "Can't use %s `%s' to implement/extend %s `%s'",
-        (TYPE_ARRAY_P (super_type) ? "array" : "class"),
-        IDENTIFIER_POINTER (DECL_NAME (super_decl)),
+       (this_wfl, "%s `%s' can't implement/extend %s `%s'",
         (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (this_decl))) ? 
-         "interface" : "class"),
-        IDENTIFIER_POINTER (DECL_NAME (this_decl)));
+         "Interface" : "Class"),
+        IDENTIFIER_POINTER (DECL_NAME (this_decl)),
+        (TYPE_ARRAY_P (super_type) ? "array" : "class"),
+        IDENTIFIER_POINTER (DECL_NAME (super_decl)));
       return 1;
     }
 
@@ -5239,14 +5239,23 @@ check_inner_circular_reference (source, target)
 
   if (!basetype_vec)
     return NULL_TREE;
-  
+
   for (i = 0; i < TREE_VEC_LENGTH (basetype_vec); i++)
     {
-      tree su = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
+      tree su;
+
+      /* We can end up with a NULL_TREE or an incomplete type here if
+        we encountered previous type resolution errors. It's safe to
+        simply ignore these cases.  */
+      if (TREE_VEC_ELT (basetype_vec, i) == NULL_TREE)
+       continue;
+      su = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
+      if (INCOMPLETE_TYPE_P (su))
+       continue;
 
       if (inherits_from_p (su, target))
        return lookup_cl (TYPE_NAME (su));
-      
+
       for (ctx = DECL_CONTEXT (TYPE_NAME (su)); ctx; ctx = DECL_CONTEXT (ctx))
        {
          /* An enclosing context shouldn't be TARGET */
@@ -5401,7 +5410,7 @@ build_alias_initializer_parameter_list (mode, class_type, parm, artificial)
    where found. ARGS is non NULL when a special signature must be
    enforced. This is the case for anonymous classes.  */
 
-static void
+static tree
 craft_constructor (class_decl, args)
      tree class_decl, args;
 {
@@ -5450,6 +5459,7 @@ craft_constructor (class_decl, args)
   /* Now, mark the artificial parameters. */
   DECL_FUNCTION_NAP (decl) = artificial;
   DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1;
+  return decl;
 }
 
 
@@ -5634,7 +5644,7 @@ java_complete_class ()
                  tree mdecl = JDEP_DECL (dep), signature;
                  /* Recompute and reset the signature, check first that
                     all types are now defined. If they're not,
-                    dont build the signature. */
+                    don't build the signature. */
                  if (check_method_types_complete (mdecl))
                    {
                      signature = build_java_signature (TREE_TYPE (mdecl));
@@ -5746,14 +5756,15 @@ do_resolve_class (enclosing, class_type, decl, cl)
 {
   tree new_class_decl = NULL_TREE, super = NULL_TREE;
   tree saved_enclosing_type = enclosing ? TREE_TYPE (enclosing) : NULL_TREE;
-  struct hash_table _ht, *circularity_hash = &_ht;
+  tree decl_result;
+  htab_t circularity_hash;
 
   /* This hash table is used to register the classes we're going
      through when searching the current class as an inner class, in
      order to detect circular references. Remember to free it before
      returning the section 0- of this function. */
-  hash_table_init (circularity_hash, hash_newfunc,
-                  java_hash_hash_tree_node, java_hash_compare_tree_node);
+  circularity_hash = htab_create (20, htab_hash_pointer, htab_eq_pointer, 
+                                 NULL);
 
   /* 0- Search in the current class as an inner class.
      Maybe some code here should be added to load the class or
@@ -5775,7 +5786,7 @@ do_resolve_class (enclosing, class_type, decl, cl)
        enclosing = NULL_TREE;
     }
 
-  hash_table_free (circularity_hash);
+  htab_delete (circularity_hash);
 
   if (new_class_decl)
     return new_class_decl;
@@ -5842,9 +5853,34 @@ do_resolve_class (enclosing, class_type, decl, cl)
       if (check_pkg_class_access (TYPE_NAME (class_type), cl, true))
         return NULL_TREE;
     }
-  
+
   /* 6- Last call for a resolution */
-  return IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+  decl_result = IDENTIFIER_CLASS_VALUE (TYPE_NAME (class_type));
+
+  /* The final lookup might have registered a.b.c into a.b$c If we
+     failed at the first lookup, progressively change the name if
+     applicable and use the matching DECL instead. */
+  if (!decl_result && QUALIFIED_P (TYPE_NAME (class_type)))
+    {
+      char *separator;
+      tree name = TYPE_NAME (class_type);
+      char *namebuffer = alloca (IDENTIFIER_LENGTH (name) + 1);
+
+      strcpy (namebuffer, IDENTIFIER_POINTER (name));
+
+      do {
+
+       /* Reach the last '.', and if applicable, replace it by a `$' and
+          see if this exists as a type. */
+       if ((separator = strrchr (namebuffer, '.')))
+         {
+           *separator = '$';
+           name = get_identifier (namebuffer);
+           decl_result = IDENTIFIER_CLASS_VALUE (name);
+         }
+      } while (!decl_result && separator);
+    }
+  return decl_result;
 }
 
 static tree
@@ -6257,7 +6293,7 @@ java_check_methods (class_decl)
 }
 
 /* Check all the methods of CLASS_DECL. Methods are first completed
-   then checked according to regular method existance rules.  If no
+   then checked according to regular method existence rules.  If no
    constructor for CLASS_DECL were encountered, then build its
    declaration.  */
 
@@ -6607,34 +6643,33 @@ lookup_java_method2 (clas, method_decl, do_interface)
 /* Return the line that matches DECL line number, and try its best to
    position the column number. Used during error reports.  */
 
+static GTY(()) tree cl_v;
 static tree
 lookup_cl (decl)
      tree decl;
 {
-  static tree cl = NULL_TREE;
   char *line, *found;
   
   if (!decl)
     return NULL_TREE;
 
-  if (cl == NULL_TREE)
+  if (cl_v == NULL_TREE)
     {
-      cl = build_expr_wfl (NULL_TREE, NULL, 0, 0);
-      ggc_add_tree_root (&cl, 1);
+      cl_v = build_expr_wfl (NULL_TREE, NULL, 0, 0);
     }
 
-  EXPR_WFL_FILENAME_NODE (cl) = get_identifier (DECL_SOURCE_FILE (decl));
-  EXPR_WFL_SET_LINECOL (cl, DECL_SOURCE_LINE_FIRST (decl), -1);
+  EXPR_WFL_FILENAME_NODE (cl_v) = get_identifier (DECL_SOURCE_FILE (decl));
+  EXPR_WFL_SET_LINECOL (cl_v, DECL_SOURCE_LINE_FIRST (decl), -1);
 
-  line = java_get_line_col (EXPR_WFL_FILENAME (cl), 
-                           EXPR_WFL_LINENO (cl), EXPR_WFL_COLNO (cl));
+  line = java_get_line_col (EXPR_WFL_FILENAME (cl_v), 
+                           EXPR_WFL_LINENO (cl_v), EXPR_WFL_COLNO (cl_v));
 
   found = strstr ((const char *)line, 
                  (const char *)IDENTIFIER_POINTER (DECL_NAME (decl)));
   if (found)
-    EXPR_WFL_SET_LINECOL (cl, EXPR_WFL_LINENO (cl), found - line);
+    EXPR_WFL_SET_LINECOL (cl_v, EXPR_WFL_LINENO (cl_v), found - line);
 
-  return cl;
+  return cl_v;
 }
 
 /* Look for a simple name in the single-type import list */
@@ -6874,7 +6909,7 @@ read_import_dir (wfl)
 }
 
 /* Possibly find a type in the import on demands specified
-   types. Returns 1 if an error occured, 0 otherwise. Run throught the
+   types. Returns 1 if an error occurred, 0 otherwise. Run through the
    entire list, to detected potential double definitions.  */
                 
 static int
@@ -6983,66 +7018,47 @@ static void
 register_package (name)
      tree name;
 {
-  static struct hash_table _pht, *pht = NULL;
+  static htab_t pht;
+  PTR *e;
 
-  if (!pht)
-    {
-      hash_table_init (&_pht, hash_newfunc, 
-                      java_hash_hash_tree_node, java_hash_compare_tree_node);
-      pht = &_pht;
-    }
-  
-  if (!hash_lookup (pht, (const hash_table_key) name, FALSE, NULL))
+  if (pht == NULL)
+    pht = htab_create (50, htab_hash_pointer, htab_eq_pointer, NULL);
+
+  e = htab_find_slot (pht, name, INSERT);
+  if (*e == NULL)
     {
       package_list = chainon (package_list, build_tree_list (name, NULL));
-      hash_lookup (pht, (const hash_table_key) name, TRUE, NULL);
+      *e = name;
     }
 }
 
 static tree
-resolve_package (pkg, next)
-     tree pkg, *next;
+resolve_package (pkg, next, type_name)
+     tree pkg, *next, *type_name;
 {
-  tree current, acc;
-  tree type_name = NULL_TREE;
-  const char *name = IDENTIFIER_POINTER (EXPR_WFL_NODE (pkg));
+  tree current;
+  tree decl = NULL_TREE;
+  *type_name = NULL_TREE;
 
   /* The trick is to determine when the package name stops and were
      the name of something contained in the package starts. Then we
      return a fully qualified name of what we want to get. */
 
-  /* Do a quick search on well known package names */
-  if (!strncmp (name, "java.lang.reflect", 17))
-    {
-      *next = 
-       TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg))));
-      type_name = lookup_package_type (name, 17);
-    }
-  else if (!strncmp (name, "java.lang", 9))
-    {
-      *next = TREE_CHAIN (TREE_CHAIN (EXPR_WFL_QUALIFICATION (pkg)));
-      type_name = lookup_package_type (name, 9);
-    }
-
-  /* If we found something here, return */
-  if (type_name)
-    return type_name; 
-
   *next = EXPR_WFL_QUALIFICATION (pkg);
 
   /* Try to progressively construct a type name */
   if (TREE_CODE (pkg) == EXPR_WITH_FILE_LOCATION)
-    for (acc = NULL_TREE, current = EXPR_WFL_QUALIFICATION (pkg); 
+    for (current = EXPR_WFL_QUALIFICATION (pkg); 
         current; current = TREE_CHAIN (current))
       {
        /* If we don't have what we're expecting, exit now. TYPE_NAME
           will be null and the error caught later. */
        if (TREE_CODE (QUAL_WFL (current)) != EXPR_WITH_FILE_LOCATION)
          break;
-       acc = merge_qualified_name (acc, EXPR_WFL_NODE (QUAL_WFL (current)));
-       if ((type_name = resolve_no_layout (acc, NULL_TREE)))
+       *type_name = 
+         merge_qualified_name (*type_name, EXPR_WFL_NODE (QUAL_WFL (current)));
+       if ((decl = resolve_no_layout (*type_name, NULL_TREE)))
          {
-           type_name = acc;
            /* resolve_package should be used in a loop, hence we
               point at this one to naturally process the next one at
               the next iteration. */
@@ -7050,22 +7066,9 @@ resolve_package (pkg, next)
            break;
          }
       }
-  return type_name;
+  return decl;
 }
 
-static tree
-lookup_package_type (name, from)
-     const char *name;
-     int from;
-{
-  char subname [128];
-  const char *sub = &name[from+1];
-  while (*sub != '.' && *sub)
-    sub++;
-  strncpy (subname, name, sub-name);
-  subname [sub-name] = '\0';
-  return get_identifier (subname);
-}
 
 /* Check accessibility of inner classes according to member access rules. 
    DECL is the inner class, ENCLOSING_DECL is the class from which the
@@ -7374,7 +7377,7 @@ create_artificial_method (class, flags, type, name, args)
   return mdecl;
 }
 
-/* Starts the body if an artifical method.  */
+/* Starts the body if an artificial method.  */
 
 static void
 start_artificial_method_body (mdecl)
@@ -7398,6 +7401,24 @@ end_artificial_method_body (mdecl)
   exit_block ();
 }
 
+/* Dump a tree of some kind.  This is a convenience wrapper for the
+   dump_* functions in tree-dump.c.  */
+static void
+dump_java_tree (phase, t)
+     enum tree_dump_index phase;
+     tree t;
+{
+  FILE *stream;
+  int flags;
+
+  stream = dump_begin (phase, &flags);
+  if (stream)
+    {
+      dump_node (t, flags, stream);
+      dump_end (phase, stream);
+    }
+}
+
 /* Terminate a function and expand its body.  */
 
 static void
@@ -7417,6 +7438,10 @@ source_end_java_method ()
   if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) == empty_stmt_node)
     BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE;
 
+  /* We've generated all the trees for this function, and it has been
+     patched.  Dump it to a file if the user requested it.  */
+  dump_java_tree (TDI_original, fndecl);
+
   /* Generate function's code */
   if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))
       && ! flag_emit_class_files
@@ -7506,20 +7531,12 @@ void java_layout_seen_class_methods ()
     }
 }
 
+static GTY(()) tree stop_reordering;
 void
 java_reorder_fields ()
 {
-  static tree stop_reordering = NULL_TREE;
-  static int initialized_p;
   tree current;
 
-  /* Register STOP_REORDERING with the garbage collector.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&stop_reordering, 1);
-      initialized_p = 1;
-    }
-
   for (current = gclass_list; current; current = TREE_CHAIN (current))
     {
       current_class = TREE_TYPE (TREE_VALUE (current));
@@ -7704,7 +7721,9 @@ java_complete_expand_methods (class_decl)
 
       if (METHOD_NATIVE (decl))
        {
-         tree body = build_jni_stub (decl);
+         tree body;
+         current_function_decl = decl;
+         body = build_jni_stub (decl);
          BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)) = body;
        }
 
@@ -7800,8 +7819,8 @@ maybe_generate_pre_expand_clinit (class_type)
    MODIFY_EXPR with a constant value.  */
 
 static int
-analyze_clinit_body (bbody)
-     tree bbody;
+analyze_clinit_body (this_class, bbody)
+     tree this_class, bbody;
 {
   while (bbody)
     switch (TREE_CODE (bbody))
@@ -7815,7 +7834,7 @@ analyze_clinit_body (bbody)
        break;
        
       case COMPOUND_EXPR:
-       if (analyze_clinit_body (TREE_OPERAND (bbody, 0)))
+       if (analyze_clinit_body (this_class, TREE_OPERAND (bbody, 0)))
          return 1;
        bbody = TREE_OPERAND (bbody, 1);
        break;
@@ -7826,8 +7845,16 @@ analyze_clinit_body (bbody)
        if (TREE_CODE (TREE_OPERAND (bbody, 1)) == NEW_ARRAY_INIT
            && flag_emit_class_files)
          return 1;
-       /* Return 0 if the operand is constant, 1 otherwise.  */
-       return ! TREE_CONSTANT (TREE_OPERAND (bbody, 1));
+
+       /* There are a few cases where we're required to keep
+          <clinit>:
+          - If this is an assignment whose operand is not constant,
+          - If this is an assignment to a non-initialized field,
+          - If this field is not a member of the current class.
+       */
+       return (! TREE_CONSTANT (TREE_OPERAND (bbody, 1))
+               || ! DECL_INITIAL (TREE_OPERAND (bbody, 0))
+               || DECL_CONTEXT (TREE_OPERAND (bbody, 0)) != this_class);
 
       default:
        return 1;
@@ -7846,7 +7873,6 @@ maybe_yank_clinit (mdecl)
 {
   tree type, current;
   tree fbody, bbody;
-  int found = 0;
   
   if (!DECL_CLINIT_P (mdecl))
     return 0;
@@ -7862,7 +7888,7 @@ maybe_yank_clinit (mdecl)
     return 0;
   if (bbody && ! flag_emit_class_files && bbody != empty_stmt_node)
     return 0;
-  
+
   type = DECL_CONTEXT (mdecl);
   current = TYPE_FIELDS (type);
 
@@ -7871,13 +7897,12 @@ maybe_yank_clinit (mdecl)
     {
       tree f_init;
 
-      /* We're not interested in non static field */
+      /* We're not interested in non-static fields.  */
       if (!FIELD_STATIC (current))
        continue;
 
-      /* nor in fields with initializers. */
+      /* Nor in fields without initializers. */
       f_init = DECL_INITIAL (current);
-
       if (f_init == NULL_TREE)
        continue;
 
@@ -7887,20 +7912,15 @@ maybe_yank_clinit (mdecl)
         correctly. */
       if (! JSTRING_TYPE_P (TREE_TYPE (current))
          && ! JNUMERIC_TYPE_P (TREE_TYPE (current)))
-       break;
+       return 0;
 
       if (! FIELD_FINAL (current) || ! TREE_CONSTANT (f_init))
-       break;
+       return 0;
     }
 
   /* Now we analyze the method body and look for something that
      isn't a MODIFY_EXPR */
-  if (bbody == empty_stmt_node)
-    found = 0;
-  else
-    found = analyze_clinit_body (bbody);
-
-  if (current || found)
+  if (bbody != empty_stmt_node && analyze_clinit_body (type, bbody))
     return 0;
 
   /* Get rid of <clinit> in the class' list of methods */
@@ -8004,7 +8024,7 @@ java_complete_expand_method (mdecl)
       
       /* Before we check initialization, attached all class initialization
         variable to the block_body */
-      hash_traverse (&DECL_FUNCTION_INIT_TEST_TABLE (mdecl),
+      htab_traverse (DECL_FUNCTION_INIT_TEST_TABLE (mdecl),
                     attach_init_test_initialization_flags, block_body);
       
       if (! flag_emit_xref && ! METHOD_NATIVE (mdecl))
@@ -8021,9 +8041,11 @@ java_complete_expand_method (mdecl)
                 MDECL. This used with caution helps removing extra
                 initialization of self. */
              if (METHOD_STATIC (mdecl))
-               hash_lookup (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (mdecl),
-                            (hash_table_key) DECL_CONTEXT (mdecl),
-                            TRUE, NULL);
+               {
+                 *(htab_find_slot 
+                   (DECL_FUNCTION_INITIALIZED_CLASS_TABLE (mdecl),
+                    DECL_CONTEXT (mdecl), INSERT)) = DECL_CONTEXT (mdecl);
+               }
            }
        }
       ctxp->explicit_constructor_p = 0;
@@ -8091,7 +8113,7 @@ java_expand_method_bodies (class)
              /* For each class definitely initialized in
                 CALLED_METHOD, fill ASSIGNMENT_COMPOUND with
                 assignment to the class initialization flag. */
-             hash_traverse (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (called_method),
+             htab_traverse (DECL_FUNCTION_INITIALIZED_CLASS_TABLE (called_method),
                             emit_test_initialization,
                             assignment_compound_list);
 
@@ -8499,7 +8521,7 @@ build_access_to_thisn (from, to, lc)
 {
   tree access = NULL_TREE;
 
-  while (from != to)
+  while (from != to && PURE_INNER_CLASS_TYPE_P (from))
     {
       if (!access)
         {
@@ -8519,8 +8541,8 @@ build_access_to_thisn (from, to, lc)
          access = make_qualified_primary (cn, access, lc);
        }
 
-      /* if FROM isn't an inter class, that's fine, we've done
-         enough. What we're looking for can be accessed from there. */
+      /* If FROM isn't an inner class, that's fine, we've done enough.
+         What we're looking for can be accessed from there.  */
       from = DECL_CONTEXT (TYPE_NAME (from));
       if (!from)
        break;
@@ -8579,27 +8601,19 @@ maybe_build_thisn_access_method (type)
    This function can be invoked with TYPE to NULL, available and then
    has to count the parser context.  */
 
+static GTY(()) tree saved_thisn;
+static GTY(()) tree saved_type;
+
 static tree
 build_current_thisn (type)
     tree type;
 {
   static int saved_i = -1;
-  static tree saved_thisn = NULL_TREE;
-  static tree saved_type = NULL_TREE;
   static int saved_type_i = 0;
-  static int initialized_p;
   tree decl;
   char buffer [24];
   int i = 0;
 
-  /* Register SAVED_THISN and SAVED_TYPE with the garbage collector.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&saved_thisn, 1);
-      ggc_add_tree_root (&saved_type, 1);
-      initialized_p = 1;
-    }
-
   if (type)
     {
       if (type == saved_type)
@@ -8656,6 +8670,9 @@ build_thisn_assign ()
         throw new NoClassDefFoundError(e.getMessage());}
     } */
 
+static GTY(()) tree get_message_wfl;
+static GTY(()) tree type_parm_wfl;
+
 static tree
 build_dot_class_method (class)
      tree class;
@@ -8665,14 +8682,10 @@ build_dot_class_method (class)
   tree args, tmp, saved_current_function_decl, mdecl;
   tree stmt, throw_stmt;
 
-  static tree get_message_wfl, type_parm_wfl;
-
   if (!get_message_wfl)
     {
       get_message_wfl = build_wfl_node (get_identifier ("getMessage"));
       type_parm_wfl = build_wfl_node (get_identifier ("type$"));
-      ggc_add_tree_root (&get_message_wfl, 1);
-      ggc_add_tree_root (&type_parm_wfl, 1);
     }
 
   /* Build the arguments */
@@ -8929,6 +8942,7 @@ verify_constructor_super (mdecl)
 
 /* Generate code for all context remembered for code generation.  */
 
+static GTY(()) tree reversed_class_list;
 void
 java_expand_classes ()
 {
@@ -8941,8 +8955,7 @@ java_expand_classes ()
   java_layout_classes ();
   java_parse_abort_on_error ();
 
-  cur_ctxp = ctxp_for_generation;
-  for (; cur_ctxp; cur_ctxp = cur_ctxp->next)
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       ctxp = cur_ctxp;
       input_filename = ctxp->filename;
@@ -8952,9 +8965,11 @@ java_expand_classes ()
     }
   input_filename = main_input_filename;
 
-  /* Find anonymous classes and expand their constructor, now they
-     have been fixed. */
-  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
+
+  /* Find anonymous classes and expand their constructor. This extra pass is
+     neccessary because the constructor itself is only generated when the
+     method in which it is defined is expanded. */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       tree current;
       ctxp = cur_ctxp;
@@ -8971,7 +8986,7 @@ java_expand_classes ()
                      restore_line_number_status (1);
                      java_complete_expand_method (d);
                      restore_line_number_status (0);
-                     break;    /* We now there are no other ones */
+                     break;    /* There is only one constructor. */
                    }
                }
            }
@@ -8987,13 +9002,51 @@ java_expand_classes ()
     return;
 
   /* Now things are stable, go for generation of the class data. */
-  for (cur_ctxp = ctxp_for_generation;  cur_ctxp;  cur_ctxp = cur_ctxp->next)
+
+  /* We pessimistically marked all fields external until we knew
+     what set of classes we were planning to compile.  Now mark
+     those that will be generated locally as not external.  */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
     {
       tree current;
       ctxp = cur_ctxp;
       for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
        {
-         current_class = TREE_TYPE (current);
+         tree class = TREE_TYPE (current);
+         tree field;
+         for (field = TYPE_FIELDS (class); field ; field = TREE_CHAIN (field))
+           if (FIELD_STATIC (field))
+             DECL_EXTERNAL (field) = 0;
+       }
+    }
+
+  /* Compile the classes.  */
+  for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
+    {
+      tree current;
+      reversed_class_list = NULL;
+
+      ctxp = cur_ctxp;
+
+      /* We write out the classes in reverse order.  This ensures that
+        inner classes are written before their containing classes,
+        which is important for parallel builds.  Otherwise, the
+        class file for the outer class may be found, but the class
+        file for the inner class may not be present.  In that
+        situation, the compiler cannot fall back to the original
+        source, having already read the outer class, so we must
+        prevent that situation.  */
+      for (current = ctxp->class_list; 
+          current; 
+          current = TREE_CHAIN (current))
+       reversed_class_list
+         = tree_cons (NULL_TREE, current, reversed_class_list);
+
+      for (current = reversed_class_list; 
+          current; 
+          current = TREE_CHAIN (current))
+       {
+         current_class = TREE_TYPE (TREE_VALUE (current));
          outgoing_cpool = TYPE_CPOOL (current_class);
          if (flag_emit_class_files)
            write_classfile (current_class);
@@ -9239,7 +9292,7 @@ static_ref_err (wfl, field_id, class_type)
      IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class_type))));
 }
 
-/* 15.10.1 Field Acess Using a Primary and/or Expression Name.
+/* 15.10.1 Field Access Using a Primary and/or Expression Name.
    We return something suitable to generate the field access. We also
    return the field decl in FIELD_DECL and its type in FIELD_TYPE.  If
    recipient's address can be null. */
@@ -9405,6 +9458,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
          *where_found = patch_method_invocation (qual_wfl, decl, type,
                                                  from_super,
                                                  &is_static, &ret_decl);
+         from_super = 0;
          if (*where_found == error_mark_node)
            {
              RESTORE_THIS_AND_CURRENT_CLASS;
@@ -9536,7 +9590,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              parse_error_context (wfl, "Can't reference `this' before the superclass constructor has been called");
              return 1;
            }
-         /* We have to generate code for intermediate acess */
+         /* We have to generate code for intermediate access */
          if (!from_type || TREE_TYPE (TREE_TYPE (current_this)) == type)
            {
              *where_found = decl = current_this;
@@ -9601,11 +9655,12 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
         assume a variable/class name was meant. */
       if (RESOLVE_PACKAGE_NAME_P (qual_wfl))
        {
-         tree name = resolve_package (wfl, &q);
-         if (name)
+         tree name;
+         if ((decl = resolve_package (wfl, &q, &name)))
            {
              tree list;
-             *where_found = decl = resolve_no_layout (name, qual_wfl);
+             *where_found = decl;
+
              /* We want to be absolutely sure that the class is laid
                  out. We're going to search something inside it. */
              *type_found = type = TREE_TYPE (decl);
@@ -9635,7 +9690,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
              else
                parse_error_context
                  (qual_wfl, "Undefined variable or class name: `%s'",
-                  IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)));
+                  IDENTIFIER_POINTER (name));
              return 1;
            }
        }
@@ -9735,7 +9790,7 @@ resolve_qualified_expression_name (wfl, found_decl, where_found, type_found)
                    (qual_wfl, "Attempt to reference field `%s' in `%s %s'",
                     IDENTIFIER_POINTER (EXPR_WFL_NODE (qual_wfl)),
                     lang_printable_name (type, 0),
-                    IDENTIFIER_POINTER (DECL_NAME (field_decl)));
+                    IDENTIFIER_POINTER (DECL_NAME (decl)));
                  return 1;
                }
              
@@ -9914,7 +9969,7 @@ not_accessible_p (reference, member, where, from_super)
       if (where && !inherits_from_p (reference, where))
        return 1;
 
-      /* Otherwise, access is granted if occuring from the class where
+      /* Otherwise, access is granted if occurring from the class where
         member is declared or a subclass of it. Find the right
         context to perform the check */
       if (PURE_INNER_CLASS_TYPE_P (reference))
@@ -9943,7 +9998,7 @@ not_accessible_p (reference, member, where, from_super)
       return 1;
     }
 
-  /* Default access are permitted only when occuring within the
+  /* Default access are permitted only when occurring within the
      package in which the type (REFERENCE) is declared. In other words,
      REFERENCE is defined in the current package */
   if (ctxp->package)
@@ -9994,15 +10049,15 @@ check_deprecation (wfl, decl)
 
 /* Returns 1 if class was declared in the current package, 0 otherwise */
 
+static GTY(()) tree cicp_cache;
 static int
 class_in_current_package (class)
      tree class;
 {
-  static tree cache = NULL_TREE;
   int qualified_flag;
   tree left;
 
-  if (cache == class)
+  if (cicp_cache == class)
     return 1;
 
   qualified_flag = QUALIFIED_P (DECL_NAME (TYPE_NAME (class)));
@@ -10023,15 +10078,7 @@ class_in_current_package (class)
   breakdown_qualified (&left, NULL, DECL_NAME (TYPE_NAME (class)));
   if (ctxp->package == left)
     {
-      static int initialized_p;
-      /* Register CACHE with the garbage collector.  */
-      if (!initialized_p)
-       {
-         ggc_add_tree_root (&cache, 1);
-         initialized_p = 1;
-       }
-
-      cache = class;
+      cicp_cache = class;
       return 1;
     }
   return 0;
@@ -10407,27 +10454,15 @@ patch_method_invocation (patch, primary, where, from_super,
 
   /* This handles the situation where a constructor invocation needs
      to have an enclosing context passed as a second parameter (the
-     constructor is one of an inner class. We extract it from the
-     current function.  */
+     constructor is one of an inner class). */
   if ((is_super_init || 
        (TREE_CODE (patch) == CALL_EXPR && name == this_identifier_node))
       && PURE_INNER_CLASS_TYPE_P (DECL_CONTEXT (list)))
     {
-      tree enclosing_decl = DECL_CONTEXT (TYPE_NAME (current_class));
-      tree extra_arg;
-
-      if (ANONYMOUS_CLASS_P (current_class) || !DECL_CONTEXT (enclosing_decl))
-       {
-         extra_arg = DECL_FUNCTION_BODY (current_function_decl);
-         extra_arg = TREE_CHAIN (BLOCK_EXPR_DECLS (extra_arg));
-       }
-      else
-       {
-         tree dest = TREE_TYPE (DECL_CONTEXT (enclosing_decl));
-         extra_arg = 
-           build_access_to_thisn (TREE_TYPE (enclosing_decl), dest, 0);
-         extra_arg = java_complete_tree (extra_arg);
-       }
+      tree dest = TYPE_NAME (DECL_CONTEXT (list));
+      tree extra_arg = 
+       build_access_to_thisn (current_class, DECL_CONTEXT (dest), 0);
+      extra_arg = java_complete_tree (extra_arg);
       args = tree_cons (NULL_TREE, extra_arg, args);
     }
 
@@ -10472,9 +10507,9 @@ patch_method_invocation (patch, primary, where, from_super,
       /* Generate the code used to initialize fields declared with an
         initialization statement and build a compound statement along
         with the super constructor invocation. */
+      CAN_COMPLETE_NORMALLY (patch) = 1;
       patch = build (COMPOUND_EXPR, void_type_node, patch,
                     java_complete_tree (finit_call));
-      CAN_COMPLETE_NORMALLY (patch) = 1;
     }
   return patch;
 }
@@ -10605,7 +10640,6 @@ patch_invoke (patch, method, args)
     func = method;
   else
     {
-      tree signature = build_java_signature (TREE_TYPE (method));
       switch (invocation_mode (method, CALL_USING_SUPER (patch)))
        {
        case INVOKE_VIRTUAL:
@@ -10630,9 +10664,12 @@ patch_invoke (patch, method, args)
 
        case INVOKE_SUPER:
        case INVOKE_STATIC:
-         func = build_known_method_ref (method, TREE_TYPE (method),
-                                        DECL_CONTEXT (method),
-                                        signature, args);
+         {
+           tree signature = build_java_signature (TREE_TYPE (method));
+           func = build_known_method_ref (method, TREE_TYPE (method),
+                                          DECL_CONTEXT (method),
+                                          signature, args);
+         }
          break;
 
        case INVOKE_INTERFACE:
@@ -10651,6 +10688,7 @@ patch_invoke (patch, method, args)
   TREE_TYPE (patch) = TREE_TYPE (TREE_TYPE (method));
   TREE_OPERAND (patch, 0) = func;
   TREE_OPERAND (patch, 1) = args;
+  patch = check_for_builtin (method, patch);
   original_call = patch;
 
   /* We're processing a `new TYPE ()' form. New is called and its
@@ -10662,6 +10700,8 @@ patch_invoke (patch, method, args)
     {
       tree class = DECL_CONTEXT (method);
       tree c1, saved_new, size, new;
+      tree alloc_node;
+
       if (flag_emit_class_files || flag_emit_xref)
        {
          TREE_TYPE (patch) = build_pointer_type (class);
@@ -10670,8 +10710,11 @@ patch_invoke (patch, method, args)
       if (!TYPE_SIZE (class))
        safe_layout_class (class);
       size = size_in_bytes (class);
+      alloc_node =
+       (class_has_finalize_method (class) ? alloc_object_node
+                                          : alloc_no_finalizer_node);
       new = build (CALL_EXPR, promote_type (class),
-                  build_address_of (alloc_object_node),
+                  build_address_of (alloc_node),
                   tree_cons (NULL_TREE, build_class_ref (class),
                              build_tree_list (NULL_TREE, 
                                               size_in_bytes (class))),
@@ -10781,7 +10824,14 @@ lookup_method_invoke (lc, cl, class, name, arg_list)
      know the arguments' types. */
 
   if (lc && ANONYMOUS_CLASS_P (class))
-    craft_constructor (TYPE_NAME (class), atl);
+    {
+      tree saved_current_class;
+      tree mdecl = craft_constructor (TYPE_NAME (class), atl);
+      saved_current_class = current_class;
+      current_class = class;
+      fix_constructors (mdecl);
+      current_class = saved_current_class;
+    }
 
   /* Find all candidates and then refine the list, searching for the
      most specific method. */
@@ -10836,7 +10886,7 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
      int lc;
      tree class, name, arglist;
 {
-  static struct hash_table t, *searched_classes = NULL;
+  static htab_t searched_classes;
   static int search_not_done = 0;
   tree list = NULL_TREE, all_list = NULL_TREE;
 
@@ -10844,20 +10894,17 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
      already. */
   if (searched_classes)
     {
-      if (hash_lookup (searched_classes, 
-                      (const hash_table_key) class, FALSE, NULL))
-       return NULL;
+      if (htab_find (searched_classes, class) != NULL)
+       return NULL;
     }
   else
     {
-      hash_table_init (&t, hash_newfunc, java_hash_hash_tree_node,
-                      java_hash_compare_tree_node);
-      searched_classes = &t;
+      searched_classes = htab_create (10, htab_hash_pointer,
+                                     htab_eq_pointer, NULL);
     }
     
   search_not_done++;
-  hash_lookup (searched_classes, 
-              (const hash_table_key) class, TRUE, NULL);
+  *htab_find_slot (searched_classes, class, INSERT) = class;
 
   if (!CLASS_LOADED_P (class) && !CLASS_FROM_SOURCE_P (class))
     {
@@ -10937,15 +10984,13 @@ find_applicable_accessible_methods_list (lc, class, name, arglist)
     {
       if (!lc
          && TYPE_METHODS (object_type_node)
-         && !hash_lookup (searched_classes, 
-                           (const hash_table_key) object_type_node, 
-                           FALSE, NULL))
+         && htab_find (searched_classes, object_type_node) == NULL)
        {
           search_applicable_methods_list (lc, 
                                           TYPE_METHODS (object_type_node),
                                           name, arglist, &list, &all_list);
         }
-      hash_table_free (searched_classes);
+      htab_delete (searched_classes);
       searched_classes = NULL;
     }
 
@@ -11075,25 +11120,15 @@ find_most_specific_methods_list (list)
    corresponding parameter of M1. Implementation expects M2_OR_ARGLIST
    to change less often than M1. */
 
+static GTY(()) tree m2_arg_value;
+static GTY(()) tree m2_arg_cache;
+
 static int
 argument_types_convertible (m1, m2_or_arglist)
     tree m1, m2_or_arglist;
 {
-  static tree m2_arg_value = NULL_TREE;
-  static tree m2_arg_cache = NULL_TREE;
-  static int initialized_p;
-
   register tree m1_arg, m2_arg;
 
-  /* Register M2_ARG_VALUE and M2_ARG_CACHE with the garbage
-     collector.  */
-  if (!initialized_p)
-    {
-      ggc_add_tree_root (&m2_arg_value, 1);
-      ggc_add_tree_root (&m2_arg_cache, 1);
-      initialized_p = 1;
-    }
-
   SKIP_THIS_AND_ARTIFICIAL_PARMS (m1_arg, m1)
 
   if (m2_arg_value == m2_or_arglist)
@@ -11158,7 +11193,9 @@ qualify_ambiguous_name (id)
       {
       case CALL_EXPR:
        qual_wfl = TREE_OPERAND (qual_wfl, 0);
-       if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION)
+       if (TREE_CODE (qual_wfl) != EXPR_WITH_FILE_LOCATION
+           || (EXPR_WFL_QUALIFICATION (qual_wfl)
+               && TREE_CODE (EXPR_WFL_QUALIFICATION (qual_wfl)) == TREE_LIST))
          {
            qual = EXPR_WFL_QUALIFICATION (qual_wfl);
            qual_wfl = QUAL_WFL (qual);
@@ -11202,11 +11239,17 @@ qualify_ambiguous_name (id)
 
     else if (code == INTEGER_CST)
       name = qual_wfl;
-    
+
     else if (code == CONVERT_EXPR &&
             TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
       name = TREE_OPERAND (qual_wfl, 0);
-    
+
+    else if (code == CONVERT_EXPR
+            && TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == CALL_EXPR
+            && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0))
+                == EXPR_WITH_FILE_LOCATION))
+      name = TREE_OPERAND (TREE_OPERAND (qual_wfl, 0), 0);
+
     else if ((code == ARRAY_REF || code == CALL_EXPR || code == MODIFY_EXPR) &&
             TREE_CODE (TREE_OPERAND (qual_wfl, 0)) == EXPR_WITH_FILE_LOCATION)
       name = EXPR_WFL_NODE (TREE_OPERAND (qual_wfl, 0));
@@ -11771,14 +11814,28 @@ java_complete_lhs (node)
              if (TREE_CODE (nn) != EXIT_EXPR)
                {
                  SET_WFL_OPERATOR (wfl_operator, node, wfl_op2);
-                 parse_error_context (wfl_operator, "Unreachable statement");
+                 if (SUPPRESS_UNREACHABLE_ERROR (nn))
+                   {
+                     /* Perhaps this warning should have an
+                        associated flag.  The code being compiled is
+                        pedantically correct, but useless.  */
+                     parse_warning_context (wfl_operator,
+                                            "Unreachable statement");
+                   }
+                 else
+                   parse_error_context (wfl_operator,
+                                        "Unreachable statement");
                }
            }
          TREE_OPERAND (node, 1) = java_complete_tree (TREE_OPERAND (node, 1));
          if (TREE_OPERAND (node, 1) == error_mark_node)
            return error_mark_node;
+         /* Even though we might allow the case where the first
+            operand doesn't return normally, we still should compute
+            CAN_COMPLETE_NORMALLY correctly.  */
          CAN_COMPLETE_NORMALLY (node)
-           = CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1));
+           = (CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0))
+              && CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 1)));
        }
       TREE_TYPE (node) = TREE_TYPE (TREE_OPERAND (node, 1));
       break;
@@ -12026,6 +12083,8 @@ java_complete_lhs (node)
       else
        {
          node = patch_assignment (node, wfl_op1);
+         if (node == error_mark_node)
+           return error_mark_node;
          /* Reorganize the tree if necessary. */
          if (flag && (!JREFERENCE_TYPE_P (TREE_TYPE (node)) 
                       || JSTRING_P (TREE_TYPE (node))))
@@ -12269,7 +12328,7 @@ build_expr_block (body, decls)
   return node;
 }
 
-/* Create a new function block and link it approriately to current
+/* Create a new function block and link it appropriately to current
    function block chain */
 
 static tree
@@ -12479,8 +12538,82 @@ build_assignment (op, op_location, lhs, rhs)
   return assignment;
 }
 
-/* Print an INTEGER_CST node in a static buffer, and return the buffer. */
+/* Print an INTEGER_CST node as decimal in a static buffer, and return
+   the buffer.  This is used only for string conversion.  */
+static char *
+string_convert_int_cst (node)
+     tree node;
+{
+  static char buffer[80];
+
+  unsigned HOST_WIDE_INT lo = TREE_INT_CST_LOW (node);
+  unsigned HOST_WIDE_INT hi = TREE_INT_CST_HIGH (node);
+  char *p = buffer + sizeof (buffer) - 1;
+  int neg = 0;
+
+  unsigned HOST_WIDE_INT hibit = (((unsigned HOST_WIDE_INT) 1)
+                                 << (HOST_BITS_PER_WIDE_INT - 1));
+
+  *p-- = '\0';
+
+  /* If negative, note the fact and negate the value.  */
+  if ((hi & hibit))
+    {
+      lo = ~lo;
+      hi = ~hi;
+      if (++lo == 0)
+       ++hi;
+      neg = 1;
+    }
+
+  /* Divide by 10 until there are no bits left.  */
+  while (hi || lo)
+    {
+      unsigned HOST_WIDE_INT acc = 0;
+      unsigned HOST_WIDE_INT outhi = 0, outlo = 0;
+      unsigned int i;
+
+      /* Use long division to compute the result and the remainder.  */
+      for (i = 0; i < 2 * HOST_BITS_PER_WIDE_INT; ++i)
+       {
+         /* Shift a bit into accumulator.  */
+         acc <<= 1;
+         if ((hi & hibit))
+           acc |= 1;
+
+         /* Shift the value.  */
+         hi <<= 1;
+         if ((lo & hibit))
+           hi |= 1;
+         lo <<= 1;
+
+         /* Shift the correct bit into the result.  */
+         outhi <<= 1;
+         if ((outlo & hibit))
+           outhi |= 1;
+         outlo <<= 1;
+         if (acc >= 10)
+           {
+             acc -= 10;
+             outlo |= 1;
+           }
+       }
+
+      /* FIXME: ASCII assumption.  */
+      *p-- = '0' + acc;
+
+      hi = outhi;
+      lo = outlo;
+    }
+
+  if (neg)
+    *p-- = '-';
 
+  return p + 1;
+}
+
+/* Print an INTEGER_CST node in a static buffer, and return the
+   buffer.  This is used only for error handling.  */
 char *
 print_int_node (node)
     tree node;
@@ -12522,6 +12655,7 @@ patch_assignment (node, wfl_op1)
   tree lhs_type = NULL_TREE, rhs_type, new_rhs = NULL_TREE;
   int error_found = 0;
   int lvalue_from_array = 0;
+  int is_return = 0;
 
   EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (node);
 
@@ -12530,9 +12664,8 @@ patch_assignment (node, wfl_op1)
     {
       lhs_type = TREE_TYPE (lvalue);
     }
-  /* Or Lhs can be a array acccess. Should that be lvalue ? FIXME +
-     comment on reason why */
-  else if (TREE_CODE (wfl_op1) == ARRAY_REF)
+  /* Or Lhs can be an array access. */
+  else if (TREE_CODE (lvalue) == ARRAY_REF)
     {
       lhs_type = TREE_TYPE (lvalue);
       lvalue_from_array = 1;
@@ -12542,7 +12675,15 @@ patch_assignment (node, wfl_op1)
     lhs_type = TREE_TYPE (lvalue);
   /* Or a function return slot */
   else if (TREE_CODE (lvalue) == RESULT_DECL)
-    lhs_type = TREE_TYPE (lvalue);
+    {
+      /* If the return type is an integral type, then we create the
+        RESULT_DECL with a promoted type, but we need to do these
+        checks against the unpromoted type to ensure type safety.  So
+        here we look at the real type, not the type of the decl we
+        are modifying.  */
+      lhs_type = TREE_TYPE (TREE_TYPE (current_function_decl));
+      is_return = 1;
+    }
   /* Otherwise, we might want to try to write into an optimized static
      final, this is an of a different nature, reported further on. */
   else if (TREE_CODE (wfl_op1) == EXPR_WITH_FILE_LOCATION
@@ -12557,6 +12698,7 @@ patch_assignment (node, wfl_op1)
     }
 
   rhs_type = TREE_TYPE (rhs);
+
   /* 5.1 Try the assignment conversion for builtin type. */
   new_rhs = try_builtin_assignconv (wfl_op1, lhs_type, rhs);
 
@@ -12594,7 +12736,7 @@ patch_assignment (node, wfl_op1)
          wfl = wfl_operator;
          if (COMPOUND_ASSIGN_P (TREE_OPERAND (node, 1)))
            strcpy (operation, "assignment");
-         else if (TREE_CODE (TREE_OPERAND (node, 0)) == RESULT_DECL)
+         else if (is_return)
            strcpy (operation, "`return'");
          else
            strcpy (operation, "`='");
@@ -12614,86 +12756,43 @@ patch_assignment (node, wfl_op1)
   if (error_found)
     return error_mark_node;
 
+  /* If we're processing a `return' statement, promote the actual type
+     to the promoted type.  */
+  if (is_return)
+    new_rhs = convert (TREE_TYPE (lvalue), new_rhs);
+
   /* 10.10: Array Store Exception runtime check */
   if (!flag_emit_class_files
       && !flag_emit_xref
       && lvalue_from_array 
       && JREFERENCE_TYPE_P (TYPE_ARRAY_ELEMENT (lhs_type)))
     {
-      tree check;
-      tree base = lvalue;
+      tree array, store_check, base, index_expr;
+      
+      /* Save RHS so that it doesn't get re-evaluated by the store check. */ 
+      new_rhs = save_expr (new_rhs);
 
-      /* 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
+      /* Get the INDIRECT_REF. */
+      array = TREE_OPERAND (TREE_OPERAND (lvalue, 0), 0);
+      /* Get the array pointer expr. */
+      array = TREE_OPERAND (array, 0);
+      store_check = build_java_arraystore_check (array, new_rhs);
+      
+      index_expr = TREE_OPERAND (lvalue, 1);
+      
+      if (TREE_CODE (index_expr) == COMPOUND_EXPR)
        {
-          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);
-         /* We can have a COMPOUND_EXPR here when doing bounds check. */
-         if (TREE_CODE (op) == COMPOUND_EXPR)
-           op = TREE_OPERAND (op, 1);
-         base = TREE_OPERAND (op, 0);
-         /* Strip the last PLUS_EXPR to obtain the base. */
-         if (TREE_CODE (base) == PLUS_EXPR)
-           base = TREE_OPERAND (base, 0);
-       }
-
-      /* Build the invocation of _Jv_CheckArrayStore */
-      new_rhs = save_expr (new_rhs);
-      check = build (CALL_EXPR, void_type_node,
-                    build_address_of (soft_checkarraystore_node),
-                    tree_cons (NULL_TREE, base,
-                               build_tree_list (NULL_TREE, new_rhs)),
-                    NULL_TREE);
-      TREE_SIDE_EFFECTS (check) = 1;
-
-      /* We have to decide on an insertion point */
-      if (TREE_CODE (lvalue) == COMPOUND_EXPR)
-       {
-         tree t;
-         if (flag_bounds_check)
-           {
-             t = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0);
-             TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (lvalue, 1), 0), 0) =
-               build (COMPOUND_EXPR, void_type_node, t, check);
-           }
-         else
-           TREE_OPERAND (lvalue, 1) = build (COMPOUND_EXPR, lhs_type,
-                                             check, TREE_OPERAND (lvalue, 1));
+         /* A COMPOUND_EXPR here is a bounds check. The bounds check must 
+            happen before the store check, so prepare to insert the store
+            check within the second operand of the existing COMPOUND_EXPR. */
+         base = index_expr;
        }
-      else 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 */
-          new_compound =
-            build (COMPOUND_EXPR, void_type_node, bound_check, check);
-
-          /* Re-assemble the augmented array access. */
-          lvalue = build (COMPOUND_EXPR, TREE_TYPE (lvalue),
-                         new_compound, lvalue);
-        }
       else
-        lvalue = build (COMPOUND_EXPR, TREE_TYPE (lvalue), check, lvalue);
+        base = lvalue;
+      
+      index_expr = TREE_OPERAND (base, 1);
+      TREE_OPERAND (base, 1) = build (COMPOUND_EXPR, TREE_TYPE (index_expr), 
+                                     store_check, index_expr);
     }
 
   /* Final locals can be used as case values in switch
@@ -12762,12 +12861,6 @@ try_builtin_assignconv (wfl_op1, lhs_type, rhs)
        new_rhs = rhs;
     }
 
-  /* Zero accepted everywhere */
-  else if (TREE_CODE (rhs) == INTEGER_CST 
-      && TREE_INT_CST_HIGH (rhs) == 0 && TREE_INT_CST_LOW (rhs) == 0
-      && JPRIMITIVE_TYPE_P (rhs_type))
-    new_rhs = convert (lhs_type, rhs);
-
   /* 5.1.1 Try Identity Conversion,
      5.1.2 Try Widening Primitive Conversion */
   else if (valid_builtin_assignconv_identity_widening_p (lhs_type, rhs_type))
@@ -13337,7 +13430,7 @@ patch_binop (node, wfl_op1, wfl_op2)
        }
 
       /* Unary numeric promotion (5.6.1) is performed on each operand
-         separatly */
+         separately */
       op1 = do_unary_numeric_promotion (op1);
       op2 = do_unary_numeric_promotion (op2);
 
@@ -13357,7 +13450,7 @@ patch_binop (node, wfl_op1, wfl_op2)
       if (code == URSHIFT_EXPR && ! flag_emit_class_files)
        {
          tree to_return;
-          tree utype = unsigned_type (prom_type);
+          tree utype = java_unsigned_type (prom_type);
           op1 = convert (utype, op1);
          TREE_SET_CODE (node, RSHIFT_EXPR);
           TREE_OPERAND (node, 0) = op1;
@@ -13377,6 +13470,15 @@ patch_binop (node, wfl_op1, wfl_op2)
 
       TREE_TYPE (node) = boolean_type_node;
 
+      /* OP1_TYPE might be NULL when OP1 is a string constant.  */
+      if ((cn = patch_string (op1))) 
+       {
+         op1 = cn;
+         op1_type = TREE_TYPE (op1);
+       }
+      if (op1_type == NULL_TREE)
+       abort ();
+
       if (!(op2_type = resolve_type_during_patch (op2)))
        return error_mark_node;
 
@@ -13643,8 +13745,8 @@ merge_string_cste (op1, op2, after)
          string = ch;
        }
       else
-         string = print_int_node (op2);
-      
+       string = string_convert_int_cst (op2);
+
       return do_merge_string_cste (op1, string, strlen (string), after);
     }
   return NULL_TREE;
@@ -13723,8 +13825,8 @@ build_string_concatenation (op1, op2)
     op2 = patch_string_cst (op2);
 
   /* If either one of the constant is null and the other non null
-     operand is a String object, return it. */
-  if (JSTRING_TYPE_P (TREE_TYPE (op1)) && !op2)
+     operand is a String constant, return it. */
+  if ((TREE_CODE (op1) == STRING_CST) && !op2)
     return op1;
 
   /* If OP1 isn't already a StringBuffer, create and
@@ -14642,18 +14744,6 @@ patch_return (node)
       tree exp = java_complete_tree (return_exp);
       tree modify, patched;
 
-      /* If the function returned value and EXP are booleans, EXP has
-      to be converted into the type of DECL_RESULT, which is integer
-      (see complete_start_java_method) */
-      if (TREE_TYPE (exp) == boolean_type_node &&
-         TREE_TYPE (TREE_TYPE (meth)) == boolean_type_node)
-       exp = convert_to_integer (TREE_TYPE (DECL_RESULT (meth)), exp);
-
-      /* `null' can be assigned to a function returning a reference */
-      if (JREFERENCE_TYPE_P (TREE_TYPE (TREE_TYPE (meth))) &&
-         exp == null_pointer_node)
-       exp = build_null_of_type (TREE_TYPE (TREE_TYPE (meth)));
-
       if ((patched = patch_string (exp)))
        exp = patched;
       
@@ -14808,7 +14898,7 @@ build_new_loop (loop_body)
        COMPOUND_EXPR           (loop main body)
          EXIT_EXPR             (this order is for while/for loops.
          LABELED_BLOCK_EXPR      the order is reversed for do loops)
-           LABEL_DECL           (a continue occuring here branches at the 
+           LABEL_DECL           (a continue occurring here branches at the 
            BODY                         end of this labeled block)
        INCREMENT               (if any)
 
@@ -14882,7 +14972,22 @@ finish_for_loop (location, condition, update, body)
   /* Put the condition and the loop body in place */
   tree loop = finish_loop_body (location, condition, body, 0);
   /* LOOP is the current loop which has been now popped of the loop
-     stack. Install the update block */
+     stack.  Mark the update block as reachable and install it.  We do
+     this because the (current interpretation of the) JLS requires
+     that the update expression be considered reachable even if the
+     for loop's body doesn't complete normally.  */
+  if (update != NULL_TREE && update != empty_stmt_node)
+    {
+      tree up2 = update;
+      if (TREE_CODE (up2) == EXPR_WITH_FILE_LOCATION)
+       up2 = EXPR_WFL_NODE (up2);
+      /* Try to detect constraint violations.  These would be
+        programming errors somewhere.  */
+      if (! IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (up2)))
+         || TREE_CODE (up2) == LOOP_EXPR)
+       abort ();
+      SUPPRESS_UNREACHABLE_ERROR (up2) = 1;
+    }
   LOOP_EXPR_BODY_UPDATE_BLOCK (LOOP_EXPR_BODY (loop)) = update;
   return loop;
 }
@@ -15151,8 +15256,8 @@ patch_switch_statement (node)
                = EXPR_WFL_LINECOL (TREE_PURPOSE (iter));
              /* The case_label_list is in reverse order, so print the
                 outer label first.  */
-             parse_error_context (wfl_operator, "duplicate case label: `%d'",
-                                  subval);
+             parse_error_context (wfl_operator, "duplicate case label: `"
+                                  HOST_WIDE_INT_PRINT_DEC "'", subval);
              EXPR_WFL_LINECOL (wfl_operator)
                = EXPR_WFL_LINECOL (TREE_PURPOSE (subiter));
              parse_error_context (wfl_operator, "original label is here");
@@ -15444,7 +15549,7 @@ patch_throw_statement (node, wfl_op1)
 
   SET_WFL_OPERATOR (wfl_operator, node, wfl_op1);
   /* An instance can't throw a checked exception unless that exception
-     is explicitely declared in the `throws' clause of each
+     is explicitly declared in the `throws' clause of each
      constructor. This doesn't apply to anonymous classes, since they
      don't have declared constructors. */
   if (!unchecked_ok 
@@ -15967,8 +16072,9 @@ mark_parser_ctxt (p)
 void
 init_src_parse ()
 {
-  /* Register roots with the garbage collector.  */
-  ggc_add_tree_root (src_parse_roots, sizeof (src_parse_roots) / sizeof(tree));
+  /* Sanity check; we've been bit by this before.  */
+  if (ARRAY_SIZE (ctxp->modifier_ctx) != MODIFIER_TK - PUBLIC_TK)
+    abort ();
 }
 
 \f
@@ -15978,16 +16084,16 @@ init_src_parse ()
 
 /* Attach to PTR (a block) the declaration found in ENTRY. */
 
-static bool
+static int
 attach_init_test_initialization_flags (entry, ptr)
-     struct hash_entry *entry;
+     PTR *entry;
      PTR ptr;
 {
   tree block = (tree)ptr;
-  struct init_test_hash_entry *ite = (struct init_test_hash_entry *) entry;
+  struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
   
-  TREE_CHAIN (ite->init_test_decl) = BLOCK_EXPR_DECLS (block);
-  BLOCK_EXPR_DECLS (block) = ite->init_test_decl;
+  TREE_CHAIN (ite->value) = BLOCK_EXPR_DECLS (block);
+  BLOCK_EXPR_DECLS (block) = ite->value;
   return true;
 }
 
@@ -15997,28 +16103,29 @@ attach_init_test_initialization_flags (entry, ptr)
    initialized static class flags if a flag already existed, otherwise
    a new one is created.  */
 
-static bool
-emit_test_initialization (entry, info)
-     struct hash_entry *entry;
+static int
+emit_test_initialization (entry_p, info)
+     PTR *entry_p;
      PTR info;
 {
   tree l = (tree) info;
   tree decl, init;
-
-  struct init_test_hash_entry *ite = (struct init_test_hash_entry *)
-    hash_lookup (&DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl),
-                entry->key,
-                current_function_decl != TREE_PURPOSE (l), NULL);
+  tree key = (tree) *entry_p;
+  tree *ite;
+  htab_t cf_ht = DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl);
 
   /* If we haven't found a flag and we're dealing with self registered
      with current_function_decl, then don't do anything. Self is
      always added as definitely initialized but this information is
      valid only if used outside the current function. */
-  if (! ite)
+  if (current_function_decl == TREE_PURPOSE (l)
+      && java_treetreehash_find (cf_ht, key) == NULL)
     return true;
+    
+  ite = java_treetreehash_new (cf_ht, key);
 
   /* If we don't have a variable, create one and install it. */
-  if (! ite->init_test_decl)
+  if (*ite == NULL)
     {
       tree block;
       
@@ -16032,10 +16139,10 @@ emit_test_initialization (entry, info)
       block = BLOCK_SUBBLOCKS (GET_CURRENT_BLOCK (current_function_decl));
       TREE_CHAIN (decl) = BLOCK_EXPR_DECLS (block);
       BLOCK_EXPR_DECLS (block) = decl;
-      ite->init_test_decl = decl;
+      *ite = decl;
     }
   else
-    decl = ite->init_test_decl;
+    decl = *ite;
 
   /* Now simply augment the compound that holds all the assignments
      pertaining to this method invocation. */
@@ -16046,3 +16153,6 @@ emit_test_initialization (entry, info)
 
   return true;
 }
+
+#include "gt-java-parse.h"
+#include "gtype-java.h"