OSDN Git Service

PR optimization/4382
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
index 2e02b7c..3a5de01 100644 (file)
@@ -1,22 +1,22 @@
 /* Implement classes and message passing for Objective C.
-   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
-   Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
+   2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Steve Naroff.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
+along with GCC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
@@ -41,11 +41,12 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "expr.h"
 #include "c-tree.h"
-#include "c-lex.h"
 #include "c-common.h"
 #include "flags.h"
 #include "objc-act.h"
@@ -55,12 +56,10 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "toplev.h"
 #include "ggc.h"
-#include "cpplib.h"
+#include "varray.h"
 #include "debug.h"
 #include "target.h"
-#include "varray.h"
-#include "langhooks.h"
-#include "langhooks-def.h"
+#include "diagnostic.h"
 
 /* This is the default way of generating a method name.  */
 /* I am not sure it is really correct.
@@ -89,48 +88,11 @@ Boston, MA 02111-1307, USA.  */
 #define OBJC_FORWARDING_MIN_OFFSET 0
 #endif
 \f
-/* Define the special tree codes that we use.  */
-
-/* Table indexed by tree code giving a string containing a character
-   classifying the tree code.  */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-static const char objc_tree_code_type[] = {
-  'x',
-#include "objc-tree.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
-   operands beyond the fixed part of the node structure.
-   Not used for types or decls.  */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-static const int objc_tree_code_length[] = {
-  0,
-#include "objc-tree.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
-   Used for printing out the tree and error messages.  */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-static const char * const objc_tree_code_name[] = {
-  "@@dummy",
-#include "objc-tree.def"
-};
-#undef DEFTREECODE
 \f
 /* Set up for use of obstacks.  */
 
 #include "obstack.h"
 
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
 /* This obstack is used to accumulate the encoding of a data type.  */
 static struct obstack util_obstack;
 /* This points to the beginning of obstack contents,
@@ -157,10 +119,6 @@ char *util_firstobj;
 
 static void init_objc                          PARAMS ((void));
 static void finish_objc                                PARAMS ((void));
-static const char *objc_init                   PARAMS ((const char *));
-static void objc_init_options                  PARAMS ((void));
-static int objc_decode_option                  PARAMS ((int, char **));
-static void objc_post_options                  PARAMS ((void));
 
 /* Code generation.  */
 
@@ -173,7 +131,6 @@ static tree build_objc_method_call          PARAMS ((int, tree, tree,
 static void generate_strings                   PARAMS ((void));
 static tree get_proto_encoding                         PARAMS ((tree));
 static void build_selector_translation_table   PARAMS ((void));
-static tree build_ivar_chain                   PARAMS ((tree, int));
 
 static tree objc_add_static_instance           PARAMS ((tree, tree));
 
@@ -206,7 +163,6 @@ static int check_methods_accessible         PARAMS ((tree, tree,
 static void encode_aggregate_within            PARAMS ((tree, int, int,
                                                       int, int));
 static const char *objc_demangle               PARAMS ((const char *));
-static const char *objc_printable_name         PARAMS ((tree, int));
 static void objc_expand_function_end            PARAMS ((void));
 
 /* Hash tables to manage the global pool of method prototypes.  */
@@ -214,6 +170,7 @@ static void objc_expand_function_end            PARAMS ((void));
 hash *nst_method_hash_list = 0;
 hash *cls_method_hash_list = 0;
 
+static size_t hash_func                                PARAMS ((tree));
 static void hash_init                          PARAMS ((void));
 static void hash_enter                         PARAMS ((hash *, tree));
 static hash hash_lookup                                PARAMS ((hash *, tree));
@@ -282,6 +239,7 @@ static tree lookup_protocol_in_reflist              PARAMS ((tree, tree));
 static tree create_builtin_decl                        PARAMS ((enum tree_code,
                                                       tree, const char *));
 static void setup_string_decl                  PARAMS ((void));
+static void build_string_class_template                PARAMS ((void));
 static tree my_build_string                    PARAMS ((int, const char *));
 static void build_objc_symtab_template         PARAMS ((void));
 static tree init_def_list                      PARAMS ((tree));
@@ -293,7 +251,6 @@ static tree build_typed_selector_reference          PARAMS ((tree, tree));
 static tree build_selector_reference           PARAMS ((tree));
 static tree build_class_reference_decl         PARAMS ((void));
 static void add_class_reference                        PARAMS ((tree));
-static tree objc_copy_list                     PARAMS ((tree, tree *));
 static tree build_protocol_template            PARAMS ((void));
 static tree build_descriptor_table_initializer PARAMS ((tree, tree));
 static tree build_method_prototype_list_template PARAMS ((tree, int));
@@ -336,9 +293,7 @@ static void generate_classref_translation_entry     PARAMS ((tree));
 static void handle_class_ref                   PARAMS ((tree));
 static void generate_struct_by_value_array     PARAMS ((void))
      ATTRIBUTE_NORETURN;
-static void objc_act_parse_init                        PARAMS ((void));
-static void ggc_mark_imp_list                  PARAMS ((void *));
-static void ggc_mark_hash_table                        PARAMS ((void *));
+static void encode_complete_bitfield           PARAMS ((int, tree, int));
 
 /*** Private Interface (data) ***/
 
@@ -357,40 +312,30 @@ static void ggc_mark_hash_table                   PARAMS ((void *));
 #define UTAG_METHOD_LIST       "_objc_method_list"
 #define UTAG_CATEGORY          "_objc_category"
 #define UTAG_MODULE            "_objc_module"
-#define UTAG_STATICS           "_objc_statics"
 #define UTAG_SYMTAB            "_objc_symtab"
 #define UTAG_SUPER             "_objc_super"
 #define UTAG_SELECTOR          "_objc_selector"
 
 #define UTAG_PROTOCOL          "_objc_protocol"
-#define UTAG_PROTOCOL_LIST     "_objc_protocol_list"
 #define UTAG_METHOD_PROTOTYPE  "_objc_method_prototype"
 #define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
 
-#ifdef NEXT_OBJC_RUNTIME
-#define STRING_OBJECT_CLASS_NAME "NSConstantString"
-#else
-#define STRING_OBJECT_CLASS_NAME "NXConstantString"
-#endif
 /* Note that the string object global name is only needed for the
    NeXT runtime.  */
 #define STRING_OBJECT_GLOBAL_NAME "_NSConstantStringClassReference"
 
 #define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
 
-static const char *constant_string_class_name = NULL;
-
 static const char *TAG_GETCLASS;
 static const char *TAG_GETMETACLASS;
 static const char *TAG_MSGSEND;
 static const char *TAG_MSGSENDSUPER;
 static const char *TAG_EXECCLASS;
+static const char *default_constant_string_class_name;
 
-/* The OCTI_... enumeration itself in in objc/objc-act.h.  */
+/* The OCTI_... enumeration itself is in objc/objc-act.h.  */
 tree objc_global_trees[OCTI_MAX];
 
-int objc_receiver_context;
-
 static void handle_impent                      PARAMS ((struct imp_entry *));
 
 struct imp_entry *imp_list = 0;
@@ -411,89 +356,20 @@ extern enum debug_info_type write_symbols;
 
 extern const char *dump_base_name;
 \f
-/* Generate code for GNU or NeXT runtime environment.  */
-
-#ifdef NEXT_OBJC_RUNTIME
-int flag_next_runtime = 1;
-#else
-int flag_next_runtime = 0;
-#endif
-
-int flag_typed_selectors;
-
-/* Open and close the file for outputting class declarations, if requested.  */
-
-int flag_gen_declaration = 0;
+static int flag_typed_selectors;
 
 FILE *gen_declaration_file;
 
-/* Warn if multiple methods are seen for the same selector, but with
-   different argument types.  */
-
-int warn_selector = 0;
-
-/* Warn if methods required by a protocol are not implemented in the 
-   class adopting it.  When turned off, methods inherited to that
-   class are also considered implemented */
-
-int flag_warn_protocol = 1;
-
 /* Tells "encode_pointer/encode_aggregate" whether we are generating
    type descriptors for instance variables (as opposed to methods).
    Type descriptors for instance variables contain more information
-   than methods (for static typing and embedded structures). This
-   was added to support features being planned for dbkit2.  */
+   than methods (for static typing and embedded structures).  */
 
 static int generating_instance_variables = 0;
 
-/* Tells the compiler that this is a special run.  Do not perform
-   any compiling, instead we are to test some platform dependent
-   features and output a C header file with appropriate definitions. */
-
-static int print_struct_values = 0;
-
-#undef LANG_HOOKS_NAME
-#define LANG_HOOKS_NAME "GNU Objective-C"
-#undef LANG_HOOKS_INIT
-#define LANG_HOOKS_INIT objc_init
-#undef LANG_HOOKS_FINISH
-#define LANG_HOOKS_FINISH c_common_finish
-#undef LANG_HOOKS_INIT_OPTIONS
-#define LANG_HOOKS_INIT_OPTIONS objc_init_options
-#undef LANG_HOOKS_DECODE_OPTION
-#define LANG_HOOKS_DECODE_OPTION objc_decode_option
-#undef LANG_HOOKS_POST_OPTIONS
-#define LANG_HOOKS_POST_OPTIONS objc_post_options
-#undef LANG_HOOKS_PRINT_IDENTIFIER
-#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
-#undef LANG_HOOKS_SET_YYDEBUG
-#define LANG_HOOKS_SET_YYDEBUG c_set_yydebug
-/* Inlining hooks same as the C front end.  */
-#undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
-#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
-  c_cannot_inline_tree_fn
-#undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
-#define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
-  c_disregard_inline_limits
-#undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
-#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
-  anon_aggr_type_p
-
-/* Each front end provides its own.  */
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
-
-static varray_type deferred_fns;
-
-/* Post-switch processing.  */
-static void
-objc_post_options ()
-{
-  c_common_post_options ();
-}
-
-/* Some platforms pass small structures through registers versus through
-   an invisible pointer.  Determine at what size structure is the 
-   transition point between the two possibilities. */
+/* Some platforms pass small structures through registers versus
+   through an invisible pointer.  Determine at what size structure is
+   the transition point between the two possibilities.  */
 
 static void
 generate_struct_by_value_array ()
@@ -504,7 +380,7 @@ generate_struct_by_value_array ()
   int aggregate_in_mem[32];
   int found = 0;
 
-  /* Presumably no platform passes 32 byte structures in a register. */
+  /* Presumably no platform passes 32 byte structures in a register.  */
   for (i = 1; i < 32; i++)
     {
       char buffer[5];
@@ -534,7 +410,7 @@ generate_struct_by_value_array ()
     }
  
   /* We found some structures that are returned in registers instead of memory
-     so output the necessary data. */
+     so output the necessary data.  */
   if (found)
     {
       for (i = 31; i >= 0;  i--)
@@ -554,19 +430,13 @@ generate_struct_by_value_array ()
   exit (0);
 }
 
-static void
-objc_init_options ()
-{
-  c_common_init_options (clk_objective_c);
-}
-
-static const char *
+const char *
 objc_init (filename)
      const char *filename;
 {
   filename = c_objc_common_init (filename);
-
-  decl_printable_name = objc_printable_name;
+  if (filename == NULL)
+    return filename;
 
   /* Force the line number back to 0; check_newline will have
      raised it to 1, which will make the builtin functions appear
@@ -590,6 +460,7 @@ objc_init (filename)
       TAG_MSGSEND = "objc_msgSend";
       TAG_MSGSENDSUPER = "objc_msgSendSuper";
       TAG_EXECCLASS = "__objc_execClass";
+      default_constant_string_class_name = "NSConstantString";
     }
   else
     {
@@ -598,6 +469,7 @@ objc_init (filename)
       TAG_MSGSEND = "objc_msg_lookup";
       TAG_MSGSENDSUPER = "objc_msg_lookup_super";
       TAG_EXECCLASS = "__objc_exec_class";
+      default_constant_string_class_name = "NXConstantString";
       flag_typed_selectors = 1;
     }
 
@@ -608,85 +480,22 @@ objc_init (filename)
   if (print_struct_values)
     generate_struct_by_value_array ();
 
-  objc_act_parse_init ();
-
-  VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
-  ggc_add_tree_varray_root (&deferred_fns, 1);
-
   return filename;
 }
 
-/* Register a function tree, so that its optimization and conversion
-   to RTL is only done at the end of the compilation.  */
-
-int
-defer_fn (fn)
-     tree fn;
-{
-  VARRAY_PUSH_TREE (deferred_fns, fn);
-
-  return 1;
-}
-
 void
 finish_file ()
 {
-  int i;
+  c_objc_common_finish_file ();
 
-  for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_fns); i++)
-    /* Don't output the same function twice.  We may run into such
-       situations when an extern inline function is later given a
-       non-extern-inline definition.  */
-    if (! TREE_ASM_WRITTEN (VARRAY_TREE (deferred_fns, i)))
-      c_expand_deferred_function (VARRAY_TREE (deferred_fns, i));
-  VARRAY_FREE (deferred_fns);
-
-  finish_objc ();              /* Objective-C finalization */
+  /* Finalize Objective-C runtime data.  No need to generate tables
+     and code if only checking syntax.  */
+  if (!flag_syntax_only)
+    finish_objc ();
 
   if (gen_declaration_file)
     fclose (gen_declaration_file);
 }
-
-static int
-objc_decode_option (argc, argv)
-     int argc;
-     char **argv;
-{
-  const char *p = argv[0];
-
-  if (!strcmp (p, "-gen-decls"))
-    flag_gen_declaration = 1;
-  else if (!strcmp (p, "-Wselector"))
-    warn_selector = 1;
-  else if (!strcmp (p, "-Wno-selector"))
-    warn_selector = 0;
-  else if (!strcmp (p, "-Wprotocol"))
-    flag_warn_protocol = 1;
-  else if (!strcmp (p, "-Wno-protocol"))
-    flag_warn_protocol = 0;
-  else if (!strcmp (p, "-fgnu-runtime"))
-    flag_next_runtime = 0;
-  else if (!strcmp (p, "-fno-next-runtime"))
-    flag_next_runtime = 0;
-  else if (!strcmp (p, "-fno-gnu-runtime"))
-    flag_next_runtime = 1;
-  else if (!strcmp (p, "-fnext-runtime"))
-    flag_next_runtime = 1;
-  else if (!strcmp (p, "-print-objc-runtime-info"))
-    print_struct_values = 1;
-#define CSTSTRCLASS "-fconstant-string-class="
-  else if (!strncmp (p, CSTSTRCLASS, sizeof(CSTSTRCLASS) - 2)) {
-    if (strlen (argv[0]) <= strlen (CSTSTRCLASS))
-      error ("no class name specified as argument to -fconstant-string-class");
-    constant_string_class_name = xstrdup(argv[0] + sizeof(CSTSTRCLASS) - 1);
-  }
-#undef CSTSTRCLASS
-  else
-    return c_decode_option (argc, argv);
-
-  return 1;
-}
-
 \f
 static tree
 define_decl (declarator, declspecs)
@@ -710,14 +519,6 @@ define_decl (declarator, declspecs)
    `a' and `b' are the same class type, or
    `a' and `b' are of class types A and B such that B is a descendant of A.  */
 
-int
-maybe_objc_comptypes (lhs, rhs, reflexive)
-     tree lhs, rhs;
-     int reflexive;
-{
-  return objc_comptypes (lhs, rhs, reflexive);
-}
-
 static tree
 lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
    tree rproto_list;
@@ -755,44 +556,58 @@ lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
 
 static tree
 lookup_protocol_in_reflist (rproto_list, lproto)
-   tree rproto_list;
-   tree lproto;
+     tree rproto_list;
+     tree lproto;
 {
-   tree rproto, p;
+  tree rproto, p;
 
-   /* Make sure the protocol is supported by the object on the rhs.  */
-   if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
-     {
-       tree fnd = 0;
-       for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
-        {
-          p = TREE_VALUE (rproto);
+  /* Make sure the protocol is supported by the object on the rhs.  */
+  if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE)
+    {
+      tree fnd = 0;
+      for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
+       {
+         p = TREE_VALUE (rproto);
 
-          if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
-            {
-              if (lproto == p)
-                fnd = lproto;
+         if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
+           {
+             if (lproto == p)
+               fnd = lproto;
 
-              else if (PROTOCOL_LIST (p))
-                fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
-            }
+             else if (PROTOCOL_LIST (p))
+               fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto);
+           }
 
-          if (fnd)
-            return fnd;
-        }
-     }
-   else
-     {
-       ; /* An identifier...if we could not find a protocol.  */
-     }
+         if (fnd)
+           return fnd;
+       }
+    }
+  else
+    {
+      ; /* An identifier...if we could not find a protocol.  */
+    }
 
-   return 0;
+  return 0;
 }
 
-/* Return 1 if LHS and RHS are compatible types for assignment
-   or various other operations.  Return 0 if they are incompatible,
-   and return -1 if we choose to not decide.  When the operation
-   is REFLEXIVE, check for compatibility in either direction.  */
+/* Return 1 if LHS and RHS are compatible types for assignment or
+   various other operations.  Return 0 if they are incompatible, and
+   return -1 if we choose to not decide (because the types are really
+   just C types, not ObjC specific ones).  When the operation is
+   REFLEXIVE (typically comparisons), check for compatibility in
+   either direction; when it's not (typically assignments), don't.
+
+   This function is called in two cases: when both lhs and rhs are
+   pointers to records (in which case we check protocols too), and
+   when both lhs and rhs are records (in which case we check class
+   inheritance only).
+
+   Warnings about classes/protocols not implementing a protocol are
+   emitted here (multiple of those warnings might be emitted for a
+   single line!); generic warnings about incompatible assignments and
+   lacks of casts in comparisons are/must be emitted by the caller if
+   we return 0.
+*/
 
 int
 objc_comptypes (lhs, rhs, reflexive)
@@ -802,6 +617,8 @@ objc_comptypes (lhs, rhs, reflexive)
 {
   /* New clause for protocols.  */
 
+  /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE.  We only
+     manage the ObjC ones, and leave the rest to the C code.  */
   if (TREE_CODE (lhs) == POINTER_TYPE
       && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
       && TREE_CODE (rhs) == POINTER_TYPE
@@ -816,29 +633,75 @@ objc_comptypes (lhs, rhs, reflexive)
          tree rproto, rproto_list;
          tree p;
 
+         /* <Protocol> = <Protocol>  */
          if (rhs_is_proto)
            {
              rproto_list = TYPE_PROTOCOL_LIST (rhs);
-
-             /* Make sure the protocol is supported by the object
-                on the rhs.  */
-             for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
+             
+             if (!reflexive)
                {
-                 p = TREE_VALUE (lproto);
-                 rproto = lookup_protocol_in_reflist (rproto_list, p);
+                 /* An assignment between objects of type 'id
+                    <Protocol>'; make sure the protocol on the lhs is
+                    supported by the object on the rhs.  */
+                 for (lproto = lproto_list; lproto; 
+                      lproto = TREE_CHAIN (lproto))
+                   {
+                     p = TREE_VALUE (lproto);
+                     rproto = lookup_protocol_in_reflist (rproto_list, p);
 
-                 if (!rproto)
-                   warning ("object does not conform to the `%s' protocol",
-                            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+                     if (!rproto)
+                       warning 
+                         ("object does not conform to the `%s' protocol",
+                          IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+                   }
+                 return 1;
+               }
+             else
+               {
+                 /* Obscure case - a comparison between two objects
+                    of type 'id <Protocol>'.  Check that either the
+                    protocol on the lhs is supported by the object on
+                    the rhs, or viceversa.  */
+                 
+                 /* Check if the protocol on the lhs is supported by the
+                    object on the rhs.  */
+                 for (lproto = lproto_list; lproto; 
+                      lproto = TREE_CHAIN (lproto))
+                   {
+                     p = TREE_VALUE (lproto);
+                     rproto = lookup_protocol_in_reflist (rproto_list, p);
+                     
+                     if (!rproto)
+                       {
+                         /* Check failed - check if the protocol on the rhs
+                            is supported by the object on the lhs.  */
+                         for (rproto = rproto_list; rproto; 
+                              rproto = TREE_CHAIN (rproto))
+                           {
+                             p = TREE_VALUE (rproto);
+                             lproto = lookup_protocol_in_reflist (lproto_list,
+                                                                  p);
+
+                             if (!lproto)
+                               {
+                                 /* This check failed too: incompatible  */
+                                 return 0;
+                               }
+                           }
+                         return 1;
+                       }
+                   }
+                 return 1;
                }
            }
+         /* <Protocol> = <class> *  */
          else if (TYPED_OBJECT (TREE_TYPE (rhs)))
            {
              tree rname = TYPE_NAME (TREE_TYPE (rhs));
              tree rinter;
 
-             /* Make sure the protocol is supported by the object
-                on the rhs.  */
+             /* Make sure the protocol is supported by the object on
+                the rhs.  */
              for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
                {
                  p = TREE_VALUE (lproto);
@@ -850,13 +713,16 @@ objc_comptypes (lhs, rhs, reflexive)
                      tree cat;
 
                      rproto_list = CLASS_PROTOCOL_LIST (rinter);
-                     /* If the underlying ObjC class does not have
-                        protocols attached to it, perhaps there are
-                        "one-off" protocols attached to the rhs?
-                        E.g., 'id<MyProt> foo;'.  */
-                     if (!rproto_list)
-                       rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
                      rproto = lookup_protocol_in_reflist (rproto_list, p);
+                     /* If the underlying ObjC class does not have
+                        the protocol we're looking for, check for "one-off"
+                        protocols (e.g., `NSObject<MyProt> *foo;') attached
+                        to the rhs.  */
+                     if (!rproto)
+                       {
+                         rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
+                         rproto = lookup_protocol_in_reflist (rproto_list, p);
+                       }
 
                      /* Check for protocols adopted by categories.  */
                      cat = CLASS_CATEGORY_LIST (rinter);
@@ -864,7 +730,6 @@ objc_comptypes (lhs, rhs, reflexive)
                        {
                          rproto_list = CLASS_PROTOCOL_LIST (cat);
                          rproto = lookup_protocol_in_reflist (rproto_list, p);
-
                          cat = CLASS_CATEGORY_LIST (cat);
                        }
 
@@ -873,31 +738,127 @@ objc_comptypes (lhs, rhs, reflexive)
 
                  if (!rproto)
                    warning ("class `%s' does not implement the `%s' protocol",
-                            IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
-                            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+                            IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
+                            IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
                }
+             return 1;
            }
-
-         /* May change...based on whether there was any mismatch */
-          return 1;
+         /* <Protocol> = id */
+         else if (TYPE_NAME (TREE_TYPE (rhs)) == objc_object_id)
+           {
+             return 1;
+           }
+         /* <Protocol> = Class */
+         else if (TYPE_NAME (TREE_TYPE (rhs)) == objc_class_id)
+           {
+             return 0;
+           }
+         /* <Protocol> = ?? : let comptypes decide.  */
+          return -1;
         }
       else if (rhs_is_proto)
-       /* Lhs is not a protocol...warn if it is statically typed */
-       return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
+       {
+         /* <class> * = <Protocol> */
+         if (TYPED_OBJECT (TREE_TYPE (lhs)))
+           {
+             if (reflexive)
+               {
+                 tree rname = TYPE_NAME (TREE_TYPE (lhs));
+                 tree rinter;
+                 tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
+                 
+                 /* Make sure the protocol is supported by the object on
+                    the lhs.  */
+                 for (rproto = rproto_list; rproto; 
+                      rproto = TREE_CHAIN (rproto))
+                   {
+                     tree p = TREE_VALUE (rproto);
+                     tree lproto = 0;
+                     rinter = lookup_interface (rname);
 
+                     while (rinter && !lproto)
+                       {
+                         tree cat;
+
+                         tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
+                         lproto = lookup_protocol_in_reflist (lproto_list, p);
+                         /* If the underlying ObjC class does not
+                            have the protocol we're looking for,
+                            check for "one-off" protocols (e.g.,
+                            `NSObject<MyProt> *foo;') attached to the
+                            lhs.  */
+                         if (!lproto)
+                           {
+                             lproto_list = TYPE_PROTOCOL_LIST 
+                               (TREE_TYPE (lhs));
+                             lproto = lookup_protocol_in_reflist 
+                               (lproto_list, p);
+                           }
+
+                         /* Check for protocols adopted by categories.  */
+                         cat = CLASS_CATEGORY_LIST (rinter);
+                         while (cat && !lproto)
+                           {
+                             lproto_list = CLASS_PROTOCOL_LIST (cat);
+                             lproto = lookup_protocol_in_reflist (lproto_list,
+                                                                  p);
+                             cat = CLASS_CATEGORY_LIST (cat);
+                           }
+                         
+                         rinter = lookup_interface (CLASS_SUPER_NAME 
+                                                    (rinter));
+                       }
+                     
+                     if (!lproto)
+                       warning ("class `%s' does not implement the `%s' protocol",
+                                IDENTIFIER_POINTER (TYPE_NAME 
+                                                    (TREE_TYPE (lhs))),
+                                IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+                   }
+                 return 1;
+               }
+             else
+               return 0;
+           }
+         /* id = <Protocol> */
+         else if (TYPE_NAME (TREE_TYPE (lhs)) == objc_object_id)
+           {
+             return 1;
+           }
+         /* Class = <Protocol> */
+         else if (TYPE_NAME (TREE_TYPE (lhs)) == objc_class_id)
+           {
+             return 0;
+           }
+         /* ??? = <Protocol> : let comptypes decide */
+         else
+           {
+             return -1;
+           }
+       }
       else
-       /* Defer to comptypes.  */
-       return -1;
+       {
+         /* Attention: we shouldn't defer to comptypes here.  One bad
+            side effect would be that we might loose the REFLEXIVE
+            information.
+         */
+         lhs = TREE_TYPE (lhs);
+         rhs = TREE_TYPE (rhs);
+       }
     }
 
-  else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
-    ; /* Fall thru.  This is the case we have been handling all along */
-  else
-    /* Defer to comptypes.  */
-    return -1;
-
-  /* `id' = `<class> *', `<class> *' = `id' */
+  if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
+    {
+      /* Nothing to do with ObjC - let immediately comptypes take
+        responsibility for checking.  */
+      return -1;
+    }
 
+  /* `id' = `<class> *' `<class> *' = `id': always allow it.
+     Please note that 
+     'Object *o = [[Object alloc] init]; falls
+     in the case <class> * = `id'.
+  */
   if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
       || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
     return 1;
@@ -938,7 +899,7 @@ objc_comptypes (lhs, rhs, reflexive)
       return 0;
     }
   else
-    /* Defer to comptypes.  */
+    /* Not an ObjC type - let comptypes do the check.  */
     return -1;
 }
 
@@ -956,13 +917,6 @@ objc_check_decl (decl)
     error_with_decl (decl, "`%s' cannot be statically allocated");
 }
 
-void
-maybe_objc_check_decl (decl)
-     tree decl;
-{
-  objc_check_decl (decl);
-}
-
 /* Implement static typing.  At this point, we know we have an interface.  */
 
 tree
@@ -977,7 +931,6 @@ get_static_reference (interface, protocols)
       tree t, m = TYPE_MAIN_VARIANT (type);
 
       t = copy_node (type);
-      TYPE_BINFO (t) = make_tree_vec (2);
 
       /* Add this type to the chain of variants of TYPE.  */
       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
@@ -1010,12 +963,12 @@ get_object_reference (protocols)
     {
       type = TREE_TYPE (type_decl);
       if (TYPE_MAIN_VARIANT (type) != id_type)
-       warning ("Unexpected type for `id' (%s)",
+       warning ("unexpected type for `id' (%s)",
                 gen_declaration (type, errbuf));
     }
   else
     {
-      error ("Undefined type `id', please import <objc/objc.h>");
+      error ("undefined type `id', please import <objc/objc.h>");
       return error_mark_node;
     }
 
@@ -1028,7 +981,6 @@ get_object_reference (protocols)
       tree t, m = TYPE_MAIN_VARIANT (type);
 
       t = copy_node (type);
-      TYPE_BINFO (t) = make_tree_vec (2);
 
       /* Add this type to the chain of variants of TYPE.  */
       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
@@ -1089,7 +1041,7 @@ lookup_and_install_protocols (protocols)
 
       if (!p)
        {
-         error ("Cannot find protocol declaration for `%s'",
+         error ("cannot find protocol declaration for `%s'",
                 IDENTIFIER_POINTER (ident));
          if (prev)
            TREE_CHAIN (prev) = TREE_CHAIN (proto);
@@ -1205,14 +1157,12 @@ synth_module_prologue ()
       DECL_INLINE (umsg_decl) = 1;
       DECL_ARTIFICIAL (umsg_decl) = 1;
 
-      if (flag_traditional && TAG_MSGSEND[0] != '_')
-       DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
-
       make_decl_rtl (umsg_decl, NULL);
       pushdecl (umsg_decl);
     }
   else
-    umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0);
+    umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN,
+                                 NULL, NULL_TREE);
 
   /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
 
@@ -1223,7 +1173,8 @@ synth_module_prologue ()
                                                 NULL_TREE)));
 
   umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
-                                    temp_type, 0, NOT_BUILT_IN, 0);
+                                     temp_type, 0, NOT_BUILT_IN,
+                                     NULL, NULL_TREE);
 
   /* id objc_getClass (const char *); */
 
@@ -1234,12 +1185,14 @@ synth_module_prologue ()
                                              NULL_TREE)));
 
   objc_get_class_decl
-    = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0);
+    = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
+                       NULL, NULL_TREE);
 
   /* id objc_getMetaClass (const char *); */
 
   objc_get_meta_class_decl
-    = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0);
+    = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN,
+                       NULL, NULL_TREE);
 
   /* static SEL _OBJC_SELECTOR_TABLE[]; */
 
@@ -1250,7 +1203,7 @@ synth_module_prologue ()
          /* Suppress outputting debug symbols, because
             dbxout_init hasn'r been called yet.  */
          enum debug_info_type save_write_symbols = write_symbols;
-         struct gcc_debug_hooks *save_hooks = debug_hooks;
+         const struct gcc_debug_hooks *const save_hooks = debug_hooks;
          write_symbols = NO_DEBUG;
          debug_hooks = &do_nothing_debug_hooks;
 
@@ -1276,12 +1229,40 @@ synth_module_prologue ()
 
   /* Forward declare constant_string_id and constant_string_type.  */
   if (!constant_string_class_name)
-    constant_string_class_name = STRING_OBJECT_CLASS_NAME;
-  
+    constant_string_class_name = default_constant_string_class_name;
+
   constant_string_id = get_identifier (constant_string_class_name);
   constant_string_type = xref_tag (RECORD_TYPE, constant_string_id);
 }
 
+/* Predefine the following data type:
+
+   struct STRING_OBJECT_CLASS_NAME 
+   {
+     Object isa;
+     char *cString;
+     unsigned int length;
+   }; */
+
+static void
+build_string_class_template ()
+{
+  tree field_decl, field_decl_chain;
+
+  field_decl = create_builtin_decl (FIELD_DECL, id_type, "isa");
+  field_decl_chain = field_decl;
+
+  field_decl = create_builtin_decl (FIELD_DECL,
+                                   build_pointer_type (char_type_node),
+                                   "cString");
+  chainon (field_decl_chain, field_decl);
+
+  field_decl = create_builtin_decl (FIELD_DECL, unsigned_type_node, "length");
+  chainon (field_decl_chain, field_decl);
+
+  finish_struct (constant_string_type, field_decl_chain, NULL_TREE);
+}
+
 /* Custom build_string which sets TREE_TYPE!  */
 
 static tree
@@ -1289,21 +1270,7 @@ my_build_string (len, str)
      int len;
      const char *str;
 {
-  int wide_flag = 0;
-  tree a_string = build_string (len, str);
-
-  /* Some code from combine_strings, which is local to c-parse.y.  */
-  if (TREE_TYPE (a_string) == int_array_type_node)
-    wide_flag = 1;
-
-  TREE_TYPE (a_string)
-    = build_array_type (wide_flag ? integer_type_node : char_type_node,
-                       build_index_type (build_int_2 (len - 1, 0)));
-
-  TREE_CONSTANT (a_string) = 1;        /* Puts string in the readonly segment */
-  TREE_STATIC (a_string) = 1;
-
-  return a_string;
+  return fix_string_type (build_string (len, str));
 }
 
 /* Given a chain of STRING_CST's, build a static instance of
@@ -1322,18 +1289,37 @@ build_objc_string_object (strings)
 
   if (lookup_interface (constant_string_id) == NULL_TREE)
     {
-      error ("Cannot find interface declaration for `%s'",
+      error ("cannot find interface declaration for `%s'",
             IDENTIFIER_POINTER (constant_string_id));
       return error_mark_node;
     }
 
   add_class_reference (constant_string_id);
 
-  string = combine_strings (strings);
+  if (TREE_CHAIN (strings))
+    {
+      varray_type vstrings;
+      VARRAY_TREE_INIT (vstrings, 32, "strings");
+
+      for (; strings ; strings = TREE_CHAIN (strings))
+       VARRAY_PUSH_TREE (vstrings, strings);
+
+      string = combine_strings (vstrings);
+    }
+  else
+    string = strings;
+
+  string = fix_string_type (string);
+
   TREE_SET_CODE (string, STRING_CST);
   length = TREE_STRING_LENGTH (string) - 1;
 
-  /* & ((NXConstantString) {0, string, length})  */
+  /* We could not properly create NXConstantString in synth_module_prologue,
+     because that's called before debugging is initialized.  Do it now.  */
+  if (TYPE_FIELDS (constant_string_type) == NULL_TREE)
+    build_string_class_template ();
+
+  /* & ((NXConstantString) { NULL, string, length })  */
 
   if (flag_next_runtime)
     {
@@ -1342,7 +1328,7 @@ build_objc_string_object (strings)
       setup_string_decl ();
       if (string_class_decl == NULL_TREE)
        {
-         error ("Cannot find reference tag for class `%s'",
+         error ("cannot find reference tag for class `%s'",
                 IDENTIFIER_POINTER (constant_string_id));
          return error_mark_node;
        }
@@ -1417,8 +1403,27 @@ static tree
 build_constructor (type, elts)
      tree type, elts;
 {
-  tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
+  tree constructor, f, e;
+
+  /* ??? Most of the places that we build constructors, we don't fill in
+     the type of integers properly.  Convert them all en masse.  */
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      f = TREE_TYPE (type);
+      if (TREE_CODE (f) == POINTER_TYPE || TREE_CODE (f) == INTEGER_TYPE)
+       for (e = elts; e ; e = TREE_CHAIN (e))
+         TREE_VALUE (e) = convert (f, TREE_VALUE (e));
+    }
+  else
+    {
+      f = TYPE_FIELDS (type);
+      for (e = elts; e && f; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
+       if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
+           || TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
+         TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
+    }
 
+  constructor = build (CONSTRUCTOR, type, NULL_TREE, elts);
   TREE_CONSTANT (constructor) = 1;
   TREE_STATIC (constructor) = 1;
   TREE_READONLY (constructor) = 1;
@@ -1582,8 +1587,8 @@ init_objc_symtab (type)
   return build_constructor (type, nreverse (initlist));
 }
 
-/* Push forward-declarations of all the categories
-   so that init_def_list can use them in a CONSTRUCTOR.  */
+/* Push forward-declarations of all the categories so that
+   init_def_list can use them in a CONSTRUCTOR.  */
 
 static void
 forward_declare_categories ()
@@ -1782,6 +1787,9 @@ build_module_descriptor ()
     init_function_decl = current_function_decl;
     TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
     TREE_USED (init_function_decl) = 1;
+    /* Don't let this one be deferred.  */
+    DECL_INLINE (init_function_decl) = 0;
+    DECL_UNINLINABLE (init_function_decl) = 1;
     current_function_cannot_inline
       = "static constructors and destructors cannot be inlined";
 
@@ -1792,7 +1800,7 @@ build_module_descriptor ()
 
     c_expand_expr_stmt (decelerator);
 
-    finish_function (0);
+    finish_function (0, 0);
 
     return XEXP (DECL_RTL (init_function_decl), 0);
   }
@@ -1832,7 +1840,7 @@ get_objc_string_decl (ident, section)
   else
     abort ();
 
-  for (; chain != 0; chain = TREE_VALUE (chain))
+  for (; chain != 0; chain = TREE_CHAIN (chain))
     if (TREE_VALUE (chain) == ident)
       return (TREE_PURPOSE (chain));
 
@@ -2022,6 +2030,32 @@ build_selector_translation_table ()
     {
       tree expr;
 
+      if (warn_selector && objc_implementation_context)
+      {
+        tree method_chain;
+        bool found = false;
+        for (method_chain = meth_var_names_chain;
+             method_chain;
+             method_chain = TREE_CHAIN (method_chain))
+          {
+            if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
+              {
+                found = true;
+                break;
+              }
+          }
+        if (!found)
+          {
+            /* Adjust line number for warning message.  */
+            int save_lineno = lineno;
+            if (flag_next_runtime && TREE_PURPOSE (chain))
+              lineno = DECL_SOURCE_LINE (TREE_PURPOSE (chain));
+            warning ("creating selector for non existant method %s",
+                     IDENTIFIER_POINTER (TREE_VALUE (chain)));
+            lineno = save_lineno;
+          }
+      }
+
       expr = build_selector (TREE_VALUE (chain));
 
       if (flag_next_runtime)
@@ -2105,8 +2139,8 @@ get_proto_encoding (proto)
    identifier_node that represent the selector.  */
 
 static tree
-build_typed_selector_reference (ident, proto)
-     tree ident, proto;
+build_typed_selector_reference (ident, prototype)
+     tree ident, prototype;
 {
   tree *chain = &sel_ref_chain;
   tree expr;
@@ -2114,14 +2148,14 @@ build_typed_selector_reference (ident, proto)
 
   while (*chain)
     {
-      if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
+      if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
        goto return_at_index;
 
       index++;
       chain = &TREE_CHAIN (*chain);
     }
 
-  *chain = tree_cons (proto, ident, NULL_TREE);
+  *chain = tree_cons (prototype, ident, NULL_TREE);
 
  return_at_index:
   expr = build_unary_op (ADDR_EXPR,
@@ -2220,7 +2254,7 @@ add_class_reference (ident)
 
 tree
 get_class_reference (ident)
-    tree ident;
+     tree ident;
 {
   if (flag_next_runtime)
     {
@@ -2330,9 +2364,9 @@ objc_declare_alias (alias_ident, class_ident)
      tree class_ident;
 {
   if (is_class_name (class_ident) != class_ident)
-    warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
+    warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
   else if (is_class_name (alias_ident))
-    warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
+    warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
   else
     alias_chain = tree_cons (class_ident, alias_ident, alias_chain);
 }
@@ -2389,6 +2423,17 @@ is_class_name (ident)
 }
 
 tree
+objc_is_id (ident)
+     tree ident;
+{
+  /* NB: This function may be called before the ObjC front-end
+     has been initialized, in which case ID_TYPE will be NULL. */
+  return (id_type && ident && TYPE_P (ident) && IS_ID (ident)) 
+         ? id_type 
+         : NULL_TREE;
+}
+
+tree
 lookup_interface (ident)
      tree ident;
 {
@@ -2402,51 +2447,23 @@ lookup_interface (ident)
   return NULL_TREE;
 }
 
-static tree
-objc_copy_list (list, head)
-     tree list;
-     tree *head;
-{
-  tree newlist = NULL_TREE, tail = NULL_TREE;
+/* Used by: build_private_template, continue_class,
+   and for @defs constructs.  */
 
-  while (list)
-    {
-      tail = copy_node (list);
-
-      /* The following statement fixes a bug when inheriting instance
-        variables that are declared to be bitfields. finish_struct
-        expects to find the width of the bitfield in DECL_INITIAL.  */
-      if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
-       DECL_INITIAL (tail) = DECL_SIZE (tail);
-
-      newlist = chainon (newlist, tail);
-      list = TREE_CHAIN (list);
-    }
-
-  *head = newlist;
-  return tail;
-}
-
-/* Used by: build_private_template, get_class_ivars, and
-   continue_class.  COPY is 1 when called from @defs.  In this case
-   copy all fields.  Otherwise don't copy leaf ivars since we rely on
-   them being side-effected exactly once by finish_struct.  */
-
-static tree
-build_ivar_chain (interface, copy)
+tree
+get_class_ivars (interface)
      tree interface;
-     int copy;
 {
   tree my_name, super_name, ivar_chain;
 
   my_name = CLASS_NAME (interface);
   super_name = CLASS_SUPER_NAME (interface);
+  ivar_chain = CLASS_IVARS (interface);
 
-  /* Possibly copy leaf ivars.  */
-  if (copy)
-    objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
-  else
-    ivar_chain = CLASS_IVARS (interface);
+  /* Save off a pristine copy of the leaf ivars (i.e, those not
+     inherited from a super class).  */
+  if (!CLASS_OWN_IVARS (interface))
+    CLASS_OWN_IVARS (interface) = copy_list (ivar_chain);
 
   while (super_name)
     {
@@ -2456,28 +2473,28 @@ build_ivar_chain (interface, copy)
       if (!super_interface)
         {
          /* fatal did not work with 2 args...should fix */
-         error ("Cannot find interface declaration for `%s', superclass of `%s'",
+         error ("cannot find interface declaration for `%s', superclass of `%s'",
                 IDENTIFIER_POINTER (super_name),
                 IDENTIFIER_POINTER (my_name));
          exit (FATAL_EXIT_CODE);
         }
 
       if (super_interface == interface)
-       fatal_error ("Circular inheritance in interface declaration for `%s'",
+       fatal_error ("circular inheritance in interface declaration for `%s'",
                     IDENTIFIER_POINTER (super_name));
 
       interface = super_interface;
       my_name = CLASS_NAME (interface);
       super_name = CLASS_SUPER_NAME (interface);
 
-      op1 = CLASS_IVARS (interface);
+      op1 = CLASS_OWN_IVARS (interface);
       if (op1)
         {
-         tree head, tail = objc_copy_list (op1, &head);
+         tree head = copy_list (op1);
 
          /* Prepend super class ivars...make a copy of the list, we
             do not want to alter the original.  */
-         TREE_CHAIN (tail) = ivar_chain;
+         chainon (head, ivar_chain);
          ivar_chain = head;
         }
     }
@@ -2504,7 +2521,7 @@ build_private_template (class)
     {
       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
 
-      ivar_context = build_ivar_chain (class, 0);
+      ivar_context = get_class_ivars (class);
 
       finish_struct (uprivate_record, ivar_context, NULL_TREE);
 
@@ -2845,17 +2862,15 @@ generate_descriptor_table (type, name, size, list, proto)
 }
 
 static void
-generate_method_descriptors (protocol) /* generate_dispatch_tables */
-  tree protocol;
+generate_method_descriptors (protocol)
+     tree protocol;
 {
   tree initlist, chain, method_list_template;
   tree cast, variable_length_type;
   int size;
 
   if (!objc_method_prototype_template)
-    {
-      objc_method_prototype_template = build_method_prototype_template ();
-    }
+    objc_method_prototype_template = build_method_prototype_template ();
 
   cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
                                get_identifier (UTAG_METHOD_PROTOTYPE_LIST))),
@@ -2972,6 +2987,9 @@ hack_method_prototype (nst_methods, tmp_decl)
   /* Usually called from store_parm_decls -> init_function_start.  */
 
   DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
+
+  if (current_function_decl)
+    abort ();
   current_function_decl = tmp_decl;
 
   {
@@ -2995,6 +3013,7 @@ hack_method_prototype (nst_methods, tmp_decl)
   /* install return type */
   TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
 
+  current_function_decl = NULL;
 }
 
 static void
@@ -3020,6 +3039,43 @@ generate_protocol_references (plist)
     }
 }
 
+/* For each protocol which was referenced either from a @protocol()
+   expression, or because a class/category implements it (then a
+   pointer to the protocol is stored in the struct describing the
+   class/category), we create a statically allocated instance of the
+   Protocol class.  The code is written in such a way as to generate
+   as few Protocol objects as possible; we generate a unique Protocol
+   instance for each protocol, and we don't generate a Protocol
+   instance if the protocol is never referenced (either from a
+   @protocol() or from a class/category implementation).  These
+   statically allocated objects can be referred to via the static
+   (that is, private to this module) symbols _OBJC_PROTOCOL_n.
+   
+   The statically allocated Protocol objects that we generate here
+   need to be fixed up at runtime in order to be used: the 'isa'
+  pointer of the objects need to be set up to point to the 'Protocol'
+   class, as known at runtime.
+
+   The NeXT runtime fixes up all protocols at program startup time,
+   before main() is entered.  It uses a low-level trick to look up all
+   those symbols, then loops on them and fixes them up.
+
+   The GNU runtime as well fixes up all protocols before user code
+   from the module is executed; it requires pointers to those symbols
+   to be put in the objc_symtab (which is then passed as argument to
+   the function __objc_exec_class() which the compiler sets up to be
+   executed automatically when the module is loaded); setup of those
+   Protocol objects happen in two ways in the GNU runtime: all
+   Protocol objects referred to by a class or category implementation
+   are fixed up when the class/category is loaded; all Protocol
+   objects referred to by a @protocol() expression are added by the
+   compiler to the list of statically allocated instances to fixup
+   (the same list holding the statically allocated constant string
+   objects).  Because, as explained above, the compiler generates as
+   few Protocol objects as possible, some Protocol object might end up
+   being referenced multiple times when compiled with the GNU runtime,
+   and end up being fixed up multiple times at runtime inizialization.
+   But that doesn't hurt, it's just a little inefficient.  */
 static void
 generate_protocols ()
 {
@@ -3481,9 +3537,9 @@ error_with_ivar (message, decl, rawdecl)
      tree decl;
      tree rawdecl;
 {
-  count_error (0);
+  diagnostic_count_diagnostic (global_dc, DK_ERROR);
 
-  report_error_function (DECL_SOURCE_FILE (decl));
+  diagnostic_report_current_function (global_dc);
 
   error_with_file_and_line (DECL_SOURCE_FILE (decl),
                            DECL_SOURCE_LINE (decl),
@@ -3492,10 +3548,6 @@ error_with_ivar (message, decl, rawdecl)
 
 }
 
-#define USERTYPE(t) \
- (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
-  ||  TREE_CODE (t) == ENUMERAL_TYPE)
-
 static void
 check_ivars (inter, imp)
      tree inter;
@@ -3766,7 +3818,7 @@ build_ivar_list_initializer (type, field_decl)
           ivar);
       obstack_free (&util_obstack, util_firstobj);
 
-      /* Set offset. */
+      /* Set offset.  */
       ivar = tree_cons (NULL_TREE, byte_position (field_decl), ivar);
       initlist = tree_cons (NULL_TREE, 
                            build_constructor (type, nreverse (ivar)),
@@ -3875,6 +3927,11 @@ build_dispatch_table_initializer (type, entries)
                            build_selector (METHOD_SEL_NAME (entries)),
                            NULL_TREE);
 
+      /* Generate the method encoding if we don't have one already.  */
+      if (! METHOD_ENCODING (entries))
+       METHOD_ENCODING (entries) =
+         encode_method_def (METHOD_DEFINITION (entries));
+
       elemlist = tree_cons (NULL_TREE,
                            add_objc_string (METHOD_ENCODING (entries),
                                             meth_var_types),
@@ -4520,6 +4577,10 @@ adjust_type_for_id_default (type)
        chain;
        chain = TREE_CHAIN (chain))
     {
+      if (TYPED_OBJECT (TREE_VALUE (chain))
+          && !(TREE_VALUE (type) 
+               && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
+        error ("can not use an object as parameter to a method\n");
       if (!is_objc_type_qualifier (TREE_VALUE (chain)))
        return type;
     }
@@ -4790,12 +4851,12 @@ receiver_is_class_object (receiver)
    the identifier of the selector of the message.  This is
    used when printing warnings about argument mismatches.  */
 
-static tree building_objc_message_expr = 0;
+static tree current_objc_message_selector = 0;
 
 tree
-maybe_building_objc_message_expr ()
+objc_message_selector ()
 {
-  return building_objc_message_expr;
+  return current_objc_message_selector;
 }
 
 /* Construct an expression for sending a message.
@@ -4866,7 +4927,7 @@ finish_message_expr (receiver, sel_name, method_params)
   tree selector, self_object, retval;
   int statically_typed = 0, statically_allocated = 0;
   
-  /* Determine receiver type. */
+  /* Determine receiver type.  */
   tree rtype = TREE_TYPE (receiver);
   int super = IS_SUPER (rtype);
 
@@ -4878,8 +4939,8 @@ finish_message_expr (receiver, sel_name, method_params)
               && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
        statically_typed = 1;
       else if ((flag_next_runtime
-               || (IS_ID (rtype)
-                   && (class_ident = receiver_is_class_object (receiver)))))
+               || (IS_ID (rtype)))
+              && (class_ident = receiver_is_class_object (receiver)))
        ;
       else if (! IS_ID (rtype)
               /* Allow any type that matches objc_class_type.  */
@@ -4891,7 +4952,7 @@ finish_message_expr (receiver, sel_name, method_params)
       if (statically_allocated)
        receiver = build_unary_op (ADDR_EXPR, receiver, 0);
 
-      /* Don't evaluate the receiver twice. */
+      /* Don't evaluate the receiver twice.  */
       receiver = save_expr (receiver);
       self_object = receiver;
     }
@@ -4936,7 +4997,7 @@ finish_message_expr (receiver, sel_name, method_params)
       if (iface)
        method_prototype = lookup_instance_method_static (iface, sel_name);
 
-      if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
+      if (! method_prototype && ctype && TYPE_PROTOCOL_LIST (ctype))
        method_prototype
          = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
                                            sel_name, 0);
@@ -5020,7 +5081,7 @@ finish_message_expr (receiver, sel_name, method_params)
 
       if (!method_prototype)
        {
-         warning ("cannot find class (factory) method.");
+         warning ("cannot find class (factory) method");
          warning ("return type for `%s' defaults to id",
                   IDENTIFIER_POINTER (sel_name));
        }
@@ -5038,7 +5099,7 @@ finish_message_expr (receiver, sel_name, method_params)
        {
           hash hsh;
 
-         warning ("method `%s' not implemented by protocol.",
+         warning ("method `%s' not implemented by protocol",
                   IDENTIFIER_POINTER (sel_name));
 
           /* Try and find the method signature in the global pools.  */
@@ -5064,14 +5125,14 @@ finish_message_expr (receiver, sel_name, method_params)
       method_prototype = check_duplicates (hsh);
       if (!method_prototype)
        {
-         warning ("cannot find method.");
+         warning ("cannot find method");
          warning ("return type for `%s' defaults to id",
                   IDENTIFIER_POINTER (sel_name));
        }
     }
 
   /* Save the selector name for printing error messages.  */
-  building_objc_message_expr = sel_name;
+  current_objc_message_selector = sel_name;
 
   /* Build the parameters list for looking up the method.
      These are the object itself and the selector.  */
@@ -5085,7 +5146,7 @@ finish_message_expr (receiver, sel_name, method_params)
                                   receiver, self_object,
                                   selector, method_params);
 
-  building_objc_message_expr = 0;
+  current_objc_message_selector = 0;
 
   return retval;
 }
@@ -5229,6 +5290,8 @@ build_protocol_reference (p)
   PROTOCOL_FORWARD_DECL (p) = decl;
 }
 
+/* This function is called by the parser when (and only when) a
+   @protocol() expression is found, in order to compile it.  */
 tree
 build_protocol_expr (protoname)
      tree protoname;
@@ -5238,7 +5301,7 @@ build_protocol_expr (protoname)
 
   if (!p)
     {
-      error ("Cannot find protocol declaration for `%s'",
+      error ("cannot find protocol declaration for `%s'",
             IDENTIFIER_POINTER (protoname));
       return error_mark_node;
     }
@@ -5250,9 +5313,56 @@ build_protocol_expr (protoname)
 
   TREE_TYPE (expr) = protocol_type;
 
+  /* The @protocol() expression is being compiled into a pointer to a
+     statically allocated instance of the Protocol class.  To become
+     usable at runtime, the 'isa' pointer of the instance need to be
+     fixed up at runtime by the runtime library, to point to the
+     actual 'Protocol' class.  */
+
+  /* For the GNU runtime, put the static Protocol instance in the list
+     of statically allocated instances, so that we make sure that its
+     'isa' pointer is fixed up at runtime by the GNU runtime library
+     to point to the Protocol class (at runtime, when loading the
+     module, the GNU runtime library loops on the statically allocated
+     instances (as found in the defs field in objc_symtab) and fixups
+     all the 'isa' pointers of those objects).  */
+  if (! flag_next_runtime)
+    {
+      /* This type is a struct containing the fields of a Protocol
+        object.  (Cfr. protocol_type instead is the type of a pointer
+        to such a struct).  */
+      tree protocol_struct_type = xref_tag 
+       (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
+      tree *chain;
+      
+      /* Look for the list of Protocol statically allocated instances
+        to fixup at runtime.  Create a new list to hold Protocol
+        statically allocated instances, if the list is not found.  At
+        present there is only another list, holding NSConstantString
+        static instances to be fixed up at runtime.  */
+      for (chain = &objc_static_instances;
+          *chain && TREE_VALUE (*chain) != protocol_struct_type;
+          chain = &TREE_CHAIN (*chain));
+      if (!*chain)
+       {
+         *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
+         add_objc_string (TYPE_NAME (protocol_struct_type),
+                          class_names);
+       }
+      
+      /* Add this statically allocated instance to the Protocol list.  */
+      TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, 
+                                        PROTOCOL_FORWARD_DECL (p),
+                                        TREE_PURPOSE (*chain));
+    }
+  
+
   return expr;
 }
 
+/* This function is called by the parser when a @selector() expression
+   is found, in order to compile it.  It is only called by the parser
+   and only to compile a @selector().  */
 tree
 build_selector_expr (selnamelist)
      tree selnamelist;
@@ -5268,6 +5378,32 @@ build_selector_expr (selnamelist)
   else
     abort ();
 
+  /* If we are required to check @selector() expressions as they
+     are found, check that the selector has been declared.  */
+  if (warn_undeclared_selector)
+    {
+      /* Look the selector up in the list of all known class and
+         instance methods (up to this line) to check that the selector
+         exists.  */
+      hash hsh;
+
+      /* First try with instance methods.  */
+      hsh = hash_lookup (nst_method_hash_list, selname);
+      
+      /* If not found, try with class methods.  */
+      if (!hsh)
+       {
+         hsh = hash_lookup (cls_method_hash_list, selname);
+       }
+      
+      /* If still not found, print out a warning.  */
+      if (!hsh)
+       {
+         warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
+       }
+    }
+  
+
   if (flag_typed_selectors)
     return build_typed_selector_reference (selname, 0);
   else
@@ -5314,14 +5450,27 @@ build_ivar_reference (id)
 
   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
 }
-\f/* Make the hash value positive.  */
-#define HASHFUNCTION(key)      ((size_t) key & 0x7fffffff)
+\f
+/* Compute a hash value for a given method SEL_NAME.  */
 
+static size_t
+hash_func (sel_name)
+     tree sel_name;
+{
+  const unsigned char *s 
+    = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
+  size_t h = 0;
+  
+  while (*s)
+    h = h * 67 + *s++ - 113;
+  return h;  
+}
+     
 static void
 hash_init ()
 {
-  nst_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
-  cls_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
+  nst_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
+  cls_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
 }
 
 /* WARNING!!!!  hash_enter is called with a method, and will peek
@@ -5334,18 +5483,10 @@ hash_enter (hashlist, method)
      hash *hashlist;
      tree method;
 {
-  static hash  hash_alloc_list = 0;
-  static int   hash_alloc_index = 0;
   hash obj;
-  int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
+  int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
 
-  if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
-    {
-      hash_alloc_index = 0;
-      hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
-                                       * HASH_ALLOC_LIST_SIZE);
-    }
-  obj = &hash_alloc_list[hash_alloc_index++];
+  obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
   obj->list = 0;
   obj->next = hashlist[slot];
   obj->key = method;
@@ -5360,7 +5501,7 @@ hash_lookup (hashlist, sel_name)
 {
   hash target;
 
-  target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
+  target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
 
   while (target)
     {
@@ -5377,17 +5518,9 @@ hash_add_attr (entry, value)
      hash entry;
      tree value;
 {
-  static attr  attr_alloc_list = 0;
-  static int   attr_alloc_index = 0;
   attr obj;
 
-  if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
-    {
-      attr_alloc_index = 0;
-      attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
-                                       * ATTR_ALLOC_LIST_SIZE);
-    }
-  obj = &attr_alloc_list[attr_alloc_index++];
+  obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
   obj->next = entry->list;
   obj->value = value;
 
@@ -5410,6 +5543,7 @@ lookup_method (mchain, method)
     {
       if (METHOD_SEL_NAME (mchain) == key)
        return mchain;
+
       mchain = TREE_CHAIN (mchain);
     }
   return NULL_TREE;
@@ -5544,13 +5678,13 @@ add_class_method (class, method)
   else
     {
       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
-       error ("duplicate definition of class method `%s'.",
+       error ("duplicate definition of class method `%s'",
               IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
       else
         {
          /* Check types; if different, complain.  */
          if (!comp_proto_with_proto (method, mth))
-           error ("duplicate declaration of class method `%s'.",
+           error ("duplicate declaration of class method `%s'",
                   IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
         }
     }
@@ -5586,13 +5720,13 @@ add_instance_method (class, method)
   else
     {
       if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE)
-       error ("duplicate definition of instance method `%s'.",
+       error ("duplicate definition of instance method `%s'",
               IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
       else
         {
          /* Check types; if different, complain.  */
          if (!comp_proto_with_proto (method, mth))
-           error ("duplicate declaration of instance method `%s'.",
+           error ("duplicate declaration of instance method `%s'",
                   IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
         }
     }
@@ -5743,7 +5877,7 @@ is_public (expr, identifier)
        {
          if (!lookup_interface (TYPE_NAME (basetype)))
            {
-             error ("Cannot find interface declaration for `%s'",
+             error ("cannot find interface declaration for `%s'",
                     IDENTIFIER_POINTER (TYPE_NAME (basetype)));
              return 0;
            }
@@ -5781,18 +5915,6 @@ is_public (expr, identifier)
 
   return 1;
 }
-
-/* Implement @defs (<classname>) within struct bodies.  */
-
-tree
-get_class_ivars (interface)
-     tree interface;
-{
-  /* Make sure we copy the leaf ivars in case @defs is used in a local
-     context.  Otherwise finish_struct will overwrite the layout info
-     using temporary storage.  */
-  return build_ivar_chain (interface, 1);
-}
 \f
 /* Make sure all entries in CHAIN are also in LIST.  */
 
@@ -5921,7 +6043,7 @@ check_methods_accessible (chain, context, mtype)
 
       chain = TREE_CHAIN (chain); /* next method...  */
     }
-    return first;
+  return first;
 }
 
 /* Check whether the current interface (accessible via
@@ -5939,7 +6061,7 @@ check_protocol (p, type, name)
       int f1, f2;
 
       /* Ensure that all protocols have bodies!  */
-      if (flag_warn_protocol)
+      if (warn_protocol)
        {
          f1 = check_methods (PROTOCOL_CLS_METHODS (p),
                              CLASS_CLS_METHODS (objc_implementation_context),
@@ -5969,6 +6091,7 @@ check_protocol (p, type, name)
       tree subs = PROTOCOL_LIST (p);
       tree super_class =
        lookup_interface (CLASS_SUPER_NAME (implementation_template));
+
       while (subs) 
        {
          tree sub = TREE_VALUE (subs);
@@ -6023,7 +6146,7 @@ start_class (code, class_name, super_name, protocol_list)
     }
 
   class = make_node (code);
-  TYPE_BINFO (class) = make_tree_vec (5);
+  TYPE_BINFO (class) = make_tree_vec (6);
 
   CLASS_NAME (class) = class_name;
   CLASS_SUPER_NAME (class) = super_name;
@@ -6072,7 +6195,7 @@ start_class (code, class_name, super_name, protocol_list)
 
       if (!(implementation_template = lookup_interface (class_name)))
         {
-         warning ("Cannot find interface declaration for `%s'",
+         warning ("cannot find interface declaration for `%s'",
                   IDENTIFIER_POINTER (class_name));
          add_class (implementation_template = objc_implementation_context);
         }
@@ -6121,7 +6244,7 @@ start_class (code, class_name, super_name, protocol_list)
 
       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
        {
-         error ("Cannot find interface declaration for `%s'",
+         error ("cannot find interface declaration for `%s'",
                 IDENTIFIER_POINTER (class_name));
          exit (FATAL_EXIT_CODE);
        }
@@ -6157,7 +6280,7 @@ start_class (code, class_name, super_name, protocol_list)
 
       if (!(implementation_template = lookup_interface (class_name)))
         {
-         error ("Cannot find interface declaration for `%s'",
+         error ("cannot find interface declaration for `%s'",
                 IDENTIFIER_POINTER (class_name));
          exit (FATAL_EXIT_CODE);
         }
@@ -6187,7 +6310,7 @@ continue_class (class)
       if (!objc_class_template)
        build_class_template ();
 
-      imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry));
+      imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
 
       imp_entry->next = imp_list;
       imp_entry->imp_context = class;
@@ -6213,7 +6336,7 @@ continue_class (class)
 
       if (!TYPE_FIELDS (record))
        {
-         finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
+         finish_struct (record, get_class_ivars (class), NULL_TREE);
          CLASS_STATIC_TEMPLATE (class) = record;
 
          /* Mark this record as a class template for static typing.  */
@@ -6313,10 +6436,8 @@ lookup_protocol (ident)
   tree chain;
 
   for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain))
-    {
-      if (ident == PROTOCOL_NAME (chain))
-       return chain;
-    }
+    if (ident == PROTOCOL_NAME (chain))
+      return chain;
 
   return NULL_TREE;
 }
@@ -6393,7 +6514,7 @@ start_protocol (code, name, list)
 
 void
 finish_protocol (protocol)
-       tree protocol ATTRIBUTE_UNUSED;
+     tree protocol ATTRIBUTE_UNUSED;
 {
 }
 
@@ -6535,12 +6656,12 @@ encode_aggregate_within (type, curtype, format, left, right)
     {
       tree name = TYPE_NAME (type);
 
-      /* we have a reference; this is a NeXT extension. */
+      /* we have a reference; this is a NeXT extension.  */
 
       if (obstack_object_size (&util_obstack) - curtype == 1
          && format == OBJC_ENCODE_INLINE_DEFS)
        {
-         /* Output format of struct for first level only. */
+         /* Output format of struct for first level only.  */
          tree fields = TYPE_FIELDS (type);
 
          if (name && TREE_CODE (name) == IDENTIFIER_NODE)
@@ -6574,7 +6695,7 @@ encode_aggregate_within (type, curtype, format, left, right)
 
       else
        {
-         /* We have an untagged structure or a typedef. */
+         /* We have an untagged structure or a typedef.  */
          obstack_1grow (&util_obstack, left);
          obstack_1grow (&util_obstack, '?');
          obstack_1grow (&util_obstack, right);
@@ -6630,7 +6751,7 @@ encode_aggregate_within (type, curtype, format, left, right)
                            IDENTIFIER_POINTER (name),
                            strlen (IDENTIFIER_POINTER (name)));
          else
-             /* We have an untagged structure or a typedef. */
+             /* We have an untagged structure or a typedef.  */
              obstack_1grow (&util_obstack, '?');
 
          obstack_1grow (&util_obstack, right);
@@ -6766,7 +6887,10 @@ encode_type (type, curtype, format)
 }
 
 static void
-encode_complete_bitfield (int position, tree type, int size)
+encode_complete_bitfield (position, type, size)
+     int position;
+     tree type;
+     int size;
 {
   enum tree_code code = TREE_CODE (type);
   char buffer[40];
@@ -6812,7 +6936,8 @@ encode_complete_bitfield (int position, tree type, int size)
            charType = 'q';
        }
     }
-
+  else if (code == ENUMERAL_TYPE)
+    charType = 'i';
   else
     abort ();
 
@@ -6835,14 +6960,14 @@ encode_field_decl (field_decl, curtype, format)
      the bitfield typing information.  */
   if (flag_next_runtime)
     {
-      if (DECL_BIT_FIELD (field_decl))
+      if (DECL_BIT_FIELD_TYPE (field_decl))
        encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
       else
        encode_type (TREE_TYPE (field_decl), curtype, format);
     }
   else
     {
-      if (DECL_BIT_FIELD (field_decl))
+      if (DECL_BIT_FIELD_TYPE (field_decl))
        encode_complete_bitfield (int_bit_position (field_decl),
                                  DECL_BIT_FIELD_TYPE (field_decl),
                                  tree_low_cst (DECL_SIZE (field_decl), 1));
@@ -6958,10 +7083,10 @@ warn_with_method (message, mtype, method)
      int mtype;
      tree method;
 {
-  if (count_error (1) == 0)
+  if (!diagnostic_count_diagnostic (global_dc, DK_WARNING))
     return;
 
-  report_error_function (DECL_SOURCE_FILE (method));
+  diagnostic_report_current_function (global_dc);
 
   /* Add a readable method name to the warning.  */
   warning_with_file_and_line (DECL_SOURCE_FILE (method),
@@ -7190,7 +7315,7 @@ get_super_receiver ()
          tree super_name = CLASS_SUPER_NAME (implementation_template);
          tree super_class;
 
-         /* Barf if super used in a category of Object. */
+         /* Barf if super used in a category of Object.  */
          if (!super_name)
            {
              error ("no super class declared in interface for `%s'",
@@ -7202,9 +7327,13 @@ get_super_receiver ()
            {
              super_class = get_class_reference (super_name);
              if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
+               /* Cast the super class to 'id', since the user may not have
+                  included <objc/objc-class.h>, leaving 'struct objc_class'
+                  an incomplete type.  */
                super_class
-                 = build_component_ref (build_indirect_ref (super_class, "->"),
-                                        get_identifier ("isa"));
+                 = build_component_ref (build_indirect_ref 
+                                        (build_c_cast (id_type, super_class), "->"),
+                                         get_identifier ("isa"));
            }
          else
            {
@@ -7306,7 +7435,7 @@ void
 finish_method_def ()
 {
   lang_expand_function_end = objc_expand_function_end;
-  finish_function (0);
+  finish_function (0, 1);
   lang_expand_function_end = NULL;
 
   /* Required to implement _msgSuper. This must be done AFTER finish_function,
@@ -7962,12 +8091,21 @@ gen_method_decl (method, buf)
 \f
 /* Debug info.  */
 
+
+/* Dump an @interface declaration of the supplied class CHAIN to the
+   supplied file FP.  Used to implement the -gen-decls option (which
+   prints out an @interface declaration of all classes compiled in
+   this run); potentially useful for debugging the compiler too.  */
 static void
 dump_interface (fp, chain)
      FILE *fp;
      tree chain;
 {
-  char *buf = (char *)xmalloc (256);
+  /* FIXME: A heap overflow here whenever a method (or ivar)
+     declaration is so long that it doesn't fit in the buffer.  The
+     code and all the related functions should be rewritten to avoid
+     using fixed size buffers.  */
+  char *buf = (char *) xmalloc (1024 * 10);
   const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
   tree ivar_decls = CLASS_RAW_IVARS (chain);
   tree nst_methods = CLASS_NST_METHODS (chain);
@@ -7975,14 +8113,26 @@ dump_interface (fp, chain)
 
   fprintf (fp, "\n@interface %s", my_name);
 
+  /* CLASS_SUPER_NAME is used to store the superclass name for 
+     classes, and the category name for categories.  */
   if (CLASS_SUPER_NAME (chain))
     {
-      const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
-      fprintf (fp, " : %s\n", super_name);
+      const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
+      
+      if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE 
+         || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
+       {
+         fprintf (fp, " (%s)\n", name);
+       }
+      else
+       {
+         fprintf (fp, " : %s\n", name);
+       }
     }
   else
     fprintf (fp, "\n");
 
+  /* FIXME - the following doesn't seem to work at the moment.  */
   if (ivar_decls)
     {
       fprintf (fp, "{\n");
@@ -8006,7 +8156,8 @@ dump_interface (fp, chain)
       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
       cls_methods = TREE_CHAIN (cls_methods);
     }
-  fprintf (fp, "\n@end");
+
+  fprintf (fp, "@end\n");
 }
 
 /* Demangle function for Objective-C */
@@ -8066,7 +8217,7 @@ objc_demangle (mangled)
     return mangled;             /* not an objc mangled name */
 }
 
-static const char *
+const char *
 objc_printable_name (decl, kind)
      tree decl;
      int kind ATTRIBUTE_UNUSED;
@@ -8077,22 +8228,10 @@ objc_printable_name (decl, kind)
 static void
 init_objc ()
 {
-  /* Add the special tree codes of Objective C to the tables.  */
-
   gcc_obstack_init (&util_obstack);
   util_firstobj = (char *) obstack_finish (&util_obstack);
 
-  memcpy (tree_code_type + (int) LAST_BASE_TREE_CODE,
-         objc_tree_code_type,
-         (int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE);
-  memcpy (tree_code_length + (int) LAST_BASE_TREE_CODE,
-         objc_tree_code_length,
-         (((int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE) * sizeof (int)));
-  memcpy (tree_code_name + (int) LAST_BASE_TREE_CODE,
-         objc_tree_code_name,
-         (((int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE) * sizeof (char *)));
-
-  errbuf = (char *)xmalloc (BUFSIZE);
+  errbuf = (char *) xmalloc (BUFSIZE);
   hash_init ();
   synth_module_prologue ();
 }
@@ -8123,7 +8262,7 @@ finish_objc ()
 #endif
 
   /* Process the static instances here because initialization of objc_symtab
-     depends on them. */
+     depends on them.  */
   if (objc_static_instances)
     generate_static_references ();
 
@@ -8138,7 +8277,16 @@ finish_objc ()
 
       UOBJC_CLASS_decl = impent->class_decl;
       UOBJC_METACLASS_decl = impent->meta_decl;
-
+      
+      /* Dump the @interface of each class as we compile it, if the
+        -gen-decls option is in use.  TODO: Dump the classes in the
+         order they were found, rather than in reverse order as we
+         are doing now.  */
+      if (flag_gen_declaration)
+       {
+         dump_interface (gen_declaration_file, objc_implementation_context);
+       }
+      
       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        {
          /* all of the following reference the string pool...  */
@@ -8164,7 +8312,7 @@ finish_objc ()
   if (objc_implementation_context || class_names_chain || objc_static_instances
       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
     {
-      /* Arrange for Objc data structures to be initialized at run time.  */
+      /* Arrange for ObjC data structures to be initialized at run time.  */
       rtx init_sym = build_module_descriptor ();
       if (init_sym && targetm.have_ctors_dtors)
        (* targetm.asm_out.constructor) (init_sym, DEFAULT_INIT_PRIORITY);
@@ -8189,12 +8337,6 @@ finish_objc ()
 
   generate_strings ();
 
-  if (flag_gen_declaration)
-    {
-      add_class (objc_implementation_context);
-      dump_interface (gen_declaration_file, objc_implementation_context);
-    }
-
   if (warn_selector)
     {
       int slot;
@@ -8243,7 +8385,7 @@ finish_objc ()
 
 static void
 generate_classref_translation_entry (chain)
-    tree chain;
+     tree chain;
 {
   tree expr, name, decl_specs, decl, sc_spec;
   tree type;
@@ -8303,6 +8445,7 @@ handle_class_ref (chain)
   decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
   DECL_INITIAL (decl) = exp;
   TREE_STATIC (decl) = 1;
+  TREE_USED (decl) = 1;
 
   pushdecl (decl);
   rest_of_decl_compilation (decl, 0, 0, 0);
@@ -8324,7 +8467,7 @@ handle_impent (impent)
 
       string = (char *) alloca (strlen (class_name) + 30);
 
-      sprintf (string, "*%sobjc_class_name_%s",
+      sprintf (string, "%sobjc_class_name_%s",
                (flag_next_runtime ? "." : "__"), class_name);
     }
   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
@@ -8339,7 +8482,7 @@ handle_impent (impent)
 
       /* Do the same for categories.  Even though no references to
          these symbols are generated automatically by the compiler, it
-         gives you a handle to pull them into an archive by hand. */
+         gives you a handle to pull them into an archive by hand.  */
       sprintf (string, "*%sobjc_category_name_%s_%s",
                (flag_next_runtime ? "." : "__"), class_name, class_super_name);
     }
@@ -8352,61 +8495,25 @@ handle_impent (impent)
       ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
       return;
     }
+  else
 #endif
-
-  /* (Should this be a routine in varasm.c?) */
-  readonly_data_section ();
-  assemble_global (string);
-  assemble_align (UNITS_PER_WORD);
-  assemble_label (string);
-  assemble_zeros (UNITS_PER_WORD);
-}
-\f
-static void
-ggc_mark_imp_list (arg)
-    void *arg;
-{
-  struct imp_entry *impent;
-
-  for (impent = *(struct imp_entry **)arg; impent; impent = impent->next)
     {
-      ggc_mark_tree (impent->imp_context);
-      ggc_mark_tree (impent->imp_template);
-      ggc_mark_tree (impent->class_decl);
-      ggc_mark_tree (impent->meta_decl);
-    }
-}
-
-static void
-ggc_mark_hash_table (arg)
-    void *arg;
-{
-  hash *hash_table = *(hash **)arg;
-  hash hst;
-  attr list;
-  int i;
-
-  if (hash_table == NULL)
-    return;
-  for (i = 0; i < SIZEHASHTABLE; i++)
-    for (hst = hash_table [i]; hst; hst = hst->next)
-      {
-       ggc_mark_tree (hst->key);
-       for (list = hst->list; list; list = list->next)
-         ggc_mark_tree (list->value);
-      }
-}
+      tree decl, init;
 
-/* Add GC roots for variables local to this file.  */
-static void
-objc_act_parse_init ()
-{
-  ggc_add_tree_root (objc_global_trees, OCTI_MAX);
-  ggc_add_root (&imp_list, 1, sizeof imp_list, ggc_mark_imp_list);
-  ggc_add_root (&nst_method_hash_list, 1, sizeof nst_method_hash_list, ggc_mark_hash_table);
-  ggc_add_root (&cls_method_hash_list, 1, sizeof cls_method_hash_list, ggc_mark_hash_table);
+      init = build_int_2 (0, 0);
+      TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
+      decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
+      TREE_PUBLIC (decl) = 1;
+      TREE_READONLY (decl) = 1;
+      TREE_USED (decl) = 1;
+      TREE_CONSTANT (decl) = 1;
+      DECL_CONTEXT (decl) = 0;
+      DECL_ARTIFICIAL (decl) = 1;
+      DECL_INITIAL (decl) = init;
+      assemble_variable (decl, 1, 0, 0);
+    }
 }
-
+\f
 /* Look up ID as an instance variable.  */
 tree
 lookup_objc_ivar (id)
@@ -8414,8 +8521,8 @@ lookup_objc_ivar (id)
 {
   tree decl;
 
-  if (objc_receiver_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
-    /* we have a message to super */
+  if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
+    /* We have a message to super.  */
     return get_super_receiver ();
   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
     {
@@ -8427,3 +8534,5 @@ lookup_objc_ivar (id)
   else
     return 0;
 }
+
+#include "gtype-objc.h"