OSDN Git Service

2007-02-07 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / java / class.c
index 972877d..804c239 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions related to building classes and their related objects.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -46,6 +46,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "cgraph.h"
 #include "tree-iterator.h"
 #include "cgraph.h"
+#include "vecprim.h"
 
 /* DOS brain-damage */
 #ifndef O_BINARY
@@ -68,6 +69,8 @@ static void register_class (void);
 
 struct obstack temporary_obstack;
 
+static const char *cyclic_inheritance_report;
+
 /* The compiler generates different code depending on whether or not
    it can assume certain classes have been compiled down to native
    code or not.  The compiler options -fassume-compiled= and
@@ -107,6 +110,10 @@ static GTY(()) tree class_roots[4];
 
 static GTY(()) VEC(tree,gc) *registered_class;
 
+/* A tree that returns the address of the class$ of the class
+   currently being compiled.  */
+static GTY(()) tree this_classdollar;
+
 /* Return the node that most closely represents the class whose name
    is IDENT.  Start the search from NODE (followed by its siblings).
    Return NULL if an appropriate node does not exist.  */
@@ -206,7 +213,7 @@ add_assume_compiled (const char *ident, int excludep)
 
 /* The default value returned by enable_assertions. */
 
-#define DEFAULT_ENABLE_ASSERT (flag_emit_class_files || optimize == 0)
+#define DEFAULT_ENABLE_ASSERT (optimize == 0)
 
 /* Enter IDENT (a class or package name) into the enable-assertions table.
    VALUE is true to enable and false to disable. */
@@ -497,6 +504,9 @@ set_class_decl_access_flags (int access_flags, tree class_decl)
   if (access_flags & ACC_PRIVATE)   CLASS_PRIVATE (class_decl) = 1;
   if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1;
   if (access_flags & ACC_STRICT)    CLASS_STRICTFP (class_decl) = 1;
+  if (access_flags & ACC_ENUM)      CLASS_ENUM (class_decl) = 1;
+  if (access_flags & ACC_SYNTHETIC) CLASS_SYNTHETIC (class_decl) = 1;
+  if (access_flags & ACC_ANNOTATION) CLASS_ANNOTATION (class_decl) = 1;
 }
 
 /* Return length of inheritance chain of CLAS, where java.lang.Object is 0,
@@ -663,19 +673,6 @@ add_interface (tree this_class, tree interface_class)
   BINFO_BASE_APPEND (TYPE_BINFO (this_class), interface_binfo);
 }
 
-#if 0
-/* Return the address of a pointer to the first FUNCTION_DECL
-   in the list (*LIST) whose DECL_NAME is NAME. */
-
-static tree *
-find_named_method (tree *list, tree name)
-{
-  while (*list && DECL_NAME (*list) != name)
-    list = &TREE_CHAIN (*list);
-  return list;
-}
-#endif
-
 static tree
 build_java_method_type (tree fntype, tree this_class, int access_flags)
 {
@@ -719,9 +716,6 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
     DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl) =
       htab_create_ggc (50, htab_hash_pointer, htab_eq_pointer, NULL);
 
-  /* Initialize the static method invocation compound list */
-  DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl) = NULL_TREE;
-
   TREE_CHAIN (fndecl) = TYPE_METHODS (this_class);
   TYPE_METHODS (this_class) = fndecl;
 
@@ -741,6 +735,10 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
       METHOD_NATIVE (fndecl) = 1;
       DECL_EXTERNAL (fndecl) = 1;
     }
+  else
+    /* FNDECL is external unless we are compiling it into this object
+       file.  */
+    DECL_EXTERNAL (fndecl) = CLASS_FROM_CURRENTLY_COMPILED_P (this_class) == 0;
   if (access_flags & ACC_STATIC) 
     METHOD_STATIC (fndecl) = DECL_INLINE (fndecl) = 1;
   if (access_flags & ACC_FINAL) 
@@ -748,6 +746,9 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
   if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1;
   if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1;
   if (access_flags & ACC_STRICT) METHOD_STRICTFP (fndecl) = 1;
+  if (access_flags & ACC_SYNTHETIC) DECL_ARTIFICIAL (fndecl) = 1;
+  if (access_flags & ACC_BRIDGE) METHOD_BRIDGE (fndecl) = 1;
+  if (access_flags & ACC_VARARGS) METHOD_VARARGS (fndecl) = 1;
   return fndecl;
 }
 
@@ -780,6 +781,7 @@ add_field (tree class, tree name, tree field_type, int flags)
   TREE_CHAIN (field) = TYPE_FIELDS (class);
   TYPE_FIELDS (class) = field;
   DECL_CONTEXT (field) = class;
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field);
 
   if (flags & ACC_PUBLIC) FIELD_PUBLIC (field) = 1;
   if (flags & ACC_PROTECTED) FIELD_PROTECTED (field) = 1;
@@ -791,15 +793,17 @@ add_field (tree class, tree name, tree field_type, int flags)
       TREE_THIS_VOLATILE (field) = 1;
     }
   if (flags & ACC_TRANSIENT) FIELD_TRANSIENT (field) = 1;
+  if (flags & ACC_ENUM) FIELD_ENUM (field) = 1;
+  if (flags & ACC_SYNTHETIC) FIELD_SYNTHETIC (field) = 1;
   if (is_static)
     {
       FIELD_STATIC (field) = 1;
       /* Always make field externally visible.  This is required so
         that native methods can always access the field.  */
       TREE_PUBLIC (field) = 1;
-      /* Considered external until we know what classes are being
-        compiled into this object file.  */
-      DECL_EXTERNAL (field) = 1;
+      /* Considered external unless we are compiling it into this
+        object file.  */
+      DECL_EXTERNAL (field) = (is_compiled_class (class) != 2);
     }
 
   return field;
@@ -833,24 +837,6 @@ set_constant_value (tree field, tree constant)
     }
 }
 
-/* Count the number of Unicode chars encoded in a given Ut8 string. */
-
-#if 0
-int
-strLengthUtf8 (char *str, int len)
-{
-  register unsigned char* ptr = (unsigned char*) str;
-  register unsigned char *limit = ptr + len;
-  int str_length = 0;
-  for (; ptr < limit; str_length++) {
-    if (UTF8_GET (ptr, limit) < 0)
-      return -1;
-  }
-  return str_length;
-}
-#endif
-
-
 /* Calculate a hash value for a string encoded in Utf8 format.
  * This returns the same hash value as specified for java.lang.String.hashCode.
  */
@@ -937,7 +923,7 @@ build_utf8_ref (tree name)
   layout_decl (decl, 0);
   pushdecl (decl);
   rest_of_decl_compilation (decl, global_bindings_p (), 0);
-  cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
+  varpool_mark_needed_node (varpool_node (decl));
   utf8_decl_list = decl;
   ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl);
   IDENTIFIER_UTF8_REF (name) = ref;
@@ -1022,6 +1008,54 @@ build_classdollar_field (tree type)
   return decl;
 }
 
+/* Create a local variable that holds the the current class$.  */
+
+void
+cache_this_class_ref (tree fndecl)
+{
+  if (optimize)
+    {
+      tree classdollar_field;
+      if (flag_indirect_classes)
+       classdollar_field = build_classdollar_field (output_class);
+      else
+       classdollar_field = build_static_class_ref (output_class);
+
+      this_classdollar = build_decl (VAR_DECL, NULL_TREE, 
+                                    TREE_TYPE (classdollar_field));
+      
+      java_add_local_var (this_classdollar);
+      java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (this_classdollar), 
+                            this_classdollar, classdollar_field));
+    }
+  else
+    this_classdollar = build_classdollar_field (output_class);
+
+  /* Prepend class initialization for static methods reachable from
+     other classes.  */
+  if (METHOD_STATIC (fndecl)
+      && (! METHOD_PRIVATE (fndecl)
+          || INNER_CLASS_P (DECL_CONTEXT (fndecl)))
+      && ! DECL_CLINIT_P (fndecl)
+      && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
+    {
+      tree init = build3 (CALL_EXPR, void_type_node,
+                         build_address_of (soft_initclass_node),
+                         build_tree_list (NULL_TREE, this_classdollar),
+                         NULL_TREE);
+      java_add_stmt (init);
+    }
+}
+
+/* Remove the reference to the local variable that holds the current
+   class$.  */
+
+void
+uncache_this_class_ref (tree fndecl ATTRIBUTE_UNUSED)
+{
+  this_classdollar = build_classdollar_field (output_class);
+}
+
 /* Build a reference to the class TYPE.
    Also handles primitive types and array types. */
 
@@ -1041,7 +1075,7 @@ build_class_ref (tree type)
        return build_indirect_class_ref (type);
 
       if (type == output_class && flag_indirect_classes)
-       return build_classdollar_field (type);
+       return this_classdollar;
       
       if (TREE_CODE (type) == RECORD_TYPE)
        return build_static_class_ref (type);
@@ -1050,40 +1084,6 @@ build_class_ref (tree type)
          const char *name;
          tree decl_name;
          char buffer[25];
-         if (flag_emit_class_files)
-           {
-             const char *prim_class_name;
-             tree prim_class;
-             if (type == char_type_node)
-               prim_class_name = "java.lang.Character";
-             else if (type == boolean_type_node)
-               prim_class_name = "java.lang.Boolean";
-             else if (type == byte_type_node)
-               prim_class_name = "java.lang.Byte";
-             else if (type == short_type_node)
-               prim_class_name = "java.lang.Short";
-             else if (type == int_type_node)
-               prim_class_name = "java.lang.Integer";
-             else if (type == long_type_node)
-               prim_class_name = "java.lang.Long";
-             else if (type == float_type_node)
-                prim_class_name = "java.lang.Float";
-             else if (type == double_type_node)
-                prim_class_name = "java.lang.Double";
-             else if (type == void_type_node)
-                prim_class_name = "java.lang.Void";
-             else
-               gcc_unreachable ();
-
-             prim_class = lookup_class (get_identifier (prim_class_name));
-             /* We wrap the class in a NOP_EXPR, because it is a
-                type.  We can't hold it in the COMPONENT_REF itself,
-                as that type must remain NULL.  */
-             prim_class = build1 (NOP_EXPR, prim_class, NULL_TREE);
-             
-             return build3 (COMPONENT_REF, NULL_TREE,
-                            prim_class, TYPE_identifier_node, NULL_TREE);
-           }
          decl_name = TYPE_NAME (type);
          if (TREE_CODE (decl_name) == TYPE_DECL)
            decl_name = DECL_NAME (decl_name);
@@ -1130,6 +1130,7 @@ build_fieldref_cache_entry (int index, tree fdecl ATTRIBUTE_UNUSED)
       TREE_PUBLIC (decl) = 0;
       DECL_EXTERNAL (decl) = 0;
       DECL_ARTIFICIAL (decl) = 1;
+      DECL_IGNORED_P (decl) = 1;
       pushdecl_top_level (decl);
     }
   return decl;
@@ -1218,6 +1219,10 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_VOLATILE;
       if (FIELD_TRANSIENT (decl))
        access_flags |= ACC_TRANSIENT;
+      if (FIELD_ENUM (decl))
+       access_flags |= ACC_ENUM;
+      if (FIELD_SYNTHETIC (decl))
+       access_flags |= ACC_SYNTHETIC;
       return access_flags;
     }
   if (TREE_CODE (decl) == TYPE_DECL)
@@ -1240,6 +1245,12 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_PROTECTED;
       if (CLASS_STRICTFP (decl))
        access_flags |= ACC_STRICT;
+      if (CLASS_ENUM (decl))
+       access_flags |= ACC_ENUM;
+      if (CLASS_SYNTHETIC (decl))
+       access_flags |= ACC_SYNTHETIC;
+      if (CLASS_ANNOTATION (decl))
+       access_flags |= ACC_ANNOTATION;
       return access_flags;
     }
   if (TREE_CODE (decl) == FUNCTION_DECL)
@@ -1264,6 +1275,12 @@ get_access_flags_from_decl (tree decl)
        access_flags |= ACC_STRICT;
       if (METHOD_INVISIBLE (decl))
        access_flags |= ACC_INVISIBLE;
+      if (DECL_ARTIFICIAL (decl))
+       access_flags |= ACC_SYNTHETIC;
+      if (METHOD_BRIDGE (decl))
+       access_flags |= ACC_BRIDGE;
+      if (METHOD_VARARGS (decl))
+       access_flags |= ACC_VARARGS;
       return access_flags;
     }
   gcc_unreachable ();
@@ -1645,6 +1662,8 @@ make_class_data (tree type)
       to where objects actually point at, following new g++ ABI. */
   tree dtable_start_offset = build_int_cst (NULL_TREE,
                                            2 * POINTER_SIZE / BITS_PER_UNIT);
+  VEC(int, heap) *field_indexes;
+  tree first_real_field;
 
   this_class_addr = build_static_class_ref (type);
   decl = TREE_OPERAND (this_class_addr, 0);
@@ -1654,15 +1673,28 @@ make_class_data (tree type)
     {
       tree dtable = get_dispatch_table (type, this_class_addr);
       uses_jv_markobj = uses_jv_markobj_p (dtable);
-      dtable_decl = build_dtable_decl (type);
-      DECL_INITIAL (dtable_decl) = dtable;
-      TREE_STATIC (dtable_decl) = 1;
-      DECL_ARTIFICIAL (dtable_decl) = 1;
-      DECL_IGNORED_P (dtable_decl) = 1;
+      if (type == class_type_node && class_dtable_decl != NULL_TREE)
+       {
+         /* We've already created some other class, and consequently
+            we made class_dtable_decl.  Now we just want to fill it
+            in.  */
+         dtable_decl = class_dtable_decl;
+       }
+      else
+       {
+         dtable_decl = build_dtable_decl (type);
+         TREE_STATIC (dtable_decl) = 1;
+         DECL_ARTIFICIAL (dtable_decl) = 1;
+         DECL_IGNORED_P (dtable_decl) = 1;
+       }
+
       TREE_PUBLIC (dtable_decl) = 1;
+      DECL_INITIAL (dtable_decl) = dtable;
       if (! flag_indirect_classes)
        rest_of_decl_compilation (dtable_decl, 1, 0);
-      if (type == class_type_node)
+      /* Maybe we're compiling Class as the first class.  If so, set
+        class_dtable_decl to the decl we just made.  */
+      if (type == class_type_node && class_dtable_decl == NULL_TREE)
        class_dtable_decl = dtable_decl;
     }
 
@@ -1672,7 +1704,54 @@ make_class_data (tree type)
     field = TREE_CHAIN (field);  /* Skip dummy fields.  */
   if (field && DECL_NAME (field) == NULL_TREE)
     field = TREE_CHAIN (field);  /* Skip dummy field for inherited data. */
-  for ( ;  field != NULL_TREE;  field = TREE_CHAIN (field))
+  first_real_field = field;
+
+  /* First count static and instance fields.  */
+  for ( ; field != NULL_TREE; field = TREE_CHAIN (field))
+    {
+      if (! DECL_ARTIFICIAL (field))
+       {
+         if (FIELD_STATIC (field))
+           static_field_count++;
+         else if (uses_jv_markobj || !flag_reduced_reflection)
+           instance_field_count++;
+       }
+    }
+  field_count = static_field_count + instance_field_count;
+  field_indexes = VEC_alloc (int, heap, field_count);
+  
+  /* gcj sorts fields so that static fields come first, followed by
+     instance fields.  Unfortunately, by the time this takes place we
+     have already generated the reflection_data for this class, and
+     that data contains indexes into the fields.  So, we generate a
+     permutation that maps each original field index to its final
+     position.  Then we pass this permutation to
+     rewrite_reflection_indexes(), which fixes up the reflection
+     data.  */
+  {
+    int i;
+    int static_count = 0;
+    int instance_count = static_field_count;
+    int field_index;
+
+    for (i = 0, field = first_real_field; 
+        field != NULL_TREE; 
+        field = TREE_CHAIN (field), i++)
+    {
+      if (! DECL_ARTIFICIAL (field))
+       {
+         field_index = 0;
+         if (FIELD_STATIC (field))
+           field_index = static_count++;
+         else if (uses_jv_markobj || !flag_reduced_reflection)
+           field_index = instance_count++;
+         VEC_quick_push (int, field_indexes, field_index);
+       }
+    }
+  }
+
+  for (field = first_real_field; field != NULL_TREE; 
+       field = TREE_CHAIN (field))
     {
       if (! DECL_ARTIFICIAL (field))
        {
@@ -1682,7 +1761,6 @@ make_class_data (tree type)
                  as it is used in the creation of the field itself. */
               tree init = make_field_value (field);
              tree initial = DECL_INITIAL (field);
-             static_field_count++;
              static_fields = tree_cons (NULL_TREE, init, static_fields);
              /* If the initial value is a string constant,
                 prevent output_constant from trying to assemble the value. */
@@ -1695,12 +1773,11 @@ make_class_data (tree type)
          else if (uses_jv_markobj || !flag_reduced_reflection)
            {
               tree init = make_field_value (field);
-             instance_field_count++;
              instance_fields = tree_cons (NULL_TREE, init, instance_fields);
            }
        }
     }
-  field_count = static_field_count + instance_field_count;
+
   if (field_count > 0)
     {
       static_fields = nreverse (static_fields);
@@ -1780,8 +1857,10 @@ make_class_data (tree type)
       DECL_ARTIFICIAL (class_dtable_decl) = 1;
       DECL_IGNORED_P (class_dtable_decl) = 1;
       if (is_compiled_class (class_type_node) != 2)
-       DECL_EXTERNAL (class_dtable_decl) = 1;
-      rest_of_decl_compilation (class_dtable_decl, 1, 0);
+       {
+         DECL_EXTERNAL (class_dtable_decl) = 1;
+         rest_of_decl_compilation (class_dtable_decl, 1, 0);
+       }
     }
 
   super = CLASSTYPE_SUPER (type);
@@ -1863,10 +1942,12 @@ make_class_data (tree type)
 
   START_RECORD_CONSTRUCTOR (temp, object_type_node);
   PUSH_FIELD_VALUE (temp, "vtable",
-                   build2 (PLUS_EXPR, dtable_ptr_type,
-                           build1 (ADDR_EXPR, dtable_ptr_type,
-                                   class_dtable_decl),
-                           dtable_start_offset));
+                   (flag_indirect_classes 
+                    ? null_pointer_node
+                    : build2 (PLUS_EXPR, dtable_ptr_type,
+                              build1 (ADDR_EXPR, dtable_ptr_type,
+                                      class_dtable_decl),
+                              dtable_start_offset)));
   if (! flag_hash_synchronization)
     PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
   FINISH_RECORD_CONSTRUCTOR (temp);
@@ -1998,6 +2079,48 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "engine", null_pointer_node);
 
+  if (TYPE_REFLECTION_DATA (current_class))
+    {
+      int i;
+      int count = TYPE_REFLECTION_DATASIZE (current_class);
+      VEC (constructor_elt, gc) *v
+       = VEC_alloc (constructor_elt, gc, count);
+      unsigned char *data = TYPE_REFLECTION_DATA (current_class);
+      tree max_index = build_int_cst (sizetype, count);
+      tree index = build_index_type (max_index);
+      tree type = build_array_type (unsigned_byte_type_node, index);
+      char buf[64];
+      tree array;
+      static int reflection_data_count;
+
+      sprintf (buf, "_reflection_data_%d", reflection_data_count++);
+      array = build_decl (VAR_DECL, get_identifier (buf), type);
+
+      rewrite_reflection_indexes (field_indexes);
+
+      for (i = 0; i < count; i++)
+       {
+         constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
+         elt->index = build_int_cst (sizetype, i);
+         elt->value = build_int_cstu (byte_type_node, data[i]);
+       }
+
+      DECL_INITIAL (array) = build_constructor (type, v);
+      TREE_STATIC (array) = 1;
+      DECL_ARTIFICIAL (array) = 1;
+      DECL_IGNORED_P (array) = 1;
+      TREE_READONLY (array) = 1;
+      TREE_CONSTANT (DECL_INITIAL (array)) = 1;
+      rest_of_decl_compilation (array, 1, 0);
+      
+      PUSH_FIELD_VALUE (cons, "reflection_data", build_address_of (array));
+
+      free (data);
+      TYPE_REFLECTION_DATA (current_class) = NULL;
+    }
+  else
+    PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node);
+
   FINISH_RECORD_CONSTRUCTOR (cons);
 
   DECL_INITIAL (decl) = cons;
@@ -2063,18 +2186,16 @@ is_compiled_class (tree class)
     return 1;
   if (TYPE_ARRAY_P (class))
     return 0;
-  if (class == current_class)
-    return 2;
 
   seen_in_zip = (TYPE_JCF (class) && JCF_SEEN_IN_ZIP (TYPE_JCF (class)));
-  if (CLASS_FROM_CURRENTLY_COMPILED_P (class) || seen_in_zip)
+  if (CLASS_FROM_CURRENTLY_COMPILED_P (class))
     {
       /* The class was seen in the current ZIP file and will be
         available as a compiled class in the future but may not have
         been loaded already. Load it if necessary. This prevent
         build_class_ref () from crashing. */
 
-      if (seen_in_zip && !CLASS_LOADED_P (class))
+      if (seen_in_zip && !CLASS_LOADED_P (class) && (class != current_class))
         load_class (class, 1);
 
       /* We return 2 for class seen in ZIP and class from files
@@ -2088,7 +2209,7 @@ is_compiled_class (tree class)
        {
          if (CLASS_FROM_SOURCE_P (class))
            safe_layout_class (class);
-         else
+         else if (class != current_class)
            load_class (class, 1);
        }
       return 1;
@@ -2179,7 +2300,7 @@ push_super_field (tree this_class, tree super_class)
 /* Handle the different manners we may have to lay out a super class.  */
 
 static tree
-maybe_layout_super_class (tree super_class, tree this_class)
+maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED)
 {
   if (!super_class)
     return NULL_TREE;
@@ -2197,33 +2318,7 @@ maybe_layout_super_class (tree super_class, tree this_class)
       if (TREE_TYPE (super_class) != NULL_TREE)
        super_class = TREE_TYPE (super_class);
       else
-       {
-         /* do_resolve_class expects an EXPR_WITH_FILE_LOCATION, so
-            we give it one.  */
-         tree this_wrap = NULL_TREE;
-
-         /* Set the correct context for class resolution.  */
-         current_class = this_class;
-
-         if (this_class)
-           {
-             tree this_decl = TYPE_NAME (this_class);
-#ifdef USE_MAPPED_LOCATION
-             this_wrap = build_expr_wfl (this_class,
-                                         DECL_SOURCE_LOCATION (this_decl));
-#else
-             this_wrap = build_expr_wfl (this_class,
-                                         DECL_SOURCE_FILE (this_decl),
-                                         DECL_SOURCE_LINE (this_decl), 0);
-#endif
-           }
-         super_class
-           = do_resolve_class (DECL_CONTEXT (TYPE_NAME (this_class)),
-                               this_class, super_class, NULL_TREE, this_wrap);
-         if (!super_class)
-           return NULL_TREE;   /* FIXME, NULL_TREE not checked by caller. */
-         super_class = TREE_TYPE (super_class);
-       }
+       gcc_unreachable ();
     }
   if (!TYPE_SIZE (super_class))
     safe_layout_class (super_class);
@@ -2231,6 +2326,22 @@ maybe_layout_super_class (tree super_class, tree this_class)
   return super_class;
 }
 
+/* safe_layout_class just makes sure that we can load a class without
+   disrupting the current_class, input_file, input_line, etc, information
+   about the class processed currently.  */
+
+void
+safe_layout_class (tree class)
+{
+  tree save_current_class = current_class;
+  location_t save_location = input_location;
+
+  layout_class (class);
+
+  current_class = save_current_class;
+  input_location = save_location;
+}
+
 void
 layout_class (tree this_class)
 {
@@ -2384,7 +2495,7 @@ layout_class_methods (tree this_class)
 
   if (TYPE_NVIRTUALS (this_class))
     return;
-
+  
   super_class = CLASSTYPE_SUPER (this_class);
 
   if (super_class)
@@ -2447,9 +2558,12 @@ layout_class_method (tree this_class, tree super_class,
   tree method_name = DECL_NAME (method_decl);
 
   TREE_PUBLIC (method_decl) = 1;
-  /* Considered external until we know what classes are being
-     compiled into this object file.  */
-  DECL_EXTERNAL (method_decl) = 1;
+
+  /* Considered external unless it is being compiled into this object
+     file, or it was already flagged as external.  */
+  if (!DECL_EXTERNAL (method_decl))
+    DECL_EXTERNAL (method_decl) = ((is_compiled_class (this_class) != 2)
+                                   || METHOD_NATIVE (method_decl));
 
   if (ID_INIT_P (method_name))
     {
@@ -2461,14 +2575,14 @@ layout_class_method (tree this_class, tree super_class,
            p = ptr;
        }
       DECL_CONSTRUCTOR_P (method_decl) = 1;
-      build_java_argument_signature (TREE_TYPE (method_decl));
+      build_java_signature (TREE_TYPE (method_decl));
     }
   else if (! METHOD_STATIC (method_decl))
     {
       tree method_sig =
-       build_java_argument_signature (TREE_TYPE (method_decl));
+       build_java_signature (TREE_TYPE (method_decl));
       bool method_override = false;
-      tree super_method = lookup_argument_method (super_class, method_name,
+      tree super_method = lookup_java_method (super_class, method_name,
                                                  method_sig);
       if (super_method != NULL_TREE
          && ! METHOD_DUMMY (super_method))