OSDN Git Service

PR optimization/4382
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
index a96a2ce..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,7 +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 "diagnostic.h"
 
 /* This is the default way of generating a method name.  */
 /* I am not sure it is really correct.
@@ -84,49 +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.  Possibilities are
-   t, d, s, c, r, <, 1 and 2.  See objc-tree.def for details.  */
-
-#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,
@@ -136,38 +102,35 @@ char *util_firstobj;
 /* for encode_method_def */
 #include "rtl.h"
 
+/* The version identifies which language generation and runtime
+   the module (file) was compiled for, and is recorded in the
+   module descriptor.  */
+
 #define OBJC_VERSION   (flag_next_runtime ? 5 : 8)
 #define PROTOCOL_VERSION 2
 
+/* (Decide if these can ever be validly changed.) */
 #define OBJC_ENCODE_INLINE_DEFS        0
 #define OBJC_ENCODE_DONT_INLINE_DEFS   1
 
-/* Needed to help fix missing @end situations.  */
-extern tree objc_implementation_context;
-
 /*** Private Interface (procedures) ***/
 
 /* Used by compile_file.  */
 
 static void init_objc                          PARAMS ((void));
 static void finish_objc                                PARAMS ((void));
-static void objc_init                          PARAMS ((void));
-static void objc_init_options                  PARAMS ((void));
-static int objc_decode_option                  PARAMS ((int, char **));
-static void objc_post_options                  PARAMS ((void));
 
 /* Code generation.  */
 
 static void synth_module_prologue              PARAMS ((void));
 static tree build_constructor                  PARAMS ((tree, tree));
-static const char *build_module_descriptor      PARAMS ((void));
+static rtx build_module_descriptor             PARAMS ((void));
 static tree init_module_descriptor             PARAMS ((tree));
 static tree build_objc_method_call             PARAMS ((int, tree, tree,
                                                       tree, 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));
 
@@ -191,9 +154,6 @@ static tree generate_protocol_list          PARAMS ((tree));
 static void generate_forward_declaration_to_string_table PARAMS ((void));
 static void build_protocol_reference           PARAMS ((tree));
 
-#if 0
-static tree init_selector                      PARAMS ((int));
-#endif
 static tree build_keyword_selector             PARAMS ((tree));
 static tree synth_id_with_class_suffix         PARAMS ((const char *, tree));
 
@@ -203,26 +163,14 @@ 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));
 
-/* Misc. bookkeeping */
-
-typedef struct hashed_entry    *hash;
-typedef struct hashed_attribute  *attr;
+/* Hash tables to manage the global pool of method prototypes.  */
 
-struct hashed_attribute
-{
-  attr next;
-  tree value;
-};
-struct hashed_entry
-{
-  attr list;
-  hash next;
-  tree key;
-};
+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));
@@ -251,6 +199,7 @@ static tree build_selector_reference_decl   PARAMS ((void));
 
 static tree add_protocol                       PARAMS ((tree));
 static tree lookup_protocol                    PARAMS ((tree));
+static void check_protocol_recursively         PARAMS ((tree, tree));
 static tree lookup_and_install_protocols       PARAMS ((tree));
 
 /* Type encoding.  */
@@ -289,6 +238,8 @@ static tree lookup_method_in_protocol_list  PARAMS ((tree, tree, int));
 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));
@@ -296,14 +247,10 @@ static tree init_objc_symtab                      PARAMS ((tree));
 static void forward_declare_categories         PARAMS ((void));
 static void generate_objc_symtab_decl          PARAMS ((void));
 static tree build_selector                     PARAMS ((tree));
-#if 0
-static tree build_msg_pool_reference           PARAMS ((int));
-#endif
 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,6 +283,8 @@ static tree check_duplicates                        PARAMS ((hash));
 static tree receiver_is_class_object           PARAMS ((tree));
 static int check_methods                       PARAMS ((tree, tree, int));
 static int conforms_to_protocol                        PARAMS ((tree, tree));
+static void check_protocol                     PARAMS ((tree, const char *,
+                                                      const char *));
 static void check_protocols                    PARAMS ((tree, const char *,
                                                       const char *));
 static tree encode_method_def                  PARAMS ((tree));
@@ -344,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) ***/
 
@@ -365,220 +312,36 @@ 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"
 
-#define STRING_OBJECT_CLASS_NAME "NXConstantString"
-#define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
+/* Note that the string object global name is only needed for the
+   NeXT runtime.  */
+#define STRING_OBJECT_GLOBAL_NAME "_NSConstantStringClassReference"
 
-static const char *constant_string_class_name = NULL;
+#define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
 
 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;
 
-/* Set by `continue_class' and checked by `is_public'.  */
-
-#define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type))
-#define TYPED_OBJECT(type) \
-       (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
-
-tree objc_ellipsis_node;
-
-enum objc_tree_index
-{
-    OCTI_STATIC_NST,
-    OCTI_STATIC_NST_DECL,
-    OCTI_SELF_ID,
-    OCTI_UCMD_ID,
-    OCTI_UNUSED_LIST,
-    OCTI_SELF_DECL,
-    OCTI_UMSG_DECL,
-    OCTI_UMSG_SUPER_DECL,
-    OCTI_GET_CLASS_DECL,
-    OCTI_GET_MCLASS_DECL,
-    OCTI_SUPER_TYPE,
-    OCTI_SEL_TYPE,
-    OCTI_ID_TYPE,
-    OCTI_CLS_TYPE,
-    OCTI_NST_TYPE,
-    OCTI_PROTO_TYPE,
-
-    OCTI_CLS_CHAIN,
-    OCTI_ALIAS_CHAIN,
-    OCTI_INTF_CHAIN,
-    OCTI_PROTO_CHAIN,
-    OCTI_CLS_REF_CHAIN,
-    OCTI_SEL_REF_CHAIN,
-    OCTI_CLS_NAMES_CHAIN,
-    OCTI_METH_VAR_NAMES_CHAIN,
-    OCTI_METH_VAR_TYPES_CHAIN,
-
-    OCTI_SYMBOLS_DECL,
-    OCTI_NST_VAR_DECL,
-    OCTI_CLS_VAR_DECL,
-    OCTI_NST_METH_DECL,
-    OCTI_CLS_METH_DECL,
-    OCTI_CLS_DECL,
-    OCTI_MCLS_DECL,
-    OCTI_SEL_TABLE_DECL,
-    OCTI_MODULES_DECL,
-    OCTI_STRG_DECL,
-
-    OCTI_IMPL_CTX,
-    OCTI_IMPL_TEMPL,
-
-    OCTI_CLS_TEMPL,
-    OCTI_CAT_TEMPL,
-    OCTI_UPRIV_REC,
-    OCTI_PROTO_TEMPL,
-    OCTI_SEL_TEMPL,
-    OCTI_UCLS_SUPER_REF,
-    OCTI_UUCLS_SUPER_REF,
-    OCTI_METH_TEMPL,
-    OCTI_IVAR_TEMPL,
-    OCTI_SYMTAB_TEMPL,
-    OCTI_MODULE_TEMPL,
-    OCTI_SUPER_TEMPL,
-    OCTI_OBJ_REF,
-    OCTI_OBJ_ID,
-    OCTI_CLS_ID,
-    OCTI_ID_ID,
-    OCTI_CNST_STR_ID,
-    OCTI_CNST_STR_TYPE,
-    OCTI_SUPER_DECL,
-    OCTI_METH_CTX,
-
-    OCTI_MAX
-};
-
-static tree objc_global_trees[OCTI_MAX];
-
-/* List of classes with list of their static instances.  */
-#define objc_static_instances  objc_global_trees[OCTI_STATIC_NST]
-
-/* The declaration of the array administrating the static instances.  */
-#define static_instances_decl  objc_global_trees[OCTI_STATIC_NST_DECL]
-
-/* Some commonly used instances of "identifier_node".  */
-
-#define self_id                        objc_global_trees[OCTI_SELF_ID]
-#define ucmd_id                        objc_global_trees[OCTI_UCMD_ID]
-#define unused_list            objc_global_trees[OCTI_UNUSED_LIST]
-
-#define self_decl              objc_global_trees[OCTI_SELF_DECL]
-#define umsg_decl              objc_global_trees[OCTI_UMSG_DECL]
-#define umsg_super_decl                objc_global_trees[OCTI_UMSG_SUPER_DECL]
-#define objc_get_class_decl    objc_global_trees[OCTI_GET_CLASS_DECL]
-#define objc_get_meta_class_decl                       \
-                               objc_global_trees[OCTI_GET_MCLASS_DECL]
-
-#define super_type             objc_global_trees[OCTI_SUPER_TYPE]
-#define selector_type          objc_global_trees[OCTI_SEL_TYPE]
-#define id_type                        objc_global_trees[OCTI_ID_TYPE]
-#define objc_class_type                objc_global_trees[OCTI_CLS_TYPE]
-#define instance_type          objc_global_trees[OCTI_NST_TYPE]
-#define protocol_type          objc_global_trees[OCTI_PROTO_TYPE]
-
-/* Type checking macros.  */
-
-#define IS_ID(TYPE) \
-  (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type))
-#define IS_PROTOCOL_QUALIFIED_ID(TYPE) \
-  (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE))
-#define IS_SUPER(TYPE) \
-  (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type))
-
-#define class_chain            objc_global_trees[OCTI_CLS_CHAIN]
-#define alias_chain            objc_global_trees[OCTI_ALIAS_CHAIN]
-#define interface_chain                objc_global_trees[OCTI_INTF_CHAIN]
-#define protocol_chain         objc_global_trees[OCTI_PROTO_CHAIN]
-
-/* Chains to manage selectors that are referenced and defined in the
-   module.  */
-
-#define cls_ref_chain          objc_global_trees[OCTI_CLS_REF_CHAIN]   /* Classes referenced.  */
-#define sel_ref_chain          objc_global_trees[OCTI_SEL_REF_CHAIN]   /* Selectors referenced.  */
-
-/* Chains to manage uniquing of strings.  */
-
-#define class_names_chain      objc_global_trees[OCTI_CLS_NAMES_CHAIN]
-#define meth_var_names_chain   objc_global_trees[OCTI_METH_VAR_NAMES_CHAIN]
-#define meth_var_types_chain   objc_global_trees[OCTI_METH_VAR_TYPES_CHAIN]
-
-/* Hash tables to manage the global pool of method prototypes.  */
-
-static hash *nst_method_hash_list = 0;
-static hash *cls_method_hash_list = 0;
-
-/* Backend data declarations.  */
-
-#define UOBJC_SYMBOLS_decl             objc_global_trees[OCTI_SYMBOLS_DECL]
-#define UOBJC_INSTANCE_VARIABLES_decl  objc_global_trees[OCTI_NST_VAR_DECL]
-#define UOBJC_CLASS_VARIABLES_decl     objc_global_trees[OCTI_CLS_VAR_DECL]
-#define UOBJC_INSTANCE_METHODS_decl    objc_global_trees[OCTI_NST_METH_DECL]
-#define UOBJC_CLASS_METHODS_decl       objc_global_trees[OCTI_CLS_METH_DECL]
-#define UOBJC_CLASS_decl               objc_global_trees[OCTI_CLS_DECL]
-#define UOBJC_METACLASS_decl           objc_global_trees[OCTI_MCLS_DECL]
-#define UOBJC_SELECTOR_TABLE_decl      objc_global_trees[OCTI_SEL_TABLE_DECL]
-#define UOBJC_MODULES_decl             objc_global_trees[OCTI_MODULES_DECL]
-#define UOBJC_STRINGS_decl             objc_global_trees[OCTI_STRG_DECL]
-
-/* The following are used when compiling a class implementation.
-   implementation_template will normally be an interface, however if
-   none exists this will be equal to implementation_context...it is
-   set in start_class.  */
-
-#define implementation_context         objc_global_trees[OCTI_IMPL_CTX]
-#define implementation_template                objc_global_trees[OCTI_IMPL_TEMPL]
-
-struct imp_entry
-{
-  struct imp_entry *next;
-  tree imp_context;
-  tree imp_template;
-  tree class_decl;             /* _OBJC_CLASS_<my_name>; */
-  tree meta_decl;              /* _OBJC_METACLASS_<my_name>; */
-};
+/* The OCTI_... enumeration itself is in objc/objc-act.h.  */
+tree objc_global_trees[OCTI_MAX];
 
 static void handle_impent                      PARAMS ((struct imp_entry *));
 
-static struct imp_entry *imp_list = 0;
-static int imp_count = 0;      /* `@implementation' */
-static int cat_count = 0;      /* `@category' */
-
-#define objc_class_template    objc_global_trees[OCTI_CLS_TEMPL]
-#define objc_category_template objc_global_trees[OCTI_CAT_TEMPL]
-#define uprivate_record                objc_global_trees[OCTI_UPRIV_REC]
-#define objc_protocol_template objc_global_trees[OCTI_PROTO_TEMPL]
-#define objc_selector_template objc_global_trees[OCTI_SEL_TEMPL]
-#define ucls_super_ref         objc_global_trees[OCTI_UCLS_SUPER_REF]
-#define uucls_super_ref                objc_global_trees[OCTI_UUCLS_SUPER_REF]
-
-#define objc_method_template   objc_global_trees[OCTI_METH_TEMPL]
-#define objc_ivar_template     objc_global_trees[OCTI_IVAR_TEMPL]
-#define objc_symtab_template   objc_global_trees[OCTI_SYMTAB_TEMPL]
-#define objc_module_template   objc_global_trees[OCTI_MODULE_TEMPL]
-#define objc_super_template    objc_global_trees[OCTI_SUPER_TEMPL]
-#define objc_object_reference  objc_global_trees[OCTI_OBJ_REF]
-
-#define objc_object_id         objc_global_trees[OCTI_OBJ_ID]
-#define objc_class_id          objc_global_trees[OCTI_CLS_ID]
-#define objc_id_id             objc_global_trees[OCTI_ID_ID]
-#define constant_string_id     objc_global_trees[OCTI_CNST_STR_ID]
-#define constant_string_type   objc_global_trees[OCTI_CNST_STR_TYPE]
-#define UOBJC_SUPER_decl       objc_global_trees[OCTI_SUPER_DECL]
-
-#define method_context         objc_global_trees[OCTI_METH_CTX]
+struct imp_entry *imp_list = 0;
+int imp_count = 0;     /* `@implementation' */
+int cat_count = 0;     /* `@category' */
+
 static int  method_slot = 0;   /* Used by start_method_def, */
 
 #define BUFSIZE                1024
@@ -593,64 +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;
-
-/* Each front end provides its own.  */
-struct lang_hooks lang_hooks = {objc_init,
-                               NULL, /* objc_finish */
-                               objc_init_options,
-                               objc_decode_option,
-                               objc_post_options};
-
-/* Post-switch processing.  */
-static void
-objc_post_options ()
-{
-  cpp_post_options (parse_in);
-}
-
-/* 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 ()
@@ -661,7 +380,7 @@ generate_struct_by_value_array ()
   int aggregate_in_mem[32];
   int found = 0;
 
-  /* Presumbaly 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];
@@ -691,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--)
@@ -711,23 +430,19 @@ generate_struct_by_value_array ()
   exit (0);
 }
 
-static void
-objc_init_options ()
+const char *
+objc_init (filename)
+     const char *filename;
 {
-  parse_in = cpp_create_reader (CLK_OBJC);
-  c_language = clk_objective_c;
-}
+  filename = c_objc_common_init (filename);
+  if (filename == NULL)
+    return filename;
 
-static void
-objc_init ()
-{
   /* Force the line number back to 0; check_newline will have
      raised it to 1, which will make the builtin functions appear
      not to be built in.  */
   lineno = 0;
 
-  c_common_lang_init ();
-
   /* If gen_declaration desired, open the output file.  */
   if (flag_gen_declaration)
     {
@@ -745,6 +460,7 @@ objc_init ()
       TAG_MSGSEND = "objc_msgSend";
       TAG_MSGSENDSUPER = "objc_msgSendSuper";
       TAG_EXECCLASS = "__objc_execClass";
+      default_constant_string_class_name = "NSConstantString";
     }
   else
     {
@@ -753,6 +469,7 @@ objc_init ()
       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;
     }
 
@@ -763,82 +480,29 @@ objc_init ()
   if (print_struct_values)
     generate_struct_by_value_array ();
 
-  objc_act_parse_init ();
-  c_parse_init ();
+  return filename;
 }
 
 void
 finish_file ()
 {
-  finish_objc ();              /* Objective-C finalization */
+  c_objc_common_finish_file ();
+
+  /* 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);
 }
-
-const char *
-lang_identify ()
-{
-  return "objc";
-}
-
-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;
-}
-
-/* used by print-tree.c */
-
-void
-lang_print_xnode (file, node, indent)
-     FILE *file ATTRIBUTE_UNUSED;
-     tree node ATTRIBUTE_UNUSED;
-     int indent ATTRIBUTE_UNUSED;
-{
-}
-
 \f
 static tree
 define_decl (declarator, declspecs)
      tree declarator;
      tree declspecs;
 {
-  tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE);
+  tree decl = start_decl (declarator, declspecs, 0, NULL_TREE);
   finish_decl (decl, NULL_TREE, NULL_TREE);
   return decl;
 }
@@ -855,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;
@@ -900,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)
@@ -947,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
@@ -961,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);
@@ -996,6 +714,15 @@ objc_comptypes (lhs, rhs, reflexive)
 
                      rproto_list = CLASS_PROTOCOL_LIST (rinter);
                      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);
@@ -1003,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);
                        }
 
@@ -1012,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;
@@ -1077,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;
 }
 
@@ -1095,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
@@ -1116,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);
@@ -1149,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;
     }
 
@@ -1167,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);
@@ -1187,6 +1000,32 @@ get_object_reference (protocols)
   return type;
 }
 
+/* Check for circular dependencies in protocols.  The arguments are
+   PROTO, the protocol to check, and LIST, a list of protocol it
+   conforms to.  */
+
+static void 
+check_protocol_recursively (proto, list)
+     tree proto;
+     tree list;
+{
+  tree p;
+
+  for (p = list; p; p = TREE_CHAIN (p))
+    {
+      tree pp = TREE_VALUE (p);
+
+      if (TREE_CODE (pp) == IDENTIFIER_NODE)
+       pp = lookup_protocol (pp);
+
+      if (pp == proto)
+       fatal_error ("protocol `%s' has circular dependency",
+                    IDENTIFIER_POINTER (PROTOCOL_NAME (pp)));      
+      if (pp)
+       check_protocol_recursively (proto, PROTOCOL_LIST (pp));
+    }
+}
+
 static tree
 lookup_and_install_protocols (protocols)
      tree protocols;
@@ -1202,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);
@@ -1243,6 +1082,19 @@ create_builtin_decl (code, type, name)
   return decl;
 }
 
+/* Find the decl for the constant string class.  */
+
+static void
+setup_string_decl ()
+{
+  if (!string_class_decl)
+    {
+      if (!constant_string_global_id)
+       constant_string_global_id = get_identifier (STRING_OBJECT_GLOBAL_NAME);
+      string_class_decl = lookup_name (constant_string_global_id);
+    }
+}
+
 /* Purpose: "play" parser, creating/installing representations
    of the declarations that are required by Objective-C.
 
@@ -1305,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, ...); */
 
@@ -1323,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 *); */
 
@@ -1334,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[]; */
 
@@ -1350,12 +1203,15 @@ synth_module_prologue ()
          /* Suppress outputting debug symbols, because
             dbxout_init hasn'r been called yet.  */
          enum debug_info_type save_write_symbols = write_symbols;
+         const struct gcc_debug_hooks *const save_hooks = debug_hooks;
          write_symbols = NO_DEBUG;
+         debug_hooks = &do_nothing_debug_hooks;
 
          build_selector_template ();
          temp_type = build_array_type (objc_selector_template, NULL_TREE);
 
          write_symbols = save_write_symbols;
+         debug_hooks = save_hooks;
        }
       else
        temp_type = build_array_type (selector_type, NULL_TREE);
@@ -1373,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
@@ -1386,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
@@ -1419,20 +1289,58 @@ 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)
+    {
+      /* For the NeXT runtime, we can generate a literal reference
+        to the string class, don't need to run a constructor.  */
+      setup_string_decl ();
+      if (string_class_decl == NULL_TREE)
+       {
+         error ("cannot find reference tag for class `%s'",
+                IDENTIFIER_POINTER (constant_string_id));
+         return error_mark_node;
+       }
+      initlist = build_tree_list
+       (NULL_TREE,
+        copy_node (build_unary_op (ADDR_EXPR, string_class_decl, 0)));
+    }
+  else
+    {
+      initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
+    }
 
-  initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
   initlist
     = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
                 initlist);
@@ -1495,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;
@@ -1660,27 +1587,27 @@ 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 ()
 {
   struct imp_entry *impent;
-  tree sav = implementation_context;
+  tree sav = objc_implementation_context;
 
   for (impent = imp_list; impent; impent = impent->next)
     {
       if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
        {
          /* Set an invisible arg to synth_id_with_class_suffix.  */
-         implementation_context = impent->imp_context;
+         objc_implementation_context = impent->imp_context;
          impent->class_decl
            = create_builtin_decl (VAR_DECL, objc_category_template,
-                                  IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context)));
+                                  IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", objc_implementation_context)));
        }
     }
-  implementation_context = sav;
+  objc_implementation_context = sav;
 }
 
 /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
@@ -1707,7 +1634,7 @@ generate_objc_symtab_decl ()
                                   tree_cons (NULL_TREE,
                                              objc_symtab_template, sc_spec),
                                   1,
-                                  NULL_TREE, NULL_TREE);
+                                  NULL_TREE);
 
   TREE_USED (UOBJC_SYMBOLS_decl) = 1;
   DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1;
@@ -1751,13 +1678,12 @@ init_module_descriptor (type)
 
 /* Write out the data structures to describe Objective C classes defined.
    If appropriate, compile and output a setup function to initialize them.
-   Return a string which is the name of a function to call to initialize
-   the Objective C data structures for this file (and perhaps for other files
-   also).
+   Return a symbol_ref to the function to call to initialize the Objective C
+   data structures for this file (and perhaps for other files also).
 
    struct objc_module { ... } _OBJC_MODULE = { ... };   */
 
-static const char *
+static rtx
 build_module_descriptor ()
 {
   tree decl_specs, field_decl, field_decl_chain;
@@ -1807,7 +1733,7 @@ build_module_descriptor ()
                                           ridpointers[(int) RID_STATIC]));
 
   UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
-                                  decl_specs, 1, NULL_TREE, NULL_TREE);
+                                  decl_specs, 1, NULL_TREE);
 
   DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1;
   DECL_IGNORED_P (UOBJC_MODULES_decl) = 1;
@@ -1826,64 +1752,57 @@ build_module_descriptor ()
      way of generating the requisite code.  */
 
   if (flag_next_runtime)
-    return 0;
+    return NULL_RTX;
 
   {
-    tree parms, function_decl, decelerator, void_list_node_1;
-    tree function_type;
-    tree init_function_name = get_file_function_name ('I');
+    tree parms, execclass_decl, decelerator, void_list_node_1;
+    tree init_function_name, init_function_decl;
 
     /* Declare void __objc_execClass (void *); */
 
     void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
-    function_type
-      = build_function_type (void_type_node,
-                            tree_cons (NULL_TREE, ptr_type_node,
-                                       void_list_node_1));
-    function_decl = build_decl (FUNCTION_DECL,
-                               get_identifier (TAG_EXECCLASS),
-                               function_type);
-    DECL_EXTERNAL (function_decl) = 1;
-    DECL_ARTIFICIAL (function_decl) = 1;
-    TREE_PUBLIC (function_decl) = 1;
-
-    pushdecl (function_decl);
-    rest_of_decl_compilation (function_decl, 0, 0, 0);
-
-    parms
-      = build_tree_list (NULL_TREE,
-                        build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
-    decelerator = build_function_call (function_decl, parms);
+    execclass_decl = build_decl (FUNCTION_DECL,
+                                get_identifier (TAG_EXECCLASS),
+                                build_function_type (void_type_node,
+                                       tree_cons (NULL_TREE, ptr_type_node,
+                                                  void_list_node_1)));
+    DECL_EXTERNAL (execclass_decl) = 1;
+    DECL_ARTIFICIAL (execclass_decl) = 1;
+    TREE_PUBLIC (execclass_decl) = 1;
+    pushdecl (execclass_decl);
+    rest_of_decl_compilation (execclass_decl, 0, 0, 0);
+    assemble_external (execclass_decl);
 
     /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);}  */
 
+    init_function_name = get_file_function_name ('I');
     start_function (void_list_node_1,
                    build_nt (CALL_EXPR, init_function_name,
-                             /* This has the format of the output
-                                of get_parm_info.  */
                              tree_cons (NULL_TREE, NULL_TREE,
                                         void_list_node_1),
                              NULL_TREE),
-                   NULL_TREE, NULL_TREE);
-#if 0 /* This should be turned back on later
-        for the systems where collect is not needed.  */
-    /* Make these functions nonglobal
-       so each file can use the same name.  */
-    TREE_PUBLIC (current_function_decl) = 0;
-#endif
-    TREE_USED (current_function_decl) = 1;
+                   NULL_TREE);
     store_parm_decls ();
 
-    assemble_external (function_decl);
-    c_expand_expr_stmt (decelerator);
+    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";
+
+    parms
+      = build_tree_list (NULL_TREE,
+                        build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
+    decelerator = build_function_call (execclass_decl, parms);
 
-    TREE_PUBLIC (current_function_decl) = 1;
+    c_expand_expr_stmt (decelerator);
 
-    function_decl = current_function_decl;
-    finish_function (0);
+    finish_function (0, 0);
 
-    /* Return the name of the constructor function.  */
-    return XSTR (XEXP (DECL_RTL (function_decl), 0), 0);
+    return XEXP (DECL_RTL (init_function_decl), 0);
   }
 }
 
@@ -1921,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));
 
@@ -1957,7 +1876,7 @@ generate_static_references ()
       decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
                             build_tree_list (NULL_TREE,
                                              ridpointers[(int) RID_STATIC]));
-      decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
+      decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
       DECL_CONTEXT (decl) = 0;
       DECL_ARTIFICIAL (decl) = 1;
 
@@ -1997,7 +1916,7 @@ generate_static_references ()
                         build_tree_list (NULL_TREE,
                                          ridpointers[(int) RID_STATIC]));
   static_instances_decl
-    = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE);
+    = start_decl (expr_decl, decl_spec, 1, NULL_TREE);
   TREE_USED (static_instances_decl) = 1;
   DECL_CONTEXT (static_instances_decl) = 0;
   DECL_ARTIFICIAL (static_instances_decl) = 1;
@@ -2023,7 +1942,7 @@ generate_strings ()
        = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
-      decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
+      decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
       DECL_CONTEXT (decl) = NULL_TREE;
       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
                                     IDENTIFIER_POINTER (string));
@@ -2038,7 +1957,7 @@ generate_strings ()
        = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
-      decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
+      decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
       DECL_CONTEXT (decl) = NULL_TREE;
       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
                                     IDENTIFIER_POINTER (string));
@@ -2053,7 +1972,7 @@ generate_strings ()
        = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
       expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
-      decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
+      decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
       DECL_CONTEXT (decl) = NULL_TREE;
       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
                                IDENTIFIER_POINTER (string));
@@ -2099,39 +2018,6 @@ build_selector (ident)
     return build_c_cast (selector_type, expr); /* cast! */
 }
 
-/* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
-   The cast stops the compiler from issuing the following message:
-   grok.m: warning: initialization of non-const * pointer from const *
-   grok.m: warning: initialization between incompatible pointer types.  */
-
-#if 0
-static tree
-build_msg_pool_reference (offset)
-     int offset;
-{
-  tree expr = build_int_2 (offset, 0);
-  tree cast;
-
-  expr = build_array_ref (UOBJC_STRINGS_decl, expr);
-  expr = build_unary_op (ADDR_EXPR, expr, 0);
-
-  cast = build_tree_list (build_tree_list (NULL_TREE,
-                                          ridpointers[(int) RID_CHAR]),
-                         build1 (INDIRECT_REF, NULL_TREE, NULL_TREE));
-  TREE_TYPE (expr) = groktypename (cast);
-  return expr;
-}
-
-static tree
-init_selector (offset)
-     int offset;
-{
-  tree expr = build_msg_pool_reference (offset);
-  TREE_TYPE (expr) = selector_type;
-  return expr;
-}
-#endif
-
 static void
 build_selector_translation_table ()
 {
@@ -2144,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)
@@ -2159,7 +2071,7 @@ build_selector_translation_table ()
 
          /* The `decl' that is returned from start_decl is the one that we
             forward declared in `build_selector_reference'  */
-         decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
+         decl = start_decl (var_decl, decl_specs, 1, NULL_TREE );
        }
 
       /* add one for the '\0' character */
@@ -2227,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;
@@ -2236,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,
@@ -2342,7 +2254,7 @@ add_class_reference (ident)
 
 tree
 get_class_reference (ident)
-    tree ident;
+     tree ident;
 {
   if (flag_next_runtime)
     {
@@ -2377,13 +2289,7 @@ get_class_reference (ident)
     }
 }
 
-/* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances
-   of identifier_node that represent the selector. It returns the
-   offset of the selector from the beginning of the _OBJC_STRINGS
-   pool. This offset is typically used by init_selector during code
-   generation.
-
-   For each string section we have a chain which maps identifier nodes
+/* For each string section we have a chain which maps identifier nodes
    to decls for the strings.  */
 
 static tree
@@ -2458,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);
 }
@@ -2517,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;
 {
@@ -2530,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;
-
-  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.  */
+/* Used by: build_private_template, continue_class,
+   and for @defs constructs.  */
 
-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)
     {
@@ -2584,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;
         }
     }
@@ -2632,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);
 
@@ -2960,7 +2849,7 @@ generate_descriptor_table (type, name, size, list, proto)
   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
 
   decl = start_decl (synth_id_with_class_suffix (name, proto),
-                    decl_specs, 1, NULL_TREE, NULL_TREE);
+                    decl_specs, 1, NULL_TREE);
   DECL_CONTEXT (decl) = NULL_TREE;
 
   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
@@ -2973,19 +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;
 {
-  static tree objc_method_prototype_template;
   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 ();
-      ggc_add_tree_root (&objc_method_prototype_template, 1);
-    }
+    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))),
@@ -3053,14 +2938,14 @@ build_tmp_function_decl ()
                  (build_tree_list (decl_specs,
                                    build1 (INDIRECT_REF, NULL_TREE,
                                            NULL_TREE)),
-                  build_tree_list (NULL_TREE, NULL_TREE)));
+                  NULL_TREE));
 
   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE,
                                          get_identifier (TAG_SELECTOR)));
   expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE);
 
   push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl),
-                                  build_tree_list (NULL_TREE, NULL_TREE)));
+                                  NULL_TREE));
   parms = get_parm_info (0);
   poplevel (0, 0, 0);
 
@@ -3102,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;
 
   {
@@ -3125,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
@@ -3150,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 ()
 {
@@ -3216,7 +3142,7 @@ generate_protocols ()
       decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec);
 
       decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p),
-                        decl_specs, 1, NULL_TREE, NULL_TREE);
+                        decl_specs, 1, NULL_TREE);
 
       DECL_CONTEXT (decl) = NULL_TREE;
 
@@ -3581,7 +3507,7 @@ synth_forward_declarations ()
 
   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
 
-  an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context);
+  an_id = synth_id_with_class_suffix ("_OBJC_CLASS", objc_implementation_context);
 
   sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]);
   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
@@ -3592,7 +3518,7 @@ synth_forward_declarations ()
   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
 
   an_id = synth_id_with_class_suffix ("_OBJC_METACLASS",
-                                     implementation_context);
+                                     objc_implementation_context);
 
   UOBJC_METACLASS_decl = define_decl (an_id, decl_specs);
   TREE_USED (UOBJC_METACLASS_decl) = 1;
@@ -3611,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),
@@ -3622,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;
@@ -3896,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)),
@@ -3921,8 +3843,8 @@ generate_ivars_list (type, name, size, list)
   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
 
-  decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
-                    decl_specs, 1, NULL_TREE, NULL_TREE);
+  decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
+                    decl_specs, 1, NULL_TREE);
 
   initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
   initlist = tree_cons (NULL_TREE, list, initlist);
@@ -4005,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),
@@ -4086,8 +4013,8 @@ generate_dispatch_table (type, name, size, list)
   sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
   decl_specs = tree_cons (NULL_TREE, type, sc_spec);
 
-  decl = start_decl (synth_id_with_class_suffix (name, implementation_context),
-                    decl_specs, 1, NULL_TREE, NULL_TREE);
+  decl = start_decl (synth_id_with_class_suffix (name, objc_implementation_context),
+                    decl_specs, 1, NULL_TREE);
 
   initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
   initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist);
@@ -4119,7 +4046,7 @@ generate_dispatch_tables ()
 
   variable_length_type = groktypename (cast);
 
-  chain = CLASS_CLS_METHODS (implementation_context);
+  chain = CLASS_CLS_METHODS (objc_implementation_context);
   if (chain)
     {
       size = list_length (chain);
@@ -4131,7 +4058,7 @@ generate_dispatch_tables ()
 
       UOBJC_CLASS_METHODS_decl
        = generate_dispatch_table (method_list_template,
-                                  ((TREE_CODE (implementation_context)
+                                  ((TREE_CODE (objc_implementation_context)
                                     == CLASS_IMPLEMENTATION_TYPE)
                                    ? "_OBJC_CLASS_METHODS"
                                    : "_OBJC_CATEGORY_CLASS_METHODS"),
@@ -4141,7 +4068,7 @@ generate_dispatch_tables ()
   else
     UOBJC_CLASS_METHODS_decl = 0;
 
-  chain = CLASS_NST_METHODS (implementation_context);
+  chain = CLASS_NST_METHODS (objc_implementation_context);
   if (chain)
     {
       size = list_length (chain);
@@ -4151,7 +4078,7 @@ generate_dispatch_tables ()
       initlist
        = build_dispatch_table_initializer (objc_method_template, chain);
 
-      if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
+      if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        UOBJC_INSTANCE_METHODS_decl
          = generate_dispatch_table (method_list_template,
                                     "_OBJC_INSTANCE_METHODS",
@@ -4245,7 +4172,7 @@ generate_protocol_list (i_or_p)
 
   expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
 
-  refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE);
+  refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
   DECL_CONTEXT (refs_decl) = NULL_TREE;
 
   finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl),
@@ -4454,8 +4381,8 @@ generate_category (cat)
   decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec);
 
   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY",
-                                                implementation_context),
-                    decl_specs, 1, NULL_TREE, NULL_TREE);
+                                                objc_implementation_context),
+                    decl_specs, 1, NULL_TREE);
 
   initlist = build_category_initializer (TREE_TYPE (decl),
                                         cat_name_expr, class_name_expr,
@@ -4538,7 +4465,7 @@ generate_shared_structures ()
   decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec);
 
   decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1,
-                    NULL_TREE, NULL_TREE);
+                    NULL_TREE);
 
   initlist
     = build_shared_structure_initializer
@@ -4555,7 +4482,7 @@ generate_shared_structures ()
   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
 
   decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1,
-                    NULL_TREE, NULL_TREE);
+                    NULL_TREE);
 
   initlist
     = build_shared_structure_initializer
@@ -4582,8 +4509,8 @@ synth_id_with_class_suffix (preamble, ctxt)
   if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE
       || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE)
     {
-      const char *class_name
-       = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
+      const char *const class_name
+       = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
       string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3);
       sprintf (string, "%s_%s", preamble,
               IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
@@ -4592,10 +4519,10 @@ synth_id_with_class_suffix (preamble, ctxt)
           || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE)
     {
       /* We have a category.  */
-      const char *class_name
-       = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
-      const char *class_super_name
-       = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context));
+      const char *const class_name
+       = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
+      const char *const class_super_name
+       = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
       string = (char *) alloca (strlen (preamble)
                                + strlen (class_name)
                                + strlen (class_super_name)
@@ -4650,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;
     }
@@ -4783,8 +4714,8 @@ build_method_decl (code, ret_type, selector, add_args)
 #define METHOD_DEF 0
 #define METHOD_REF 1
 
-/* Used by `build_message_expr' and `comp_method_types'.  Return an
-   argument list for method METH.  CONTEXT is either METHOD_DEF or
+/* Used by `build_objc_method_call' and `comp_method_types'.  Return
+   an argument list for method METH.  CONTEXT is either METHOD_DEF or
    METHOD_REF, saying whether we are trying to define a method or call
    one.  SUPERFLAG says this is for a send to super; this makes a
    difference for the NeXT calling sequence in which the lookup and
@@ -4860,18 +4791,29 @@ check_duplicates (hsh)
   return meth;
 }
 
-/* If RECEIVER is a class reference, return the identifier node for the
-   referenced class.  RECEIVER is created by get_class_reference, so we
-   check the exact form created depending on which runtimes are used.  */
+/* If RECEIVER is a class reference, return the identifier node for
+   the referenced class.  RECEIVER is created by get_class_reference,
+   so we check the exact form created depending on which runtimes are
+   used.  */
 
 static tree
 receiver_is_class_object (receiver)
       tree receiver;
 {
   tree chain, exp, arg;
+
+  /* The receiver is 'self' in the context of a class method.  */
+  if (objc_method_context
+      && receiver == self_decl
+      && TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
+    {
+      return CLASS_NAME (objc_implementation_context);
+    }
+  
   if (flag_next_runtime)
     {
-      /* The receiver is a variable created by build_class_reference_decl.  */
+      /* The receiver is a variable created by
+         build_class_reference_decl.  */
       if (TREE_CODE (receiver) == VAR_DECL
          && TREE_TYPE (receiver) == objc_class_type)
        /* Look up the identifier.  */
@@ -4883,12 +4825,13 @@ receiver_is_class_object (receiver)
     {
       /* The receiver is a function call that returns an id.  Check if
         it is a call to objc_getClass, if so, pick up the class name.  */
-      if ((exp = TREE_OPERAND (receiver, 0))
+      if (TREE_CODE (receiver) == CALL_EXPR 
+         && (exp = TREE_OPERAND (receiver, 0))
          && TREE_CODE (exp) == ADDR_EXPR
          && (exp = TREE_OPERAND (exp, 0))
          && TREE_CODE (exp) == FUNCTION_DECL
          && exp == objc_get_class_decl
-         /* we have a call to objc_getClass! */
+         /* We have a call to objc_getClass!  */
          && (arg = TREE_OPERAND (receiver, 1))
          && TREE_CODE (arg) == TREE_LIST
          && (arg = TREE_VALUE (arg)))
@@ -4908,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.
@@ -4928,57 +4871,14 @@ build_message_expr (mess)
      tree mess;
 {
   tree receiver = TREE_PURPOSE (mess);
-  tree selector, self_object;
-  tree rtype, sel_name;
+  tree sel_name;
   tree args = TREE_VALUE (mess);
   tree method_params = NULL_TREE;
-  tree method_prototype = NULL_TREE;
-  tree retval;
-  int statically_typed = 0, statically_allocated = 0;
-  tree class_ident = 0;
-
-  /* 1 if this is sending to the superclass.  */
-  int super;
 
   if (TREE_CODE (receiver) == ERROR_MARK)
     return error_mark_node;
 
-  /* Determine receiver type.  */
-  rtype = TREE_TYPE (receiver);
-  super = IS_SUPER (rtype);
-
-  if (! super)
-    {
-      if (TREE_STATIC_TEMPLATE (rtype))
-       statically_allocated = 1;
-      else if (TREE_CODE (rtype) == POINTER_TYPE
-              && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
-       statically_typed = 1;
-      else if ((flag_next_runtime
-               || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype)))
-              && (class_ident = receiver_is_class_object (receiver)))
-       ;
-      else if (! IS_ID (rtype)
-              /* Allow any type that matches objc_class_type.  */
-              && ! comptypes (rtype, objc_class_type))
-       {
-         warning ("invalid receiver type `%s'",
-                  gen_declaration (rtype, errbuf));
-       }
-
-      if (statically_allocated)
-       receiver = build_unary_op (ADDR_EXPR, receiver, 0);
-
-      /* Don't evaluate the receiver twice.  */
-      receiver = save_expr (receiver);
-      self_object = receiver;
-    }
-  else
-    /* If sending to `super', use current self as the object.  */
-    self_object = self_decl;
-
   /* Obtain the full selector name.  */
-
   if (TREE_CODE (args) == IDENTIFIER_NODE)
     /* A unary selector.  */
     sel_name = args;
@@ -4988,8 +4888,6 @@ build_message_expr (mess)
     abort ();
 
   /* Build the parameter list to give to the method.  */
-
-  method_params = NULL_TREE;
   if (TREE_CODE (args) == TREE_LIST)
     {
       tree chain = args, prev = NULL_TREE;
@@ -5013,9 +4911,58 @@ build_message_expr (mess)
       method_params = args;
     }
 
+  return finish_message_expr (receiver, sel_name, method_params);
+}
+
+/* The 'finish_message_expr' routine is called from within
+   'build_message_expr' for non-template functions.  In the case of
+   C++ template functions, it is called from 'build_expr_from_tree'
+   (in decl2.c) after RECEIVER and METHOD_PARAMS have been expanded.  */
+   
+tree
+finish_message_expr (receiver, sel_name, method_params)
+     tree receiver, sel_name, method_params; 
+{      
+  tree method_prototype = NULL_TREE, class_ident = NULL_TREE;
+  tree selector, self_object, retval;
+  int statically_typed = 0, statically_allocated = 0;
+  
+  /* Determine receiver type.  */
+  tree rtype = TREE_TYPE (receiver);
+  int super = IS_SUPER (rtype);
+
+  if (! super)
+    {
+      if (TREE_STATIC_TEMPLATE (rtype))
+       statically_allocated = 1;
+      else if (TREE_CODE (rtype) == POINTER_TYPE
+              && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
+       statically_typed = 1;
+      else if ((flag_next_runtime
+               || (IS_ID (rtype)))
+              && (class_ident = receiver_is_class_object (receiver)))
+       ;
+      else if (! IS_ID (rtype)
+              /* Allow any type that matches objc_class_type.  */
+              && ! comptypes (rtype, objc_class_type))
+       {
+         warning ("invalid receiver type `%s'",
+                  gen_declaration (rtype, errbuf));
+       }
+      if (statically_allocated)
+       receiver = build_unary_op (ADDR_EXPR, receiver, 0);
+
+      /* Don't evaluate the receiver twice.  */
+      receiver = save_expr (receiver);
+      self_object = receiver;
+    }
+  else
+    /* If sending to `super', use current self as the object.  */
+    self_object = self_decl;
+
   /* Determine operation return type.  */
 
-  if (IS_SUPER (rtype))
+  if (super)
     {
       tree iface;
 
@@ -5024,7 +4971,7 @@ build_message_expr (mess)
          iface
            = lookup_interface (CLASS_SUPER_NAME (implementation_template));
 
-         if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
+         if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
            method_prototype = lookup_instance_method_static (iface, sel_name);
          else
            method_prototype = lookup_class_method_static (iface, sel_name);
@@ -5050,7 +4997,7 @@ build_message_expr (mess)
       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);
@@ -5066,8 +5013,8 @@ build_message_expr (mess)
 
       /* `self' is now statically_typed.  All methods should be visible
          within the context of the implementation.  */
-      if (implementation_context
-         && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
+      if (objc_implementation_context
+         && CLASS_NAME (objc_implementation_context) == TYPE_NAME (ctype))
        {
          method_prototype
            = lookup_instance_method_static (implementation_template,
@@ -5079,11 +5026,11 @@ build_message_expr (mess)
                                                sel_name, 0);
 
          if (! method_prototype
-             && implementation_template != implementation_context)
+             && implementation_template != objc_implementation_context)
            /* The method is not published in the interface.  Check
                locally.  */
            method_prototype
-             = lookup_method (CLASS_NST_METHODS (implementation_context),
+             = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
                               sel_name);
        }
       else
@@ -5110,18 +5057,18 @@ build_message_expr (mess)
     }
   else if (class_ident)
     {
-      if (implementation_context
-         && CLASS_NAME (implementation_context) == class_ident)
+      if (objc_implementation_context
+         && CLASS_NAME (objc_implementation_context) == class_ident)
        {
          method_prototype
            = lookup_class_method_static (implementation_template, sel_name);
 
          if (!method_prototype
-             && implementation_template != implementation_context)
+             && implementation_template != objc_implementation_context)
            /* The method is not published in the interface. Check
                locally.  */
            method_prototype
-             = lookup_method (CLASS_CLS_METHODS (implementation_context),
+             = lookup_method (CLASS_CLS_METHODS (objc_implementation_context),
                               sel_name);
        }
       else
@@ -5134,7 +5081,7 @@ build_message_expr (mess)
 
       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));
        }
@@ -5152,7 +5099,7 @@ build_message_expr (mess)
        {
           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.  */
@@ -5170,22 +5117,22 @@ build_message_expr (mess)
 
       /* We think we have an instance...loophole: extern id Object; */
       hsh = hash_lookup (nst_method_hash_list, sel_name);
+      
       if (!hsh)
-       /* For various loopholes, like sending messages to self in a
-          factory context.  */
+       /* For various loopholes */     
        hsh = hash_lookup (cls_method_hash_list, sel_name);
 
       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.  */
@@ -5199,7 +5146,7 @@ build_message_expr (mess)
                                   receiver, self_object,
                                   selector, method_params);
 
-  building_objc_message_expr = 0;
+  current_objc_message_selector = 0;
 
   return retval;
 }
@@ -5239,12 +5186,12 @@ build_objc_method_call (super_flag, method_prototype, lookup_object, object,
             Clobber the data type of SENDER temporarily to accept
             all the arguments for this operation, and to return
             whatever this operation returns.  */
-         tree arglist = NULL_TREE;
-         tree retval;
+         tree arglist = NULL_TREE, retval, savarg, savret;
+         tree ret_type = groktypename (TREE_TYPE (method_prototype));
 
          /* Save the proper contents of SENDER's data type.  */
-         tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
-         tree savret = TREE_TYPE (TREE_TYPE (sender));
+         savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
+         savret = TREE_TYPE (TREE_TYPE (sender));
 
          /* Install this method's argument types.  */
          arglist = get_arg_type_list (method_prototype, METHOD_REF,
@@ -5252,8 +5199,7 @@ build_objc_method_call (super_flag, method_prototype, lookup_object, object,
          TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
 
          /* Install this method's return type.  */
-         TREE_TYPE (TREE_TYPE (sender))
-           = groktypename (TREE_TYPE (method_prototype));
+         TREE_TYPE (TREE_TYPE (sender)) = ret_type;
 
          /* Call SENDER with all the parameters.  This will do type
             checking using the arg types for this method.  */
@@ -5344,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;
@@ -5353,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;
     }
@@ -5365,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;
@@ -5383,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
@@ -5411,7 +5432,7 @@ tree
 build_ivar_reference (id)
      tree id;
 {
-  if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
+  if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
     {
       /* Historically, a class method that produced objects (factory
         method) would assign `self' to the instance that it
@@ -5430,31 +5451,26 @@ build_ivar_reference (id)
   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
 }
 \f
-#define HASH_ALLOC_LIST_SIZE   170
-#define ATTR_ALLOC_LIST_SIZE   170
-#define SIZEHASHTABLE          257
-
-/* make positive */
-#define HASHFUNCTION(key)      ((HOST_WIDE_INT) key & 0x7fffffff)
+/* 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 *)xmalloc (SIZEHASHTABLE * sizeof (hash));
-  cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
-
-  if (!nst_method_hash_list || !cls_method_hash_list)
-    perror ("unable to allocate space in objc-act.c");
-  else
-    {
-      int i;
-
-      for (i = 0; i < SIZEHASHTABLE; i++)
-       {
-         nst_method_hash_list[i] = 0;
-         cls_method_hash_list[i] = 0;
-       }
-    }
+  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
@@ -5467,20 +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);
-      if (! hash_alloc_list)
-       perror ("unable to allocate in objc-act.c");
-    }
-  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;
@@ -5495,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)
     {
@@ -5512,19 +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);
-      if (! attr_alloc_list)
-       perror ("unable to allocate in objc-act.c");
-    }
-  obj = &attr_alloc_list[attr_alloc_index++];
+  obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
   obj->next = entry->list;
   obj->value = value;
 
@@ -5547,6 +5543,7 @@ lookup_method (mchain, method)
     {
       if (METHOD_SEL_NAME (mchain) == key)
        return mchain;
+
       mchain = TREE_CHAIN (mchain);
     }
   return NULL_TREE;
@@ -5658,7 +5655,9 @@ lookup_class_method_static (interface, ident)
     }
   while (inter);
 
-  /* Simulate wrap around.  */
+  /* If no class (factory) method was found, check if an _instance_
+     method of the same name exists in the root class.  This is what
+     the Objective-C runtime will do.  */
   return lookup_instance_method_static (root_inter, ident);
 }
 
@@ -5679,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)));
         }
     }
@@ -5721,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)));
         }
     }
@@ -5878,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;
            }
@@ -5891,12 +5890,12 @@ is_public (expr, identifier)
              /* Important difference between the Stepstone translator:
                 all instance variables should be public within the context
                 of the implementation.  */
-             if (implementation_context
-                 && (((TREE_CODE (implementation_context)
+             if (objc_implementation_context
+                 && (((TREE_CODE (objc_implementation_context)
                        == CLASS_IMPLEMENTATION_TYPE)
-                      || (TREE_CODE (implementation_context)
+                      || (TREE_CODE (objc_implementation_context)
                           == CATEGORY_IMPLEMENTATION_TYPE))
-                     && (CLASS_NAME (implementation_context)
+                     && (CLASS_NAME (objc_implementation_context)
                          == TYPE_NAME (basetype))))
                return ! is_private (decl);
 
@@ -5907,7 +5906,7 @@ is_public (expr, identifier)
            }
        }
 
-      else if (implementation_context && (basetype == objc_object_reference))
+      else if (objc_implementation_context && (basetype == objc_object_reference))
        {
          TREE_TYPE (expr) = uprivate_record;
          warning ("static access to object of type `id'");
@@ -5916,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.  */
 
@@ -5945,14 +5932,14 @@ check_methods (chain, list, mtype)
        {
          if (first)
            {
-             if (TREE_CODE (implementation_context)
+             if (TREE_CODE (objc_implementation_context)
                  == CLASS_IMPLEMENTATION_TYPE)
                warning ("incomplete implementation of class `%s'",
-                        IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
-             else if (TREE_CODE (implementation_context)
+                        IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
+             else if (TREE_CODE (objc_implementation_context)
                       == CATEGORY_IMPLEMENTATION_TYPE)
                warning ("incomplete implementation of category `%s'",
-                        IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
+                        IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
              first = 0;
            }
 
@@ -5966,16 +5953,17 @@ check_methods (chain, list, mtype)
     return first;
 }
 
+/* Check if CLASS, or its superclasses, explicitly conforms to PROTOCOL.  */
+
 static int
 conforms_to_protocol (class, protocol)
      tree class;
      tree protocol;
 {
-   while (protocol)
+   if (TREE_CODE (protocol) == PROTOCOL_INTERFACE_TYPE)
      {
        tree p = CLASS_PROTOCOL_LIST (class);
-
-       while (p && TREE_VALUE (p) != TREE_VALUE (protocol))
+       while (p && TREE_VALUE (p) != protocol)
         p = TREE_CHAIN (p);
 
        if (!p)
@@ -5987,8 +5975,6 @@ conforms_to_protocol (class, protocol)
           if (!tmp)
             return 0;
         }
-
-       protocol = TREE_CHAIN (protocol);
      }
 
    return 1;
@@ -6039,16 +6025,16 @@ check_methods_accessible (chain, context, mtype)
        {
          if (first)
            {
-             if (TREE_CODE (implementation_context)
+             if (TREE_CODE (objc_implementation_context)
                  == CLASS_IMPLEMENTATION_TYPE)
                warning ("incomplete implementation of class `%s'",
                         IDENTIFIER_POINTER
-                          (CLASS_NAME (implementation_context)));
-             else if (TREE_CODE (implementation_context)
+                          (CLASS_NAME (objc_implementation_context)));
+             else if (TREE_CODE (objc_implementation_context)
                       == CATEGORY_IMPLEMENTATION_TYPE)
                warning ("incomplete implementation of category `%s'",
                         IDENTIFIER_POINTER
-                          (CLASS_SUPER_NAME (implementation_context)));
+                          (CLASS_SUPER_NAME (objc_implementation_context)));
              first = 0;
            }
          warning ("method definition for `%c%s' not found",
@@ -6057,60 +6043,85 @@ check_methods_accessible (chain, context, mtype)
 
       chain = TREE_CHAIN (chain); /* next method...  */
     }
-    return first;
+  return first;
 }
 
+/* Check whether the current interface (accessible via
+   'objc_implementation_context') actually implements protocol P, along
+   with any protocols that P inherits.  */
+   
 static void
-check_protocols (proto_list, type, name)
-     tree proto_list;
+check_protocol (p, type, name)
+     tree p;
      const char *type;
      const char *name;
 {
-  for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
+  if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
     {
-      tree p = TREE_VALUE (proto_list);
+      int f1, f2;
 
-      if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
+      /* Ensure that all protocols have bodies!  */
+      if (warn_protocol)
        {
-         int f1, f2;
-         
-         /* Ensure that all protocols have bodies.  */
-         if (flag_warn_protocol) {
-           f1 = check_methods (PROTOCOL_CLS_METHODS (p),
-                               CLASS_CLS_METHODS (implementation_context),
-                               '+');
-           f2 = check_methods (PROTOCOL_NST_METHODS (p),
-                               CLASS_NST_METHODS (implementation_context),
-                               '-');
-         } else {
-           f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
-                                          implementation_context,
-                                          '+');
-           f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
-                                          implementation_context,
-                                          '-');
-         }
-
-         if (!f1 || !f2)
-           warning ("%s `%s' does not fully implement the `%s' protocol",
-                    type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
-
+         f1 = check_methods (PROTOCOL_CLS_METHODS (p),
+                             CLASS_CLS_METHODS (objc_implementation_context),
+                             '+');
+         f2 = check_methods (PROTOCOL_NST_METHODS (p),
+                             CLASS_NST_METHODS (objc_implementation_context),
+                             '-');
        }
       else
-        {
-         ; /* An identifier if we could not find a protocol.  */
-        }
+       {
+         f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p),
+                                        objc_implementation_context,
+                                        '+');
+         f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p),
+                                        objc_implementation_context,
+                                        '-');
+       }
 
-      /* Check protocols recursively.  */
-      if (PROTOCOL_LIST (p))
+      if (!f1 || !f2)
+       warning ("%s `%s' does not fully implement the `%s' protocol",
+                type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+    }
+    
+  /* Check protocols recursively.  */
+  if (PROTOCOL_LIST (p))
+    {
+      tree subs = PROTOCOL_LIST (p);
+      tree super_class =
+       lookup_interface (CLASS_SUPER_NAME (implementation_template));
+
+      while (subs) 
        {
-         tree super_class
-           = lookup_interface (CLASS_SUPER_NAME (implementation_template));
-         if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p)))
-           check_protocols (PROTOCOL_LIST (p), type, name);
+         tree sub = TREE_VALUE (subs);
+
+         /* If the superclass does not conform to the protocols
+            inherited by P, then we must!  */
+         if (!super_class || !conforms_to_protocol (super_class, sub))
+           check_protocol (sub, type, name);
+         subs = TREE_CHAIN (subs);
        }
     }
 }
+       
+/* Check whether the current interface (accessible via
+   'objc_implementation_context') actually implements the protocols listed
+   in PROTO_LIST.  */
+   
+static void
+check_protocols (proto_list, type, name)
+     tree proto_list;
+     const char *type;
+     const char *name;
+{
+  for ( ; proto_list; proto_list = TREE_CHAIN (proto_list))
+    {
+      tree p = TREE_VALUE (proto_list);
+
+      check_protocol (p, type, name);
+    }
+}
 \f
 /* Make sure that the class CLASS_NAME is defined
    CODE says which kind of thing CLASS_NAME ought to be.
@@ -6135,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;
@@ -6151,11 +6162,8 @@ start_class (code, class_name, super_name, protocol_list)
   if (code == CLASS_IMPLEMENTATION_TYPE)
     {
       {
-        static tree implemented_classes = 0;
         tree chain;
 
-       if (!implemented_classes)
-         ggc_add_tree_root (&implemented_classes, 1);
         for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain))
            if (TREE_VALUE (chain) == class_name)
             {
@@ -6181,15 +6189,15 @@ start_class (code, class_name, super_name, protocol_list)
       /* Reset for multiple classes per file.  */
       method_slot = 0;
 
-      implementation_context = class;
+      objc_implementation_context = class;
 
       /* Lookup the interface for this implementation.  */
 
       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 = implementation_context);
+         add_class (implementation_template = objc_implementation_context);
         }
 
       /* If a super class has been specified in the implementation,
@@ -6199,7 +6207,7 @@ start_class (code, class_name, super_name, protocol_list)
          && (super_name != CLASS_SUPER_NAME (implementation_template)))
         {
          tree previous_name = CLASS_SUPER_NAME (implementation_template);
-          const char *name =
+          const char *const name =
            previous_name ? IDENTIFIER_POINTER (previous_name) : "";
          error ("conflicting super class name `%s'",
                 IDENTIFIER_POINTER (super_name));
@@ -6208,7 +6216,7 @@ start_class (code, class_name, super_name, protocol_list)
 
       else if (! super_name)
        {
-         CLASS_SUPER_NAME (implementation_context) 
+         CLASS_SUPER_NAME (objc_implementation_context) 
            = CLASS_SUPER_NAME (implementation_template);
        }
     }
@@ -6236,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);
        }
@@ -6264,7 +6272,7 @@ start_class (code, class_name, super_name, protocol_list)
       /* Reset for multiple classes per file.  */
       method_slot = 0;
 
-      implementation_context = class;
+      objc_implementation_context = class;
 
       /* For a category, class_name is really the name of the class that
         the following set of methods will be associated with.  We must
@@ -6272,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);
         }
@@ -6302,9 +6310,7 @@ continue_class (class)
       if (!objc_class_template)
        build_class_template ();
 
-      if (!(imp_entry
-           = (struct imp_entry *) xmalloc (sizeof (struct imp_entry))))
-       perror ("unable to allocate in objc-act.c");
+      imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
 
       imp_entry->next = imp_list;
       imp_entry->imp_context = class;
@@ -6330,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.  */
@@ -6354,18 +6360,18 @@ finish_class (class)
     {
       /* All code generation is done in finish_objc.  */
 
-      if (implementation_template != implementation_context)
+      if (implementation_template != objc_implementation_context)
        {
          /* Ensure that all method listed in the interface contain bodies.  */
          check_methods (CLASS_CLS_METHODS (implementation_template),
-                        CLASS_CLS_METHODS (implementation_context), '+');
+                        CLASS_CLS_METHODS (objc_implementation_context), '+');
          check_methods (CLASS_NST_METHODS (implementation_template),
-                        CLASS_NST_METHODS (implementation_context), '-');
+                        CLASS_NST_METHODS (objc_implementation_context), '-');
 
          if (CLASS_PROTOCOL_LIST (implementation_template))
            check_protocols (CLASS_PROTOCOL_LIST (implementation_template),
                             "class",
-                            IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
+                            IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context)));
        }
     }
 
@@ -6385,14 +6391,14 @@ finish_class (class)
        {
          /* Ensure all method listed in the interface contain bodies.  */
          check_methods (CLASS_CLS_METHODS (category),
-                        CLASS_CLS_METHODS (implementation_context), '+');
+                        CLASS_CLS_METHODS (objc_implementation_context), '+');
          check_methods (CLASS_NST_METHODS (category),
-                        CLASS_NST_METHODS (implementation_context), '-');
+                        CLASS_NST_METHODS (objc_implementation_context), '-');
 
          if (CLASS_PROTOCOL_LIST (category))
            check_protocols (CLASS_PROTOCOL_LIST (category),
                             "category",
-                            IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
+                            IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
        }
     }
 
@@ -6430,14 +6436,39 @@ 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;
 }
 
+/* This function forward declares the protocols named by NAMES.  If
+   they are already declared or defined, the function has no effect.  */
+
+void
+objc_declare_protocols (names)
+     tree names;
+{
+  tree list;
+
+  for (list = names; list; list = TREE_CHAIN (list))
+    {
+      tree name = TREE_VALUE (list);
+
+      if (lookup_protocol (name) == NULL_TREE)
+       {
+         tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
+
+         TYPE_BINFO (protocol) = make_tree_vec (2);
+         PROTOCOL_NAME (protocol) = name;
+         PROTOCOL_LIST (protocol) = NULL_TREE;
+         add_protocol (protocol);
+         PROTOCOL_DEFINED (protocol) = 0;
+         PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
+       }
+    }
+}
+
 tree
 start_protocol (code, name, list)
      enum tree_code code;
@@ -6446,32 +6477,44 @@ start_protocol (code, name, list)
 {
   tree protocol;
 
-  /* This is as good a place as any.  Need to invoke push_tag_toplevel.  */
+  /* This is as good a place as any.  Need to invoke
+     push_tag_toplevel.  */
   if (!objc_protocol_template)
     objc_protocol_template = build_protocol_template ();
 
-  protocol = make_node (code);
-  TYPE_BINFO (protocol) = make_tree_vec (2);
-
-  PROTOCOL_NAME (protocol) = name;
-  PROTOCOL_LIST (protocol) = list;
+  protocol = lookup_protocol (name);
 
-  lookup_and_install_protocols (list);
+  if (!protocol)
+    {
+      protocol = make_node (code);
+      TYPE_BINFO (protocol) = make_tree_vec (2);
 
-  if (lookup_protocol (name))
-    warning ("duplicate declaration for protocol `%s'",
-          IDENTIFIER_POINTER (name));
-  else
-    add_protocol (protocol);
+      PROTOCOL_NAME (protocol) = name;
+      PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
+      add_protocol (protocol);
+      PROTOCOL_DEFINED (protocol) = 1;
+      PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
 
-  PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
+      check_protocol_recursively (protocol, list);
+    }
+  else if (! PROTOCOL_DEFINED (protocol))
+    {
+      PROTOCOL_DEFINED (protocol) = 1;
+      PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
 
+      check_protocol_recursively (protocol, list);
+    }
+  else
+    {
+      warning ("duplicate declaration for protocol `%s'",
+              IDENTIFIER_POINTER (name));
+    }
   return protocol;
 }
 
 void
 finish_protocol (protocol)
-       tree protocol ATTRIBUTE_UNUSED;
+     tree protocol ATTRIBUTE_UNUSED;
 {
 }
 
@@ -6603,17 +6646,22 @@ encode_aggregate_within (type, curtype, format, left, right)
      int left;
      int right;
 {
+  /* The RECORD_TYPE may in fact be a typedef!  For purposes
+     of encoding, we need the real underlying enchilada.  */
+  if (TYPE_MAIN_VARIANT (type))
+    type = TYPE_MAIN_VARIANT (type);
+
   if (obstack_object_size (&util_obstack) > 0
       && *(obstack_next_free (&util_obstack) - 1) == '^')
     {
       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)
@@ -6647,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);
@@ -6703,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);
@@ -6839,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];
@@ -6885,7 +6936,8 @@ encode_complete_bitfield (int position, tree type, int size)
            charType = 'q';
        }
     }
-
+  else if (code == ENUMERAL_TYPE)
+    charType = 'i';
   else
     abort ();
 
@@ -6908,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));
@@ -6947,7 +6999,7 @@ start_method_def (method)
   tree decl_specs;
 
   /* Required to implement _msgSuper.  */
-  method_context = method;
+  objc_method_context = method;
   UOBJC_SUPER_decl = NULL_TREE;
 
   /* Must be called BEFORE start_function.  */
@@ -6955,7 +7007,7 @@ start_method_def (method)
 
   /* Generate prototype declarations for arguments..."new-style".  */
 
-  if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
+  if (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL)
     decl_specs = build_tree_list (NULL_TREE, uprivate_record);
   else
     /* Really a `struct objc_class *'. However, we allow people to
@@ -6965,7 +7017,7 @@ start_method_def (method)
   push_parm_decl (build_tree_list
                  (build_tree_list (decl_specs,
                                    build1 (INDIRECT_REF, NULL_TREE, self_id)),
-                  build_tree_list (unused_list, NULL_TREE)));
+                  unused_list));
 
   decl_specs = build_tree_list (NULL_TREE,
                                xref_tag (RECORD_TYPE,
@@ -6973,7 +7025,7 @@ start_method_def (method)
   push_parm_decl (build_tree_list
                  (build_tree_list (decl_specs,
                                    build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
-                  build_tree_list (unused_list, NULL_TREE)));
+                  unused_list));
 
   /* Generate argument declarations if a keyword_decl.  */
   if (METHOD_SEL_ARGS (method))
@@ -6992,7 +7044,7 @@ start_method_def (method)
              TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
              push_parm_decl (build_tree_list
                              (build_tree_list (arg_spec, arg_decl),
-                              build_tree_list (NULL_TREE, NULL_TREE)));
+                              NULL_TREE));
 
              /* Unhook: restore the abstract declarator.  */
              TREE_OPERAND (last_expr, 0) = NULL_TREE;
@@ -7002,7 +7054,7 @@ start_method_def (method)
            push_parm_decl (build_tree_list
                            (build_tree_list (arg_spec,
                                              KEYWORD_ARG_NAME (arglist)),
-                            build_tree_list (NULL_TREE, NULL_TREE)));
+                            NULL_TREE));
 
          arglist = TREE_CHAIN (arglist);
        }
@@ -7031,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),
@@ -7050,22 +7102,17 @@ static int
 comp_method_with_proto (method, proto)
      tree method, proto;
 {
-  static tree function_type = 0;
-
-  /* Create a function_type node once.  */
-  if (!function_type)
-    {
-      function_type = make_node (FUNCTION_TYPE);
-      ggc_add_tree_root (&function_type, 1);
-    }
+  /* Create a function template node at most once.  */
+  if (!function1_template)
+    function1_template = make_node (FUNCTION_TYPE);
 
   /* Install argument types - normally set by build_function_type.  */
-  TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
+  TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto, METHOD_DEF, 0);
 
   /* install return type */
-  TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
+  TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
 
-  return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
+  return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
 }
 
 /* Return 1 if PROTO1 is consistent with PROTO2.  */
@@ -7074,25 +7121,21 @@ static int
 comp_proto_with_proto (proto0, proto1)
      tree proto0, proto1;
 {
-  static tree function_type[2];
-
-  /* Create a couple function_type node's once.  */
-  if (!function_type[0])
-    {
-      function_type[0] = make_node (FUNCTION_TYPE);
-      function_type[1] = make_node (FUNCTION_TYPE);
-      ggc_add_tree_root (function_type, 2);
-    }
+  /* Create a couple of function_template nodes at most once.  */
+  if (!function1_template)
+    function1_template = make_node (FUNCTION_TYPE);
+  if (!function2_template)
+    function2_template = make_node (FUNCTION_TYPE);
 
   /* Install argument types; normally set by build_function_type.  */
-  TYPE_ARG_TYPES (function_type[0]) = get_arg_type_list (proto0, METHOD_REF, 0);
-  TYPE_ARG_TYPES (function_type[1]) = get_arg_type_list (proto1, METHOD_REF, 0);
+  TYPE_ARG_TYPES (function1_template) = get_arg_type_list (proto0, METHOD_REF, 0);
+  TYPE_ARG_TYPES (function2_template) = get_arg_type_list (proto1, METHOD_REF, 0);
 
   /* Install return type.  */
-  TREE_TYPE (function_type[0]) = groktypename (TREE_TYPE (proto0));
-  TREE_TYPE (function_type[1]) = groktypename (TREE_TYPE (proto1));
+  TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
+  TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
 
-  return comptypes (function_type[0], function_type[1]);
+  return comptypes (function1_template, function2_template);
 }
 
 /* - Generate an identifier for the function. the format is "_n_cls",
@@ -7116,11 +7159,11 @@ really_start_method (method, parmlist)
   decl_specs = chainon (sc_spec, ret_spec);
 
   sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method));
-  class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context));
-  cat_name = ((TREE_CODE (implementation_context)
+  class_name = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
+  cat_name = ((TREE_CODE (objc_implementation_context)
               == CLASS_IMPLEMENTATION_TYPE)
              ? NULL
-             : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
+             : IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context)));
   method_slot++;
 
   /* Make sure this is big enough for any plausible method label.  */
@@ -7145,7 +7188,7 @@ really_start_method (method, parmlist)
       method_decl = ret_decl;
 
       /* Fool the parser into thinking it is starting a function.  */
-      start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE);
+      start_function (decl_specs, method_decl, NULL_TREE);
 
       /* Unhook: this has the effect of restoring the abstract declarator.  */
       TREE_OPERAND (save_expr, 0) = NULL_TREE;
@@ -7156,7 +7199,7 @@ really_start_method (method, parmlist)
       TREE_VALUE (TREE_TYPE (method)) = method_decl;
 
       /* Fool the parser into thinking it is starting a function.  */
-      start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE);
+      start_function (decl_specs, method_decl, NULL_TREE);
 
       /* Unhook: this has the effect of restoring the abstract declarator.  */
       TREE_VALUE (TREE_TYPE (method)) = NULL_TREE;
@@ -7166,7 +7209,7 @@ really_start_method (method, parmlist)
 
   /* Check consistency...start_function, pushdecl, duplicate_decls.  */
 
-  if (implementation_template != implementation_context)
+  if (implementation_template != objc_implementation_context)
     {
       tree proto;
 
@@ -7197,7 +7240,7 @@ continue_method_def ()
 {
   tree parmlist;
 
-  if (METHOD_ADD_ARGS (method_context) == objc_ellipsis_node)
+  if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
     /* We have a `, ...' immediately following the selector.  */
     parmlist = get_parm_info (0);
   else
@@ -7208,7 +7251,7 @@ continue_method_def ()
   self_decl = TREE_PURPOSE (parmlist);
 
   poplevel (0, 0, 0);
-  really_start_method (method_context, parmlist);
+  really_start_method (objc_method_context, parmlist);
   store_parm_decls ();
 }
 
@@ -7222,7 +7265,7 @@ add_objc_decls ()
       UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER),
                                     build_tree_list (NULL_TREE,
                                                      objc_super_template),
-                                    0, NULL_TREE, NULL_TREE);
+                                    0, NULL_TREE);
 
       finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE);
 
@@ -7241,7 +7284,7 @@ add_objc_decls ()
 tree
 get_super_receiver ()
 {
-  if (method_context)
+  if (objc_method_context)
     {
       tree super_expr, super_expr_list;
 
@@ -7254,13 +7297,13 @@ get_super_receiver ()
       super_expr = build_component_ref (UOBJC_SUPER_decl,
                                        get_identifier ("class"));
 
-      if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
+      if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        {
          /* [_cls, __cls]Super are "pre-built" in
             synth_forward_declarations.  */
 
          super_expr = build_modify_expr (super_expr, NOP_EXPR,
-                                         ((TREE_CODE (method_context)
+                                         ((TREE_CODE (objc_method_context)
                                            == INSTANCE_METHOD_DECL)
                                           ? ucls_super_ref
                                           : uucls_super_ref));
@@ -7272,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'",
@@ -7283,15 +7326,19 @@ get_super_receiver ()
          if (flag_next_runtime)
            {
              super_class = get_class_reference (super_name);
-             if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
+             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
            {
              add_class_reference (super_name);
-             super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL
+             super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
                             ? objc_get_class_decl : objc_get_meta_class_decl);
              assemble_external (super_class);
              super_class
@@ -7381,19 +7428,19 @@ encode_method_def (func_decl)
 static void
 objc_expand_function_end ()
 {
-  METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
+  METHOD_ENCODING (objc_method_context) = encode_method_def (current_function_decl);
 }
 
 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,
      since the optimizer may find "may be used before set" errors.  */
-  method_context = NULL_TREE;
+  objc_method_context = NULL_TREE;
 }
 
 #if 0
@@ -7401,10 +7448,10 @@ int
 lang_report_error_function (decl)
       tree decl;
 {
-  if (method_context)
+  if (objc_method_context)
     {
       fprintf (stderr, "In method `%s'\n",
-              IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
+              IDENTIFIER_POINTER (METHOD_SEL_NAME (objc_method_context)));
       return 1;
     }
 
@@ -7951,7 +7998,7 @@ gen_declaration_1 (atype_or_adecl, buf)
          || TREE_CODE (atype_or_adecl) == PARM_DECL
          || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
        {
-         const char *decl_name =
+         const char *const decl_name =
            (DECL_NAME (atype_or_adecl)
             ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) : "");
 
@@ -8044,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);
@@ -8057,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");
@@ -8088,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 */
@@ -8148,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;
@@ -8159,34 +8228,12 @@ objc_printable_name (decl, kind)
 static void
 init_objc ()
 {
-  /* Add the special tree codes of Objective C to the tables.  */
-
-#define LAST_CODE LAST_C_TREE_CODE
-
   gcc_obstack_init (&util_obstack);
   util_firstobj = (char *) obstack_finish (&util_obstack);
 
-  memcpy (tree_code_type + (int) LAST_CODE,
-         objc_tree_code_type,
-         (int) LAST_OBJC_TREE_CODE - (int) LAST_CODE);
-  memcpy (tree_code_length + (int) LAST_CODE,
-         objc_tree_code_length,
-         (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) * sizeof (int)));
-  memcpy (tree_code_name + (int) LAST_CODE,
-         objc_tree_code_name,
-         (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) * sizeof (char *)));
-
-  errbuf = (char *)xmalloc (BUFSIZE);
+  errbuf = (char *) xmalloc (BUFSIZE);
   hash_init ();
   synth_module_prologue ();
-
-  /* Change the default error function */
-  save_lang_status = &push_c_function_context;
-  restore_lang_status = &pop_c_function_context;
-  mark_lang_status = &mark_c_function_context;
-  decl_printable_name = objc_printable_name;
-  lang_expand_expr = c_expand_expr;
-  lang_expand_decl_stmt = c_expand_decl_stmt;
 }
 \f
 static void
@@ -8203,7 +8250,7 @@ finish_objc ()
   if (objc_implementation_context)
     {
       warning ("`@end' missing in implementation context");
-      finish_class (implementation_context);
+      finish_class (objc_implementation_context);
       objc_ivar_chain = NULL_TREE;
       objc_implementation_context = NULL_TREE;
     }
@@ -8215,23 +8262,32 @@ 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 ();
 
-  if (implementation_context || class_names_chain
+  if (imp_list || class_names_chain
       || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
     generate_objc_symtab_decl ();
 
   for (impent = imp_list; impent; impent = impent->next)
     {
-      implementation_context = impent->imp_context;
+      objc_implementation_context = impent->imp_context;
       implementation_template = impent->imp_template;
 
       UOBJC_CLASS_decl = impent->class_decl;
       UOBJC_METACLASS_decl = impent->meta_decl;
-
-      if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE)
+      
+      /* 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...  */
          generate_ivar_lists ();
@@ -8241,7 +8297,7 @@ finish_objc ()
       else
        {
          generate_dispatch_tables ();
-         generate_category (implementation_context);
+         generate_category (objc_implementation_context);
        }
     }
 
@@ -8253,13 +8309,13 @@ finish_objc ()
   if (protocol_chain)
     generate_protocols ();
 
-  if (implementation_context || class_names_chain || objc_static_instances
+  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.  */
-      const char *init_name = build_module_descriptor ();
-      if (init_name)
-       assemble_constructor (init_name);
+      /* 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);
     }
 
   /* Dump the class references.  This forces the appropriate classes
@@ -8281,12 +8337,6 @@ finish_objc ()
 
   generate_strings ();
 
-  if (flag_gen_declaration)
-    {
-      add_class (implementation_context);
-      dump_interface (gen_declaration_file, implementation_context);
-    }
-
   if (warn_selector)
     {
       int slot;
@@ -8335,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;
@@ -8354,7 +8404,7 @@ generate_classref_translation_entry (chain)
 
   /* The decl that is returned from start_decl is the one that we
      forward declared in build_class_reference.  */
-  decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE);
+  decl = start_decl (name, decl_specs, 1, NULL_TREE);
   DECL_CONTEXT (decl) = NULL_TREE;
   finish_decl (decl, expr, NULL_TREE);
   return;
@@ -8388,213 +8438,82 @@ handle_class_ref (chain)
   pushdecl (decl);
   rest_of_decl_compilation (decl, 0, 0, 0);
 
-  /* Make following constant read-only, but only for GNU runtime.  */
-  if (!flag_next_runtime)
-    readonly_data_section ();
-
+  /* Make a decl for the address.  */
+  sprintf (string, "%sobjc_class_ref_%s",
+          (flag_next_runtime ? "." : "__"), name);
   exp = build1 (ADDR_EXPR, string_type_node, decl);
+  decl = build_decl (VAR_DECL, get_identifier (string), string_type_node);
+  DECL_INITIAL (decl) = exp;
+  TREE_STATIC (decl) = 1;
+  TREE_USED (decl) = 1;
 
-  /* Align the section properly.  */
-  assemble_constant_align (exp);
-
-  /* Inform the assembler about this new external thing.  */
-  assemble_external (decl);
-
-  /* Output a constant to reference this address.  */
-  output_constant (exp, int_size_in_bytes (string_type_node));
+  pushdecl (decl);
+  rest_of_decl_compilation (decl, 0, 0, 0);
 }
 
 static void
 handle_impent (impent)
      struct imp_entry *impent;
 {
-  implementation_context = impent->imp_context;
+  char *string;
+
+  objc_implementation_context = impent->imp_context;
   implementation_template = impent->imp_template;
 
   if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
     {
-      const char *class_name =
+      const char *const class_name =
        IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
-      char *string = (char *) alloca (strlen (class_name) + 30);
 
-      if (flag_next_runtime)
-       {
-         /* Grossly unportable.
-            People should know better than to assume
-            such things about assembler syntax!  */
-         sprintf (string, ".objc_class_name_%s=0", class_name);
-         assemble_asm (my_build_string (strlen (string) + 1, string));
-
-         sprintf (string, ".globl .objc_class_name_%s", class_name);
-         assemble_asm (my_build_string (strlen (string) + 1, string));
-       }
+      string = (char *) alloca (strlen (class_name) + 30);
 
-      else
-       {
-         sprintf (string, "%sobjc_class_name_%s",
-                  (flag_next_runtime ? "." : "__"), class_name);
-         assemble_global (string);
-         assemble_label (string);
-       }
+      sprintf (string, "%sobjc_class_name_%s",
+               (flag_next_runtime ? "." : "__"), class_name);
     }
-
   else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
     {
-      const char *class_name =
+      const char *const class_name =
        IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
-      const char *class_super_name =
-       IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
-      char *string = (char *) alloca (strlen (class_name)
-                                     + strlen (class_super_name) + 30);
-
-      /* 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.  */
-      if (flag_next_runtime)
-       {
-         /* Grossly unportable.  */
-         sprintf (string, ".objc_category_name_%s_%s=0",
-                  class_name, class_super_name);
-         assemble_asm (my_build_string (strlen (string) + 1, string));
-
-         sprintf (string, ".globl .objc_category_name_%s_%s",
-                  class_name, class_super_name);
-         assemble_asm (my_build_string (strlen (string) + 1, string));
-       }
-
-      else
-       {
-         sprintf (string, "%sobjc_category_name_%s_%s",
-                  (flag_next_runtime ? "." : "__"),
-                  class_name, class_super_name);
-         assemble_global (string);
-         assemble_label (string);
-       }
-    }
-}
-\f
-#ifdef DEBUG
-
-static void
-objc_debug (fp)
-     FILE *fp;
-{
-  char *buf = (char *)xmalloc (256);
-
-  {                            /* dump function prototypes */
-    tree loop = UOBJC_MODULES_decl;
-
-    fprintf (fp, "\n\nfunction prototypes:\n");
-    while (loop)
-      {
-       if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
-         {
-           /* We have a function definition: generate prototype.  */
-           fprintf (fp, "%s;\n", gen_declaration (loop, errbuf));
-         }
-       loop = TREE_CHAIN (loop);
-      }
-  }
-  {
-    /* Dump global chains.  */
-    tree loop;
-    int i, index = 0, offset = 0;
-    hash hashlist;
-
-    for (i = 0; i < SIZEHASHTABLE; i++)
-      {
-       if (hashlist = nst_method_hash_list[i])
-         {
-           fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
-           do
-             {
-               fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
-               hashlist = hashlist->next;
-             }
-           while (hashlist);
-         }
-      }
-
-    for (i = 0; i < SIZEHASHTABLE; i++)
-      {
-       if (hashlist = cls_method_hash_list[i])
-         {
-           fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
-           do
-             {
-               fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
-               hashlist = hashlist->next;
-             }
-           while (hashlist);
-         }
-      }
+      const char *const class_super_name =
+        IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
 
-    fprintf (fp, "\nsel_refdef_chain:\n");
-    for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
-      {
-       fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
-                IDENTIFIER_POINTER (TREE_VALUE (loop)));
-       index++;
-       /* add one for the '\0' character */
-       offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
-      }
-
-    fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
-  }
-}
-#endif
-
-void
-print_lang_statistics ()
-{
-}
+      string = (char *) alloca (strlen (class_name)
+                               + strlen (class_super_name) + 30);
 
-static void
-ggc_mark_imp_list (arg)
-    void *arg;
-{
-  struct imp_entry *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.  */
+      sprintf (string, "*%sobjc_category_name_%s_%s",
+               (flag_next_runtime ? "." : "__"), class_name, class_super_name);
+    }
+  else
+    return;
 
-  for (impent = *(struct imp_entry **)arg; impent; impent = impent->next)
+#ifdef ASM_DECLARE_CLASS_REFERENCE
+  if (flag_next_runtime)
     {
-      ggc_mark_tree (impent->imp_context);
-      ggc_mark_tree (impent->imp_template);
-      ggc_mark_tree (impent->class_decl);
-      ggc_mark_tree (impent->meta_decl);
+      ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
+      return;
     }
-}
-
-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);
-      }
-}
+  else
+#endif
+    {
+      tree decl, init;
 
-/* Add GC roots for variables local to this file.  */
-static void
-objc_act_parse_init ()
-{
-  ggc_add_tree_root (&objc_ellipsis_node, 1);
-  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)
@@ -8602,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)))
     {
@@ -8616,45 +8535,4 @@ lookup_objc_ivar (id)
     return 0;
 }
 
-/* Parser callbacks.
-   Some ObjC keywords are reserved only in a particular context:
-   in out inout bycopy byref oneway.
-   We have to save and restore the IDENTIFIER_NODEs that describe
-   them as keywords, when appropriate.  */
-
-#define N_PQ 6
-static tree saved_pq[N_PQ];
-static tree saved_not_pq[N_PQ];
-static const char *const pq_strings[N_PQ] = {
-  "bycopy", "byref", "in", "inout", "oneway", "out"
-};
-
-void
-save_and_forget_protocol_qualifiers ()
-{
-  int i;
-  for (i = 0; i < N_PQ; i++)
-    saved_pq[i] = set_identifier (pq_strings[i], NULL_TREE);
-
-  ggc_add_tree_root (saved_pq, N_PQ);
-  ggc_add_tree_root (saved_not_pq, N_PQ);
-}
-
-void
-forget_protocol_qualifiers ()
-{
-  int i;
-  for (i = 0; i < N_PQ; i++)
-    {
-      set_identifier (pq_strings[i], saved_not_pq[i]);
-      saved_not_pq[i] = NULL_TREE;
-    }
-}
-
-void
-remember_protocol_qualifiers ()
-{
-  int i;
-  for (i = 0; i < N_PQ; i++)
-    saved_not_pq[i] = set_identifier (pq_strings[i], saved_pq[i]);
-}
+#include "gtype-objc.h"