OSDN Git Service

Tue Nov 24 17:06:38 1998 Per Bothner <bothner@cygnus.com>
authorapbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Nov 1998 17:57:41 +0000 (17:57 +0000)
committerapbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Nov 1998 17:57:41 +0000 (17:57 +0000)
* (generate_classfile): Always write class access flag with
  ACC_SUPER set.
Tue Nov 24 16:34:33 1998  Alexandre Petit-Bianco  <apbianco@cygnus.com>
* class.c (maybe_layout_super_class): New function.
(layout_class): Reorganized. Loop on class methods dispatched into
  a new function. Call maybe_layout_super_class.
(layout_class_methods, layout_class_method): New functions.
* expr.c (expand_java_NEW): Call layout_class_methods on loaded
  class.
(expand_invoke): Likewise.
* java-tree.h (all_class_list): New global variable declared.
(layout_class_methods, layout_class_method): New function
  prototypes.
(LAYOUT_SEEN_CLASS_METHODS): New macro.
* jcf-parse.c (all_class_list): New global variable.
(load_class): Extended what class_or_name can be. Use parser
  context mechanism to save globals before calling jcf_parse.
(jcf_parse_source): Don't parse twice if HAS_BEEN_ALREADY_PARSED_P
  is set on the file name.
(jcf_parse): Layout class methods when Object is loaded, otherwise
  record class in all_class_list for delayed method layout.
(parse_class_file): Use LAYOUT_SEEN_CLASS_METHODS.
* lang.c (put_decl_node): Decode <init> into the decl context
  class name.
* lex.c (java_allocate_new_line): Use xmalloc.
* parse.h (INCOMPLETE_TYPE_P): Redefined to work with incomplete
  pointers, not TREE_LIST elements.
(struct parser_ctxt): Fixed comment indentations, added comments
  and reordered some fields.
(java_check_methods): Function prototype removed.
* parse.y (java_push_parser_context): Use xmalloc.
(java_parser_context_restore_global): Pop extra pushed ctxp only
  when there's nothing next.
(maybe_create_class_interface_decl): Fixed comment, add new
  created class decl to all_class_list.
(method_header): Use GET_REAL_TYPE on argument's types.
(method_declarator): Use GET_REAL_TYPE, change type to the real
  type in TREE_LIST dependency node. Build argument list with the
  real type.
(create_jdep_list): Use xmalloc. Removed allocation error message.
(obtain_incomplete_type): Fixed leading comment. Broadened
  incoming argument meaning.
(register_incomplete_type): Use xmalloc. Removed allocation error
  message.
(safe_layout_class): Fixed leading comment.
(jdep_resolve_class): Reversed if statement condition and switch
  if and else bodies.
(resolve_and_layout): Fixed leading comment. Broadened incoming
  argument meaning.
(complete_class_report_errors): New local variable name, for
  clarity. purify_type_name used for all error cases.
(java_get_real_method_name): Stricter check on constructors.
(java_check_regular_methods): Reverse methods list only if not
  already laid out. Layout artificial constructor.
(java_check_methods): Deleted.
(source_start_java_method): Obtain incomplete type for patchable
  method arguments.
(java_layout_classes): Fixed leading comment. Use
  LAYOUT_SEEN_CLASS_METHODS, use a loop to check methods. Added else
  statement to layout operation, reuse LAYOUT_SEEN_CLASS_METHODS
  before returning. Fixed comments.
(java_expand_classes): Check for errors up front.
(patch_method_invocation): Class to search is resolved and laid
  out.
A step forward truly mixing .class and .java during package
compilation. Includes a Per's patch.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23834 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/java/ChangeLog
gcc/java/class.c
gcc/java/expr.c
gcc/java/java-tree.h
gcc/java/jcf-parse.c
gcc/java/jcf-write.c
gcc/java/lang.c
gcc/java/lex.c
gcc/java/parse.c
gcc/java/parse.h
gcc/java/parse.y

index 5e039df..a0dd3fb 100644 (file)
@@ -1,3 +1,72 @@
+Tue Nov 24 17:06:38 1998  Per Bothner  <bothner@cygnus.com>
+
+       * (generate_classfile): Always write class access flag with
+       ACC_SUPER set.
+
+Tue Nov 24 16:34:33 1998  Alexandre Petit-Bianco  <apbianco@cygnus.com>
+
+       * class.c (maybe_layout_super_class): New function.
+       (layout_class): Reorganized. Loop on class methods dispatched into
+       a new function. Call maybe_layout_super_class.
+       (layout_class_methods, layout_class_method): New functions.
+       * expr.c (expand_java_NEW): Call layout_class_methods on loaded
+       class.
+       (expand_invoke): Likewise.
+       * java-tree.h (all_class_list): New global variable declared.
+       (layout_class_methods, layout_class_method): New function
+       prototypes.
+       (LAYOUT_SEEN_CLASS_METHODS): New macro.
+       * jcf-parse.c (all_class_list): New global variable.
+       (load_class): Extended what class_or_name can be. Use parser
+       context mechanism to save globals before calling jcf_parse.
+       (jcf_parse_source): Don't parse twice if HAS_BEEN_ALREADY_PARSED_P
+       is set on the file name.
+       (jcf_parse): Layout class methods when Object is loaded, otherwise
+       record class in all_class_list for delayed method layout.
+       (parse_class_file): Use LAYOUT_SEEN_CLASS_METHODS.
+       * lang.c (put_decl_node): Decode <init> into the decl context
+       class name.
+       * lex.c (java_allocate_new_line): Use xmalloc.
+       * parse.h (INCOMPLETE_TYPE_P): Redefined to work with incomplete
+       pointers, not TREE_LIST elements.
+       (struct parser_ctxt): Fixed comment indentations, added comments
+       and reordered some fields.
+       (java_check_methods): Function prototype removed.
+       * parse.y (java_push_parser_context): Use xmalloc.
+       (java_parser_context_restore_global): Pop extra pushed ctxp only
+       when there's nothing next.
+       (maybe_create_class_interface_decl): Fixed comment, add new
+       created class decl to all_class_list.
+       (method_header): Use GET_REAL_TYPE on argument's types.
+       (method_declarator): Use GET_REAL_TYPE, change type to the real
+       type in TREE_LIST dependency node. Build argument list with the
+       real type.
+       (create_jdep_list): Use xmalloc. Removed allocation error message.
+       (obtain_incomplete_type): Fixed leading comment. Broadened
+       incoming argument meaning.
+       (register_incomplete_type): Use xmalloc. Removed allocation error
+       message.
+       (safe_layout_class): Fixed leading comment.
+       (jdep_resolve_class): Reversed if statement condition and switch
+       if and else bodies.
+       (resolve_and_layout): Fixed leading comment. Broadened incoming
+       argument meaning.
+       (complete_class_report_errors): New local variable name, for
+       clarity. purify_type_name used for all error cases.
+       (java_get_real_method_name): Stricter check on constructors.
+       (java_check_regular_methods): Reverse methods list only if not
+       already laid out. Layout artificial constructor.
+       (java_check_methods): Deleted.
+       (source_start_java_method): Obtain incomplete type for patchable
+       method arguments.
+       (java_layout_classes): Fixed leading comment. Use
+       LAYOUT_SEEN_CLASS_METHODS, use a loop to check methods. Added else
+       statement to layout operation, reuse LAYOUT_SEEN_CLASS_METHODS
+       before returning. Fixed comments.
+       (java_expand_classes): Check for errors up front.
+       (patch_method_invocation): Class to search is resolved and laid
+       out.
+       
 Tue Nov 24 12:57:13 1998  Per Bothner  <bothner@cygnus.com>
 
        * expr.c (java_lang_expand_expr):  Add missing emit_queue.
index 0f8d488..e0ea241 100644 (file)
@@ -1323,39 +1323,55 @@ push_super_field (this_class, super_class)
   DECL_SIZE (base_decl) = TYPE_SIZE (super_class);
 }
 
+/* Handle the different manners we may have to lay out a super class.  */
+
+static tree
+maybe_layout_super_class (super_class)
+     tree super_class;
+{
+  if (TREE_CODE (super_class) == RECORD_TYPE)
+    {
+      if (!CLASS_LOADED_P (super_class) 
+         && CLASS_FROM_SOURCE_P (super_class))
+       safe_layout_class (super_class);
+      if (!CLASS_LOADED_P (super_class))
+       load_class (super_class, 1);
+    }
+  /* We might have to layout the class before its dependency on
+     the super class gets resolved by java_complete_class  */
+  else if (TREE_CODE (super_class) == TREE_LIST)
+    {
+      tree name = TYPE_NAME (TREE_PURPOSE (super_class));
+      load_class (name, 1);
+      super_class = IDENTIFIER_CLASS_VALUE (name);
+      if (!super_class)
+           return;
+      super_class = TREE_TYPE (super_class);
+    }
+  if (!TYPE_SIZE (super_class))
+    safe_layout_class (super_class);
+
+  return super_class;
+}
+
 void
 layout_class (this_class)
      tree this_class;
 {
   tree super_class = CLASSTYPE_SUPER (this_class);
-  tree handle_type = CLASS_TO_HANDLE_TYPE (this_class);
-  tree method_decl, field;
-  tree dtable_count;
-  int i;
+  tree field;
 
   if (super_class)
     {
-      /* Class seen in source are now complete and can be layed out.
-        Once layed out, a class seen in the source has its
-        CLASS_LOADED_P flag set */
-      if (CLASS_FROM_SOURCE_P (super_class) && !CLASS_LOADED_P (super_class))
-       safe_layout_class (super_class);
-      if (! CLASS_LOADED_P (super_class))
-       load_class (super_class, 1);
+      super_class = maybe_layout_super_class (super_class);
       if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK)
        {
          TYPE_SIZE (this_class) = error_mark_node;
          return;
        }
-      dtable_count = TYPE_NVIRTUALS (super_class);
-
       if (TYPE_SIZE (this_class) == NULL_TREE)
        push_super_field (this_class, super_class);
     }
-  else
-    {
-      dtable_count = integer_zero_node;
-    }
 
   for (field = TYPE_FIELDS (this_class);
        field != NULL_TREE;  field = TREE_CHAIN (field))
@@ -1368,178 +1384,217 @@ layout_class (this_class)
     }
 
   layout_type (this_class);
+}
 
-  TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
+void
+layout_class_methods (this_class)
+     tree this_class;
+{
+  tree method_decl, dtable_count;
+  tree super_class, handle_type;
+
+  if (TYPE_NVIRTUALS (this_class))
+    return;
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+  super_class = CLASSTYPE_SUPER (this_class);
+  handle_type = CLASS_TO_HANDLE_TYPE (this_class);
 
-  for (method_decl = TYPE_METHODS (handle_type), i = 0;
-       method_decl; method_decl = TREE_CHAIN (method_decl), i++)
+  if (super_class)
     {
-      char *ptr;
-      char buf[8];
-      char *asm_name;
-      tree method_name = DECL_NAME (method_decl);
-      int method_name_is_wfl = 
-       (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION);
-      if (method_name_is_wfl)
-       method_name = java_get_real_method_name (method_decl);
+      super_class = maybe_layout_super_class (super_class);
+      if (!TYPE_NVIRTUALS (super_class))
+       layout_class_methods (super_class);
+      dtable_count = TYPE_NVIRTUALS (super_class);
+    }
+  else
+    dtable_count = integer_zero_node;
+  
+  TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
+
+  for (method_decl = TYPE_METHODS (handle_type);
+       method_decl; method_decl = TREE_CHAIN (method_decl))
+    dtable_count = layout_class_method (this_class, super_class, 
+                                       method_decl, dtable_count);
+
+  TYPE_NVIRTUALS (this_class) = dtable_count;
+
+#ifdef JAVA_USE_HANDLES
+  layout_type (handle_type);
+#endif
+  pop_obstacks ();
+}
+
+/* Lay METHOD_DECL out, returning a possibly new value of
+   DTABLE_COUNT.  */
+
+tree
+layout_class_method (this_class, super_class, method_decl, dtable_count)
+     tree this_class, super_class, method_decl, dtable_count;
+{
+  char *ptr;
+  char buf[8];
+  char *asm_name;
+  tree method_name = DECL_NAME (method_decl);
+  int method_name_is_wfl = 
+    (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION);
+  if (method_name_is_wfl)
+    method_name = java_get_real_method_name (method_decl);
 #if 1
-      /* Remove this once we no longer need old (Kaffe / JDK 1.0)  mangling. */
-      if (! flag_assume_compiled && METHOD_NATIVE (method_decl))
+  /* Remove this once we no longer need old (Kaffe / JDK 1.0)  mangling. */
+  if (! flag_assume_compiled && METHOD_NATIVE (method_decl))
+    {
+      for (ptr = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
+          *ptr; )
+       {
+         int ch = *ptr++;
+         if (ch == '.')
+           ch = '_';
+         obstack_1grow (&temporary_obstack, (char) ch);
+       }
+      obstack_1grow (&temporary_obstack, (char) '_');
+      if (method_name == init_identifier_node)
+       obstack_grow (&temporary_obstack, "INIT", 4);
+      else
+       obstack_grow (&temporary_obstack,
+                     IDENTIFIER_POINTER (method_name),
+                     IDENTIFIER_LENGTH (method_name));
+    }
+  else
+#endif
+    {
+      int len;  tree arg, arglist, t;
+      int method_name_needs_escapes = 0;
+      if (method_name != init_identifier_node 
+         && method_name != finit_identifier_node)
        {
-         for (ptr = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
-              *ptr; )
+         int encoded_len
+           = unicode_mangling_length (IDENTIFIER_POINTER (method_name), 
+                                      IDENTIFIER_LENGTH (method_name));
+         if (encoded_len > 0)
            {
-             int ch = *ptr++;
-             if (ch == '.')
-               ch = '_';
-             obstack_1grow (&temporary_obstack, (char) ch);
+             method_name_needs_escapes = 1;
+             emit_unicode_mangled_name (&temporary_obstack,
+                                        IDENTIFIER_POINTER (method_name), 
+                                        IDENTIFIER_LENGTH (method_name));
            }
-         obstack_1grow (&temporary_obstack, (char) '_');
-         if (method_name == init_identifier_node)
-           obstack_grow (&temporary_obstack, "INIT", 4);
          else
-           obstack_grow (&temporary_obstack,
-                         IDENTIFIER_POINTER (method_name),
-                         IDENTIFIER_LENGTH (method_name));
+           {
+             obstack_grow (&temporary_obstack,
+                           IDENTIFIER_POINTER (method_name),
+                           IDENTIFIER_LENGTH (method_name));
+           }
        }
-      else
-#endif
+      
+      obstack_grow (&temporary_obstack, "__", 2);
+      if (method_name == finit_identifier_node)
+       obstack_grow (&temporary_obstack, "finit", 5);
+      append_gpp_mangled_type (&temporary_obstack, this_class);
+      TREE_PUBLIC (method_decl) = 1;
+      
+      t = TREE_TYPE (method_decl);
+      arglist = TYPE_ARG_TYPES (t);
+      if (TREE_CODE (t) == METHOD_TYPE)
+       arglist = TREE_CHAIN (arglist);
+      for (arg = arglist; arg != NULL_TREE;  )
        {
-         int len;  tree arg, arglist, t;
-         int method_name_needs_escapes = 0;
-         if (method_name != init_identifier_node 
-             && method_name != finit_identifier_node)
+         tree a = arglist;
+         tree argtype = TREE_VALUE (arg);
+         int tindex = 1;
+         if (TREE_CODE (argtype) == POINTER_TYPE)
            {
-             int encoded_len
-               = unicode_mangling_length (IDENTIFIER_POINTER (method_name), 
-                                          IDENTIFIER_LENGTH (method_name));
-             if (encoded_len > 0)
-               {
-                 method_name_needs_escapes = 1;
-                 emit_unicode_mangled_name (&temporary_obstack,
-                                            IDENTIFIER_POINTER (method_name), 
-                                            IDENTIFIER_LENGTH (method_name));
-               }
-             else
-               {
-                 obstack_grow (&temporary_obstack,
-                               IDENTIFIER_POINTER (method_name),
-                               IDENTIFIER_LENGTH (method_name));
-               }
+             /* This is O(N**2).  Do we care?  Cfr gcc/cp/method.c. */
+             while (a != arg && argtype != TREE_VALUE (a))
+               a = TREE_CHAIN (a), tindex++;
            }
-
-         obstack_grow (&temporary_obstack, "__", 2);
-         if (method_name == finit_identifier_node)
-           obstack_grow (&temporary_obstack, "finit", 5);
-         append_gpp_mangled_type (&temporary_obstack, this_class);
-         TREE_PUBLIC (method_decl) = 1;
-
-         t = TREE_TYPE (method_decl);
-         arglist = TYPE_ARG_TYPES (t);
-         if (TREE_CODE (t) == METHOD_TYPE)
-           arglist = TREE_CHAIN (arglist);
-         for (arg = arglist; arg != NULL_TREE;  )
+         else
+           a = arg;
+         if (a != arg)
            {
-             tree a = arglist;
-             tree argtype = TREE_VALUE (arg);
-             int tindex = 1;
-             if (TREE_CODE (argtype) == POINTER_TYPE)
+             char buf[12];
+             int nrepeats = 0;
+             do
                {
-                 /* This is O(N**2).  Do we care?  Cfr gcc/cp/method.c. */
-                 while (a != arg && argtype != TREE_VALUE (a))
-                   a = TREE_CHAIN (a), tindex++;
+                 arg = TREE_CHAIN (arg); nrepeats++;
                }
-             else
-               a = arg;
-             if (a != arg)
+             while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
+             if (nrepeats > 1)
                {
-                 char buf[12];
-                 int nrepeats = 0;
-                 do
-                   {
-                     arg = TREE_CHAIN (arg); nrepeats++;
-                   }
-                 while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
-                 if (nrepeats > 1)
-                   {
-                     obstack_1grow (&temporary_obstack, 'N');
-                     sprintf (buf, "%d", nrepeats);
-                     obstack_grow (&temporary_obstack, buf, strlen (buf));
-                     if (nrepeats > 9)
-                       obstack_1grow (&temporary_obstack, '_');
-                   }
-                 else
-                   obstack_1grow (&temporary_obstack, 'T');
-                 sprintf (buf, "%d", tindex);
+                 obstack_1grow (&temporary_obstack, 'N');
+                 sprintf (buf, "%d", nrepeats);
                  obstack_grow (&temporary_obstack, buf, strlen (buf));
-                 if (tindex > 9)
+                 if (nrepeats > 9)
                    obstack_1grow (&temporary_obstack, '_');
                }
              else
-               {
-                 append_gpp_mangled_type (&temporary_obstack, argtype);
-                 arg = TREE_CHAIN (arg);
-               }
+               obstack_1grow (&temporary_obstack, 'T');
+             sprintf (buf, "%d", tindex);
+             obstack_grow (&temporary_obstack, buf, strlen (buf));
+             if (tindex > 9)
+               obstack_1grow (&temporary_obstack, '_');
            }
-         if (method_name_needs_escapes)
-           obstack_1grow (&temporary_obstack, 'U');
-       }
-      obstack_1grow (&temporary_obstack, '\0');
-      asm_name = obstack_finish (&temporary_obstack);
-      DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
-      if (! METHOD_ABSTRACT (method_decl))
-       make_function_rtl (method_decl);
-      obstack_free (&temporary_obstack, asm_name);
-
-      if (method_name == init_identifier_node)
-       {
-         char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
-         for (ptr = p; *ptr; )
+         else
            {
-             if (*ptr++ == '.')
-               p = ptr;
+             append_gpp_mangled_type (&temporary_obstack, argtype);
+             arg = TREE_CHAIN (arg);
            }
-         if (method_name_is_wfl)
-           EXPR_WFL_NODE (DECL_NAME (method_decl)) = get_identifier (p);
-         else
-           DECL_NAME (method_decl) = get_identifier (p);
-         DECL_CONSTRUCTOR_P (method_decl) = 1;
        }
-      else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+      if (method_name_needs_escapes)
+       obstack_1grow (&temporary_obstack, 'U');
+    }
+  obstack_1grow (&temporary_obstack, '\0');
+  asm_name = obstack_finish (&temporary_obstack);
+  DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
+  if (! METHOD_ABSTRACT (method_decl))
+    make_function_rtl (method_decl);
+  obstack_free (&temporary_obstack, asm_name);
+  
+  if (method_name == init_identifier_node)
+    {
+      char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
+      for (ptr = p; *ptr; )
        {
-         tree method_sig = build_java_argument_signature (TREE_TYPE (method_decl));
-         tree super_method = lookup_argument_method (super_class, method_name,
+         if (*ptr++ == '.')
+           p = ptr;
+       }
+      if (method_name_is_wfl)
+       EXPR_WFL_NODE (DECL_NAME (method_decl)) = get_identifier (p);
+      else
+       DECL_NAME (method_decl) = get_identifier (p);
+      DECL_CONSTRUCTOR_P (method_decl) = 1;
+    }
+  else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+    {
+      tree method_sig = 
+       build_java_argument_signature (TREE_TYPE (method_decl));
+      tree super_method = lookup_argument_method (super_class, method_name,
                                                  method_sig);
-         if (super_method != NULL_TREE)
-           {
-             DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
-             if (DECL_VINDEX (method_decl) == NULL_TREE)
-               error_with_decl (method_decl,
-                        "non-static method '%s' overrides static method");
+      if (super_method != NULL_TREE)
+       {
+         DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
+         if (DECL_VINDEX (method_decl) == NULL_TREE)
+           error_with_decl (method_decl,
+                            "non-static method '%s' overrides static method");
 #if 0
-             else if (TREE_TYPE (TREE_TYPE (method_decl))
-                      != TREE_TYPE (TREE_TYPE (super_method)))
-               {
-                 error_with_decl (method_decl,
-                                "Method `%s' redefined with different return type");  
-                 error_with_decl (super_method,
-                                "Overridden decl is here");
-               }
+else if (TREE_TYPE (TREE_TYPE (method_decl))
+        != TREE_TYPE (TREE_TYPE (super_method)))
+  {
+    error_with_decl (method_decl,
+                    "Method `%s' redefined with different return type");  
+    error_with_decl (super_method,
+                    "Overridden decl is here");
+  }
 #endif
-           }
-         else if (! METHOD_FINAL (method_decl)
-                  && ! CLASS_FINAL (TYPE_NAME (this_class)))
-           {
-             DECL_VINDEX (method_decl) = dtable_count;
-             dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
-           }
+       }
+      else if (! METHOD_FINAL (method_decl)
+              && ! CLASS_FINAL (TYPE_NAME (this_class))
+              && dtable_count)
+       {
+         DECL_VINDEX (method_decl) = dtable_count;
+         dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
        }
     }
-  TYPE_NVIRTUALS (this_class) = dtable_count;
-
-#ifdef JAVA_USE_HANDLES
-  layout_type (handle_type);
-#endif
+  return dtable_count;
 }
 
 static tree registered_class = NULL_TREE;
index 5631656..7ac3d19 100644 (file)
@@ -910,6 +910,7 @@ expand_java_NEW (type)
 {
   if (! CLASS_LOADED_P (type))
     load_class (type, 1);
+  layout_class_methods (type);
   push_value (build (CALL_EXPR, promote_type (type),
                     build_address_of (alloc_object_node),
                     tree_cons (NULL_TREE, build_class_ref (type),
@@ -1485,6 +1486,7 @@ expand_invoke (opcode, method_ref_index, nargs)
       if (TREE_CODE (TYPE_SIZE (self_type)) == ERROR_MARK)
        fatal ("failed to find class '%s'", self_name);
     }
+  layout_class_methods (self_type);
 
   if (method_name == init_identifier_node)
     method = lookup_java_constructor (CLASS_TO_HANDLE_TYPE (self_type),
index 4554638..66aae18 100644 (file)
@@ -112,6 +112,9 @@ extern tree main_class;
 /* The class we are currently processing. */
 extern tree current_class;
 
+/* List of all class DECLs seen so far.  */
+extern tree all_class_list;
+
 /* Nonzero if we want to automatically do array bounds checking;
    on by default.  Use -fno-bounds-check to disable.  */
 
@@ -483,6 +486,8 @@ extern tree unmangle_classname PROTO ((const char *name, int name_length));
 extern tree parse_signature_string PROTO ((const unsigned char *, int));
 extern tree get_type_from_signature PROTO ((tree));
 extern void layout_class PROTO ((tree));
+extern tree layout_class_method PROTO ((tree, tree, tree, tree));
+extern void layout_class_methods PROTO ((tree));
 extern tree make_class ();
 extern tree build_class_ref PROTO ((tree));
 extern tree build_dtable_decl PROTO ((tree));
@@ -835,3 +840,10 @@ extern tree *type_map;
      if (java_error_count)                                             \
        return;                                                         \
    }
+
+#define LAYOUT_SEEN_CLASS_METHODS()                                        \
+  {                                                                        \
+    tree current;                                                          \
+    for (current = all_class_list; current; current = TREE_CHAIN (current)) \
+      layout_class_methods (TREE_TYPE (TREE_VALUE (current)));             \
+  }
index 8a01b2c..c9f2ed7 100644 (file)
@@ -61,7 +61,10 @@ tree current_class = NULL_TREE;
 /* The class we started with. */
 tree main_class = NULL_TREE;
 
-/* The FIELD_DECL for the current field. */
+/* List of all class DECL seen so far.  */
+tree all_class_list = NULL_TREE;
+
+/* The FIELD_DECL for the current field.  */
 static tree current_field = NULL_TREE;
 
 /* The METHOD_DECL for the current method.  */
@@ -450,8 +453,7 @@ load_class (class_or_name, verbose)
      int verbose;
 {
   JCF this_jcf, *jcf;
-  tree name = (TREE_CODE (class_or_name) == IDENTIFIER_NODE ?
-              class_or_name : DECL_NAME (TYPE_NAME (class_or_name)));
+  tree name;
   tree save_current_class = current_class;
   char *save_input_filename = input_filename;
   JCF *save_current_jcf = current_jcf;
@@ -459,6 +461,17 @@ load_class (class_or_name, verbose)
   if (current_jcf->read_state)
     saved_pos = ftell (current_jcf->read_state);
 
+  /* class_or_name can be the name of the class we want to load */
+  if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
+    name = class_or_name;
+  /* In some cases, it's a dependency that we process earlier that
+     we though */
+  else if (TREE_CODE (class_or_name) == TREE_LIST)
+    name = TYPE_NAME (TREE_PURPOSE (class_or_name));
+  /* Or it's a type in the making */
+  else
+    name = DECL_NAME (TYPE_NAME (class_or_name));
+
   push_obstacks (&permanent_obstack, &permanent_obstack);
 
   /* Search in current zip first.  */
@@ -494,10 +507,12 @@ load_class (class_or_name, verbose)
   if (current_jcf->java_source)
     jcf_parse_source (current_jcf);
   else {
-    int saved_lineno = lineno;
+    java_parser_context_save_global ();
+    java_push_parser_context ();
     input_filename = current_jcf->filename;
     jcf_parse (current_jcf);
-    lineno = saved_lineno;
+    java_pop_parser_context (0);
+    java_parser_context_restore_global ();
   }
 
   if (!current_jcf->seen_in_zip)
@@ -524,13 +539,16 @@ jcf_parse_source (jcf)
   java_push_parser_context ();
   input_filename = current_jcf->filename;
   file = get_identifier (input_filename);
-  if (!(finput = fopen (input_filename, "r")))
-    fatal ("input file `%s' just disappeared - jcf_parse_source",
-          input_filename);
-  parse_source_file (file);
-  if (fclose (finput))
-    fatal ("can't close input file `%s' stream - jcf_parse_source",
-          input_filename);
+  if (!HAS_BEEN_ALREADY_PARSED_P (file))
+    {
+      if (!(finput = fopen (input_filename, "r")))
+       fatal ("input file `%s' just disappeared - jcf_parse_source",
+              input_filename);
+      parse_source_file (file);
+      if (fclose (finput))
+       fatal ("can't close input file `%s' stream - jcf_parse_source",
+              input_filename);
+    }
   java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file));
   java_parser_context_restore_global ();
 }
@@ -586,6 +604,11 @@ jcf_parse (jcf)
 
   push_obstacks (&permanent_obstack, &permanent_obstack);
   layout_class (current_class);
+  if (current_class == object_type_node)
+    layout_class_methods (object_type_node);
+  else
+    all_class_list = tree_cons (NULL_TREE, 
+                               TYPE_NAME (current_class), all_class_list );
   pop_obstacks ();
 }
 
@@ -612,6 +635,8 @@ parse_class_file ()
   char *save_input_filename = input_filename;
   int save_lineno = lineno;
 
+  LAYOUT_SEEN_CLASS_METHODS ();
+
   input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class));
   lineno = 0;
   debug_start_source_file (input_filename);
index c371096..036f4de 100644 (file)
@@ -2342,7 +2342,8 @@ generate_classfile (clas, state)
   else
     i = 8 + 2 * total_supers;
   ptr = append_chunk (NULL, i, state);
-  i = get_access_flags (TYPE_NAME (clas));  PUT2 (i); /* acces_flags */
+  i = get_access_flags (TYPE_NAME (clas)) | ACC_SUPER;
+  PUT2 (i); /* acces_flags */
   i = find_class_constant (&state->cpool, clas);  PUT2 (i);  /* this_class */
   if (clas == object_type_node)
     {
index d560550..4e646d2 100644 (file)
@@ -358,7 +358,12 @@ put_decl_node (node)
          put_decl_string (".", 1);
        }
 #endif
-      put_decl_node (DECL_NAME (node));
+      if (TREE_CODE (node) == FUNCTION_DECL
+         && DECL_NAME (node) == init_identifier_node
+         && !DECL_ARTIFICIAL (node) && current_class)
+       put_decl_node (TYPE_NAME (current_class));
+      else
+       put_decl_node (DECL_NAME (node));
       if (TREE_CODE (node) == FUNCTION_DECL && TREE_TYPE (node) != NULL_TREE)
        {
          int i = 0;
index 0a632f1..946e574 100644 (file)
@@ -153,12 +153,12 @@ java_allocate_new_line ()
 
   if (!ctxp->c_line)
     {
-      ctxp->c_line = (struct java_line *)malloc (sizeof (struct java_line));
+      ctxp->c_line = (struct java_line *)xmalloc (sizeof (struct java_line));
       ctxp->c_line->max = JAVA_LINE_MAX;
-      ctxp->c_line->line = (unicode_t *)malloc 
-         (sizeof (unicode_t)*ctxp->c_line->max);
+      ctxp->c_line->line = (unicode_t *)xmalloc 
+       (sizeof (unicode_t)*ctxp->c_line->max);
       ctxp->c_line->unicode_escape_p = 
-         (char *)malloc (sizeof (char)*ctxp->c_line->max);
+         (char *)xmalloc (sizeof (char)*ctxp->c_line->max);
       ctxp->c_line->white_space_only = 0;
     }
 
index 5bee4f3..8e147cd 100644 (file)
@@ -4675,7 +4675,7 @@ void
 java_push_parser_context ()
 {
   struct parser_ctxt *new = 
-    (struct parser_ctxt *)malloc(sizeof (struct parser_ctxt));
+    (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
 
   bzero (new, sizeof (struct parser_ctxt));
   new->next = ctxp;
@@ -4716,7 +4716,7 @@ java_parser_context_restore_global ()
   current_class = ctxp->current_class;
   input_filename = ctxp->filename;
   current_function_decl = ctxp->current_function_decl;
-  if (extra_ctxp_pushed_p)
+  if (!ctxp->next && extra_ctxp_pushed_p)
     {
       java_pop_parser_context (0);
       extra_ctxp_pushed_p = 0;
@@ -5175,8 +5175,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
   TREE_CHAIN (decl) = ctxp->class_list;
   ctxp->class_list = decl;
 
-  /* Create a new node in the global list */
+  /* Create a new nodes in the global lists */
   ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list);
+  all_class_list = tree_cons (NULL_TREE, decl, all_class_list);
 
   /* Install a new dependency list element */
   create_jdep_list (ctxp);
@@ -5310,7 +5311,7 @@ create_class (flags, id, super, interfaces)
          super_decl_type = TREE_TYPE (super_decl);
        }
       else
-       super_decl_type = 
+       super_decl_type =
          register_incomplete_type (JDEP_SUPER, super, decl, NULL_TREE);
     }
   else if (TREE_TYPE (decl) != object_type_node)
@@ -5689,8 +5690,7 @@ method_header (flags, type, mdecl, throws)
          tree itype;
          patch_stage = JDEP_METHOD_RETURN;
          itype = register_incomplete_type (patch_stage, type, id, NULL_TREE);
-         TREE_TYPE (meth) = (TREE_CODE (itype) == TREE_LIST ? 
-                             TREE_PURPOSE (itype) : itype);
+         TREE_TYPE (meth) = GET_REAL_TYPE (itype);
        }
     }
   else
@@ -5928,6 +5928,7 @@ method_declarator (id, list)
       tree name = EXPR_WFL_NODE (wfl_name);
       tree already, arg_node;
       tree type_wfl = NULL_TREE;
+      tree real_type;
 
       /* Obtain a suitable type for resolution, if necessary */
       SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain);
@@ -5936,8 +5937,13 @@ method_declarator (id, list)
       type = build_array_from_name (type, type_wfl, name, &name);
       EXPR_WFL_NODE (wfl_name) = name;
 
-      if (TREE_CODE (type) == RECORD_TYPE)
-       type = promote_type (type);
+      real_type = GET_REAL_TYPE (type);
+      if (TREE_CODE (real_type) == RECORD_TYPE)
+       {
+         real_type = promote_type (real_type);
+         if (TREE_CODE (type) == TREE_LIST)
+           TREE_PURPOSE (type) = real_type;
+       }
 
       /* Check redefinition */
       for (already = arg_types; already; already = TREE_CHAIN (already))
@@ -5963,7 +5969,7 @@ method_declarator (id, list)
        }
 
       /* The argument node: a name and a (possibly) incomplete type */
-      arg_node = build_tree_list (name, type);
+      arg_node = build_tree_list (name, real_type);
       if (jdep)
        JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node);
       TREE_CHAIN (arg_node) = arg_types;
@@ -6081,11 +6087,7 @@ static void
 create_jdep_list (ctxp)
      struct parser_ctxt *ctxp;
 {
-  jdeplist *new = malloc (sizeof (jdeplist));  
-  
-  if (!new)
-    fatal ("Can't alloc jdeplist - create_jdep_list");
-    
+  jdeplist *new = (jdeplist *)xmalloc (sizeof (jdeplist));     
   new->first = new->last = NULL;
   new->next = ctxp->classd_list;
   ctxp->classd_list = new;
@@ -6105,14 +6107,22 @@ reverse_jdep_list (ctxp)
   return prev;
 }
 
-/* Create a fake pointer based on the ID stored in the WFL */
+/* Create a fake pointer based on the ID stored in
+   TYPE_NAME. TYPE_NAME can be a WFL or a incomplete type asking to be
+   registered again. */
 
 static tree
-obtain_incomplete_type (wfl)
-     tree wfl;
+obtain_incomplete_type (type_name)
+     tree type_name;
 {
-  tree ptr;
-  tree name = EXPR_WFL_NODE (wfl);
+  tree ptr, name;
+
+  if (TREE_CODE (type_name) == EXPR_WITH_FILE_LOCATION)
+    name = EXPR_WFL_NODE (type_name);
+  else if (INCOMPLETE_TYPE_P (type_name))
+    name = TYPE_NAME (type_name);
+  else
+    fatal ("invalid type name - obtain_incomplete_type");
 
   for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
     if (TYPE_NAME (TREE_PURPOSE (ptr)) == name)
@@ -6143,10 +6153,8 @@ register_incomplete_type (kind, wfl, decl, ptr)
      int kind;
      tree wfl, decl, ptr;
 {
-  jdep *new = malloc (sizeof (jdep));
+  jdep *new = (jdep *)xmalloc (sizeof (jdep));
 
-  if (!new)
-    fatal ("Can't allocate new jdep - register_incomplete_type");
   if (!ptr && kind != JDEP_METHOD_END) /* JDEP_METHOD_END is a mere marker */
     ptr = obtain_incomplete_type (wfl);
 
@@ -6195,6 +6203,10 @@ java_check_circular_reference ()
     }
 }
 
+/* safe_layout_class just makes sure that we can load a class without
+   disrupting the current_class, input_file, lineno, etc, information
+   about the class processed currently.  */
+
 void
 safe_layout_class (class)
      tree class;
@@ -6220,20 +6232,18 @@ jdep_resolve_class (dep)
 {
   tree decl;
 
-  if (!JDEP_RESOLVED_P (dep))
+  if (JDEP_RESOLVED_P (dep))
+    decl = JDEP_RESOLVED_DECL (dep);
+  else
     {
-      decl = 
-       resolve_class (JDEP_TO_RESOLVE (dep), JDEP_DECL (dep), JDEP_WFL (dep));
+      decl = resolve_class (JDEP_TO_RESOLVE (dep), 
+                           JDEP_DECL (dep), JDEP_WFL (dep));
       JDEP_RESOLVED (dep, decl);
     }
-  else
-    decl = JDEP_RESOLVED_DECL (dep);
-
+    
   if (!decl)
-    {
-      complete_class_report_errors (dep);
-      return NULL_TREE;
-    }
+    complete_class_report_errors (dep);
+
   return decl;
 }
 
@@ -6486,7 +6496,8 @@ do_resolve_class (class_type, decl, cl)
 }
 
 /* Resolve NAME and lay it out (if not done and if not the current
-   parsed class). Return a decl node.  */
+   parsed class). Return a decl node. This function is meant to be
+   called when type resolution is necessary during the walk pass.  */
 
 static tree
 resolve_and_layout (something, cl)
@@ -6495,20 +6506,49 @@ resolve_and_layout (something, cl)
 {
   tree decl;
 
-  if (TREE_CODE (something) == POINTER_TYPE)
-    something = TREE_TYPE (something);
+  /* Don't do that on the current class */
+  if (something == current_class)
+    return TYPE_NAME (current_class);
 
+  /* Don't do anything for void and other primitive types */
   if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
     return NULL_TREE;
 
+  /* Pointer types can be reall pointer types or fake pointers. When
+     finding a real pointer, recheck for primitive types */
+  if (TREE_CODE (something) == POINTER_TYPE)
+    {
+      if (TREE_TYPE (something))
+       {
+         something = TREE_TYPE (something);
+         if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
+           return NULL_TREE;
+       }
+      else
+       something = TYPE_NAME (something);
+    }
+
+  /* Don't do anything for arrays of primitive types */
+  if (TREE_CODE (something) == RECORD_TYPE && TYPE_ARRAY_P (something)
+      && JPRIMITIVE_TYPE_P (TYPE_ARRAY_ELEMENT (something)))
+    return NULL_TREE;
+
+  /* If something is not and IDENTIFIER_NODE, it can be a a TYPE_DECL
+     or a real TYPE */
   if (TREE_CODE (something) != IDENTIFIER_NODE)
     something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ?
            DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something));
 
-  decl = resolve_no_layout (something, cl);
-  if (decl && TREE_TYPE (decl) != current_class 
-      && !CLASS_LOADED_P (TREE_TYPE (decl)))
+  if (!(decl = resolve_no_layout (something, cl)))
+    return NULL_TREE;
+
+  /* Resolve and layout if necessary */
+  layout_class_methods (TREE_TYPE (decl));
+  if (CLASS_FROM_SOURCE_P (TREE_TYPE (decl)))
+    CHECK_METHODS (decl);
+  if (TREE_TYPE (decl) != current_class && !CLASS_LOADED_P (TREE_TYPE (decl)))
     safe_layout_class (TREE_TYPE (decl));
+
   return decl;
 }
 
@@ -6528,8 +6568,10 @@ resolve_no_layout (name, cl)
   return decl;
 }
 
-/* Called to report errors. Skip leader '[' in a complex array type
-   description that failed to be resolved. */
+/* Called when reporting errors. Skip leader '[' in a complex array
+   type description that failed to be resolved. Append a matching
+   number of [] at the end of a newly allocated string that contains
+   the type's name part.  */
 
 static char *
 purify_type_name (name)
@@ -6537,6 +6579,7 @@ purify_type_name (name)
 {
   while (*name && *name == '[')
     name++;
+
   return name;
 }
 
@@ -6546,25 +6589,31 @@ static void
 complete_class_report_errors (dep)
      jdep *dep;
 {
+  char *name;
+
+  if (!JDEP_WFL (dep))
+    return;
+
+  name = IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)));
   switch (JDEP_KIND (dep))
     {
     case JDEP_SUPER:
       parse_error_context  
        (JDEP_WFL (dep), "Superclass `%s' of class `%s' not found",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
       break;
     case JDEP_FIELD:
       parse_error_context
        (JDEP_WFL (dep), "Type `%s' not found in declaration of field `%s'",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
       break;
     case JDEP_METHOD:          /* Covers arguments */
       parse_error_context
        (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
         "argument `%s' of method `%s'",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))),
         IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep))));
       break;
@@ -6572,7 +6621,7 @@ complete_class_report_errors (dep)
       parse_error_context
        (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
         "return type of method `%s'", 
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))));
       break;
     case JDEP_INTERFACE:
@@ -6662,8 +6711,11 @@ java_get_real_method_name (method_decl)
   tree method_name = DECL_NAME (method_decl);
   if (DECL_CONSTRUCTOR_P (method_decl))
     return init_identifier_node;
-  else if (ctxp 
-          && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name))
+  /* Don't confuse method only bearing the name of their class as
+     constructors */
+  else if (ctxp && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name)
+          && get_access_flags_from_decl (method_decl) <= ACC_PROTECTED
+          && TREE_TYPE (TREE_TYPE (method_decl)) == void_type_node)
     return init_identifier_node;
   else
     return EXPR_WFL_NODE (method_name);
@@ -6728,7 +6780,8 @@ java_check_regular_methods (class_decl)
   if (class == object_type_node)
     return;
 
-  TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+  if (!TYPE_NVIRTUALS (class))
+    TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
 
   /* Should take interfaces into account. FIXME */
   for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
@@ -6877,11 +6930,15 @@ java_check_regular_methods (class_decl)
   if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
     DECL_NAME (found) = saved_found_wfl;
 
-  TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+  if (!TYPE_NVIRTUALS (class))
+    TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
 
   if (!saw_constructor)
     {
-      /* No constructor seen, we craft one, at line 0 */
+      /* No constructor seen, we craft one, at line 0. Since this
+       operation takes place after we laid methods out
+       (layout_class_methods), we prepare the its DECL
+       appropriately. */
       int flags;
       tree decl;
 
@@ -6893,6 +6950,7 @@ java_check_regular_methods (class_decl)
       decl = create_artificial_method (class, flags, void_type_node, 
                                       init_identifier_node, NULL_TREE);
       DECL_CONSTRUCTOR_P (decl) = 1;
+      layout_class_method (TREE_TYPE (class_decl), NULL_TREE, decl, NULL_TREE);
     }
 }
 
@@ -7013,18 +7071,6 @@ java_check_abstract_methods (interface_decl)
     }
 }
 
-/* Check the method on all the defined classes. Process all the
-   classes that we compiled from source code for this CU.  */
-
-void
-java_check_methods ()
-{
-  tree current;
-  for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
-    if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
-      CHECK_METHODS (TREE_VALUE (current));
-}
-
 /* Lookup methods in interfaces using their name and partial
    signature. Return a matching method only if their types differ.  */
 
@@ -7598,14 +7644,14 @@ source_start_java_method (fndecl)
       tree type = TREE_VALUE (tem);
       tree name = TREE_PURPOSE (tem);
       
-      /* If type is incomplete. Layout can't take place
-        now. Create an incomplete decl and ask for the decl to be
-        patched later */
+      /* If type is incomplete. Create an incomplete decl and ask for
+        the decl to be patched later */
       if (INCOMPLETE_TYPE_P (type))
        {
          jdep *jdep;
          tree real_type = GET_REAL_TYPE (type);
          parm_decl = build_decl (PARM_DECL, name, real_type);
+         type = obtain_incomplete_type (type);
          register_incomplete_type (JDEP_PARM, NULL_TREE, NULL_TREE, type);
          jdep = CLASSD_LAST (ctxp->classd_list);
          JDEP_MISC (jdep) = name;
@@ -7784,18 +7830,27 @@ add_stmt_to_compound (existing, type, stmt)
 /* Hold THIS for the scope of the current public method decl.  */
 static tree current_this;
 
-/* Layout all class found during parsing. Also fixes the order of some
-   lists.  */
+/* Layout the methods of all classes loaded in one way on an
+   other. Check methods of source parsed classes. Then reorder the
+   fields and layout the classes or the type of all source parsed
+   classes */
 
 void
 java_layout_classes ()
 {
   tree current;
 
-  java_check_methods ();
-  /* Error reported by the caller */
-  if (java_error_count)
-    return;
+  /* Layout the methods of all classes seen so far */
+  LAYOUT_SEEN_CLASS_METHODS ();
+  java_parse_abort_on_error ();
+  all_class_list = NULL_TREE;
+
+  /* Then check the methods of all parsed classes */
+  for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
+    if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
+      CHECK_METHODS (TREE_VALUE (current));
+  java_parse_abort_on_error ();
+
   for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
     {
       current_class = TREE_TYPE (TREE_VALUE (current));
@@ -7805,8 +7860,8 @@ java_layout_classes ()
       if (TYPE_FIELDS (current_class) && current_class != object_type_node
          && current_class != class_type_node)
       {
-       /* Always leave the dummy field in front if its already there,
-          and layout the class for proper field offets. */
+       /* If the dummy field is there, reverse the right fields and
+          just layout the type for proper fields offset */
        if (!DECL_NAME (TYPE_FIELDS (current_class)))
          {
            tree fields = TYPE_FIELDS (current_class);
@@ -7814,7 +7869,8 @@ java_layout_classes ()
            TYPE_SIZE (current_class) = NULL_TREE;
            layout_type (current_class);
          }
-       /* It's time to layout the class */
+       /* We don't have a dummy field, we need to layout the class,
+           after having reversed the fields */
        else
          {
            TYPE_FIELDS (current_class) = 
@@ -7823,12 +7879,8 @@ java_layout_classes ()
            layout_class (current_class);
          }
       }
-      
-      /* Do a layout if necessary */
-      if (!TYPE_SIZE (current_class) 
-         || (current_class == object_type_node)
-         || current_class == class_type_node)
-       safe_layout_class (current_class);
+      else
+       layout_class (current_class);
 
       /* From now on, the class is considered completely loaded */
       CLASS_LOADED_P (current_class) = 1;
@@ -7837,6 +7889,12 @@ java_layout_classes ()
       if (java_error_count)
        return;
     }
+
+  /* We might have reloaded classes durign the process of laying out
+     classes for code generation. We must layout the methods of those
+     late additions, as constructor checks might use them */
+  LAYOUT_SEEN_CLASS_METHODS ();
+  java_parse_abort_on_error ();
 }
 
 /* Expand all methods in all registered classes.  */
@@ -8100,9 +8158,8 @@ java_expand_finals ()
 void
 java_expand_classes ()
 {
-  ctxp = ctxp_for_generation;
-  /* If we found error earlier, we don't want to report then twice. */
-  if (java_error_count || !ctxp)
+  java_parse_abort_on_error ();
+  if (!(ctxp = ctxp_for_generation))
     return;
   java_layout_classes ();
   java_parse_abort_on_error ();
@@ -8996,7 +9053,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl, super)
          /* Class to search is NULL if we're searching the current one */
          if (class_to_search)
            {
-             class_to_search = resolve_no_layout (class_to_search, NULL_TREE);
+             class_to_search = resolve_and_layout (class_to_search, 
+                                                   NULL_TREE);
              if (!class_to_search)
                {
                  parse_error_context 
@@ -9817,6 +9875,7 @@ java_complete_tree (node)
       TREE_OPERAND (node, 0) = cn;
       TREE_TYPE (node) = void_type_node;
       CAN_COMPLETE_NORMALLY (node) = 1;
+      TREE_SIDE_EFFECTS (node) = 1;
       break;
 
     case DEFAULT_EXPR:
@@ -9832,6 +9891,7 @@ java_complete_tree (node)
       else
        SWITCH_HAS_DEFAULT (nn) = 1;
       TREE_TYPE (node) = void_type_node;
+      TREE_SIDE_EFFECTS (node) = 1;
       CAN_COMPLETE_NORMALLY (node) = 1;
       break;
 
index b2b0644..b73b8db 100644 (file)
@@ -147,10 +147,10 @@ extern tree stabilize_reference PROTO ((tree));
     TYPE_NAME (ptr) = name;                    \
   }
 
-#define INCOMPLETE_TYPE_P(NODE)                                        \
-  ((TREE_CODE (NODE) == TREE_LIST)                             \
-   && (TREE_CODE (TREE_PURPOSE (NODE)) == POINTER_TYPE)        \
-   && (TREE_TYPE (TREE_PURPOSE (NODE)) == NULL_TREE))
+#define INCOMPLETE_TYPE_P(NODE)                                \
+  ((TREE_CODE (NODE) == POINTER_TYPE)                  \
+   && !TREE_TYPE (NODE)                                \
+   && TREE_CODE (TYPE_NAME (NODE)) == IDENTIFIER_NODE)
 
 /* Set the EMIT_LINE_NOTE flag of a EXPR_WLF to 1 if debug information
    are requested. Works in the context of a parser rule. */
@@ -589,13 +589,13 @@ struct parser_ctxt {
   int parser_ccb_indent;            /* Keep track of {} indent, parser */
   int osb_number;                   /* Keep track of ['s */
   int minus_seen;                   /* Integral literal overflow */
-  int lineno;                      /* Current lineno */
-  int java_error_flag;             /* Report error when true */
+  int lineno;                       /* Current lineno */
+  int java_error_flag;              /* Report error when true */
   int deprecated;                   /* @deprecated tag seen */
 
   /* This section is defined only if we compile jc1 */
 #ifndef JC1_LITE
-  tree modifier_ctx [11];           /* WFL of modifiers */
+  tree modifier_ctx [11];          /* WFL of modifiers */
   tree current_class;              /* Current class */
   tree current_function_decl;      /* Current function decl, save/restore */
 
@@ -609,30 +609,34 @@ struct parser_ctxt {
 
   tree package;                            /* Defined package ID */
 
+  /* Those tow list are saved accross file traversal */
   tree  incomplete_class;          /* List of non-complete classes */
-  tree  current_parsed_class;      /* Class currently parsed */
-  tree  current_parsed_class_un;    /* Curr. parsed class unqualified name */
+  tree  gclass_list;               /* All classes seen from source code */
+
+  /* These two lists won't survive file traversal */
   tree  class_list;                /* List of classes in a CU */
-  tree  gclass_list;               /* All classes seen so far. */
   jdeplist *classd_list;           /* Classe dependencies in a CU */
   
+  tree  current_parsed_class;      /* Class currently parsed */
+  tree  current_parsed_class_un;    /* Curr. parsed class unqualified name */
+
   tree non_static_initialized;     /* List of non static initialized fields */
   tree static_initialized;         /* List of static non final initialized */
 
   tree import_list;                /* List of import */
   tree import_demand_list;         /* List of import on demand */
 
-  tree current_loop;                /* List of the currently nested loops/switches */
-  tree current_labeled_block;       /* List of currently nested
-                                       labeled blocks. */
+  tree current_loop;               /* List of the currently nested 
+                                      loops/switches */
+  tree current_labeled_block;      /* List of currently nested
+                                      labeled blocks. */
 
-  int pending_block;                /* Pending block to close */
+  int pending_block;               /* Pending block to close */
 
-  int explicit_constructor_p;       /* True when processing an
-                                       explicit constructor. This flag is 
-                                       used to trap illegal argument usage 
-                                       during an explicit constructor
-                                       invocation. */
+  int explicit_constructor_p;      /* True when processing an explicit
+                                      constructor. This flag is used to trap
+                                      illegal argument usage during an
+                                      explicit constructor invocation. */
 #endif /* JC1_LITE */
 };
 
@@ -803,7 +807,6 @@ void safe_layout_class PROTO ((tree));
 void java_complete_class PROTO ((void));
 void java_check_circular_reference PROTO ((void));
 void java_check_final PROTO ((void));
-void java_check_methods PROTO ((void));
 void java_layout_classes PROTO ((void));
 tree java_method_add_stmt PROTO ((tree, tree));
 char *java_get_line_col PROTO ((char *, int, int));
index d59210b..be09d72 100644 (file)
@@ -2070,7 +2070,7 @@ void
 java_push_parser_context ()
 {
   struct parser_ctxt *new = 
-    (struct parser_ctxt *)malloc(sizeof (struct parser_ctxt));
+    (struct parser_ctxt *)xmalloc(sizeof (struct parser_ctxt));
 
   bzero (new, sizeof (struct parser_ctxt));
   new->next = ctxp;
@@ -2111,7 +2111,7 @@ java_parser_context_restore_global ()
   current_class = ctxp->current_class;
   input_filename = ctxp->filename;
   current_function_decl = ctxp->current_function_decl;
-  if (extra_ctxp_pushed_p)
+  if (!ctxp->next && extra_ctxp_pushed_p)
     {
       java_pop_parser_context (0);
       extra_ctxp_pushed_p = 0;
@@ -2570,8 +2570,9 @@ maybe_create_class_interface_decl (decl, qualified_name, cl)
   TREE_CHAIN (decl) = ctxp->class_list;
   ctxp->class_list = decl;
 
-  /* Create a new node in the global list */
+  /* Create a new nodes in the global lists */
   ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list);
+  all_class_list = tree_cons (NULL_TREE, decl, all_class_list);
 
   /* Install a new dependency list element */
   create_jdep_list (ctxp);
@@ -3084,8 +3085,7 @@ method_header (flags, type, mdecl, throws)
          tree itype;
          patch_stage = JDEP_METHOD_RETURN;
          itype = register_incomplete_type (patch_stage, type, id, NULL_TREE);
-         TREE_TYPE (meth) = (TREE_CODE (itype) == TREE_LIST ? 
-                             TREE_PURPOSE (itype) : itype);
+         TREE_TYPE (meth) = GET_REAL_TYPE (itype);
        }
     }
   else
@@ -3323,6 +3323,7 @@ method_declarator (id, list)
       tree name = EXPR_WFL_NODE (wfl_name);
       tree already, arg_node;
       tree type_wfl = NULL_TREE;
+      tree real_type;
 
       /* Obtain a suitable type for resolution, if necessary */
       SET_TYPE_FOR_RESOLUTION (type, type_wfl, must_chain);
@@ -3331,8 +3332,13 @@ method_declarator (id, list)
       type = build_array_from_name (type, type_wfl, name, &name);
       EXPR_WFL_NODE (wfl_name) = name;
 
-      if (TREE_CODE (type) == RECORD_TYPE)
-       type = promote_type (type);
+      real_type = GET_REAL_TYPE (type);
+      if (TREE_CODE (real_type) == RECORD_TYPE)
+       {
+         real_type = promote_type (real_type);
+         if (TREE_CODE (type) == TREE_LIST)
+           TREE_PURPOSE (type) = real_type;
+       }
 
       /* Check redefinition */
       for (already = arg_types; already; already = TREE_CHAIN (already))
@@ -3358,7 +3364,7 @@ method_declarator (id, list)
        }
 
       /* The argument node: a name and a (possibly) incomplete type */
-      arg_node = build_tree_list (name, type);
+      arg_node = build_tree_list (name, real_type);
       if (jdep)
        JDEP_GET_PATCH (jdep) = &TREE_VALUE (arg_node);
       TREE_CHAIN (arg_node) = arg_types;
@@ -3476,11 +3482,7 @@ static void
 create_jdep_list (ctxp)
      struct parser_ctxt *ctxp;
 {
-  jdeplist *new = malloc (sizeof (jdeplist));  
-  
-  if (!new)
-    fatal ("Can't alloc jdeplist - create_jdep_list");
-    
+  jdeplist *new = (jdeplist *)xmalloc (sizeof (jdeplist));     
   new->first = new->last = NULL;
   new->next = ctxp->classd_list;
   ctxp->classd_list = new;
@@ -3500,14 +3502,22 @@ reverse_jdep_list (ctxp)
   return prev;
 }
 
-/* Create a fake pointer based on the ID stored in the WFL */
+/* Create a fake pointer based on the ID stored in
+   TYPE_NAME. TYPE_NAME can be a WFL or a incomplete type asking to be
+   registered again. */
 
 static tree
-obtain_incomplete_type (wfl)
-     tree wfl;
+obtain_incomplete_type (type_name)
+     tree type_name;
 {
-  tree ptr;
-  tree name = EXPR_WFL_NODE (wfl);
+  tree ptr, name;
+
+  if (TREE_CODE (type_name) == EXPR_WITH_FILE_LOCATION)
+    name = EXPR_WFL_NODE (type_name);
+  else if (INCOMPLETE_TYPE_P (type_name))
+    name = TYPE_NAME (type_name);
+  else
+    fatal ("invalid type name - obtain_incomplete_type");
 
   for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr))
     if (TYPE_NAME (TREE_PURPOSE (ptr)) == name)
@@ -3538,10 +3548,8 @@ register_incomplete_type (kind, wfl, decl, ptr)
      int kind;
      tree wfl, decl, ptr;
 {
-  jdep *new = malloc (sizeof (jdep));
+  jdep *new = (jdep *)xmalloc (sizeof (jdep));
 
-  if (!new)
-    fatal ("Can't allocate new jdep - register_incomplete_type");
   if (!ptr && kind != JDEP_METHOD_END) /* JDEP_METHOD_END is a mere marker */
     ptr = obtain_incomplete_type (wfl);
 
@@ -3590,6 +3598,10 @@ java_check_circular_reference ()
     }
 }
 
+/* safe_layout_class just makes sure that we can load a class without
+   disrupting the current_class, input_file, lineno, etc, information
+   about the class processed currently.  */
+
 void
 safe_layout_class (class)
      tree class;
@@ -3615,20 +3627,18 @@ jdep_resolve_class (dep)
 {
   tree decl;
 
-  if (!JDEP_RESOLVED_P (dep))
+  if (JDEP_RESOLVED_P (dep))
+    decl = JDEP_RESOLVED_DECL (dep);
+  else
     {
-      decl = 
-       resolve_class (JDEP_TO_RESOLVE (dep), JDEP_DECL (dep), JDEP_WFL (dep));
+      decl = resolve_class (JDEP_TO_RESOLVE (dep), 
+                           JDEP_DECL (dep), JDEP_WFL (dep));
       JDEP_RESOLVED (dep, decl);
     }
-  else
-    decl = JDEP_RESOLVED_DECL (dep);
-
+    
   if (!decl)
-    {
-      complete_class_report_errors (dep);
-      return NULL_TREE;
-    }
+    complete_class_report_errors (dep);
+
   return decl;
 }
 
@@ -3881,7 +3891,8 @@ do_resolve_class (class_type, decl, cl)
 }
 
 /* Resolve NAME and lay it out (if not done and if not the current
-   parsed class). Return a decl node.  */
+   parsed class). Return a decl node. This function is meant to be
+   called when type resolution is necessary during the walk pass.  */
 
 static tree
 resolve_and_layout (something, cl)
@@ -3890,20 +3901,49 @@ resolve_and_layout (something, cl)
 {
   tree decl;
 
-  if (TREE_CODE (something) == POINTER_TYPE)
-    something = TREE_TYPE (something);
+  /* Don't do that on the current class */
+  if (something == current_class)
+    return TYPE_NAME (current_class);
 
+  /* Don't do anything for void and other primitive types */
   if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
     return NULL_TREE;
 
+  /* Pointer types can be reall pointer types or fake pointers. When
+     finding a real pointer, recheck for primitive types */
+  if (TREE_CODE (something) == POINTER_TYPE)
+    {
+      if (TREE_TYPE (something))
+       {
+         something = TREE_TYPE (something);
+         if (JPRIMITIVE_TYPE_P (something) || something == void_type_node)
+           return NULL_TREE;
+       }
+      else
+       something = TYPE_NAME (something);
+    }
+
+  /* Don't do anything for arrays of primitive types */
+  if (TREE_CODE (something) == RECORD_TYPE && TYPE_ARRAY_P (something)
+      && JPRIMITIVE_TYPE_P (TYPE_ARRAY_ELEMENT (something)))
+    return NULL_TREE;
+
+  /* If something is not and IDENTIFIER_NODE, it can be a a TYPE_DECL
+     or a real TYPE */
   if (TREE_CODE (something) != IDENTIFIER_NODE)
     something = (TREE_CODE (TYPE_NAME (something)) == TYPE_DECL ?
            DECL_NAME (TYPE_NAME (something)) : TYPE_NAME (something));
 
-  decl = resolve_no_layout (something, cl);
-  if (decl && TREE_TYPE (decl) != current_class 
-      && !CLASS_LOADED_P (TREE_TYPE (decl)))
+  if (!(decl = resolve_no_layout (something, cl)))
+    return NULL_TREE;
+
+  /* Resolve and layout if necessary */
+  layout_class_methods (TREE_TYPE (decl));
+  if (CLASS_FROM_SOURCE_P (TREE_TYPE (decl)))
+    CHECK_METHODS (decl);
+  if (TREE_TYPE (decl) != current_class && !CLASS_LOADED_P (TREE_TYPE (decl)))
     safe_layout_class (TREE_TYPE (decl));
+
   return decl;
 }
 
@@ -3923,8 +3963,8 @@ resolve_no_layout (name, cl)
   return decl;
 }
 
-/* Called to report errors. Skip leader '[' in a complex array type
-   description that failed to be resolved. */
+/* Called when reporting errors. Skip leader '[' in a complex array
+   type description that failed to be resolved.  */
 
 static char *
 purify_type_name (name)
@@ -3941,25 +3981,31 @@ static void
 complete_class_report_errors (dep)
      jdep *dep;
 {
+  char *name;
+
+  if (!JDEP_WFL (dep))
+    return;
+
+  name = IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep)));
   switch (JDEP_KIND (dep))
     {
     case JDEP_SUPER:
       parse_error_context  
        (JDEP_WFL (dep), "Superclass `%s' of class `%s' not found",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
       break;
     case JDEP_FIELD:
       parse_error_context
        (JDEP_WFL (dep), "Type `%s' not found in declaration of field `%s'",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (DECL_NAME (JDEP_DECL (dep))));
       break;
     case JDEP_METHOD:          /* Covers arguments */
       parse_error_context
        (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
         "argument `%s' of method `%s'",
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))),
         IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_MISC (dep))));
       break;
@@ -3967,7 +4013,7 @@ complete_class_report_errors (dep)
       parse_error_context
        (JDEP_WFL (dep), "Type `%s' not found in the declaration of the "
         "return type of method `%s'", 
-        IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_WFL (dep))),
+        purify_type_name (name),
         IDENTIFIER_POINTER (EXPR_WFL_NODE (JDEP_DECL_WFL (dep))));
       break;
     case JDEP_INTERFACE:
@@ -4057,8 +4103,11 @@ java_get_real_method_name (method_decl)
   tree method_name = DECL_NAME (method_decl);
   if (DECL_CONSTRUCTOR_P (method_decl))
     return init_identifier_node;
-  else if (ctxp 
-          && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name))
+  /* Don't confuse method only bearing the name of their class as
+     constructors */
+  else if (ctxp && ctxp->current_parsed_class_un == EXPR_WFL_NODE (method_name)
+          && get_access_flags_from_decl (method_decl) <= ACC_PROTECTED
+          && TREE_TYPE (TREE_TYPE (method_decl)) == void_type_node)
     return init_identifier_node;
   else
     return EXPR_WFL_NODE (method_name);
@@ -4123,7 +4172,8 @@ java_check_regular_methods (class_decl)
   if (class == object_type_node)
     return;
 
-  TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+  if (!TYPE_NVIRTUALS (class))
+    TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
 
   /* Should take interfaces into account. FIXME */
   for (method = TYPE_METHODS (class); method; method = TREE_CHAIN (method))
@@ -4272,11 +4322,15 @@ java_check_regular_methods (class_decl)
   if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl)
     DECL_NAME (found) = saved_found_wfl;
 
-  TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
+  if (!TYPE_NVIRTUALS (class))
+    TYPE_METHODS (class) = nreverse (TYPE_METHODS (class));
 
   if (!saw_constructor)
     {
-      /* No constructor seen, we craft one, at line 0 */
+      /* No constructor seen, we craft one, at line 0. Since this
+       operation takes place after we laid methods out
+       (layout_class_methods), we prepare the its DECL
+       appropriately. */
       int flags;
       tree decl;
 
@@ -4288,6 +4342,7 @@ java_check_regular_methods (class_decl)
       decl = create_artificial_method (class, flags, void_type_node, 
                                       init_identifier_node, NULL_TREE);
       DECL_CONSTRUCTOR_P (decl) = 1;
+      layout_class_method (TREE_TYPE (class_decl), NULL_TREE, decl, NULL_TREE);
     }
 }
 
@@ -4408,18 +4463,6 @@ java_check_abstract_methods (interface_decl)
     }
 }
 
-/* Check the method on all the defined classes. Process all the
-   classes that we compiled from source code for this CU.  */
-
-void
-java_check_methods ()
-{
-  tree current;
-  for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
-    if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
-      CHECK_METHODS (TREE_VALUE (current));
-}
-
 /* Lookup methods in interfaces using their name and partial
    signature. Return a matching method only if their types differ.  */
 
@@ -4993,14 +5036,14 @@ source_start_java_method (fndecl)
       tree type = TREE_VALUE (tem);
       tree name = TREE_PURPOSE (tem);
       
-      /* If type is incomplete. Layout can't take place
-        now. Create an incomplete decl and ask for the decl to be
-        patched later */
+      /* If type is incomplete. Create an incomplete decl and ask for
+        the decl to be patched later */
       if (INCOMPLETE_TYPE_P (type))
        {
          jdep *jdep;
          tree real_type = GET_REAL_TYPE (type);
          parm_decl = build_decl (PARM_DECL, name, real_type);
+         type = obtain_incomplete_type (type);
          register_incomplete_type (JDEP_PARM, NULL_TREE, NULL_TREE, type);
          jdep = CLASSD_LAST (ctxp->classd_list);
          JDEP_MISC (jdep) = name;
@@ -5179,18 +5222,27 @@ add_stmt_to_compound (existing, type, stmt)
 /* Hold THIS for the scope of the current public method decl.  */
 static tree current_this;
 
-/* Layout all class found during parsing. Also fixes the order of some
-   lists.  */
+/* Layout the methods of all classes loaded in one way on an
+   other. Check methods of source parsed classes. Then reorder the
+   fields and layout the classes or the type of all source parsed
+   classes */
 
 void
 java_layout_classes ()
 {
   tree current;
 
-  java_check_methods ();
-  /* Error reported by the caller */
-  if (java_error_count)
-    return;
+  /* Layout the methods of all classes seen so far */
+  LAYOUT_SEEN_CLASS_METHODS ();
+  java_parse_abort_on_error ();
+  all_class_list = NULL_TREE;
+
+  /* Then check the methods of all parsed classes */
+  for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
+    if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current))))
+      CHECK_METHODS (TREE_VALUE (current));
+  java_parse_abort_on_error ();
+
   for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current))
     {
       current_class = TREE_TYPE (TREE_VALUE (current));
@@ -5200,8 +5252,8 @@ java_layout_classes ()
       if (TYPE_FIELDS (current_class) && current_class != object_type_node
          && current_class != class_type_node)
       {
-       /* Always leave the dummy field in front if its already there,
-          and layout the class for proper field offets. */
+       /* If the dummy field is there, reverse the right fields and
+          just layout the type for proper fields offset */
        if (!DECL_NAME (TYPE_FIELDS (current_class)))
          {
            tree fields = TYPE_FIELDS (current_class);
@@ -5209,7 +5261,8 @@ java_layout_classes ()
            TYPE_SIZE (current_class) = NULL_TREE;
            layout_type (current_class);
          }
-       /* It's time to layout the class */
+       /* We don't have a dummy field, we need to layout the class,
+           after having reversed the fields */
        else
          {
            TYPE_FIELDS (current_class) = 
@@ -5218,12 +5271,8 @@ java_layout_classes ()
            layout_class (current_class);
          }
       }
-      
-      /* Do a layout if necessary */
-      if (!TYPE_SIZE (current_class) 
-         || (current_class == object_type_node)
-         || current_class == class_type_node)
-       safe_layout_class (current_class);
+      else
+       layout_class (current_class);
 
       /* From now on, the class is considered completely loaded */
       CLASS_LOADED_P (current_class) = 1;
@@ -5232,6 +5281,12 @@ java_layout_classes ()
       if (java_error_count)
        return;
     }
+
+  /* We might have reloaded classes durign the process of laying out
+     classes for code generation. We must layout the methods of those
+     late additions, as constructor checks might use them */
+  LAYOUT_SEEN_CLASS_METHODS ();
+  java_parse_abort_on_error ();
 }
 
 /* Expand all methods in all registered classes.  */
@@ -5495,9 +5550,8 @@ java_expand_finals ()
 void
 java_expand_classes ()
 {
-  ctxp = ctxp_for_generation;
-  /* If we found error earlier, we don't want to report then twice. */
-  if (java_error_count || !ctxp)
+  java_parse_abort_on_error ();
+  if (!(ctxp = ctxp_for_generation))
     return;
   java_layout_classes ();
   java_parse_abort_on_error ();
@@ -6391,7 +6445,8 @@ patch_method_invocation (patch, primary, where, is_static, ret_decl, super)
          /* Class to search is NULL if we're searching the current one */
          if (class_to_search)
            {
-             class_to_search = resolve_no_layout (class_to_search, NULL_TREE);
+             class_to_search = resolve_and_layout (class_to_search, 
+                                                   NULL_TREE);
              if (!class_to_search)
                {
                  parse_error_context